diff options
-rw-r--r-- | tango/README.md | 31 | ||||
-rwxr-xr-x | tango/Uca | 121 | ||||
-rw-r--r-- | tango/setup.py | 14 |
3 files changed, 166 insertions, 0 deletions
diff --git a/tango/README.md b/tango/README.md new file mode 100644 index 0000000..21107b9 --- /dev/null +++ b/tango/README.md @@ -0,0 +1,31 @@ +## Installation + +Install the server script with + + $ python setup.py install + +and create a new TANGO server `Uca/xyz` with a class named `Camera`. + + +## Usage + +Before starting the server, you have to create a new device property `camera` +which specifies which camera to use. If not set, the `mock` camera will be used +by default. + +Start the device server with + + $ Uca foo + +You should be able to manipulate camera attributes like `exposure_time` and the +like and store frames using a `Start`, `Store`, `Stop` cycle. + +```python +import PyTango + +camera = PyTango.DeviceProxy("foo/Camera/mock") +camera.exposure_time = 0.1 +camera.Start() +camera.Store('foo.tif') +camera.Stop() +``` diff --git a/tango/Uca b/tango/Uca new file mode 100755 index 0000000..47f4021 --- /dev/null +++ b/tango/Uca @@ -0,0 +1,121 @@ +#!/usr/bin/env python + +import sys +import time +import numpy as np +import PyTango +from gi.repository import Uca, GObject +from PyTango import Attr, AttrWriteType, DevState +from PyTango.server import Device, DeviceMeta, device_property, command, server_run + +try: + import tifffile + HAVE_TIFFFILE = True +except ImportError: + print("Could not import tifffile, consider to install it") + HAVE_TIFFFILE = False + + +def get_tango_type(prop): + mapping = { + GObject.TYPE_BOOLEAN: PyTango.CmdArgType.DevBoolean, + GObject.TYPE_CHAR: PyTango.CmdArgType.DevUChar, + GObject.TYPE_UCHAR: PyTango.CmdArgType.DevUChar, + GObject.TYPE_FLOAT: PyTango.CmdArgType.DevFloat, + GObject.TYPE_INT: PyTango.CmdArgType.DevShort, # DevInt is invalid? + GObject.TYPE_UINT: PyTango.CmdArgType.DevUShort, # check + GObject.TYPE_LONG: PyTango.CmdArgType.DevLong, + GObject.TYPE_DOUBLE: PyTango.CmdArgType.DevDouble, + GObject.TYPE_STRING: PyTango.CmdArgType.DevString, + } + + return mapping.get(prop, None) + + +def get_tango_write_type(prop): + if prop.flags & GObject.ParamFlags.WRITABLE: + if prop.flags & GObject.ParamFlags.READABLE: + return AttrWriteType.READ_WRITE + + return AttrWriteType.WRITE + + if prop.flags & GObject.ParamFlags.READABLE: + return AttrWriteType.READ + + raise RuntimeError("{} has no valid param flag".format(prop.name)) + + +def prop_to_attr_name(name): + return name.replace('-', '_') + + +def attr_to_prop_name(name): + return name.replace('_', '-') + + +class Camera(Device): + __metaclass__ = DeviceMeta + + camera = device_property(dtype=str, default_value='mock') + + def init_device(self): + Device.init_device(self) + self.set_state(DevState.ON) + self.pm = Uca.PluginManager() + self.device = self.pm.get_camerah(self.camera, None) + self.attrs = {} + + for prop in self.device.props: + tango_type = get_tango_type(prop.value_type) + write_type = get_tango_write_type(prop) + + if tango_type: + name = prop_to_attr_name(prop.name) + attr = Attr(name, tango_type, write_type) + attr_props = PyTango.UserDefaultAttrProp() + attr_props.set_description(prop.blurb) + attr.set_default_properties(attr_props) + + write_func = None + + if write_type in (AttrWriteType.WRITE, AttrWriteType.READ_WRITE): + write_func = self.do_write + + self.attrs[prop.name] = self.add_attribute(attr, self.do_read, write_func) + + def grab(self): + array = np.empty(self.shape, dtype=self.dtype) + data = array.__array_interface__['data'][0] + self.device.grab(data) + return array + + def do_read(self, attr): + name = attr_to_prop_name(attr.get_name()) + attr.set_value(self.device.get_property(name)) + + def do_write(self, attr): + name = attr_to_prop_name(attr.get_name()) + self.device.set_property(name, attr.get_write_value()) + + @command + def Start(self): + self.shape = (self.device.props.roi_height, self.device.props.roi_width) + self.dtype = np.uint16 if self.device.props.sensor_bitdepth > 8 else np.uint8 + self.device.start_recording() + + @command + def Stop(self): + self.device.stop_recording() + + @command(dtype_in=str, doc_in="Path and filename to store frame") + def Store(self, path): + frame = self.grab() + + if HAVE_TIFFFILE: + tifffile.imsave(path, frame) + else: + np.savez(open(path, 'wb'), frame) + + +if __name__ == '__main__': + server_run((Camera,)) diff --git a/tango/setup.py b/tango/setup.py new file mode 100644 index 0000000..8b12153 --- /dev/null +++ b/tango/setup.py @@ -0,0 +1,14 @@ +from setuptools import setup + +setup( + name='tangouca', # jeez + version='0.0.1', + author='Matthias Vogelgesang', + author_email='matthias.vogelgesang@kit.edu', + url='http://ufo.kit.edu', + license='(?)', + description='TANGO server for libuca', + long_description='TANGO server for libuca', + scripts=['Uca'], + install_requires=['PyTango'] +) |