Skip to content

Commit d105791

Browse files
committed
(spectrum-viewer): add detailed logging for ROI actions and fitting
1 parent eb492ba commit d105791

File tree

11 files changed

+97
-4
lines changed

11 files changed

+97
-4
lines changed

mantidimaging/gui/widgets/spectrum_widgets/export_data_table_widget.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
# Copyright (C) 2021 ISIS Rutherford Appleton Laboratory UKRI
22
# SPDX - License - Identifier: GPL-3.0-or-later
33
from __future__ import annotations
4+
from logging import getLogger
45

56
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QTableView, QHeaderView, QAbstractItemView
67
from PyQt5.QtGui import QStandardItemModel, QStandardItem
78
from PyQt5.QtCore import Qt
89

10+
LOG = getLogger(__name__)
11+
912

1013
class ExportDataTableWidget(QWidget):
1114
"""
@@ -66,6 +69,8 @@ def update_roi_data(self, roi_name: str, params: dict[str, float], status: str =
6669
else:
6770
self.model.appendRow(items)
6871

72+
LOG.info("Export table updated: ROI=%s, Params=%s, Status=%s", roi_name, params, status)
73+
6974
def _find_row_by_roi_name(self, roi_name: str) -> int | None:
7075
"""
7176
Find the row index for a given ROI name. Returns None if not found.
@@ -80,3 +85,4 @@ def clear_table(self) -> None:
8085
Remove all rows from the table.
8186
"""
8287
self.model.removeRows(0, self.model.rowCount())
88+
LOG.info("Export table cleared")

mantidimaging/gui/widgets/spectrum_widgets/fitting_display_widget.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
from mantidimaging.gui.windows.spectrum_viewer.model import allowed_modes
1414
from mantidimaging.gui.windows.spectrum_viewer.spectrum_widget import SpectrumPlotWidget, SpectrumROI
1515
from mantidimaging.core.fitting.fitting_functions import FittingRegion
16+
from logging import getLogger
17+
18+
LOG = getLogger(__name__)
1619

1720

1821
class FittingDisplayWidget(QWidget):
@@ -64,6 +67,7 @@ def update_plot(self, x_data: np.ndarray, y_data: np.ndarray, label: str = "ROI"
6467
self.spectrum_plot.spectrum.plot(x_data, y_data, name=label, pen=(255, 255, 0))
6568
self.spectrum_plot.spectrum.addItem(self.fitting_region)
6669
self.set_default_region(x_data, y_data)
70+
LOG.debug("Spectrum plot updated: label=%s, points=%d", label, len(x_data))
6771

6872
def update_image(self, image: np.ndarray | None) -> None:
6973
if image is not None:
@@ -114,6 +118,7 @@ def set_selected_fit_region(self, region: tuple[float, float]) -> None:
114118
height = self.fitting_region.size().y()
115119
self.fitting_region.setPos((x_start, y_pos))
116120
self.fitting_region.setSize((width, height))
121+
LOG.info("Fit region set: x_start=%.3f, x_end=%.3f", x_start, x_end)
117122

118123
def get_selected_fit_region(self) -> FittingRegion:
119124
pos = self.fitting_region.pos()
@@ -154,6 +159,7 @@ def show_fit_line(self, x_data: np.ndarray, y_data: np.ndarray, *, color: tuple[
154159
self._current_fit_line = None
155160
self._current_fit_line = self.spectrum_plot.spectrum.plot(x_data, y_data, name=label, pen=color)
156161
self._showing_initial_fit = initial
162+
LOG.debug("Fit line displayed: label=%s, initial=%s, points=%d", label, initial, len(x_data))
157163

158164
def is_initial_fit_visible(self) -> bool:
159165
return self._showing_initial_fit

mantidimaging/gui/widgets/spectrum_widgets/fitting_param_form_widget.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22
# SPDX - License - Identifier: GPL-3.0-or-later
33
from __future__ import annotations
44
from typing import TYPE_CHECKING
5+
from logging import getLogger
56

67
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QSizePolicy, QPushButton
78
from PyQt5.QtGui import QDoubleValidator
89

910
if TYPE_CHECKING:
1011
from mantidimaging.gui.windows.spectrum_viewer import SpectrumViewerWindowPresenter
1112

13+
LOG = getLogger(__name__)
14+
1215

1316
class FittingParamFormWidget(QWidget):
1417
"""
@@ -68,11 +71,13 @@ def set_parameter_values(self, values: dict[str, float]) -> None:
6871
for name, value in values.items():
6972
row = self._rows[name]
7073
row[2].setText(f"{value:f}")
74+
LOG.debug("Final fit parameter values updated: %s", values)
7175

