python-microscope / microscope

Python library for control of microscope devices, supporting hardware triggers and distribution of devices over the network for performance and flexibility.
https://www.python-microscope.org
GNU General Public License v3.0
69 stars 41 forks source link

Fix issue74 #80

Closed mickp closed 5 years ago

mickp commented 5 years ago

Fixed Thorlabs filter wheel and updated interface.

The wheel position and filter were exposed as settings, but this complicates things needlessly: clients should just call get_position, set_position and get_filters, directly. Nothing used the 'filters' setting, so I've removed it now. I've marked the 'position' setting as deprecated, as it is currently used by cockpit. Eventually, it should be removed.

The 'filters' argument is now an optional keyword for all filterwheels. It can be a list, or a dict mapping possition to filter, where each entry is either a description string, or a tuple of description and some value (e.g. wavelength, neutral density, ...). Alternatively, filterwheels may be created using a 'positions' keyword argument to specify the total number of positions the wheel offers. This will usually be hard-coded in the concrete implementations, as it is usually fixed for a given model of filter wheel.

Some filter wheels have manual controls. I considered having a polling thread to regularly query the wheel position and thereby catch manual position changes. However, filterwheels currently have no mechanism to notify the client of a change, so we leave it to the client to ensure they query the wheel position as needed, either before actions where the wheel's position is critical, or regularly, as required.

mickp commented 5 years ago

(Force-pushed to squash a bunch of minor commits.)

carandraug commented 5 years ago

If a device does not specify the number of positions, which is what happens currently in the test cases for filterwheels, then _positions is never set and things such as _get_num_positions fail. Example:

>>> from microscope.testsuite.devices import TestFilterWheel
>>> w = TestFilterWheel(filters=[(0, 'DAPI', '430')])
>>> w.get_num_positions()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/carandraug/src/python-microscope/microscope/devices.py", line 1087, in get_num_positions
    return(max( self._positions, len(self._filters)))
AttributeError: 'TestFilterWheel' object has no attribute '_positions'

This is because the constructor defaults positions to zero and will skip creating this attribute if it is zero. Maybe these arguments should not have default values?

mickp commented 5 years ago

In order to be completely defined, a filter wheel needs to specify either or both of:

I don't think there's a case where _get_num_positions will fail: it returns max(len(_filters), _positions); if neither have been specified, then it will return 0, because the default arguments result in _filters={} and _positions=0.

I modified the existing test cases accordingly, and added a new one. There's a typo in one test case, though, which I'll fix now.

mickp commented 5 years ago

Looks like you fixed the typo already - thanks.