bdb/traits/mgf.rs
1use std::convert::AsRef;
2use std::fs::File;
3use std::io::{BufRead, BufReader, BufWriter, Cursor, Write};
4use std::path::Path;
5
6use util::ResultType;
7
8/// Identifier for the MGF file format type.
9///
10/// MGF files are superficially similar text files, with a start and end
11/// delimiter for each scan (usually "BEGIN IONS" and "END IONS"). The
12/// scan metadata is encoded in a header, and each peak in the scan
13/// is encoded on a separate line.
14#[repr(u8)]
15#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
16pub enum MgfKind {
17 /// MSConvert MGF file format.
18 MsConvert = 1,
19 /// Pava MGF file format.
20 Pava = 2,
21 /// ProteoWizard MGF file format.
22 Pwiz = 3,
23 /// Pava MS1 (FullMs) MGF file format.
24 FullMs = 4,
25}
26
27
28/// Serialize to and from MGF.
29///
30/// MGF, or Mascot General Format, is generic format with a start and
31/// end scan delimiter, along with metadata along 1 or multiple header
32/// lines, followed by individual scans (usually with tab-delimited data).
33/// There are many MGF flavors, however, a sample (MSConvert) format
34/// is shown below.
35///
36/// # Serialized Format
37///
38/// ```text
39/// BEGIN IONS
40/// TITLE=Sample.33450.33450.4 File:"Sample.raw", NativeID:"controllerType=0 controllerNumber=1 scan=33450"
41/// RTINSECONDS=8692.657303
42/// PEPMASS=775.15625 170643.953125
43/// CHARGE=4+
44/// 205.9304178 0.0
45/// 205.9320046 0.0
46/// 205.9335913 0.0
47/// 205.9351781 0.0
48/// END IONS
49/// ```
50pub trait Mgf: Sized {
51 /// Estimate the size of the resulting MGF output to avoid reallocations.
52 #[inline(always)]
53 fn estimate_mgf_size(&self, _: MgfKind) -> usize {
54 0
55 }
56
57 /// Export model to MGF.
58 ///
59 /// Note that many small writers are made to the writer, so the writer
60 /// should be buffered.
61 fn to_mgf<T: Write>(&self, writer: &mut T, kind: MgfKind) -> ResultType<()>;
62
63 /// Export model to MGF string.
64 fn to_mgf_string(&self, kind: MgfKind) -> ResultType<String> {
65 let capacity = self.estimate_mgf_size(kind);
66 let mut writer = Cursor::new(Vec::with_capacity(capacity));
67
68 self.to_mgf(&mut writer, kind)?;
69 match String::from_utf8(writer.into_inner()) {
70 Err(e) => Err(Box::new(e)),
71 Ok(v) => Ok(v),
72 }
73 }
74
75 /// Export model to MGF output file.
76 #[inline]
77 fn to_mgf_file<P: AsRef<Path>>(&self, path: P, kind: MgfKind) -> ResultType<()> {
78 let file = File::create(path)?;
79 let mut writer = BufWriter::new(file);
80 self.to_mgf(&mut writer, kind)
81 }
82
83 /// Import model from MGF.
84 fn from_mgf<T: BufRead>(reader: &mut T, kind: MgfKind) -> ResultType<Self>;
85
86 /// Import model from MGF string.
87 #[inline]
88 fn from_mgf_string(text: &str, kind: MgfKind) -> ResultType<Self> {
89 // Rust uses the contents of the immutable &str as the buffer
90 // Cursor is then immutable.
91 let mut reader = Cursor::new(text);
92 Self::from_mgf(&mut reader, kind)
93 }
94
95 /// Import model from MGF file.
96 #[inline]
97 fn from_mgf_file<P: AsRef<Path>>(path: P, kind: MgfKind) -> ResultType<Self> {
98 let file = File::open(path)?;
99 let mut reader = BufReader::new(file);
100 Self::from_mgf(&mut reader, kind)
101 }
102}
103
104/// Specialization of the `Mgf` trait for collections.
105pub trait MgfCollection: Mgf {
106 /// Export collection to MGF.
107 ///
108 /// Returns an error if any of the items within the collection
109 /// are invalid.
110 ///
111 /// Note that many small writers are made to the writer, so the writer
112 /// should be buffered.
113 fn to_mgf_strict<T: Write>(&self, writer: &mut T, kind: MgfKind) -> ResultType<()>;
114
115 /// Export collection to MGF.
116 ///
117 /// Returns only errors due to serialization issues, otherwise,
118 /// exports as many items as possible.
119 ///
120 /// Note that many small writers are made to the writer, so the writer
121 /// should be buffered.
122 fn to_mgf_lenient<T: Write>(&self, writer: &mut T, kind: MgfKind) -> ResultType<()>;
123
124 /// Import collection from MGF.
125 ///
126 /// Returns an error if any of the items within the MGF document
127 /// are invalid.
128 fn from_mgf_strict<T: BufRead>(reader: &mut T, kind: MgfKind) -> ResultType<Self>;
129
130 /// Import collection from MGF.
131 ///
132 /// Returns only errors due to deserialization errors, otherwise,
133 /// imports as many items as possible.
134 fn from_mgf_lenient<T: BufRead>(reader: &mut T, kind: MgfKind) -> ResultType<Self>;
135}