openmassspec_core/cv/mod.rs
1//! Typed PSI-MS and UO controlled-vocabulary terms used by the mzML writer.
2//!
3//! Every constant here is generated from `psi-ms.obo` by
4//! `scripts/gen-cv.py` (the term list is `scripts/cv-terms.txt`), and the
5//! generated file records the OBO source URL and `data-version`
6//! ([`PSI_MS_VERSION`], [`PSI_MS_SOURCE_URL`]). A [`Term`] can only be built
7//! inside this module, so an accession is always paired with its exact OBO
8//! name.
9//!
10//! Reader crates can turn a [`Term`] into a [`CvTerm`](crate::CvTerm) with
11//! `From`:
12//!
13//! ```
14//! use openmassspec_core::{cv, CvTerm};
15//!
16//! let term: CvTerm = cv::PEAK_PICKING.into();
17//! assert_eq!(term.accession, "MS:1000035");
18//! assert_eq!(term.name, "peak picking");
19//! ```
20
21mod terms;
22
23pub use terms::*;
24
25/// A PSI-MS (`MS:`) or Unit Ontology (`UO:`) term known at compile time.
26///
27/// The fields are private: the only values are the generated constants in
28/// this module, so the accession and name always match the ontology.
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30pub struct Term {
31 accession: &'static str,
32 name: &'static str,
33}
34
35impl Term {
36 /// Accession, e.g. `"MS:1000016"`.
37 pub const fn accession(self) -> &'static str {
38 self.accession
39 }
40
41 /// Exact OBO name, e.g. `"scan start time"`.
42 pub const fn name(self) -> &'static str {
43 self.name
44 }
45
46 /// mzML `cvRef` for this term: `"UO"` for Unit Ontology accessions,
47 /// `"MS"` otherwise.
48 pub fn cv_ref(self) -> &'static str {
49 if self.accession.starts_with("UO:") {
50 "UO"
51 } else {
52 "MS"
53 }
54 }
55}
56
57/// Look up a generated term by accession.
58pub fn lookup(accession: &str) -> Option<Term> {
59 ALL.iter().copied().find(|t| t.accession == accession)
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn lookup_finds_generated_terms() {
68 assert_eq!(lookup("MS:1000016"), Some(SCAN_START_TIME));
69 assert_eq!(lookup("MS:0000000"), None);
70 assert_eq!(MINUTE.cv_ref(), "UO");
71 assert_eq!(MZ.cv_ref(), "MS");
72 }
73
74 #[test]
75 fn accessions_are_unique() {
76 let mut seen = std::collections::HashSet::new();
77 for t in ALL {
78 assert!(seen.insert(t.accession()), "duplicate {}", t.accession());
79 }
80 }
81}