Skip to main content

mzdata_meta/
file_description.rs

1use regex::{self, Regex};
2
3use crate::impl_param_described;
4// use crate::io::infer_format;
5use crate::params::{
6    ControlledVocabulary, Param, ParamDescribed, ParamList, ParamValue, ValueRef, CURIE,
7};
8
9/// Description of a source file, including location and type.
10///
11/// This is usually another mass spectrometry data file. For some
12/// vendor raw formats that are directories, there can be many files.
13/// See <https://peptideatlas.org/tmp/mzML1.1.0.html#sourceFile>.
14#[derive(Debug, Clone, Default, PartialEq, Eq)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct SourceFile {
17    /// The name of the source file without any path or location information
18    pub name: String,
19    /// The URI-formatted location where the file was retrieved.
20    pub location: String,
21    /// A unique identifier for this source file
22    pub id: String,
23    /// The [`MassSpectrometerFileFormatTerm`]-defined parameter for this file
24    pub file_format: Option<Param>,
25    /// The [`NativeSpectrumIdentifierFormatTerm`]-defined parameter for this file
26    pub id_format: Option<Param>,
27    /// The rest of the parameters for this file.
28    pub params: ParamList,
29}
30
31impl SourceFile {
32    /// Convert [`SourceFile::id_format`] into a [`NativeSpectrumIDFormat`] carrying its own
33    /// parser machinery, if such a term mapping exists
34    pub fn native_id_format(&self) -> Option<NativeSpectrumIDFormat> {
35        self.id_format
36            .as_ref()
37            .and_then(|p| p.curie())
38            .and_then(|p| NativeSpectrumIdentifierFormatTerm::from_curie(&p))
39            .map(|t| t.build())
40    }
41}
42
43/// A description of the file data file and its contents
44#[derive(Debug, Clone, Default, PartialEq, Eq)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
46pub struct FileDescription {
47    /// Descriptors of the content spectra
48    pub contents: ParamList,
49    /// Any source files involved in producing the current file, such as vendor raw files.
50    pub source_files: Vec<SourceFile>,
51}
52
53impl FileDescription {
54    pub fn new(contents: ParamList, source_files: Vec<SourceFile>) -> Self {
55        Self {
56            contents,
57            source_files,
58        }
59    }
60
61    /// Checks to see if the "MS1 spectrum" term is present in the file contents
62    ///
63    /// **Note**: This does not actually inspect the spectra in the file, only the metadata,
64    /// which may be incorrect/missing.
65    pub fn has_ms1_spectra(&self) -> bool {
66        self.get_param_by_curie(&CURIE::new(ControlledVocabulary::MS, 1000579))
67            .is_some()
68    }
69
70    /// Checks to see if the "MSn spectrum" term is present in the file contents.
71    ///
72    /// **Note**: This does not actually inspect the spectra in the file, only the metadata,
73    /// which may be incorrect/missing.
74    pub fn has_msn_spectra(&self) -> bool {
75        self.get_param_by_curie(&CURIE::new(ControlledVocabulary::MS, 1000580))
76            .is_some()
77    }
78
79    pub fn has_contents(&self) -> bool {
80        !self.contents.is_empty()
81    }
82}
83
84impl_param_described!(SourceFile);
85
86impl ParamDescribed for FileDescription {
87    fn params(&self) -> &[Param] {
88        &self.contents
89    }
90
91    fn params_mut(&mut self) -> &mut ParamList {
92        &mut self.contents
93    }
94}
95
96crate::cvmap! {
97    #[flag_type=&str]
98    #[allow(unused)]
99    #[doc = "A text-based schema that defines how native spectrum identifiers are formatted.
100    These patterns are often found in mzML-compatible formats."]
101    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
102    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
103    /*[[[cog
104    import cog
105    import subprocess
106    buf = subprocess.check_output(['python', 'cv/extract_native_ids.py']).decode('utf8')
107    for line in buf.splitlines():
108        cog.outl(line)
109    ]]]*/
110    pub enum NativeSpectrumIdentifierFormatTerm {
111        #[term(cv=MS, accession=1000767, name="native spectrum identifier format", flags={r"(.+)"}, parents={[]})]
112        #[doc = r"native spectrum identifier format - `(.+)`"]
113        NativeSpectrumIdentifierFormat,
114        #[term(cv=MS, accession=1000768, name="Thermo nativeID format", flags={r"controllerType=(?<controllerType>\d+) controllerNumber=(?<controllerNumber>\d+) scan=(?<scan>\d+)"}, parents={["MS:1000767"]})]
115        #[doc = r"Thermo nativeID format - `controllerType=(?<controllerType>\d+) controllerNumber=(?<controllerNumber>\d+) scan=(?<scan>\d+)`"]
116        ThermoNativeIDFormat,
117        #[term(cv=MS, accession=1000769, name="Waters nativeID format", flags={r"function=(?<function>\d+) process=(?<process>\d+) scan=(?<scan>\d+)"}, parents={["MS:1000767"]})]
118        #[doc = r"Waters nativeID format - `function=(?<function>\d+) process=(?<process>\d+) scan=(?<scan>\d+)`"]
119        WatersNativeIDFormat,
120        #[term(cv=MS, accession=1000770, name="WIFF nativeID format", flags={r"sample=(?<sample>\d+) period=(?<period>\d+) cycle=(?<cycle>\d+) experiment=(?<experiment>\d+)"}, parents={["MS:1000767"]})]
121        #[doc = r"WIFF nativeID format - `sample=(?<sample>\d+) period=(?<period>\d+) cycle=(?<cycle>\d+) experiment=(?<experiment>\d+)`"]
122        WIFFNativeIDFormat,
123        #[term(cv=MS, accession=1000771, name="Bruker/Agilent YEP nativeID format", flags={r"scan=(?<scan>\d+)"}, parents={["MS:1000767"]})]
124        #[doc = r"Bruker/Agilent YEP nativeID format - `scan=(?<scan>\d+)`"]
125        BrukerAgilentYEPNativeIDFormat,
126        #[term(cv=MS, accession=1000772, name="Bruker BAF nativeID format", flags={r"scan=(?<scan>\d+)"}, parents={["MS:1000767"]})]
127        #[doc = r"Bruker BAF nativeID format - `scan=(?<scan>\d+)`"]
128        BrukerBAFNativeIDFormat,
129        #[term(cv=MS, accession=1000773, name="Bruker FID nativeID format", flags={r"file=(?<file>\S+)"}, parents={["MS:1000767"]})]
130        #[doc = r"Bruker FID nativeID format - `file=(?<file>\S+)`"]
131        BrukerFIDNativeIDFormat,
132        #[term(cv=MS, accession=1000774, name="multiple peak list nativeID format", flags={r"index=(?<index>\d+)"}, parents={["MS:1000767"]})]
133        #[doc = r"multiple peak list nativeID format - `index=(?<index>\d+)`"]
134        MultiplePeakListNativeIDFormat,
135        #[term(cv=MS, accession=1000775, name="single peak list nativeID format", flags={r"file=(?<file>\S+)"}, parents={["MS:1000767"]})]
136        #[doc = r"single peak list nativeID format - `file=(?<file>\S+)`"]
137        SinglePeakListNativeIDFormat,
138        #[term(cv=MS, accession=1000776, name="scan number only nativeID format", flags={r"scan=(?<scan>\d+)"}, parents={["MS:1000767"]})]
139        #[doc = r"scan number only nativeID format - `scan=(?<scan>\d+)`"]
140        ScanNumberOnlyNativeIDFormat,
141        #[term(cv=MS, accession=1000777, name="spectrum identifier nativeID format", flags={r"spectrum=(?<spectrum>\d+)"}, parents={["MS:1000767"]})]
142        #[doc = r"spectrum identifier nativeID format - `spectrum=(?<spectrum>\d+)`"]
143        SpectrumIdentifierNativeIDFormat,
144        #[term(cv=MS, accession=1000823, name="Bruker U2 nativeID format", flags={r"declaration=(?<declaration>\d+) collection=(?<collection>\d+) scan=(?<scan>\d+)"}, parents={["MS:1000767"]})]
145        #[doc = r"Bruker U2 nativeID format - `declaration=(?<declaration>\d+) collection=(?<collection>\d+) scan=(?<scan>\d+)`"]
146        BrukerU2NativeIDFormat,
147        #[term(cv=MS, accession=1000824, name="no nativeID format", flags={r"(.+)"}, parents={["MS:1000767"]})]
148        #[doc = r"no nativeID format - `(.+)`"]
149        NoNativeIDFormat,
150        #[term(cv=MS, accession=1000929, name="Shimadzu Biotech nativeID format", flags={r"source=(?<source>\S+) start=(?<start>\d+) end=(?<end>\d+)"}, parents={["MS:1000767"]})]
151        #[doc = r"Shimadzu Biotech nativeID format - `source=(?<source>\S+) start=(?<start>\d+) end=(?<end>\d+)`"]
152        ShimadzuBiotechNativeIDFormat,
153        #[term(cv=MS, accession=1001186, name="Mobilion MBI nativeID format", flags={r"frame=(?<frame>\d+) scan=(?<scan>\d+)"}, parents={["MS:1000767"]})]
154        #[doc = r"Mobilion MBI nativeID format - `frame=(?<frame>\d+) scan=(?<scan>\d+)`"]
155        MobilionMBINativeIDFormat,
156        #[term(cv=MS, accession=1001480, name="SCIEX TOF/TOF nativeID format", flags={r"jobRun=(?<jobRun>\d+) spotLabel=(?<spotLabel>\S+) spectrum=(?<spectrum>\d+)"}, parents={["MS:1000767"]})]
157        #[doc = r"SCIEX TOF/TOF nativeID format - `jobRun=(?<jobRun>\d+) spotLabel=(?<spotLabel>\S+) spectrum=(?<spectrum>\d+)`"]
158        SCIEXTOFTOFNativeIDFormat,
159        #[term(cv=MS, accession=1001508, name="Agilent MassHunter nativeID format", flags={r"scanId=(?<scanId>\d+)"}, parents={["MS:1000767"]})]
160        #[doc = r"Agilent MassHunter nativeID format - `scanId=(?<scanId>\d+)`"]
161        AgilentMassHunterNativeIDFormat,
162        #[term(cv=MS, accession=1001526, name="spectrum from database integer nativeID format", flags={r"databasekey=(?<databasekey>-?\d+)"}, parents={["MS:1000767"]})]
163        #[doc = r"spectrum from database integer nativeID format - `databasekey=(?<databasekey>-?\d+)`"]
164        SpectrumFromDatabaseIntegerNativeIDFormat,
165        #[term(cv=MS, accession=1001528, name="Mascot query number", flags={r"query=(?<query>\d+)"}, parents={["MS:1000767", "MS:1001405"]})]
166        #[doc = r"Mascot query number - `query=(?<query>\d+)`"]
167        MascotQueryNumber,
168        #[term(cv=MS, accession=1001531, name="spectrum from ProteinScape database nativeID format", flags={r"databasekey=(?<databasekey>-?\d+)"}, parents={["MS:1000767", "MS:1001529"]})]
169        #[doc = r"spectrum from ProteinScape database nativeID format - `databasekey=(?<databasekey>-?\d+)`"]
170        SpectrumFromProteinScapeDatabaseNativeIDFormat,
171        #[term(cv=MS, accession=1001532, name="spectrum from database string nativeID format", flags={r"databasekey=(?<databasekey>\S+)"}, parents={["MS:1000767", "MS:1001529"]})]
172        #[doc = r"spectrum from database string nativeID format - `databasekey=(?<databasekey>\S+)`"]
173        SpectrumFromDatabaseStringNativeIDFormat,
174        #[term(cv=MS, accession=1001559, name="SCIEX TOF/TOF T2D nativeID format", flags={r"file=(?<file>\S+)"}, parents={["MS:1000767"]})]
175        #[doc = r"SCIEX TOF/TOF T2D nativeID format - `file=(?<file>\S+)`"]
176        SCIEXTOFTOFT2DNativeIDFormat,
177        #[term(cv=MS, accession=1001562, name="Scaffold nativeID format", flags={r"(.+)"}, parents={["MS:1000767"]})]
178        #[doc = r"Scaffold nativeID format - `(.+)`"]
179        ScaffoldNativeIDFormat,
180        #[term(cv=MS, accession=1002303, name="Bruker Container nativeID format", flags={r"(.+)"}, parents={["MS:1000767"]})]
181        #[doc = r"Bruker Container nativeID format - `(.+)`"]
182        BrukerContainerNativeIDFormat,
183        #[term(cv=MS, accession=1002532, name="UIMF nativeID format", flags={r"frame=(?<frame>\d+) scan=(?<scan>\d+) frameType=(?<frameType>\d+)"}, parents={["MS:1000767"]})]
184        #[doc = r"UIMF nativeID format - `frame=(?<frame>\d+) scan=(?<scan>\d+) frameType=(?<frameType>\d+)`"]
185        UIMFNativeIDFormat,
186        #[term(cv=MS, accession=1002818, name="Bruker TDF nativeID format", flags={r"frame=(?<frame>\d+) scan=(?<scan>\d+)"}, parents={["MS:1000767"]})]
187        #[doc = r"Bruker TDF nativeID format - `frame=(?<frame>\d+) scan=(?<scan>\d+)`"]
188        BrukerTDFNativeIDFormat,
189        #[term(cv=MS, accession=1002898, name="Shimadzu Biotech QTOF nativeID format", flags={r"scan=(?<scan>\d+)"}, parents={["MS:1000767"]})]
190        #[doc = r"Shimadzu Biotech QTOF nativeID format - `scan=(?<scan>\d+)`"]
191        ShimadzuBiotechQTOFNativeIDFormat,
192        #[term(cv=MS, accession=1003283, name="Bruker TSF nativeID format", flags={r"frame=(?<frame>\d+)"}, parents={["MS:1000767"]})]
193        #[doc = r"Bruker TSF nativeID format - `frame=(?<frame>\d+)`"]
194        BrukerTSFNativeIDFormat,
195    }
196    //[[[end]]] (sum: q+gQ/J50Sc)
197}
198
199/// A text-based schema that defines how native spectrum identifiers are formatted.
200///
201/// These patterns are often found in mzML-compatible formats.
202#[derive(Debug, Clone)]
203pub struct NativeSpectrumIDFormat {
204    pub term: NativeSpectrumIdentifierFormatTerm,
205    parser: Regex,
206    field_names: Vec<Option<String>>,
207}
208
209impl PartialEq for NativeSpectrumIDFormat {
210    fn eq(&self, other: &Self) -> bool {
211        self.term == other.term
212    }
213}
214
215impl From<NativeSpectrumIdentifierFormatTerm> for NativeSpectrumIDFormat {
216    fn from(value: NativeSpectrumIdentifierFormatTerm) -> Self {
217        Self::new(value)
218    }
219}
220
221#[derive(Debug, Clone, thiserror::Error, PartialEq)]
222pub enum NativeIDFormatError {
223    /// The ID format required a different number of groups than what were found
224    #[error("{term:?} required {expected} arguments, but received {received} arguments")]
225    IncorrectArgumentNumber {
226        term: NativeSpectrumIdentifierFormatTerm,
227        expected: usize,
228        received: usize,
229    },
230    /// The ID format's pattern did not match the provided string
231    #[error("{term:?} did not match {text}")]
232    PatternMismatch {
233        term: NativeSpectrumIdentifierFormatTerm,
234        text: String,
235    },
236}
237
238impl NativeSpectrumIDFormat {
239    pub fn new(term: NativeSpectrumIdentifierFormatTerm) -> Self {
240        let parser = term.parser();
241        let field_names = parser
242            .capture_names()
243            .skip(1)
244            .map(|s| s.map(|i| i.to_string()))
245            .collect();
246        Self {
247            term,
248            parser,
249            field_names,
250        }
251    }
252
253    pub const fn name(&self) -> &str {
254        self.term.name()
255    }
256
257    pub const fn curie(&self) -> CURIE {
258        CURIE::new(self.term.controlled_vocabulary(), self.term.accession())
259    }
260
261    /// This parses the provided string, returning the captured groups of the ID pattern if they are present
262    /// in a [`regex::Captures`] structure that can be indexed by group number.
263    pub fn parse<'h>(&self, ident: &'h str) -> Option<regex::Captures<'h>> {
264        self.parser.captures(ident)
265    }
266
267    /// This parses the provided string, returning the capture groups as (name, value) pairs they are present
268    pub fn parse_named<'h>(
269        &self,
270        ident: &'h str,
271    ) -> Result<Vec<(Option<String>, &'h str)>, NativeIDFormatError> {
272        if let Some(hits) = self.parser.captures(ident) {
273            Ok(self
274                .parser
275                .capture_names()
276                .enumerate()
277                .map(|(i, name)| {
278                    let m = if let Some(name_) = name {
279                        hits.name(name_).unwrap()
280                    } else {
281                        hits.get(i).unwrap()
282                    };
283                    (name.map(|s| s.to_string()), m.as_str())
284                })
285                .collect())
286        } else {
287            Err(NativeIDFormatError::PatternMismatch {
288                term: self.term,
289                text: ident.to_string(),
290            })
291        }
292    }
293
294    /// Given the field values of a nativeID format, create string in that format
295    pub fn format<'h>(
296        &self,
297        values: impl IntoIterator<Item = ValueRef<'h>>,
298    ) -> Result<String, NativeIDFormatError> {
299        let mut buffer = String::with_capacity(64);
300        let names = &self.field_names;
301        let n_names = names.len().saturating_sub(1);
302        let values: Vec<_> = values.into_iter().collect();
303        if values.len() != names.len() {
304            return Err(NativeIDFormatError::IncorrectArgumentNumber {
305                term: self.term,
306                expected: names.len(),
307                received: values.len(),
308            });
309        }
310        for (i, (k, v)) in names.iter().zip(values).enumerate() {
311            match k {
312                Some(k) => {
313                    buffer.push_str(k);
314                    buffer.push('=');
315                    buffer.push_str(&v.as_str());
316                }
317                None => {
318                    buffer.push_str(&v.as_str());
319                }
320            };
321            if i < n_names {
322                buffer.push(' ');
323            }
324        }
325        Ok(buffer)
326    }
327}
328
329impl NativeSpectrumIdentifierFormatTerm {
330    /// Create a new [`regex::Regex`] for this identifier format.
331    pub fn parser(&self) -> regex::Regex {
332        regex::Regex::new(self.flags()).unwrap()
333    }
334
335    /// This parses the provided string, returning the captured groups of the ID pattern if they are present
336    /// in a [`regex::Captures`] structure that can be indexed by group number.
337    ///
338    /// # Note
339    /// This method creates a new regular expression on each invocation, making it expensive to invoke.
340    /// If you must call this repeatedly, instead use [`NativeSpectrumIdentifierFormatTerm::build`] to create a
341    /// the regular expression once and re-use it directly.
342    pub fn parse<'h>(&self, ident: &'h str) -> Option<regex::Captures<'h>> {
343        let parser = self.parser();
344        parser.captures(ident)
345    }
346
347    /// Create a [`NativeSpectrumIDFormat`] that owns the [`Regex`] produced
348    /// by [`NativeSpectrumIdentifierFormatTerm::parser`]
349    pub fn build(&self) -> NativeSpectrumIDFormat {
350        (*self).into()
351    }
352
353    /// Given the field values of a nativeID format, create string in that format
354    ///
355    /// # Note
356    /// This method creates a new expression formatter every time.
357    /// Use [`NativeSpectrumIdentifierFormatTerm::build`] to create a re-useable
358    /// parser/formatter.
359    pub fn format<'h>(&self, values: impl IntoIterator<Item = ValueRef<'h>>) -> String {
360        self.build().format(values).unwrap()
361    }
362
363    /// This parses the provided string, returning the capture groups as (name, value) pairs they are present.
364    ///
365    /// # Note
366    /// This method creates a new regular expression on each invocation, making it expensive to invoke.
367    /// If you must call this repeatedly, instead use [`NativeSpectrumIdentifierFormatTerm::build`] to create a
368    /// the regular expression once and re-use it directly.
369    pub fn parse_named<'h>(&self, ident: &'h str) -> Vec<(Option<String>, &'h str)> {
370        self.build().parse_named(ident).unwrap()
371    }
372}
373
374crate::cvmap! {
375    #[flag_type=i32]
376    #[allow(unused)]
377    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
378    /*[[[cog
379    import cog
380    import subprocess
381    buf = subprocess.check_output(['python', 'cv/extract_file_formats.py']).decode('utf8')
382    for line in buf.splitlines():
383        cog.outl(line)
384    ]]]*/
385    pub enum MassSpectrometerFileFormatTerm {
386        #[term(cv=MS, accession=1000526, name="Waters raw format", flags={0}, parents={["MS:1000560"]})]
387        #[doc = "Waters raw format - Waters data file format found in a Waters RAW directory, generated from an MS acquisition."]
388        WatersRaw,
389        #[term(cv=MS, accession=1000560, name="mass spectrometer file format", flags={0}, parents={["MS:1001459"]})]
390        #[doc = "mass spectrometer file format - The format of the file being used. This could be a instrument or vendor specific proprietary file format or a converted open file format."]
391        MassSpectrometerFile,
392        #[term(cv=MS, accession=1000562, name="ABI WIFF format", flags={0}, parents={["MS:1000560"]})]
393        #[doc = "ABI WIFF format - Applied Biosystems WIFF file format."]
394        ABIWIFF,
395        #[term(cv=MS, accession=1000563, name="Thermo RAW format", flags={0}, parents={["MS:1000560"]})]
396        #[doc = "Thermo RAW format - Thermo Scientific RAW file format."]
397        ThermoRAW,
398        #[term(cv=MS, accession=1000564, name="PSI mzData format", flags={0}, parents={["MS:1000560"]})]
399        #[doc = "PSI mzData format - Proteomics Standards Initiative mzData file format."]
400        PSIMzData,
401        #[term(cv=MS, accession=1000565, name="Micromass PKL format", flags={0}, parents={["MS:1000560"]})]
402        #[doc = "Micromass PKL format - Micromass PKL file format."]
403        MicromassPKL,
404        #[term(cv=MS, accession=1000566, name="ISB mzXML format", flags={0}, parents={["MS:1000560"]})]
405        #[doc = "ISB mzXML format - Institute of Systems Biology mzXML file format."]
406        ISBMzXML,
407        #[term(cv=MS, accession=1000567, name="Bruker/Agilent YEP format", flags={0}, parents={["MS:1000560"]})]
408        #[doc = "Bruker/Agilent YEP format - Bruker/Agilent YEP file format."]
409        BrukerAgilentYEP,
410        #[term(cv=MS, accession=1000584, name="mzML format", flags={0}, parents={["MS:1000560"]})]
411        #[doc = "mzML format - Proteomics Standards Initiative mzML file format."]
412        MzML,
413        #[term(cv=MS, accession=1000613, name="DTA format", flags={0}, parents={["MS:1000560"]})]
414        #[doc = "DTA format - SEQUEST DTA file format."]
415        DTA,
416        #[term(cv=MS, accession=1000614, name="ProteinLynx Global Server mass spectrum XML format", flags={0}, parents={["MS:1000560"]})]
417        #[doc = "ProteinLynx Global Server mass spectrum XML format - Peak list file format used by ProteinLynx Global Server."]
418        ProteinLynxGlobalServerMassSpectrumXML,
419        #[term(cv=MS, accession=1000740, name="parameter file", flags={0}, parents={["MS:1000560"]})]
420        #[doc = "parameter file - Parameter file used to configure the acquisition of raw data on the instrument."]
421        ParameterFile,
422        #[term(cv=MS, accession=1000742, name="Bioworks SRF format", flags={0}, parents={["MS:1000560", "MS:1001040"]})]
423        #[doc = "Bioworks SRF format - Thermo Finnigan SRF file format."]
424        BioworksSRF,
425        #[term(cv=MS, accession=1000815, name="Bruker BAF format", flags={0}, parents={["MS:1000560"]})]
426        #[doc = "Bruker BAF format - Bruker BAF raw file format."]
427        BrukerBAF,
428        #[term(cv=MS, accession=1000816, name="Bruker U2 format", flags={0}, parents={["MS:1000560"]})]
429        #[doc = "Bruker U2 format - Bruker HyStar U2 file format."]
430        BrukerU2,
431        #[term(cv=MS, accession=1000825, name="Bruker FID format", flags={0}, parents={["MS:1000560"]})]
432        #[doc = "Bruker FID format - Bruker FID file format."]
433        BrukerFID,
434        #[term(cv=MS, accession=1000930, name="Shimadzu Biotech database entity", flags={0}, parents={["MS:1000560"]})]
435        #[doc = "Shimadzu Biotech database entity - Shimadzu Biotech format."]
436        ShimadzuBiotechDatabaseEntity,
437        #[term(cv=MS, accession=1001062, name="Mascot MGF format", flags={0}, parents={["MS:1000560"]})]
438        #[doc = "Mascot MGF format - Mascot MGF file format."]
439        MascotMGF,
440        #[term(cv=MS, accession=1001185, name="Mobilion MBI format", flags={0}, parents={["MS:1000560"]})]
441        #[doc = "Mobilion MBI format - Mobilion MBI file format."]
442        MobilionMBI,
443        #[term(cv=MS, accession=1001245, name="PerSeptive PKS format", flags={0}, parents={["MS:1000560"]})]
444        #[doc = "PerSeptive PKS format - PerSeptive peak list file format."]
445        PerSeptivePKS,
446        #[term(cv=MS, accession=1001246, name="SCIEX API III format", flags={0}, parents={["MS:1000560"]})]
447        #[doc = "SCIEX API III format - PE SCIEX peak list file format."]
448        SCIEXAPIIII,
449        #[term(cv=MS, accession=1001247, name="Bruker XML format", flags={0}, parents={["MS:1000560"]})]
450        #[doc = "Bruker XML format - Bruker data exchange XML format."]
451        BrukerXML,
452        #[term(cv=MS, accession=1001369, name="text format", flags={0}, parents={["MS:1000560"]})]
453        #[doc = "text format - Simple text file format of 'm/z \\[intensity\\]' values for a PMF (or single MS2) search."]
454        Text,
455        #[term(cv=MS, accession=1001463, name="Phenyx XML format", flags={0}, parents={["MS:1000560", "MS:1001040"]})]
456        #[doc = "Phenyx XML format - Phenyx open XML file format."]
457        PhenyxXML,
458        #[term(cv=MS, accession=1001466, name="MS2 format", flags={0}, parents={["MS:1000560"]})]
459        #[doc = "MS2 format - MS2 file format for MS2 spectral data."]
460        MS2,
461        #[term(cv=MS, accession=1001481, name="SCIEX TOF/TOF database", flags={0}, parents={["MS:1000560"]})]
462        #[doc = "SCIEX TOF/TOF database - Applied Biosystems/MDS Analytical Technologies TOF/TOF instrument database."]
463        SCIEXTOFTOFDatabase,
464        #[term(cv=MS, accession=1001509, name="Agilent MassHunter format", flags={0}, parents={["MS:1000560"]})]
465        #[doc = "Agilent MassHunter format - A data file format found in an Agilent MassHunter directory which contains raw data acquired by an Agilent mass spectrometer."]
466        AgilentMassHunter,
467        #[term(cv=MS, accession=1001527, name="Proteinscape spectra", flags={0}, parents={["MS:1000560"]})]
468        #[doc = "Proteinscape spectra - Spectra from Bruker/Protagen Proteinscape database."]
469        ProteinscapeSpectra,
470        #[term(cv=MS, accession=1001560, name="SCIEX TOF/TOF T2D format", flags={0}, parents={["MS:1000560"]})]
471        #[doc = "SCIEX TOF/TOF T2D format - Applied Biosystems/MDS Analytical Technologies TOF/TOF instrument export format."]
472        SCIEXTOFTOFT2D,
473        #[term(cv=MS, accession=1001881, name="mz5 format", flags={0}, parents={["MS:1000560"]})]
474        #[doc = "mz5 format - mz5 file format, modelled after mzML."]
475        Mz5,
476        #[term(cv=MS, accession=1002302, name="Bruker Container format", flags={0}, parents={["MS:1000560"]})]
477        #[doc = "Bruker Container format - Bruker Container raw file format."]
478        BrukerContainer,
479        #[term(cv=MS, accession=1002385, name="SCiLS Lab format", flags={0}, parents={["MS:1000560"]})]
480        #[doc = "SCiLS Lab format - SCiLS Lab file format."]
481        SCiLSLab,
482        #[term(cv=MS, accession=1002441, name="Andi-MS format", flags={0}, parents={["MS:1000560"]})]
483        #[doc = "Andi-MS format - AIA Analytical Data Interchange file format for mass spectrometry data."]
484        AndiMS,
485        #[term(cv=MS, accession=1002531, name="UIMF format", flags={0}, parents={["MS:1000560"]})]
486        #[doc = "UIMF format - SQLite-based file format created at Pacific Northwest National Lab. It stores an intermediate analysis of ion-mobility mass spectrometry data."]
487        UIMF,
488        #[term(cv=MS, accession=1002597, name="MS1 format", flags={0}, parents={["MS:1000560"]})]
489        #[doc = "MS1 format - MS1 file format for MS1 spectral data."]
490        MS1,
491        #[term(cv=MS, accession=1002817, name="Bruker TDF format", flags={0}, parents={["MS:1000560"]})]
492        #[doc = "Bruker TDF format - Bruker TDF raw file format."]
493        BrukerTDF,
494        #[term(cv=MS, accession=1002838, name="mzMLb format", flags={0}, parents={["MS:1000560"]})]
495        #[doc = "mzMLb format - mzMLb file format, mzML encapsulated within HDF5."]
496        MzMLb,
497        #[term(cv=MS, accession=1002899, name="msalign format", flags={0}, parents={["MS:1000560"]})]
498        #[doc = "msalign format - msalign file format."]
499        Msalign,
500        #[term(cv=MS, accession=1002900, name="feature format", flags={0}, parents={["MS:1000560"]})]
501        #[doc = "feature format - TopFD feature file format."]
502        Feature,
503        #[term(cv=MS, accession=1002966, name="chrom format", flags={0}, parents={["MS:1000560"]})]
504        #[doc = "chrom format - The Lipid Data Analyzer native chrom format."]
505        Chrom,
506        #[term(cv=MS, accession=1002996, name="Andromeda:apl file format", flags={0}, parents={["MS:1000560"]})]
507        #[doc = "Andromeda:apl file format - Peak list file format of the Andromeda search engine."]
508        AndromedaAplFile,
509        #[term(cv=MS, accession=1003009, name="Shimadzu Biotech LCD format", flags={0}, parents={["MS:1000560"]})]
510        #[doc = "Shimadzu Biotech LCD format - Shimadzu Biotech LCD file format."]
511        ShimadzuBiotechLCD,
512        #[term(cv=MS, accession=1003282, name="Bruker TSF format", flags={0}, parents={["MS:1000560"]})]
513        #[doc = "Bruker TSF format - Bruker TSF raw file format."]
514        BrukerTSF,
515        #[term(cv=MS, accession=1003374, name="Open Chromatography Binary OCB format", flags={0}, parents={["MS:1000560"]})]
516        #[doc = "Open Chromatography Binary OCB format - ChemClipse/OpenChrom file format."]
517        OpenChromatographyBinaryOCB,
518        #[term(cv=MS, accession=1003448, name="SCIEX WIFF2 format", flags={0}, parents={["MS:1000560"]})]
519        #[doc = "SCIEX WIFF2 format - SCIEX WIFF2 file format."]
520        SCIEXWIFF2,
521        #[term(cv=MS, accession=1003610, name="mzPeak format", flags={0}, parents={["MS:1000560"]})]
522        #[doc = "mzPeak format - Proteomics Standards Initiatve mzPeak file format."]
523        MzPeak,
524        #[term(cv=MS, accession=1003611, name="imzML format", flags={0}, parents={["MS:1000560"]})]
525        #[doc = "imzML format - IMSIS imzML imaging file format."]
526        ImzML,
527        #[term(cv=MS, accession=1003810, name="Ionoptika V1 format", flags={0}, parents={["MS:1000560"]})]
528        #[doc = "Ionoptika V1 format - Ionoptika data format generated by J105 TOF-SIMS instrument."]
529        IonoptikaV1,
530        #[term(cv=MS, accession=1003811, name="Ionoptika V3 format", flags={0}, parents={["MS:1000560"]})]
531        #[doc = "Ionoptika V3 format - Ionoptika data format generated by J105 TOF-SIMS instrument."]
532        IonoptikaV3,
533        #[term(cv=MS, accession=1003973, name="LECO PEG format", flags={0}, parents={["MS:1000560"]})]
534        #[doc = "LECO PEG format - Proprietary binary data format with extension '.peg', used by LECO ChromaTOF software to store raw and processed data from LECO Pegasus series mass spectrometers."]
535        LECOPEG,
536        #[term(cv=MS, accession=1003974, name="JEOL JPF format", flags={0}, parents={["MS:1000560"]})]
537        #[doc = "JEOL JPF format - Proprietary binary data format with extension '.jpf', used by JEOL mass spectrometry systems and associated data processing software to store mass spectral data."]
538        JEOLJPF,
539    }
540    //[[[end]]] (sum: yJZKtYY8y6)
541}
542
543#[allow(unused, clippy::upper_case_acronyms)]
544#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
545#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
546#[doc = "The kinds of spectrum that might be represented"]
547pub enum SpectrumType {
548    #[doc = "mass spectrum - A plot of the relative abundance of a beam or other collection of ions as a function of the mass-to-charge ratio (m/z)."]
549    MassSpectrum,
550    #[doc = "charge inversion mass spectrum - The measurement of the relative abundance of ions that result from a charge inversion reaction as a function of m/z."]
551    ChargeInversionMassSpectrum,
552    #[doc = "constant neutral gain spectrum - A spectrum formed of all product ions that have been produced by gain of a pre-selected neutral mass following the reaction with and addition of the gas in a collision cell."]
553    ConstantNeutralGainSpectrum,
554    #[doc = "constant neutral loss spectrum - A spectrum formed of all product ions that have been produced with a selected m/z decrement from any precursor ions. The spectrum shown correlates to the precursor ion spectrum. See also neutral loss spectrum."]
555    ConstantNeutralLossSpectrum,
556    #[doc = "e/2 mass spectrum - A mass spectrum obtained using a sector mass spectrometer in which the electric sector field E is set to half the value required to transmit the main ion-beam. This spectrum records the signal from doubly charged product ions of charge-stripping reactions."]
557    E2MassSpectrum,
558    #[doc = "precursor ion spectrum - Spectrum generated by scanning precursor m/z while monitoring a fixed product m/z."]
559    PrecursorIonSpectrum,
560    #[doc = "product ion spectrum - OBSOLETE A mass spectrum recorded from any spectrometer in which the appropriate m/z separation scan function is set to record the product ion or ions of selected precursor ions."]
561    ProductIonSpectrum,
562    #[doc = "MS1 spectrum - Mass spectrum created by a single-stage MS experiment or the first stage of a multi-stage experiment."]
563    MS1Spectrum,
564    #[doc = "MSn spectrum - MSn refers to multi-stage MS2 experiments designed to record product ion spectra where n is the number of product ion stages (progeny ions). For ion traps, sequential MS/MS experiments can be undertaken where n > 2 whereas for a simple triple quadrupole system n=2. Use the term ms level (MS:1000511) for specifying n."]
565    MSnSpectrum,
566    #[doc = "CRM spectrum - Spectrum generated from MSn experiment with three or more stages of m/z separation and in which a particular multi-step reaction path is monitored."]
567    CRMSpectrum,
568    #[doc = "SIM spectrum - Spectrum obtained with the operation of a mass spectrometer in which the abundances of one ion or several ions of specific m/z values are recorded rather than the entire mass spectrum (Selected Ion Monitoring)."]
569    SIMSpectrum,
570    #[doc = "SRM spectrum - Spectrum obtained when data are acquired from specific product ions corresponding to m/z values of selected precursor ions a recorded via two or more stages of mass spectrometry. The precursor/product ion pair is called a transition pair. Data can be obtained for a single transition pair or multiple transition pairs. Multiple time segments of different transition pairs can exist in a single file. Single precursor ions can have multiple product ions consitituting multiple transition pairs. Selected reaction monitoring can be performed as tandem mass spectrometry in time or tandem mass spectrometry in space."]
571    SRMSpectrum,
572    #[doc = "PDA spectrum - OBSOLETE Spectrum generated from a photodiode array detector (ultraviolet/visible spectrum)."]
573    PDASpectrum,
574    #[doc = "enhanced multiply charged spectrum - MS1 spectrum that is enriched in multiply-charged ions compared to singly-charged ions."]
575    EnhancedMultiplyChargedSpectrum,
576    #[doc = "time-delayed fragmentation spectrum - MSn spectrum in which the product ions are collected after a time delay, which allows the observation of lower energy fragmentation processes after precursor ion activation."]
577    TimeDelayedFragmentationSpectrum,
578    #[doc = "electromagnetic radiation spectrum - A plot of the relative intensity of electromagnetic radiation as a function of the wavelength."]
579    ElectromagneticRadiationSpectrum,
580    #[doc = "emission spectrum - A plot of the relative intensity of electromagnetic radiation emitted by atoms or molecules when excited."]
581    EmissionSpectrum,
582    #[doc = "absorption spectrum - A plot of the relative intensity of electromagnetic radiation absorbed by atoms or molecules when excited."]
583    AbsorptionSpectrum,
584}
585#[doc = r" These methods are part of the controlled vocabulary mapping"]
586impl SpectrumType {
587    #[doc = r" Retrieve the accession number for this term, independent of its controlled vocabulary"]
588    pub const fn accession(&self) -> crate::params::AccessionIntCode {
589        match self {
590            Self::MassSpectrum => 1000294,
591            Self::ChargeInversionMassSpectrum => 1000322,
592            Self::ConstantNeutralGainSpectrum => 1000325,
593            Self::ConstantNeutralLossSpectrum => 1000326,
594            Self::E2MassSpectrum => 1000328,
595            Self::PrecursorIonSpectrum => 1000341,
596            Self::ProductIonSpectrum => 1000343,
597            Self::MS1Spectrum => 1000579,
598            Self::MSnSpectrum => 1000580,
599            Self::CRMSpectrum => 1000581,
600            Self::SIMSpectrum => 1000582,
601            Self::SRMSpectrum => 1000583,
602            Self::PDASpectrum => 1000620,
603            Self::EnhancedMultiplyChargedSpectrum => 1000789,
604            Self::TimeDelayedFragmentationSpectrum => 1000790,
605            Self::ElectromagneticRadiationSpectrum => 1000804,
606            Self::EmissionSpectrum => 1000805,
607            Self::AbsorptionSpectrum => 1000806,
608        }
609    }
610    #[doc = r" Retrieve the controlled vocabulary this term belongs to"]
611    pub const fn controlled_vocabulary(&self) -> crate::params::ControlledVocabulary {
612        match self {
613            Self::MassSpectrum => crate::params::ControlledVocabulary::MS,
614            Self::ChargeInversionMassSpectrum => crate::params::ControlledVocabulary::MS,
615            Self::ConstantNeutralGainSpectrum => crate::params::ControlledVocabulary::MS,
616            Self::ConstantNeutralLossSpectrum => crate::params::ControlledVocabulary::MS,
617            Self::E2MassSpectrum => crate::params::ControlledVocabulary::MS,
618            Self::PrecursorIonSpectrum => crate::params::ControlledVocabulary::MS,
619            Self::ProductIonSpectrum => crate::params::ControlledVocabulary::MS,
620            Self::MS1Spectrum => crate::params::ControlledVocabulary::MS,
621            Self::MSnSpectrum => crate::params::ControlledVocabulary::MS,
622            Self::CRMSpectrum => crate::params::ControlledVocabulary::MS,
623            Self::SIMSpectrum => crate::params::ControlledVocabulary::MS,
624            Self::SRMSpectrum => crate::params::ControlledVocabulary::MS,
625            Self::PDASpectrum => crate::params::ControlledVocabulary::MS,
626            Self::EnhancedMultiplyChargedSpectrum => crate::params::ControlledVocabulary::MS,
627            Self::TimeDelayedFragmentationSpectrum => crate::params::ControlledVocabulary::MS,
628            Self::ElectromagneticRadiationSpectrum => crate::params::ControlledVocabulary::MS,
629            Self::EmissionSpectrum => crate::params::ControlledVocabulary::MS,
630            Self::AbsorptionSpectrum => crate::params::ControlledVocabulary::MS,
631        }
632    }
633    #[doc = r" Retrieve the plain text human readable name for this term"]
634    pub const fn name(&self) -> &'static str {
635        match self {
636            Self::MassSpectrum => "mass spectrum",
637            Self::ChargeInversionMassSpectrum => "charge inversion mass spectrum",
638            Self::ConstantNeutralGainSpectrum => "constant neutral gain spectrum",
639            Self::ConstantNeutralLossSpectrum => "constant neutral loss spectrum",
640            Self::E2MassSpectrum => "e/2 mass spectrum",
641            Self::PrecursorIonSpectrum => "precursor ion spectrum",
642            Self::ProductIonSpectrum => "product ion spectrum",
643            Self::MS1Spectrum => "MS1 spectrum",
644            Self::MSnSpectrum => "MSn spectrum",
645            Self::CRMSpectrum => "CRM spectrum",
646            Self::SIMSpectrum => "SIM spectrum",
647            Self::SRMSpectrum => "SRM spectrum",
648            Self::PDASpectrum => "PDA spectrum",
649            Self::EnhancedMultiplyChargedSpectrum => "enhanced multiply charged spectrum",
650            Self::TimeDelayedFragmentationSpectrum => "time-delayed fragmentation spectrum",
651            Self::ElectromagneticRadiationSpectrum => "electromagnetic radiation spectrum",
652            Self::EmissionSpectrum => "emission spectrum",
653            Self::AbsorptionSpectrum => "absorption spectrum",
654        }
655    }
656    #[doc = r" Attempt to map a string by name to retrieve one of the terms from this"]
657    #[doc = r" set."]
658    #[doc = r""]
659    #[doc = r" If no match is found, [`None`] is returned."]
660    pub fn from_name(name: &str) -> Option<Self> {
661        match name {
662            "mass spectrum" => Some(Self::MassSpectrum),
663            "charge inversion mass spectrum" => Some(Self::ChargeInversionMassSpectrum),
664            "constant neutral gain spectrum" => Some(Self::ConstantNeutralGainSpectrum),
665            "constant neutral loss spectrum" => Some(Self::ConstantNeutralLossSpectrum),
666            "e/2 mass spectrum" => Some(Self::E2MassSpectrum),
667            "precursor ion spectrum" => Some(Self::PrecursorIonSpectrum),
668            "product ion spectrum" => Some(Self::ProductIonSpectrum),
669            "MS1 spectrum" => Some(Self::MS1Spectrum),
670            "MSn spectrum" => Some(Self::MSnSpectrum),
671            "CRM spectrum" => Some(Self::CRMSpectrum),
672            "SIM spectrum" => Some(Self::SIMSpectrum),
673            "SRM spectrum" => Some(Self::SRMSpectrum),
674            "PDA spectrum" => Some(Self::PDASpectrum),
675            "enhanced multiply charged spectrum" => Some(Self::EnhancedMultiplyChargedSpectrum),
676            "time-delayed fragmentation spectrum" => Some(Self::TimeDelayedFragmentationSpectrum),
677            "electromagnetic radiation spectrum" => Some(Self::ElectromagneticRadiationSpectrum),
678            "emission spectrum" => Some(Self::EmissionSpectrum),
679            "absorption spectrum" => Some(Self::AbsorptionSpectrum),
680            _ => None,
681        }
682    }
683    #[doc = r" Attempt to map the numeric accession number to retrieve one of the terms from this"]
684    #[doc = r" set."]
685    #[doc = r""]
686    #[doc = r" If no match is found, [`None`] is returned."]
687    pub const fn from_accession(accession: crate::params::AccessionIntCode) -> Option<Self> {
688        match accession {
689            1000294 => Some(Self::MassSpectrum),
690            1000322 => Some(Self::ChargeInversionMassSpectrum),
691            1000325 => Some(Self::ConstantNeutralGainSpectrum),
692            1000326 => Some(Self::ConstantNeutralLossSpectrum),
693            1000328 => Some(Self::E2MassSpectrum),
694            1000341 => Some(Self::PrecursorIonSpectrum),
695            1000343 => Some(Self::ProductIonSpectrum),
696            1000579 => Some(Self::MS1Spectrum),
697            1000580 => Some(Self::MSnSpectrum),
698            1000581 => Some(Self::CRMSpectrum),
699            1000582 => Some(Self::SIMSpectrum),
700            1000583 => Some(Self::SRMSpectrum),
701            1000620 => Some(Self::PDASpectrum),
702            1000789 => Some(Self::EnhancedMultiplyChargedSpectrum),
703            1000790 => Some(Self::TimeDelayedFragmentationSpectrum),
704            1000804 => Some(Self::ElectromagneticRadiationSpectrum),
705            1000805 => Some(Self::EmissionSpectrum),
706            1000806 => Some(Self::AbsorptionSpectrum),
707            _ => None,
708        }
709    }
710    #[doc = r" Convert this term into a [`ParamCow`](crate::params::ParamCow) without a value."]
711    pub const fn to_param(self) -> crate::params::ParamCow<'static> {
712        crate::params::ParamCow::const_new(
713            self.name(),
714            crate::params::ValueRef::Empty,
715            Some(self.accession()),
716            Some(self.controlled_vocabulary()),
717            crate::params::Unit::Unknown,
718        )
719    }
720    #[doc = r" Convert a [`CURIE`]($crate::params::CURIE) by accession."]
721    #[doc = r""]
722    #[doc = r" If no match is found, [`None`] is returned."]
723    pub const fn from_curie(curie: &crate::params::CURIE) -> Option<Self> {
724        if matches!(
725            curie.controlled_vocabulary,
726            crate::params::ControlledVocabulary::MS
727        ) {
728            Self::from_accession(curie.accession)
729        } else {
730            None
731        }
732    }
733    #[doc = r" Attempt to convert a [`ParamCow`](crate::params::ParamCow) to a term from this set."]
734    #[doc = r""]
735    #[doc = r" If no match is found, [`None`] is returned."]
736    #[doc = r""]
737    #[doc = r" # Note"]
738    #[doc = r" This method can be called in `const` contexts, requiring the type be [`ParamCow`](crate::params::ParamCow) with a `'static`"]
739    #[doc = r" lifetime parameter, but the regular [`From`] trait is implemented for all [`ParamLike`](crate::params::ParamLike) types."]
740    pub const fn from_param(p: &crate::params::ParamCow<'static>) -> Option<Self> {
741        if let Some(acc) = p.accession {
742            Self::from_accession(acc)
743        } else {
744            None
745        }
746    }
747    #[doc = r" Retrieve a term set specific set of flags"]
748    pub fn flags(&self) -> i32 {
749        match self {
750            Self::MassSpectrum => { 0 },
751            Self::ChargeInversionMassSpectrum => { 0 },
752            Self::ConstantNeutralGainSpectrum => { 0 },
753            Self::ConstantNeutralLossSpectrum => { 0 },
754            Self::E2MassSpectrum => { 0 },
755            Self::PrecursorIonSpectrum => { 0 },
756            Self::ProductIonSpectrum => { 0 },
757            Self::MS1Spectrum => { 0 },
758            Self::MSnSpectrum => { 0 },
759            Self::CRMSpectrum => { 0 },
760            Self::SIMSpectrum => { 0 },
761            Self::SRMSpectrum => { 0 },
762            Self::PDASpectrum => { 0 },
763            Self::EnhancedMultiplyChargedSpectrum => { 0 },
764            Self::TimeDelayedFragmentationSpectrum => { 0 },
765            Self::ElectromagneticRadiationSpectrum => { 0 },
766            Self::EmissionSpectrum => { 0 },
767            Self::AbsorptionSpectrum => { 0 },
768        }
769    }
770    #[doc = r" Retrieve the list of zero or more terms in the set which are"]
771    #[doc = r" parents of this term."]
772    pub fn parents(&self) -> Vec<Self> {
773        match self {
774            Self::MassSpectrum => { ["MS:1000524", "MS:1000559"] }
775                .iter()
776                .flat_map(|s: &&str| {
777                    let curie = s.parse::<crate::params::CURIE>().unwrap();
778                    Self::from_accession(curie.accession)
779                })
780                .collect(),
781            Self::ChargeInversionMassSpectrum => { ["MS:1000294"] }
782                .iter()
783                .flat_map(|s: &&str| {
784                    let curie = s.parse::<crate::params::CURIE>().unwrap();
785                    Self::from_accession(curie.accession)
786                })
787                .collect(),
788            Self::ConstantNeutralGainSpectrum => { ["MS:1000294"] }
789                .iter()
790                .flat_map(|s: &&str| {
791                    let curie = s.parse::<crate::params::CURIE>().unwrap();
792                    Self::from_accession(curie.accession)
793                })
794                .collect(),
795            Self::ConstantNeutralLossSpectrum => { ["MS:1000294"] }
796                .iter()
797                .flat_map(|s: &&str| {
798                    let curie = s.parse::<crate::params::CURIE>().unwrap();
799                    Self::from_accession(curie.accession)
800                })
801                .collect(),
802            Self::E2MassSpectrum => { ["MS:1000294"] }
803                .iter()
804                .flat_map(|s: &&str| {
805                    let curie = s.parse::<crate::params::CURIE>().unwrap();
806                    Self::from_accession(curie.accession)
807                })
808                .collect(),
809            Self::PrecursorIonSpectrum => { ["MS:1000294"] }
810                .iter()
811                .flat_map(|s: &&str| {
812                    let curie = s.parse::<crate::params::CURIE>().unwrap();
813                    Self::from_accession(curie.accession)
814                })
815                .collect(),
816            Self::ProductIonSpectrum => { ["MS:1000294"] }
817                .iter()
818                .flat_map(|s: &&str| {
819                    let curie = s.parse::<crate::params::CURIE>().unwrap();
820                    Self::from_accession(curie.accession)
821                })
822                .collect(),
823            Self::MS1Spectrum => { ["MS:1000294"] }
824                .iter()
825                .flat_map(|s: &&str| {
826                    let curie = s.parse::<crate::params::CURIE>().unwrap();
827                    Self::from_accession(curie.accession)
828                })
829                .collect(),
830            Self::MSnSpectrum => { ["MS:1000294"] }
831                .iter()
832                .flat_map(|s: &&str| {
833                    let curie = s.parse::<crate::params::CURIE>().unwrap();
834                    Self::from_accession(curie.accession)
835                })
836                .collect(),
837            Self::CRMSpectrum => { ["MS:1000294"] }
838                .iter()
839                .flat_map(|s: &&str| {
840                    let curie = s.parse::<crate::params::CURIE>().unwrap();
841                    Self::from_accession(curie.accession)
842                })
843                .collect(),
844            Self::SIMSpectrum => { ["MS:1000294"] }
845                .iter()
846                .flat_map(|s: &&str| {
847                    let curie = s.parse::<crate::params::CURIE>().unwrap();
848                    Self::from_accession(curie.accession)
849                })
850                .collect(),
851            Self::SRMSpectrum => { ["MS:1000294"] }
852                .iter()
853                .flat_map(|s: &&str| {
854                    let curie = s.parse::<crate::params::CURIE>().unwrap();
855                    Self::from_accession(curie.accession)
856                })
857                .collect(),
858            Self::PDASpectrum => { ["MS:1000524", "MS:1000559"] }
859                .iter()
860                .flat_map(|s: &&str| {
861                    let curie = s.parse::<crate::params::CURIE>().unwrap();
862                    Self::from_accession(curie.accession)
863                })
864                .collect(),
865            Self::EnhancedMultiplyChargedSpectrum => { ["MS:1000579"] }
866                .iter()
867                .flat_map(|s: &&str| {
868                    let curie = s.parse::<crate::params::CURIE>().unwrap();
869                    Self::from_accession(curie.accession)
870                })
871                .collect(),
872            Self::TimeDelayedFragmentationSpectrum => { ["MS:1000580"] }
873                .iter()
874                .flat_map(|s: &&str| {
875                    let curie = s.parse::<crate::params::CURIE>().unwrap();
876                    Self::from_accession(curie.accession)
877                })
878                .collect(),
879            Self::ElectromagneticRadiationSpectrum => { ["MS:1000524", "MS:1000559"] }
880                .iter()
881                .flat_map(|s: &&str| {
882                    let curie = s.parse::<crate::params::CURIE>().unwrap();
883                    Self::from_accession(curie.accession)
884                })
885                .collect(),
886            Self::EmissionSpectrum => { ["MS:1000524", "MS:1000559"] }
887                .iter()
888                .flat_map(|s: &&str| {
889                    let curie = s.parse::<crate::params::CURIE>().unwrap();
890                    Self::from_accession(curie.accession)
891                })
892                .collect(),
893            Self::AbsorptionSpectrum => { ["MS:1000524", "MS:1000559"] }
894                .iter()
895                .flat_map(|s: &&str| {
896                    let curie = s.parse::<crate::params::CURIE>().unwrap();
897                    Self::from_accession(curie.accession)
898                })
899                .collect(),
900        }
901    }
902}
903impl<P> From<P> for SpectrumType
904where
905    P: crate::params::ParamLike,
906{
907    fn from(value: P) -> Self {
908        Self::from_accession(value.accession().expect(concat!(
909            "Cannot convert an uncontrolled parameter to ",
910            stringify!(SpectrumType)
911        )))
912        .unwrap_or_else(|| {
913            panic!(
914                "Could not map {:?}:{} to {}",
915                value.controlled_vocabulary().unwrap(),
916                value.accession().unwrap(),
917                stringify!(SpectrumType)
918            )
919        })
920    }
921}
922impl From<SpectrumType> for crate::params::ParamCow<'static> {
923    fn from(value: SpectrumType) -> Self {
924        value.to_param()
925    }
926}
927impl From<SpectrumType> for crate::params::Param {
928    fn from(value: SpectrumType) -> Self {
929        value.to_param().into()
930    }
931}
932impl From<&SpectrumType> for crate::params::ParamCow<'static> {
933    fn from(value: &SpectrumType) -> Self {
934        value.to_param()
935    }
936}
937impl From<&SpectrumType> for crate::params::Param {
938    fn from(value: &SpectrumType) -> Self {
939        value.to_param().into()
940    }
941}
942
943macro_rules! t {
944    ($t:expr) => {
945        ($t, $t.to_param())
946    };
947}
948const SPECTRUM_TYPES: &[(crate::SpectrumType, crate::params::ParamCow<'static>)] = &[
949    t!(crate::SpectrumType::MS1Spectrum),
950    t!(crate::SpectrumType::MSnSpectrum),
951    t!(crate::SpectrumType::MassSpectrum),
952    t!(crate::SpectrumType::ChargeInversionMassSpectrum),
953    t!(crate::SpectrumType::ConstantNeutralGainSpectrum),
954    t!(crate::SpectrumType::ConstantNeutralLossSpectrum),
955    t!(crate::SpectrumType::E2MassSpectrum),
956    t!(crate::SpectrumType::PrecursorIonSpectrum),
957    t!(crate::SpectrumType::ProductIonSpectrum),
958    t!(crate::SpectrumType::MS1Spectrum),
959    t!(crate::SpectrumType::MSnSpectrum),
960    t!(crate::SpectrumType::CRMSpectrum),
961    t!(crate::SpectrumType::SIMSpectrum),
962    t!(crate::SpectrumType::SRMSpectrum),
963    t!(crate::SpectrumType::PDASpectrum),
964    t!(crate::SpectrumType::EnhancedMultiplyChargedSpectrum),
965    t!(crate::SpectrumType::TimeDelayedFragmentationSpectrum),
966    t!(crate::SpectrumType::ElectromagneticRadiationSpectrum),
967    t!(crate::SpectrumType::EmissionSpectrum),
968    t!(crate::SpectrumType::AbsorptionSpectrum),
969];
970
971impl SpectrumType {
972    /// Check if this a mass spectrum or some other kind of spectrum
973    pub fn is_mass_spectrum(&self) -> bool {
974        self.parents().contains(&Self::MassSpectrum) || *self == Self::MassSpectrum
975    }
976
977    /// Get the default measurement dimension for this kind of spectrum
978    pub const fn default_main_axis(&self) -> mzdata_bindata::ArrayType {
979        match self {
980            SpectrumType::PDASpectrum => mzdata_bindata::ArrayType::WavelengthArray,
981            SpectrumType::ElectromagneticRadiationSpectrum => mzdata_bindata::ArrayType::WavelengthArray,
982            SpectrumType::EmissionSpectrum => mzdata_bindata::ArrayType::WavelengthArray,
983            SpectrumType::AbsorptionSpectrum => mzdata_bindata::ArrayType::WavelengthArray,
984            _ => mzdata_bindata::ArrayType::MZArray,
985        }
986    }
987
988    /// Get an array of all available types
989    pub const fn all_types() -> &'static [(SpectrumType, crate::params::ParamCow<'static>)] {
990        SPECTRUM_TYPES
991    }
992}