![]() |
OpenMS
|
Class-separated FDR calculation for nucleic-acid cross-links (NuXL). More...
#include <OpenNuXL/include/NuXLFDR.h>
Public Types | |
| enum class | XLGroups { OFF , ON , AUTO } |
| Separate FDR group for short cross-links. More... | |
Public Member Functions | |
| NuXLFDR (size_t report_top_hits, XLGroups xl_groups=XLGroups::OFF) | |
| Construct with a top-hit cap that controls how FalseDiscoveryRate is parametrised. | |
| bool | useShortXLGroup (const PeptideIdentificationList &xl_pi, Size &short_decoys) const |
Whether the short cross-links of xl_pi get their own FDR group. | |
| void | splitIntoPeptidesAndXLs (const PeptideIdentificationList &peptide_ids, PeptideIdentificationList &pep_pi, PeptideIdentificationList &xl_pi) const |
Partition peptide_ids into plain-peptide and cross-link PSM lists by their single top hit. | |
| void | mergePeptidesAndXLs (const PeptideIdentificationList &pep_pi, const PeptideIdentificationList &xl_pi, PeptideIdentificationList &peptide_ids) const |
| Re-merge a previously split (splitIntoPeptidesAndXLs) pair of lists into one PSM list. | |
| void | QValueAtPSMLevel (PeptideIdentificationList &peptide_ids) const |
Compute PSM-level q-values across peptide_ids without splitting by class. | |
| void | calculatePeptideAndXLQValueAtPSMLevel (const PeptideIdentificationList &peptide_ids, PeptideIdentificationList &pep_pi, PeptideIdentificationList &xl_pi) const |
| Compute PSM- and peptide-level q-values separately for plain and cross-linked PSMs. | |
| void | calculatePeptideAndXLQValueAndFilterAtPSMLevel (const std::vector< ProteinIdentification > &protein_ids, const PeptideIdentificationList &peptide_ids, PeptideIdentificationList &pep, double peptide_PSM_qvalue_threshold, double peptide_peptide_qvalue_threshold, PeptideIdentificationList &xl_pi, std::vector< double > xl_PSM_qvalue_thresholds, std::vector< double > xl_peptidelevel_qvalue_thresholds, const std::string &out_idxml, int decoy_factor) const |
| Compute separated FDRs, apply class-specific filters, and write per-threshold idXML / TSV reports. | |
Static Public Member Functions | |
| static XLGroups | xlGroupsFromString (const std::string &s) |
| Parse "auto", "on" or "off" (the values of the NuXL:fdr_groups option) | |
| static bool | isShortXL (const PeptideHit &hit) |
Whether hit is a short cross-link: NuXL:isXL, at most SHORT_XL_MAX_LENGTH residues and at least SHORT_XL_MIN_NA_LENGTH nucleotides (NuXL:NA_length) | |
Static Public Attributes | |
| static constexpr Size | SHORT_XL_MAX_LENGTH = 9 |
| short cross-link: at most this many residues ... | |
| static constexpr Size | SHORT_XL_MIN_NA_LENGTH = 2 |
| ... and at least this many nucleotides in the adduct | |
| static constexpr Size | AUTO_MIN_DECOYS = 10 |
| XLGroups::AUTO: decoys the short cross-links need ... | |
| static constexpr double | AUTO_FDR = 0.1 |
| ... among the cross-links at this FDR over all cross-links | |
Private Member Functions | |
| void | setUpFDR_ (FalseDiscoveryRate &fdr) const |
Set the parameters described at QValueAtPSMLevel() on fdr. | |
Private Attributes | |
| size_t | report_top_hits_ |
Top-hit cap consulted by the FDR-applying methods to toggle use_all_hits. | |
| XLGroups | xl_groups_ |
| Whether short cross-links form their own FDR group. | |
Class-separated FDR calculation for nucleic-acid cross-links (NuXL).
Splits PSMs into a "plain peptide" class (NuXL:isXL == 0) and a "cross-link" class (NuXL:isXL != 0), computes FDR separately for each, and (optionally) writes one filtered idXML per requested XL q-value threshold plus a TSV protein report for stringent (<= 10%) XL FDRs.
Built on top of FalseDiscoveryRate. Decoys are kept in the FDR result (so downstream Percolator and similar tools can still see them); the convenience filter method calls IDFilter::removeDecoyHits before writing.
|
strong |
Separate FDR group for short cross-links.
Short cross-links (see isShortXL()) carry little sequence-specific fragment evidence next to their large adduct, so at the same score far more of them are false than of the other cross-links. With a single cross-link FDR, most of the false cross-links accepted at a given threshold are short ones. In their own group, both groups are held at the requested FDR.
| Enumerator | |
|---|---|
| OFF | one FDR over all cross-links |
| ON | short cross-links form their own FDR group |
| AUTO | as ON if the short cross-links have enough decoys to estimate their own FDR (see useShortXLGroup()), else as OFF |
|
explicit |
Construct with a top-hit cap that controls how FalseDiscoveryRate is parametrised.
report_top_hits >= 2 toggles use_all_hits = true on the underlying FalseDiscoveryRate so q-values are computed across all hits per PSM, not only the top hit. The value is otherwise stored verbatim and consulted by the QValueAtPSMLevel and calculatePeptideAndXLQValueAtPSMLevel methods.
| [in] | report_top_hits | Top-hit cap; values >= 2 enable the underlying FDR engine's use_all_hits mode. |
| [in] | xl_groups | Whether short cross-links form their own FDR group (see XLGroups). |
| void calculatePeptideAndXLQValueAndFilterAtPSMLevel | ( | const std::vector< ProteinIdentification > & | protein_ids, |
| const PeptideIdentificationList & | peptide_ids, | ||
| PeptideIdentificationList & | pep, | ||
| double | peptide_PSM_qvalue_threshold, | ||
| double | peptide_peptide_qvalue_threshold, | ||
| PeptideIdentificationList & | xl_pi, | ||
| std::vector< double > | xl_PSM_qvalue_thresholds, | ||
| std::vector< double > | xl_peptidelevel_qvalue_thresholds, | ||
| const std::string & | out_idxml, | ||
| int | decoy_factor | ||
| ) | const |
Compute separated FDRs, apply class-specific filters, and write per-threshold idXML / TSV reports.
Pipeline (every step is observable behaviour, not implementation detail):
pep and xl_pi with FDR-annotated PSMs.decoy_factor != 1, divides every cross-link hit's score by decoy_factor (peptide hits are not touched).<= 1e-5 to every cross-link score so PSMs that originally tied on the q-value resolve to a unique ordering. Uses "svm_score" when at least one XL hit carries it, otherwise "NuXL:score". (max - min) score range and is undefined when all XL hits share the same score.pep and xl_pi.pep on PEPTIDE_Q_VALUE when peptide_peptide_qvalue_threshold is in (0, 1); values <= 0 or >= 1 disable the filter.pep PSMs by score when peptide_PSM_qvalue_threshold is in (0, 1).{out_idxml}{threshold:.4f}_peptides.idXML (with out_idxml the literal prefix and threshold the configured cut formatted to four decimal places), with unreferenced proteins pruned.xl_PSM_qvalue_thresholds: 0.0 entries are rewritten to 1.0 (disabled filter = 100% FDR) and the vector is then sorted in descending order so increasingly stringent filters are applied progressively to the same xl_pi (filters compound across iterations).Exception::InvalidValue is thrown):PEPTIDE_Q_VALUE when the peptide-level threshold is in (0, 1);(0, 1);protein_ids;ProteinIdentification of that copy;{out_idxml}{threshold:.4f}_XLs.idXML;<= 0.1, also write a TSV protein report to {out_idxml}proteins{threshold:.4f}_XLs.tsv (skipped for permissive FDRs to bound output size).| [in] | protein_ids | Protein identifications used as the source for the per-file protein lists; unreferenced proteins are pruned per output. |
| [in] | peptide_ids | Input PSMs (mixed plain + XL). |
| [out] | pep | Receives the filtered plain-peptide PSMs (after step 6). |
| [in] | peptide_PSM_qvalue_threshold | Plain-peptide PSM-level q-value cut; values outside (0, 1) disable the filter. |
| [in] | peptide_peptide_qvalue_threshold | Plain-peptide peptide-level q-value cut; values outside (0, 1) disable the filter. |
| [out] | xl_pi | Receives the filtered cross-link PSMs (state at the most stringent XL threshold). |
| [in] | xl_PSM_qvalue_thresholds | Cross-link PSM-level q-value thresholds; 0.0 is rewritten to 1.0 (disabled = 100% FDR). The vector is sorted descending in place. |
| [in] | xl_peptidelevel_qvalue_thresholds | Cross-link peptide-level q-value thresholds paired by index with xl_PSM_qvalue_thresholds (must have the same size). |
| [in] | out_idxml | Output filename prefix; the FDR threshold and a suffix (_peptides.idXML / _XLs.idXML / proteins...XLs.tsv) are appended. |
| [in] | decoy_factor | Score scale-down factor for the XL class; ignored when equal to 1. |
| OpenMS::Exception::InvalidValue | when xl_PSM_qvalue_thresholds and xl_peptidelevel_qvalue_thresholds differ in size. |
References NuXLProteinReport::annotateProteinModificationForTopHits(), NuXLFDR::calculatePeptideAndXLQValueAtPSMLevel(), IDFilter::filterHitsByScore(), OpenMS::StringUtils::number(), OPENMS_LOG_INFO, OpenMS::Constants::UserParam::PEPTIDE_Q_VALUE, IDFilter::removeDecoyHits(), IDFilter::removeUnreferencedProteins(), TextFile::store(), IdXMLFile::store(), and OpenMS::StringUtils::toStr().
| void calculatePeptideAndXLQValueAtPSMLevel | ( | const PeptideIdentificationList & | peptide_ids, |
| PeptideIdentificationList & | pep_pi, | ||
| PeptideIdentificationList & | xl_pi | ||
| ) | const |
Compute PSM- and peptide-level q-values separately for plain and cross-linked PSMs.
Internally calls splitIntoPeptidesAndXLs and then applies FalseDiscoveryRate to each output list with the same parameters as QValueAtPSMLevel. The q-values are computed independently on each class so XL and non-XL FDR control are not confounded. If useShortXLGroup() is true, the q-values of the short and the other cross-links are computed separately, every cross-link hit is annotated with its group (meta value NuXL:fdr_group: short_XL or XL), and xl_pi keeps the order of the input.
| [in] | peptide_ids | Input mixed plain-peptide / cross-link PSMs. |
| [out] | pep_pi | Plain-peptide PSMs with PSM- and peptide-level q-values annotated. |
| [out] | xl_pi | Cross-link PSMs with PSM- and peptide-level q-values annotated. |
References FalseDiscoveryRate::apply(), NuXLFDR::AUTO, NuXLFDR::AUTO_FDR, NuXLFDR::AUTO_MIN_DECOYS, ExposedVector< VectorElement >::clear(), ExposedVector< VectorElement >::empty(), NuXLFDR::isShortXL(), OPENMS_LOG_INFO, ExposedVector< VectorElement >::push_back(), NuXLFDR::setUpFDR_(), NuXLFDR::SHORT_XL_MAX_LENGTH, NuXLFDR::SHORT_XL_MIN_NA_LENGTH, ExposedVector< VectorElement >::size(), NuXLFDR::splitIntoPeptidesAndXLs(), NuXLFDR::useShortXLGroup(), and NuXLFDR::xl_groups_.
Referenced by NuXLFDR::calculatePeptideAndXLQValueAndFilterAtPSMLevel().
|
static |
Whether hit is a short cross-link: NuXL:isXL, at most SHORT_XL_MAX_LENGTH residues and at least SHORT_XL_MIN_NA_LENGTH nucleotides (NuXL:NA_length)
References MetaInfoInterface::getMetaValue(), PeptideHit::getSequence(), NuXLFDR::SHORT_XL_MAX_LENGTH, NuXLFDR::SHORT_XL_MIN_NA_LENGTH, and AASequence::size().
Referenced by NuXLFDR::calculatePeptideAndXLQValueAtPSMLevel(), and NuXLFDR::useShortXLGroup().
| void mergePeptidesAndXLs | ( | const PeptideIdentificationList & | pep_pi, |
| const PeptideIdentificationList & | xl_pi, | ||
| PeptideIdentificationList & | peptide_ids | ||
| ) | const |
Re-merge a previously split (splitIntoPeptidesAndXLs) pair of lists into one PSM list.
pep_pi entries are appended verbatim. For each xl_pi entry, the meta value "spectrum_reference" is used as the merge key:
PeptideIdentification;"spectrum_reference" appears in at most one of pep_pi / xl_pi. The append branch only matters when merging lists assembled by other means.peptide_ids is cleared on entry.
| [in] | pep_pi | Plain-peptide PSMs (typically from splitIntoPeptidesAndXLs). |
| [in] | xl_pi | Cross-link PSMs (typically from splitIntoPeptidesAndXLs). |
| [out] | peptide_ids | Receives the merged PSM list keyed by "spectrum_reference". |
References ExposedVector< VectorElement >::clear(), and ExposedVector< VectorElement >::push_back().
| void QValueAtPSMLevel | ( | PeptideIdentificationList & | peptide_ids | ) | const |
Compute PSM-level q-values across peptide_ids without splitting by class.
Wraps FalseDiscoveryRate with add_decoy_proteins = true, add_decoy_peptides = true (decoys are retained in the result for downstream tools such as Percolator), and use_all_hits = true iff report_top_hits_ passed to the constructor is >= 2. Also computes the peptide-level q-value meta value Constants::UserParam::PEPTIDE_Q_VALUE on each hit.
| [in,out] | peptide_ids | PSMs to score in place; each hit receives PSM- and peptide-level q-value meta values. |
References FalseDiscoveryRate::apply(), and NuXLFDR::setUpFDR_().
|
private |
Set the parameters described at QValueAtPSMLevel() on fdr.
References DefaultParamHandler::getParameters(), NuXLFDR::report_top_hits_, DefaultParamHandler::setParameters(), and Param::setValue().
Referenced by NuXLFDR::calculatePeptideAndXLQValueAtPSMLevel(), NuXLFDR::QValueAtPSMLevel(), and NuXLFDR::useShortXLGroup().
| void splitIntoPeptidesAndXLs | ( | const PeptideIdentificationList & | peptide_ids, |
| PeptideIdentificationList & | pep_pi, | ||
| PeptideIdentificationList & | xl_pi | ||
| ) | const |
Partition peptide_ids into plain-peptide and cross-link PSM lists by their single top hit.
For each input PeptideIdentification this keeps only the single top-ranked hit (the first hit; hits are assumed sorted best-first) and assigns it to exactly one output list according to the integer meta value "NuXL:isXL" (zero → plain peptide, → pep_pi; anything else → cross-link, → xl_pi). This is a winner-takes-the-spectrum class competition: a spectrum is claimed by whichever class its best hit belongs to and therefore contributes to pep_pi or xl_pi but never to both. Lower-ranked hits of the other class are intentionally dropped so that, e.g., a spectrum best explained as a plain peptide does not also inflate the cross-link FDR pool. This single-top-hit split is applied regardless of report_top_hits (which only toggles use_all_hits inside the underlying FalseDiscoveryRate q-value estimation, not the class split here).
pep_pi and xl_pi are cleared on entry.
| [in] | peptide_ids | Input mixed plain-peptide / cross-link PSMs. |
| [out] | pep_pi | Receives the PSMs whose top hit is a plain peptide (NuXL:isXL == 0), one hit each. |
| [out] | xl_pi | Receives the PSMs whose top hit is a cross-link (NuXL:isXL != 0), one hit each. |
References ExposedVector< VectorElement >::back(), ExposedVector< VectorElement >::clear(), ExposedVector< VectorElement >::push_back(), and PeptideIdentification::setHits().
Referenced by NuXLFDR::calculatePeptideAndXLQValueAtPSMLevel().
| bool useShortXLGroup | ( | const PeptideIdentificationList & | xl_pi, |
| Size & | short_decoys | ||
| ) | const |
Whether the short cross-links of xl_pi get their own FDR group.
XLGroups::ON: if there are short cross-links. XLGroups::AUTO: if, among the cross-links that pass AUTO_FDR with one FDR over all cross-links, at least AUTO_MIN_DECOYS are short decoys. Below that, the FDR of the short cross-links would rest on too few decoys. The decision uses only the decoy counts, not the numbers of identifications the two ways would give. In both modes, the short and the other cross-links each need at least one decoy: FalseDiscoveryRate gives every target of a list without decoys q-value 0.
| [in] | xl_pi | Cross-link identifications, one hit each (as produced by splitIntoPeptidesAndXLs()). |
| [out] | short_decoys | Number of short decoys counted for the decision (XLGroups::AUTO; 0 otherwise). |
References FalseDiscoveryRate::apply(), NuXLFDR::AUTO_FDR, NuXLFDR::AUTO_MIN_DECOYS, ExposedVector< VectorElement >::begin(), ExposedVector< VectorElement >::end(), PeptideIdentification::getHits(), NuXLFDR::isShortXL(), NuXLFDR::OFF, NuXLFDR::ON, OPENMS_LOG_WARN, NuXLFDR::setUpFDR_(), and NuXLFDR::xl_groups_.
Referenced by NuXLFDR::calculatePeptideAndXLQValueAtPSMLevel().
|
static |
Parse "auto", "on" or "off" (the values of the NuXL:fdr_groups option)
References NuXLFDR::AUTO, NuXLFDR::OFF, and NuXLFDR::ON.
|
staticconstexpr |
... among the cross-links at this FDR over all cross-links
Referenced by NuXLFDR::calculatePeptideAndXLQValueAtPSMLevel(), and NuXLFDR::useShortXLGroup().
|
staticconstexpr |
XLGroups::AUTO: decoys the short cross-links need ...
Referenced by NuXLFDR::calculatePeptideAndXLQValueAtPSMLevel(), and NuXLFDR::useShortXLGroup().
|
private |
Top-hit cap consulted by the FDR-applying methods to toggle use_all_hits.
Referenced by NuXLFDR::setUpFDR_().
|
staticconstexpr |
short cross-link: at most this many residues ...
Referenced by NuXLFDR::calculatePeptideAndXLQValueAtPSMLevel(), and NuXLFDR::isShortXL().
|
staticconstexpr |
... and at least this many nucleotides in the adduct
Referenced by NuXLFDR::calculatePeptideAndXLQValueAtPSMLevel(), and NuXLFDR::isShortXL().
|
private |
Whether short cross-links form their own FDR group.
Referenced by NuXLFDR::calculatePeptideAndXLQValueAtPSMLevel(), and NuXLFDR::useShortXLGroup().