Skip to content

Include modification C/S counts in library-wide isotope envelopes - #145

Merged
jspaezp merged 2 commits into
mainfrom
feat/108-isotope-composition
Sep 13, 2026
Merged

jspaezp merged 2 commits into
mainfrom
feat/108-isotope-composition

Conversation

@jspaezp

@jspaezp jspaezp commented Sep 12, 2026

Copy link
Copy Markdown
Collaborator

Precursor isotope envelopes now include modification C/S contributions and use one calculation method across the entire library. Previously, scoring counted stripped residues and selected an averagine fallback independently for each entry.

For example, PEPTC[UNIMOD:4]IDEK previously used C43/S1, ignoring carbamidomethyl. It now uses C45/S1. DIA-NN C(UniMod:4) and mzSpecLib C[U:Carbamidomethyl] produce the same envelope. If one entry instead has a mass-only modification, every stored target and shipped decoy uses mass-estimated C/S.

  • Retains the existing fast, three-bin C/S distribution. Signed modification deltas and independently supplied, explicitly based formulas can establish counts. Other elements remain outside this approximation.
  • Resolves the method during ReferenceLibrary finalization and caches three intensities per stored row. Synthetic mass-shift decoys reuse the parent's envelope, including its unshifted mass in mass-estimated mode.
  • Reports method, composition coverage and unavailable reasons through the shared CLI/viewer plan and Parquet metadata. Rejects comparable neutral-formula C/S conflicts and mass estimates outside the calculator's numerical range.
  • Removes the per-entry selector and production sequence-reparsing path. Modification annotations resolve once per distinct annotation during finalization. Dense RowValues sidecars retain opaque stored-row addressing.

The access path is now ReferenceLibrary → ScoringPlan → IsotopePlan → cached row envelope → RefQuery → existing extraction/scoring. Score-macro feature declarations do not change.

Validation: library/scoring/CLI/macro tests and doctests; actual DIA-NN/mzSpecLib and prediction/reload equivalence; target/shipped-decoy/generated-variant cases; formula-only inputs, signed/terminal modifications, unresolved and labelled chemistry, model limits; viewer tests and Parquet metadata. Formatting and workspace Clippy (including dashboard) pass. No real-data performance or FDR benchmark was run.

Closes #108. Slice 3 of #97; sequence-free scoring remains the next slice.

@github-actions

github-actions Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

Apex-finder bench

cargo run -p apex_sim --release --example bench -- 1000 2

Sensitivity + timing across canonical scenarios
=== summary (n=1000, tol=±2 cycles) ===
  scenario                      pass2%  pass1%   medErr    us/run
  clean                          100.0   100.0        0     27.14
  moderate_noise                  92.7    92.7        0     27.85
  high_noise+interference         59.3    59.3        1     26.67
  heavy_interference               7.4     7.4       88     26.81
  mismatched_library              59.8    59.8        1     26.77
  absent_top_fragment             16.0    16.0       65     26.74
  absent_precursor                59.3    59.3        1     26.82

=== broad apex-finding (n=500, tol=±2 cycles) ===
  scenario                      pass2%  pass1%   medErr    us/run
  broad_clean                    100.0   100.0        0    162.39
  broad_moderate_noise            50.6    50.6        1    158.64
  broad_high_noise+interf         27.6    27.6      308    159.87
  broad_hard_3x_density            0.8     0.8      487    158.84
  broad_mismatched_library        41.0    41.0      161    158.82
  broad_measured_density          49.6    49.6       13    187.71

=== narrow recovery (n=1000, tol=±2 cycles) ===
  scenario                      pass2%  pass1%   medErr    us/run
  narrow_clean                   100.0   100.0        0     18.62
  narrow_moderate_noise           81.3    81.3        0     18.51
  narrow_high_noise+interf        65.8    65.8        1     18.30
  narrow_hard_3x_density          10.9    10.9       34     18.26
  narrow_mismatched_library       62.8    62.8        1     18.17
  narrow_measured_density         83.6    83.6        0     20.95

=== narrow score discrimination (AUC, n_seed_pairs=1000) ===
  scenario                         AUC   med+signal    med-noise
  narrow_clean                   1.000     4.329e14      7.199e7
  narrow_moderate_noise          0.870      4.054e9      3.054e8
  narrow_high_noise+interf       0.830      2.761e9      3.602e8
  narrow_hard_3x_density         0.684      3.644e9      1.244e9
  narrow_mismatched_library      0.842      2.172e9      3.575e8
  narrow_measured_density        0.858      4.341e9      2.562e8

commit 37aec05

Comment thread rust/timsseek/src/scoring/plan.rs Outdated
/// Owned by its reference library; callers cannot install a plan from another library.
#[derive(Debug, Clone, Serialize)]
pub struct ScoringPlan {
isotopes: crate::fragment_mass::isotope_plan::IsotopePlan,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

import

Copilot AI 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.

🟡 Changes recommended

Reject negative or NaN neutral masses before accepting isotope envelopes.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Centralizes library-wide isotope-envelope calculation with modification-aware C/S contributions, cached row envelopes, and shared scoring, CLI, viewer, and Parquet integration.

Changes:

  • Adds composition- and mass-estimated isotope planning.
  • Removes production sequence-reparsing fallback.
  • Adds metadata, validation, and cross-reader coverage.
  • Requires validation of negative or NaN neutral masses.
File summaries
File Summary
rust/timsseek/src/scoring/plan.rs Integrates isotope planning into scoring.
rust/timsseek/src/scoring/parquet_writer.rs Verifies isotope metadata serialization.
rust/timsseek/src/models/sequence.rs Restricts sequence parsing to test helpers.
rust/timsseek/src/fragment_mass/mod.rs Exposes the isotope-plan module.
rust/timsseek/src/fragment_mass/isotope_plan.rs Resolves and caches isotope envelopes.
rust/timsseek/src/fragment_mass/elution_group_converter.rs Retains fast C/S counting.
rust/timsseek/src/fragment_mass/averagine.rs Supports mass-based C/S estimation.
rust/timsseek/src/data_sources/reference_library.rs Uses finalized library envelopes.
rust/timsseek_cli/src/predicted_library.rs Covers prediction/reload equivalence.
rust/timsquery/src/models/target_columns.rs Adds row-addressed sidecars.
rust/timsquery/src/models/capabilities.rs Documents isotope capability semantics.
rust/timsquery/src/chemistry/analyte.rs Documents isotope chemistry behavior.
rust/timsquery/src/chemistry.rs Updates chemistry documentation.
rust/timsquery_viewer/src/file_loader.rs Aligns viewer isotope behavior.
docs/development.md Documents isotope-plan policy.
Review details
  • Files reviewed: 15/15 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +111 to +113
let z = f64::from(geom.charge(row));
let envelope = isotope_dist_from_mass(geom.precursor_mz(row) * z - z * PROTON_MASS);
if !envelope.iter().all(|v| v.is_finite()) {
Ok(counts)
}

fn valid_counts(cs: Counts) -> Resolution {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

super over-engineered ...

@jspaezp
jspaezp marked this pull request as ready for review September 13, 2026 03:00
@jspaezp
jspaezp merged commit 008a254 into main Sep 13, 2026
8 checks passed
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.

Isotope envelopes ignore the atomic composition of modifications

2 participants