7276
def set_fitted_parameter_values(self, values: dict[str, float]) -> None:
7377
for name, value in values.items():
7478
row = self._rows[name]
7579
row[3].setText(f"{value:f}")
80+
LOG.debug("Final fit parameter values updated: %s", values)
7681

7782
def get_initial_param_values(self) -> list[float]:
7883
params = [float(row[2].text()) for row in self._rows.values()]
@@ -91,3 +96,4 @@ def clear_rows(self) -> None:
9196
widget.setParent(None)
9297
self.params_layout.layout().removeItem(row_layout)
9398
self._rows.clear()
99+
LOG.debug("Parameter form rows cleared")

mantidimaging/gui/widgets/spectrum_widgets/fitting_selection_widget.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
from PyQt5 import QtWidgets, QtCore
88

99
from mantidimaging.core.fitting.fitting_functions import BaseFittingFunction
10+
from logging import getLogger
11+
12+
LOG = getLogger(__name__)
1013

1114

1215
class FitSelectionWidget(QtWidgets.QGroupBox):
1316
"""
1417
A custom Qt widget for selecting an Fitting Model.
15-
1618
Attributes:
1719
fitDropdown: A dropdown menu for selecting fits.
1820
func_dict: A dictionary for storing fitting functions available in the viewer.
@@ -45,6 +47,7 @@ def _on_selection_changed(self) -> None:
4547
""" Handle dropdown selection change and emit signal. """
4648
selected_fit = self.fitDropdown.currentText()
4749
self.selectionChanged.emit(self.func_dict[selected_fit])
50+
LOG.info("Fit function selected: %s", self.fitDropdown.currentText())
4851

4952
def set_available_fitting_functions(self) -> None:
5053
""" Update the dropdown and trigger selection change if needed. """

mantidimaging/gui/widgets/spectrum_widgets/roi_form_widget.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from PyQt5.QtCore import pyqtSignal, QSignalBlocker, QModelIndex
88
from PyQt5.QtGui import QPixmap
99
from PyQt5.QtWidgets import QAbstractItemView, QHeaderView, QLabel
10+
from logging import getLogger
1011

1112
from mantidimaging.core.utility import finder
1213
from mantidimaging.core.utility.sensible_roi import SensibleROI
@@ -17,6 +18,8 @@
1718
if TYPE_CHECKING:
1819
from PyQt5.QtWidgets import QTabWidget, QComboBox, QPushButton, QSpinBox, QGroupBox
1920

21+
LOG = getLogger(__name__)
22+
2023

2124
class ROIFormWidget(BaseWidget):
2225
"""
@@ -81,12 +84,15 @@ def _check_rits_step_validity(self) -> None:
8184
bin_size = self.bin_size_spinBox.value()
8285
roi_width = roi.right - roi.left
8386
roi_height = roi.bottom - roi.top
87+
norm_mode = self.transmission_error_mode_combobox.currentText()
8488

8589
if ((roi_width - bin_size) % step != 0 or (roi_height - bin_size) % step != 0):
8690
warning = (f"Step size {step} and bin size {bin_size} do not evenly divide ROI dimensions "
8791
f"({roi_width}x{roi_height}). Some rows or columns may not be exported.")
8892
self.show_rits_warning(warning)
8993
else:
94+
LOG.info("RITS config valid — bin=%d, step=%d, norm_error=%s, roi_size=%dx%d", bin_size, step, norm_mode,
95+
roi_width, roi_height)
9096
self.show_rits_warning(None)
9197

