Skip to content

matching and presence - #100

Merged
stanfish06 merged 23 commits into
masterfrom
cross-matching
Aug 10, 2026
Merged

stanfish06 merged 23 commits into
masterfrom
cross-matching

Conversation

@stanfish06

Copy link
Copy Markdown
Owner
  • image based cross matching initial
  • depbot
  • cross match wire in
  • cross matching and h5ad saving update
  • fix io
  • update: equilvalence test apis to prepare for homotopy computation
  • update: homotopy coherence prototype
  • update: homotopy coherence
  • coherence
  • update: coherence
  • update: coherence
  • update: more stable loop reconstruction and matching
  • logging
  • many chages: boundary check, cross match
  • update: coherence computation
  • small fix
  • update: coherence
  • update: coherence api
  • coherence
  • presence test
  • wire wilcoxon test
  • wilcoxon guards
  • small fixes

@stanfish06
stanfish06 merged commit 3e1e603 into master Aug 10, 2026
6 checks passed

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3e1e6032cc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 459 to 463
geometric_distance=geo_dist,
neighbor_rank=rank,
image_death_simplex=[
int(v) for v in image_death_simplices[i] if v >= 0
]
or None,
image_death_simplex=image_death_simplex,
boundary_checked=bool(boundary_checked[i]),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve topological equivalence when loading matches

When saving bootstrap results after homological-equivalence checks, _serialize_loop_matches never writes topological_equivalence, and this constructor consequently restores every match with it set to None. Because LoopTrack.filter_matches(keep="equivalent") treats None as accepted, candidates that explicitly failed the boundary check become valid matches after a save/load round trip, changing presence counts and downstream Hodge analyses; the equivalence certificate and coherence data need to be serialized and restored.

Useful? React with 👍 / 👎.

Comment thread src/scloop/io/__init__.py
Comment on lines +155 to +159
if CROSS_MATCH_RESULT_KEY in adata.uns and SCLOOP_UNS_KEY not in adata.uns:
raise ValueError(
f"adata.uns holds cross-dataset matching results "
f"('{CROSS_MATCH_RESULT_KEY}') but no '{SCLOOP_UNS_KEY}'. "
"Use scloop.io.save_cross_match(matcher, path) instead."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Provide a real persistence path for cross-match results

For every AnnData returned by match_loops, scloop_cross_match is present while scloop is absent, so save_scloop always enters this branch and directs the caller to scloop.io.save_cross_match. No such function exists anywhere in the repository or is exported from this module, leaving expensive cross-dataset matching results with no advertised way to save them.

Useful? React with 👍 / 👎.

Comment on lines +159 to +161
if hd.boundary_matrix_d1.shape[0] > max_rows_boundary_matrix:
logger.warning(
f"Boundary matrix has more than {max_columns_boundary_matrix} columns. Downstream computation could be slow"
f"Boundary matrix has more than {max_rows_boundary_matrix} rows. Downstream computation could be slow"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep limiting boundary-matrix columns

For dense radius graphs, the number of triangle columns grows much faster than the number of edge rows, and this commit also changes Ripser to emit every triangle. Checking shape[0] means, for example, a 200-vertex clique has only 19,900 rows and bypasses the default 30,000 limit despite producing about 1.3 million columns, so autoshrinking never runs and the full matrix proceeds into storage and Hodge computations with severe memory/runtime impact. The guard and loop need to constrain the triangle-column dimension (or both dimensions), not only rows.

Useful? React with 👍 / 👎.

Comment thread src/scloop/io/__init__.py
Comment on lines +111 to +120
companion = ad.AnnData(
X=X,
obs=adata.obs.copy(),
var=adata.var.copy(),
obsm=dict(adata.obsm),
varm=dict(adata.varm),
obsp=dict(adata.obsp),
varp=dict(adata.varp),
layers=layers,
uns=uns,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve AnnData raw data in full saves

When minify=False, the companion is labeled as a full save but this reconstruction omits adata.raw. prepare_adata explicitly populates adata.raw before HVG selection, so the normal save/load path silently discards the original expression matrix and its full gene metadata even though only the scloop-specific uns entries are meant to be stripped; copy raw into the companion for non-minified saves.

Useful? React with 👍 / 👎.

Comment on lines +662 to +666
loop_class.death
for side in sides
for loop_class in side.loop_classes
if loop_class is not None
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Derive image thresholds in the aligned coordinate space

When image matching a pair of non-reference datasets, the union radius graph is built from each dataset's learned X_scloop_aligned embedding, but this automatic threshold is derived from loop deaths computed earlier in each dataset's native embedding. MLP/NF mappings are not constrained to preserve distance scale, so the default threshold can be too small to create the required cross-dataset simplices (yielding no matches) or excessively large; calculate the threshold from aligned geometry or require an explicit aligned-space threshold.

Useful? React with 👍 / 👎.

Comment on lines +775 to +777
for ti, tid in enumerate(track_ids):
for bi, cv in coherence_per_track[tid]:
presence_matrix[rows_bootstrap[bi], ti] = cv if cv else 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Aggregate multiple matches within each bootstrap

A loop track can have multiple equivalent candidate matches in the same bootstrap, but each assignment here overwrites the preceding coherence value for that bootstrap. Consequently the Wilcoxon presence result depends on candidate iteration order and ignores all but the last match; group values by (track, bootstrap) and apply an explicit aggregate such as the configured mean or maximum before constructing the matrix.

Useful? React with 👍 / 👎.

Comment on lines +1251 to +1252
match presence_test_method:
case "fisher":

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject unsupported presence-test methods

The previous conditional ended with a ValueError, but this match has no fallback case. A typo or dynamically supplied value in kwargs_loop_test now silently skips the presence test while persistence testing continues, potentially leaving presence_test_result unset or stale and making the pipeline appear successful; retain an explicit default case that rejects unknown methods.

Useful? React with 👍 / 👎.

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