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.
- microEye/__init__.py +47 -0
- microEye/_version.py +2 -0
- microEye/analysis/__init__.py +1 -0
- microEye/analysis/checklist_dialog.py +143 -0
- microEye/analysis/cmosMaps.py +228 -0
- microEye/analysis/filters/__init__.py +9 -0
- microEye/analysis/filters/base.py +21 -0
- microEye/analysis/filters/spatial.py +338 -0
- microEye/analysis/filters/temporal.py +76 -0
- microEye/analysis/fitting/__init__.py +0 -0
- microEye/analysis/fitting/fit.py +680 -0
- microEye/analysis/fitting/nena.py +375 -0
- microEye/analysis/fitting/phasor_fit.py +90 -0
- microEye/analysis/fitting/processing.py +317 -0
- microEye/analysis/fitting/psf/__init__.py +6 -0
- microEye/analysis/fitting/psf/extract.py +1129 -0
- microEye/analysis/fitting/psf/rubost_mean.py +150 -0
- microEye/analysis/fitting/psf/spline.py +167 -0
- microEye/analysis/fitting/psf/stats/__init__.py +12 -0
- microEye/analysis/fitting/psf/stats/core.py +295 -0
- microEye/analysis/fitting/psf/stats/curve_fit.py +708 -0
- microEye/analysis/fitting/psf/stats/io.py +104 -0
- microEye/analysis/fitting/psf/stats/slope_fit.py +171 -0
- microEye/analysis/fitting/psf/temp.py +147 -0
- microEye/analysis/fitting/psf/test.py +47 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUfunctions.py +657 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUmleFit_LM.py +1336 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUsplineLib.py +270 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/__init__.py +1 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUfunctions.py +609 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_EMCCD.py +1396 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_sCMOS.py +1426 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUsplineLib.py +231 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/__init__.py +2 -0
- microEye/analysis/fitting/pyfit3Dcspline/__init__.py +10 -0
- microEye/analysis/fitting/pyfit3Dcspline/constants.py +27 -0
- microEye/analysis/fitting/pyfit3Dcspline/mainfunctions.py +903 -0
- microEye/analysis/fitting/results.py +917 -0
- microEye/analysis/fitting/results_stats.py +251 -0
- microEye/analysis/fitting/tardis.py +209 -0
- microEye/analysis/multi_viewer.py +568 -0
- microEye/analysis/processing/__init__.py +1 -0
- microEye/analysis/processing/frc.py +120 -0
- microEye/analysis/rendering/__init__.py +3 -0
- microEye/analysis/rendering/base.py +452 -0
- microEye/analysis/rendering/cloud.py +215 -0
- microEye/analysis/rendering/core.py +47 -0
- microEye/analysis/rendering/volumetric.py +198 -0
- microEye/analysis/tools/__init__.py +0 -0
- microEye/analysis/tools/kymograms.py +1079 -0
- microEye/analysis/tools/roi_selectors.py +556 -0
- microEye/analysis/utils/__init__.py +3 -0
- microEye/analysis/utils/coordinates.py +18 -0
- microEye/analysis/utils/images.py +68 -0
- microEye/analysis/utils/windows.py +19 -0
- microEye/analysis/viewer/__init__.py +3 -0
- microEye/analysis/viewer/image_options_widget.py +615 -0
- microEye/analysis/viewer/images.py +1225 -0
- microEye/analysis/viewer/layers_widget.py +415 -0
- microEye/analysis/viewer/localizations.py +1304 -0
- microEye/analysis/viewer/psf.py +1003 -0
- microEye/analysis/viewer/volume.py +456 -0
- microEye/hardware/__init__.py +3 -0
- microEye/hardware/cams/__init__.py +29 -0
- microEye/hardware/cams/camera_calibration.py +99 -0
- microEye/hardware/cams/camera_list.py +528 -0
- microEye/hardware/cams/camera_options.py +694 -0
- microEye/hardware/cams/camera_panel.py +941 -0
- microEye/hardware/cams/dummy/__init__.py +1 -0
- microEye/hardware/cams/dummy/dummy_panel.py +759 -0
- microEye/hardware/cams/jobs.py +497 -0
- microEye/hardware/cams/line_profiler.py +99 -0
- microEye/hardware/cams/linescan/IR_Cam.py +474 -0
- microEye/hardware/cams/linescan/__init__.py +1 -0
- microEye/hardware/cams/micam.py +524 -0
- microEye/hardware/cams/pco/__init__.py +58 -0
- microEye/hardware/cams/pco/enums.py +382 -0
- microEye/hardware/cams/pco/pco_cam.py +761 -0
- microEye/hardware/cams/pco/pco_panel.py +477 -0
- microEye/hardware/cams/shortcuts.py +312 -0
- microEye/hardware/cams/thorlabs/__init__.py +1 -0
- microEye/hardware/cams/thorlabs/thorlabs.py +1508 -0
- microEye/hardware/cams/thorlabs/thorlabs_panel.py +850 -0
- microEye/hardware/cams/ueye/__init__.py +1 -0
- microEye/hardware/cams/ueye/ueye_camera.py +1023 -0
- microEye/hardware/cams/ueye/ueye_panel.py +861 -0
- microEye/hardware/cams/vimba/__init__.py +1 -0
- microEye/hardware/cams/vimba/vimba_cam.py +1000 -0
- microEye/hardware/cams/vimba/vimba_panel.py +813 -0
- microEye/hardware/device.py +60 -0
- microEye/hardware/lasers/__init__.py +13 -0
- microEye/hardware/lasers/io_matchbox.py +791 -0
- microEye/hardware/lasers/io_params.py +85 -0
- microEye/hardware/lasers/io_single_laser.py +742 -0
- microEye/hardware/lasers/laser_relay.py +594 -0
- microEye/hardware/mieye/__init__.py +1 -0
- microEye/hardware/mieye/acquisition_manager.py +467 -0
- microEye/hardware/mieye/devices_manager.py +533 -0
- microEye/hardware/mieye/miEye.py +659 -0
- microEye/hardware/misc/__init__.py +0 -0
- microEye/hardware/misc/acquisition_view.py +71 -0
- microEye/hardware/misc/reglo.py +761 -0
- microEye/hardware/misc/temp.py +188 -0
- microEye/hardware/port_config.py +59 -0
- microEye/hardware/protocols/__init__.py +2 -0
- microEye/hardware/protocols/actions.py +402 -0
- microEye/hardware/protocols/actions_items.py +703 -0
- microEye/hardware/protocols/designer.py +244 -0
- microEye/hardware/protocols/scene_manager.py +191 -0
- microEye/hardware/protocols/serialization.py +97 -0
- microEye/hardware/pycromanager/__init__.py +16 -0
- microEye/hardware/pycromanager/core.py +1433 -0
- microEye/hardware/pycromanager/devices.py +461 -0
- microEye/hardware/pycromanager/enums.py +107 -0
- microEye/hardware/pycromanager/headless.py +153 -0
- microEye/hardware/pycromanager/utils.py +34 -0
- microEye/hardware/pycromanager/widgets/__init__.py +5 -0
- microEye/hardware/pycromanager/widgets/bridges.py +407 -0
- microEye/hardware/pycromanager/widgets/headless_manager.py +258 -0
- microEye/hardware/pycromanager/widgets/headless_options.py +224 -0
- microEye/hardware/pycromanager/widgets/pycro_panel.py +455 -0
- microEye/hardware/stages/__init__.py +18 -0
- microEye/hardware/stages/elliptec/__init__.py +5 -0
- microEye/hardware/stages/elliptec/baseDevice.py +314 -0
- microEye/hardware/stages/elliptec/device.py +384 -0
- microEye/hardware/stages/elliptec/deviceID.py +212 -0
- microEye/hardware/stages/elliptec/devicePort.py +379 -0
- microEye/hardware/stages/elliptec/deviceStatus.py +65 -0
- microEye/hardware/stages/elliptec/devicesView.py +706 -0
- microEye/hardware/stages/elliptec/ellDevices.py +134 -0
- microEye/hardware/stages/elliptec/messageUpdater.py +34 -0
- microEye/hardware/stages/elliptec/motorInfo.py +153 -0
- microEye/hardware/stages/elliptec/stage.py +62 -0
- microEye/hardware/stages/elliptec/test.py +139 -0
- microEye/hardware/stages/kinesis/__init__.py +1 -0
- microEye/hardware/stages/kinesis/kdc101/__init__.py +1 -0
- microEye/hardware/stages/kinesis/kdc101/enums.py +1002 -0
- microEye/hardware/stages/kinesis/kdc101/factory.py +171 -0
- microEye/hardware/stages/kinesis/kdc101/kdc101.py +718 -0
- microEye/hardware/stages/kinesis/kinesis.py +776 -0
- microEye/hardware/stages/piezo_concept.py +607 -0
- microEye/hardware/stages/stabilizer.py +785 -0
- microEye/hardware/stages/stage.py +89 -0
- microEye/hardware/widgets/__init__.py +10 -0
- microEye/hardware/widgets/controller.py +246 -0
- microEye/hardware/widgets/devices.py +133 -0
- microEye/hardware/widgets/focusWidget.py +264 -0
- microEye/hardware/widgets/qlist_slider.py +113 -0
- microEye/hardware/widgets/scan_acquisition.py +424 -0
- microEye/icons/1024.png +0 -0
- microEye/icons/128.png +0 -0
- microEye/icons/16.png +0 -0
- microEye/icons/24.png +0 -0
- microEye/icons/256.png +0 -0
- microEye/icons/32.png +0 -0
- microEye/icons/48.png +0 -0
- microEye/icons/512.png +0 -0
- microEye/icons/64.png +0 -0
- microEye/icons/__init__.py +0 -0
- microEye/icons/close.svg +88 -0
- microEye/icons/mieye.png +0 -0
- microEye/icons/min.svg +83 -0
- microEye/icons/viewer.png +0 -0
- microEye/launcher.py +42 -0
- microEye/qt.py +181 -0
- microEye/utils/__init__.py +2 -0
- microEye/utils/enum_encoder.py +10 -0
- microEye/utils/expandable_groupbox.py +93 -0
- microEye/utils/gui_helper.py +457 -0
- microEye/utils/hid/__init__.py +8 -0
- microEye/utils/hid/controller.py +153 -0
- microEye/utils/hid/device.py +63 -0
- microEye/utils/hid/enums.py +140 -0
- microEye/utils/hid/utils.py +58 -0
- microEye/utils/labelled_slider.py +134 -0
- microEye/utils/metadata.py +599 -0
- microEye/utils/metadata_tree.py +718 -0
- microEye/utils/micro_launcher.py +245 -0
- microEye/utils/parameter_tree.py +325 -0
- microEye/utils/pyscripting.py +444 -0
- microEye/utils/retry_exec.py +35 -0
- microEye/utils/start_gui.py +112 -0
- microEye/utils/thread_worker.py +115 -0
- microEye/utils/uImage.py +1512 -0
- microeye-2.3.2.dist-info/METADATA +401 -0
- microeye-2.3.2.dist-info/RECORD +190 -0
- microeye-2.3.2.dist-info/WHEEL +5 -0
- microeye-2.3.2.dist-info/entry_points.txt +2 -0
- microeye-2.3.2.dist-info/licenses/LICENSE +674 -0
- 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
|