diff --git a/microscope/cameras/atmcd.py b/microscope/cameras/atmcd.py index 7424b8cf..d030ee56 100644 --- a/microscope/cameras/atmcd.py +++ b/microscope/cameras/atmcd.py @@ -1134,7 +1134,7 @@ def __str__(self): from threading import Lock import functools from microscope import devices -from microscope.devices import keep_acquiring, Setting, Binning, ROI +from microscope.devices import keep_acquiring, Binning, ROI import time # A lock on the DLL used to ensure DLL calls act on the correct device. @@ -1255,17 +1255,17 @@ def initialize(self): # Mode name = 'readout mode' if self._readout_modes: - self.settings[name] = Setting(name, 'enum', - None, - self._set_readout_mode, - lambda: [str(mode) for mode in self._readout_modes]) + self.add_setting(name, 'enum', + None, + self._set_readout_mode, + lambda: [str(mode) for mode in self._readout_modes]) self.settings[name].set(0) # TriggerMode name = 'TriggerMode' - self.settings[name] = Setting(name, 'enum', - None, - self._bind(SetTriggerMode), - TriggerMode) + self.add_setting(name, 'enum', + None, + self._bind(SetTriggerMode), + TriggerMode) if self._caps.ulTriggerModes & AC_TRIGGERMODE_EXTERNAL: self.settings[name].set(TriggerMode.EXTERNAL) elif self._caps.ulTriggerModes & AC_TRIGGERMODE_CONTINUOUS: @@ -1284,9 +1284,7 @@ def initialize(self): setter = self._bind(SetMCPGain) vrange = self._bind(GetMCPGainRange) if getter or setter: - self.settings[name] = Setting(name, 'int', - getter, setter, vrange, - setter is None) + self.add_setting(name, 'int', getter, setter, vrange, setter is None) # Temperature name = 'TemperatureSetPoint' getter, setter, vrange = None, None, None @@ -1295,77 +1293,73 @@ def initialize(self): if self._caps.ulGetFunctions & AC_GETFUNCTION_TEMPERATURERANGE: vrange = self._bind(GetTemperatureRange) if setter: - self.settings[name] = Setting(name, 'int', - None, setter, vrange, - setter is None) + self.add_setting(name, 'int', None, setter, vrange, setter is None) # Set a conservative default temperature set-point. self.settings[name].set(-20) # Fan control name = 'Temperature' - self.settings[name] = Setting(name, 'int', - self.get_sensor_temperature, - None, (None, None), True) + self.add_setting(name, 'int', self.get_sensor_temperature, None, (None, None), True) name = 'Fan mode' - self.settings[name] = Setting(name, 'enum', - None, # Can't query fan mode - self._bind(SetFanMode), - {0:'full', 1:'low', 2:'off'} - ) + self.add_setting(name, 'enum', + None, # Can't query fan mode + self._bind(SetFanMode), + {0:'full', 1:'low', 2:'off'} + ) # Cooler control name = 'Cooler Enabled' - self.settings[name] = Setting(name, 'bool', - None, - self._set_cooler_state, - None) + self.add_setting(name, 'bool', + None, + self._set_cooler_state, + None) self.settings[name].set(True) # Binning name = 'Binning' - self.settings[name] = Setting(name, 'tuple', - self.get_binning, - self.set_binning, - None) + self.add_setting(name, 'tuple', + self.get_binning, + self.set_binning, + None) # Roi name = 'Roi' - self.settings[name] = Setting(name, 'tuple', - self.get_roi, - lambda roi: self.set_roi(*roi), - None) + self.add_setting(name, 'tuple', + self.get_roi, + lambda roi: self.set_roi(*roi), + None) # BaselineClamp name = 'BaselineClamp' if self._caps.ulSetFunctions & AC_SETFUNCTION_BASELINECLAMP: - self.settings[name] = Setting(name, 'bool', - None, - self._bind(SetBaselineClamp)) + self.add_setting(name, 'bool', + None, + self._bind(SetBaselineClamp)) self.settings[name].set(False) # BaselineOffset nam = 'BaselineOffset' if self._caps.ulSetFunctions & AC_SETFUNCTION_BASELINEOFFSET: - self.settings[name] = Setting(name, 'int', - None, - self._bind(SetBaselineOffset), - (-1000, 1000)) + self.add_setting(name, 'int', + None, + self._bind(SetBaselineOffset), + (-1000, 1000)) self.settings[name].set(0) # EMAdvanced name = 'EMAdvanced' if self._caps.ulSetFunctions & AC_SETFUNCTION_EMADVANCED: - self.settings[name] = Setting(name, 'bool', - None, - self._bind(SetEMAdvanced)) + self.add_setting(name, 'bool', + None, + self._bind(SetEMAdvanced)) self.settings[name].set(False) # GateMode name = 'GateMode' if self._caps.ulSetFunctions & AC_SETFUNCTION_GATEMODE: vrange = range(0, [5,6][self._caps.ulCameraType & AC_CAMERATYPE_ISTAR]) - self.setings[name] = Setting(name, 'int', - None, - self._bind(SetGateMode), - vrange) + self.add_setting(name, 'int', + None, + self._bind(SetGateMode), + vrange) # HighCapacity name = 'HighCapacity' if self._caps.ulSetFunctions & AC_SETFUNCTION_HIGHCAPACITY: - self.settings[name] = Setting(name, 'bool', - None, - self._bind(SetHighCapacity)) + self.add_setting(name, 'bool', + None, + self._bind(SetHighCapacity)) def _fetch_data(self): """Poll for data and return it, with minimal processing. diff --git a/microscope/devices.py b/microscope/devices.py index f7732eb8..c5950baf 100644 --- a/microscope/devices.py +++ b/microscope/devices.py @@ -75,7 +75,10 @@ _call_if_callable = lambda f: f() if callable(f) else f -class Setting(): +class _Setting(): + # TODO: refactor into subclasses to avoid if isinstance .. elif .. else. + # Settings classes should be private: devices should use a factory method + # rather than instantiate settings directly; most already use add_setting for this. def __init__(self, name, dtype, get_func, set_func=None, values=None, readonly=False): """Create a setting. @@ -265,8 +268,6 @@ def make_safe(self): def add_setting(self, name, dtype, get_func, set_func, values, readonly=False): """Add a setting definition. - Can also use self.settings[name] = Setting(name, dtype,...) - :param name: the setting's name :param dtype: a data type from ('int', 'float', 'bool', 'enum', 'str') :param get_func: a function to get the current value @@ -290,7 +291,7 @@ class with getter, setter, etc., and adding Setting instances as raise Exception("Invalid values type for %s '%s': expected function or %s" % (dtype, name, DTYPES[dtype][1:])) else: - self.settings[name] = Setting(name, dtype, get_func, set_func, values, readonly) + self.settings[name] = _Setting(name, dtype, get_func, set_func, values, readonly) def get_setting(self, name): """Return the current value of a setting.""" diff --git a/microscope/stages/linkam.py b/microscope/stages/linkam.py index 704d8387..01107e24 100644 --- a/microscope/stages/linkam.py +++ b/microscope/stages/linkam.py @@ -31,10 +31,9 @@ * get_id returns an empty string, not the device serial number.""" import ctypes -from ctypes import addressof, byref, POINTER +from ctypes import byref, POINTER from enum import Enum, IntEnum from microscope import devices -from microscope.devices import Setting import datetime, time _max_version_length = 20 diff --git a/microscope/testsuite/test_settings.py b/microscope/testsuite/test_settings.py index 2916ba7c..d4e1ca81 100644 --- a/microscope/testsuite/test_settings.py +++ b/microscope/testsuite/test_settings.py @@ -49,8 +49,8 @@ def create_enum_setting(default, with_getter=True, with_setter=True): thing = ThingWithSomething(EnumSetting(default)) getter = thing.get_val if with_getter else None setter = thing.set_val if with_setter else None - setting = microscope.devices.Setting('foobar', 'enum', get_func=getter, - set_func=setter, values=EnumSetting) + setting = microscope.devices._Setting('foobar', 'enum', get_func=getter, + set_func=setter, values=EnumSetting) return setting, thing