Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2027 adjustable ROI #2031

Merged
merged 23 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#2027: The Spectrum ROI details display in an adjustable table via spinboxes
51 changes: 44 additions & 7 deletions mantidimaging/gui/ui/spectrum_viewer.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>921</width>
<height>739</height>
<width>905</width>
<height>752</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -351,17 +351,54 @@
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<widget class="QGroupBox" name="roiPropertiesGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>200</height>
</size>
</property>
<property name="title">
<string>ROI Properties</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QTableWidget" name="roiPropertiesTableWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>200</height>
</size>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="PropertiesSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
<height>40</height>
</size>
</property>
</spacer>
Expand Down
4 changes: 4 additions & 0 deletions mantidimaging/gui/windows/spectrum_viewer/presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ def handle_roi_moved(self, force_new_spectrums: bool = False) -> None:
self.model.set_roi(name, roi)
self.view.set_spectrum(name, self.model.get_spectrum(name, self.spectrum_mode))

def handle_roi_clicked(self, roi) -> None:
self.view.current_roi = roi.name
self.view.set_roi_properties()

def redraw_spectrum(self, name: str) -> None:
"""
Redraw the spectrum with the given name
Expand Down
24 changes: 23 additions & 1 deletion mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def __init__(self, name: str, sensible_roi: SensibleROI, *args, **kwargs):
self.addScaleHandle([0, 0], [1, 1])
self.addScaleHandle([0, 1], [1, 0])
self._selected_row = None
self.roi.setAcceptedMouseButtons(Qt.MouseButton.LeftButton)

self.menu = QMenu()
change_color_action = QAction("Change ROI Colour", self)
Expand Down Expand Up @@ -82,6 +83,10 @@ def colour(self, colour: tuple[int, int, int, int]) -> None:
def selected_row(self) -> Optional[int]:
return self._selected_row

def adjust_spec_roi(self, roi: SensibleROI) -> None:
self.setPos((roi.left, roi.top))
self.setSize((roi.width, roi.height))


class SpectrumWidget(QWidget):
"""
Expand All @@ -91,6 +96,13 @@ class SpectrumWidget(QWidget):
"""
image: MIMiniImageView
spectrum: PlotItem

range_control: LinearRegionItem
roi_dict: dict[Optional[str], ROI]
last_clicked_roi: str

range_changed = pyqtSignal(object)
roi_clicked = pyqtSignal(object)
roi_changed = pyqtSignal()
roiColorChangeRequested = pyqtSignal(str, tuple)

Expand Down Expand Up @@ -160,8 +172,9 @@ def set_roi_visibility_flags(self, name: str, visible: bool) -> None:
for handle in handles:
handle.setVisible(visible)
self.roi_dict[name].setVisible(visible)
self.roi_dict[name].setAcceptedMouseButtons(Qt.NoButton)
self.roi_dict[name].setAcceptedMouseButtons(Qt.MouseButton.LeftButton)
self.roi_dict[name].sigRegionChanged.connect(self.roi_changed.emit)
self.roi_dict[name].sigClicked.connect(self.roi_clicked.emit)

def set_roi_alpha(self, name: str, alpha: float) -> None:
"""
Expand Down Expand Up @@ -190,9 +203,18 @@ def add_roi(self, roi: SensibleROI, name: str) -> None:
self.roi_dict[name] = roi_object.roi
self.max_roi_size = roi_object.size()
self.roi_dict[name].sigRegionChanged.connect(self.roi_changed.emit)
self.roi_dict[name].sigClicked.connect(self.roi_clicked.emit)
self.image.vb.addItem(self.roi_dict[name])
self.roi_dict[name].hoverPen = mkPen(self.roi_dict[name].colour, width=3)

def adjust_roi(self, new_roi: SensibleROI, roi_name: str):
"""
Adjust the existing ROI with the given name.
@param new_roi: The new SpectrumROI to replace the existing SpectrumROI
@param roi_name: The name of the existing ROI.
"""
self.roi_dict[roi_name].adjust_spec_roi(new_roi)

