napari-musa 1.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.
@@ -0,0 +1,463 @@
1
+ """ """
2
+
3
+ import sys
4
+ from os.path import dirname
5
+
6
+ sys.path.append(dirname(dirname(__file__)))
7
+ import napari
8
+ import numpy as np
9
+ import pyqtgraph as pg
10
+ from magicgui.widgets import (
11
+ CheckBox,
12
+ ComboBox,
13
+ Container,
14
+ FloatSpinBox,
15
+ PushButton,
16
+ SpinBox,
17
+ )
18
+ from matplotlib.backends.backend_qt5agg import (
19
+ FigureCanvasQTAgg as FigureCanvas,
20
+ )
21
+ from matplotlib.backends.backend_qt5agg import (
22
+ NavigationToolbar2QT as NavigationToolbar,
23
+ )
24
+ from matplotlib.figure import Figure
25
+ from napari.utils.notifications import show_info, show_warning
26
+ from qtpy.QtWidgets import (
27
+ QGroupBox,
28
+ QHBoxLayout,
29
+ QScrollArea,
30
+ QVBoxLayout,
31
+ QWidget,
32
+ )
33
+
34
+ from napari_musa.modules.functions import (
35
+ RGB_to_hex,
36
+ UMAP_analysis,
37
+ reduce_spatial_dimension_dwt_inverse,
38
+ )
39
+
40
+
41
+ class UMAP(QWidget):
42
+ """ """
43
+
44
+ def __init__(self, viewer: napari.Viewer, data, plot):
45
+ """ """
46
+ super().__init__()
47
+ self.viewer = viewer
48
+ self.data = data
49
+ self.plot = plot
50
+ # Configure the scroll area
51
+ scroll = QScrollArea()
52
+ scroll.setWidgetResizable(True)
53
+ content_widget = QWidget() # Container widget
54
+ content_layout = QVBoxLayout(
55
+ content_widget
56
+ ) # Vertical layout: organize widgets from top to bottom
57
+ # Configure UI
58
+ self.createUI(
59
+ content_layout
60
+ ) # The function to create the UI that fills the content_layout
61
+ # Configure principal layout
62
+ scroll.setWidget(
63
+ content_widget
64
+ ) # content_widget is a content of scroll area
65
+ main_layout = QVBoxLayout(self)
66
+ main_layout.addWidget(scroll)
67
+ self.setLayout(main_layout)
68
+
69
+ def createUI(self, layout):
70
+ """Create the components for the UI"""
71
+ layout.addWidget(self.create_umap_controls_box())
72
+ layout.addWidget(self.creare_scatterplot_box())
73
+ layout.addWidget(self.creare_plot_box())
74
+ layout.addWidget(self.create_inverse_reduction_box())
75
+
76
+ # %% Creation of UI boxes
77
+
78
+ def create_umap_controls_box(self):
79
+ """ """
80
+ controls_box = QGroupBox("UMAP Parameters")
81
+ # rgb_box.setFixedHeight(200)
82
+ controls_layout = QVBoxLayout()
83
+ controls_layout.addSpacing(10)
84
+ # Elements
85
+ row1 = QHBoxLayout()
86
+ self.reduced_dataset = CheckBox(text="Reduced dataset")
87
+ self.masked_dataset = CheckBox(text="Masked dataset")
88
+ self.modes_combobox = ComboBox(
89
+ choices=self.data.modes, label="Select the imaging mode"
90
+ )
91
+ row1.addWidget(self.reduced_dataset.native)
92
+ row1.addWidget(self.modes_combobox.native)
93
+ controls_layout.addLayout(row1)
94
+
95
+ row2 = QHBoxLayout()
96
+ row2.addWidget(self.masked_dataset.native)
97
+ controls_layout.addLayout(row2)
98
+
99
+ self.downsampling_spinbox = SpinBox(
100
+ min=1, max=6, value=1, step=1, name="Downsampling"
101
+ )
102
+ self.metric_dropdown = ComboBox(
103
+ choices=[
104
+ "cosine",
105
+ "euclidean",
106
+ "correlation",
107
+ "mahalanobis",
108
+ "seuclidean ",
109
+ "braycurtis",
110
+ ],
111
+ label="Select the metric",
112
+ )
113
+ self.n_neighbors_spinbox = SpinBox(
114
+ min=5, max=500, value=20, step=5, name="N Neighbours"
115
+ )
116
+ self.min_dist_spinbox = FloatSpinBox(
117
+ min=0.0, max=1.0, value=0.0, step=0.1, name="Min dist"
118
+ )
119
+ self.spread_spinbox = FloatSpinBox(
120
+ min=1.0, max=3.0, value=1.0, step=0.1, name="Spread"
121
+ )
122
+ self.init_dropdown = ComboBox(
123
+ choices=["spectral", "pca", "tswspectral"], label="Init"
124
+ )
125
+ self.densmap = CheckBox(text="Densmap")
126
+ controls_layout.addWidget(
127
+ Container(
128
+ widgets=[
129
+ self.downsampling_spinbox,
130
+ self.metric_dropdown,
131
+ self.n_neighbors_spinbox,
132
+ self.min_dist_spinbox,
133
+ self.spread_spinbox,
134
+ self.init_dropdown,
135
+ self.densmap,
136
+ ]
137
+ ).native
138
+ )
139
+
140
+ run_btn = PushButton(text="Run UMAP")
141
+ run_btn.clicked.connect(self.run_umap)
142
+ controls_layout.addWidget(run_btn.native)
143
+
144
+ UMAP_loyout_perform = QHBoxLayout()
145
+ self.UMAP_colorRGB = CheckBox(text="Scatterplot with True RGB")
146
+ show_btn = PushButton(text="Show UMAP scatterplot")
147
+ show_btn.clicked.connect(self.show_umap_scatter)
148
+ UMAP_loyout_perform.addWidget(
149
+ Container(
150
+ widgets=[self.UMAP_colorRGB, show_btn], layout="horizontal"
151
+ ).native
152
+ )
153
+ controls_layout.addLayout(UMAP_loyout_perform)
154
+ controls_box.setLayout(controls_layout)
155
+ return controls_box
156
+
157
+ def creare_scatterplot_box(self):
158
+ """ """
159
+ scatterplot_box = QGroupBox("UMAP Scatterplot")
160
+ layout = QVBoxLayout()
161
+ layout.addSpacing(10)
162
+ self.umap_plot = pg.PlotWidget()
163
+ self.plot.setup_scatterplot(self.umap_plot)
164
+ # Add control buttons for scatter plot interaction
165
+ btn_layout = QHBoxLayout()
166
+ for icon, func in [
167
+ ("fa5s.home", lambda: self.umap_plot.getViewBox().autoRange()),
168
+ (
169
+ "fa5s.draw-polygon",
170
+ lambda: self.plot.polygon_selection(self.umap_plot),
171
+ ),
172
+ ("ri.add-box-fill", self.handle_selection),
173
+ (
174
+ "mdi6.image-edit",
175
+ lambda: self.plot.save_image_button(self.umap_plot),
176
+ ),
177
+ ]:
178
+ btn = self.plot.create_button(icon)
179
+ btn.clicked.connect(func)
180
+ btn_layout.addWidget(btn)
181
+ self.point_size = SpinBox(
182
+ min=1, max=100, value=1, step=1, name="Point size"
183
+ )
184
+ show_areas_on_scatterplot_btn = PushButton(
185
+ text="Show areas of Label Layer on scatteplot"
186
+ )
187
+ show_areas_on_scatterplot_btn.clicked.connect(
188
+ self.show_areas_on_scatterplot_btn_f
189
+ )
190
+ btn_layout.addSpacing(30)
191
+ btn_layout.addWidget(Container(widgets=[self.point_size]).native)
192
+ layout.addLayout(btn_layout)
193
+ layout.addWidget(self.umap_plot)
194
+ layout.addWidget(show_areas_on_scatterplot_btn.native)
195
+ scatterplot_box.setLayout(layout)
196
+ return scatterplot_box
197
+
198
+ def creare_plot_box(self):
199
+ """ """
200
+ meanplot_box = QGroupBox("Mean plot")
201
+ layout = QVBoxLayout()
202
+ layout.addSpacing(20)
203
+ layout = QVBoxLayout()
204
+ self.mean_plot = FigureCanvas(Figure(figsize=(5, 3)))
205
+ self.mean_plot.setMinimumSize(300, 450)
206
+ self.mean_plot_toolbar = NavigationToolbar(self.mean_plot, self)
207
+ self.plot.customize_toolbar(self.mean_plot_toolbar)
208
+ self.plot.setup_plot(self.mean_plot)
209
+
210
+ mean_spec_btn = PushButton(text="Mean Spectrum")
211
+ self.std_checkbox = CheckBox(text="Plot Std Dev")
212
+ self.norm_checkbox = CheckBox(text="Normalize")
213
+ self.derivative_checkbox = CheckBox(text="Derivative")
214
+
215
+ mean_spec_btn.clicked.connect(
216
+ lambda: self.plot.show_plot(
217
+ self.mean_plot,
218
+ mode=self.modes_combobox.value,
219
+ std_flag=self.std_checkbox.value,
220
+ norm_flag=self.norm_checkbox.value,
221
+ reduced_dataset_flag=self.reduced_dataset.value,
222
+ derivative_flag=self.derivative_checkbox.value,
223
+ )
224
+ )
225
+
226
+ controls = [
227
+ self.std_checkbox,
228
+ self.norm_checkbox,
229
+ self.derivative_checkbox,
230
+ mean_spec_btn,
231
+ ]
232
+ layout.addWidget(Container(widgets=controls).native)
233
+ layout.addWidget(self.mean_plot)
234
+ layout.addWidget(self.mean_plot_toolbar)
235
+
236
+ # Export button
237
+ export_btn = PushButton(text="Export spectra")
238
+ export_btn.clicked.connect(
239
+ lambda: (
240
+ self.plot.show_plot(
241
+ self.mean_plot,
242
+ mode=self.modes_combobox.value,
243
+ std_flag=self.std_checkbox.value,
244
+ norm_flag=self.norm_checkbox.value,
245
+ reduced_dataset_flag=self.reduced_dataset.value,
246
+ export_txt_flag=True,
247
+ )
248
+ )
249
+ )
250
+ layout.addWidget(Container(widgets=[export_btn]).native)
251
+ meanplot_box.setLayout(layout)
252
+ return meanplot_box
253
+
254
+ def create_inverse_reduction_box(self):
255
+ """ """
256
+ inverse_reduction_box = QGroupBox("Inverse Dimensionality Reduction")
257
+ # rgb_box.setFixedHeight(200)
258
+ inverse_reduction_layout = QVBoxLayout()
259
+ inverse_reduction_layout.addSpacing(10)
260
+ # Elements
261
+ inverse_reduction_btn = PushButton(text="Perform inverse reduction")
262
+ inverse_reduction_btn.clicked.connect(self.inverse_reduction_btn_f)
263
+ inverse_reduction_layout.addWidget(inverse_reduction_btn.native)
264
+
265
+ inverse_reduction_box.setLayout(inverse_reduction_layout)
266
+ return inverse_reduction_box
267
+
268
+ def run_umap(self):
269
+ """Perform UMAP"""
270
+ mode = self.modes_combobox.value
271
+ if self.masked_dataset.value:
272
+ dataset = self.data.hypercubes_masked[mode]
273
+ data_reshaped = dataset.reshape(
274
+ dataset.shape[0] * dataset.shape[1], -1
275
+ )
276
+ self.points = np.array(
277
+ np.where(~np.isnan(np.mean(data_reshaped, axis=1)))
278
+ ).flatten()
279
+ elif self.reduced_dataset.value:
280
+ dataset = self.data.hypercubes_red[mode]
281
+ self.points = []
282
+ else:
283
+ dataset = self.data.hypercubes[mode]
284
+ self.points = []
285
+
286
+ self.data.umap_maps[mode] = UMAP_analysis(
287
+ dataset,
288
+ downsampling=self.downsampling_spinbox.value,
289
+ points=self.points,
290
+ metric=self.metric_dropdown.value,
291
+ n_neighbors=self.n_neighbors_spinbox.value,
292
+ min_dist=self.min_dist_spinbox.value,
293
+ spread=self.spread_spinbox.value,
294
+ init=self.init_dropdown.value,
295
+ densmap=self.densmap.value,
296
+ random_state=42,
297
+ )
298
+ show_info("UMAP analysis completed!")
299
+
300
+ def show_umap_scatter(self):
301
+ """Plot UMAP scatter plot"""
302
+ mode = self.modes_combobox.value
303
+ self.umap_data = self.data.umap_maps[mode]
304
+ if self.UMAP_colorRGB.value:
305
+ if self.reduced_dataset.value:
306
+ colors = np.array(RGB_to_hex(self.data.rgb_red[mode])).reshape(
307
+ -1
308
+ )
309
+ elif self.masked_dataset.value:
310
+ colors = np.array(
311
+ RGB_to_hex(self.data.rgb_masked[mode])
312
+ ).reshape(-1)
313
+ else:
314
+ colors = np.array(RGB_to_hex(self.data.rgb[mode])).reshape(-1)
315
+ else:
316
+ colors = pg.mkBrush("#262930")
317
+
318
+ print("Colors: \n", colors)
319
+ self.plot.show_scatterplot(
320
+ self.umap_plot,
321
+ self.umap_data,
322
+ colors,
323
+ self.points,
324
+ self.point_size.value,
325
+ )
326
+
327
+ def handle_selection(self):
328
+ """Handle polygon selection and create label layer"""
329
+ mode = self.modes_combobox.value
330
+ if self.reduced_dataset.value and not self.masked_dataset.value:
331
+ dataset = self.data.hypercubes_red[mode]
332
+ self.points = []
333
+ elif self.masked_dataset.value or (
334
+ self.reduced_dataset.value and self.masked_dataset.value
335
+ ):
336
+ dataset = self.data.hypercubes_masked[mode]
337
+ data_reshaped = dataset.reshape(
338
+ dataset.shape[0] * dataset.shape[1], -1
339
+ )
340
+ self.points = np.array(
341
+ np.where(~np.isnan(np.mean(data_reshaped, axis=1)))
342
+ ).flatten()
343
+ else:
344
+ dataset = self.data.hypercubes[mode]
345
+ self.points = []
346
+ self.plot.show_selected_points(
347
+ self.umap_data,
348
+ dataset,
349
+ mode,
350
+ self.points,
351
+ )
352
+
353
+ def show_areas_on_scatterplot_btn_f(self):
354
+ mode = self.modes_combobox.value
355
+ selected_layer = self.viewer.layers.selection.active
356
+ # Check if the selected layer is a label layer
357
+ if not isinstance(selected_layer, napari.layers.Labels):
358
+ show_warning(
359
+ "⚠️ The selected layer is not a label layer. Please, select a label layer."
360
+ )
361
+ return
362
+ labels_data = selected_layer.data
363
+ if labels_data is None or np.all(
364
+ labels_data == 0
365
+ ): # check if all elements are 0
366
+ show_warning("⚠️ The selected label layer is empty")
367
+ return
368
+ # num_classes = int(labels_data.max())
369
+ colormap = np.array(selected_layer.colormap.colors)
370
+ print(colormap)
371
+ print(colormap.shape)
372
+ # colormap[0] = [0, 0, 0, 0.5]
373
+ rgb_image = colormap[labels_data] # fancy indexing
374
+ if self.reduced_dataset.value:
375
+ dataset = self.data.hypercubes_red[mode]
376
+ rgb_image = rgb_image[: dataset.shape[0], : dataset.shape[1], :]
377
+ print(rgb_image)
378
+ print(rgb_image.shape)
379
+ colors = RGB_to_hex(rgb_image)
380
+
381
+ self.plot.show_scatterplot(
382
+ self.umap_plot,
383
+ self.umap_data,
384
+ colors.reshape(-1),
385
+ self.points,
386
+ self.point_size.value,
387
+ )
388
+
389
+ def inverse_reduction_btn_f(self):
390
+ mode = self.modes_combobox.value
391
+ selected_layer = self.viewer.layers.selection.active
392
+
393
+ if isinstance(selected_layer, napari.layers.Labels):
394
+ label_data = selected_layer.data
395
+ reduced_data = self.data.hypercubes_spatial_red[mode]
396
+ print(label_data.shape)
397
+ label_data = label_data[
398
+ : reduced_data.shape[0], : reduced_data.shape[1]
399
+ ]
400
+ num_classes = int(label_data.max())
401
+ # colormap = np.array(selected_layer.colormap.colors)
402
+ reduced_data_masked = np.zeros(
403
+ (label_data.shape[0], label_data.shape[1], num_classes)
404
+ )
405
+ print(self.data.hypercubes_spatial_red_params[mode])
406
+ print(self.data.hypercubes_spatial_red_params[mode][0])
407
+ LH = reduced_data_masked
408
+ HL = reduced_data_masked
409
+ HH = reduced_data_masked
410
+ for idx in range(num_classes):
411
+ points = np.where(label_data == idx + 1, 1, 0).astype(float)
412
+ print("Points shape:", points.shape)
413
+ reduced_data_masked[:, :, idx] = (
414
+ np.mean(reduced_data, axis=2) * points
415
+ )
416
+ LH[:, :, idx] = (
417
+ np.mean(
418
+ self.data.hypercubes_spatial_red_params[mode][0],
419
+ axis=2,
420
+ )
421
+ * points
422
+ )
423
+ HL[:, :, idx] = (
424
+ np.mean(
425
+ self.data.hypercubes_spatial_red_params[mode][1],
426
+ axis=2,
427
+ )
428
+ * points
429
+ )
430
+ HH[:, :, idx] = (
431
+ np.mean(
432
+ self.data.hypercubes_spatial_red_params[mode][2],
433
+ axis=2,
434
+ )
435
+ * points
436
+ )
437
+ reconstructed_data_masked = reduce_spatial_dimension_dwt_inverse(
438
+ reduced_data_masked,
439
+ (LH, HL, HH, self.data.hypercubes_spatial_red_params[mode][3]),
440
+ )
441
+ masks = reconstructed_data_masked != 0 # boolean
442
+ H, W, K = masks.shape
443
+ labels_reconstructed = np.zeros((H, W), dtype=np.int32)
444
+ for k in range(
445
+ K
446
+ ): # first mask wins on the others, but with UMAP i should not have overlapping areas
447
+ sel = masks[:, :, k] & (labels_reconstructed == 0)
448
+ labels_reconstructed[sel] = k + 1
449
+ lenx, leny, lenwl = self.data.hypercubes[mode].shape
450
+ labels_reconstructed = labels_reconstructed[:lenx, :leny]
451
+ # K = colormap.shape[0] - 1
452
+ # color_dict = {i: colormap[i, :3] for i in range(1, K+1)}
453
+ self.viewer.add_labels(
454
+ labels_reconstructed,
455
+ name=str(mode) + " - Inverse Reduced Selection",
456
+ )
457
+
458
+ else:
459
+ show_warning(
460
+ "⚠️ The selected layer is not a label layer. Please, select an image layer."
461
+ )
462
+ return
463
+ return
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '1.0.0'
32
+ __version_tuple__ = version_tuple = (1, 0, 0)
33
+
34
+ __commit_id__ = commit_id = None
napari_musa/main.py ADDED
@@ -0,0 +1,150 @@
1
+ """ """
2
+
3
+ import napari
4
+ import napari as np
5
+ from qtpy.QtCore import QTimer
6
+
7
+ from napari_musa.modules.data import Data
8
+ from napari_musa.modules.plot import Plot
9
+ from napari_musa.Widget_DataManager import DataManager
10
+ from napari_musa.Widgets_DataVisualization import DataVisualization
11
+ from napari_musa.Widgets_EndmembersExtraction import EndmembersExtraction
12
+ from napari_musa.Widgets_Fusion import Fusion
13
+ from napari_musa.Widgets_NMF import NMF
14
+ from napari_musa.Widgets_PCA import PCA
15
+ from napari_musa.Widgets_UMAP import UMAP
16
+
17
+
18
+ def setup_connections(self):
19
+ """ """
20
+ self.viewer.text_overlay.visible = True
21
+
22
+ def on_step_change(event=None):
23
+ layer = self.viewer.layers.selection.active
24
+ if layer and isinstance(layer, napari.layers.Image):
25
+ name = layer.name
26
+ if "NNLS" in name or "SAM" in name:
27
+ self.endmextr_widget.update_number_H()
28
+ elif "NMF" in name:
29
+ self.nmf_widget.update_number_H()
30
+ elif "PCA" in name:
31
+ self.pca_widget.update_number_H()
32
+ else:
33
+ self.datamanager_widget.update_wl()
34
+
35
+ # collega la funzione wrapper
36
+ self.viewer.dims.events.current_step.connect(on_step_change)
37
+
38
+ # resto invariato
39
+ self.viewer.layers.selection.events.active.connect(
40
+ self.datamanager_widget.layer_auto_selection
41
+ )
42
+
43
+
44
+ def on_new_layer(self, event):
45
+ layer = event.value
46
+ if (
47
+ isinstance(layer, napari.layers.Labels) and layer.data.ndim == 3
48
+ ): # (C, Y, X)
49
+
50
+ def replace():
51
+ if layer in self.viewer.layers: # solo se esiste ancora
52
+ new_labels = np.zeros(layer.data.shape[1:], dtype=np.int32)
53
+ name = layer.name
54
+ self.viewer.layers.remove(layer)
55
+ self.viewer.add_labels(new_labels, name=name)
56
+
57
+ QTimer.singleShot(0, replace)
58
+
59
+
60
+ def update_modes_comboboxes(self):
61
+ for widget in [
62
+ self.datamanager_widget,
63
+ self.umap_widget,
64
+ self.fusion_widget,
65
+ self.endmextr_widget,
66
+ self.pca_widget,
67
+ self.nmf_widget,
68
+ ]:
69
+ for attr_name in dir(widget):
70
+ if attr_name.startswith("modes_combobox"):
71
+ if widget == self.fusion_widget:
72
+ widget.modes_combobox_1.choices = self.data.modes
73
+ widget.modes_combobox_2.choices = self.data.modes
74
+ widget.modes_combobox_3.choices = self.data.modes
75
+ else:
76
+ current_value = widget.modes_combobox.value
77
+ widget.modes_combobox.choices = self.data.modes
78
+ if current_value not in self.data.modes:
79
+ widget.modes_combobox.value = current_value
80
+
81
+
82
+ def run_napari_app():
83
+ """Add widgets to the viewer"""
84
+ try:
85
+ viewer = napari.current_viewer()
86
+ except AttributeError:
87
+ viewer = napari.Viewer()
88
+
89
+ # WIDGETS
90
+ data = Data()
91
+ plot_datavisualization = Plot(viewer=viewer, data=data)
92
+ datamanager_widget = DataManager(viewer, data)
93
+ datavisualization_widget = DataVisualization(
94
+ viewer, data, plot_datavisualization, datamanager_widget
95
+ )
96
+ fusion_widget = Fusion(viewer, data)
97
+
98
+ plot_umap = Plot(viewer=viewer, data=data)
99
+ umap_widget = UMAP(viewer, data, plot_umap)
100
+ nmf_widget = NMF(viewer, data, plot_umap)
101
+ endmextr_widget = EndmembersExtraction(viewer, data, plot_umap)
102
+ plot_pca = Plot(viewer=viewer, data=data)
103
+ pca_widget = PCA(viewer, data, plot_pca)
104
+
105
+ datamanager_widget.mode_added.connect(update_modes_comboboxes)
106
+
107
+ # Add widget as dock
108
+ datamanager_dock = viewer.window.add_dock_widget(
109
+ datamanager_widget, name="Data Manager", area="right"
110
+ )
111
+ datavisualization_dock = viewer.window.add_dock_widget(
112
+ datavisualization_widget, name="Data Visualization", area="right"
113
+ )
114
+ fusion_dock = viewer.window.add_dock_widget(
115
+ fusion_widget, name="Fusion", area="right"
116
+ )
117
+ umap_dock = viewer.window.add_dock_widget(
118
+ umap_widget, name="UMAP", area="right"
119
+ )
120
+ endmextr_dock = viewer.window.add_dock_widget(
121
+ endmextr_widget, name="Endmembers", area="right"
122
+ )
123
+ pca_dock = viewer.window.add_dock_widget(
124
+ pca_widget, name="PCA", area="right"
125
+ )
126
+ nmf_dock = viewer.window.add_dock_widget(
127
+ nmf_widget, name="NMF", area="right"
128
+ )
129
+
130
+ # Tabify the widgets
131
+ viewer.window._qt_window.tabifyDockWidget(
132
+ datamanager_dock, datavisualization_dock
133
+ )
134
+ viewer.window._qt_window.tabifyDockWidget(
135
+ datavisualization_dock, fusion_dock
136
+ )
137
+ viewer.window._qt_window.tabifyDockWidget(fusion_dock, umap_dock)
138
+ viewer.window._qt_window.tabifyDockWidget(umap_dock, pca_dock)
139
+ viewer.window._qt_window.tabifyDockWidget(pca_dock, endmextr_dock)
140
+ viewer.window._qt_window.tabifyDockWidget(endmextr_dock, nmf_dock)
141
+ # Text overlay in the viewer
142
+ viewer.text_overlay.visible = True
143
+
144
+ setup_connections()
145
+ viewer.layers.events.inserted.connect(on_new_layer)
146
+ viewer.layers.selection.events.active.connect(
147
+ datamanager_widget.on_layer_selected
148
+ )
149
+
150
+ return None # Non serve restituire nulla
Binary file
@@ -0,0 +1,48 @@
1
+ """ """
2
+
3
+ import sys
4
+ from os.path import dirname
5
+
6
+ sys.path.append(dirname(dirname(__file__)))
7
+
8
+ # print("here: ", dirname(dirname(__file__))) #print for the directory folder
9
+
10
+
11
+ class Data:
12
+ """ """
13
+
14
+ def __init__(self):
15
+ """ """
16
+ self.filepath = ""
17
+ self.hypercubes = {}
18
+ self.hypercubes_red = {}
19
+ self.hypercubes_spatial_red = {} # For the spectra
20
+ self.hypercubes_spatial_red_params = {}
21
+ self.hypercubes_masked = {}
22
+ self.wls = {}
23
+ self.rgb = {} # Dictionary needed for the fusion process
24
+ self.rgb_red = {} # Dictionary needed for the fusion process
25
+ self.rgb_masked = {}
26
+ self.wls_red = {}
27
+ self.pca_maps = {}
28
+ self.nmf_maps = {}
29
+ self.nmf_basis = {}
30
+ self.svd_maps = {}
31
+ self.umap_maps = {} # valutare se da togliere.
32
+ self.vertex_basis = {}
33
+ self.nnls_maps = {}
34
+ self.sam_maps = {}
35
+ self.modes = [
36
+ "Reflectance",
37
+ "PL",
38
+ "PL - 2",
39
+ "Raman",
40
+ "Fused",
41
+ "-",
42
+ ] # fused: self.modes.append
43
+ self.mode = None # valutare se da togliere con nuovo widget
44
+ self.wl_value = 0
45
+ self.fusion_modes = []
46
+
47
+
48
+ # %% Other functions