microeye 2.3.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. microEye/__init__.py +47 -0
  2. microEye/_version.py +2 -0
  3. microEye/analysis/__init__.py +1 -0
  4. microEye/analysis/checklist_dialog.py +143 -0
  5. microEye/analysis/cmosMaps.py +228 -0
  6. microEye/analysis/filters/__init__.py +9 -0
  7. microEye/analysis/filters/base.py +21 -0
  8. microEye/analysis/filters/spatial.py +338 -0
  9. microEye/analysis/filters/temporal.py +76 -0
  10. microEye/analysis/fitting/__init__.py +0 -0
  11. microEye/analysis/fitting/fit.py +680 -0
  12. microEye/analysis/fitting/nena.py +375 -0
  13. microEye/analysis/fitting/phasor_fit.py +90 -0
  14. microEye/analysis/fitting/processing.py +317 -0
  15. microEye/analysis/fitting/psf/__init__.py +6 -0
  16. microEye/analysis/fitting/psf/extract.py +1129 -0
  17. microEye/analysis/fitting/psf/rubost_mean.py +150 -0
  18. microEye/analysis/fitting/psf/spline.py +167 -0
  19. microEye/analysis/fitting/psf/stats/__init__.py +12 -0
  20. microEye/analysis/fitting/psf/stats/core.py +295 -0
  21. microEye/analysis/fitting/psf/stats/curve_fit.py +708 -0
  22. microEye/analysis/fitting/psf/stats/io.py +104 -0
  23. microEye/analysis/fitting/psf/stats/slope_fit.py +171 -0
  24. microEye/analysis/fitting/psf/temp.py +147 -0
  25. microEye/analysis/fitting/psf/test.py +47 -0
  26. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUfunctions.py +657 -0
  27. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUmleFit_LM.py +1336 -0
  28. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUsplineLib.py +270 -0
  29. microEye/analysis/fitting/pyfit3Dcspline/CPU/__init__.py +1 -0
  30. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUfunctions.py +609 -0
  31. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_EMCCD.py +1396 -0
  32. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_sCMOS.py +1426 -0
  33. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUsplineLib.py +231 -0
  34. microEye/analysis/fitting/pyfit3Dcspline/GPU/__init__.py +2 -0
  35. microEye/analysis/fitting/pyfit3Dcspline/__init__.py +10 -0
  36. microEye/analysis/fitting/pyfit3Dcspline/constants.py +27 -0
  37. microEye/analysis/fitting/pyfit3Dcspline/mainfunctions.py +903 -0
  38. microEye/analysis/fitting/results.py +917 -0
  39. microEye/analysis/fitting/results_stats.py +251 -0
  40. microEye/analysis/fitting/tardis.py +209 -0
  41. microEye/analysis/multi_viewer.py +568 -0
  42. microEye/analysis/processing/__init__.py +1 -0
  43. microEye/analysis/processing/frc.py +120 -0
  44. microEye/analysis/rendering/__init__.py +3 -0
  45. microEye/analysis/rendering/base.py +452 -0
  46. microEye/analysis/rendering/cloud.py +215 -0
  47. microEye/analysis/rendering/core.py +47 -0
  48. microEye/analysis/rendering/volumetric.py +198 -0
  49. microEye/analysis/tools/__init__.py +0 -0
  50. microEye/analysis/tools/kymograms.py +1079 -0
  51. microEye/analysis/tools/roi_selectors.py +556 -0
  52. microEye/analysis/utils/__init__.py +3 -0
  53. microEye/analysis/utils/coordinates.py +18 -0
  54. microEye/analysis/utils/images.py +68 -0
  55. microEye/analysis/utils/windows.py +19 -0
  56. microEye/analysis/viewer/__init__.py +3 -0
  57. microEye/analysis/viewer/image_options_widget.py +615 -0
  58. microEye/analysis/viewer/images.py +1225 -0
  59. microEye/analysis/viewer/layers_widget.py +415 -0
  60. microEye/analysis/viewer/localizations.py +1304 -0
  61. microEye/analysis/viewer/psf.py +1003 -0
  62. microEye/analysis/viewer/volume.py +456 -0
  63. microEye/hardware/__init__.py +3 -0
  64. microEye/hardware/cams/__init__.py +29 -0
  65. microEye/hardware/cams/camera_calibration.py +99 -0
  66. microEye/hardware/cams/camera_list.py +528 -0
  67. microEye/hardware/cams/camera_options.py +694 -0
  68. microEye/hardware/cams/camera_panel.py +941 -0
  69. microEye/hardware/cams/dummy/__init__.py +1 -0
  70. microEye/hardware/cams/dummy/dummy_panel.py +759 -0
  71. microEye/hardware/cams/jobs.py +497 -0
  72. microEye/hardware/cams/line_profiler.py +99 -0
  73. microEye/hardware/cams/linescan/IR_Cam.py +474 -0
  74. microEye/hardware/cams/linescan/__init__.py +1 -0
  75. microEye/hardware/cams/micam.py +524 -0
  76. microEye/hardware/cams/pco/__init__.py +58 -0
  77. microEye/hardware/cams/pco/enums.py +382 -0
  78. microEye/hardware/cams/pco/pco_cam.py +761 -0
  79. microEye/hardware/cams/pco/pco_panel.py +477 -0
  80. microEye/hardware/cams/shortcuts.py +312 -0
  81. microEye/hardware/cams/thorlabs/__init__.py +1 -0
  82. microEye/hardware/cams/thorlabs/thorlabs.py +1508 -0
  83. microEye/hardware/cams/thorlabs/thorlabs_panel.py +850 -0
  84. microEye/hardware/cams/ueye/__init__.py +1 -0
  85. microEye/hardware/cams/ueye/ueye_camera.py +1023 -0
  86. microEye/hardware/cams/ueye/ueye_panel.py +861 -0
  87. microEye/hardware/cams/vimba/__init__.py +1 -0
  88. microEye/hardware/cams/vimba/vimba_cam.py +1000 -0
  89. microEye/hardware/cams/vimba/vimba_panel.py +813 -0
  90. microEye/hardware/device.py +60 -0
  91. microEye/hardware/lasers/__init__.py +13 -0
  92. microEye/hardware/lasers/io_matchbox.py +791 -0
  93. microEye/hardware/lasers/io_params.py +85 -0
  94. microEye/hardware/lasers/io_single_laser.py +742 -0
  95. microEye/hardware/lasers/laser_relay.py +594 -0
  96. microEye/hardware/mieye/__init__.py +1 -0
  97. microEye/hardware/mieye/acquisition_manager.py +467 -0
  98. microEye/hardware/mieye/devices_manager.py +533 -0
  99. microEye/hardware/mieye/miEye.py +659 -0
  100. microEye/hardware/misc/__init__.py +0 -0
  101. microEye/hardware/misc/acquisition_view.py +71 -0
  102. microEye/hardware/misc/reglo.py +761 -0
  103. microEye/hardware/misc/temp.py +188 -0
  104. microEye/hardware/port_config.py +59 -0
  105. microEye/hardware/protocols/__init__.py +2 -0
  106. microEye/hardware/protocols/actions.py +402 -0
  107. microEye/hardware/protocols/actions_items.py +703 -0
  108. microEye/hardware/protocols/designer.py +244 -0
  109. microEye/hardware/protocols/scene_manager.py +191 -0
  110. microEye/hardware/protocols/serialization.py +97 -0
  111. microEye/hardware/pycromanager/__init__.py +16 -0
  112. microEye/hardware/pycromanager/core.py +1433 -0
  113. microEye/hardware/pycromanager/devices.py +461 -0
  114. microEye/hardware/pycromanager/enums.py +107 -0
  115. microEye/hardware/pycromanager/headless.py +153 -0
  116. microEye/hardware/pycromanager/utils.py +34 -0
  117. microEye/hardware/pycromanager/widgets/__init__.py +5 -0
  118. microEye/hardware/pycromanager/widgets/bridges.py +407 -0
  119. microEye/hardware/pycromanager/widgets/headless_manager.py +258 -0
  120. microEye/hardware/pycromanager/widgets/headless_options.py +224 -0
  121. microEye/hardware/pycromanager/widgets/pycro_panel.py +455 -0
  122. microEye/hardware/stages/__init__.py +18 -0
  123. microEye/hardware/stages/elliptec/__init__.py +5 -0
  124. microEye/hardware/stages/elliptec/baseDevice.py +314 -0
  125. microEye/hardware/stages/elliptec/device.py +384 -0
  126. microEye/hardware/stages/elliptec/deviceID.py +212 -0
  127. microEye/hardware/stages/elliptec/devicePort.py +379 -0
  128. microEye/hardware/stages/elliptec/deviceStatus.py +65 -0
  129. microEye/hardware/stages/elliptec/devicesView.py +706 -0
  130. microEye/hardware/stages/elliptec/ellDevices.py +134 -0
  131. microEye/hardware/stages/elliptec/messageUpdater.py +34 -0
  132. microEye/hardware/stages/elliptec/motorInfo.py +153 -0
  133. microEye/hardware/stages/elliptec/stage.py +62 -0
  134. microEye/hardware/stages/elliptec/test.py +139 -0
  135. microEye/hardware/stages/kinesis/__init__.py +1 -0
  136. microEye/hardware/stages/kinesis/kdc101/__init__.py +1 -0
  137. microEye/hardware/stages/kinesis/kdc101/enums.py +1002 -0
  138. microEye/hardware/stages/kinesis/kdc101/factory.py +171 -0
  139. microEye/hardware/stages/kinesis/kdc101/kdc101.py +718 -0
  140. microEye/hardware/stages/kinesis/kinesis.py +776 -0
  141. microEye/hardware/stages/piezo_concept.py +607 -0
  142. microEye/hardware/stages/stabilizer.py +785 -0
  143. microEye/hardware/stages/stage.py +89 -0
  144. microEye/hardware/widgets/__init__.py +10 -0
  145. microEye/hardware/widgets/controller.py +246 -0
  146. microEye/hardware/widgets/devices.py +133 -0
  147. microEye/hardware/widgets/focusWidget.py +264 -0
  148. microEye/hardware/widgets/qlist_slider.py +113 -0
  149. microEye/hardware/widgets/scan_acquisition.py +424 -0
  150. microEye/icons/1024.png +0 -0
  151. microEye/icons/128.png +0 -0
  152. microEye/icons/16.png +0 -0
  153. microEye/icons/24.png +0 -0
  154. microEye/icons/256.png +0 -0
  155. microEye/icons/32.png +0 -0
  156. microEye/icons/48.png +0 -0
  157. microEye/icons/512.png +0 -0
  158. microEye/icons/64.png +0 -0
  159. microEye/icons/__init__.py +0 -0
  160. microEye/icons/close.svg +88 -0
  161. microEye/icons/mieye.png +0 -0
  162. microEye/icons/min.svg +83 -0
  163. microEye/icons/viewer.png +0 -0
  164. microEye/launcher.py +42 -0
  165. microEye/qt.py +181 -0
  166. microEye/utils/__init__.py +2 -0
  167. microEye/utils/enum_encoder.py +10 -0
  168. microEye/utils/expandable_groupbox.py +93 -0
  169. microEye/utils/gui_helper.py +457 -0
  170. microEye/utils/hid/__init__.py +8 -0
  171. microEye/utils/hid/controller.py +153 -0
  172. microEye/utils/hid/device.py +63 -0
  173. microEye/utils/hid/enums.py +140 -0
  174. microEye/utils/hid/utils.py +58 -0
  175. microEye/utils/labelled_slider.py +134 -0
  176. microEye/utils/metadata.py +599 -0
  177. microEye/utils/metadata_tree.py +718 -0
  178. microEye/utils/micro_launcher.py +245 -0
  179. microEye/utils/parameter_tree.py +325 -0
  180. microEye/utils/pyscripting.py +444 -0
  181. microEye/utils/retry_exec.py +35 -0
  182. microEye/utils/start_gui.py +112 -0
  183. microEye/utils/thread_worker.py +115 -0
  184. microEye/utils/uImage.py +1512 -0
  185. microeye-2.3.2.dist-info/METADATA +401 -0
  186. microeye-2.3.2.dist-info/RECORD +190 -0
  187. microeye-2.3.2.dist-info/WHEEL +5 -0
  188. microeye-2.3.2.dist-info/entry_points.txt +2 -0
  189. microeye-2.3.2.dist-info/licenses/LICENSE +674 -0
  190. microeye-2.3.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,134 @@
