python-data-acquisition / meta

For laying organizational groundwork
Other
18 stars 4 forks source link

Common API: Should control be imperative or state based? #5

Open campagnola opened 4 years ago

campagnola commented 4 years ago

@David-Baddeley writes:

Should control be imperative or state based? (and the somewhat related question of whether it should be synchronous or asynchronous). I.E. for a stage, should we be doing something like move_to(new_position) or rather set_attribute('position', new_position). The state-based approach has some significant advantages when it comes to automation (you can essentially describe the entire microscope state as a dictionary, and tell the microscope to assume a given state before starting acquisition - the alternative of telling each device in turn to perform an imperative action rapidly gets clunky, and can result in a poorly defined state - e.g. if you used relative moves). It also lets you easily define or autogenerate GUIs (although they tend to end up being somewhat crap, with micromanager being a case in point). The weakness of the state-based approach is that some things are intrinsically imperative (e.g. camera acquisition), and that the state based approach is potentially slower (e.g. state is only defined once a translation stage has come to rest - you can't do stuff while the stage is moving). All this can be shimmed around to some extent in an adapter, but as a lot of hardware offers both state based and imperative APIs and/or a mixture of both it probably makes sense to know what you are aiming for at the start.

edbarnard commented 4 years ago

In my experience I have had to use both imperative and state-based to do my experiments. I have defaulted to a state-based metadata system in ScopeFoundry (see LoggedQuantities), but allow for Measurements to imperatively talk to hardware when necessary for performance or synchronization reasons. Would a hybrid system like this make sense?

campagnola commented 4 years ago

Agreed--a mixture of imperative and state-based approaches will probably be most natural at this level. The boundary between the two isn't always totally clear, but I generally use state-based for things that do not directly cause any action to be taken by the device, and imperative otherwise.

I think that's basically what our first prototype device class looks like (https://github.com/python-data-acquisition/prototypes/blob/master/abstract/imaging_device.py). There's one spot in particular where this issue shows up--when we ask to acquire a fixed-length image sequence, that is done by setting a parameter to define the sequence length and then starting the camera, like:

cam.set_properties({'acquire_mode': 'fixed_length', 'fixed_frame_count': 10})
cam.start_acquisition()

An alternative here that is possibly more natural is just:

cam.start_acquisition(frame_count=10)
campagnola commented 4 years ago

..but I'm having a hard time coming up with a reason why start_acquisition(frame_count) seems natural, whereas start_acquisition(exposure_time) does not.

aquilesC commented 4 years ago

I would say that exposure time does not depend on the acquisition. For example, you are not setting the ROI, binning, nor which trigger you are using. I would say that the settings of the camera are not parameters of the acquisition. I think it also reflects how you normally work with a camera: first, you set all the parameters, you see it 'live' and check that things are OK, then you record a movie.