18 Commits
Author SHA1 Message Date
duan_jandClaude Fable 5.1 d70cac45bf fix(gui): keep the file-name preview in the plain theme color
CI / lint (push) Skipped
CI / lint (pull_request) Successful in 1m18s
CI / test (3.12) (push) Skipped
CI / test (3.13) (push) Skipped
CI / test-with-beamline-plugins (pxi_bec) (push) Skipped
CI / test-with-beamline-plugins (pxii_bec) (push) Skipped
CI / test-with-beamline-plugins (pxiii_bec) (push) Skipped
CI / test (3.12) (pull_request) Failing after 1m4s
CI / test (3.14) (pull_request) Successful in 1m7s
CI / test (3.13) (pull_request) Successful in 1m15s
CI / test-with-beamline-plugins (pxi_bec) (pull_request) Successful in 1m17s
CI / test-with-beamline-plugins (pxii_bec) (pull_request) Successful in 1m17s
CI / test-with-coverage (pull_request) Successful in 1m35s
CI / test-with-beamline-plugins (pxiii_bec) (pull_request) Successful in 1m40s
CI / coverage-analysis (pull_request) Successful in 4s
Dawn: the red "file exists" tint on the path label reads as an error
across the whole panel. The Run guard's popup already reports a clash,
so the label stays in the standard text color. The popup now also asks
the user to run the data collection again after the run number bump.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 18:44:56 +02:00
duan_jandClaude Fable 5.1 010513e141 fix(gui): reach the file-exists guard from every tab, test exact names
The tabs are handed parent=DataCollectionSettings but
QStackedWidget.addWidget() reparents them to the stack, so the guard's
parent() lookup never found file_path_panel and every Run (rotation,
screening, raster, X-ray centering, Simple) skipped the check. Lookup
now walks up the widget tree; regression test drives all five runs
through the real DataCollectionSettings.

The "taken" test is exact again: <run>_master.h5 plus the DAQ's
derived <run>_raster2d/_raster1d_master.h5. The directory test and the
_*_master.h5 glob are gone: neither is a file a run writes, and they
painted run numbers red that nothing would ever produce.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 18:44:56 +02:00
duan_jandClaude Fable 5.1 646de67291 fix(gui): make the file-exists guard literal: popup, run +1, no scan
update_filename() still skipped to the next free run number on every
edit and refresh, so the name was always free by the time Run was
clicked and the guard never fired. The name is now exactly what the
fields say (label turns red on a clash); on Run, an existing target
pops "File already exists", bumps the run number by one and does
nothing else.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 18:44:56 +02:00
duan_jandClaude Fable 5.1 8798a81555 fix(gui): pop up "File already exists" instead of silently bumping the run
The Run guard called set_scan_kind(), which runs update_filename() and
skips to the next free run number before the existence check, so the
check never fired and the scan started under a new number without a
word. Now the check runs first, then a warning box names the existing
master file and the run number it moved to, and the run is blocked.

- Simple tab "Run rotation" had no guard at all; same guard added
- "Taken" also matches <run>_*_master.h5: X-ray Centering writes
  <run>_raster2d_master.h5, which the exact name missed
- Camera context-menu "Evaluate grid" presses the panel button, so it
  gets the guard and stays inert while the button is disabled
- Dead next_free_run_from() removed

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 18:44:56 +02:00
duan_jandClaude Fable 5 1fe3c7f4e5 refactor: transmission is a per-mode setting, placed in its section
The shared "Rotation transmission" row sat in the top rows of BOTH the
Gridscan and Rotation tabs, where it read as one setting for everything
(and as nonsense in the Gridscan tab). Now each tab places its own row:
Gridscan keeps "Transmission" with the shared resolution/distance rows,
and the Rotation tab moves "Rotation transmission" below the Screening
block and its Run button, as the first row of the Rotation section -
next to the fields it actually applies to. Screening keeps its separate
"Screening transmission". No behavior change: same field, same
spreadsheet/user-value handling, only the label and the placement.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-14 13:23:32 +02:00
duan_jandClaude Fable 5.1 f1cf55adb9 fix: take the aareDB transmission as the fraction aarecommon >= 0.7 declares
CI / lint (push) Successful in 1m11s
Docs build and publish / docker (push) Successful in 4s
CI / test (3.12) (push) Canceled after 1m22s
CI / test (3.13) (push) Canceled after 1m3s
CI / test (3.14) (push) Canceled after 1m0s
CI / test-with-beamline-plugins (pxii_bec) (push) Canceled after 55s
CI / test-with-beamline-plugins (pxi_bec) (push) Canceled after 56s
CI / test-with-beamline-plugins (pxiii_bec) (push) Canceled after 31s
CI / test-with-coverage (push) Canceled after 23s
CI / coverage-analysis (push) Canceled after 0s
Build and Publish / release (push) Successful in 17s
CI resolves aarecommon 0.7.3, where DataCollectionParameters.transmission
is a 0-to-1 fraction that rejects anything above 1.0 (the percent sheets
are converted inside AareDB >= 0.83, which main already requires). The
divide-by-100 from the earlier 'percentage' fix therefore failed the
model test on CI and would have turned 20% into 0.2% at the beamline.
Pass the fraction through and pin aarecommon>=0.7.3 so the older int
percentage model can no longer be installed; relock.

