Scoring, thresholds, and honest reporting

This page explains LipidOracle's scoring and tresholding system. It differs in many ways from classical lipidomics tools that stop at a positive match. LipidOracle attempts to quantify specificity: is there enough information to claim that the top hit is better than the others? Or is there a group of equally likely candidates? These questions are addressed quantitatively by analyzing all possible isomers, their fragments, and obtain a honest estimate of the underlying ambiguity in annotation.

The short version

Every scoring step in LipidOracle is built around one rule: never report more structural detail than the spectrum can actually support, and always make it possible to check that claim yourself. Where the evidence is decisive, the name says so. Where it isn't, the name says that too, instead of quietly picking whichever candidate happened to score highest.

Two questions, kept structurally separate

LipidOracle's annotation pipeline answers two different questions about a lipid, and it never lets an answer to one leak into the other: which chains are present (stage 2), and where exactly, within those chains, does a double bond or oxidation sit (stage 3). Each stage produces its own score (s2_score, s3_score), its own selection logic, and its own honesty check, described below. Neither one is used to prop up the other.

Why a single confidence score is not enough

Both stage-2 and stage-3 scores are normalised per spectrum, so the best-scoring candidate for a given feature always reads close to its own scale's maximum. That's a deliberate, standard choice — it's what makes a score comparable across spectra of wildly different intensity — but it has a consequence worth stating plainly, because most tools that report a "confidence score" don't: a high top score, on its own, cannot tell you whether the runner-up scored almost as well.

A feature where the second-best candidate trails far behind is a confident, well-determined call. A feature where five or ten candidates all cluster near the same top score is not, even though both features report an identical-looking best score. Reading the score column alone, you cannot tell these two situations apart — and a workflow that reports only the single best-scoring name per feature is, structurally, throwing that distinction away.

This is exactly why LipidOracle does not stop at "report the best-scoring candidate." Everything described below — the selection method, the assertion gate, and the resolvability audit — exists specifically to recover the information a bare top score cannot express: how many isomers is the spectrum actually unable to tell apart, and is the reported name honest about that.

How this differs from a typical lipidomics workflow

Most MS/MS lipid annotation tools score every candidate against the spectrum, keep the single best-scoring hit per feature, and report its name and score as the answer. That's not wrong as far as it goes — but it silently assumes that "best-scoring" means "determined", which, as above, is often not true. LipidOracle starts from the opposite assumption: ambiguity is the normal case, and the pipeline's job is to detect it and say so, not paper over it.

Typical workflow

  • Reports the single best-scoring candidate per feature, whether or not any rival came close.
  • A fixed score-ratio cutoff (e.g. "within 1% of the top hit") decides what's kept, regardless of how many candidates cluster there.
  • A confident-looking name is produced even when the deciding peaks were never actually observed in that spectrum.
  • Thresholds are often unstated, unpublished, or buried in source code rather than in the documentation a user reads.

LipidOracle

  • Reports every candidate within a statistically meaningful, spectrum-specific credible set — one candidate when the evidence is decisive, many when it isn't.
  • Checks, per feature, whether the winning candidate actually has peaks distinguishing it from its best rival — not just a higher score.
  • Falls back to a coarser, honest name (e.g. species-level) rather than asserting a position the spectrum cannot back up.
  • Tests its own thresholds against chemically impossible structures, on the record, and publishes every default and every parameter (see Parameters).

Stage 2: which chains are present

Once a sum composition is fixed (say PC 34:1), there is usually more than one way to split those carbons and double bonds across two acyl chains — 16:0_18:1 or 16:1_18:0 weigh exactly the same, so a precursor mass alone can never tell them apart. Stage 2 uses the MS2 fragment spectrum to decide, scoring each candidate arrangement as a blend of two questions: did the fragments this structure predicts actually show up, and how much of what was actually measured does this structure explain.

s2_score = 0.75 × (matched_weight − 2 × exclusion_penalty) / total_weight
         + 0.25 × (matched_intensity / total_intensity)

Fragments a structure predicts should be absent count too: finding one anyway is evidence against that structure, and is subtracted at twice its weight — ruling a candidate out is worth more than merely supporting one.

Passing the score thresholds (s2_lo_score_cutoff, then a relative cutoff against the best candidate in that scan) only means a candidate out-scored its rivals. It does not mean the spectrum could tell them apart. So every contested composition is separately audited: the winning arrangement is compared against its best-scoring disagreeing rival, and the pipeline counts, peak by peak, which of the fragments unique to one or the other were actually observed. Only when the winner's own distinguishing peaks were seen more often than the rival's is the call marked resolvable. That verdict — yes, no, or uncontested — is published in every export as s2_resolvability (the same three-state column for stage 3's C=C/oxygen-position audit is s3_resolvability), not buried in an internal log.

Stage 3: exactly where, within a chain

Stage 3 takes an already-identified chain and asks where, specifically, a double bond or an oxygen sits — using MS2 evidence that breaks the chain itself, not just the fragment that detaches it from the glycerol backbone. This needs a dissociation method built for the purpose: LipidOracle supports five, each implementing a published, peer-reviewed fragmentation chemistry (see references below) rather than a proprietary in-house scheme.

MethodWhat it measures
ead1 / ead2Electron-activated dissociation: a near-continuous fragment ladder along the whole chain, whose spacing shifts at a double bond. ead2 additionally localises hydroxyl and ketone groups.
uvpdUV photodissociation: a sharp pair of diagnostic ions flanking a double bond, ~24 Da apart.
oadOxygen attachment dissociation: two required anchor ions per double bond (OAD02, OAD15), currently scoped to unoxidised diacyl PC [M+H]+.
ozidOzone-induced dissociation: a matched aldehyde/Criegee ion pair per double bond, validated for specific class/adduct combinations.

By default, every candidate's score is converted into a probability, not rescaled to a fixed 1.0. A top score alone still cannot say whether it was a decisive win or a coin toss among ten near-ties, which is exactly what selection exists to answer instead. Three further checks recover that information, and none of them can be read off the score column alone:

Honest reporting

  • Ambiguity is reported, not resolved by fiat. When multiple structures are equally consistent with the spectrum, the annotation says so — as multiple idlevel-3 candidates, and as explicit uncertainty markers inside the exported CXSMILES structure itself — rather than arbitrarily picking one and presenting it as settled.
  • The pipeline is allowed to say "I don't know". Every fallback described above (species-level names, unlocalised positions, the assertion gate) exists to let an annotation stop short of a claim the data doesn't support, instead of forcing a confident-looking answer out of thin evidence.
  • What's calibrated is distinguished from what isn't. Where a confidence number has actually been fitted against known, confirmed positions, that's stated. Where a number is exported only as a diagnostic because no ground-truth dataset exists yet to calibrate it against (for example, stage 2's chain-arrangement posterior), that's stated too, instead of presenting every number as equally trustworthy.
  • The method is checked against its own worst case. The null-decoy test above exists purely to catch LipidOracle being overconfident about its own output — a self-audit most tools do not publish, if they run it at all.

References

Where to go next