def get_roi(self, roi_name: str) -> SensibleROI:
"""
Get the ROI with the given name. If no name is given, the default ROI is returned.
Expand Down
90 changes: 89 additions & 1 deletion mantidimaging/gui/windows/spectrum_viewer/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QCheckBox, QVBoxLayout, QFileDialog, QPushButton, QLabel, QAbstractItemView, QHeaderView, \
QTabWidget, QComboBox, QSpinBox
QTabWidget, QComboBox, QSpinBox, QTableWidget, QTableWidgetItem, QGroupBox
from PyQt5.QtCore import QSignalBlocker, Qt

from mantidimaging.core.utility import finder
from mantidimaging.gui.mvp_base import BaseMainWindowView
Expand All @@ -17,6 +18,7 @@
from mantidimaging.gui.widgets import RemovableRowTableView
from .spectrum_widget import SpectrumWidget
from mantidimaging.gui.windows.spectrum_viewer.roi_table_model import TableModel
from mantidimaging.core.utility.sensible_roi import SensibleROI

import numpy as np

Expand All @@ -42,6 +44,11 @@ class SpectrumViewerWindowView(BaseMainWindowView):
bin_size_spinBox: QSpinBox
bin_step_spinBox: QSpinBox

roiPropertiesTableWidget: QTableWidget
roiPropertiesGroupBox: QGroupBox

last_clicked_roi: str

spectrum_widget: SpectrumWidget

def __init__(self, main_window: 'MainWindowView'):
Expand All @@ -64,6 +71,8 @@ def __init__(self, main_window: 'MainWindowView'):
self.imageLayout.addWidget(self.spectrum_widget)

self.spectrum.range_changed.connect(self.presenter.handle_range_slide_moved)

self.spectrum_widget.roi_clicked.connect(self.presenter.handle_roi_clicked)
self.spectrum_widget.roi_changed.connect(self.presenter.handle_roi_moved)
self.spectrum_widget.roiColorChangeRequested.connect(self.presenter.change_roi_colour)

Expand Down Expand Up @@ -98,7 +107,55 @@ def __init__(self, main_window: 'MainWindowView'):
self.tableView.setSelectionMode(QAbstractItemView.SingleSelection)
self.tableView.setAlternatingRowColors(True)

# Roi Prop table
self.roi_table_properties = ["Top", "Bottom", "Left", "Right"]
self.roi_table_properties_secondary = ["Width", "Height"]
self.roiPropertiesTableWidget.setColumnCount(3)
self.roiPropertiesTableWidget.setRowCount(3)
self.roiPropertiesTableWidget.setColumnWidth(0, 80)
self.roiPropertiesTableWidget.setColumnWidth(1, 50)
self.roiPropertiesTableWidget.setColumnWidth(2, 50)

self.roiPropertiesSpinBoxes = {}
self.roiPropertiesLabels = {}
for prop in self.roi_table_properties:
spin_box = QSpinBox()
if prop == "Top" or prop == "Bottom":
spin_box.setMaximum(self.spectrum_widget.image.image_data.shape[0])
if prop == "Left" or prop == "Right":
spin_box.setMaximum(self.spectrum_widget.image.image_data.shape[1])
spin_box.valueChanged.connect(self.adjust_roi)
self.roiPropertiesSpinBoxes[prop] = spin_box
for prop in self.roi_table_properties_secondary:
label = QLabel()
self.roiPropertiesLabels[prop] = label

self.roiPropertiesTableWidget.horizontalHeader().hide()
self.roiPropertiesTableWidget.verticalHeader().hide()
self.roiPropertiesTableWidget.setShowGrid(False)

roiPropertiesTableText = ["x1, x2", "y1, y2", "Width, Height"]
self.roiPropertiesTableTextDict = {}
for text in roiPropertiesTableText:
item = QTableWidgetItem(text)
item.setFlags(Qt.ItemIsSelectable)
self.roiPropertiesTableTextDict[text] = item

self.roiPropertiesTableWidget.setItem(0, 0, self.roiPropertiesTableTextDict["x1, x2"])
self.roiPropertiesTableWidget.setCellWidget(0, 1, self.roiPropertiesSpinBoxes["Left"])
self.roiPropertiesTableWidget.setCellWidget(0, 2, self.roiPropertiesSpinBoxes["Right"])
self.roiPropertiesTableWidget.setItem(1, 0, self.roiPropertiesTableTextDict["y1, y2"])
self.roiPropertiesTableWidget.setCellWidget(1, 1, self.roiPropertiesSpinBoxes["Top"])
self.roiPropertiesTableWidget.setCellWidget(1, 2, self.roiPropertiesSpinBoxes["Bottom"])
self.roiPropertiesTableWidget.setItem(2, 0, self.roiPropertiesTableTextDict["Width, Height"])
self.roiPropertiesTableWidget.setCellWidget(2, 1, self.roiPropertiesLabels["Width"])
self.roiPropertiesTableWidget.setCellWidget(2, 2, self.roiPropertiesLabels["Height"])

self.spectrum_widget.roi_changed.connect(self.set_roi_properties)

_ = self.roi_table_model # Initialise model
self.current_roi = self.roi_table_model.roi_names()[0]
self.set_roi_properties()

def on_row_change(item, _) -> None:
"""
Expand All @@ -110,6 +167,7 @@ def on_row_change(item, _) -> None:
selected_row_data = self.roi_table_model.row_data(item.row())
self.selected_row = item.row()
self.current_roi = selected_row_data[0]
self.set_roi_properties()