Also satisfy the diff typecheck gate: basedpyright only counts instance
variables assigned in __init__, so the Database/User toggle widgets are
created there and _build_source_toggle only lays them out.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 11:56:57 +02:00
leonarski_fandClaude Opus 5 63d902a82a fix: read the aareDB transmission as the percentage it is
DataCollectionParameters.transmission is a StrictInt documented as
"positive, between 0 and 100" (aareDB's own API description of the
spreadsheet payload), while every model that consumes it wants a 0-to-1
fraction. The old "divide by 100 only when above 1.0" guess therefore
turned a spreadsheet asking for 1% into a scan at 100% transmission -
a hundredfold dose on the sample. A fraction cannot be stored in that
column at all: the model rejects 0.2.

The mapping test now builds a real DataCollectionParameters instead of a
stand-in namespace, so a renamed column fails the test rather than the
beamline. That is what let 'totalrange' through.

daq.py's spreadsheet_params and get_auto_raster_params still carry both
the old column name and the same transmission guess.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JHoUkj66jxByS2ypY5h9Mn
2026-09-08 11:56:57 +02:00
leonarski_fandClaude Opus 5 7cc662bfd8 fix: read the aareDB total angle from the column that exists
The column is totalangle, not totalrange, so reading it raised
AttributeError four times a second in the status loop.

Reading a spreadsheet cell now goes through _spreadsheet_float, which
treats a missing column, an empty cell and a cell that does not hold a
number all as "not set" and logs the column once. aareDB owns these
names; the GUI should fall back to its defaults when one moves, not die
on the status loop it is read from.

Note that the same misspelling is still in daq.py (spreadsheet_params
and get_auto_raster_params), where getattr's default hides it: automation
has never picked up the total angle from the spreadsheet either.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JHoUkj66jxByS2ypY5h9Mn
2026-09-08 11:56:57 +02:00
leonarski_fandClaude Opus 5 8833f3a9d1 fix: keep user values in the scan panels across sample mounts
The panels kept the effective detector distance, resolution and
transmission in their own attributes, and a sample change overwrote those
from the spreadsheet whatever the Database/User toggle said. The fields
went on showing the user's numbers while the scan request carried the
database ones, so a value had to be re-entered after every mount.

The fields are now the only place a value lives. Each setting is worth,
in order: what the user typed while "User values" is selected, what the
mounted sample asks for, the panel default - one rule, ScanSettingsPanel
._setting, that each panel spells out a line at a time. Overrides are per
setting, so a setting the user did not touch keeps following the sample.

Along the way:

* DbOverrideLineEdit is gone; the panels use NumberLineEdit directly, and
  the per-widget database/user bookkeeping is replaced by SampleParameters,
  the one place that knows the aareDB spreadsheet column names.
* The (name, widget, converter) mapping loops with getattr/hasattr are
  replaced by explicit per-field commit slots.
* The omega speed cap no longer drives one field's validator from another
  field's value: it is a read-out plus a check on the pair at Run time.
* _add_row/_add_pair_row build the label/field/unit rows, which also puts
  the Total angle degree sign on its own row instead of the header above.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JHoUkj66jxByS2ypY5h9Mn
