[Motmot] Periodic trigger addons

Andrew Straw astraw at caltech.edu
Wed May 20 00:51:47 UTC 2009


(CCing to the motmot email list.)

John Schneider wrote:
> Hi Andrew,
> 
> The external trigger/periodic trigger were easy to set up and work
> great! I'm hoping to add some functionality to the periodic trigger
> but my python is crap...
> I want to be able to start the periodic trigger at the same time as I
> start recording by adding a little bit of text to
> fview_periodic_trigger.py which will send the command to the main
> fview to start recording, I tried adding:
> ...
>     enabled = traits.Bool(False)
>     fp_start= traits.Bool(False)
>     fp_stop=traits.Bool(False)
>     traits_view = View(Group(Item(name='Nth_frame'),
>                              Item(name='fp_start'),
>                              Item(name='fp_stop'),
> 			     ))
> ...
>     def process_frame(self,cam_id,buf,buf_offset,timestamp,framenumber):
>         if self.fp_start:
>             self.enabled=True
>         if self.enabled:
>             if framenumber%self.Nth_frame == 0:
> 	        if self.fp_start:
> 		    filename = time.strftime( 'movie%Y%m%d_%H%M%S.fmf' )
> 	            fullpath = os.path.join( fview.record_dir, filename )
>    		    fview.start_streaming(fullpath,1)
> 		    self.fp_start=False
> 		if self.fp_stop:
>                     fview.stop_streaming()
> 		    self.enabled=False
> ...

I think what you want is that fp_start and fp_stop are traits.Button
instances.  Then define a couple traits functions to handle the event
that occurs when the button is pressed.

def _fp_start_fired(self):
    self.enabled = True
    filename = time.strftime( 'movie%Y%m%d_%H%M%S.fmf' )
    fullpath = os.path.join( fview.record_dir, filename )
    fview.start_streaming(fullpath,1)

def _fp_stop_fired(self):
    fview.stop_streaming()
    self.enabled=False

> But only managed to get the camera thread to die,

The output of fview.log may be enlightening as to exactly what's going
on here, but in the meantime, I have some more advice.

 no doubt because
> what I tried to do makes no sense in python as-is.

The problem is that you're mixing variables and function calls across
threads. Multi-threaded programming is a real pain to get right. The
basic ideas are actually simple, but the number of places to go wrong
are virtually infinite. The process_frame() function is being called
from its own thread, and you don't want to call into functions from the
rest of the program that aren't /thread safe/ from the process_frame()
thread. Certainly fview.start_streaming() is not thread safe. (The other
tenant of multi-threaded programming is that shared variable access must
be controlled such that no two threads are attempting to simultaneously
access the same variable in an unsafe way. This is usually done with
locks. In fact, "thread safe" simply refers to functions which do not
access variables or other resources safely.)

As additional advice, perhaps unneeded in this instance: you can use
Queue.Queue to pass variables between threads. Or else use traits.Event
or threading.Event to send events around.

The above code I added will do the start_streaming from the GUI thread,
as this is an event handler and thus should be OK with regards to thread
safety. Also, self.enabled would be the only variable shared across
threads, and traits.Bool types are OK to share across threads.

> Is it possible to obtain variables (fview.record_dir, possibly
> nth_frame value) and pass arguments to fview
> (fview.start_streaming/fview.stop_streaming) without modifying fview?
> or is there a better way to accomplish this?
> 
> Thanks as always for your programs and help,
> 
> Jon
> 


-- 
Andrew D. Straw, Ph.D.
California Institute of Technology
http://www.its.caltech.edu/~astraw/


More information about the Motmot mailing list