9298

@@ -123,6 +129,7 @@ def set_roi_values(self, roi: SensibleROI) -> None:
123129
self.spin_bottom.setValue(roi.bottom)
124130
self.label_width.setText(str(roi.width))
125131
self.label_height.setText(str(roi.height))
132+
LOG.debug("ROI bounds set: left=%d, right=%d, top=%d, bottom=%d", roi.left, roi.right, roi.top, roi.bottom)
126133

127134
def set_roi_limits(self, shape: tuple[int, ...]) -> None:
128135
self.spin_left.setMaximum(shape[1])
@@ -234,19 +241,22 @@ def add_row(self, name: str, colour: tuple[int, int, int, int], roi_names: list[
234241
self.roi_table_model.appendNewRow(name, colour, True)
235242
self.selected_row = self.roi_table_model.rowCount() - 1
236243
self.selectRow(self.selected_row)
244+
LOG.debug("ROI added to table: name=%s, color=%s", name, colour[:3])
237245

238246
def remove_row(self, row: int) -> None:
239247
"""
240248
Remove a row from the ROI table
241249
"""
242250
self.roi_table_model.remove_row(row)
243251
self.selectRow(0)
252+
LOG.debug("ROI row removed: row=%d", row)
244253

245254
def clear_table(self) -> None:
246255
"""
247256
Clears the ROI table in the spectrum viewer.
248257
"""
249258
self.roi_table_model.clear_table()
259+
LOG.debug("ROI table cleared")
250260

251261
def select_roi(self, roi_name: str) -> None:
252262
selected_row = self.find_row_for_roi(roi_name)

mantidimaging/gui/widgets/spectrum_widgets/roi_selection_widget.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33

44
from mantidimaging.gui.windows.spectrum_viewer.model import ROI_RITS
55
from PyQt5 import QtWidgets, QtCore
6+
from logging import getLogger
7+
8+
LOG = getLogger(__name__)
69

710

811
class ROISelectionWidget(QtWidgets.QGroupBox):
912
"""
1013
A custom Qt widget for selecting an ROI.
11-
1214
Attributes:
1315
roiDropdown: A dropdown menu for selecting ROIs.
1416
selectionChanged: Signal emitted when the ROI selection changes.
@@ -34,6 +36,7 @@ def _on_selection_changed(self) -> None:
3436
selected_roi = self.roiDropdown.currentText()
3537
if selected_roi != self.previous_selection:
3638
self.previous_selection = selected_roi
39+
LOG.info("ROI selected: %s", selected_roi)
3740
self.selectionChanged.emit(selected_roi)
3841

3942
def update_roi_list(self, roi_names: list[str]) -> None:
@@ -50,6 +53,7 @@ def update_roi_list(self, roi_names: list[str]) -> None:
5053
self._on_selection_changed()
5154
self._on_selection_changed()
5255
self.roiDropdown.blockSignals(False)
56+
LOG.debug("ROI dropdown updated: %s", filtered_rois)
5357

5458
def set_selected_roi(self, roi_name: str) -> None:
5559
""" Set the dropdown selection to the given ROI name. """

mantidimaging/gui/widgets/spectrum_widgets/tof_properties.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
# SPDX - License - Identifier: GPL-3.0-or-later
33

44
from PyQt5 import QtCore, QtWidgets
5+
from logging import getLogger
6+
7+
LOG = getLogger(__name__)
58

69

710
class ExperimentSetupFormWidget(QtWidgets.QGroupBox):
@@ -75,6 +78,7 @@ def flight_path(self) -> float:
7578
@flight_path.setter
7679
def flight_path(self, value: float) -> None:
7780
self.flightPathSpinBox.setValue(value)
81+
LOG.debug("Flight path set to: %.3f m", value)
7882

7983
@property
8084
def time_delay(self) -> float:
@@ -83,6 +87,7 @@ def time_delay(self) -> float:
8387
@time_delay.setter
8488
def time_delay(self, value: float):
8589
self.timeDelaySpinBox.setValue(value)
90+
LOG.debug("Time delay set to: %.3f µs", value)
8691

8792
def connect_value_changed(self, handler: QtCore.pyqtSlot):
8893
self.flightPathSpinBox.valueChanged.connect(handler)

mantidimaging/gui/windows/spectrum_viewer/model.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,15 @@ def set_stack(self, stack: ImageStack | None) -> None:
127127
return
128128
self.tof_range = (0, stack.data.shape[0] - 1)
129129
self.tof_data = self.get_stack_time_of_flight()
130+
LOG.info("Sample stack set: shape=%s, ToF range=(%d–%d)", stack.data.shape, self.tof_range[0],
131+
self.tof_range[1])
130132

131133
def set_normalise_stack(self, normalise_stack: ImageStack | None) -> None:
132134
self._normalise_stack = normalise_stack
135+
if normalise_stack is not None:
136+
LOG.info("Normalisation stack set: shape=%s", normalise_stack.data.shape)
137+
else:
138+
LOG.info("Normalisation stack cleared")
133139

134140
def get_normalized_averaged_image(self) -> np.ndarray | None:
135141
"""
@@ -164,7 +170,6 @@ def get_stack_spectrum(stack: ImageStack | None,
164170
"""
165171
Computes the mean spectrum of the given image stack within the specified region of interest (ROI).
166172
If the image stack is None, an empty numpy array is returned.
167-
168173
Parameters:
169174
stack (Optional[ImageStack]): The image stack to compute the spectrum from.
170175
It can be None, in which case an empty array is returned.
@@ -250,6 +255,9 @@ def get_spectrum(self,
250255
average_shuttercount = self.get_shuttercount_normalised_correction_parameter()
251256
spectrum = spectrum / average_shuttercount
252257

258+
LOG.debug("Computing spectrum: ROI=%s, mode=%s, cached=%s", roi, mode.name,
259+
(*roi, mode, normalise_with_shuttercount) in self.spectrum_cache)
260+
253261
return spectrum
254262

255263
def store_spectrum(self, roi: SensibleROI, mode: SpecType, normalise_with_shuttercount: bool, spectrum: np.ndarray):
@@ -382,6 +390,9 @@ def save_csv(self,
382390
csv_output.write(outfile)
383391
self.save_roi_coords(self.get_roi_coords_filename(path), rois)
384392

393+
LOG.info("Saving spectra to CSV: path=%s, ROIs=%s, normalised=%s, shuttercount=%s", path, list(rois.keys()),
394+
normalise, normalise_with_shuttercount)
395+
385396
def save_single_rits_spectrum(self, path: Path, error_mode: ErrorMode, roi: SensibleROI) -> None:
386397
"""
387398
Saves the spectrum for the RITS ROI to a RITS file.
@@ -419,6 +430,9 @@ def save_rits_roi(self, path: Path, error_mode: ErrorMode, roi: SensibleROI, nor
419430

420431
self.export_spectrum_to_rits(path, tof, transmission, transmission_error)
421432

433+
LOG.info("Exporting RITS file: path=%s, ROI=(%d,%d,%d,%d), error_mode=%s", path, roi.left, roi.top, roi.right,
434+
roi.bottom, error_mode.name)
435+
422436
def validate_bin_and_step_size(self, roi: SensibleROI, bin_size: int, step_size: int) -> None:
423437
"""
424438
Validates the bin size and step size for saving RITS images.
@@ -427,7 +441,6 @@ def validate_bin_and_step_size(self, roi: SensibleROI, bin_size: int, step_size:
427441
- Bin size must be larger than or equal to step size.
428442
- Both bin size and step size must be less than or equal to the smallest dimension of the ROI.
429443
If any of these conditions are not met, a ValueError is raised.
430-
431444
Parameters:
432445
roi: The region of interest (ROI) to which the bin size and step size should be compared.
433446
bin_size (int): The size of the bins to be validated.

0 commit comments

Comments
 (0)