diff --git a/src/io/mgf.rs b/src/io/mgf.rs index 6a1b98a..7bc83cc 100644 --- a/src/io/mgf.rs +++ b/src/io/mgf.rs @@ -90,6 +90,7 @@ struct SpectrumBuilder< pub intensity_array: Vec, pub charge_array: Vec, pub has_charge: u32, + pub precursor_charge: Option, pub detail_level: DetailLevel, empty_metadata: bool, centroided_type: PhantomData, @@ -114,6 +115,7 @@ impl Default for SpectrumB intensity_array: Default::default(), charge_array: Default::default(), has_charge: Default::default(), + precursor_charge: Default::default(), detail_level: Default::default(), centroided_type: Default::default(), deconvoluted_type: Default::default(), @@ -341,17 +343,8 @@ impl MGFReade .map_err(|e| warn!("Failed to parse PEPMASS intensity {value}: {e}")) .unwrap_or_default(); let charge: Option = match parts.next() { - Some(c) => match c.parse::() { - Ok(val) => Some(val), - Err(e) => { - self.state = MGFParserState::Error; - self.error = Some(MGFError::MalformedHeaderLine(format!( - "Malformed charge value in PEPMASS header {value}: {e}" - ))); - return false; - } - }, - None => None, + Some(c) => self.parse_charge(c), + None => builder.precursor_charge, }; builder.description.precursor = Some(Precursor { ions: vec![SelectedIon { @@ -364,40 +357,16 @@ impl MGFReade }); } "CHARGE" => { - let (sign, value, tail_sign) = if let Some(stripped) = value.strip_suffix('+') { - (1, stripped, true) - } else if let Some(stripped) = value.strip_suffix('-') { - (-1, stripped, true) - } else { - (1, value, false) - }; - - if tail_sign && (value.starts_with('-') || value.starts_with('+')) { - self.state = MGFParserState::Error; - self.error = Some(MGFError::MalformedHeaderLine(format!( - "Could not parse CHARGE header {value}" - ))); - return false; - } - - match value.parse::() { - Ok(z) => { - if let Some(ion) = builder - .description - .precursor - .get_or_insert_with(Precursor::default) - .iter_mut() - .last() - { - ion.charge = Some(sign * z); - } - } - Err(e) => { - self.state = MGFParserState::Error; - self.error = Some(MGFError::MalformedHeaderLine(format!( - "Could not parse CHARGE header {value} : {e}" - ))); - return false; + builder.precursor_charge = self.parse_charge(value); + if let Some(ion) = builder + .description + .precursor + .get_or_insert_with(Precursor::default) + .iter_mut() + .last() + { + if ion.charge.is_none() { + ion.charge = builder.precursor_charge } } } @@ -418,6 +387,35 @@ impl MGFReade } } + fn parse_charge(&mut self, value: &str) -> Option { + let (sign, value, tail_sign) = if let Some(stripped) = value.strip_suffix('+') { + (1, stripped, true) + } else if let Some(stripped) = value.strip_suffix('-') { + (-1, stripped, true) + } else { + (1, value, false) + }; + + if tail_sign && (value.starts_with('-') || value.starts_with('+')) { + self.state = MGFParserState::Error; + self.error = Some(MGFError::MalformedHeaderLine(format!( + "Could not parse charge value {value}" + ))); + return None; + } + + match value.parse::() { + Ok(z) => Some(sign * z), + Err(e) => { + self.state = MGFParserState::Error; + self.error = Some(MGFError::MalformedHeaderLine(format!( + "Could not parse charge value {value} : {e}" + ))); + return None; + } + } + } + fn handle_peak(&mut self, line: &str, builder: &mut SpectrumBuilder) -> bool { let peak_line = self.parse_peak_from_line(line, builder).unwrap_or(false); if peak_line { @@ -1197,7 +1195,7 @@ mod test { } } assert_eq!(ms1_count, 0); - assert_eq!(msn_count, 34); + assert_eq!(msn_count, 35); } #[test] @@ -1224,7 +1222,7 @@ mod test { }) } assert_eq!(ms1_count, 0); - assert_eq!(msn_count, 34); + assert_eq!(msn_count, 35); } #[test] diff --git a/src/io/shorthand.rs b/src/io/shorthand.rs index 090a66c..9b34038 100644 --- a/src/io/shorthand.rs +++ b/src/io/shorthand.rs @@ -310,7 +310,7 @@ mod test { assert_eq!(val.len(), 48); let val: Vec<_> = mz_read!("./test/data/small.mgf".as_ref(), reader => { reader.collect() })?; - assert_eq!(val.len(), 34); + assert_eq!(val.len(), 35); let val = mz_read!("./test/data/small.mzML".as_ref(), reader => { reader.file_description().clone() })?; assert_eq!(val.source_files.len(), 1); Ok(()) diff --git a/test/data/small.mgf b/test/data/small.mgf index 018de26..7ee903d 100644 --- a/test/data/small.mgf +++ b/test/data/small.mgf @@ -25514,3 +25514,16 @@ PEPMASS=882.535034179688 29807.576171875 1743.361206 3.1923613548 END IONS +BEGIN IONS +TITLE=charge before pepmass +CHARGE=2+ +PEPMASS=475.137295 +ION_MOBILITY=42.42 +RTINSECONDS=51.2 +72.04439 100 +148.06043 600 +232.07504 300 +263.08737 400 +347.10198 500 +423.11802 200 +END IONS