2026-09-08 11:56:57 +02:00
duan_j a19cbf1081 test: no need to test energy 0 and update tolerance
CI / lint (pull_request) Successful in 53s
CI / test (3.11) (pull_request) Successful in 58s
CI / test (3.13) (pull_request) Successful in 59s
CI / test (3.12) (pull_request) Successful in 1m3s
CI / test-with-beamline-plugins (pxi_bec) (pull_request) Successful in 1m12s
CI / test-with-beamline-plugins (pxii_bec) (pull_request) Successful in 1m14s
CI / test-with-beamline-plugins (pxiii_bec) (pull_request) Successful in 1m18s
CI / test-with-coverage (pull_request) Successful in 1m29s
CI / coverage-analysis (pull_request) Successful in 3s
CI / lint (push) Successful in 34s
Docs build and publish / docker (push) Successful in 17s
CI / test (3.11) (push) Canceled after 37s
CI / test (3.12) (push) Canceled after 36s
CI / test (3.13) (push) Canceled after 32s
CI / test-with-beamline-plugins (pxi_bec) (push) Canceled after 31s
CI / test-with-beamline-plugins (pxii_bec) (push) Canceled after 27s
CI / test-with-beamline-plugins (pxiii_bec) (push) Canceled after 26s
CI / test-with-coverage (push) Canceled after 22s
CI / coverage-analysis (push) Canceled after 0s
Build and Publish / release (push) Successful in 20s
test: update test...
2026-08-24 19:24:29 +02:00
duan_jandClaude Fable 5 b984a36f7c fix: energy spin movestate colors never rendered
The movestate property sat on the spinbox's inner QLineEdit, which both
themes deliberately paint transparent (QAbstractSpinBox QLineEdit rule)
- the state machine worked but no color ever showed, and the tests only
asserted the property, not the paint. The property now lives on the
spinbox itself with QAbstractSpinBox[movestate=...] added to both
themes' rules, verified by a pixel-sampling regression test that grabs
the rendered widget through the real stylesheet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 19:24:29 +02:00
duan_jandClaude Fable 5 e1d11aa949 feat: MotorMoveGroup semantics for both Set Energy rows
The energy setpoint applies via the Change Energy button, not Enter, so
it gets the full motor state machine instead of the typing-pending
color: neutral tracks the readback, a user edit stages pending (and is
the only thing that enables the button), the click turns moving, and
readback arrival within tol returns to neutral. New SpinMoveState in
motor_move_group.py adapts the pattern to a QDoubleSpinBox+button pair
(colors ride the movestate QSS via the spin's internal QLineEdit);
replaces the hand-rolled pending-until-click in the exp-config row and
covers the Beamline setup row that had no color at all. The server's
0.0 detector-unavailable energy is kept out of the readback feed so it
cannot clamp the spin to the range minimum.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 19:24:29 +02:00
duan_jandClaude Fable 5 225d7064c4 feat: bound Set Energy to a 4-20 keV placeholder range
Both Set Energy rows allowed 1-30 keV, an arbitrary spinbox default;
nothing downstream validates the request (daq.change_energy forwards
straight to bec). Shared ENERGY_MIN/MAX_KEV constants now bound both
spins to 4-20 keV with a tooltip flagging the range as pending
Beamline Scientist confirmation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 19:24:29 +02:00
duan_jandClaude Fable 5 3e7c334abb feat: pending color while typing in Experiment configuration values
Values inside the Experiment configuration banner now show the same
pending color as the motor move boxes while the typed text differs from
the applied value; Enter (or focus-out) commits as before and clears it.
Opt-in via NumberLineEdit(track_pending=True) because MotorMoveGroup
owns the movestate property on its registered boxes; reuses the existing
movestate QSS, so no new styling. The Set Energy spinbox marks pending
until Change Energy is clicked, since its apply gate is the button.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 19:24:29 +02:00
duan_jandClaude Fable 5 36675e0204 feat: auto-centering row with apply-after-mount, grid button raster-only
Auto Centering moves out of the experiment tabs to its own row between
Manual sample and Exp. Config., with an apply-after-mount checkbox that
re-runs it on every detected sample mount (guarded against firing on GUI
startup). Draw a Grid now only shows on the Raster scan tab.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 19:54:50 +02:00
perl_d b0863e5ddb style: format with ruff
Build and Publish / test (pull_request) Failing after 1m23s
Build and Publish / build (pull_request) Skipped
Build and Publish / Build and Deploy Docs (pull_request) Skipped
2026-07-06 11:53:49 +02:00
perl_d 13bddd43c7 refactor: use aarecommon and remove common 2026-07-06 11:53:49 +02:00
appleb_mandClaude Opus 4.8 476aa69d70 data collection settings: panel-level Database/User-values toggle
Add DbOverrideLineEdit: a numeric field holding both a database value and
the user's value, driven by a per-tab Database/User-values toggle. The
user's value persists across samples, can be reverted to the database
value, and recovered again - replacing the clunky per-field checkboxes.

Fix the dtz<->resolution coupling so editing one updates the other in both
Database and User modes (previously it broke whenever a value was
overridden). Wire resolution, detector distance, transmission, exposure,
rotation total/image angle and the raster grid element size through the
new widget; other panels are untouched.

Add tests covering persist/revert/recover, the toggle's downstream emit,
the dtz/resolution coupling in both modes, and cross-sample persistence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 15:30:08 +02:00