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,718 @@
1
+ import json
2
+ from enum import Enum
3
+ from typing import Any, Optional, Union
4
+
5
+ import ome_types.model as om
6
+ from ome_types.model import *
7
+ from ome_types.model.simple_types import PixelType, UnitsLength, UnitsTime
8
+ from pyqtgraph.parametertree import Parameter, ParameterTree
9
+ from pyqtgraph.parametertree.parameterTypes import ActionParameter, GroupParameter
10
+
11
+ from microEye.qt import QtWidgets, getOpenFileName, getSaveFileName
12
+ from microEye.utils.parameter_tree import Tree
13
+
14
+
15
+ class MetaParams(Enum):
16
+ '''
17
+ Enum class defining metadata parameters.
18
+ '''
19
+ EXPERIMENT_NAME = 'Experiment.Name'
20
+ EXP_DESC = 'Experiment.Description'
21
+ EXP_EMAIL = 'Experiment.Email'
22
+ EXP_FNAME = 'Experiment.First Name'
23
+ EXP_LNAME = 'Experiment.Last Name'
24
+ EXP_INSTITUTE = 'Experiment.Institute'
25
+ PIXEL_TYPE = 'Image.Pixel Type'
26
+ PX_SIZE = 'Image.Pixel X-Size'
27
+ PY_SIZE = 'Image.Pixel Y-Size'
28
+ P_UNIT = 'Image.Pixel Unit'
29
+ CHANNEL_NAME = 'Image.Channel Name'
30
+ FLUOR_NAME = 'Image.Fluorophore'
31
+ EXPOSURE = 'Image.Exposure Time'
32
+ EXPOSURE_UNIT = 'Image.Exposure Time Unit'
33
+ ACQ_MODE = 'Image.Acquisition Mode'
34
+ ILL_TYPE = 'Image.Illumination Type'
35
+ CONTRAST = 'Image.Contrast Method'
36
+ EXCITATION = 'Image.Excitation Wavelength'
37
+ EMISSION = 'Image.Emission Wavelength'
38
+ WAVE_UNIT = 'Image.Wavelength Unit'
39
+ MICRO_MANUFACTURER = 'Instruments.Microscope Manufacturer'
40
+ MICRO_MODEL = 'Instruments.Microscope Model'
41
+ OBJ_MANUFACTURER = 'Instruments.Objective Manufacturer'
42
+ OBJ_MODEL = 'Instruments.Objective Model'
43
+ OBJ_LENS_NA = 'Instruments.Objective NA'
44
+ OBJ_NOM_MAG = 'Instruments.Objective Nominal Magnification'
45
+ OBJ_IMMERSION = 'Instruments.Objective Immersion'
46
+ OBJ_CORR = 'Instruments.Objective Correction'
47
+ DET_MANUFACTURER = 'Instruments.Detector Manufacturer'
48
+ DET_MODEL = 'Instruments.Detector Model'
49
+ DET_SERIAL = 'Instruments.Detector Serial Number'
50
+ DET_TYPE = 'Instruments.Detector Type'
51
+ DICHROIC_MANUFACTURER = 'Instruments.Dichroic Manufacturer'
52
+ DICHROIC_MODEL = 'Instruments.Dichroic'
53
+ EXFILTER_MODEL = 'Instruments.Excitation Filter'
54
+ EMFILTER_MODEL = 'Instruments.Emission Filter'
55
+ DICHROIC_MODEL_LIST = 'Instruments.Dichroics'
56
+ EXFILTER_MODEL_LIST = 'Instruments.Excitation Filters'
57
+ EMFILTER_MODEL_LIST = 'Instruments.Emission Filters'
58
+ DICHROIC_MODEL_BTN = 'Instruments.Add Dichroic'
59
+ EXFILTER_MODEL_BTN = 'Instruments.Add Excitation Filters'
60
+ EMFILTER_MODEL_BTN = 'Instruments.Add Emission Filters'
61
+ EXPORT_STATE = 'Actions.Export State'
62
+ IMPORT_STATE = 'Actions.Import State'
63
+ EXPORT_XML = 'Actions.Export XML'
64
+ IMPORT_XML = 'Actions.Import XML'
65
+
66
+ def __str__(self):
67
+ '''
68
+ Return the last part of the enum value (Param name).
69
+ '''
70
+ return self.value.split('.')[-1]
71
+
72
+ def get_path(self):
73
+ '''
74
+ Return the full parameter path.
75
+ '''
76
+ return self.value.split('.')
77
+
78
+ class MetadataEditorTree(Tree):
79
+ '''
80
+ Tree widget for editing metadata parameters.
81
+
82
+ Attributes
83
+ ----------
84
+ paramsChanged : Signal
85
+ Signal for parameter changed event.
86
+
87
+ DICHROIC_SUGGESTIONS : list
88
+ List of dichroic suggestions, adjust to fit your setup.
89
+ EMISSION_FILTERS : list
90
+ List of emission filter suggestions, adjust to fit your setup.
91
+ EXCITATION_FILTERS : list
92
+ List of excitation filter suggestions, adjust to fit your setup.
93
+ '''
94
+ PARAMS = MetaParams
95
+
96
+ DICHROIC_SUGGESTIONS = [
97
+ 'EM 550 Longpass',
98
+ 'EM 640 Longpass',
99
+ 'EX 405/488/532/640 2mm MultiBand',
100
+ 'EX 405/488/561/635 3mm MultiBand',
101
+ 'EX 488/640 2mm MultiBand',
102
+ 'EX 405/514/647 2mm MultiBand',
103
+ 'EX 405/514/635 1mm MultiBand',
104
+ 'Other/None',
105
+ ]
106
+ '''List of dichroic suggestions, adjust to fit your setup.
107
+
108
+ Suggestions for dichroic filters that can be used.
109
+ '''
110
+
111
+ EMISSION_FILTERS = [
112
+ '740/40 Bandpass (11)',
113
+ '697/75 Bandpass (1)',
114
+ '692/40 Bandpass (2)',
115
+ '630/69 Bandpass (9)',
116
+ '600/40 Bandpass (10)',
117
+ '591.5/43 Bandpass (3)',
118
+ '575/35 Bandpass (4)',
119
+ '550 Longpass (5)',
120
+ '540/50 Bandpass (6)',
121
+ '525/45 Bandpass (7)',
122
+ '405/488/532/642 MultiBand (8)',
123
+ 'Other/None',
124
+ ]
125
+ '''List of emission filter suggestions, adjust to fit your setup.
126
+
127
+ Suggestions for emission filters that can be used.
128
+ '''
129
+
130
+ EXCITATION_FILTERS = [
131
+ '405/488/532/638 MultiBand',
132
+ '405/488/561/638 MultiBand',
133
+ '515/10 BandPass',
134
+ '561/03 BandPass',
135
+ '640/10 BandPass',
136
+ 'Other/None',
137
+ ]
138
+ '''List of excitation filter suggestions, adjust to fit your setup.
139
+
140
+ Suggestions for excitation filters that can be used.
141
+ '''
142
+
143
+ def __init__(self, parent: Optional['QtWidgets.QWidget'] = None):
144
+ '''
145
+ Initialize the MetadataEditorTree.
146
+
147
+ Parameters
148
+ ----------
149
+ parent : QWidget, optional
150
+ The parent widget, by default None.
151
+ '''
152
+ super().__init__(parent=parent)
153
+
154
+ def create_parameters(self):
155
+ '''
156
+ Create the parameter tree structure.
157
+ '''
158
+ params = [
159
+ {'name': 'Experiment', 'type': 'group', 'children': [
160
+ {'name': str(MetaParams.EXPERIMENT_NAME),
161
+ 'type': 'str', 'value': '001_Experiment'},
162
+ {'name': str(MetaParams.EXP_DESC), 'type': 'text', 'value': ''},
163
+ {'name': str(MetaParams.EXP_EMAIL), 'type': 'str', 'value': ''},
164
+ {'name': str(MetaParams.EXP_FNAME), 'type': 'str', 'value': ''},
165
+ {'name': str(MetaParams.EXP_LNAME), 'type': 'str', 'value': ''},
166
+ {'name': str(MetaParams.EXP_INSTITUTE), 'type': 'str', 'value': ''},
167
+ ]},
168
+ {'name': 'Image', 'type': 'group', 'children': [
169
+ {'name': str(MetaParams.PIXEL_TYPE), 'type': 'list',
170
+ 'limits': PixelType._member_names_, 'value': PixelType.UINT16.name},
171
+ {'name': str(MetaParams.PX_SIZE), 'type': 'float',
172
+ 'value': 114.17, 'limits': [0.0, 10000.0], 'decimals': 5},
173
+ {'name': str(MetaParams.PY_SIZE), 'type': 'float',
174
+ 'value': 114.17, 'limits': [0.0, 10000.0], 'decimals': 5},
175
+ {'name': str(MetaParams.P_UNIT), 'type': 'list',
176
+ 'limits': UnitsLength._member_names_,
177
+ 'value': UnitsLength.NANOMETER.name},
178
+ {'name': str(MetaParams.CHANNEL_NAME), 'type': 'str', 'value': 'CAM_1'},
179
+ {'name': str(MetaParams.FLUOR_NAME), 'type': 'str', 'value': ''},
180
+ {'name': str(MetaParams.EXPOSURE), 'type': 'float',
181
+ 'value': 100.0, 'limits': [0.0, 10000.0], 'decimals': 5},
182
+ {'name': str(MetaParams.EXPOSURE_UNIT), 'type': 'list',
183
+ 'limits': UnitsTime._member_names_,
184
+ 'value': UnitsTime.MILLISECOND.name},
185
+ {'name': str(MetaParams.ACQ_MODE), 'type': 'list',
186
+ 'limits': Channel_AcquisitionMode._member_names_,
187
+ 'value': Channel_AcquisitionMode.SINGLE_MOLECULE_IMAGING.name},
188
+ {'name': str(MetaParams.ILL_TYPE), 'type': 'list',
189
+ 'limits': Channel_IlluminationType._member_names_,
190
+ 'value': Channel_IlluminationType.OTHER.name},
191
+ {'name': str(MetaParams.CONTRAST), 'type': 'list',
192
+ 'limits': Channel_ContrastMethod._member_names_,
193
+ 'value': Channel_ContrastMethod.FLUORESCENCE.name},
194
+ {'name': str(MetaParams.EXCITATION), 'type': 'float',
195
+ 'value': 638, 'limits': [0.0, 10000.0], 'decimals': 5},
196
+ {'name': str(MetaParams.EMISSION), 'type': 'float',
197
+ 'value': 670, 'limits': [0.0, 10000.0], 'decimals': 5},
198
+ {'name': str(MetaParams.WAVE_UNIT), 'type': 'list',
199
+ 'limits': UnitsLength._member_names_,
200
+ 'value': UnitsLength.NANOMETER.name},
201
+ ]},
202
+ {'name': 'Instruments', 'type': 'group', 'children': [
203
+ {'name': str(MetaParams.MICRO_MANUFACTURER),
204
+ 'type': 'str', 'value': 'VU/FTMC'},
205
+ {'name': str(MetaParams.MICRO_MODEL),
206
+ 'type': 'str', 'value': 'Main scope'},
207
+ {'name': str(MetaParams.OBJ_MANUFACTURER),
208
+ 'type': 'str', 'value': 'Nikon'},
209
+ {'name': str(MetaParams.OBJ_MODEL), 'type': 'str',
210
+ 'value': 'CFI Apochromat TIRF 60XC Oil'},
211
+ {'name': str(MetaParams.OBJ_LENS_NA), 'type': 'float',
212
+ 'value': 1.49, 'limits': [0.0, 2.0], 'step': 0.1, 'decimals': 5},
213
+ {'name': str(MetaParams.OBJ_NOM_MAG), 'type': 'float',
214
+ 'value': 60.0, 'limits': [0.0, 1000.0], 'decimals': 5},
215
+ {'name': str(MetaParams.OBJ_IMMERSION), 'type': 'list',
216
+ 'limits': Objective_Immersion._member_names_,
217
+ 'value': Objective_Immersion.OIL.name},
218
+ {'name': str(MetaParams.OBJ_CORR), 'type': 'list',
219
+ 'limits': Objective_Correction._member_names_,
220
+ 'value': Objective_Correction.PLAN_APO.name},
221
+ {'name': str(MetaParams.DET_MANUFACTURER), 'type': 'str',
222
+ 'value': 'Allied Vision'},
223
+ {'name': str(MetaParams.DET_MODEL), 'type': 'str', 'value': 'U-511m'},
224
+ {'name': str(MetaParams.DET_SERIAL), 'type': 'str', 'value': ''},
225
+ {'name': str(MetaParams.DET_TYPE), 'type': 'list',
226
+ 'limits': Detector_Type._member_names_,
227
+ 'value': Detector_Type.CMOS.name},
228
+ {'name': str(MetaParams.DICHROIC_MANUFACTURER),
229
+ 'type': 'str', 'value': ''},
230
+ {'name': str(MetaParams.DICHROIC_MODEL), 'type': 'list', 'value': '',
231
+ 'limits': self.DICHROIC_SUGGESTIONS},
232
+ {'name': str(MetaParams.DICHROIC_MODEL_BTN), 'type': 'action'},
233
+ {'name': str(MetaParams.DICHROIC_MODEL_LIST), 'type': 'group',
234
+ 'children': []},
235
+ {'name': str(MetaParams.EXFILTER_MODEL), 'type': 'list', 'value': '',
236
+ 'limits': self.EXCITATION_FILTERS},
237
+ {'name': str(MetaParams.EXFILTER_MODEL_BTN), 'type': 'action'},
238
+ {'name': str(MetaParams.EXFILTER_MODEL_LIST), 'type': 'group',
239
+ 'children': []},
240
+ {'name': str(MetaParams.EMFILTER_MODEL), 'type': 'list', 'value': '',
241
+ 'limits': self.EMISSION_FILTERS},
242
+ {'name': str(MetaParams.EMFILTER_MODEL_BTN), 'type': 'action'},
243
+ {'name': str(MetaParams.EMFILTER_MODEL_LIST), 'type': 'group',
244
+ 'children': []},
245
+ ]},
246
+ {'name': 'Actions', 'type': 'group', 'children': [
247
+ {'name': str(MetaParams.EXPORT_STATE), 'type': 'action'},
248
+ {'name': str(MetaParams.IMPORT_STATE), 'type': 'action'},
249
+ {'name': str(MetaParams.EXPORT_XML), 'type': 'action'},
250
+ {'name': str(MetaParams.IMPORT_XML), 'type': 'action'},
251
+ ]},
252
+ ]
253
+
254
+ self.param_tree = Parameter.create(name='', type='group', children=params)
255
+ self.param_tree.sigTreeStateChanged.connect(self.change)
256
+ self.header().setSectionResizeMode(
257
+ QtWidgets.QHeaderView.ResizeMode.ResizeToContents)
258
+
259
+ self.get_param(
260
+ MetaParams.DICHROIC_MODEL_BTN).sigActivated.connect(
261
+ lambda: self.add_param_child(
262
+ MetaParams.DICHROIC_MODEL_LIST,
263
+ MetaParams.DICHROIC_MODEL))
264
+ self.get_param(
265
+ MetaParams.EXFILTER_MODEL_BTN).sigActivated.connect(
266
+ lambda: self.add_param_child(
267
+ MetaParams.EXFILTER_MODEL_LIST,
268
+ MetaParams.EXFILTER_MODEL))
269
+ self.get_param(
270
+ MetaParams.EMFILTER_MODEL_BTN).sigActivated.connect(
271
+ lambda: self.add_param_child(
272
+ MetaParams.EMFILTER_MODEL_LIST,
273
+ MetaParams.EMFILTER_MODEL))
274
+
275
+ self.get_param(
276
+ MetaParams.IMPORT_STATE).sigActivated.connect(self.load_json)
277
+ self.get_param(
278
+ MetaParams.EXPORT_STATE).sigActivated.connect(self.export_json)
279
+ self.get_param(
280
+ MetaParams.IMPORT_XML).sigActivated.connect(self.load_xml)
281
+ self.get_param(
282
+ MetaParams.EXPORT_XML).sigActivated.connect(self.save)
283
+
284
+ def add_param_child(self, parent: MetaParams, value: Union[MetaParams, Any]):
285
+ '''
286
+ Add a child parameter to the specified parent parameter.
287
+
288
+ Parameters
289
+ ----------
290
+ parent : MetaParams
291
+ The parent parameter to which the child will be added.
292
+ value : Union[MetaParams, Any]
293
+ The value of the child parameter.
294
+
295
+ Returns
296
+ -------
297
+ None
298
+ '''
299
+ parent = self.get_param(parent)
300
+ parent.addChild(
301
+ {'name' : 'Item 1', 'type': 'str',
302
+ 'value': self.get_param_value(value) if \
303
+ isinstance(value, MetaParams) else value, 'removable': True},
304
+ True)
305
+
306
+ def change(self, param: Parameter, changes: list):
307
+ '''
308
+ Handle parameter changes as needed.
309
+
310
+ Parameters
311
+ ----------
312
+ param : Parameter
313
+ The parameter that triggered the change.
314
+ changes : list
315
+ List of changes.
316
+
317
+ Returns
318
+ -------
319
+ None
320
+ '''
321
+ # Handle parameter changes as needed
322
+ pass
323
+
324
+ def save(self):
325
+ '''
326
+ Save metadata to an OME-XML file.
327
+
328
+ Returns
329
+ -------
330
+ None
331
+ '''
332
+ try:
333
+ filename, _ = getSaveFileName(
334
+ self, 'Save metadata', filter='OME-XML Files (*.ome.xml);;')
335
+ if filename:
336
+ ome_obj = self.gen_OME_XML(1, 512, 512)
337
+ with open(filename, 'w', encoding='utf8') as f:
338
+ f.write(ome_obj.to_xml())
339
+ except Exception as e:
340
+ print(f'Error saving file: {e}')
341
+
342
+ def load_xml(self):
343
+ '''
344
+ Load metadata from an OME-XML file.
345
+
346
+ Returns
347
+ -------
348
+ None
349
+ '''
350
+ try:
351
+ filename, _ = getOpenFileName(
352
+ self, 'Load metadata', filter='OME-XML Files (*.ome.xml);;')
353
+ if filename:
354
+ xml = ''
355
+ with open(filename, encoding='utf8') as f:
356
+ xml = f.read()
357
+ self.pop_OME_XML(OME.from_xml(xml))
358
+ except Exception as e:
359
+ print(f'Error loading file: {e}')
360
+
361
+
362
+ def gen_OME_XML(
363
+ self, frames: int, width: int, height: int,
364
+ channels: int = 1, z_planes: int = 1,
365
+ dimension_order: Pixels_DimensionOrder =Pixels_DimensionOrder.XYZCT):
366
+ '''
367
+ Generates OME-XML metadata.
368
+
369
+ Parameters
370
+ ----------
371
+ frames : int
372
+ Number of frames.
373
+ width : int
374
+ Image width.
375
+ height : int
376
+ Image height.
377
+ channels : int, optional
378
+ Number of channels, by default 1.
379
+ z_planes : int, optional
380
+ Number of z-planes, by default 1.
381
+ dimension_order : Pixels_DimensionOrder, optional
382
+ Dimension order, by default Pixels_DimensionOrder.XYZCT.
383
+
384
+ Returns
385
+ -------
386
+ om.OME
387
+ Generated OME-XML object.
388
+ '''
389
+ ome_obj = om.OME(creator='microEye Python Package')
390
+
391
+ experimenter = om.Experimenter()
392
+ experimenter.first_name = self.get_param_value(MetaParams.EXP_FNAME)
393
+ experimenter.last_name = self.get_param_value(MetaParams.EXP_LNAME)
394
+ experimenter.email = self.get_param_value(MetaParams.EXP_EMAIL)
395
+ experimenter.institution = self.get_param_value(MetaParams.EXP_INSTITUTE)
396
+ ome_obj.experimenters.append(experimenter)
397
+
398
+ micro = Microscope()
399
+ micro.manufacturer = self.get_param_value(MetaParams.MICRO_MANUFACTURER)
400
+ micro.model = self.get_param_value(MetaParams.MICRO_MODEL)
401
+
402
+ objective = Objective()
403
+ objective.manufacturer = self.get_param_value(MetaParams.OBJ_MANUFACTURER)
404
+ objective.model = self.get_param_value(MetaParams.OBJ_MODEL)
405
+ objective.lens_na = self.get_param_value(MetaParams.OBJ_LENS_NA)
406
+ objective.nominal_magnification = self.get_param_value(MetaParams.OBJ_NOM_MAG)
407
+ objective.immersion = Objective_Immersion._member_map_.get(
408
+ self.get_param_value(MetaParams.OBJ_IMMERSION), Objective_Immersion.OIL)
409
+ objective.correction = Objective_Correction._member_map_.get(
410
+ self.get_param_value(MetaParams.OBJ_CORR), Objective_Correction.PLAN_APO)
411
+
412
+ detector = Detector()
413
+ detector.manufacturer = self.get_param_value(MetaParams.DET_MANUFACTURER)
414
+ detector.model = self.get_param_value(MetaParams.DET_MODEL)
415
+ detector.serial_number = self.get_param_value(MetaParams.DET_SERIAL)
416
+ detector.type = Detector_Type._member_map_.get(
417
+ self.get_param_value(MetaParams.DET_TYPE), Detector_Type.CMOS)
418
+
419
+ exFilters = Filter()
420
+ exFilters.model = ', '.join(
421
+ self.get_children(MetaParams.EXFILTER_MODEL_LIST))
422
+ emFilters = Filter()
423
+ emFilters.model = ', '.join(
424
+ self.get_children(MetaParams.EMFILTER_MODEL_LIST))
425
+
426
+ instrument = Instrument()
427
+ instrument.microscope = micro
428
+ instrument.objectives.append(objective)
429
+ instrument.detectors.append(detector)
430
+
431
+ for item in self.get_children(MetaParams.DICHROIC_MODEL_LIST):
432
+ dichroic = Dichroic()
433
+ dichroic.manufacturer = self.get_param_value(
434
+ MetaParams.DICHROIC_MANUFACTURER)
435
+ dichroic.model = item
436
+ instrument.dichroics.append(dichroic)
437
+
438
+ instrument.filters.append(exFilters)
439
+ instrument.filters.append(emFilters)
440
+
441
+ ome_obj.instruments.append(instrument)
442
+
443
+ planes = [om.Plane(
444
+ the_c=0,
445
+ the_t=i,
446
+ the_z=0,
447
+ exposure_time=self.get_param_value(MetaParams.EXPOSURE),
448
+ exposure_time_unit=UnitsTime._member_map_.get(
449
+ self.get_param_value(MetaParams.EXPOSURE_UNIT),
450
+ UnitsTime.SECOND)
451
+ ) for i in range(frames)]
452
+
453
+ channel = om.Channel()
454
+ channel.name = self.get_param_value(MetaParams.CHANNEL_NAME)
455
+ channel.fluor = self.get_param_value(MetaParams.FLUOR_NAME)
456
+ channel.acquisition_mode = Channel_AcquisitionMode._member_map_.get(
457
+ self.get_param_value(MetaParams.ACQ_MODE),
458
+ Channel_AcquisitionMode.SINGLE_MOLECULE_IMAGING)
459
+ channel.illumination_type = Channel_IlluminationType._member_map_.get(
460
+ self.get_param_value(MetaParams.ILL_TYPE),
461
+ Channel_IlluminationType.OTHER)
462
+ channel.contrast_method = Channel_ContrastMethod._member_map_.get(
463
+ self.get_param_value(MetaParams.CONTRAST),
464
+ Channel_ContrastMethod.FLUORESCENCE)
465
+ channel.excitation_wavelength = self.get_param_value(MetaParams.EXCITATION)
466
+ channel.emission_wavelength = self.get_param_value(MetaParams.EMISSION)
467
+ channel.excitation_wavelength_unit = UnitsLength._member_map_.get(
468
+ self.get_param_value(MetaParams.WAVE_UNIT), UnitsLength.NANOMETER)
469
+ channel.emission_wavelength_unit = UnitsLength._member_map_.get(
470
+ self.get_param_value(MetaParams.WAVE_UNIT), UnitsLength.NANOMETER)
471
+ channel.samples_per_pixel = 1
472
+
473
+ pixels = om.Pixels(
474
+ size_c=channels, size_t=frames,
475
+ size_x=width,
476
+ size_y=height,
477
+ size_z=z_planes,
478
+ type=PixelType._member_map_.get(
479
+ self.get_param_value(MetaParams.PIXEL_TYPE),
480
+ PixelType.UINT16),
481
+ dimension_order=dimension_order,
482
+ # metadata_only=True,
483
+ physical_size_x=self.get_param_value(MetaParams.PX_SIZE),
484
+ physical_size_x_unit=UnitsLength._member_map_.get(
485
+ self.get_param_value(MetaParams.P_UNIT), UnitsLength.MICROMETER),
486
+ physical_size_y=self.get_param_value(MetaParams.PY_SIZE),
487
+ physical_size_y_unit=UnitsLength._member_map_.get(
488
+ self.get_param_value(MetaParams.P_UNIT), UnitsLength.MICROMETER),
489
+ time_increment=self.get_param_value(MetaParams.EXPOSURE),
490
+ time_increment_unit=UnitsTime._member_map_.get(
491
+ self.get_param_value(MetaParams.EXPOSURE_UNIT), UnitsTime.SECOND),
492
+ )
493
+ pixels.tiff_data_blocks.append(om.TiffData())
494
+ pixels.channels.append(channel)
495
+ pixels.planes.extend(planes)
496
+ img = om.Image(
497
+ id='Image:1',
498
+ name=self.get_param_value(MetaParams.EXPERIMENT_NAME),
499
+ pixels=pixels,
500
+ description=self.get_param_value(MetaParams.EXP_DESC)
501
+ )
502
+ ome_obj.images.append(img)
503
+ ome_obj = OME.model_validate(ome_obj)
504
+
505
+ # with open('config.xml', 'w', encoding='utf8') as f:
506
+ # f.write(ome_obj.to_xml())
507
+
508
+ return ome_obj
509
+
510
+ def gen_OME_XML_short(
511
+ self, frames: int, width: int, height: int,
512
+ channels: int = 1, z_planes: int = 1,
513
+ dimension_order: Pixels_DimensionOrder =Pixels_DimensionOrder.XYZCT):
514
+ '''
515
+ Generates short version of OME-XML metadata.
516
+
517
+ Parameters
518
+ ----------
519
+ frames : int
520
+ Number of frames.
521
+ width : int
522
+ Image width.
523
+ height : int
524
+ Image height.
525
+ channels : int, optional
526
+ Number of channels, by default 1.
527
+ z_planes : int, optional
528
+ Number of z-planes, by default 1.
529
+ dimension_order : Pixels_DimensionOrder, optional
530
+ Dimension order, by default Pixels_DimensionOrder.XYZCT.
531
+
532
+ Returns
533
+ -------
534
+ om.OME
535
+ Generated OME-XML object.
536
+ '''
537
+ ome_obj = om.OME(creator='microEye Python Package')
538
+
539
+ experimenter = om.Experimenter()
540
+ experimenter.first_name = self.get_param_value(MetaParams.EXP_FNAME)
541
+ experimenter.last_name = self.get_param_value(MetaParams.EXP_LNAME)
542
+ experimenter.email = self.get_param_value(MetaParams.EXP_EMAIL)
543
+ experimenter.institution = self.get_param_value(MetaParams.EXP_INSTITUTE)
544
+ ome_obj.experimenters.append(experimenter)
545
+
546
+ detector = Detector()
547
+ detector.manufacturer = self.get_param_value(MetaParams.DET_MANUFACTURER)
548
+ detector.model = self.get_param_value(MetaParams.DET_MODEL)
549
+ detector.serial_number = self.get_param_value(MetaParams.DET_SERIAL)
550
+ detector.type = Detector_Type._member_map_[
551
+ self.get_param_value(MetaParams.DET_TYPE)]
552
+
553
+ instrument = Instrument()
554
+ instrument.detectors.append(detector)
555
+
556
+ ome_obj.instruments.append(instrument)
557
+
558
+ planes = [om.Plane(
559
+ the_c=0,
560
+ the_t=i,
561
+ the_z=0,
562
+ exposure_time=self.get_param_value(MetaParams.EXPOSURE),
563
+ exposure_time_unit=UnitsTime._member_map_[
564
+ self.get_param_value(MetaParams.EXPOSURE_UNIT)
565
+ ]
566
+ ) for i in range(frames)]
567
+
568
+ channel = om.Channel()
569
+
570
+ pixels = om.Pixels(
571
+ size_c=channels, size_t=frames,
572
+ size_x=width,
573
+ size_y=height,
574
+ size_z=z_planes,
575
+ type=PixelType._member_map_[
576
+ self.get_param_value(MetaParams.PIXEL_TYPE)],
577
+ dimension_order=dimension_order,
578
+ # metadata_only=True,
579
+ physical_size_x=self.get_param_value(MetaParams.PX_SIZE),
580
+ physical_size_x_unit=UnitsLength._member_map_[
581
+ self.get_param_value(MetaParams.P_UNIT)],
582
+ physical_size_y=self.get_param_value(MetaParams.PY_SIZE),
583
+ physical_size_y_unit=UnitsLength._member_map_[
584
+ self.get_param_value(MetaParams.P_UNIT)],
585
+ time_increment=self.get_param_value(MetaParams.EXPOSURE),
586
+ time_increment_unit=UnitsTime._member_map_[
587
+ self.get_param_value(MetaParams.EXPOSURE_UNIT)],
588
+ )
589
+ pixels.tiff_data_blocks.append(om.TiffData())
590
+ pixels.channels.append(channel)
591
+ pixels.planes.extend(planes)
592
+ img = om.Image(
593
+ id='Image:1',
594
+ name=self.get_param_value(MetaParams.EXPERIMENT_NAME),
595
+ pixels=pixels,
596
+ description=self.get_param_value(MetaParams.EXP_DESC)
597
+ )
598
+ ome_obj.images.append(img)
599
+ ome_obj = OME.model_validate(ome_obj)
600
+
601
+ return ome_obj
602
+
603
+ def pop_OME_XML(self, ome_obj: OME):
604
+ '''
605
+ Populate the widget with OME-XML metadata.
606
+
607
+ Parameters
608
+ ----------
609
+ ome_obj : om.OME
610
+ The OME-XML object to be loaded.
611
+ '''
612
+ if ome_obj.images.__len__() > 0:
613
+ img = ome_obj.images[0]
614
+ self.set_param_value(MetaParams.EXPERIMENT_NAME, img.name)
615
+ self.set_param_value(MetaParams.EXP_DESC,img.description)
616
+ if img.pixels is not None:
617
+ pixels = img.pixels
618
+ if pixels.physical_size_x is not None:
619
+ self.set_param_value(
620
+ MetaParams.PX_SIZE,
621
+ float(pixels.physical_size_x))
622
+ self.set_param_value(
623
+ MetaParams.P_UNIT,
624
+ pixels.physical_size_x_unit.name)
625
+ if pixels.physical_size_y is not None:
626
+ self.set_param_value(
627
+ MetaParams.PY_SIZE,
628
+ float(pixels.physical_size_y))
629
+ if pixels.time_increment is not None:
630
+ self.set_param_value(
631
+ MetaParams.EXPOSURE,
632
+ float(pixels.time_increment))
633
+ self.set_param_value(
634
+ MetaParams.EXPOSURE_UNIT,
635
+ pixels.time_increment_unit.name)
636
+ self.set_param_value(
637
+ MetaParams.PIXEL_TYPE, pixels.type.name)
638
+ if pixels.channels.__len__() > 0:
639
+ channel = pixels.channels[0]
640
+ self.set_param_value(MetaParams.CHANNEL_NAME, channel.name)
641
+ self.set_param_value(MetaParams.FLUOR_NAME, channel.fluor)
642
+ if channel.acquisition_mode:
643
+ self.set_param_value(
644
+ MetaParams.ACQ_MODE,
645
+ channel.acquisition_mode.name)
646
+ if channel.illumination_type:
647
+ self.set_param_value(
648
+ MetaParams.ILL_TYPE,
649
+ channel.illumination_type.name)
650
+ if channel.contrast_method:
651
+ self.set_param_value(
652
+ MetaParams.CONTRAST,
653
+ channel.contrast_method.name)
654
+ if channel.excitation_wavelength:
655
+ self.set_param_value(
656
+ MetaParams.EXCITATION,
657
+ float(channel.excitation_wavelength))
658
+ self.set_param_value(
659
+ MetaParams.WAVE_UNIT,
660
+ channel.excitation_wavelength_unit.name)
661
+ if channel.emission_wavelength:
662
+ self.set_param_value(
663
+ MetaParams.EMISSION,
664
+ float(channel.emission_wavelength))
665
+ self.set_param_value(
666
+ MetaParams.WAVE_UNIT,
667
+ channel.emission_wavelength_unit.name)
668
+ if ome_obj.experimenters.__len__() > 0:
669
+ exper = ome_obj.experimenters[0]
670
+ self.set_param_value(MetaParams.EXP_FNAME, exper.first_name)
671
+ self.set_param_value(MetaParams.EXP_LNAME, exper.last_name)
672
+ self.set_param_value(MetaParams.EXP_EMAIL, exper.email)
673
+ self.set_param_value(MetaParams.EXP_INSTITUTE, exper.institution)
674
+ if ome_obj.instruments.__len__() > 0:
675
+ inst = ome_obj.instruments[0]
676
+ if inst.microscope is not None:
677
+ micro = inst.microscope
678
+ self.set_param_value(
679
+ MetaParams.MICRO_MANUFACTURER, micro.manufacturer)
680
+ self.set_param_value(MetaParams.MICRO_MODEL, micro.model)
681
+ if inst.objectives.__len__() > 0:
682
+ objective = inst.objectives[0]
683
+ self.set_param_value(
684
+ MetaParams.OBJ_MANUFACTURER, objective.manufacturer)
685
+ self.set_param_value(MetaParams.OBJ_MODEL, objective.model)
686
+ self.set_param_value(
687
+ MetaParams.OBJ_LENS_NA,
688
+ float(objective.lens_na))
689
+ self.set_param_value(
690
+ MetaParams.OBJ_NOM_MAG,
691
+ float(objective.nominal_magnification))
692
+ self.set_param_value(
693
+ MetaParams.OBJ_IMMERSION, objective.immersion.name)
694
+ self.set_param_value(
695
+ MetaParams.OBJ_CORR, objective.correction.name)
696
+ if inst.detectors.__len__() > 0:
697
+ detector = inst.detectors[0]
698
+ self.set_param_value(
699
+ MetaParams.DET_MANUFACTURER, detector.manufacturer)
700
+ self.set_param_value(MetaParams.DET_MODEL, detector.model)
701
+ self.set_param_value(MetaParams.DET_SERIAL, detector.serial_number)
702
+ self.set_param_value(MetaParams.DET_TYPE, detector.type.name)
703
+ if inst.dichroics.__len__() > 0:
704
+ self.get_param(MetaParams.DICHROIC_MODEL_LIST).clearChildren()
705
+ for dichroic in inst.dichroics:
706
+ self.set_param_value(
707
+ MetaParams.DICHROIC_MANUFACTURER, dichroic.manufacturer)
708
+ self.add_param_child(
709
+ MetaParams.DICHROIC_MODEL_LIST, dichroic.model)
710
+ if inst.filters.__len__() > 1:
711
+ self.get_param(MetaParams.EXFILTER_MODEL_LIST).clearChildren()
712
+ self.get_param(MetaParams.EMFILTER_MODEL_LIST).clearChildren()
713
+ exFilters = inst.filters[0]
714
+ for _filter in inst.filters[0].model.split(', '):
715
+ self.add_param_child(MetaParams.EXFILTER_MODEL_LIST, _filter)
716
+ emFilters = inst.filters[1]
717
+ for _filter in inst.filters[1].model.split(', '):
718
+ self.add_param_child(MetaParams.EMFILTER_MODEL_LIST, _filter)