Repository navigation
Feature: utils.apply_peptide_batch_effects() - #49
Conversation
Simulates peptide-specific batch effects to evaluate batch-aware proteoform inference together with utils.proteoform_group_simulator() and utils.proteoform_simulation_metrics(). - flavor="subset_shift": n_peptides peptides per protein are shifted by the same log2fc in every sample of the affected batches - batches as list selects batch labels, as int draws them at random; at least one batch stays unaffected - only proteins with more than n_peptides peptides are eligible; fraction limits the share of randomly selected proteins - log_space=False multiplies by 2 ** log2fc, True adds log2fc (assumes log2 data); warns if log_space does not match .X - ground truth in .var['batch_effect'], parameters and seed in .uns['batch_effect_simulation'] Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Documentation build overview
13 files changed ·
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 27bcec6560
ℹ️ 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".
| affected_batches = [ | ||
| b.item() if isinstance(b, np.generic) else b for b in affected_batches |
There was a problem hiding this comment.
Preserve NumPy datetime batch labels before matching
When batches contains nanosecond-resolution np.datetime64 labels, .item() converts each label to an integer timestamp; the subsequent Series.isin() comparison against a datetime batch column then matches no observations. The function consequently flags peptides and records an affected batch in .uns while leaving every intensity unchanged. Build obs_mask from the original labels before converting values for serialization, or normalize datetime labels without changing their comparison semantics.
Useful? React with 👍 / 👎.
| else: | ||
| X = np.array(Xsrc, dtype=float) | ||
|
|
||
| looks_log = is_log_transformed(adata)[0] |
There was a problem hiding this comment.
Avoid densifying sparse input twice
For sparse .X, line 300 already retains a full dense float matrix, but is_log_transformed(adata) densifies the original sparse matrix again internally. Large peptide matrices therefore require roughly two simultaneous dense copies and can run out of memory despite sparse input being explicitly supported; run the log-scale heuristic on the already-created X array instead.
AGENTS.md reference: AGENTS.md:L71-L76
Useful? React with 👍 / 👎.
Summary
pr.utils.apply_peptide_batch_effects()plants a peptide-level batch effect in a dataset.Related issues
None
General checklist
HISTORY.mdupdated under[Unreleased]✨ Feature
What it adds:
pr.utils.apply_peptide_batch_effects()with flavor"subset_shift":n_peptidespeptides are drawn and shifted by the samelog2fcin every sample of the affected batches. All other values are unchanged.batchesas a list names the affected batch labels; as an int it draws that many batches at random. At least one batch must stay unaffected.n_peptidespeptides are eligible, so every affected protein keeps at least one unshifted peptide.fractionsets the share of eligible proteins, randomly selected, that receive the effect.log_space=False(default) multiplies by2 ** log2fc;log_space=Trueaddslog2fcand assumes log2-transformed.X. It warns iflog_spacedoes not match whether.Xlooks log-transformed..var["batch_effect"], and parameters and seed to.uns["batch_effect_simulation"].A shift that is constant within a batch leaves every within-batch peptide correlation unchanged but separates the shifted peptides from their siblings across batches. Naive COPF can then call spurious proteoform groups, while batch-aware COPF is unaffected by construction.
Example usage:
Pilot on the Schessner et al. (2023) DOM data (PXD034969, 36 samples, 3 replicates as batches), 2 iterations per arm, one random replicate shifted. These runs used an earlier, uncommitted version of the function (
apply_batch_effects(), flavor"peptide_mix"). The draws and the shift in linear space are unchanged in this PR, but the numbers were not re-run after the renames:Naive COPF calls many more background proteins from log2 FC −2 on; batch-aware COPF is unchanged at every effect size.
tests/utils/test_batch_effect_simulation.py, 40 tests)docs/sphinx/source/api/utils.rst). The Sphinx build was not run locally🤖 Generated with Claude Code