From a2c5ed3d5cb9fb622e5ac3abf6aae705de727dde Mon Sep 17 00:00:00 2001 From: Dawn Date: Wed, 9 Sep 2026 15:27:59 +0200 Subject: [PATCH] feat: show spreadsheet params in sample list Add Oscillation, Exposure, Total range and Transmission columns to the dewar sample table, read from SampleShortInfo.aaredb_params (already filled by spreadsheetupdater from AareDB, so no server change). Transmission is shown as percent like the user spreadsheet. The new columns are nullable, so the header sort key now puts None last instead of raising on None < float. Co-Authored-By: Claude Fable 5.1 --- src/aare/gui/models/user_sample_model.py | 26 ++++++++++++++++++++++-- tests/unit/gui/test_models.py | 25 +++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/aare/gui/models/user_sample_model.py b/src/aare/gui/models/user_sample_model.py index 0d25a5ce..78699887 100644 --- a/src/aare/gui/models/user_sample_model.py +++ b/src/aare/gui/models/user_sample_model.py @@ -43,7 +43,19 @@ def get_entry(sample: SampleShortInfo, column: int): return sample.screening_count elif column == 10: return sample.rotation_count + # Data-collection params straight from the AareDB spreadsheet (filled by + # spreadsheetupdater). Nullable: samples without params show blank. elif column == 11: + return sample.aaredb_params.oscillation if sample.aaredb_params else None + elif column == 12: + return sample.aaredb_params.exposure if sample.aaredb_params else None + elif column == 13: + return sample.aaredb_params.totalangle if sample.aaredb_params else None + elif column == 14: + # Model holds a 0-1 fraction; users think in spreadsheet percent. + t = sample.aaredb_params.transmission if sample.aaredb_params else None + return None if t is None else round(t * 100, 1) + elif column == 15: return sample.comment return "" @@ -74,6 +86,10 @@ class UserSampleSpreadsheet(QAbstractTableModel): # collected, so Screening sits left of Rotation. "Screening count", "Rotation count", + "Oscillation (°)", + "Exposure (s)", + "Total range (°)", + "Transmission (%)", "Comment", ] self.current_sample = current_sample @@ -261,10 +277,16 @@ class UserSampleSpreadsheet(QAbstractTableModel): ), # Reverse for descending order ) else: - # Sort the samples based on the specified column and order + # Sort the samples based on the specified column and order. + # Nullable columns (params, comment): None sorts last, never + # compared against a real value (None < float raises). + def _key(row): + v = get_entry(row, self._sort_col) + return (v is None, "" if v is None else v) + self._sorted_samples = sorted( filtered, - key=lambda row: get_entry(row, self._sort_col), + key=_key, reverse=( self._sort_order == Qt.SortOrder.DescendingOrder ), # Reverse for descending order diff --git a/tests/unit/gui/test_models.py b/tests/unit/gui/test_models.py index 95c634bc..e36b10df 100644 --- a/tests/unit/gui/test_models.py +++ b/tests/unit/gui/test_models.py @@ -263,3 +263,28 @@ def test_mime_data_round_trips_for_chip_drops(status_model): samples = SampleShortInfoList.model_validate_json(payload.text()) assert len(samples.s) == 2 assert samples.s[0].db_id == model.get_id(0).db_id + + +def test_spreadsheet_param_columns(status_model): + from aarecommon.models.models import DataCollectionParameters + + model = status_model + hdr = model.header + osc, exp, tot, trans = ( + hdr.index("Oscillation (°)"), + hdr.index("Exposure (s)"), + hdr.index("Total range (°)"), + hdr.index("Transmission (%)"), + ) + model.get_id(_row_of(model, 1)).aaredb_params = DataCollectionParameters( + oscillation=0.1, exposure=0.01, totalangle=360, transmission=0.125 + ) + row = _row_of(model, 1) + d = lambda c: model.data(model.index(row, c), Qt.ItemDataRole.DisplayRole) + assert (d(osc), d(exp), d(tot), d(trans)) == (0.1, 0.01, 360, 12.5) + # No params -> blank, and sorting a mostly-None column must not raise; + # the real value sorts first. + assert model.data(model.index(_row_of(model, 2), osc), Qt.ItemDataRole.DisplayRole) is None + model.sort(osc, Qt.SortOrder.AscendingOrder) + assert model.get_id(0).db_id == 1 + assert model.headerData(hdr.index("Comment"), Qt.Orientation.Horizontal, 0) == "Comment"