spacr.qt.screens.tabulate

Workflow inputs and outputs

Tabulate

Choose grouping variables and measurement columns, then inspect pivot tables and groupwise sample sizes.

Open: Help search → Database Browser → Tabulate.

Inputs and outputs below include conditional alternatives. The guidance and handoff notes say which route applies.

Inputs

  • Measured objects — measurements/measurements.db; object tables depend on the enabled cell, nucleus, pathogen and organelle masks. Relevant tables, depending on the route: cell, nucleus, pathogen, cytoplasm. Relevant columns, depending on the route: plateID, rowID, columnID, fieldID.

Outputs

  • Figures and table exports — The output location chosen by the tool; exports describe the selected data and filters.

API reference.

Module tutorial.

The Tabulate screen — a pivot table, and the chart of it underneath.

A JMP-style Tabulate: drag plateID down the rows, gene across the columns, tick the aggregations, read the numbers. It is the first thing most people want from a measurement database and the last thing spaCR had.

Four parts, three of them already written:

The table is not a chart

“Plot this table” hands the Graph Builder to_long() — one row per non-empty cell, one column per statistic — and the Graph Builder does the rest. So x = plateID, y = mean, size = n is a drag, and there is no second implementation of scales, facets or colour to keep in step with the first.

Two things follow from the summary being a real frame rather than a picture, and both are correct rather than unfortunate:

  • the chart’s own status line reports no object keys in this table, because a summary row is a group, not an object. Brushing it cannot publish an object selection, and saying so beats publishing an empty one.

  • the chart is on its own linked-selection source, so it does not answer to a lasso drawn over individual cells somewhere else.

Filter, then aggregate

A filter change recomputes the pivot rather than restyling it, for the same reason it recomputes a PCA: an aggregate is a property of the population, and a mean of the unfiltered rows shown next to a filtered plot is the kind of mismatch nobody catches by eye.

register() is not called at import; see spacr.qt.screens.graph_builder.register() for the registration collateral still owned by app.py.

Classes

TabulateScreen

Load a measurement table, pivot it, and plot the summary.

Functions

make_tabulate_screen(→ PySide6.QtWidgets.QWidget)

Factory handed to spacr.qt.app.register_app().

register(→ bool)

Put Tabulate in the app registry, through the public seam. Idempotent.

Module Contents

class spacr.qt.screens.tabulate.TabulateScreen(parent=None, *, link=None, threaded: bool = True)[source]

Bases: PySide6.QtWidgets.QWidget

Load a measurement table, pivot it, and plot the summary.

Parameters:
  • link – a private LinkedSelection for tests. None joins the process-wide one.

  • parent – parent widget; ownership only.

  • threaded – False runs every table read inline instead of on the job runner’s thread. A TEST NEEDS THE RESULT ON THE LINE AFTER THE CALL; a user needs the window to keep painting while a large table loads. The jobs are the same either way – they still register, still report failure through job_failed – so only the waiting differs.

Build the screen: the pivot builder beside the shared filter.

The pivot, the graph and the filter are sections of CollapsibleSplitter panes – each folds by its heading and each shared edge drags.

Parameters:
  • parent – parent widget, or None.

  • link – shared selection link.

  • threaded – read the database on a worker thread. Set False in tests so a load finishes before it returns.

active_jobs() → int[source]

How many worker threads are still winding down.

choose_table() → None[source]

Ask which table in the project to use.

closeEvent(event)[source]

Stop background work and unlink before going away.

Parameters:

event – the Qt close event.

is_busy() → bool[source]

True while a table read is in flight.

load_path(path: str, table: str | None = None) → None[source]

Load a CSV or one table of a SQLite measurement database.

The read runs on a worker thread. SELECT * FROM cell into pandas measures 1.5 s for a 200 000-row measurement table on a warm local SSD, and this method used to run it inline: the whole window stopped redrawing for the read. Listing the table names stays inline – it is one sqlite_master query, measured at 0.4 ms – because the picker has to be populated before the read is dispatched, to know which table to read.

Returns as soon as the read is dispatched; _on_frame_loaded() finishes on the GUI thread.

Parameters:

path – a .csv, .tsv or .txt file, or any other suffix as a SQLite database whose table names fill the table picker. A database that cannot be listed is reported in the source line and nothing is read.

plot_summary(frame: pandas.DataFrame | None = None) → None[source]

Hand the summary to the Graph Builder.

The summary rows are groups rather than objects, so the chart’s status line will say the table carries no object keys and that brushing cannot publish a selection. That is the truth about a mean of forty cells, and it is better said than worked around.

set_frame(frame: pandas.DataFrame, *, label: str = '') → None[source]

Pivot frame. The one call a host needs.

Parameters:

frame – the table to filter and pivot; it replaces the current one.

spacr.qt.screens.tabulate.make_tabulate_screen(app_key: str | None = None) → PySide6.QtWidgets.QWidget[source]

Factory handed to spacr.qt.app.register_app().

spacr.qt.screens.tabulate.register() → bool[source]

Put Tabulate in the app registry, through the public seam. Idempotent.

The strings above travel with the registration — spacr.qt.app.register_app() fans intro, cli_note, api_module and translations out into the four tables that used to need a hand-edit each.

Returns:

True if this call is what registered it. Safe to call twice.

Not called at import, for the reason app.py’s _SELF_REGISTERING_APPS table documents: a registration made anywhere else is one that some importer’s snapshot of APPS predates. Turning this screen on is one row in that table:

("spacr.qt.screens.tabulate", "register"),

left out here because spacr/qt/app.py belongs to another change in flight, and because a new APPS row currently reddens the per-app inventory tests for reasons this screen cannot fix.