self.tableView.selectionModel().currentRowChanged.connect(on_row_change)

Expand Down Expand Up @@ -156,6 +214,8 @@ def on_visibility_change(self) -> None:
When the visibility of an ROI is changed, update the visibility of the ROI in the spectrum widget
"""
if self.presenter.export_mode == ExportMode.ROI_MODE:
self.current_roi = self.last_clicked_roi
self.set_roi_properties()
for roi_name, _, roi_visible in self.roi_table_model:
if roi_visible is False:
self.set_roi_alpha(0, roi_name)
Expand All @@ -169,6 +229,9 @@ def on_visibility_change(self) -> None:
if self.presenter.export_mode == ExportMode.IMAGE_MODE:
self.set_roi_alpha(255, ROI_RITS)
self.presenter.redraw_spectrum(ROI_RITS)
self.last_clicked_roi = self.current_roi
self.current_roi = ROI_RITS
self.set_roi_properties()
else:
self.set_roi_alpha(0, ROI_RITS)

Expand Down Expand Up @@ -371,3 +434,28 @@ def set_binning_visibility(self) -> None:
self.bin_size_spinBox.setHidden(hide_binning)
self.bin_step_label.setHidden(hide_binning)
self.bin_step_spinBox.setHidden(hide_binning)

def set_roi_properties(self) -> None:
current_roi = self.presenter.model.get_roi(self.current_roi)
self.roiPropertiesGroupBox.setTitle(f"Roi Properties: {self.current_roi}")
roi_iter_order = ["Left", "Top", "Right", "Bottom"]
for row, pos in enumerate(current_roi):
with QSignalBlocker(self.roiPropertiesSpinBoxes[roi_iter_order[row]]):
self.roiPropertiesSpinBoxes[roi_iter_order[row]].setValue(pos)
self.set_roi_spinbox_ranges()
self.presenter.redraw_spectrum(self.current_roi)
self.roiPropertiesLabels["Width"].setText(str(current_roi.width))
self.roiPropertiesLabels["Height"].setText(str(current_roi.height))

def adjust_roi(self) -> None:
roi_iter_order = ["Left", "Top", "Right", "Bottom"]
new_points = [self.roiPropertiesSpinBoxes[prop].value() for prop in roi_iter_order]
new_roi = SensibleROI().from_list(new_points)
self.presenter.model.set_roi(self.current_roi, new_roi)
self.spectrum_widget.adjust_roi(new_roi, self.current_roi)

def set_roi_spinbox_ranges(self):
self.roiPropertiesSpinBoxes["Left"].setMaximum(self.roiPropertiesSpinBoxes["Right"].value() - 1)
self.roiPropertiesSpinBoxes["Right"].setMinimum(self.roiPropertiesSpinBoxes["Left"].value() + 1)
self.roiPropertiesSpinBoxes["Top"].setMaximum(self.roiPropertiesSpinBoxes["Bottom"].value() - 1)
self.roiPropertiesSpinBoxes["Bottom"].setMinimum(self.roiPropertiesSpinBoxes["Top"].value() + 1)
Loading