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