spacr.qt.widgets.object_settings_grid¶
The repeated per-object settings, drawn as one row per question.
78 of Mask’s 201 settings are the SAME twenty-odd questions asked once per
object type – cell_diameter, nucleus_diameter,
pathogen_diameter, organelle_diameter – and a form that lists them
flat asks 203 questions before anything is segmented. A table was chosen over
tabs and over leaving the names flat.
spacr.object_settings_table is the model and draws nothing; this is
the view over it. The split matters more than it looks: the stored keys never
change, so no settings file, notebook, tutorial or spacr-run invocation
migrates. What was wrong was the presentation, so only the presentation
changes.
WHY THIS SHAPE IS WHAT LETS AN ARBITRARY ORGANELLE COUNT LAND. The number of
organelles a run may declare is not fixed. In a flat vocabulary each new organelle is twenty new
settings that every tooltip table and translation catalog has to learn; here
it is one COLUMN, and the number of questions does not move.
ObjectSettingsGrid.add_object() is that operation, and it starts a new
organelle from the first one’s answers rather than from a global default
nobody chose.
TWO THINGS THIS VIEW IS CAREFUL ABOUT, both of which would corrupt a settings file rather than merely look wrong:
A value keeps its type.
cell_diameteris an int,organelle_ cellprob_thresholdis a float, and a cell edited in a table arrives as a string. Writing"12"where12was is a settings file that has quietly changed meaning, and the pipeline reading it either coerces silently or fails a long way from here.A question an object does not ask stays absent.
cytoplasmhas no channel, no diameter and no detection method – it is DERIVED, cell minus the rest, not found in a channel. Those cells are blank and not editable, because writing a value there invents a key nothing reads.
Classes¶
The per-object settings table, and the button that widens it. |
|
One row per question, one column per object type. |
Module Contents¶
- class spacr.qt.widgets.object_settings_grid.ObjectSettingsGrid(parent=None)[source]¶
Bases:
PySide6.QtWidgets.QWidgetThe per-object settings table, and the button that widens it.
- Parameters:
parent – parent widget.
Build the per-object settings grid.
Sorting is installed after the model is set, as the contract requires – the view is wrapped in a proxy, so the selection model has to be taken afterwards. Sorting the questions on screen reorders nothing on disk, because the stored answers are read from the model rather than the view.
The table opens tall enough to show its rows and can be dragged from the grip: inside a settings panel it is one row of a scrolling form, and a plain
QTableViewdefault put twenty-odd questions behind an inner scrollbar inside an outer one.- Parameters:
parent – parent widget, or
None.
- add_filter(name: str) bool[source]¶
Add a filter row for regionprop
name, every cell empty.- Parameters:
name – a scalar scikit-image regionprop, e.g.
"area"or"intensity_mean"; legacy spellings are accepted.- Returns:
False when the name is not a filterable property or the row is already there.
- add_organelle() bool[source]¶
Add the next organelle column, seeded from the first one.
- Returns:
False when there is no slot left, with the reason on screen rather than as an exception into a GUI slot.
A slot whose channel is unset is hidden.
- choose_model_for(obj: str) bool[source]¶
Open the model zoo for one object and store what it returns.
- Parameters:
obj – object name whose
model_namecell receives the chosen path, e.g."cell".- Returns:
True when a model was chosen. Cancelling leaves the cell alone rather than clearing it – a cancelled dialog is not an instruction to forget the model already set.
- eventFilter(watched, event)[source]¶
Show the same sticky, linked tooltip the form shows.
THE SAME POPUP, NOT A SECOND ONE. The flat form puts rich help on a widget and lets
HoverTooltipdraw it: a typed body, an API link, and the setting’s animation when it has one. A table has no widget per cell, so the anchor is the view and the cell under the pointer decides which setting it is speaking for.The native tooltip is swallowed for the same reason the form swallows it – it disappears the moment the pointer moves toward the API link, and that link is the point.
- Parameters:
watched – the object the filter is installed on: this widget (font changes), the help band (enter and leave) or the table’s viewport (tooltip, mouse move and leave).
event – the event; a tooltip event on the viewport is swallowed and every other event is passed on to the base class.
- filter_properties() Tuple[str, ...][source]¶
The properties the table has a filter row for, in order.
- next_organelle() str[source]¶
The role the next organelle column would take, or
''.Empty at the ceiling. Slot names are lettered – an object type is embedded in an underscore-separated object key, so a digit would be ambiguous against the object LABEL – and the lettering CARRIES past
z, so the ceiling is where two letters run out rather than one.COUNTS UP FROM THE SLOTS IN USE rather than from one. Walking every slot from the start was fine while there were 26; there are now 702, and the caller that presses Add repeatedly turned an O(slots) scan into an O(slots squared) one.
Hidden slots count as in use too.
- set_app_key(app_key: str) None[source]¶
Say which module’s API documentation the tooltips should link to.
- Parameters:
app_key – registry key of the module, e.g.
"mask";Noneor empty clears it.
- set_filters(value) None[source]¶
Show
object_filtersas it now stands, e.g. after a file load.- Parameters:
value – the setting’s value, a mapping or its text.
- set_settings(settings: Mapping[str, Any]) None[source]¶
Show the per-object half of a flat settings dict.
The rest is KEPT, not dropped:
settings()returns it unchanged beside the table’s own keys, so this widget can edit a corner of a settings file without holding the whole of it hostage.- Parameters:
settings – flat settings dict, or
None; its<object>_<question>keys become the table.
- set_user_height(height: int) None[source]¶
Fix the table at
heightpx, clamped to at least MIN_TABLE_H.- Parameters:
height – wanted table height in pixels.
- set_value(question: str, obj: str, text: str) bool[source]¶
Type into one cell the way the editor would.
The screen’s own edit path, exposed so a test drives the same code an item delegate does rather than reaching into the model.
- Parameters:
question – settings question, i.e. the key suffix shared by every object (
"min_area"forcell_min_area).obj – object name, the key prefix (
"cell","nucleus", …).text – what the user would type; converted to the type of the cell’s current value (or a sibling’s). Returns
Falsefor an unknown row or column, a cell the object does not ask, or no change.
- class spacr.qt.widgets.object_settings_grid.ObjectSettingsModel(parent=None)[source]¶
Bases:
PySide6.QtCore.QAbstractTableModelOne row per question, one column per object type.
A model rather than a widget full of cells because the table is 55 rows by as many objects as the run has, and every one of those cells would otherwise be a widget the form has to build, lay out and translate.
- Parameters:
parent – parent widget.
Create the empty per-object settings table model.
- Parameters:
parent – parent object, or
None.
- asks(question: str, obj: str) bool[source]¶
Whether
objasksquestionat all.Absence is a fact about the object, not a value it has yet to be given: cytoplasm is derived and has no channel to be found in.
- Parameters:
question – settings question, i.e. the key suffix shared by every object (
"min_area"forcell_min_area).obj – object name, the key prefix (
"cell","nucleus", …).
- columnCount(parent=QModelIndex()) int[source]¶
How many objects the table has a column for.
- Parameters:
parent – unused; the model is flat.
- Returns:
the column count.
- data(index, role=Qt.DisplayRole)[source]¶
One cell of the table.
- Parameters:
index – the cell.
role – the Qt display role.
- Returns:
the cell’s value for that role, or None.
- flags(index)[source]¶
Which cells are editable.
ONLY THE CELLS AN OBJECT ACTUALLY ASKS. A blank cell means that object does not ask that question, and making it editable would invite an answer to a question nobody posed.
- Parameters:
index – the cell.
- Returns:
the Qt item flags.
- headerData(section, orientation, role=Qt.DisplayRole)[source]¶
One header label: a question name, or an object name.
- Parameters:
section – the row or column number.
orientation – which header.
role – the Qt display role.
- Returns:
the label, or None.
- question_at(row: int) str[source]¶
The settings question one row asks, or
''.- Parameters:
row – zero-based table row; out of range gives
''.
- rowCount(parent=QModelIndex()) int[source]¶
How many questions the table asks.
- Parameters:
parent – unused; the model is flat.
- Returns:
the row count.
- setData(index, value, role=Qt.EditRole) bool[source]¶
Write one cell back into the settings.
- Parameters:
index – the cell.
value – what the user typed.
role – the Qt edit role.
- Returns:
True when the value was taken.