itasc.contact_analysis.shape_tables¶
Aggregated shape tables — index-keyed, materialized views of the products.
Contact Analysis builds one per-position artifact per quantity (a tidy
object_table). This module pools those, across the in-scope positions, into a
small set of aggregated, index-keyed tables — one file per distinct natural
index — written flat at <out_dir>/<name>.csv. They are materialized
views: regenerate-whole, never upserted, so a re-aggregate rewrites the file from
scratch and CSV stays viable (no concurrent partial write into a shared file). The
per-position artifacts remain the normalized source of truth; these tables are a
reproducible projection of them.
The pooled tables are label-agnostic: a per-cell subpopulation classification
(NLS class_label etc.) is not joined here. A consumer that wants a class split
joins it downstream from the dataset that defines it (keyed on
experiment_id, position_id, cell_id).
Partitioning principle: one table per quantifier. Each
Quantifier that aggregates
declares its natural index (table_keys); its tidy object_table is pooled
across positions into a table named by the quantifier’s quantity_id. Value
columns stay namespaced by quantity_id (cell_shape.area_um2) so a later
joined view across tables never has colliding names. The keys and the catalogue
metadata (the classification columns — whatever the widget defined) stay
bare. (Previously several quantities sharing an index were outer-joined into one
wide table — that produced god tables and is gone.)
Generalizes the old one-quantity-at-a-time pooling
(napari…plots._pooling.pool_quantity) to “all quantities of an index,
persisted.” Backend-only (no Qt) so headless / batch runs and the standalone
wheel use it unchanged.
Module attributes
The single run-level provenance sidecar written beside the pooled tables. |
Functions
|
Regenerate every aggregated table for the in-scope records; return the table name → written CSV path map. |
|
Pool the quantifier name's per-position table across records into one frame. |
|
A stable home for the aggregated tables: the common ancestor of the in-scope positions' folders. |
|
Read an aggregated-table CSV, restoring integer dtype on the key columns ( |
Map table name → |
|
|
The aggregated table quantity_id lands in — its own |
|
Where table name's CSV lives: flat under out_dir. |
Classes
|
One aggregated table: a single quantifier's pooled |
- class itasc.contact_analysis.shape_tables.ShapeTableSpec(name, keys, quantity_ids)[source]¶
Bases:
objectOne aggregated table: a single quantifier’s pooled
object_table— the table name (itsquantity_id), the index keys, and the contributing quantity (quantity_idscarries the one id, kept a tuple for the pooling machinery).
- itasc.contact_analysis.shape_tables.shape_table_registry()[source]¶
Map table name →
ShapeTableSpec. Each aggregating quantifier — one that declares atable_keysindex — is its own table, named by itsquantity_idand keyed by its own grain. No quantifier shares a table with another (no god tables).- Return type:
- itasc.contact_analysis.shape_tables.table_for_quantity(quantity_id)[source]¶
The aggregated table quantity_id lands in — its own
quantity_idwhen it aggregates (declarestable_keys), elseNone(contacts and other non-aggregated quantities).
- itasc.contact_analysis.shape_tables.build_table(name, records, *, params=None)[source]¶
Pool the quantifier name’s per-position table across records into one frame.
For each in-scope record the quantifier’s tidy table is computed in memory via
compute_object_table()(value columns namespaced byquantity_id) and the catalogue metadata is stamped; the per-position frames are then concatenated. params carries the shared build knobs (e.g.fov_area_mm2,pixel_size_um) — the same onesbuild_quantities()threads intobuild, so a param-gated quantifier (cell shape needspixel_size_um) pools consistently with what was actually built. The result is label-agnostic (noclass_labeljoin). Empty when nothing computes. In-memory only — seeaggregate()to persist.
- itasc.contact_analysis.shape_tables.read_table(path)[source]¶
Read an aggregated-table CSV, restoring integer dtype on the key columns (
frame/*_id) so downstream group-bys match the in-memory build.
- itasc.contact_analysis.shape_tables.aggregate(records, out_dir=None, *, params=None, quantities=None)[source]¶
Regenerate every aggregated table for the in-scope records; return the table name → written CSV path map.
Materialized-view semantics: each table is rebuilt whole and its CSV overwritten (a previously-written table for a now-out-of-scope position is simply not regenerated with that position). A table that pools to no rows is skipped (no empty file). out_dir defaults to
catalogue_root(). params is forwarded tobuild_table()(the shared build knobs the param-gated quantifiers need to compute at all).quantities restricts which tables are written:
None(the default) writes every registered table; a sequence writes only those whosequantity_idit names (unknown / non-tabular ids — e.g. thecontactsproducer — are simply absent from the table registry and ignored). An empty sequence writes nothing.
- itasc.contact_analysis.shape_tables.table_path(out_dir, name)[source]¶
Where table name’s CSV lives: flat under out_dir.
- itasc.contact_analysis.shape_tables.catalogue_root(records)[source]¶
A stable home for the aggregated tables: the common ancestor of the in-scope positions’ folders. Falls back to the first position’s parent, then to the current directory when no position folder is known.
- itasc.contact_analysis.shape_tables.PROVENANCE_NAME = 'provenance.json'¶
The single run-level provenance sidecar written beside the pooled tables. The cheap quantities are computed in memory and never persisted per-position, so their old per-position
.provenance.jsonsidecars are gone; this one file records how a whole aggregate run was produced instead.