Edit on GitHub

starplast.slot_tree

A window showing every slot, its place in the tree, and what fills it.

Why this exists

The slot catalog is 222 entries across three hierarchies and two organisms. Every check run on it so far was a Python one-liner written for the occasion and thrown away -- which is how the first audit reported a leak that did not exist, because the one-liner reimplemented pattern matching instead of calling slots.declared_columns.

A sanity check nobody can see is a sanity check nobody performs. This is the audit made permanent and visible: open it and the shape of the whole catalog is in front of you, including the parts that are empty -- which are the most informative parts, and the reason the empty rows are coloured rather than hidden.

The rule this module follows

Nothing here reimplements the catalog. The tree comes from slots.relationship_tree, the columns from slots.declared_columns, the coverage from slots.resolve, and whether a slot is filled from slots.is_filled. A second copy of that logic in GUI code is a second thing to keep in step, and it would not be kept in step -- the window would then disagree with the pipeline while looking authoritative, which is worse than having no window.

It opens with no data

nodes=None is a supported state, not a degenerate one. This is the tool for inspecting an arm before its table exists, and a viewer that needs data to show a slot cannot show the arm that most needs looking at. With no table, coverage is blank and the catalog is still fully browsable.

ALARMS = {'empty': ('slots with no data', 'A slot nothing fills. This is the map of what has not been measured yet, and it is the most useful number in this window -- an empty slot is a question with a known shape, which is what makes it findable.'), 'double': ('columns claimed twice', "A column matched by two slots' patterns. Zero today, and it must stay zero: a column answering two questions means holding one out does not hold the other out, which is how a held-out feature leaks back into the map that was built on it."), 'orphan': ('columns claimed by nobody', "A column in the table that no slot's patterns match. Zero today. A column nothing claims is a measurement the catalog cannot describe, so it can never be held out, audited or reported."), 'citation': ('candidates with no accession', 'A candidate naming a paper but no downloadable accession. A citation nobody can fetch is not a filled slot, and this count exists so that it cannot read as one.')}
HEADINGS = [('slot', 'The question, at its address in this hierarchy. Group rows aggregate what is beneath them; leaves are slots.'), ('grade', 'Evidence grade of the filling data: A measured in this organism, B measured nearby and transferred, C predicted or derived. A dash means nothing fills it.'), ('genes', 'How many genes carry a value, computed live from the loaded table by `slots.resolve` -- not read from a generated CSV, which could be stale.'), ('coverage', 'That count as a share of the table.'), ('what fills it', "The columns this slot's patterns match in the loaded table, or the candidate sources when nothing does.")]
def shipped_sources() -> dict:

Every table and graph the catalog is graded against, keyed by organism.

Loaded here rather than taken from the window, because this viewer must be able to show an arm the open window is not displaying -- that is most of its purpose. Missing files are simply absent from the result: an arm that has not been built shows its catalog with no coverage, which is the honest picture and the one instruction 40 asks for.

def audit( organism: str, nodes=None, tables=None, graph=None, rows: dict = None) -> dict:

The four counts this window exists to make impossible to miss.

Computed with the same functions the pipeline uses, so the window cannot report a clean catalog while the build sees a broken one.

class SlotTree(PyQt6.QtWidgets.QWidget):

The tree, its filters, and the details pane, as one widget so a test can build it headlessly.

Split from the window for the same reason build_preferences is split from open_preferences: a window that has to be shown to be inspected cannot be tested without a display.

SlotTree( nodes: pandas.DataFrame = None, tables: dict = None, parent=None, organism: str = None, graph=None, sources: dict = None)
nodes
graph
tables
hierarchy
organism
filter
alarms
tree
details
def rebuild(self, *_):

Redraw the tree for the current hierarchy, organism and filter.

class SlotTreeWindow(PyQt6.QtWidgets.QMainWindow):

The tree in a window of its own -- shown, never exec'd.

Same rule as Preferences: a modal here would mean checking the catalog against the map from memory, which is exactly the comparison this is for.

SlotTreeWindow( nodes: pandas.DataFrame = None, tables: dict = None, parent=None, organism: str = None, graph=None, sources: dict = None)
view