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,599 @@
1
+ import typing
2
+
3
+ import ome_types.model as om
4
+ from ome_types.model import *
5
+ from ome_types.model.simple_types import PixelType, UnitsLength, UnitsTime
6
+
7
+ from microEye.qt import QApplication, QtWidgets, getOpenFileName, getSaveFileName
8
+ from microEye.utils.gui_helper import *
9
+
10
+
11
+ class MetadataEditor(QtWidgets.QWidget):
12
+ '''
13
+ A PyQt-based GUI for editing OME-XML metadata.
14
+
15
+ Attributes
16
+ ----------
17
+ experiment : QLineEdit
18
+ Experiment name input field.
19
+ exp_desc : QTextEdit
20
+ Experiment description input field.
21
+ exp_email : QLineEdit
22
+ Experimenter's email input field.
23
+ exp_fName : QLineEdit
24
+ Experimenter's first name input field.
25
+ exp_lName : QLineEdit
26
+ Experimenter's last name input field.
27
+ exp_institute : QLineEdit
28
+ Experimenter's institute input field.
29
+ pixel_type : QComboBox
30
+ Pixel type selection dropdown.
31
+ px_size : QDoubleSpinBox
32
+ Pixel x-size input field.
33
+ py_size : QDoubleSpinBox
34
+ Pixel y-size input field.
35
+ p_unit : QComboBox
36
+ Unit selection dropdown for pixel size.
37
+ channel_name : QLineEdit
38
+ Channel name input field.
39
+ fluor_name : QLineEdit
40
+ Fluorophore input field.
41
+ exposure : QDoubleSpinBox
42
+ Exposure time input field.
43
+ exposure_unit : QComboBox
44
+ Exposure time unit selection dropdown.
45
+ acq_mode : QComboBox
46
+ Acquisition mode selection dropdown.
47
+ ill_type : QComboBox
48
+ Illumination type selection dropdown.
49
+ contrast : QComboBox
50
+ Contrast method selection dropdown.
51
+ excitation : QDoubleSpinBox
52
+ Excitation wavelength input field.
53
+ emission : QDoubleSpinBox
54
+ Emission wavelength input field.
55
+ wave_unit : QComboBox
56
+ Wavelength unit selection dropdown.
57
+ micro_manufacturer : QLineEdit
58
+ Microscope manufacturer input field.
59
+ micro_model : QLineEdit
60
+ Microscope model input field.
61
+ obj_manufacturer : QLineEdit
62
+ Objective manufacturer input field.
63
+ obj_model : QLineEdit
64
+ Objective model input field.
65
+ obj_lens_na : QDoubleSpinBox
66
+ Objective numerical aperture input field.
67
+ obj_nom_mag : QDoubleSpinBox
68
+ Objective nominal magnification input field.
69
+ obj_immersion : QComboBox
70
+ Objective immersion selection dropdown.
71
+ obj_corr : QComboBox
72
+ Objective correction selection dropdown.
73
+ det_manufacturer : QLineEdit
74
+ Detector manufacturer input field.
75
+ det_model : QLineEdit
76
+ Detector model input field.
77
+ det_serial : QLineEdit
78
+ Detector serial number input field.
79
+ det_type : QComboBox
80
+ Detector type selection dropdown.
81
+ dichroic_manufacturer : QLineEdit
82
+ Dichroic manufacturer input field.
83
+ dichroic_model : QLineEdit
84
+ Dichroic model input field.
85
+ exfilter_model : QLineEdit
86
+ Excitation filter model input field.
87
+ emfilter_model : QLineEdit
88
+ Emission filter model input field.
89
+ tab_view : QTabWidget
90
+ Tab view for organizing metadata sections.
91
+ main_layout : QVBoxLayout
92
+ Main layout of the widget.
93
+ '''
94
+
95
+
96
+ def __init__(self, parent: typing.Optional['QtWidgets.QWidget'] = None):
97
+ '''
98
+ Initializes the MetadataEditor widget.
99
+
100
+ Parameters
101
+ ----------
102
+ parent : Optional[QWidget], optional
103
+ The parent widget, by default None.
104
+ '''
105
+ super().__init__(parent=parent)
106
+ self.setMinimumWidth(50)
107
+ self.InitLayout()
108
+
109
+ def InitLayout(self):
110
+ '''
111
+ Initializes the main layout of the widget.
112
+ '''
113
+ self.main_layout = QtWidgets.QVBoxLayout(self)
114
+ self.tab_view = QtWidgets.QTabWidget()
115
+ self.main_layout.addWidget(self.tab_view)
116
+
117
+ self.create_tab('Experiment', self.exp_tab_setup)
118
+ self.create_tab('Image', self.image_tab_setup)
119
+ self.create_tab('Instruments', self.instruments_tab_setup)
120
+
121
+ self.main_layout.addWidget(
122
+ QtWidgets.QPushButton('Save as', clicked=self.save))
123
+ self.main_layout.addWidget(
124
+ QtWidgets.QPushButton('Import', clicked=self.load_xml))
125
+ self.setLayout(self.main_layout)
126
+
127
+ def create_tab(self, title, setup_func):
128
+ '''
129
+ Creates a tab in the tab view.
130
+
131
+ Parameters
132
+ ----------
133
+ title : str
134
+ Title of the tab.
135
+ setup_func : callable
136
+ Function for setting up the tab layout.
137
+ '''
138
+ tab = QtWidgets.QWidget()
139
+ layout = QtWidgets.QFormLayout()
140
+ tab.setLayout(layout)
141
+ self.tab_view.addTab(tab, title)
142
+ setup_func(layout)
143
+
144
+ def exp_tab_setup(self, layout):
145
+ '''
146
+ Sets up the Experiment tab.
147
+
148
+ Parameters
149
+ ----------
150
+ layout : QFormLayout
151
+ Layout for the Experiment tab.
152
+ '''
153
+ self.experiment = create_line_edit('Experiment name:', '001_Experiment', layout)
154
+ self.exp_desc = create_text_edit('Experiment description:', '', layout)
155
+ self.exp_email = create_line_edit('Experimenter e-mail:', '', layout)
156
+ self.exp_fName = create_line_edit('Experimenter First name:', '', layout)
157
+ self.exp_lName = create_line_edit('Experimenter Last name:', '', layout)
158
+ self.exp_institute = create_line_edit('Experimenter Institute:', '', layout)
159
+
160
+ def image_tab_setup(self, layout):
161
+ '''
162
+ Sets up the Image tab.
163
+
164
+ Parameters
165
+ ----------
166
+ layout : QFormLayout
167
+ Layout for the Image tab.
168
+ '''
169
+ self.pixel_type = create_combo_box(
170
+ 'Pixel type:', PixelType._member_names_,
171
+ PixelType.UINT16.name, layout)
172
+ self.px_size = create_labelled_double_spin_box(
173
+ 'Pixel x-size:', 0, 10000, 117.5, layout)
174
+ self.py_size = create_labelled_double_spin_box(
175
+ 'Pixel y-size:', 0, 10000, 117.5, layout)
176
+ self.p_unit = create_combo_box(
177
+ 'Unit:', UnitsLength._member_names_,
178
+ UnitsLength.NANOMETER.name, layout)
179
+
180
+ self.channel_name = create_line_edit('Channel name:', 'CAM_1', layout)
181
+ self.fluor_name = create_line_edit('Fluorophore:', '', layout)
182
+ self.exposure = create_labelled_double_spin_box(
183
+ 'Exposure time:', 0, 10000, 100.0, layout)
184
+ self.exposure_unit = create_combo_box(
185
+ 'Exposure time unit:', UnitsTime._member_names_,
186
+ UnitsTime.MILLISECOND.name, layout)
187
+ self.acq_mode = create_combo_box(
188
+ 'Acquisition mode:', Channel_AcquisitionMode._member_names_,
189
+ Channel_AcquisitionMode.TIRF.name, layout)
190
+ self.ill_type = create_combo_box(
191
+ 'Illumination type:', Channel_IlluminationType._member_names_,
192
+ Channel_IlluminationType.OTHER.name, layout)
193
+ self.contrast = create_combo_box(
194
+ 'Contrast method:', Channel_ContrastMethod._member_names_,
195
+ Channel_ContrastMethod.FLUORESCENCE.name, layout)
196
+ self.excitation = create_labelled_double_spin_box(
197
+ 'Excitation wavelength:', 0, 10000, 638, layout)
198
+ self.emission = create_labelled_double_spin_box(
199
+ 'Emission wavelength:', 0, 10000, 670, layout)
200
+ self.wave_unit = create_combo_box(
201
+ 'Wavelength unit:', UnitsLength._member_names_,
202
+ UnitsLength.NANOMETER.name, layout)
203
+
204
+ def instruments_tab_setup(self, layout):
205
+ '''
206
+ Sets up the Instruments tab.
207
+
208
+ Parameters
209
+ ----------
210
+ layout : QFormLayout
211
+ Layout for the Instruments tab.
212
+ '''
213
+ self.micro_manufacturer = create_line_edit(
214
+ 'Microscope manufacturer:', 'VU/FTMC', layout)
215
+ self.micro_model = create_line_edit(
216
+ 'Microscope model:', 'Main scope', layout)
217
+ self.obj_manufacturer = create_line_edit(
218
+ 'Objective manufacturer:', 'Nikon', layout)
219
+ self.obj_model = create_line_edit(
220
+ 'Objective model:', 'CFI Apochromat TIRF 60XC Oil', layout)
221
+ self.obj_lens_na = create_labelled_double_spin_box(
222
+ 'Objective NA:', 0, 2, 1.49, layout)
223
+ self.obj_nom_mag = create_labelled_double_spin_box(
224
+ 'Objective nominal Mag.:', 0, 1000, 60, layout)
225
+ self.obj_immersion = create_combo_box(
226
+ 'Objective immersion:', Objective_Immersion._member_names_,
227
+ Objective_Immersion.OIL.name, layout)
228
+ self.obj_corr = create_combo_box(
229
+ 'Objective correction:', Objective_Correction._member_names_,
230
+ Objective_Correction.APO.name, layout)
231
+ self.det_manufacturer = create_line_edit(
232
+ 'Detector manufacturer:', 'Allied Vision', layout)
233
+ self.det_model = create_line_edit(
234
+ 'Detector model:', 'U-511m', layout)
235
+ self.det_serial = create_line_edit(
236
+ 'Detector serial number:', '', layout)
237
+ self.det_type = create_combo_box(
238
+ 'Detector type:', Detector_Type._member_names_,
239
+ Detector_Type.CMOS.name, layout)
240
+ self.dichroic_manufacturer = create_line_edit(
241
+ 'Dichroic manufacturer:', '', layout)
242
+ self.dichroic_model = create_line_edit(
243
+ 'Dichroic model:', '', layout)
244
+ self.exfilter_model = create_line_edit(
245
+ 'Excitation Filters:', '', layout)
246
+ self.emfilter_model = create_line_edit(
247
+ 'Emission Filters:', '', layout)
248
+
249
+ def save(self):
250
+ '''
251
+ Saves metadata to an OME-XML file.
252
+ '''
253
+ try:
254
+ filename, _ = getSaveFileName(
255
+ self, 'Save metadata', filter='OME-XML Files (*.ome.xml);;')
256
+ if filename:
257
+ ome_obj = self.gen_OME_XML(1, 512, 512)
258
+ with open(filename, 'w', encoding='utf8') as f:
259
+ f.write(ome_obj.to_xml())
260
+ except Exception as e:
261
+ print(f'Error saving file: {e}')
262
+
263
+ def load_xml(self):
264
+ '''
265
+ Loads metadata from an OME-XML file.
266
+ '''
267
+ try:
268
+ filename, _ = getOpenFileName(
269
+ self, 'Load metadata', filter='OME-XML Files (*.ome.xml);;')
270
+ if filename:
271
+ xml = ''
272
+ with open(filename) as f:
273
+ xml = f.read()
274
+ self.pop_OME_XML(OME.from_xml(xml))
275
+ except Exception as e:
276
+ print(f'Error loading file: {e}')
277
+
278
+
279
+ def gen_OME_XML(
280
+ self, frames: int, width: int, height: int,
281
+ channels: int = 1, z_planes: int = 1,
282
+ dimension_order: Pixels_DimensionOrder =Pixels_DimensionOrder.XYZCT):
283
+ '''
284
+ Generates OME-XML metadata.
285
+
286
+ Parameters
287
+ ----------
288
+ frames : int
289
+ Number of frames.
290
+ width : int
291
+ Image width.
292
+ height : int
293
+ Image height.
294
+ channels : int, optional
295
+ Number of channels, by default 1.
296
+ z_planes : int, optional
297
+ Number of z-planes, by default 1.
298
+ dimension_order : Pixels_DimensionOrder, optional
299
+ Dimension order, by default Pixels_DimensionOrder.XYZCT.
300
+
301
+ Returns
302
+ -------
303
+ om.OME
304
+ Generated OME-XML object.
305
+ '''
306
+ ome_obj = om.OME(creator='microEye Python Package')
307
+
308
+ experimenter = om.Experimenter()
309
+ experimenter.first_name = self.exp_fName.text()
310
+ experimenter.last_name = self.exp_lName.text()
311
+ experimenter.email = self.exp_email.text()
312
+ experimenter.institution = self.exp_institute.text()
313
+ ome_obj.experimenters.append(experimenter)
314
+
315
+ micro = Microscope()
316
+ micro.manufacturer = self.micro_manufacturer.text()
317
+ micro.model = self.micro_model.text()
318
+
319
+ objective = Objective()
320
+ objective.manufacturer = self.obj_manufacturer.text()
321
+ objective.model = self.obj_model.text()
322
+ objective.lens_na = self.obj_lens_na.value()
323
+ objective.nominal_magnification = self.obj_nom_mag.value()
324
+ objective.immersion = Objective_Immersion._member_map_[
325
+ self.obj_immersion.currentText()]
326
+ objective.correction = Objective_Correction._member_map_[
327
+ self.obj_corr.currentText()]
328
+
329
+ detector = Detector()
330
+ detector.manufacturer = self.det_manufacturer.text()
331
+ detector.model = self.det_model.text()
332
+ detector.serial_number = self.det_serial.text()
333
+ detector.type = Detector_Type._member_map_[
334
+ self.det_type.currentText()]
335
+
336
+ dichroic = Dichroic()
337
+ dichroic.manufacturer = self.dichroic_manufacturer.text()
338
+ dichroic.model = self.dichroic_model.text()
339
+
340
+ exFilters = Filter()
341
+ exFilters.model = self.exfilter_model.text()
342
+ emFilters = Filter()
343
+ emFilters.model = self.emfilter_model.text()
344
+
345
+ instrument = Instrument()
346
+ instrument.microscope = micro
347
+ instrument.objectives.append(objective)
348
+ instrument.detectors.append(detector)
349
+ instrument.dichroics.append(dichroic)
350
+ instrument.filters.append(exFilters)
351
+ instrument.filters.append(emFilters)
352
+
353
+ ome_obj.instruments.append(instrument)
354
+
355
+ planes = [om.Plane(
356
+ the_c=0,
357
+ the_t=i,
358
+ the_z=0,
359
+ exposure_time=self.exposure.value(),
360
+ exposure_time_unit=UnitsTime.MILLISECOND
361
+ ) for i in range(frames)]
362
+
363
+ channel = om.Channel()
364
+ channel.name = self.channel_name.text()
365
+ channel.fluor = self.fluor_name.text()
366
+ channel.acquisition_mode = Channel_AcquisitionMode._member_map_[
367
+ self.acq_mode.currentText()]
368
+ channel.illumination_type = Channel_IlluminationType._member_map_[
369
+ self.ill_type.currentText()]
370
+ channel.contrast_method = Channel_ContrastMethod._member_map_[
371
+ self.contrast.currentText()]
372
+ channel.excitation_wavelength = self.excitation.value()
373
+ channel.emission_wavelength = self.emission.value()
374
+ channel.excitation_wavelength_unit = UnitsLength._member_map_[
375
+ self.wave_unit.currentText()]
376
+ channel.emission_wavelength_unit = UnitsLength._member_map_[
377
+ self.wave_unit.currentText()]
378
+ channel.samples_per_pixel = 1
379
+
380
+ pixels = om.Pixels(
381
+ size_c=channels, size_t=frames,
382
+ size_x=width,
383
+ size_y=height,
384
+ size_z=z_planes,
385
+ type=PixelType._member_map_[
386
+ self.pixel_type.currentText()],
387
+ dimension_order=dimension_order,
388
+ # metadata_only=True,
389
+ physical_size_x=self.px_size.value(),
390
+ physical_size_x_unit=UnitsLength._member_map_[
391
+ self.p_unit.currentText()],
392
+ physical_size_y=self.py_size.value(),
393
+ physical_size_y_unit=UnitsLength._member_map_[
394
+ self.p_unit.currentText()],
395
+ time_increment=self.exposure.value(),
396
+ time_increment_unit=UnitsTime._member_map_[
397
+ self.exposure_unit.currentText()],
398
+ )
399
+ pixels.tiff_data_blocks.append(om.TiffData())
400
+ pixels.channels.append(channel)
401
+ pixels.planes.extend(planes)
402
+ img = om.Image(
403
+ id='Image:1',
404
+ name=self.experiment.text(),
405
+ pixels=pixels,
406
+ description=self.exp_desc.toPlainText()
407
+ )
408
+ ome_obj.images.append(img)
409
+ ome_obj = OME.model_validate(ome_obj)
410
+
411
+ # with open('config.xml', 'w', encoding='utf8') as f:
412
+ # f.write(ome_obj.to_xml())
413
+
414
+ return ome_obj
415
+
416
+ def gen_OME_XML_short(
417
+ self, frames: int, width: int, height: int,
418
+ channels: int = 1, z_planes: int = 1,
419
+ dimension_order: Pixels_DimensionOrder =Pixels_DimensionOrder.XYZCT):
420
+ '''
421
+ Generates short version of OME-XML metadata.
422
+
423
+ Parameters
424
+ ----------
425
+ frames : int
426
+ Number of frames.
427
+ width : int
428
+ Image width.
429
+ height : int
430
+ Image height.
431
+ channels : int, optional
432
+ Number of channels, by default 1.
433
+ z_planes : int, optional
434
+ Number of z-planes, by default 1.
435
+ dimension_order : Pixels_DimensionOrder, optional
436
+ Dimension order, by default Pixels_DimensionOrder.XYZCT.
437
+
438
+ Returns
439
+ -------
440
+ om.OME
441
+ Generated OME-XML object.
442
+ '''
443
+ ome_obj = om.OME(creator='microEye Python Package')
444
+
445
+ experimenter = om.Experimenter()
446
+ experimenter.first_name = self.exp_fName.text()
447
+ experimenter.last_name = self.exp_lName.text()
448
+ experimenter.email = self.exp_email.text()
449
+ experimenter.institution = self.exp_institute.text()
450
+ ome_obj.experimenters.append(experimenter)
451
+
452
+ detector = Detector()
453
+ detector.manufacturer = self.det_manufacturer.text()
454
+ detector.model = self.det_model.text()
455
+ detector.serial_number = self.det_serial.text()
456
+ detector.type = Detector_Type._member_map_[
457
+ self.det_type.currentText()]
458
+
459
+ instrument = Instrument()
460
+ instrument.detectors.append(detector)
461
+
462
+ ome_obj.instruments.append(instrument)
463
+
464
+ planes = [om.Plane(
465
+ the_c=0,
466
+ the_t=i,
467
+ the_z=0,
468
+ exposure_time=self.exposure.value(),
469
+ exposure_time_unit=UnitsTime.MILLISECOND
470
+ ) for i in range(frames)]
471
+
472
+ channel = om.Channel()
473
+
474
+ pixels = om.Pixels(
475
+ size_c=channels, size_t=frames,
476
+ size_x=width,
477
+ size_y=height, size_z=z_planes,
478
+ type=PixelType._member_map_[
479
+ self.pixel_type.currentText()],
480
+ dimension_order=dimension_order,
481
+ # metadata_only=True,
482
+ physical_size_x=self.px_size.value(),
483
+ physical_size_x_unit=UnitsLength._member_map_[
484
+ self.p_unit.currentText()],
485
+ physical_size_y=self.py_size.value(),
486
+ physical_size_y_unit=UnitsLength._member_map_[
487
+ self.p_unit.currentText()],
488
+ time_increment=self.exposure.value(),
489
+ time_increment_unit=UnitsTime._member_map_[
490
+ self.exposure_unit.currentText()],
491
+ )
492
+ pixels.tiff_data_blocks.append(om.TiffData())
493
+ pixels.channels.append(channel)
494
+ pixels.planes.extend(planes)
495
+ img = om.Image(
496
+ id='Image:1',
497
+ name=self.experiment.text(),
498
+ pixels=pixels,
499
+ description=self.exp_desc.toPlainText()
500
+ )
501
+ ome_obj.images.append(img)
502
+ ome_obj = OME.model_validate(ome_obj)
503
+
504
+ return ome_obj
505
+
506
+ def pop_OME_XML(self, ome_obj: OME):
507
+ '''
508
+ Populate the widget with OME-XML metadata.
509
+
510
+ Parameters
511
+ ----------
512
+ ome_obj : om.OME
513
+ The OME-XML object to be loaded.
514
+ '''
515
+ if ome_obj.images.__len__() > 0:
516
+ img = ome_obj.images[0]
517
+ self.experiment.setText(img.name)
518
+ self.exp_desc.setText(img.description)
519
+ if img.pixels is not None:
520
+ pixels = img.pixels
521
+ if pixels.physical_size_x is not None:
522
+ self.px_size.setValue(
523
+ float(pixels.physical_size_x))
524
+ self.p_unit.setCurrentText(
525
+ pixels.physical_size_x_unit.name)
526
+ if pixels.physical_size_y is not None:
527
+ self.py_size.setValue(
528
+ float(pixels.physical_size_y))
529
+ if pixels.time_increment is not None:
530
+ self.exposure.setValue(pixels.time_increment)
531
+ self.exposure_unit.setCurrentText(
532
+ pixels.time_increment_unit.name)
533
+ self.pixel_type.setCurrentText(pixels.type.name)
534
+ if pixels.channels.__len__() > 0:
535
+ channel = pixels.channels[0]
536
+ self.channel_name.setText(channel.name)
537
+ self.fluor_name.setText(channel.fluor)
538
+ if channel.acquisition_mode:
539
+ self.acq_mode.setCurrentText(
540
+ channel.acquisition_mode.name)
541
+ if channel.illumination_type:
542
+ self.ill_type.setCurrentText(
543
+ channel.illumination_type.name)
544
+ if channel.contrast_method:
545
+ self.contrast.setCurrentText(
546
+ channel.contrast_method.name)
547
+ if channel.excitation_wavelength:
548
+ self.excitation.setValue(
549
+ float(channel.excitation_wavelength))
550
+ self.wave_unit.setCurrentText(
551
+ channel.excitation_wavelength_unit.name)
552
+ if channel.emission_wavelength:
553
+ self.emission.setValue(
554
+ float(channel.emission_wavelength))
555
+ self.wave_unit.setCurrentText(
556
+ channel.emission_wavelength_unit.name)
557
+ if ome_obj.experimenters.__len__() > 0:
558
+ exper = ome_obj.experimenters[0]
559
+ self.exp_fName.setText(exper.first_name)
560
+ self.exp_lName.setText(exper.last_name)
561
+ self.exp_email.setText(exper.email)
562
+ self.exp_institute.setText(exper.institution)
563
+ if ome_obj.instruments.__len__() > 0:
564
+ inst = ome_obj.instruments[0]
565
+ if inst.microscope is not None:
566
+ micro = inst.microscope
567
+ self.micro_manufacturer.setText(micro.manufacturer)
568
+ self.micro_model.setText(micro.model)
569
+ if inst.objectives.__len__() > 0:
570
+ objective = inst.objectives[0]
571
+ self.obj_manufacturer.setText(objective.manufacturer)
572
+ self.obj_model.setText(objective.model)
573
+ self.obj_lens_na.setValue(objective.lens_na)
574
+ self.obj_nom_mag.setValue(
575
+ objective.nominal_magnification)
576
+ self.obj_immersion.setCurrentText(objective.immersion.name)
577
+ self.obj_corr.setCurrentText(objective.correction.name)
578
+ if inst.detectors.__len__() > 0:
579
+ detector = inst.detectors[0]
580
+ self.det_manufacturer.setText(detector.manufacturer)
581
+ self.det_model.setText(detector.model)
582
+ self.det_serial.setText(detector.serial_number)
583
+ self.det_type.setCurrentText(detector.type.name)
584
+ if inst.dichroics.__len__() > 0:
585
+ dichroic = inst.dichroics[0]
586
+ self.dichroic_manufacturer.setText(dichroic.manufacturer)
587
+ self.dichroic_model.setText(dichroic.model)
588
+ if inst.filters.__len__() > 1:
589
+ exFilters = inst.filters[0]
590
+ self.exfilter_model.setText(exFilters.model)
591
+ emFilters = inst.filters[1]
592
+ self.emfilter_model.setText(emFilters.model)
593
+
594
+
595
+ if __name__ == '__main__':
596
+ app = QApplication(sys.argv)
597
+ window = MetadataEditor()
598
+ window.show()
599
+ sys.exit(app.exec())