1
+ from typing import Optional
2
+
3
+ from microEye.hardware.stages.elliptec.baseDevice import BaseDevice
4
+ from microEye.hardware.stages.elliptec.device import SHUTTER_POSITION_FACTOR, EllDevice
5
+ from microEye.hardware.stages.elliptec.deviceID import DeviceID
6
+ from microEye.hardware.stages.elliptec.devicePort import DevicePort, ELLException
7
+ from microEye.hardware.stages.elliptec.messageUpdater import MessageUpdater
8
+ from microEye.qt import QtCore
9
+
10
+
11
+ class ELLDevices(QtCore.QObject):
12
+ def __init__(self):
13
+ super().__init__()
14
+ self._selected_device: Optional[EllDevice] = None
15
+ self._devices: dict[str, EllDevice] = {}
16
+ self._message_updater = MessageUpdater()
17
+
18
+ @property
19
+ def IsOpen(self) -> bool:
20
+ return DevicePort.isOpen()
21
+
22
+ def SendFreeCommand(self, free_command: str) -> bool:
23
+ self._message_updater.update_output('Sending free command...')
24
+ DevicePort.sendFreeString(free_command)
25
+ return True
26
+
27
+ def scanAddresses(
28
+ self, min_device_address: str, max_device_address: str
29
+ ) -> list[str]:
30
+ connections = []
31
+ if not DevicePort.isOpen():
32
+ return connections
33
+
34
+ self._message_updater.update_output('Scanning for devices')
35
+ for address in [
36
+ a
37
+ for a in BaseDevice.VALID_ADDRESSES
38
+ if min_device_address <= a <= max_device_address
39
+ ]:
40
+ DevicePort.send_command(address, 'in')
41
+ try:
42
+ msg = DevicePort.wait_for_response(
43
+ address, 'IN', BaseDevice.STATUS_TIMEOUT
44
+ )
45
+ if msg:
46
+ connections.append(msg)
47
+ except ELLException as e:
48
+ DevicePort.instance().logger.error(f'Error in scanAddresses: {str(e)}')
49
+ DevicePort.instance().errorOccurred.emit(str(e))
50
+ # device address not used
51
+
52
+ count = len(connections)
53
+ self._message_updater.update_output(
54
+ f"{count} device{'s' if count != 1 else ''} found"
55
+ )
56
+ return connections
57
+
58
+ def ClearDevices(self):
59
+ self._devices.clear()
60
+
61
+ def configure(self, device_id: str) -> bool:
62
+ if not device_id:
63
+ return False
64
+
65
+ address = device_id[0]
66
+ if address in BaseDevice.VALID_ADDRESSES:
67
+ di = BaseDevice.configure(device_id, self._message_updater)
68
+ if di.DeviceType == DeviceID.DeviceTypes.Paddle:
69
+ return False
70
+ # self._devices[address] = ELLPaddlePolariser(di, self._message_updater)
71
+ elif di.DeviceType == DeviceID.DeviceTypes.Actuator:
72
+ self._devices[address] = EllDevice(di, 1, self._message_updater)
73
+ else:
74
+ self._devices[address] = EllDevice(di, 2, self._message_updater)
75
+ self._selected_device = self._devices[address]
76
+ return True
77
+
78
+ @property
79
+ def SelectedDevice(self):
80
+ return self._selected_device
81
+
82
+ def ReaddressDevice(self, old_address: str, new_address: str) -> bool:
83
+ device = self.addressedDevice(old_address)
84
+ if not device:
85
+ return False
86
+ if not device.set_address(new_address):
87
+ return False
88
+ self._devices[new_address] = self._devices.pop(old_address)
89
+ return True
90
+
91
+ def addressedDevice(self, address: str):
92
+ return self._devices.get(address)
93
+
94
+ def ValidAddresses(self, addresses: list[str]) -> list[str]:
95
+ return [addr for addr in addresses if addr in self._devices]
96
+
97
+ @property
98
+ def MessageUpdates(self) -> MessageUpdater:
99
+ return self._message_updater
100
+
101
+ def open(self) -> bool:
102
+ DevicePort.open()
103
+
104
+ def close(self) -> bool:
105
+ DevicePort.close()
106
+
107
+ def baudrate(self) -> int:
108
+ return DevicePort.baudRate()
109
+
110
+ def set_baudrate(self, baudrate: int) -> bool:
111
+ return DevicePort.setBaudRate(baudrate)
112
+
113
+ def portname(self) -> str:
114
+ return DevicePort.portName()
115
+
116
+ def set_portname(self, portname: str) -> bool:
117
+ return DevicePort.setPortName(portname)
118
+
119
+ def get_config(self) -> dict:
120
+ return {
121
+ 'port': DevicePort.portName(),
122
+ 'baudrate': DevicePort.baudRate(),
123
+ }
124
+
125
+ def load_config(self, config: dict) -> bool:
126
+ if 'port' in config:
127
+ self.set_portname(config['port'])
128
+ if 'baudrate' in config:
129
+ self.set_baudrate(config['baudrate'])
130
+ return True
131
+
132
+ @property
133
+ def ValidAddress(self) -> list[str]:
134
+ return BaseDevice.VALID_ADDRESSES
@@ -0,0 +1,34 @@
1
+ from enum import Enum
2
+ from typing import Any, Union
3
+
4
+ from microEye.qt import QtCore, Signal
5
+
6
+
7
+ class MessageUpdater(QtCore.QObject):
8
+ class UpdateTypes(Enum):
9
+ Status = 1
10
+ MotorInfo = 2
11
+ DeviceInfo = 3
12
+ Position = 4
13
+ HomeOffset = 5
14
+ JogstepSize = 6
15
+ PolarizerPositions = 7
16
+ PaddlePosition = 8
17
+
18
+ outputUpdated = Signal(list, bool)
19
+ parameterUpdated = Signal(UpdateTypes, str, object)
20
+
21
+ def __init__(self):
22
+ super().__init__()
23
+
24
+ def update_output(self, message: Union[str, list[str]], error: bool = False):
25
+ if isinstance(message, str):
26
+ message = [message]
27
+ self.outputUpdated.emit(message, error)
28
+
29
+ def update_parameter(self, update_type: UpdateTypes, address: str, data: Any):
30
+ self.parameterUpdated.emit(update_type, address, data)
31
+
32
+ def update_output_with_list(self, message: str, list_data: list[str]):
33
+ output_list = [message] + list_data
34
+ self.outputUpdated.emit(output_list, False)
@@ -0,0 +1,153 @@
1
+ import struct
2
+ from enum import Enum
3
+
4
+
5
+ class SwitchState(Enum):
6
+ ON = '1'
7
+ OFF = '0'
8
+
9
+
10
+ class MotorInfoStruct:
11
+ '''Structure containing stage axis parameters.'''
12
+
13
+ FORMAT = 'c2scc4s4s4s4s4s'
14
+ SIZE = struct.calcsize(FORMAT)
15
+
16
+ def __init__(
17
+ self,
18
+ address: bytes,
19
+ command: bytes,
20
+ loop_state: bytes,
21
+ motor_state: bytes,
22
+ current: bytes,
23
+ ramp_up: bytes,
24
+ ramp_down: bytes,
25
+ fwd_period: bytes,
26
+ rev_period: bytes,
27
+ ):
28
+ self.address = address.decode('utf-8')
29
+ self.command = command.decode('utf-8')
30
+ self.motor_id = command.decode('utf-8')[1]
31
+ self.loop_state = SwitchState(loop_state.decode('utf-8'))
32
+ self.motor_state = SwitchState(motor_state.decode('utf-8'))
33
+ self.current = int(current, 16) / 1866
34
+ self.ramp_up = int(ramp_up, 16)
35
+ self.ramp_down = int(ramp_down, 16)
36
+ self.fwd_period = int(fwd_period, 16)
37
+ self.rev_period = int(rev_period, 16)
38
+
39
+ @classmethod
40
+ def from_bytes(cls, data):
41
+ return cls(*struct.unpack(MotorInfoStruct.FORMAT, data))
42
+
43
+ class MotorInfo:
44
+ def __init__(self, motor_id: str = None):
45
+ self.motor_id = motor_id
46
+ self.motor_state = SwitchState.OFF
47
+ self.is_valid = False
48
+
49
+ self.loop_state = None
50
+ self.current = 0.0
51
+ self.ramp_up = 0
52
+ self.ramp_down = 0
53
+ self.fwd_freq = 0
54
+ self.rev_freq = 0
55
+
56
+ @classmethod
57
+ def from_string(cls, id_string: str):
58
+ motor_info_struct = MotorInfoStruct.from_bytes(id_string.encode('ascii'))
59
+ motor_info = cls('')
60
+ motor_info.motor_id = motor_info_struct.motor_id
61
+ motor_info.motor_state = motor_info_struct.motor_state
62
+ motor_info.loop_state = motor_info_struct.loop_state
63
+ motor_info.current = motor_info_struct.current
64
+ motor_info.ramp_up = motor_info_struct.ramp_up
65
+ motor_info.ramp_down = motor_info_struct.ramp_down
66
+ motor_info.fwd_freq = 14740 / motor_info_struct.fwd_period
67
+ motor_info.rev_freq = 14740 / motor_info_struct.rev_period
68
+ motor_info.is_valid = True
69
+ return motor_info
70
+
71
+ @property
72
+ def is_valid(self) -> bool:
73
+ return self._is_valid
74
+
75
+ @is_valid.setter
76
+ def is_valid(self, value: bool):
77
+ self._is_valid = value
78
+
79
+ @property
80
+ def loop_state(self) -> SwitchState:
81
+ return self._loop_state
82
+
83
+ @loop_state.setter
84
+ def loop_state(self, value: SwitchState):
85
+ self._loop_state = value
86
+
87
+ @property
88
+ def motor_state(self) -> SwitchState:
89
+ return self._motor_state
90
+
91
+ @motor_state.setter
92
+ def motor_state(self, value: SwitchState):
93
+ self._motor_state = value
94
+
95
+ @property
96
+ def current(self) -> float:
97
+ return self._current
98
+
99
+ @current.setter
100
+ def current(self, value: float):
101
+ self._current = value
102
+
103
+ @property
104
+ def ramp_up(self) -> int:
105
+ return self._ramp_up
106
+
107
+ @ramp_up.setter
108
+ def ramp_up(self, value: int):
109
+ self._ramp_up = value
110
+
111
+ @property
112
+ def ramp_down(self) -> int:
113
+ return self._ramp_down
114
+
115
+ @ramp_down.setter
116
+ def ramp_down(self, value: int):
117
+ self._ramp_down = value
118
+
119
+ @property
120
+ def fwd_freq(self) -> float:
121
+ return self._fwd_freq
122
+
123
+ @fwd_freq.setter
124
+ def fwd_freq(self, value: float):
125
+ self._fwd_freq = value
126
+
127
+ @property
128
+ def rev_freq(self) -> float:
129
+ return self._rev_freq
130
+
131
+ @rev_freq.setter
132
+ def rev_freq(self, value: float):
133
+ self._rev_freq = value
134
+
135
+ @property
136
+ def motor_id(self) -> str:
137
+ return self._motor_id
138
+
139
+ @motor_id.setter
140
+ def motor_id(self, value: str):
141
+ self._motor_id = value
142
+
143
+ def description(self) -> list:
144
+ return [
145
+ f'Motor ID {self.motor_id}',
146
+ f'Loop State {self.loop_state}',
147
+ f'Motor State {self.motor_state}',
148
+ f'Current {self.current:.2f}A',
149
+ f'Fwd Frequency {self.fwd_freq:.1f}kHz',
150
+ f'Rev Frequency {self.rev_freq:.1f}kHz',
151
+ f'RampUp {self.ramp_up}',
152
+ f'RampDown {self.ramp_down}',
153
+ ]
@@ -0,0 +1,62 @@
1
+ from enum import Enum
2
+
3
+ from microEye.qt import QtCore, Signal
4
+
5
+
6
+ class ThreadType(Enum):
7
+ Imperial = 1
8
+ Metric = 0
9
+
10
+ class ElliptecStage(QtCore.QObject):
11
+ positionChanged = Signal(int)
12
+ '''Signal emitted when position is updated'''
13
+ statusChanged = Signal(int, str)
14
+ '''Signal emitted when status is updated'''
15
+
16
+ def __init__(self, address: str, **kwargs):
17
+ super().__init__()
18
+ self.address = str(address)
19
+ # self.type = ElliptecType(kwargs.get('Model'))
20
+ self.serial_number = kwargs.get('Serial_number', 'N/A')
21
+ self.year = kwargs.get('Year', 'N/A')
22
+ self.firmware_release = kwargs.get('Firmware_release', 'N/A')
23
+ self.hardware_release = kwargs.get('Hardware_release', -1)
24
+ self.thread_type = ThreadType(kwargs.get('Thread_type', 0))
25
+ self.travel = kwargs.get('Travel', -1)
26
+ self.pulses_per_mu = kwargs.get('Pulses_per_mu', -1)
27
+ self._position = 0
28
+
29
+ self.last_response = None
30
+ self.last_status = None
31
+
32
+ @property
33
+ def position(self):
34
+ return self._position / self.pulses_per_unit()
35
+
36
+ @position.setter
37
+ def position(self, value: int):
38
+ if isinstance(value, int):
39
+ self._position = value
40
+ self.positionChanged.emit(self.position)
41
+
42
+ def update_status(self, status_code: int, status_message: str):
43
+ self.last_status = status_message
44
+ self.statusChanged.emit(status_code, status_message)
45
+
46
+ def pulses_per_unit(self):
47
+ return self.pulses_per_mu / self.travel
48
+
49
+ def __str__(self):
50
+ return (
51
+ f'ElliptecStage(address={self.address}, '
52
+ f'type={self.type.name}, '
53
+ # f'serial_number={self.serial_number}, '
54
+ # f'year={self.year}, '
55
+ # f'firmware_release={self.firmware_release}, '
56
+ # f'hardware_release={self.hardware_release}, '
57
+ # f'thread_type={self.thread_type.name}, '
58
+ # f'travel={self.travel}, '
59
+ # f'pulses_per_mu={self.pulses_per_mu}, '
60
+ f'position={self.position / self.pulses_per_unit()}, '
61
+ f'last_status={self.last_status})'
62
+ )
@@ -0,0 +1,139 @@
1
+ import sys
2
+ import time
3
+ from enum import Enum, auto
4
+
5
+ from microEye.hardware.stages.elliptec.baseDevice import BaseDevice, DeviceDirection
6
+ from microEye.hardware.stages.elliptec.deviceID import DeviceID
7
+ from microEye.hardware.stages.elliptec.devicePort import DevicePort
8
+ from microEye.hardware.stages.elliptec.ellDevices import ELLDevices
9
+ from microEye.qt import QApplication
10
+
11
+
12
+ def data_sent_handler(message: str):
13
+ print(f'\033[96mTx: {message}\033[0m') # Cyan color
14
+
15
+
16
+ def data_received_handler(message: str):
17
+ print(f'\033[92mRx: {message}\033[0m') # Green color
18
+
19
+
20
+ def output_update_handler(messages: list[str], error: bool):
21
+ for message in messages:
22
+ print(f'\033[93mOutput-> {message}\033[0m') # Yellow color
23
+
24
+
25
+ def main(args: list[str]):
26
+ # Get the communication port
27
+ port = args[0] if len(args) > 0 else 'COM3'
28
+
29
+ # Get the range of addresses used (max range is '0' to 'F')
30
+ min_search_limit = (
31
+ args[1][0].upper()
32
+ if len(args) > 1 and BaseDevice.is_valid_address(args[1][0].upper())
33
+ else '0'
34
+ )
35
+ max_search_limit = (
36
+ args[2][0].upper()
37
+ if len(args) > 2 and BaseDevice.is_valid_address(args[2][0].upper())
38
+ else '3'
39
+ )
40
+
41
+ # Setup handlers
42
+ DevicePort.instance().dataSent.connect(data_sent_handler)
43
+ DevicePort.instance().dataReceived.connect(data_received_handler)
44
+
45
+ # Create ELLDevices class to maintain the collection of Elliptec devices
46
+ ell_devices = ELLDevices()
47
+ ell_devices.MessageUpdates.outputUpdated.connect(output_update_handler)
48
+
49
+ # Attempt to connect to the port
50
+ if DevicePort.open(port):
51
+ print('Discover devices')
52
+ print('================')
53
+ # Scan the port for connected devices using the given range of addresses
54
+ devices = ell_devices.scanAddresses(min_search_limit, max_search_limit)
55
+
56
+ for device in devices:
57
+ # Configure each device found
58
+ if ell_devices.configure(device):
59
+ # Test each device found
60
+ print(f'\nIdentify device {device[0]}')
61
+ print('=================')
62
+ addressed_device = ell_devices.addressedDevice(device[0])
63
+
64
+ if addressed_device:
65
+ # Display the device information
66
+ device_info = addressed_device.deviceInfo
67
+ for info in device_info.description():
68
+ print(info)
69
+
70
+ # Test each device according to type
71
+ print(f'\nTest device {device[0]}')
72
+ print('=============')
73
+ if device_info.DeviceType in [
74
+ DeviceID.DeviceTypes.Shutter2,
75
+ DeviceID.DeviceTypes.Shutter4,
76
+ ]:
77
+ # Test the shutter device
78
+ addressed_device.home(DeviceDirection.Linear)
79
+ time.sleep(0.25)
80
+ addressed_device.jog_forward()
81
+ time.sleep(0.25)
82
+ if device_info.DeviceType == DeviceID.DeviceTypes.Shutter4:
83
+ addressed_device.jog_forward()
84
+ time.sleep(0.25)
85
+ addressed_device.jog_forward()
86
+ time.sleep(0.25)
87
+ addressed_device.jog_backward()
88
+ time.sleep(0.25)
89
+ if device_info.DeviceType == DeviceID.DeviceTypes.Shutter4:
90
+ addressed_device.jog_backward()
91
+ time.sleep(0.25)
92
+ addressed_device.jog_backward()
93
+ time.sleep(0.25)
94
+ elif device_info.DeviceType in [
95
+ DeviceID.DeviceTypes.LinearStage25mm,
96
+ DeviceID.DeviceTypes.LinearStage28mm,
97
+ DeviceID.DeviceTypes.LinearStage60mm,
98
+ DeviceID.DeviceTypes.LinearStage60mm_10,
99
+ ]:
100
+ # Test the Linear stage
101
+ # For each motor ('1' and '2') get the motor information
102
+ for c in ['1', '2']:
103
+ if addressed_device.get_motor_info(c):
104
+ motor_info = addressed_device._motor_info[c]
105
+ for info in motor_info.description():
106
+ print(f'Output-> {info}')
107
+
108
+ # Test the stage movement
109
+ addressed_device.home(DeviceDirection.Linear)
110
+ time.sleep(0.25)
111
+ addressed_device.set_jogstep_size(1.0)
112
+ for _ in range(10):
113
+ addressed_device.jog_forward()
114
+ time.sleep(0.1)
115
+ elif device_info.DeviceType in [DeviceID.DeviceTypes.OpticsRotator]:
116
+ for c in ['1', '2']:
117
+ if addressed_device.get_motor_info(c):
118
+ motor_info = addressed_device._motor_info[c]
119
+ for info in motor_info.description():
120
+ print(f'Output-> {info}')
121
+ # Test the stage movement
122
+ addressed_device.home(DeviceDirection.Clockwise)
123
+ time.sleep(0.25)
124
+ addressed_device.set_jogstep_size(10.0)
125
+ for _ in range(10):
126
+ addressed_device.jog_forward()
127
+ time.sleep(0.1)
128
+
129
+ DevicePort.close()
130
+ else:
131
+ print(f'\033[91mPort {port} unavailable\033[0m') # Red color
132
+
133
+ print('Press Enter to exit')
134
+ input()
135
+
136
+
137
+ if __name__ == '__main__':
138
+ app = QApplication([])
139
+ main(sys.argv[1:])
@@ -0,0 +1 @@
1
+ from microEye.hardware.stages.kinesis.kinesis import KinesisView, KinesisXY
@@ -0,0 +1 @@
1
+ from microEye.hardware.stages.kinesis.kdc101.kdc101 import KDC101Controller