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
67 stars 39 forks source link

pass function to device server instead of class with args as a separate argument #154

Closed carandraug closed 4 years ago

carandraug commented 4 years ago

Currently, the configuration of a device server is as follow:

DEVICES = [
    device(TestStage, 'localhost', 8009,
           conf={'limits' : {'X' : AxisLimits(0, 5000),
                             'Y' : AxisLimits(0, 5000)}}),
]

However, would be nice if instead one could pass a function that returns a device (or list of devices). Something like this:

def device_factory():
    return TestStage({'X' : AxisLimits(0, 5000), 'Y' : AxisLimits(0, 5000)})

DEVICES = [
    device(device_factory, 'localhost', 8009),
]

Other than making it easier to construct some devices, the main reason is to enable have multiple devices on the same process. For most cases we want to have them in separate processes to avoid the GIL. However, in some cases we want instead to make it easier to pass data between devices. These are cases where we need to processing (typically an image) such as the Aurox. Actually, this has already been mentioned before (see comments and review of #124). We are currently abusing ControllerDevice to achieve this, but having the ability to pass a function that will construct the devices would solve that. We could then have something like:

def func():
    camera = CameraDevice(whatever_args)
    aurox = AuroxDevice(camera)
    return [camera, aurox]

DEVICES = [
    device(func, hostame, port)
]
carandraug commented 4 years ago

I forgot to mention, although it is mentioned on #124, that this would simplify what we've been calling composite devices.

carandraug commented 4 years ago

I pushed ab194af36abe76c72d1 which adds the ability to pass a function that returns a dict. In addition of enabling what is mentioned before, it also provides a means of specifying the wanted Pyro URI. Something like this:

DEVICES = [
    device(lambda kwargs: {'ThisDevice' : Camera()}, hostname, port),
]

Which would serve PYRO:ThisDevice@hostname:port.