Skip to content

Commit

Permalink
Add option for const Q binning per run (#134)
Browse files Browse the repository at this point in the history
* add new table column 'Const. Q Bin.'
* change ReductionTableColumnIndex base class to IntEnum
* pass const Q binning option to lr_reduction
* add unit test for ReductionTableHandler
* saving and loading of parameter const_q
* update stored configuration state upon checkbox state changed
* update codecov-action version
* add unit test for ConstQCheckBoxHandler
* add ReductionTableHandler unit testing
* add release note
  • Loading branch information
backmari authored Dec 4, 2024
1 parent 431edd6 commit ba6e8e4
Show file tree
Hide file tree
Showing 28 changed files with 435 additions and 132 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test-and-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- name: Run Tests
run: xvfb-run -a python -m pytest -vv --cov=RefRed --cov-report=xml --cov-report=term test
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }} # required

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import numpy as np

# application imports
from RefRed.interfaces.mytablewidget import ReductionTableColumIndex
from RefRed.interfaces.mytablewidget import ReductionTableColumnIndex
from RefRed.reduction_table_handling.reduction_table_handler import ReductionTableHandler
from RefRed.tabledata import TableData


Expand Down Expand Up @@ -36,11 +37,12 @@ def __init__(self, parent=None, list_lrdata=None, list_wks=None, list_run=None,
self.big_table_data: TableData = self.parent.big_table_data

self.reductionTable_col = (
int(ReductionTableColumIndex.DATA_RUN) if self.is_data else int(ReductionTableColumIndex.NORM_RUN)
ReductionTableColumnIndex.DATA_RUN if self.is_data else ReductionTableColumnIndex.NORM_RUN
)

if is_data:
self.clear_reductionTable()
o_reduction_table_handler = ReductionTableHandler(parent=self.parent)
o_reduction_table_handler.clear_reduction_table()

self.insert_runs_into_table()

Expand Down Expand Up @@ -123,12 +125,5 @@ def insert_data_runs_into_table(self):
str_run = str(_run)
self.parent.ui.reductionTable.item(_index, self.reductionTable_col).setText(str_run)

def clear_reductionTable(self):
nbr_row = self.parent.ui.reductionTable.rowCount()
nbr_col = self.parent.ui.reductionTable.columnCount()
for _row in range(nbr_row):
for _col in range(1, nbr_col):
self.parent.ui.reductionTable.item(_row, _col).setText("")

def clear_big_table_data(self):
self.big_table_data = TableData(self.parent.REDUCTIONTABLE_MAX_ROWCOUNT)
5 changes: 5 additions & 0 deletions RefRed/calculations/lr_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ def __init__(
self.back_flag: bool = True
self.two_backgrounds: bool = False

self.const_q: bool = False # reduction using constant Q binning

self.all_plot_axis = AllPlotAxis()
self.tof_auto_flag = True
self.new_detector_geometry_flag = self.is_nexus_taken_after_refDate()
Expand All @@ -207,6 +209,7 @@ def __init__(
self.low_res_flag = bool(lconfig.data_low_res_flag)
self.back_flag = bool(lconfig.data_back_flag)
self.two_backgrounds = bool(lconfig.data_two_backgrounds)
self.const_q = bool(lconfig.const_q)
else:
self.peak = [int(lconfig.norm_peak[0]), int(lconfig.norm_peak[1])]
self.back = [int(lconfig.norm_back[0]), int(lconfig.norm_back[1])]
Expand All @@ -215,6 +218,7 @@ def __init__(
self.low_res_flag = bool(lconfig.norm_low_res_flag)
self.back_flag = bool(lconfig.norm_back_flag)
self.two_backgrounds = bool(lconfig.norm_two_backgrounds)
self.const_q = bool(lconfig.const_q)

elif reduction_table_cell is not None:
self.tof_auto_flag = reduction_table_cell.tof_auto_flag
Expand All @@ -228,6 +232,7 @@ def __init__(
self.low_res_flag = reduction_table_cell.low_res_flag
self.back_flag = reduction_table_cell.back_flag
self.two_backgrounds = reduction_table_cell.two_backgrounds
self.const_q = reduction_table_cell.const_q

else:
pf = PeakFinderDerivation(list(range(len(self.ycountsdata))), self.ycountsdata)
Expand Down
39 changes: 11 additions & 28 deletions RefRed/calculations/update_reduction_table_metadata.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from qtpy import QtWidgets, QtCore
from RefRed.interfaces.mytablewidget import ReductionTableColumnIndex
from RefRed.reduction_table_handling.reduction_table_handler import ReductionTableHandler


class UpdateReductionTableMetadata(object):
Expand All @@ -18,36 +19,18 @@ def update(self):
q_range = lrdata.q_range
lambda_range = lrdata.lambda_range
incident_angle = lrdata.incident_angle
const_q = lrdata.const_q

[qmin, qmax] = q_range
str_qmin = "%.4f" % qmin
_item_min = QtWidgets.QTableWidgetItem(str_qmin)
_item_min.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
str_qmax = "%.4f" % qmax
_item_max = QtWidgets.QTableWidgetItem(str_qmax)
_item_max.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)

[lmin, lmax] = lambda_range
_item_lmin = QtWidgets.QTableWidgetItem(str(lmin))
_item_lmin.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
_item_lmax = QtWidgets.QTableWidgetItem(str(lmax))
_item_lmax.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)

incident_angle = incident_angle
str_incident_angle = "%.2f" % incident_angle
_item_incident = QtWidgets.QTableWidgetItem(str_incident_angle)
_item_incident.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)

parent.ui.reductionTable.setItem(row, 6, _item_min)
parent.ui.reductionTable.setItem(row, 7, _item_max)
parent.ui.reductionTable.setItem(row, 4, _item_lmin)
parent.ui.reductionTable.setItem(row, 5, _item_lmax)
parent.ui.reductionTable.setItem(row, 3, _item_incident)

def sortIntArray(self, _array):
[_element1, _element2] = _array
_element1 = int(_element1)
_element2 = int(_element2)
_element_min = min([_element1, _element2])
_element_max = max([_element1, _element2])
return [_element_min, _element_max]

handler = ReductionTableHandler(parent)
handler.set_table_item_text(row, ReductionTableColumnIndex.Q_MIN, str_qmin)
handler.set_table_item_text(row, ReductionTableColumnIndex.Q_MAX, str_qmax)
handler.set_table_item_text(row, ReductionTableColumnIndex.LAMBDA_MIN, str(lmin))
handler.set_table_item_text(row, ReductionTableColumnIndex.LAMBDA_MAX, str(lmax))
handler.set_table_item_text(row, ReductionTableColumnIndex.TWO_THETA, str_incident_angle)
handler.set_checkbox_state(row, ReductionTableColumnIndex.CONST_Q_BINS, const_q)
3 changes: 3 additions & 0 deletions RefRed/configuration/export_xml_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def main_part(self):
q_range = _data.q_range
lambda_range = _data.lambda_range
incident_angle = _data.incident_angle
const_q = _data.const_q

_norm: Optional[LRData] = _big_table_data[row, 1]
if _norm is not None:
Expand Down Expand Up @@ -176,6 +177,8 @@ def main_part(self):

str_array.append(o_general_settings.dead_time.to_xml(indent=" ") + "\n") # dead time settings

str_array.append(' <const_q>' + str(const_q) + '</const_q>\n')

str_array.append(' </RefLData>\n')

str_array.append(' </DataSeries>\n')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ def update_lrdata(self, lrdata=None, lconfig=None, type='data', row=0):

tof_auto_flag = lconfig.tof_auto_flag
tof_range = lconfig.tof_range
const_q = lconfig.const_q

# using lconfig values
lrdata.peak = [peak1, peak2]
Expand All @@ -134,6 +135,7 @@ def update_lrdata(self, lrdata=None, lconfig=None, type='data', row=0):
lrdata.tof_range = tof_range
lrdata.tof_auto_flag = tof_auto_flag
lrdata.full_file_name = full_file_name
lrdata.const_q = const_q

index_col = 0 if type == 'data' else 1
reduction_table_index_col = index_col + 1
Expand Down
15 changes: 6 additions & 9 deletions RefRed/configuration/loading_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typing import Any

# third party imports
from qtpy import QtGui, QtCore, QtWidgets
from qtpy import QtWidgets
from qtpy.QtWidgets import QFileDialog

# application imports
Expand All @@ -22,6 +22,7 @@
)
from RefRed.lconfigdataset import LConfigDataset
from RefRed.plot.clear_plots import ClearPlots
from RefRed.reduction_table_handling.reduction_table_handler import ReductionTableHandler
from RefRed.status_message_handler import StatusMessageHandler
from RefRed.tabledata import TableData
from RefRed.utilities import str2bool
Expand Down Expand Up @@ -233,6 +234,8 @@ def get_item_boolean(item_name: str, default) -> bool:
_lambda_max = self.getNodeValue(node, "to_lambda_range")
iMetadata.lambda_range = [_lambda_min, _lambda_max]

iMetadata.const_q = get_item_boolean("const_q", default=False)

iMetadata.tof_units = "micros"

_data_sets = self.getNodeValue(node, "data_sets")
Expand Down Expand Up @@ -299,14 +302,8 @@ def clear_display(self):
ClearPlots(parent=self.parent, is_data=True, is_norm=True, all_plots=True)

def clear_reductionTable(self):
nbr_row = self.parent.ui.reductionTable.rowCount()
nbr_col = self.parent.ui.reductionTable.columnCount()
_brush_color = QtGui.QBrush()
_brush_color.setColor(QtCore.Qt.black)
for _row in range(nbr_row):
for _col in range(1, nbr_col):
self.parent.ui.reductionTable.item(_row, _col).setText("")
self.parent.ui.reductionTable.item(_row, _col).setForeground(_brush_color)
reduction_table_handler = ReductionTableHandler(parent=self.parent)
reduction_table_handler.clear_reduction_table()

def populate_reduction_table_from_lconfigdataset(self):
PopulateReductionTable(parent=self.parent)
Expand Down
6 changes: 3 additions & 3 deletions RefRed/gui_handling/gui_utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# application imports
from RefRed import WINDOW_TITLE
from RefRed.interfaces.mytablewidget import ReductionTableColumIndex
from RefRed.interfaces.mytablewidget import ReductionTableColumnIndex
from RefRed.tabledata import TableData

if TYPE_CHECKING: # imported only when running mypy but not imported when the application is running
Expand Down Expand Up @@ -81,7 +81,7 @@ def get_current_table_reduction_check_box_checked(self) -> int:
-------
Row index, or `NULL_ACTIVE_ROW` if no row is active
"""
column_index = int(ReductionTableColumIndex.PLOTTED)
column_index = ReductionTableColumnIndex.PLOTTED
for row_index in range(self.parent.REDUCTIONTABLE_MAX_ROWCOUNT):
check_box: QtWidgets.QCheckBox = self.parent.ui.reductionTable.cellWidget(row_index, column_index)
if check_box.checkState() == Qt.Checked:
Expand Down Expand Up @@ -116,7 +116,7 @@ def get_other_row_with_same_run_number_as_row(

def get_norm_runnumber(table_row_index: int) -> str:
r"""run number of the direct beam run stored in row `index` of the reduction table"""
table_column_index = int(ReductionTableColumIndex.NORM_RUN)
table_column_index = ReductionTableColumnIndex.NORM_RUN
return str(self.parent.ui.reductionTable.item(table_row_index, table_column_index).text())

all_rows = [row]
Expand Down
32 changes: 29 additions & 3 deletions RefRed/initialization/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import socket

from RefRed import WINDOW_TITLE
from RefRed.interfaces.mytablewidget import ReductionTableColumnIndex
from RefRed.plot.all_plot_axis import AllPlotAxis
from RefRed.gui_handling.gui_utility import GuiUtility
from RefRed.gui_handling.update_plot_widget_status import UpdatePlotWidgetStatus
Expand All @@ -20,9 +21,10 @@ class Gui(object):
"\u03bbmax (\u00c5)",
"Qmin (1/\u00c5)",
"Qmax (1/\u00c5)",
"Const. Q Bin.",
"Comments",
]
column_widths = [60, 200, 200, 65, 85, 85, 95, 95, 400]
column_widths = [60, 200, 200, 65, 85, 85, 95, 95, 95, 300]
stitching_column_widths = [150, 60, 60]
gui_size_coeff = 2.0 / 3.0

Expand Down Expand Up @@ -132,7 +134,7 @@ def set_main_table(self):

for row_index in range(self.parent.REDUCTIONTABLE_MAX_ROWCOUNT):
for col_index in range(len(self.column_widths)):
if col_index == 0:
if col_index == ReductionTableColumnIndex.PLOTTED:
_widget = QtWidgets.QCheckBox()
_widget.setChecked(False)
_widget.setEnabled(True)
Expand All @@ -143,12 +145,36 @@ def set_main_table(self):
_widget.stateChanged.connect(_signal_func)

parent.ui.reductionTable.setCellWidget(row_index, col_index, _widget)
elif (col_index == 1) or (col_index == 2):
elif (col_index == ReductionTableColumnIndex.DATA_RUN) or (
col_index == ReductionTableColumnIndex.NORM_RUN
):
_item = QtWidgets.QTableWidgetItem()
_flags = QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsEditable
_item.setFlags(_flags)
parent.ui.reductionTable.setItem(row_index, col_index, _item)

elif col_index == ReductionTableColumnIndex.CONST_Q_BINS:
# Create checkbox
_widget = QtWidgets.QCheckBox()
_widget.setChecked(False)
_widget.setEnabled(True)
# connect handler to state change
_widget.stateChanged.connect(
lambda state=0, row=row_index: self.parent.reduction_table_const_q_handler(state, row)
)

# Create a layout to center the checkbox
_layout = QtWidgets.QHBoxLayout()
_layout.addWidget(_widget)
_layout.setAlignment(_widget, QtCore.Qt.AlignCenter) # Align the button to the center
_layout.setContentsMargins(0, 0, 0, 0)

# Create a QWidget to hold the layout
_container = QtWidgets.QWidget()
_container.setLayout(_layout)

parent.ui.reductionTable.setCellWidget(row_index, col_index, _container)

else:
_item = QtWidgets.QTableWidgetItem()
_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
Expand Down
7 changes: 4 additions & 3 deletions RefRed/interfaces/mytablewidget.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# standard imports
from enum import Enum
from enum import IntEnum

# third party imports
from qtpy import QtWidgets
Expand Down Expand Up @@ -29,7 +29,7 @@ def setUI(self, ui_parent):
self.parent = ui_parent


class ReductionTableColumIndex(Enum):
class ReductionTableColumnIndex(IntEnum):
"""
Enumeration class associating a column index to a word easy to understand what the column index is for
"""
Expand All @@ -42,7 +42,8 @@ class ReductionTableColumIndex(Enum):
LAMBDA_MAX = 5
Q_MIN = 6
Q_MAX = 7
COMMENTS = 8
CONST_Q_BINS = 8
COMMENTS = 9

def __int__(self):
return self.value
5 changes: 5 additions & 0 deletions RefRed/interfaces/refred_main_interface.ui
Original file line number Diff line number Diff line change
Expand Up @@ -4553,6 +4553,11 @@
<string>New Column</string>
</property>
</column>
<column>
<property name="text">
<string>New Column</string>
</property>
</column>
</widget>
</item>
</layout>
Expand Down
1 change: 1 addition & 0 deletions RefRed/lconfigdataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class LConfigDataset(object):

q_range = ['0', '0']
lambda_range = ['0', '0']
const_q = False

reduce_q_axis = []
reduce_y_axis = []
Expand Down
6 changes: 6 additions & 0 deletions RefRed/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from RefRed.preview_config.preview_config import PreviewConfig
from RefRed.reduction.live_reduction_handler import LiveReductionHandler
from RefRed.reduction.reduced_data_handler import ReducedDataHandler
from RefRed.reduction_table_handling.const_q_checkbox_handler import ConstQCheckBoxHandler
from RefRed.reduction_table_handling.reduction_table_check_box import ReductionTableCheckBox
from RefRed.reduction_table_handling.update_reduction_table import UpdateReductionTable
from RefRed.reduction_table_handling.reduction_table_right_click import ReductionTableRightClick
Expand Down Expand Up @@ -233,6 +234,11 @@ def logy_toggle_data_stitching(self, checked):
def reduction_table_visibility_changed_test(self, state, row):
ReductionTableCheckBox(parent=self, row_selected=row)

@config_file_has_been_modified
def reduction_table_const_q_handler(self, state, row):
"""Handles updating stored configuration upon change in const Q checkbox state"""
ConstQCheckBoxHandler(parent=self, row=row, state=state)

def file_loaded(self, row, is_data_displayed, is_display_requested):
"""Event call-back used to display plots and re-enable the reduction table after loading"""
if is_display_requested:
Expand Down
5 changes: 5 additions & 0 deletions RefRed/reduction/individual_reduction_settings_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def retrieve(self):

self._tof_range = self.get_tof_range()
self._output_workspace_name = self.define_output_workspace_name(run_numbers=self._data_run_numbers)
self._const_q = self.get_const_q()

def to_dict(self):
"""
Expand Down Expand Up @@ -77,6 +78,7 @@ def norm_setting(setting: str) -> Optional[Any]:
norm_x_range_flag=self._norm_low_res_flag,
norm_x_range=self._norm_low_res_range,
tof_range=self._tof_range,
const_q=self._const_q,
)
return pars

Expand Down Expand Up @@ -200,3 +202,6 @@ def get_data_run_numbers(self):
def get_run_numbers(self, column_index=1):
run_numbers = self.parent.ui.reductionTable.item(self.row_index, column_index).text()
return str(run_numbers)

def get_const_q(self):
return bool(self.data.const_q)
Loading

1 comment on commit ba6e8e4

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitLab pipeline for refred-dev has been submitted for this commit: "https://code.ornl.gov/sns-hfir-scse/deployments/conda-legacy-deploy/-/pipelines/644563"

Please sign in to comment.