Conversation
…atedness Computes pairwise or single-target linkage scores between cell categories using path distance or LCA depth on the lineage tree. Supports permutation testing, parallel execution (fork-based), symmetrization, and per-tree stats. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #52 +/- ##
==========================================
+ Coverage 92.91% 93.51% +0.60%
==========================================
Files 34 35 +1
Lines 2554 2838 +284
==========================================
+ Hits 2373 2654 +281
- Misses 181 184 +3
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8a6a745aaa
ℹ️ 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".
|
|
||
| # Choose strategy: Dijkstra handles the natural "closest" direction for each metric | ||
| is_named = isinstance(aggregate, str) | ||
| use_dijkstra = is_named and ((aggregate == "min" and metric == "path") or (aggregate == "max" and metric == "lca")) |
There was a problem hiding this comment.
Compute lca+max scores from all targets, not nearest path
Routing aggregate='max' with metric='lca' through the Dijkstra shortcut is not generally correct: Dijkstra picks the target leaf with minimum path distance, but maximizing LCA depth depends on both path length and target depth ((d_src + d_tgt - path)/2). When leaves have unequal depths (non-ultrametric trees), the best LCA target can be farther by path, so this branch underestimates linkage in pairwise, single-target, and permutation computations.
Useful? React with 👍 / 👎.
| if "tree_distances" in tdata.obsp: | ||
| D = tdata.obsp["tree_distances"] | ||
| if isinstance(D, np.ndarray): | ||
| precomputed = D |
There was a problem hiding this comment.
Validate cached tree_distances before reusing
The all-pairs path reuses tdata.obsp['tree_distances'] whenever it exists as a dense array, but it never verifies that this cache was computed with the same metric, depth_key, or tree selection. If users previously ran tree_distance with different parameters, this function silently consumes stale distances and returns incorrect linkage values for mean/max/custom aggregates.
Useful? React with 👍 / 👎.
| else: # min | ||
| sym = np.minimum(arr, arr_T) |
There was a problem hiding this comment.
Raise on invalid symmetrize mode
Unknown symmetrize values currently fall into the else branch and are treated as 'min', so a typo (for example, 'meen') silently changes analysis output instead of failing fast. This makes results hard to trust because invalid user input produces a valid-looking but incorrect matrix.
Useful? React with 👍 / 👎.
…d permutation test Adds alternative='two-sided' to support two-tailed p-values. Default None preserves existing one-sided behavior (more-related direction). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
tl.ancestral_linkageto measure how closely related cells of different categories are on the lineage treetarget=None): computes a category × category linkage matrix stored intdata.uns['{key}_linkage']target=<cat>): computes per-cell distance to the nearest cell of the given category, stored intdata.obs['{target}_linkage']metric='path'(branch-length path distance) andmetric='lca'(LCA depth)test='permutation'with parallel fork-based workers (n_threads)symmetrizefor the pairwise matrixby_tree=Trueadds per-tree breakdowns in the stats tabletqdmas a package dependency (used for permutation progress)Test plan
conda run -n pycea python -m pytest tests/test_ancestral_linkage.py— 35 tests covering pairwise/single-target modes, known values, symmetrization, permutation tests, parallel execution, and edge cases🤖 Generated with Claude Code