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,659 @@
1
+ import json
2
+ import os
3
+ import warnings
4
+ import weakref
5
+ import webbrowser
6
+ from enum import Enum
7
+
8
+ from scipy.optimize import OptimizeWarning
9
+
10
+ from microEye.hardware.cams import *
11
+ from microEye.hardware.lasers import *
12
+ from microEye.hardware.mieye.acquisition_manager import AcquisitionManager
13
+ from microEye.hardware.mieye.devices_manager import DEVICES, DeviceManager
14
+ from microEye.hardware.protocols import ExperimentDesigner
15
+ from microEye.hardware.pycromanager.widgets import BridgesWidget, HeadlessManagerWidget
16
+ from microEye.hardware.stages import FocusStabilizer
17
+ from microEye.hardware.widgets import (
18
+ Controller,
19
+ DevicesView,
20
+ )
21
+ from microEye.qt import (
22
+ QT_API,
23
+ QAction,
24
+ QApplication,
25
+ QDateTime,
26
+ QMainWindow,
27
+ Qt,
28
+ QtCore,
29
+ QtWidgets,
30
+ )
31
+ from microEye.utils.pyscripting import pyEditor
32
+ from microEye.utils.retry_exec import retry_exec
33
+ from microEye.utils.start_gui import StartGUI
34
+
35
+ warnings.filterwarnings('ignore', category=OptimizeWarning)
36
+
37
+
38
+ class DOCKS(Enum):
39
+ DEVICES = 0
40
+ LASERS = 1
41
+ STAGES = 2
42
+ FOCUS = 3
43
+ CAMERAS = 4
44
+ PYSCRIPT = 5
45
+ PROTOCOLS = 6
46
+ CONTROLLER = 7
47
+ FOCUS_CAMERA = 8
48
+
49
+ def get_key(self):
50
+ return self.name.lower() + '_dock'
51
+
52
+
53
+ class miEye_module(QMainWindow):
54
+ '''The main GUI for miEye combines control and acquisition modules.
55
+
56
+ Inherits `QMainWindow`
57
+
58
+ Attributes:
59
+ - devicesDock (`QDockWidget`):
60
+ - devicesWidget (`QWidget`):
61
+ - devicesLayout (`QHBoxLayout`):
62
+ - hid_controller (`hidController`)
63
+ - devicesView (`DevicesView`)
64
+
65
+ - ir_widget (`QDockWidget`, optional):
66
+ - `QWidget`
67
+
68
+ - stagesDock (`QDockWidget`):
69
+ - stagesWidget (`QWidget`):
70
+ - stages_Layout (`QHBoxLayout`):
71
+ - z-stage (`FocPzView`)
72
+ - elliptec_controller (`elliptec_controller`)
73
+ - kinesisXY (`KinesisXY`)
74
+ - scanAcqWidget (`ScanAcquisitionWidget`)
75
+
76
+ - pyDock (`QDockWidget`):
77
+ - pyEditor (`pyEditor`)
78
+
79
+ - lasersDock (`QDockWidget`):
80
+ - lasersWidget (`QWidget`):
81
+ - lasersLayout (`QHBoxLayout`):
82
+ - laserRelayCtrllr (`LaserRelayController`)
83
+ - lasers ...
84
+
85
+ - camDock (`QDockWidget`):
86
+ - camList (`CameraList`)
87
+
88
+ - focus (`focusWidget`)
89
+ '''
90
+
91
+ def __init__(self, *args, **kwargs):
92
+ super().__init__(*args, **kwargs)
93
+
94
+ self.device_manager = DeviceManager()
95
+ self.acquisition_manager = AcquisitionManager()
96
+
97
+ self.device_manager.widgetAdded.connect(self._add_widgets)
98
+ self.device_manager.widgetRemoved.connect(self._remove_widgets)
99
+
100
+ # setting title
101
+ self.setWindowTitle('miEye module')
102
+
103
+ # setting geometry
104
+ self.setGeometry(0, 0, 1200, 920)
105
+
106
+ # Statusbar time
107
+ self.statusBar().showMessage(
108
+ f'{QT_API} | Time: '
109
+ + QtCore.QDateTime.currentDateTime().toString('hh:mm:ss,zzz')
110
+ )
111
+
112
+ # Threading
113
+ max_threads = QtCore.QThreadPool.globalInstance().maxThreadCount()
114
+ print(f'Multithreading with maximum {max_threads} threads')
115
+
116
+ # IR 1D array
117
+ self.ir_array_dock = None
118
+
119
+ # IR 2D Camera
120
+ self.cam_dock = None
121
+
122
+ # Layout
123
+ self.LayoutInit()
124
+
125
+ self.device_manager.init_devices()
126
+
127
+ # Statues Bar Timer
128
+ self.timer = QtCore.QTimer()
129
+ self.timer.setInterval(250)
130
+ self.timer.timeout.connect(self.update_gui)
131
+ self.timer.start()
132
+
133
+ self.show()
134
+
135
+ # centered
136
+ self.center()
137
+
138
+ def center(self):
139
+ '''Centers the window within the screen.'''
140
+ qtRectangle = self.frameGeometry()
141
+ centerPoint = QApplication.primaryScreen().availableGeometry().center()
142
+ qtRectangle.moveCenter(centerPoint)
143
+ self.move(qtRectangle.topLeft())
144
+
145
+ def LayoutInit(self):
146
+ '''Initializes the window layout'''
147
+
148
+ self.dock_widgets: weakref.WeakValueDictionary[DOCKS, QtWidgets.QDockWidget] = (
149
+ weakref.WeakValueDictionary()
150
+ )
151
+
152
+ self.labelStyle = {'color': '#FFF', 'font-size': '10pt'}
153
+
154
+ self.init_controller()
155
+ self.init_devices_dock()
156
+ # self.init_ir_dock()
157
+ self.init_stages_dock()
158
+ self.init_py_dock()
159
+ self.init_protocol_dock()
160
+ self.init_lasers_dock()
161
+ self.init_cam_dock()
162
+ self.tabifyDocks()
163
+
164
+ self.init_menubar()
165
+
166
+ def init_controller(self):
167
+ self.controller = Controller()
168
+ self.controller.stage_move_requested.connect(
169
+ DeviceManager.instance().moveRequest
170
+ )
171
+ self.controller.stage_stop_requested.connect(
172
+ DeviceManager.instance().stopRequest
173
+ )
174
+ self.controller.stage_home_requested.connect(
175
+ DeviceManager.instance().homeRequest
176
+ )
177
+ self.controller.stage_toggle_lock.connect(DeviceManager.instance().toggleLock)
178
+
179
+ self.addDockWidget(
180
+ Qt.DockWidgetArea.LeftDockWidgetArea, self.controller, DOCKS.CONTROLLER
181
+ )
182
+
183
+ def init_devices_dock(self):
184
+ # General settings groupbox
185
+ self.devicesDock = QtWidgets.QDockWidget('Devices', self)
186
+ self.devicesDock.setFeatures(
187
+ QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable
188
+ | QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable
189
+ )
190
+ devicesWidget = QtWidgets.QWidget()
191
+ self.devicesDock.setWidget(devicesWidget)
192
+ self.addDockWidget(
193
+ Qt.DockWidgetArea.RightDockWidgetArea, self.devicesDock, DOCKS.DEVICES
194
+ )
195
+
196
+ # vertical layout
197
+ devicesLayout = QtWidgets.QGridLayout()
198
+ devicesWidget.setLayout(devicesLayout)
199
+
200
+ self.devicesView = DevicesView()
201
+ self.devicesView.setDetectorActivated.connect(
202
+ self.device_manager._set_ir_array_detector
203
+ )
204
+ self.devicesView.resetDetectorActivated.connect(
205
+ self.device_manager._remove_ir_array_detector
206
+ )
207
+ self.devicesView.addLaserActivated.connect(self.device_manager._add_laser)
208
+ self.devicesView.setStageActivated.connect(self.device_manager._set_z_stage)
209
+
210
+ devicesLayout.addWidget(self.devicesView, 0, 1)
211
+
212
+ def init_stages_dock(self):
213
+ # Stages Tab (Elliptec + Kinesis Tab + Scan Acquisition)
214
+ self.stagesDock = QtWidgets.QDockWidget('Stages', self)
215
+ self.stagesDock.setFeatures(
216
+ QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable
217
+ | QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable
218
+ )
219
+ self.stagesWidget = QtWidgets.QTabWidget()
220
+ self.stagesWidget.setMinimumWidth(350)
221
+ self.stagesDock.setWidget(self.stagesWidget)
222
+
223
+ self.stagesWidget.addTab(
224
+ self.acquisition_manager.acquisitionWidget, 'Scan Acquistion'
225
+ )
226
+
227
+ self.addDockWidget(
228
+ Qt.DockWidgetArea.LeftDockWidgetArea, self.stagesDock, DOCKS.STAGES
229
+ )
230
+
231
+ def init_py_dock(self):
232
+ # Py Script Editor
233
+ self.pyDock = QtWidgets.QDockWidget('PyScript', self)
234
+ self.pyDock.setFeatures(
235
+ QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable
236
+ | QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable
237
+ )
238
+ self.pyEditor = pyEditor()
239
+ self.pyEditor.exec_btn.clicked.connect(lambda: self.scriptTest())
240
+ self.pyDock.setWidget(self.pyEditor)
241
+
242
+ self.addDockWidget(
243
+ Qt.DockWidgetArea.RightDockWidgetArea, self.pyDock, DOCKS.PYSCRIPT
244
+ )
245
+
246
+ def init_protocol_dock(self):
247
+ self.protocolDock = QtWidgets.QDockWidget('Protocols', self)
248
+ self.protocolDock.setFeatures(
249
+ QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable
250
+ | QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable
251
+ )
252
+ self.actionEditor = ExperimentDesigner()
253
+ self.protocolDock.setWidget(self.actionEditor)
254
+
255
+ self.addDockWidget(
256
+ Qt.DockWidgetArea.RightDockWidgetArea, self.protocolDock, DOCKS.PROTOCOLS
257
+ )
258
+
259
+ def init_lasers_dock(self):
260
+ # Lasers Tab
261
+ self.lasersDock = QtWidgets.QDockWidget('Lasers', self)
262
+ self.lasersDock.setFeatures(
263
+ QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable
264
+ | QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable
265
+ )
266
+ self.lasersLayout = QtWidgets.QGridLayout()
267
+
268
+ self.lasersWidget = QtWidgets.QWidget()
269
+ self.lasersWidget.setLayout(self.lasersLayout)
270
+
271
+ self.lasersTabs = QtWidgets.QTabWidget()
272
+
273
+ self.lasersDock.setWidget(self.lasersWidget)
274
+
275
+ self.lasersLayout.addWidget(self.lasersTabs, 0, 1)
276
+
277
+ self.addDockWidget(
278
+ Qt.DockWidgetArea.RightDockWidgetArea, self.lasersDock, DOCKS.LASERS
279
+ )
280
+
281
+ def init_cam_dock(self):
282
+ # cameras tab
283
+ self.camDock = QtWidgets.QDockWidget('Cameras List', self)
284
+ self.camDock.setFeatures(
285
+ QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable
286
+ | QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable
287
+ )
288
+
289
+ self.addDockWidget(
290
+ Qt.DockWidgetArea.RightDockWidgetArea, self.camDock, DOCKS.CAMERAS
291
+ )
292
+
293
+ def init_menubar(self):
294
+ # Create menu bar
295
+ menu_bar = self.menuBar()
296
+
297
+ # Create file menu
298
+ file_menu = menu_bar.addMenu('File')
299
+ view_menu = menu_bar.addMenu('View')
300
+ tools_menu = menu_bar.addMenu('Tools')
301
+ help_menu = menu_bar.addMenu('Help')
302
+
303
+ # Create exit action
304
+ save_config = QAction('Save Config.', self)
305
+ save_config.triggered.connect(lambda: generateConfig(self))
306
+ load_config = QAction('Load Config.', self)
307
+ load_config.triggered.connect(lambda: loadConfig(self, False))
308
+ auto_load_config = QAction('Load Config. && Connect', self)
309
+ auto_load_config.triggered.connect(lambda: loadConfig(self, True))
310
+ disconnect_devices = QAction('Disconnect Devices', self)
311
+ disconnect_devices.triggered.connect(
312
+ lambda: self.device_manager.shutdown(self, False)
313
+ )
314
+ shutdown_and_exit = QAction('Exit & Disconnect Devices', self)
315
+ shutdown_and_exit.triggered.connect(lambda: self.device_manager.shutdown(self))
316
+
317
+ github = QAction('microEye Github', self)
318
+ github.triggered.connect(
319
+ lambda: webbrowser.open('https://github.com/samhitech/microEye')
320
+ )
321
+ pypi = QAction('microEye PYPI', self)
322
+ pypi.triggered.connect(
323
+ lambda: webbrowser.open('https://pypi.org/project/microEye/')
324
+ )
325
+
326
+ # Add exit action to file menu
327
+ file_menu.addAction(save_config)
328
+ file_menu.addAction(load_config)
329
+ file_menu.addAction(auto_load_config)
330
+ file_menu.addAction(disconnect_devices)
331
+ file_menu.addAction(shutdown_and_exit)
332
+
333
+ docks: list[QtWidgets.QDockWidget] = [
334
+ self.controller,
335
+ self.devicesDock,
336
+ self.pyDock,
337
+ self.stagesDock,
338
+ self.camDock,
339
+ self.lasersDock,
340
+ ]
341
+
342
+ def connect(action: QAction, dock: QtWidgets.QDockWidget):
343
+ action.triggered.connect(lambda: dock.setVisible(action.isChecked()))
344
+
345
+ for dock in docks:
346
+ dock_act = dock.toggleViewAction()
347
+ dock_act.setEnabled(True)
348
+ if '6' in QT_API:
349
+ connect(dock_act, dock)
350
+ view_menu.addAction(dock_act)
351
+
352
+ # Tools menu
353
+ pycro_headless = HeadlessManagerWidget.get_menu_action(self)
354
+ core_instances = BridgesWidget.get_menu_action(self)
355
+
356
+ tools_menu.addAction(pycro_headless)
357
+ tools_menu.addAction(core_instances)
358
+
359
+ help_menu.addAction(github)
360
+ help_menu.addAction(pypi)
361
+
362
+ def tabifyDocks(self):
363
+ self.setTabPosition(
364
+ Qt.DockWidgetArea.LeftDockWidgetArea,
365
+ QtWidgets.QTabWidget.TabPosition.North,
366
+ )
367
+ self.setTabPosition(
368
+ Qt.DockWidgetArea.RightDockWidgetArea,
369
+ QtWidgets.QTabWidget.TabPosition.North,
370
+ )
371
+
372
+ self.tabifyDockWidget(self.lasersDock, self.devicesDock)
373
+ self.tabifyDockWidget(self.lasersDock, self.camDock)
374
+ self.tabifyDockWidget(self.lasersDock, self.protocolDock)
375
+ self.tabifyDockWidget(self.lasersDock, self.pyDock)
376
+
377
+ self.tabifyDockWidget(self.stagesDock, self.controller)
378
+
379
+ self.stagesDock.raise_()
380
+
381
+ def scriptTest(self):
382
+ exec(self.pyEditor.toPlainText())
383
+
384
+ def getDockWidget(self, text: str, content: QtWidgets.QWidget):
385
+ dock = QtWidgets.QDockWidget(text, self)
386
+ dock.setFeatures(
387
+ QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable
388
+ | QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable
389
+ )
390
+ dock.setWidget(content)
391
+ return dock
392
+
393
+ def _add_widgets(self, device: DEVICES, widget: QtWidgets.QWidget):
394
+ if device == DEVICES.LASER:
395
+ self.lasersTabs.addTab(widget, f'Laser #{self.lasersTabs.count() + 1}')
396
+
397
+ self.lasersTabs.setCurrentIndex(self.lasersTabs.count() - 1)
398
+
399
+ elif device == DEVICES.IR_CAM:
400
+ if isinstance(widget, Camera_Panel):
401
+ # IR camera widget
402
+ self.cam_dock = self.getDockWidget(widget._cam.name, widget)
403
+ self.addDockWidget(
404
+ Qt.DockWidgetArea.RightDockWidgetArea,
405
+ self.cam_dock,
406
+ DOCKS.FOCUS_CAMERA,
407
+ )
408
+ self.tabifyDockWidget(self.lasersDock, self.cam_dock)
409
+ self.cam_dock.raise_() # Bring to front
410
+ self.device_manager.focus.graph_IR.setLabel(
411
+ 'left', 'Signal', '', **self.labelStyle
412
+ )
413
+
414
+ else:
415
+ if self.ir_array_dock is None:
416
+ self.ir_array_dock = QtWidgets.QDockWidget('Array Detector')
417
+ self.ir_array_dock.setFeatures(
418
+ QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable
419
+ | QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable
420
+ )
421
+ self.addDockWidget(
422
+ Qt.DockWidgetArea.RightDockWidgetArea,
423
+ self.ir_array_dock,
424
+ DOCKS.FOCUS_CAMERA,
425
+ )
426
+ self.tabifyDockWidget(self.devicesDock, self.ir_array_dock)
427
+
428
+ self.ir_array_dock.setWidget(widget)
429
+ self.ir_array_dock.raise_() # Bring to front
430
+ self.device_manager.focus.graph_IR.setLabel(
431
+ 'left', 'Signal', 'V', **self.labelStyle
432
+ )
433
+
434
+ elif device == DEVICES.Z_STAGE:
435
+ self.stagesWidget.insertTab(0, widget, 'Z-Stage')
436
+ self.stagesWidget.setCurrentIndex(0)
437
+
438
+ elif device == DEVICES.XY_STAGE:
439
+ self.stagesWidget.insertTab(1, widget, 'XY-Stage')
440
+ self.stagesWidget.setCurrentIndex(1)
441
+
442
+ elif device == DEVICES.ELLIPTEC:
443
+ self.stagesWidget.insertTab(2, widget, 'Elliptec Devices')
444
+ self.stagesWidget.setCurrentIndex(2)
445
+
446
+ elif device == DEVICES.HID_CONTROLLER:
447
+ devicesLayout = self.devicesDock.widget().layout()
448
+
449
+ devicesLayout.addWidget(widget, 0, 0)
450
+
451
+ elif device == DEVICES.LASER_RELAY:
452
+ self.lasersLayout.addWidget(widget, 0, 0)
453
+
454
+ elif device == DEVICES.FocusStabilizer:
455
+ self.addDockWidget(
456
+ Qt.DockWidgetArea.RightDockWidgetArea, widget, DOCKS.FOCUS
457
+ )
458
+ self.tabifyDockWidget(self.lasersDock, widget)
459
+ widget.raise_() # Bring to front
460
+ elif device == DEVICES.CAM_LIST:
461
+ self.camDock.setWidget(widget)
462
+
463
+ def _remove_widgets(self, device: DEVICES, widget: QtWidgets.QWidget):
464
+ if device == DEVICES.LASER:
465
+ index = self.lasersTabs.indexOf(widget)
466
+ self.lasersTabs.removeTab(index)
467
+ elif device == DEVICES.IR_CAM:
468
+ if isinstance(widget, Camera_Panel):
469
+ self.removeDockWidget(self.cam_dock)
470
+ self.cam_dock.deleteLater()
471
+ self.cam_dock = None
472
+
473
+ else:
474
+ self.removeDockWidget(self.ir_array_dock)
475
+ self.ir_array_dock.deleteLater()
476
+ self.ir_array_dock = None
477
+
478
+ elif device == DEVICES.Z_STAGE:
479
+ pass
480
+
481
+ def update_gui(self):
482
+ '''Recurring timer updates the status bar and GUI'''
483
+
484
+ RelayBox = ' | Relay ' + (
485
+ 'connected'
486
+ if DeviceManager.instance().laser_relay.isOpen()
487
+ else 'disconnected'
488
+ )
489
+
490
+ Position = ''
491
+ Frames = ' | Frames Saved: ' + str(
492
+ FocusStabilizer.instance().num_frames_saved
493
+ )
494
+
495
+ Worker = f' | Execution time: {FocusStabilizer.instance()._exec_time:.0f}'
496
+ if DeviceManager.instance().camList.autofocusCam:
497
+ Worker += (
498
+ f' | Frames Buffer: {FocusStabilizer.instance().bufferSize():d}'
499
+ )
500
+ self.statusBar().showMessage(
501
+ f'{QT_API} | '
502
+ + 'Time: '
503
+ + QDateTime.currentDateTime().toString('hh:mm:ss,zzz')
504
+ + RelayBox
505
+ + Position
506
+ + Frames
507
+ + Worker
508
+ )
509
+
510
+ # update indicators
511
+ DeviceManager.instance().elliptecView.updateHighlight()
512
+
513
+ DeviceManager.instance().laser_relay.updatePortState()
514
+ if not DeviceManager.instance().laser_relay.isOpen():
515
+ DeviceManager.instance().laser_relay.refreshPorts()
516
+ DeviceManager.instance().laser_relay.updateHighlight(
517
+ self.device_manager.laser_relay_settings()
518
+ )
519
+ else:
520
+ DeviceManager.instance().laser_relay.updateHighlight(
521
+ self.device_manager.laser_relay_settings()
522
+ )
523
+
524
+ for _, cam_list in CameraList.CAMERAS.items():
525
+ for cam in cam_list:
526
+ cam['Panel'].updateInfo()
527
+
528
+ if DeviceManager.instance().stage:
529
+ DeviceManager.instance().stage.updatePortState()
530
+ DeviceManager.instance().stage.refreshPorts()
531
+
532
+ def addDockWidget(
533
+ self, area: Qt.DockWidgetArea, widget: QtWidgets.QDockWidget, key: DOCKS
534
+ ):
535
+ super().addDockWidget(area, widget)
536
+
537
+ if key and key not in self.dock_widgets:
538
+ self.dock_widgets[key] = widget
539
+
540
+ def StartGUI():
541
+ '''Initializes a new QApplication and miEye_module.
542
+
543
+ Use
544
+ -------
545
+ app, window = miEye_module.StartGUI()
546
+
547
+
548
+ app.exec()
549
+
550
+ Returns
551
+ -------
552
+ tuple (QApplication, microEye.miEye_module)
553
+ Returns a tuple with QApp and miEye_module main window.
554
+ '''
555
+ return StartGUI(miEye_module)
556
+
557
+
558
+ def generateConfig(mieye: miEye_module):
559
+ filename = 'config.json'
560
+
561
+ config = mieye.device_manager.get_config()
562
+
563
+ # mieye.dock_widgets = [
564
+
565
+ config['miEye_module'] = {
566
+ 'position': {
567
+ 'x': mieye.mapToGlobal(QtCore.QPoint(0, 0)).x(),
568
+ 'y': mieye.mapToGlobal(QtCore.QPoint(0, 0)).y(),
569
+ },
570
+ 'size': {
571
+ 'width': mieye.geometry().width(),
572
+ 'height': mieye.geometry().height(),
573
+ },
574
+ 'is_maximized': mieye.isMaximized(),
575
+ }
576
+
577
+ for _, (key, widget) in enumerate(mieye.dock_widgets.items()):
578
+ if isinstance(widget, QtWidgets.QDockWidget):
579
+ config[key.get_key()] = {
580
+ 'is_floating': widget.isFloating(),
581
+ 'position': {
582
+ 'x': widget.mapToGlobal(QtCore.QPoint(0, 0)).x(),
583
+ 'y': widget.mapToGlobal(QtCore.QPoint(0, 0)).y(),
584
+ },
585
+ 'size': {
586
+ 'width': widget.geometry().width(),
587
+ 'height': widget.geometry().height(),
588
+ },
589
+ 'is_visible': widget.isVisible(),
590
+ }
591
+
592
+ with open(filename, 'w') as file:
593
+ json.dump(config, file, indent=2)
594
+
595
+ print('Config.json file generated!')
596
+
597
+
598
+ def loadConfig(mieye: miEye_module, auto_connect=True):
599
+ filename = 'config.json'
600
+
601
+ if not os.path.exists(filename):
602
+ print('Config.json not found!')
603
+ return
604
+
605
+ config: dict = None
606
+
607
+ with open(filename) as file:
608
+ config = json.load(file)
609
+
610
+ if 'miEye_module' in config:
611
+ if (
612
+ 'is_maximized' in config['miEye_module']
613
+ and config['miEye_module']['is_maximized']
614
+ ):
615
+ mieye.showMaximized()
616
+ else:
617
+ mieye.setGeometry(
618
+ config['miEye_module'].get('position', {}).get('x', 100),
619
+ config['miEye_module'].get('position', {}).get('y', 100),
620
+ config['miEye_module'].get('size', {}).get('width', 1200),
621
+ config['miEye_module'].get('size', {}).get('height', 920),
622
+ )
623
+
624
+ for dock in DOCKS:
625
+ if dock.get_key() in config:
626
+ dock_config: dict = config[dock.get_key()]
627
+ widget = mieye.dock_widgets[dock]
628
+ widget.setVisible(bool(dock_config.get('is_visible', True)))
629
+ if bool(dock_config.get('is_floating', False)):
630
+ widget.setFloating(True)
631
+ widget.setGeometry(
632
+ dock_config['position']['x'],
633
+ dock_config['position']['y'],
634
+ dock_config['size']['width'],
635
+ dock_config['size']['height'],
636
+ )
637
+ else:
638
+ widget.setFloating(False)
639
+
640
+ mieye.device_manager.load_config(config)
641
+ if auto_connect:
642
+ mieye.device_manager.auto_connect()
643
+
644
+ print('Config.json file loaded!')
645
+
646
+
647
+ if __name__ == '__main__':
648
+ try:
649
+ import vimba as vb
650
+ except Exception:
651
+ vb = None
652
+
653
+ if vb:
654
+ with vb.Vimba.get_instance() as vimba:
655
+ app, window = miEye_module.StartGUI()
656
+ app.exec()
657
+ else:
658
+ app, window = miEye_module.StartGUI()
659
+ app.exec()
File without changes