waveorder 2.2.1b0__py3-none-any.whl → 3.0.0__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.
- waveorder/_version.py +16 -3
- waveorder/acq/__init__.py +0 -0
- waveorder/acq/acq_functions.py +166 -0
- waveorder/assets/HSV_legend.png +0 -0
- waveorder/assets/JCh_legend.png +0 -0
- waveorder/assets/waveorder_plugin_logo.png +0 -0
- waveorder/calib/Calibration.py +1512 -0
- waveorder/calib/Optimization.py +470 -0
- waveorder/calib/__init__.py +0 -0
- waveorder/calib/calibration_workers.py +464 -0
- waveorder/cli/apply_inverse_models.py +328 -0
- waveorder/cli/apply_inverse_transfer_function.py +379 -0
- waveorder/cli/compute_transfer_function.py +432 -0
- waveorder/cli/gui_widget.py +58 -0
- waveorder/cli/main.py +39 -0
- waveorder/cli/monitor.py +163 -0
- waveorder/cli/option_eat_all.py +47 -0
- waveorder/cli/parsing.py +122 -0
- waveorder/cli/printing.py +16 -0
- waveorder/cli/reconstruct.py +67 -0
- waveorder/cli/settings.py +187 -0
- waveorder/cli/utils.py +175 -0
- waveorder/filter.py +1 -2
- waveorder/focus.py +136 -25
- waveorder/io/__init__.py +0 -0
- waveorder/io/_reader.py +61 -0
- waveorder/io/core_functions.py +272 -0
- waveorder/io/metadata_reader.py +195 -0
- waveorder/io/utils.py +175 -0
- waveorder/io/visualization.py +160 -0
- waveorder/models/inplane_oriented_thick_pol3d_vector.py +3 -3
- waveorder/models/isotropic_fluorescent_thick_3d.py +92 -0
- waveorder/models/isotropic_fluorescent_thin_3d.py +331 -0
- waveorder/models/isotropic_thin_3d.py +73 -72
- waveorder/models/phase_thick_3d.py +103 -4
- waveorder/napari.yaml +36 -0
- waveorder/plugin/__init__.py +9 -0
- waveorder/plugin/gui.py +1094 -0
- waveorder/plugin/gui.ui +1440 -0
- waveorder/plugin/job_manager.py +42 -0
- waveorder/plugin/main_widget.py +1605 -0
- waveorder/plugin/tab_recon.py +3294 -0
- waveorder/scripts/__init__.py +0 -0
- waveorder/scripts/launch_napari.py +13 -0
- waveorder/scripts/repeat-cal-acq-rec.py +147 -0
- waveorder/scripts/repeat-calibration.py +31 -0
- waveorder/scripts/samples.py +85 -0
- waveorder/scripts/simulate_zarr_acq.py +204 -0
- waveorder/util.py +1 -1
- waveorder/visuals/napari_visuals.py +1 -1
- waveorder-3.0.0.dist-info/METADATA +350 -0
- waveorder-3.0.0.dist-info/RECORD +69 -0
- {waveorder-2.2.1b0.dist-info → waveorder-3.0.0.dist-info}/WHEEL +1 -1
- waveorder-3.0.0.dist-info/entry_points.txt +5 -0
- {waveorder-2.2.1b0.dist-info → waveorder-3.0.0.dist-info/licenses}/LICENSE +13 -1
- waveorder-2.2.1b0.dist-info/METADATA +0 -187
- waveorder-2.2.1b0.dist-info/RECORD +0 -27
- {waveorder-2.2.1b0.dist-info → waveorder-3.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
# type hint/check
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
from iohub import open_ome_zarr
|
|
12
|
+
from napari.qt.threading import WorkerBase, WorkerBaseSignals, thread_worker
|
|
13
|
+
from qtpy.QtCore import Signal
|
|
14
|
+
|
|
15
|
+
from waveorder.calib.Calibration import LC_DEVICE_NAME
|
|
16
|
+
from waveorder.cli import settings
|
|
17
|
+
from waveorder.cli.apply_inverse_transfer_function import (
|
|
18
|
+
apply_inverse_transfer_function_cli,
|
|
19
|
+
)
|
|
20
|
+
from waveorder.cli.compute_transfer_function import (
|
|
21
|
+
compute_transfer_function_cli,
|
|
22
|
+
)
|
|
23
|
+
from waveorder.io.core_functions import set_lc_state, snap_and_average
|
|
24
|
+
from waveorder.io.metadata_reader import MetadataReader
|
|
25
|
+
from waveorder.io.utils import MockEmitter, add_index_to_path, model_to_yaml
|
|
26
|
+
|
|
27
|
+
# avoid runtime import error
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
from waveorder.calib.Calibration import QLIPP_Calibration
|
|
32
|
+
from waveorder.plugin.main_widget import MainWidget
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class CalibrationSignals(WorkerBaseSignals):
|
|
36
|
+
"""
|
|
37
|
+
Custom Signals class that includes napari native signals
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
progress_update = Signal(tuple)
|
|
41
|
+
extinction_update = Signal(str)
|
|
42
|
+
intensity_update = Signal(object)
|
|
43
|
+
calib_assessment = Signal(str)
|
|
44
|
+
calib_assessment_msg = Signal(str)
|
|
45
|
+
calib_file_emit = Signal(Path)
|
|
46
|
+
plot_sequence_emit = Signal(str)
|
|
47
|
+
lc_states = Signal(tuple)
|
|
48
|
+
aborted = Signal()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class BackgroundSignals(WorkerBaseSignals):
|
|
52
|
+
"""
|
|
53
|
+
Custom Signals class that includes napari native signals
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
bg_image_emitter = Signal(tuple)
|
|
57
|
+
bire_image_emitter = Signal(tuple)
|
|
58
|
+
bg_path_update_emitter = Signal(Path)
|
|
59
|
+
aborted = Signal()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class CalibrationWorkerBase(WorkerBase):
|
|
63
|
+
"""
|
|
64
|
+
Base class for creating calibration workers.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
def __init_subclass__(cls, signals: WorkerBaseSignals):
|
|
68
|
+
"""Called when creating calibration worker classes.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
signals : WorkerBaseSignals
|
|
73
|
+
Qt Signals class for the created worker class to send data across threads.
|
|
74
|
+
"""
|
|
75
|
+
super().__init_subclass__()
|
|
76
|
+
cls.signals = signals
|
|
77
|
+
|
|
78
|
+
def __init__(self, calib_window: MainWidget, calib: QLIPP_Calibration):
|
|
79
|
+
"""Initialize the worker object.
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
calib_window : MainWidget
|
|
84
|
+
The waveorder plugin's main GUI widget object containing metadata input.
|
|
85
|
+
calib : QLIPP_Calibration
|
|
86
|
+
waveorder calibration backend object.
|
|
87
|
+
"""
|
|
88
|
+
super().__init__(SignalsClass=self.signals)
|
|
89
|
+
self.calib_window = calib_window
|
|
90
|
+
self.calib = calib
|
|
91
|
+
|
|
92
|
+
def _check_abort(self):
|
|
93
|
+
"""
|
|
94
|
+
Called if the user presses the STOP button.
|
|
95
|
+
Needs to be checked after every major step to stop the process
|
|
96
|
+
"""
|
|
97
|
+
if self.abort_requested:
|
|
98
|
+
self.aborted.emit()
|
|
99
|
+
raise TimeoutError("Stop Requested.")
|
|
100
|
+
|
|
101
|
+
def _write_meta_file(self, meta_file: str):
|
|
102
|
+
self.calib.meta_file = meta_file
|
|
103
|
+
self.calib.write_metadata(
|
|
104
|
+
notes=self.calib_window.ui.le_notes_field.text()
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class CalibrationWorker(CalibrationWorkerBase, signals=CalibrationSignals):
|
|
109
|
+
"""
|
|
110
|
+
Class to execute calibration
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
def __init__(self, calib_window, calib):
|
|
114
|
+
super().__init__(calib_window, calib)
|
|
115
|
+
|
|
116
|
+
def work(self):
|
|
117
|
+
"""
|
|
118
|
+
Runs the full calibration algorithm and emits necessary signals.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
self.plot_sequence_emit.emit("Coarse")
|
|
122
|
+
self.calib.intensity_emitter = self.intensity_update
|
|
123
|
+
self.calib.plot_sequence_emitter = self.plot_sequence_emit
|
|
124
|
+
self.progress_update.emit((1, "Calculating Blacklevel..."))
|
|
125
|
+
self._check_abort()
|
|
126
|
+
|
|
127
|
+
logging.info("Calculating Black Level ...")
|
|
128
|
+
logging.debug("Calculating Black Level ...")
|
|
129
|
+
self.calib.close_shutter_and_calc_blacklevel()
|
|
130
|
+
|
|
131
|
+
# Calculate Blacklevel
|
|
132
|
+
logging.info(f"Black Level: {self.calib.I_Black:.0f}\n")
|
|
133
|
+
logging.debug(f"Black Level: {self.calib.I_Black:.0f}\n")
|
|
134
|
+
|
|
135
|
+
self._check_abort()
|
|
136
|
+
self.progress_update.emit((10, "Calibrating Extinction State..."))
|
|
137
|
+
|
|
138
|
+
# Open shutter
|
|
139
|
+
self.calib.open_shutter()
|
|
140
|
+
|
|
141
|
+
# Set LC Wavelength:
|
|
142
|
+
self.calib.set_wavelength(int(self.calib_window.wavelength))
|
|
143
|
+
if self.calib_window.calib_mode == "MM-Retardance":
|
|
144
|
+
self.calib_window.mmc.setProperty(
|
|
145
|
+
LC_DEVICE_NAME, "Wavelength", self.calib_window.wavelength
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
self._check_abort()
|
|
149
|
+
|
|
150
|
+
# Optimize States
|
|
151
|
+
(
|
|
152
|
+
self._calibrate_4state()
|
|
153
|
+
if self.calib_window.calib_scheme == "4-State"
|
|
154
|
+
else self._calibrate_5state()
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Reset shutter autoshutter
|
|
158
|
+
self.calib.reset_shutter()
|
|
159
|
+
|
|
160
|
+
# Calculate Extinction
|
|
161
|
+
extinction_ratio = self.calib.calculate_extinction(
|
|
162
|
+
self.calib.swing,
|
|
163
|
+
self.calib.I_Black,
|
|
164
|
+
self.calib.I_Ext,
|
|
165
|
+
self.calib.I_Elliptical,
|
|
166
|
+
)
|
|
167
|
+
self._check_abort()
|
|
168
|
+
|
|
169
|
+
# Update main GUI with extinction ratio
|
|
170
|
+
self.calib.extinction_ratio = extinction_ratio
|
|
171
|
+
self.extinction_update.emit(str(extinction_ratio))
|
|
172
|
+
|
|
173
|
+
# determine metadata filename
|
|
174
|
+
meta_file = (
|
|
175
|
+
Path(self.calib_window.directory) / "calibration_metadata.txt"
|
|
176
|
+
)
|
|
177
|
+
meta_file = add_index_to_path(meta_file)
|
|
178
|
+
|
|
179
|
+
# Write Metadata
|
|
180
|
+
self._write_meta_file(meta_file)
|
|
181
|
+
self.calib_file_emit.emit(self.calib.meta_file)
|
|
182
|
+
self.progress_update.emit((100, "Finished"))
|
|
183
|
+
|
|
184
|
+
self._check_abort()
|
|
185
|
+
|
|
186
|
+
# Perform calibration assessment based on retardance values
|
|
187
|
+
self._assess_calibration()
|
|
188
|
+
|
|
189
|
+
self._check_abort()
|
|
190
|
+
|
|
191
|
+
# Emit calibrated LC states for plotting
|
|
192
|
+
self.lc_states.emit((self.calib.pol_states, self.calib.lc_states))
|
|
193
|
+
|
|
194
|
+
logging.info("\n=======Finished Calibration=======\n")
|
|
195
|
+
logging.info(f"EXTINCTION = {extinction_ratio:.2f}")
|
|
196
|
+
logging.debug("\n=======Finished Calibration=======\n")
|
|
197
|
+
logging.debug(f"EXTINCTION = {extinction_ratio:.2f}")
|
|
198
|
+
|
|
199
|
+
def _calibrate_4state(self):
|
|
200
|
+
"""
|
|
201
|
+
Run through the 4-state calibration algorithm
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
search_radius = np.min((self.calib.swing / self.calib.ratio, 0.05))
|
|
205
|
+
|
|
206
|
+
self.calib.calib_scheme = "4-State"
|
|
207
|
+
|
|
208
|
+
self._check_abort()
|
|
209
|
+
|
|
210
|
+
# Optimize Extinction State
|
|
211
|
+
self.calib.opt_Iext()
|
|
212
|
+
|
|
213
|
+
self._check_abort()
|
|
214
|
+
self.progress_update.emit((60, "Calibrating State 1..."))
|
|
215
|
+
|
|
216
|
+
# Optimize first elliptical (reference) state
|
|
217
|
+
self.calib.opt_I0()
|
|
218
|
+
self.progress_update.emit((65, "Calibrating State 2..."))
|
|
219
|
+
|
|
220
|
+
self._check_abort()
|
|
221
|
+
|
|
222
|
+
# Optimize 60 deg state
|
|
223
|
+
self.calib.opt_I60(search_radius, search_radius)
|
|
224
|
+
self.progress_update.emit((75, "Calibrating State 3..."))
|
|
225
|
+
|
|
226
|
+
self._check_abort()
|
|
227
|
+
|
|
228
|
+
# Optimize 120 deg state
|
|
229
|
+
self.calib.opt_I120(search_radius, search_radius)
|
|
230
|
+
self.progress_update.emit((85, "Writing Metadata..."))
|
|
231
|
+
|
|
232
|
+
self._check_abort()
|
|
233
|
+
|
|
234
|
+
def _calibrate_5state(self):
|
|
235
|
+
search_radius = np.min((self.calib.swing, 0.05))
|
|
236
|
+
|
|
237
|
+
self.calib.calib_scheme = "5-State"
|
|
238
|
+
|
|
239
|
+
# Optimize Extinction State
|
|
240
|
+
self.calib.opt_Iext()
|
|
241
|
+
self.progress_update.emit((50, "Calibrating State 1..."))
|
|
242
|
+
|
|
243
|
+
self._check_abort()
|
|
244
|
+
|
|
245
|
+
# Optimize First elliptical state
|
|
246
|
+
self.calib.opt_I0()
|
|
247
|
+
self.progress_update.emit((55, "Calibrating State 2..."))
|
|
248
|
+
|
|
249
|
+
self._check_abort()
|
|
250
|
+
|
|
251
|
+
# Optimize 45 deg state
|
|
252
|
+
self.calib.opt_I45(search_radius, search_radius)
|
|
253
|
+
self.progress_update.emit((65, "Calibrating State 3..."))
|
|
254
|
+
|
|
255
|
+
self._check_abort()
|
|
256
|
+
|
|
257
|
+
# Optimize 90 deg state
|
|
258
|
+
self.calib.opt_I90(search_radius, search_radius)
|
|
259
|
+
self.progress_update.emit((75, "Calibrating State 4..."))
|
|
260
|
+
|
|
261
|
+
self._check_abort()
|
|
262
|
+
|
|
263
|
+
# Optimize 135 deg state
|
|
264
|
+
self.calib.opt_I135(search_radius, search_radius)
|
|
265
|
+
self.progress_update.emit((85, "Writing Metadata..."))
|
|
266
|
+
|
|
267
|
+
self._check_abort()
|
|
268
|
+
|
|
269
|
+
def _assess_calibration(self):
|
|
270
|
+
"""
|
|
271
|
+
Assesses the quality of calibration based off retardance values.
|
|
272
|
+
Attempts to determine whether certain optical components are out of place.
|
|
273
|
+
"""
|
|
274
|
+
|
|
275
|
+
if self.calib.extinction_ratio >= 100:
|
|
276
|
+
self.calib_assessment.emit("good")
|
|
277
|
+
self.calib_assessment_msg.emit("Successful Calibration")
|
|
278
|
+
elif 80 <= self.calib.extinction_ratio < 100:
|
|
279
|
+
self.calib_assessment.emit("okay")
|
|
280
|
+
self.calib_assessment_msg.emit(
|
|
281
|
+
"Successful Calibration, Okay Extinction Ratio"
|
|
282
|
+
)
|
|
283
|
+
else:
|
|
284
|
+
self.calib_assessment.emit("bad")
|
|
285
|
+
message = (
|
|
286
|
+
"Possibilities are: a) linear polarizer and LC are not oriented properly, "
|
|
287
|
+
"b) circular analyzer has wrong handedness, "
|
|
288
|
+
"c) the condenser is not setup for Kohler illumination, "
|
|
289
|
+
"d) a component, such as autofocus dichroic or sample chamber, distorts the polarization state"
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
self.calib_assessment_msg.emit("Poor Extinction. " + message)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class BackgroundCaptureWorker(
|
|
296
|
+
CalibrationWorkerBase, signals=BackgroundSignals
|
|
297
|
+
):
|
|
298
|
+
"""
|
|
299
|
+
Class to execute background capture.
|
|
300
|
+
"""
|
|
301
|
+
|
|
302
|
+
def __init__(self, calib_window, calib):
|
|
303
|
+
super().__init__(calib_window, calib)
|
|
304
|
+
|
|
305
|
+
def work(self):
|
|
306
|
+
# Make the background folder
|
|
307
|
+
bg_path = (
|
|
308
|
+
Path(self.calib_window.directory)
|
|
309
|
+
/ self.calib_window.ui.le_bg_folder.text()
|
|
310
|
+
)
|
|
311
|
+
bg_path = add_index_to_path(bg_path)
|
|
312
|
+
bg_path.mkdir()
|
|
313
|
+
|
|
314
|
+
self._check_abort()
|
|
315
|
+
|
|
316
|
+
# capture and return background images
|
|
317
|
+
imgs = self.calib.capture_bg(self.calib_window.n_avg, bg_path)
|
|
318
|
+
|
|
319
|
+
# build background-specific reconstruction settings
|
|
320
|
+
reconstruction_settings = settings.ReconstructionSettings(
|
|
321
|
+
input_channel_names=[
|
|
322
|
+
f"State{i}"
|
|
323
|
+
for i in range(int(self.calib_window.calib_scheme[0]))
|
|
324
|
+
],
|
|
325
|
+
reconstruction_dimension=2,
|
|
326
|
+
birefringence=settings.BirefringenceSettings(
|
|
327
|
+
transfer_function=settings.BirefringenceTransferFunctionSettings(
|
|
328
|
+
swing=self.calib_window.swing
|
|
329
|
+
),
|
|
330
|
+
apply_inverse=settings.BirefringenceApplyInverseSettings(
|
|
331
|
+
wavelength_illumination=self.calib_window.recon_wavelength
|
|
332
|
+
/ 1000,
|
|
333
|
+
background_path="",
|
|
334
|
+
remove_estimated_background=False,
|
|
335
|
+
flip_orientation=False,
|
|
336
|
+
rotate_orientation=False,
|
|
337
|
+
),
|
|
338
|
+
),
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
reconstruction_config_path = bg_path / "reconstruction_settings.yml"
|
|
342
|
+
model_to_yaml(reconstruction_settings, reconstruction_config_path)
|
|
343
|
+
|
|
344
|
+
input_data_path = bg_path / "background.zarr" / "0" / "0" / "0"
|
|
345
|
+
transfer_function_path = bg_path / "transfer_function.zarr"
|
|
346
|
+
reconstruction_path = bg_path / "reconstruction.zarr"
|
|
347
|
+
|
|
348
|
+
compute_transfer_function_cli(
|
|
349
|
+
input_position_dirpath=input_data_path,
|
|
350
|
+
config_filepath=reconstruction_config_path,
|
|
351
|
+
output_dirpath=transfer_function_path,
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
apply_inverse_transfer_function_cli(
|
|
355
|
+
input_position_dirpaths=[input_data_path],
|
|
356
|
+
transfer_function_dirpath=transfer_function_path,
|
|
357
|
+
config_filepath=reconstruction_config_path,
|
|
358
|
+
output_dirpath=reconstruction_path,
|
|
359
|
+
num_processes=1,
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
# Load reconstructions from file for layers
|
|
363
|
+
with open_ome_zarr(reconstruction_path, mode="r") as dataset:
|
|
364
|
+
self.retardance = dataset["0/0/0/0"][0, 0, 0]
|
|
365
|
+
self.birefringence = dataset["0/0/0/0"][0, :, 0]
|
|
366
|
+
scale = dataset["0/0/0"].scale
|
|
367
|
+
|
|
368
|
+
# Save metadata file and emit imgs
|
|
369
|
+
meta_file = bg_path / "polarization_calibration.txt"
|
|
370
|
+
self._write_meta_file(meta_file)
|
|
371
|
+
|
|
372
|
+
# Update last calibration file
|
|
373
|
+
note = self.calib_window.ui.le_notes_field.text()
|
|
374
|
+
|
|
375
|
+
with open(self.calib_window.last_calib_meta_file, "r") as file:
|
|
376
|
+
current_json = json.load(file)
|
|
377
|
+
|
|
378
|
+
old_note = current_json["Notes"]
|
|
379
|
+
if old_note is None or old_note == "" or old_note == note:
|
|
380
|
+
current_json["Notes"] = note
|
|
381
|
+
else:
|
|
382
|
+
current_json["Notes"] = old_note + ", " + note
|
|
383
|
+
|
|
384
|
+
with open(self.calib_window.last_calib_meta_file, "w") as file:
|
|
385
|
+
json.dump(current_json, file, indent=1)
|
|
386
|
+
|
|
387
|
+
self._check_abort()
|
|
388
|
+
|
|
389
|
+
# Emit background images + background birefringence
|
|
390
|
+
self.bg_image_emitter.emit((imgs, scale))
|
|
391
|
+
self.bire_image_emitter.emit(
|
|
392
|
+
((self.retardance, self.birefringence[1]), scale)
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
# Emit bg path
|
|
396
|
+
self.bg_path_update_emitter.emit(bg_path)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
@thread_worker
|
|
400
|
+
def load_calibration(calib, metadata: MetadataReader):
|
|
401
|
+
"""
|
|
402
|
+
Sets MM properties based upon calibration metadata file
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
Parameters
|
|
406
|
+
----------
|
|
407
|
+
calib: (object) waveorder Calibration Class
|
|
408
|
+
metadata: (object) MetadataReader instance
|
|
409
|
+
|
|
410
|
+
Returns
|
|
411
|
+
-------
|
|
412
|
+
calib (object) updated waveorder Calibration Class
|
|
413
|
+
"""
|
|
414
|
+
calib.calib_scheme = metadata.Calibration_scheme
|
|
415
|
+
|
|
416
|
+
def _set_calib_attrs(calib, metadata):
|
|
417
|
+
"""Set the retardance attributes in the waveorder Calibration object"""
|
|
418
|
+
if calib.calib_scheme == "4-State":
|
|
419
|
+
lc_states = ["ext", "0", "60", "120"]
|
|
420
|
+
elif calib.calib_scheme == "5-State":
|
|
421
|
+
lc_states = ["ext", "0", "45", "90", "135"]
|
|
422
|
+
else:
|
|
423
|
+
raise ValueError(
|
|
424
|
+
"Invalid calibration scheme in metadata: {calib.calib_scheme}"
|
|
425
|
+
)
|
|
426
|
+
for side in ("A", "B"):
|
|
427
|
+
retardance_values = metadata.__getattribute__(
|
|
428
|
+
"LC" + side + "_retardance"
|
|
429
|
+
)
|
|
430
|
+
for i, state in enumerate(lc_states):
|
|
431
|
+
# set the retardance value attribute (e.g. 'lca_0')
|
|
432
|
+
retardance_name = "lc" + side.lower() + "_" + state
|
|
433
|
+
setattr(calib, retardance_name, retardance_values[i])
|
|
434
|
+
# set the swing value attribute (e.g. 'swing0')
|
|
435
|
+
if state != "ext":
|
|
436
|
+
swing_name = "swing" + state
|
|
437
|
+
setattr(calib, swing_name, metadata.Swing_measured[i - 1])
|
|
438
|
+
|
|
439
|
+
_set_calib_attrs(calib, metadata)
|
|
440
|
+
|
|
441
|
+
for state, lca, lcb in zip(
|
|
442
|
+
[f"State{i}" for i in range(5)],
|
|
443
|
+
metadata.LCA_retardance,
|
|
444
|
+
metadata.LCB_retardance,
|
|
445
|
+
):
|
|
446
|
+
calib.define_lc_state(state, lca, lcb)
|
|
447
|
+
|
|
448
|
+
# Calculate black level after loading these properties
|
|
449
|
+
calib.intensity_emitter = MockEmitter()
|
|
450
|
+
calib.close_shutter_and_calc_blacklevel()
|
|
451
|
+
calib.open_shutter()
|
|
452
|
+
set_lc_state(calib.mmc, calib.group, "State0")
|
|
453
|
+
calib.I_Ext = snap_and_average(calib.snap_manager)
|
|
454
|
+
set_lc_state(calib.mmc, calib.group, "State1")
|
|
455
|
+
calib.I_Elliptical = snap_and_average(calib.snap_manager)
|
|
456
|
+
calib.reset_shutter()
|
|
457
|
+
|
|
458
|
+
yield str(
|
|
459
|
+
calib.calculate_extinction(
|
|
460
|
+
calib.swing, calib.I_Black, calib.I_Ext, calib.I_Elliptical
|
|
461
|
+
)
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
return calib
|