Skip to content

feat(panel): store concatenated panels and bump each source on read - #478

Closed
elhb wants to merge 21 commits into
devfrom
PNA-3624-panel-concat
Closed

elhb wants to merge 21 commits into
devfrom
PNA-3624-panel-concat

Conversation

@elhb

@elhb elhb commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Description

Several --panel inputs are concatenated into one panel (marker_id, sequence_1, and sequence_2 stay unique across that panel).
Each input panel is one source, and each marker keeps a link to the source it came from.
A concatenated panel is stored in the .pxl file. It cannot be registered in the config. add_panel only accepts a single source panels.

New .pxl files store the panel in the panels and panel_sources tables.
Redundant storage of the same info is removed:

  • Panel columns are not written onto var, and uns['panel_metadata'] is no longer written. instead, the panel columns are joined onto the in-memory AnnData, on read.
  • Pixel-file metadata no longer stores panel_name or panel_version.

Files from pixelator 0.22.0 through 0.30.0 are still read from uns['panel_metadata'] and var. Denoise still reads panel_name for files from before 0.22.0.

When several files are read together, each source is bumped to the newest patch those files carry. A source is one input panel. Sources match on name, product, and major.minor. The bump renames markers in the in-memory edgelist, proximity, and layouts. The file on disk is not rewritten. Sample-called files keep hashing clones collapsed.

Denoise rebuilds the count matrix from the markers already in var, so hashing clones that sample calling removed do not come back. The full panel is still written to the tables.

from_adata is removed. It only rebuilt a panel from an AnnData that still carried the on-disk panel fields, and a loaded dataset no longer has those. Legacy .pxl files are still read directly. No caller in this repository used from_adata on an AnnData that was not the pxl file.

Fixes: PNA-3624

Type of change

  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

How Has This Been Tested?

  • Concatenate two panels and confirm marker ids and sequences must be unique.
  • Round-trip a new .pxl and confirm the panel comes from the tables, not from var or uns.
  • Open a 0.22.0–0.30.0 file and confirm the panel is rebuilt from uns and var.
  • Read two samples that share a source at different patch versions and confirm only that source is bumped, including edgelist, proximity, and layouts.
  • Run sample calling, then a patch bump, and confirm hashing clones stay collapsed and a missing non-hashing marker still fails.
  • Denoise a pre-0.22 file and confirm it still falls back to panel_name.
  • Denoise a sample-called file and confirm hashing clones removed from var do not come back.

PR checklist:

  • This comment contains a description of changes (with reason).
  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • If a new tool or package is included, I have updated dependencies in pyproject.toml and cited it properly
  • I have checked my code and documentation and corrected any misspellings
  • I have documented any significant changes to the code in CHANGELOG.md

Note

High Risk
Breaking .pxl panel storage and metadata, plus automatic patch alignment and hashing rename rules, affect denoise, sample calling, and multi-file analysis paths where marker identity must stay consistent.

Overview
This PR redefines how antibody panels are defined, stored, and reconciled across the PNA pipeline.

CLI and panel model: single-cell-pna demux, collapse, and graph now accept repeated --panel flags; inputs are concatenated into one panel (unique marker_id and sequences), with each CSV as a tracked source. PNAAntibodyPanel.from_adata is removed; panels come from the .pxl file or config via load_antibody_panels / read_dataset_panel.

On-disk format: New .pxl files persist panels in panels and panel_sources DuckDB tables. Panel columns are not duplicated on var, uns['panel_metadata'] is dropped, and file metadata no longer carries panel_name / panel_version. Rewriting legacy 0.22–0.30 files migrates panel data from uns/var into those tables.

Multi-sample reads: When several files are loaded together, align_panel_patches bumps each source to the newest patch shared across files (match on name, product, major.minor). Renames apply in memory to AnnData, edgelist, proximity, and layouts (session views); disks are unchanged. Sample-called files respect hashing_collapsed so hashing clones stay collapsed.

Pipeline fixes: Denoise reads the panel from the file and rebuilds counts using markers already in var, so clones removed by sample calling are not reintroduced. Sample calling uses structured hashing id rules and writes hashing_collapsed: true. Edgelist.to_record_batches now renames legacy marker1/marker2 like other exporters.

Reviewed by Cursor Bugbot for commit c818e23. Bugbot is set up for automated code reviews on this repo. Configure here.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/pixelator/pna/config/panel.py
Comment thread src/pixelator/pna/pixeldataset/proximity.py Outdated
Comment thread src/pixelator/pna/pixeldataset/edgelist.py Outdated
elhb and others added 6 commits October 1, 2026 17:53

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/pixelator/pna/analysis/analytical_proximity_query_helper.py Outdated
Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/pixelator/pna/config/panel_align.py Outdated
elhb and others added 4 commits October 2, 2026 11:32
Co-authored-by: Cursor <cursoragent@cursor.com>
The session views already bump marker ids, so the edgelist stream, proximity filter, and proximity SQL go back to the dev code instead of keeping a separate translation.

Co-authored-by: Cursor <cursoragent@cursor.com>
to_record_batches uses the same marker1/marker2 rename as _handle_backwards_compatibility, so a streamed legacy edgelist matches to_polars.

Co-authored-by: Cursor <cursoragent@cursor.com>
refactor(panel): bump marker ids in the session views

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/pixelator/pna/config/panel.py Outdated
elhb and others added 2 commits October 2, 2026 14:34
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/pixelator/pna/analysis/denoise.py
Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/pixelator/pna/analysis/denoise.py
Comment thread src/pixelator/pna/config/panel.py
elhb and others added 2 commits October 2, 2026 15:45
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/pixelator/pna/pixeldataset/io/pixel_data_viewer.py

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/pixelator/pna/pixeldataset/io/pixel_data_viewer.py
Comment thread src/pixelator/pna/pixeldataset/io/pixel_data_viewer.py Outdated
elhb and others added 2 commits October 5, 2026 10:10

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 76665c8. Configure here.

Comment thread src/pixelator/pna/pixeldataset/io/pixel_data_viewer.py
@elhb
elhb requested a review from Aratz October 5, 2026 09:09
@elhb elhb closed this Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant