spacr.qt.screens.measure_inputs¶
The window the FEATURES button in Make Masks opens.
Three things stacked, and the order is the order the questions come in:
spacr.qt.widgets.measure_input_table.MeasureInputTable– which file is which channel, and which is which object.The Measure module’s OWN settings form, built from
spacr.qt.screens.settings_model.SettingsWidgets. Not a copy of it and not a chosen subset: the same widgets the Measure screen builds, from the same defaults, so a setting that exists there exists here and a setting that gains a control there gains one here without this file being edited.Run, off the GUI thread, through
spacr.measure.measure_from_field_table()– which writes the folders the Mask module would have written and then callsmeasure_cropitself. The database and the folder tree are Measure’s because Measure makes them.
IT IS A QDialog, AND THAT IS WHAT MAKES IT LOOK LIKE spaCR. It used to
be a bare QWidget shown with the Qt.Window flag, which meant the
operating system’s own title bar, square corners, an opaque background and
minimise/maximise/close buttons – a window from a different program sitting
in the middle of this one. spacr.qt.widgets.glass gives every dialog
in the package the translucent card, the rounded corners and the travelling
rim, and it recognises a dialog by its TYPE. So the dress is not applied
here; being a dialog is.
Its actions are at the bottom right, in the order every spaCR dialog uses:
the thing you came to do in the accent colour (Measure, PrimaryButton),
and the way out in red beside it (Close, DangerButton). Escape is the
other way out, and closes rather than hides – see reject().
THE SETTINGS THE TABLE DECIDES ARE SHOWN AND DISABLED rather than hidden.
cell_mask_dim is not a question once the table says which column holds
the cell masks, but a user who has read the Measure documentation comes here
looking for it, and a control that is missing reads as a feature that is
missing. Shown, filled in, and not editable says the table already answered
it. spacr.measure.FIELD_TABLE_DECIDED_KEYS is the list, and it is
derived from the plane order rather than written out again here.
Classes¶
Table, Measure's settings, and a Run that goes through Measure. |
Functions¶
|
Open the FEATURES window, owned by |
|
Write one value into whichever kind of control holds it. |
Module Contents¶
- class spacr.qt.screens.measure_inputs.MeasureInputsScreen(parent: PySide6.QtWidgets.QWidget | None = None, *, threaded: bool = True)[source]¶
Bases:
PySide6.QtWidgets.QDialogTable, Measure’s settings, and a Run that goes through Measure.
- Parameters:
parent – parent widget, or
None.threaded –
Falseruns the measurement inline, emitting the same signals in the same order, so a test can drive the whole window synchronously without the behaviour diverging.
- Variables:
run_finished – emitted with the result dict when a run completes, or with
Nonewhen it failed.
Build the window and its three parts.
- apply_settings_dict(settings: Dict[str, Any]) int[source]¶
Write
settingsinto the panel’s controls.The same contract
spacr.qt.screens.app_screen.AppScreen.apply_settings_dict()has, so a settings pack saved from the Measure screen loads here.- Parameters:
settings – the values to write. Keys with no control are ignored.
- Returns:
how many controls took a value.
- closeEvent(event)[source]¶
Stop the run’s threads before Qt destroys the widgets.
Qt ABORTS THE PROCESS if a running
QThreadis destroyed, and this window is closable while a measure run – minutes of work – is in flight.spacr.qt.job_runner.shutdown_all()covers the application quitting; it does not cover one window being closed.- Parameters:
event – the Qt close event.
- derived_settings() Dict[str, Any][source]¶
The settings a run would use: the panel’s, over-written by the table.
The same call the run makes, so what this returns is what would happen rather than a second opinion about it.
- done(result)[source]¶
Stop the run whichever way the window is dismissed.
THE HOOK IS
doneAND NOTreject, and notcloseEventalone. Escape reachesreject, which hides the window WITHOUT a close event, and that would leave a measure run – minutes of work, on a thread – going behind a window nobody can see; a runningQThreaddestroyed at exit aborts the process. Overridingrejectto close instead looks like the fix and is a loop:QDialog.closeEventitself callsreject.- Parameters:
result – Qt’s dialog code, passed straight on.
- run() bool[source]¶
Measure the table, off the GUI thread.
- Returns:
whether a run was started. A table with problems in it starts nothing and says what they are.
- spacr.qt.screens.measure_inputs.open_measure_inputs(owner: PySide6.QtWidgets.QWidget | None = None, *, folder: str | None = None, threaded: bool = True) MeasureInputsScreen[source]¶
Open the FEATURES window, owned by
owner’s window.- Parameters:
owner – the screen the button is on, so Qt keeps the window alive for as long as that screen is and closes it with the application.
folder – the folder the user is drawing in. Its files are offered to the table straight away, because a user who pressed FEATURES from an open folder means that folder.
threaded –
Falseruns the measurement and the folder walk inline; for tests.
- Returns:
the window, already shown.
THE FOLDER IS NOT READ HERE. This runs in the Make Masks button handler, on the GUI thread, and
folderis a path the user chose – on a microscope rig, the share the images live on. It used toisdirandlistdirit and stat every entry before the window was even shown, so pressing FEATURES on a folder living on a sleeping automount froze the application with no traceback. The walk isMeasureInputTable.add_dropped()’s, on a worker, and the table fills in a moment later.
- spacr.qt.screens.measure_inputs.write_setting_value(widget, value) bool[source]¶
Write one value into whichever kind of control holds it.
THE TRAP THIS EXISTS FOR: only some of the settings controls carry a
set_valuemethod.cell_min_sizeis a plainQSpinBox, and a writer that testshasattr(widget, 'set_value')skips it – silently, leaving the default 8000 in place. A run configured that way measures nothing and reports success, because every object was smaller than a minimum nobody chose.The coercions are the ones
spacr.qt.screens.app_screen.AppScreen._apply_value()makes, kept in step with it by hand. They are not shared yet because that method is bound to a screen this window is not one of; if a third caller appears, move it rather than copying it again.- Parameters:
widget – the control to write into.
value – the value, coerced to the control’s own type and left alone when it cannot be.
- Returns:
whether the control took it.
Nested helpers¶
- MeasureInputsScreen.run.work()¶
Run the measurement. Worker thread; touches no widget.
The table it measures is a SNAPSHOT taken above, not the widget’s live model. A measure run takes minutes and preparing the next batch while it runs is the natural thing to do, so the GUI thread can append rows and delete channel and mask keys underneath this – which reaches the worker as a
KeyErrorin the middle of writing, or as half a field that nobody asked for. The snapshot is plain data, so copying it is cheap and it cannot be edited from anywhere.spacr/qt/screens/measure_inputs.py:447