flimkit 0.13.5__tar.gz → 0.13.6__tar.gz
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.
- {flimkit-0.13.5 → flimkit-0.13.6}/PKG-INFO +1 -1
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/FLIM/batch.py +18 -2
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/fov_preview.py +98 -10
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/gui.py +340 -26
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/irf_widget.py +15 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/modes/batch_mode.py +1 -34
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/modes/fov_mode.py +2 -3
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/modes/stitch_mode.py +2 -30
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/phasor_panel.py +135 -148
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/project_panel.py +7 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/roi_tools.py +34 -34
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/_version.py +3 -2
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/configs.py +21 -1
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/PTU/reader.py +11 -10
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/interactive.py +19 -3
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/phasor_launcher.py +45 -9
- flimkit-0.13.6/flimkit/utils/apply_settings.py +89 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/display.py +27 -3
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit.egg-info/PKG-INFO +1 -1
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit.egg-info/SOURCES.txt +1 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/LICENSE.md +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/README.md +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/FLIM/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/FLIM/assemble.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/FLIM/bg_tools.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/FLIM/fit_tools.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/FLIM/fitters.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/FLIM/irf_tools.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/FLIM/models.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/GPU/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/GPU/_base.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/GPU/cuda.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/GPU/mlx_backend.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/GPU/mps.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/GPU/rocm.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/GPU/torch_backend.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/app_state.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/controller.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/expert_settings.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/fit_help.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/icon.icns +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/icon.ico +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/icon.png +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/mode_controller.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/modes/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/modes/base.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/modes/irf_mode.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/modes/phasor_mode.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/progress_window.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/results_panel.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/UI/utils.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/cli.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/dialogs.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/BH/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/BH/reader.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/BH/writer.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/ISS/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/ISS/fdflim.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/ISS/image.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/ISS/reader.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/PS/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/PS/reader.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/PTU/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/PTU/decode.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/PTU/phu.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/PTU/series.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/PTU/stitch.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/PTU/tools.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/flim_file.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/phasor.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/formats/signal.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/image/tools.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/mpl_backend.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/phasor/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/phasor/filters.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/phasor/fret.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/phasor/interactive.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/phasor/peaks.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/phasor/signal.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/plugins/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/plugins/bindings.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/plugins/builtin/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/plugins/builtin/core_tools.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/plugins/loader.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/plugins/registry.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/project.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/synth.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/__init__.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/batch_fit.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/config_manager.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/config_snapshot.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/crash_handler.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/enhanced_outputs.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/fancy.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/lifetime_image.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/misc.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/ome_zarr.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/plotting.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/roi.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/session.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/update_check.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/xlsx_tools.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit/utils/xml_utils.py +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit.egg-info/dependency_links.txt +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit.egg-info/entry_points.txt +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit.egg-info/requires.txt +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/flimkit.egg-info/top_level.txt +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/pyproject.toml +0 -0
- {flimkit-0.13.5 → flimkit-0.13.6}/setup.cfg +0 -0
|
@@ -20,6 +20,18 @@ from ..utils.batch_fit import (
|
|
|
20
20
|
save_tile_lifetime_txt, save_map_stacks, plot_metric_summary,
|
|
21
21
|
)
|
|
22
22
|
|
|
23
|
+
def _window_kwargs(args):
|
|
24
|
+
from ..interactive import parse_exclude_ns
|
|
25
|
+
return dict(
|
|
26
|
+
irf_shift_bins=getattr(args, 'irf_shift_bins', 2),
|
|
27
|
+
fit_start_ns=getattr(args, 'fit_start_ns', None),
|
|
28
|
+
fit_end_ns=getattr(args, 'fit_end_ns', None),
|
|
29
|
+
exclude_ns=parse_exclude_ns(getattr(args, 'exclude_ns', None)),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
def _binning(args):
|
|
33
|
+
return max(1, int(getattr(args, 'binning', 1) or 1))
|
|
34
|
+
|
|
23
35
|
def _save_4d_stacks(frame_positions, group_dir, group_label):
|
|
24
36
|
sorted_t = sorted(frame_positions.keys())
|
|
25
37
|
all_s = sorted({s for pos in frame_positions.values() for s in pos})
|
|
@@ -122,6 +134,7 @@ def fit_timelapse(ptu_dir, output_dir, args,
|
|
|
122
134
|
polish=not getattr(args, 'no_polish', False),
|
|
123
135
|
cost_function=getattr(args, 'cost_function', 'poisson'),
|
|
124
136
|
sigma_max=sigma_max,
|
|
137
|
+
**_window_kwargs(args),
|
|
125
138
|
)
|
|
126
139
|
print(f' Reference fit: {time.time() - t0:.1f} s')
|
|
127
140
|
taus_ns = global_summary.get('taus_ns', global_popt[:args.nexp] * 1e9)
|
|
@@ -163,7 +176,7 @@ def fit_timelapse(ptu_dir, output_dir, args,
|
|
|
163
176
|
print(f'\n t={t} s={s}: {ptu_path.name}')
|
|
164
177
|
t_start = time.time()
|
|
165
178
|
ptu = FLIMFile(str(ptu_path), verbose=False)
|
|
166
|
-
pixel_stack = ptu.raw_pixel_stack(channel=channel)
|
|
179
|
+
pixel_stack = ptu.raw_pixel_stack(channel=channel, binning=_binning(args))
|
|
167
180
|
if pixel_stack.shape[2] != n_bins:
|
|
168
181
|
nb = pixel_stack.shape[2]
|
|
169
182
|
if nb > n_bins:
|
|
@@ -229,6 +242,7 @@ def fit_timelapse(ptu_dir, output_dir, args,
|
|
|
229
242
|
polish=not getattr(args, 'no_polish', False),
|
|
230
243
|
cost_function=getattr(args, 'cost_function', 'poisson'),
|
|
231
244
|
sigma_max=sigma_max,
|
|
245
|
+
**_window_kwargs(args),
|
|
232
246
|
)
|
|
233
247
|
plot_summed(
|
|
234
248
|
tile_decay, tile_summary, ptu, None,
|
|
@@ -430,6 +444,7 @@ def fit_zstack(ptu_dir, output_dir, args,
|
|
|
430
444
|
polish=not getattr(args, 'no_polish', False),
|
|
431
445
|
cost_function=getattr(args, 'cost_function', 'poisson'),
|
|
432
446
|
sigma_max=sigma_max,
|
|
447
|
+
**_window_kwargs(args),
|
|
433
448
|
)
|
|
434
449
|
print(f' Reference fit: {time.time() - t0:.1f} s')
|
|
435
450
|
taus_ns = global_summary.get('taus_ns', global_popt[:args.nexp] * 1e9)
|
|
@@ -489,7 +504,7 @@ def fit_zstack(ptu_dir, output_dir, args,
|
|
|
489
504
|
slice_dir = group_dir / f'z{z:04d}'
|
|
490
505
|
slice_dir.mkdir(exist_ok=True)
|
|
491
506
|
ptu = FLIMFile(str(ptu_path), verbose=False)
|
|
492
|
-
pixel_stack = ptu.raw_pixel_stack(channel=channel)
|
|
507
|
+
pixel_stack = ptu.raw_pixel_stack(channel=channel, binning=_binning(args))
|
|
493
508
|
if pixel_stack.shape[2] != n_bins:
|
|
494
509
|
nb = pixel_stack.shape[2]
|
|
495
510
|
if nb > n_bins:
|
|
@@ -555,6 +570,7 @@ def fit_zstack(ptu_dir, output_dir, args,
|
|
|
555
570
|
polish=not getattr(args, 'no_polish', False),
|
|
556
571
|
cost_function=getattr(args, 'cost_function', 'poisson'),
|
|
557
572
|
sigma_max=sigma_max,
|
|
573
|
+
**_window_kwargs(args),
|
|
558
574
|
)
|
|
559
575
|
plot_summed(
|
|
560
576
|
tile_decay, tile_summary, ptu, None,
|
|
@@ -86,7 +86,7 @@ class FOVPreviewPanel:
|
|
|
86
86
|
state='readonly', width=10)
|
|
87
87
|
self._cmap_combo.grid(row=1, column=4, sticky='w', padx=2)
|
|
88
88
|
self._cmap_combo['values'] = list(display.COLORMAPS.keys())
|
|
89
|
-
ttk.Button(ctrl_frame, text='Update', width=8, command=self.
|
|
89
|
+
ttk.Button(ctrl_frame, text='Update', width=8, command=self._on_update_display).grid(row=1, column=5, sticky='w', padx=2)
|
|
90
90
|
self._bv_show_decay = tk.BooleanVar(value=True)
|
|
91
91
|
ttk.Checkbutton(ctrl_frame, text='Show Decay Plot',
|
|
92
92
|
variable=self._bv_show_decay,
|
|
@@ -108,6 +108,22 @@ class FOVPreviewPanel:
|
|
|
108
108
|
value='amplitude', command=self._on_weighting_changed).pack(side='left')
|
|
109
109
|
ttk.Radiobutton(wt_frame, text='Intensity', variable=self._sv_tau_weighting,
|
|
110
110
|
value='intensity', command=self._on_weighting_changed).pack(side='left')
|
|
111
|
+
int_frame = ttk.Frame(ctrl_frame)
|
|
112
|
+
int_frame.grid(row=4, column=0, columnspan=6, sticky='w', pady=(4, 0))
|
|
113
|
+
ttk.Label(int_frame, text='Intensity:').pack(side='left', padx=(0, 4))
|
|
114
|
+
ttk.Label(int_frame, text='Min').pack(side='left')
|
|
115
|
+
self._sv_int_min = tk.StringVar()
|
|
116
|
+
ttk.Entry(int_frame, textvariable=self._sv_int_min, width=7).pack(side='left', padx=2)
|
|
117
|
+
ttk.Label(int_frame, text='Max').pack(side='left', padx=(6, 0))
|
|
118
|
+
self._sv_int_max = tk.StringVar()
|
|
119
|
+
ttk.Entry(int_frame, textvariable=self._sv_int_max, width=7).pack(side='left', padx=2)
|
|
120
|
+
ttk.Button(int_frame, text='Auto', width=6,
|
|
121
|
+
command=self._auto_intensity_scale).pack(side='left', padx=2)
|
|
122
|
+
self._sv_int_cmap = tk.StringVar(value='inferno')
|
|
123
|
+
int_combo = ttk.Combobox(int_frame, textvariable=self._sv_int_cmap, state='readonly',
|
|
124
|
+
width=9, values=display.INTENSITY_COLORMAPS)
|
|
125
|
+
int_combo.pack(side='left', padx=(6, 2))
|
|
126
|
+
int_combo.bind('<<ComboboxSelected>>', lambda _e: self._on_update_display())
|
|
111
127
|
self._ptu_path = None
|
|
112
128
|
self._lifetime_map = None
|
|
113
129
|
self._pixel_maps = None
|
|
@@ -119,6 +135,7 @@ class FOVPreviewPanel:
|
|
|
119
135
|
'gamma': 1.0,
|
|
120
136
|
'cmap': 'viridis',
|
|
121
137
|
}
|
|
138
|
+
self._int_display = {'vmin': None, 'vmax': None, 'cmap': 'inferno'}
|
|
122
139
|
self._n_exp = 1
|
|
123
140
|
self._irf_prompt = None
|
|
124
141
|
self._roi_manager = RoiManager()
|
|
@@ -140,6 +157,7 @@ class FOVPreviewPanel:
|
|
|
140
157
|
if not _keep_zstack:
|
|
141
158
|
self._hide_zstack()
|
|
142
159
|
self._lifetime_map = None
|
|
160
|
+
self._intensity_map = None
|
|
143
161
|
self._pixel_maps = None
|
|
144
162
|
self._cached_resid_data = None
|
|
145
163
|
if not ptu_path or not Path(ptu_path).exists():
|
|
@@ -158,8 +176,8 @@ class FOVPreviewPanel:
|
|
|
158
176
|
if is_image:
|
|
159
177
|
stack = ptu.pixel_stack(channel=None, binning=1)
|
|
160
178
|
intensity = stack.sum(axis=2)
|
|
161
|
-
|
|
162
|
-
self._ax_img
|
|
179
|
+
self._intensity_map = intensity
|
|
180
|
+
self._draw_intensity(self._ax_img, intensity)
|
|
163
181
|
else:
|
|
164
182
|
intensity = None
|
|
165
183
|
self._ax_img.text(0.5, 0.5, 'Point measurement\nno image to reconstruct',
|
|
@@ -187,6 +205,9 @@ class FOVPreviewPanel:
|
|
|
187
205
|
self._ax_resid.grid(True, alpha=0.3)
|
|
188
206
|
self._cached_resid_data = None
|
|
189
207
|
self._redraw_region_overlays()
|
|
208
|
+
if is_image:
|
|
209
|
+
self._sync_intensity_controls()
|
|
210
|
+
self._ctrl_frame.grid()
|
|
190
211
|
self._canvas_mpl.draw_idle()
|
|
191
212
|
n_photons = int(decay.sum())
|
|
192
213
|
if is_image:
|
|
@@ -275,8 +296,7 @@ class FOVPreviewPanel:
|
|
|
275
296
|
taus_fit = global_summary.get('taus_ns', [])
|
|
276
297
|
model = global_summary.get('model')
|
|
277
298
|
self._ax_img.clear()
|
|
278
|
-
|
|
279
|
-
self._ax_img.imshow(intensity_clipped, cmap='inferno', origin='upper')
|
|
299
|
+
self._draw_intensity(self._ax_img, intensity)
|
|
280
300
|
self._ax_img.set_title('Intensity', fontsize=9, fontweight='bold', color='white')
|
|
281
301
|
self._strip_image_axes(self._ax_img)
|
|
282
302
|
self._ax_flim.clear()
|
|
@@ -492,8 +512,7 @@ class FOVPreviewPanel:
|
|
|
492
512
|
return
|
|
493
513
|
intensity = tifffile.imread(str(intensity_files[0]))
|
|
494
514
|
self._ax_img.clear()
|
|
495
|
-
|
|
496
|
-
self._ax_img.imshow(intensity_clipped, cmap='inferno', origin='upper')
|
|
515
|
+
self._draw_intensity(self._ax_img, intensity)
|
|
497
516
|
self._ax_img.set_title('Stitched ROI', fontsize=9, fontweight='bold', color='white')
|
|
498
517
|
self._strip_image_axes(self._ax_img)
|
|
499
518
|
lifetime_data = None
|
|
@@ -595,6 +614,75 @@ class FOVPreviewPanel:
|
|
|
595
614
|
pass
|
|
596
615
|
self._lifetime_map = lifetime_map
|
|
597
616
|
self._update_flim_display()
|
|
617
|
+
def _intensity_limits(self, intensity):
|
|
618
|
+
import numpy as np
|
|
619
|
+
lo = self._int_display.get('vmin')
|
|
620
|
+
hi = self._int_display.get('vmax')
|
|
621
|
+
if lo is None:
|
|
622
|
+
lo = 0.0
|
|
623
|
+
if hi is None:
|
|
624
|
+
finite = np.asarray(intensity)[np.isfinite(intensity)]
|
|
625
|
+
hi = float(np.percentile(finite, 99)) if finite.size > 0 else 1.0
|
|
626
|
+
if hi <= lo:
|
|
627
|
+
hi = lo + 1.0
|
|
628
|
+
return lo, hi
|
|
629
|
+
|
|
630
|
+
def _draw_intensity(self, ax, intensity):
|
|
631
|
+
lo, hi = self._intensity_limits(intensity)
|
|
632
|
+
cmap = display.get_colormap(self._int_display.get('cmap', 'inferno'))
|
|
633
|
+
return ax.imshow(intensity, cmap=cmap, origin='upper', vmin=lo, vmax=hi)
|
|
634
|
+
|
|
635
|
+
def _read_intensity_controls(self):
|
|
636
|
+
def num(var):
|
|
637
|
+
text = var.get().strip()
|
|
638
|
+
if text == '':
|
|
639
|
+
return None
|
|
640
|
+
try:
|
|
641
|
+
return float(text)
|
|
642
|
+
except ValueError:
|
|
643
|
+
return None
|
|
644
|
+
self._int_display = {
|
|
645
|
+
'vmin': num(self._sv_int_min),
|
|
646
|
+
'vmax': num(self._sv_int_max),
|
|
647
|
+
'cmap': self._sv_int_cmap.get() or 'inferno',
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
def _sync_intensity_controls(self):
|
|
651
|
+
cs = self._int_display
|
|
652
|
+
self._sv_int_min.set('' if cs.get('vmin') is None else f"{cs['vmin']:g}")
|
|
653
|
+
self._sv_int_max.set('' if cs.get('vmax') is None else f"{cs['vmax']:g}")
|
|
654
|
+
self._sv_int_cmap.set(cs.get('cmap', 'inferno'))
|
|
655
|
+
|
|
656
|
+
def _sync_flim_controls(self):
|
|
657
|
+
cs = self._flim_color_scale
|
|
658
|
+
self._sv_tau_min.set('' if cs.get('vmin') is None else f"{cs['vmin']:.2f}")
|
|
659
|
+
self._sv_tau_max.set('' if cs.get('vmax') is None else f"{cs['vmax']:.2f}")
|
|
660
|
+
self._sv_gamma.set(str(cs.get('gamma', 1.0)))
|
|
661
|
+
self._sv_cmap.set(cs.get('cmap', 'viridis'))
|
|
662
|
+
|
|
663
|
+
def _update_intensity_display(self):
|
|
664
|
+
if self._intensity_map is None or not self._ax_img.get_visible():
|
|
665
|
+
return
|
|
666
|
+
title = self._ax_img.get_title() or 'Intensity'
|
|
667
|
+
self._ax_img.clear()
|
|
668
|
+
self._draw_intensity(self._ax_img, self._intensity_map)
|
|
669
|
+
self._ax_img.set_title(title, fontsize=9, fontweight='bold', color='white')
|
|
670
|
+
self._strip_image_axes(self._ax_img)
|
|
671
|
+
self._redraw_region_overlays()
|
|
672
|
+
self._canvas_mpl.draw_idle()
|
|
673
|
+
|
|
674
|
+
def _auto_intensity_scale(self):
|
|
675
|
+
self._sv_int_min.set('')
|
|
676
|
+
self._sv_int_max.set('')
|
|
677
|
+
self._on_update_display()
|
|
678
|
+
|
|
679
|
+
def _on_update_display(self):
|
|
680
|
+
self._read_intensity_controls()
|
|
681
|
+
self._update_intensity_display()
|
|
682
|
+
self._update_flim_display()
|
|
683
|
+
if self._lifetime_map is None:
|
|
684
|
+
self._save_color_scale_update()
|
|
685
|
+
|
|
598
686
|
def _auto_detect_scale(self):
|
|
599
687
|
import numpy as np
|
|
600
688
|
if self._lifetime_map is None:
|
|
@@ -677,6 +765,7 @@ class FOVPreviewPanel:
|
|
|
677
765
|
session_data = {key: existing_data[key].item() if existing_data[key].ndim == 0 else existing_data[key]
|
|
678
766
|
for key in existing_data.files}
|
|
679
767
|
session_data['fov_color_scale'] = json.dumps(self._flim_color_scale)
|
|
768
|
+
session_data['fov_intensity_scale'] = json.dumps(self._int_display)
|
|
680
769
|
np.savez_compressed(session_file, **session_data)
|
|
681
770
|
print(f"[Color Scale] ✓ Saved to {session_file.name}")
|
|
682
771
|
except Exception as e:
|
|
@@ -706,6 +795,7 @@ class FOVPreviewPanel:
|
|
|
706
795
|
if self._intensity_map is not None:
|
|
707
796
|
session_data['fov_intensity_map'] = self._intensity_map
|
|
708
797
|
session_data['fov_color_scale'] = json.dumps(self._flim_color_scale)
|
|
798
|
+
session_data['fov_intensity_scale'] = json.dumps(self._int_display)
|
|
709
799
|
session_data['fov_n_exp'] = self._n_exp
|
|
710
800
|
if self._ptu_path:
|
|
711
801
|
session_data['fov_ptu_path'] = self._ptu_path
|
|
@@ -927,9 +1017,7 @@ class FOVPreviewPanel:
|
|
|
927
1017
|
_ax.set_facecolor('black')
|
|
928
1018
|
if self._ax_img.get_visible() and self._intensity_map is not None:
|
|
929
1019
|
import numpy as np
|
|
930
|
-
|
|
931
|
-
np.percentile(self._intensity_map, 99))
|
|
932
|
-
self._ax_img.imshow(intensity_clipped, cmap='inferno', origin='upper')
|
|
1020
|
+
self._draw_intensity(self._ax_img, self._intensity_map)
|
|
933
1021
|
self._ax_img.set_title(img_title, fontsize=9, fontweight='bold', color='white')
|
|
934
1022
|
self._strip_image_axes(self._ax_img)
|
|
935
1023
|
elif self._ax_img.get_visible():
|