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,257 @@
1
+ """Widget to visualize the data"""
2
+
3
+ import sys
4
+ from os.path import dirname
5
+
6
+ sys.path.append(dirname(dirname(__file__)))
7
+
8
+ import napari
9
+ from magicgui.widgets import (
10
+ CheckBox,
11
+ Container,
12
+ Label,
13
+ PushButton,
14
+ SpinBox,
15
+ )
16
+ from matplotlib.backends.backend_qt5agg import (
17
+ FigureCanvasQTAgg as FigureCanvas,
18
+ )
19
+ from matplotlib.backends.backend_qt5agg import (
20
+ NavigationToolbar2QT as NavigationToolbar,
21
+ )
22
+ from matplotlib.figure import Figure
23
+ from qtpy.QtWidgets import (
24
+ QGroupBox,
25
+ QHBoxLayout,
26
+ QScrollArea,
27
+ QVBoxLayout,
28
+ QWidget,
29
+ )
30
+
31
+ from napari_musa.modules.functions import (
32
+ HSI2RGB,
33
+ falseRGB,
34
+ )
35
+
36
+
37
+ class DataVisualization(QWidget): # From QWidget
38
+ """ """
39
+
40
+ def __init__(self, viewer: napari.Viewer, data, plot, datamanager):
41
+ """ """
42
+ super().__init__() # Initialize the QWidget
43
+ self.viewer = viewer
44
+ self.data = data
45
+ self.plot = plot
46
+ self.datamanager = datamanager
47
+ # Configure the scroll area
48
+ scroll = QScrollArea()
49
+ scroll.setWidgetResizable(True)
50
+ content_widget = QWidget() # Container widget
51
+ content_layout = QVBoxLayout(
52
+ content_widget
53
+ ) # Vertical layout: organize widgets from top to bottom
54
+ # Configure UI
55
+ self.createUI(
56
+ content_layout
57
+ ) # The function to create the UI that fills the content_layout
58
+ # Configure principal layout
59
+ scroll.setWidget(
60
+ content_widget
61
+ ) # content_widget is a content of scroll area
62
+ main_layout = QVBoxLayout(self)
63
+ main_layout.addWidget(scroll)
64
+ self.setLayout(main_layout)
65
+
66
+ def createUI(self, layout):
67
+ """Create the components for the UI"""
68
+ layout.addWidget(self.create_rgb_box())
69
+ layout.addWidget(self.plot_box())
70
+
71
+ # %% Creation of UI boxes
72
+ # RGB BOX
73
+ def create_rgb_box(self):
74
+ """Create box and elements for file opening"""
75
+ rgb_box = QGroupBox("Create RGB")
76
+ # rgb_box.setFixedHeight(200)
77
+ true_rgb_layout = QVBoxLayout()
78
+ true_rgb_layout.addSpacing(10)
79
+ # Elements
80
+ true_rgb_btn = PushButton(text="Create True RGB")
81
+ true_rgb_btn.clicked.connect(self.true_rgb_btn_f)
82
+
83
+ # Add widgets to the layout
84
+ true_rgb_layout.addWidget(
85
+ Container(widgets=[true_rgb_btn], layout="horizontal").native
86
+ )
87
+ true_rgb_layout.addSpacing(30)
88
+ #
89
+ # FALSE RGB
90
+ false_rgb_layout = QVBoxLayout()
91
+ false_rgb_layout.addSpacing(5)
92
+ R_layout, self.R_min_spinbox, self.R_max_spinbox = (
93
+ self.create_channel_falsergb_section([650, 700], "R")
94
+ )
95
+ false_rgb_layout.addLayout(R_layout)
96
+ false_rgb_layout.addSpacing(5)
97
+ #
98
+ G_layout, self.G_min_spinbox, self.G_max_spinbox = (
99
+ self.create_channel_falsergb_section([550, 600], "G")
100
+ )
101
+ false_rgb_layout.addLayout(G_layout)
102
+ false_rgb_layout.addSpacing(5)
103
+ #
104
+ B_layout, self.B_min_spinbox, self.B_max_spinbox = (
105
+ self.create_channel_falsergb_section([450, 500], "B")
106
+ )
107
+ false_rgb_layout.addLayout(B_layout)
108
+ false_rgb_layout.addSpacing(5)
109
+ # False RGB button
110
+ false_rgb_btn_layout = QHBoxLayout()
111
+ false_rgb_btn = PushButton(text="Create False RGB")
112
+ false_rgb_btn.clicked.connect(self.false_rgb_btn_f)
113
+ false_rgb_btn_layout.addWidget(
114
+ Container(widgets=[false_rgb_btn]).native
115
+ )
116
+ #
117
+ false_rgb_layout.addLayout(false_rgb_btn_layout)
118
+ true_rgb_layout.addLayout(false_rgb_layout)
119
+ rgb_box.setLayout(true_rgb_layout)
120
+ return rgb_box
121
+
122
+ def create_channel_falsergb_section(self, value, label_name):
123
+ """ """
124
+ channel_layout = QHBoxLayout()
125
+ label = Label(value=label_name)
126
+ # label.native.setFixedWidth(20)
127
+ # channel_layout.addSpacing(50)
128
+ channel_layout.addWidget(label.native)
129
+ min_spinbox = SpinBox(
130
+ min=0, max=2500, step=1, value=value[0], label=label_name
131
+ )
132
+ max_spinbox = SpinBox(min=0, max=2500, step=1, value=value[1])
133
+ channel_layout.addSpacing(50)
134
+ channel_layout.addWidget(min_spinbox.native)
135
+ channel_layout.addSpacing(50)
136
+ channel_layout.addWidget(max_spinbox.native)
137
+
138
+ return channel_layout, min_spinbox, max_spinbox
139
+
140
+ def plot_box(self):
141
+ """Plot of the mean spectrum"""
142
+ plot_box = QGroupBox("Plot of mean spectrum")
143
+ plot_layout = QVBoxLayout()
144
+ plot_layout.addSpacing(10)
145
+ # Plot
146
+ plot_layout_graph = self.create_plot_graph_section()
147
+ plot_layout.addLayout(plot_layout_graph)
148
+ # Export
149
+ plot_layout_export_txt = self.create_plot_export_section()
150
+ plot_layout.addLayout(plot_layout_export_txt)
151
+ plot_box.setLayout(plot_layout)
152
+ return plot_box
153
+
154
+ def create_plot_graph_section(self):
155
+ """Mean spectrum"""
156
+ plot_layout = QVBoxLayout()
157
+
158
+ self.meanspec_plot = FigureCanvas(Figure(figsize=(5, 3)))
159
+ self.meanspec_plot.setMinimumSize(300, 450)
160
+ self.meanspec_plot_toolbar = NavigationToolbar(
161
+ self.meanspec_plot, self
162
+ )
163
+ self.plot.customize_toolbar(self.meanspec_plot_toolbar)
164
+ self.plot.setup_plot(self.meanspec_plot)
165
+ #
166
+ # Buttons and checkboxes
167
+ controls_layout = QVBoxLayout()
168
+ self.std_plot_checkbox = CheckBox(text="Plot standard deviation")
169
+ self.norm_plot_checkbox = CheckBox(text="Normalize plot")
170
+ self.derivative_checkbox = CheckBox(text="Plot with derivative")
171
+ self.dimred_checkbox = CheckBox(text="Reduced dataset")
172
+ for c in [
173
+ self.std_plot_checkbox,
174
+ self.norm_plot_checkbox,
175
+ self.derivative_checkbox,
176
+ self.dimred_checkbox,
177
+ ]:
178
+ controls_layout.addWidget(c.native)
179
+ #
180
+ plot_btn = PushButton(text="Mean spectrum")
181
+ plot_btn.clicked.connect(
182
+ lambda: self.plot.show_plot(
183
+ self.meanspec_plot,
184
+ mode=self.datamanager.modes_combobox.value,
185
+ std_flag=self.std_plot_checkbox.value,
186
+ norm_flag=self.norm_plot_checkbox.value,
187
+ reduced_dataset_flag=self.dimred_checkbox.value,
188
+ derivative_flag=self.derivative_checkbox.value,
189
+ )
190
+ )
191
+ controls_layout.addWidget(plot_btn.native)
192
+ plot_layout.addLayout(controls_layout)
193
+ plot_layout.addWidget(self.meanspec_plot)
194
+ plot_layout.addWidget(self.meanspec_plot_toolbar)
195
+
196
+ return plot_layout
197
+
198
+ def create_plot_export_section(self):
199
+ """Export mean spectrum"""
200
+ export_txt_layout = QVBoxLayout()
201
+
202
+ export_txt_btn = PushButton(text="Export spectra")
203
+ export_txt_btn.clicked.connect(
204
+ lambda: self.plot.show_plot(
205
+ self.meanspec_plot,
206
+ mode=self.datamanager.modes_combobox.value,
207
+ std_flag=self.std_plot_checkbox.value,
208
+ norm_flag=self.norm_plot_checkbox.value,
209
+ reduced_dataset_flag=self.dimred_checkbox.value,
210
+ export_txt_flag=True,
211
+ )
212
+ )
213
+
214
+ export_txt_layout.addWidget(Container(widgets=[export_txt_btn]).native)
215
+ return export_txt_layout
216
+
217
+ # %% Buttons functions
218
+ def true_rgb_btn_f(self):
219
+ """ """
220
+ data_mode = self.datamanager.modes_combobox.value
221
+ self.data.rgb[data_mode] = HSI2RGB(
222
+ self.data.wls[data_mode],
223
+ self.data.hypercubes[data_mode],
224
+ self.data.hypercubes[data_mode].shape[0],
225
+ self.data.hypercubes[data_mode].shape[1],
226
+ 65,
227
+ False,
228
+ )
229
+ self.viewer.add_image(
230
+ self.data.rgb[data_mode],
231
+ name=str(data_mode) + " RGB",
232
+ rgb=True,
233
+ metadata={"type": "rgb"},
234
+ )
235
+ return
236
+
237
+ def false_rgb_btn_f(self):
238
+ """ """
239
+ data_mode = self.datamanager.modes_combobox.value
240
+ R_values = [self.R_min_spinbox.value, self.R_max_spinbox.value]
241
+ G_values = [self.G_min_spinbox.value, self.G_max_spinbox.value]
242
+ B_values = [self.B_min_spinbox.value, self.B_max_spinbox.value]
243
+ falseRGB_image = falseRGB(
244
+ self.data.hypercubes[data_mode],
245
+ self.data.wls[data_mode],
246
+ R_values,
247
+ G_values,
248
+ B_values,
249
+ )
250
+ self.viewer.add_image(
251
+ falseRGB_image,
252
+ name=str(data_mode) + " - FALSE RGB",
253
+ rgb=True,
254
+ metadata={"type": "false_rgb"},
255
+ )
256
+
257
+ # %% Other functions
@@ -0,0 +1,382 @@
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 pandas as pd
10
+ from magicgui.widgets import (
11
+ CheckBox,
12
+ ComboBox,
13
+ Container,
14
+ FloatSpinBox,
15
+ PushButton,
16
+ Select,
17
+ SpinBox,
18
+ )
19
+ from matplotlib.backends.backend_qt5agg import (
20
+ FigureCanvasQTAgg as FigureCanvas,
21
+ )
22
+ from matplotlib.backends.backend_qt5agg import (
23
+ NavigationToolbar2QT as NavigationToolbar,
24
+ )
25
+ from matplotlib.figure import Figure
26
+ from napari.utils.notifications import show_info
27
+ from qtpy.QtCore import QTimer
28
+ from qtpy.QtWidgets import (
29
+ QFileDialog,
30
+ QGroupBox,
31
+ QHBoxLayout,
32
+ QScrollArea,
33
+ QVBoxLayout,
34
+ QWidget,
35
+ )
36
+
37
+ from napari_musa.modules.functions import (
38
+ NFINDR,
39
+ PPI,
40
+ SiVM,
41
+ inverse_metrics,
42
+ nnls_analysis,
43
+ sam_analysis,
44
+ vca,
45
+ )
46
+
47
+
48
+ class EndmembersExtraction(QWidget):
49
+ """ """
50
+
51
+ def __init__(self, viewer: napari.Viewer, data, plot):
52
+ """ """
53
+ super().__init__()
54
+ self.viewer = viewer
55
+ self.data = data
56
+ self.plot = plot
57
+ self.init_ui()
58
+
59
+ def init_ui(self):
60
+ """ """
61
+ scroll = QScrollArea()
62
+ scroll.setWidgetResizable(True)
63
+ content_widget = QWidget()
64
+ content_layout = QVBoxLayout(content_widget)
65
+
66
+ self.build_sivm_group(content_layout)
67
+ content_layout.addStretch()
68
+
69
+ scroll.setWidget(content_widget)
70
+ main_layout = QVBoxLayout(self)
71
+ main_layout.addWidget(scroll)
72
+ self.setLayout(main_layout)
73
+
74
+ def build_sivm_group(self, layout):
75
+ """ """
76
+ layout.addWidget(self.create_endmextr_controls())
77
+ layout.addWidget(self.create_upload_endmembers())
78
+ layout.addWidget(self.create_nnls())
79
+ layout.addWidget(self.create_sam())
80
+ layout.addStretch()
81
+
82
+ def create_endmextr_controls(self):
83
+ """ """
84
+ endm_box = QGroupBox("Endmembers")
85
+ endm_layout = QVBoxLayout()
86
+ endm_layout.addSpacing(10)
87
+ row1 = QHBoxLayout()
88
+ self.masked_dataset = CheckBox(text="Apply to masked dataset")
89
+ self.modes_combobox = ComboBox(
90
+ choices=self.data.modes, label="Select the imaging mode"
91
+ )
92
+ row1.addWidget(self.masked_dataset.native)
93
+ row1.addWidget(self.modes_combobox.native)
94
+ endm_layout.addLayout(row1)
95
+
96
+ # row2 = QHBoxLayout()
97
+ # row2.addWidget(self.masked_dataset.native)
98
+ # layout.addLayout(row2)
99
+
100
+ self.n_endmembers_spinbox = SpinBox(
101
+ min=1, max=500, value=10, step=1, name="Endmembers"
102
+ )
103
+ endm_layout.addWidget(
104
+ Container(widgets=[self.n_endmembers_spinbox]).native
105
+ )
106
+
107
+ row2 = QHBoxLayout()
108
+ self.modes_vertex_analysis = ComboBox(
109
+ choices=["SiVM", "VCA", "N-FINDR", "PPI"],
110
+ label="Select the endmembers extraction mode",
111
+ )
112
+ run_btn = PushButton(text="Run endmember analysis")
113
+ run_btn.clicked.connect(self.run_btn_f)
114
+ row2.addWidget(
115
+ Container(widgets=[self.modes_vertex_analysis, run_btn]).native
116
+ )
117
+ endm_layout.addLayout(row2)
118
+
119
+ row3 = QHBoxLayout()
120
+ self.sivm_basis_multiselecton = Select(
121
+ label="Select Bases", choices=[]
122
+ )
123
+ self.sivm_basis_multiselecton.changed.connect(
124
+ self.on_basis_selection_changed
125
+ )
126
+ row3.addWidget(self.sivm_basis_multiselecton.native)
127
+ endm_layout.addLayout(row3)
128
+
129
+ row4 = QVBoxLayout()
130
+ self.mean_plot = FigureCanvas(Figure(figsize=(5, 3)))
131
+ self.mean_plot.setMinimumSize(300, 450)
132
+ self.mean_plot_toolbar = NavigationToolbar(self.mean_plot, self)
133
+ self.plot.customize_toolbar(self.mean_plot_toolbar)
134
+ self.plot.setup_plot(self.mean_plot)
135
+ row4.addWidget(self.mean_plot)
136
+ row4.addWidget(self.mean_plot_toolbar)
137
+ # Export button
138
+ export_btn = PushButton(text="Export selected spectra")
139
+ export_btn.clicked.connect(self.export_spectrum)
140
+ row4.addWidget(Container(widgets=[export_btn]).native)
141
+ endm_layout.addLayout(row4)
142
+
143
+ endm_box.setLayout(endm_layout)
144
+ return endm_box
145
+
146
+ def create_upload_endmembers(self):
147
+ """ """
148
+ upload_endm_box = QGroupBox("Upload Endmembers")
149
+ upload_endm_layout = QVBoxLayout()
150
+ upload_endm_layout.addSpacing(10)
151
+ row1 = QHBoxLayout()
152
+ self.upload_endmembers_checkbox = CheckBox(
153
+ text="Use endmembers from file"
154
+ )
155
+ upload_endmember_btn = PushButton(text="Upload Endmembers")
156
+ upload_endmember_btn.clicked.connect(self.upload_endmembers_btn_f)
157
+ row1.addWidget(self.upload_endmembers_checkbox.native)
158
+ row1.addWidget(upload_endmember_btn.native)
159
+ upload_endm_layout.addLayout(row1)
160
+ upload_endm_box.setLayout(upload_endm_layout)
161
+ return upload_endm_box
162
+
163
+ def create_nnls(self):
164
+ """ """
165
+ nnls_box = QGroupBox("NNLS Analysis")
166
+ nnls_layout = QVBoxLayout()
167
+
168
+ run_btn = PushButton(text="Run NNLS")
169
+ run_btn.clicked.connect(self.run_nnls)
170
+ nnls_layout.addSpacing(10)
171
+ nnls_layout.addWidget(run_btn.native)
172
+ nnls_box.setLayout(nnls_layout)
173
+ return nnls_box
174
+
175
+ def create_sam(self):
176
+ sam_box = QGroupBox("SAM Analysis")
177
+ sam_layout = QVBoxLayout()
178
+ self.angle_spinbox = FloatSpinBox(
179
+ min=0.0, max=1.0, value=0.1, step=0.1, label="Cosine value"
180
+ )
181
+ run_sam_btn = PushButton(text="Run SAM")
182
+ run_sam_btn.clicked.connect(self.run_sam)
183
+ sam_layout.addSpacing(10)
184
+ sam_layout.addWidget(Container(widgets=[self.angle_spinbox]).native)
185
+ sam_layout.addWidget(run_sam_btn.native)
186
+ sam_box.setLayout(sam_layout)
187
+ return sam_box
188
+
189
+ def run_btn_f(self):
190
+ """Perform SiVM"""
191
+ self.sivm_basis_multiselecton.value = []
192
+ mode = self.modes_combobox.value
193
+ analysis_mode = self.modes_vertex_analysis.value
194
+ n_basis = self.n_endmembers_spinbox.value
195
+ options = [f"Basis {i}" for i in range(n_basis)]
196
+
197
+ if self.masked_dataset.value:
198
+ dataset = self.data.hypercubes_masked[mode]
199
+ data_reshaped = dataset.reshape(
200
+ dataset.shape[0] * dataset.shape[1], -1
201
+ )
202
+ dataset = np.nan_to_num(dataset, nan=0)
203
+
204
+ self.points = np.array(
205
+ np.where(~np.isnan(np.mean(data_reshaped, axis=1)))
206
+ ).flatten()
207
+
208
+ else:
209
+ dataset = self.data.hypercubes[mode]
210
+ self.points = []
211
+
212
+ if analysis_mode == "SiVM":
213
+ self.data.vertex_basis[mode] = SiVM(
214
+ dataset, n_bases=n_basis, points=self.points
215
+ )
216
+ elif analysis_mode == "VCA":
217
+ dataset_reshaped = dataset.reshape(
218
+ dataset.shape[0] * dataset.shape[1], -1
219
+ )
220
+ if len(self.points) > 0:
221
+ dataset_reshaped = dataset_reshaped[self.points, :]
222
+ self.data.vertex_basis[mode] = vca(
223
+ dataset_reshaped.transpose(), R=n_basis
224
+ )[0]
225
+ # CONTROLLARE SE VANNO E AGGIUNGERE I POINTS
226
+ elif analysis_mode == "N-FINDR":
227
+ self.data.vertex_basis[mode] = NFINDR(dataset, n_bases=n_basis)
228
+ print(self.vertex_basis[mode].shape)
229
+
230
+ elif analysis_mode == "PPI":
231
+ self.data.vertex_basis[mode] = PPI(dataset, n_bases=n_basis)
232
+ print(self.vertex_basis[mode].shape)
233
+
234
+ self.sivm_basis_multiselecton.choices = options
235
+ QTimer.singleShot(
236
+ 0, lambda: show_info("Endmember analysis completed!")
237
+ )
238
+
239
+ def on_basis_selection_changed(self, value):
240
+ mode = self.modes_combobox.value
241
+
242
+ print("Selected bases:", value)
243
+ print("Shape of the array:", self.data.vertex_basis[mode].shape)
244
+
245
+ self.basis_numbers = sorted([int(s.split()[1]) for s in value])
246
+ self.selected_basis = self.data.vertex_basis[mode][
247
+ :, self.basis_numbers
248
+ ]
249
+ print(self.selected_basis.shape)
250
+ self.selected_basis_to_show = self.selected_basis
251
+
252
+ if mode == "Fused":
253
+ fusion_point = self.data.wls[self.data.fusion_modes[0]].shape[0]
254
+ print(self.data.fusion_norm)
255
+ # xxx aggiustare corrections
256
+ print(self.data.fusion_params[0])
257
+ self.selected_basis_to_show[:fusion_point, :] = inverse_metrics(
258
+ self.selected_basis_to_show[:fusion_point, :],
259
+ self.data.fusion_norm,
260
+ self.data.fusion_params[0],
261
+ )
262
+ self.selected_basis_to_show[fusion_point:, :] = inverse_metrics(
263
+ self.selected_basis_to_show[fusion_point:, :],
264
+ self.data.fusion_norm,
265
+ self.data.fusion_params[1],
266
+ )
267
+
268
+ self.plot.show_spectra(
269
+ self.mean_plot,
270
+ self.selected_basis_to_show,
271
+ mode,
272
+ basis_numbers=self.basis_numbers,
273
+ export_txt_flag=False,
274
+ )
275
+ self.viewer.status = f"Selected basis: {self.basis_numbers}"
276
+ # QTimer.singleShot(0, lambda: show_info(f"Selected basis: {self.basis_numbers}"))
277
+ print("Selected basis: ", self.basis_numbers)
278
+
279
+ def export_spectrum(self):
280
+ """Export the mean spectrum"""
281
+ mode = self.modes_combobox.value
282
+
283
+ self.plot.show_spectra(
284
+ self.mean_plot,
285
+ self.selected_basis_to_show,
286
+ mode,
287
+ basis_numbers=self.basis_numbers,
288
+ export_txt_flag=True,
289
+ )
290
+
291
+ def upload_endmembers_btn_f(self):
292
+ """Upload endmembers from file"""
293
+
294
+ filepath, _ = QFileDialog.getOpenFileName()
295
+ print(f"The file with path {filepath} will now be opened")
296
+ df_file = pd.read_csv(filepath, sep="\t")
297
+
298
+ # wl = df_file[[col for col in df_file.columns if "Wavelength" in col]]
299
+ spectra = df_file[
300
+ [col for col in df_file.columns if "Spectrum" in col]
301
+ ]
302
+ # std = df_file[[col for col in df_file.columns if "Std" in col]]
303
+
304
+ self.uploaded_endmembers = spectra.to_numpy()
305
+
306
+ def run_nnls(self):
307
+ """Perform NNLS"""
308
+ mode = self.modes_combobox.value
309
+
310
+ if self.masked_dataset.value:
311
+ dataset = self.data.hypercubes_masked[mode]
312
+ data_reshaped = dataset.reshape(
313
+ dataset.shape[0] * dataset.shape[1], -1
314
+ )
315
+ self.points = np.array(
316
+ np.where(~np.isnan(np.mean(data_reshaped, axis=1)))
317
+ ).flatten()
318
+
319
+ dataset = np.nan_to_num(dataset, nan=0)
320
+ else:
321
+ dataset = self.data.hypercubes[mode]
322
+ self.points = []
323
+
324
+ if self.upload_endmembers_checkbox.value:
325
+ self.selected_basis = self.uploaded_endmembers
326
+
327
+ print(self.selected_basis.shape)
328
+
329
+ self.data.nnls_maps[mode] = nnls_analysis(
330
+ dataset, W=self.selected_basis
331
+ )
332
+ self.viewer.add_image(
333
+ self.data.nnls_maps[mode].transpose(2, 0, 1),
334
+ name=str(mode) + " - NNLS",
335
+ # ={"type": "hyperspectral_cube"},
336
+ )
337
+
338
+ def run_sam(self):
339
+ """Perform SAM"""
340
+ mode = self.modes_combobox.value
341
+
342
+ if self.masked_dataset.value:
343
+ dataset = self.data.hypercubes_masked[mode]
344
+ data_reshaped = dataset.reshape(
345
+ dataset.shape[0] * dataset.shape[1], -1
346
+ )
347
+ self.points = np.array(
348
+ np.where(~np.isnan(np.mean(data_reshaped, axis=1)))
349
+ ).flatten()
350
+
351
+ dataset = np.nan_to_num(dataset, nan=0)
352
+ else:
353
+ dataset = self.data.hypercubes[mode]
354
+ self.points = []
355
+
356
+ if self.upload_endmembers_checkbox.value:
357
+ self.selected_basis = self.uploaded_endmembers
358
+
359
+ self.data.sam_maps[mode] = sam_analysis(
360
+ dataset,
361
+ W=self.selected_basis,
362
+ angle=self.angle_spinbox.value,
363
+ )
364
+
365
+ self.viewer.add_image(
366
+ self.data.sam_maps[mode].transpose(2, 0, 1),
367
+ name=str(mode)
368
+ + " - SAM with angle "
369
+ + str(self.angle_spinbox.value),
370
+ colormap="gray_r",
371
+ # ={"type": "hyperspectral_cube"},
372
+ )
373
+
374
+ # %%
375
+ def update_number_H(self):
376
+ """ """
377
+ basis_index = self.viewer.dims.current_step[0]
378
+ basis_index = min(basis_index, len(self.basis_numbers) - 1)
379
+ print(f"basis_index={basis_index}, basis_numbers={self.basis_numbers}")
380
+ self.viewer.text_overlay.text = (
381
+ f"Basis number: {self.basis_numbers[basis_index]}"
382
+ )