diff --git a/.github/workflows/python-builds.yml b/.github/workflows/python-builds.yml index 296ea28..7c60cb9 100644 --- a/.github/workflows/python-builds.yml +++ b/.github/workflows/python-builds.yml @@ -11,48 +11,76 @@ jobs: linux: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Checkout current repository + uses: actions/checkout@v3 + + - name: Clone remote repository + run: | + git clone https://github.com/david-bouyssie/mzcore.git ../mzcore + ls /home/runner/work/mzio/mzcore + - uses: PyO3/maturin-action@v1 with: - manylinux: auto + manylinux: off # auto command: build - args: --release --sdist -o dist --find-interpreter + args: -o dist --strip --find-interpreter working-directory: mzio-py + - name: Upload wheels to artifact uses: actions/upload-artifact@v3 with: name: wheels - path: dist + path: mzio-py/dist + + - name: Setup tmate session + if: ${{ failure() }} + uses: mxschmitt/action-tmate@v3 windows: runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - name: Checkout current repository + uses: actions/checkout@v3 + + - name: Clone remote repository + run: | + git clone https://github.com/david-bouyssie/mzcore.git ../mzcore + ls ../mzcore + - uses: PyO3/maturin-action@v1 with: command: build - args: --release -o dist --find-interpreter + args: -o dist --strip --find-interpreter working-directory: mzio-py - - name: Upload wheels + + - name: Upload wheels to artifact uses: actions/upload-artifact@v3 with: name: wheels - path: dist + path: mzio-py/dist macos: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - name: Checkout current repository + uses: actions/checkout@v3 + + - name: Clone remote repository + run: | + git clone https://github.com/david-bouyssie/mzcore.git ../mzcore + ls ../mzcore + - uses: PyO3/maturin-action@v1 with: command: build - args: --release -o dist --universal2 --find-interpreter + args: -o dist --strip --find-interpreter --target universal2-apple-darwin working-directory: mzio-py - - name: Upload wheels + + - name: Upload wheels to artifact uses: actions/upload-artifact@v3 with: name: wheels - path: dist + path: mzio-py/dist # release: # name: Release diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e6479ef --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] + +members = [ + "mzio-rs", + "mzio-py" +] diff --git a/mzio-py/Cargo.toml b/mzio-py/Cargo.toml index 3fa289c..6bbf82e 100755 --- a/mzio-py/Cargo.toml +++ b/mzio-py/Cargo.toml @@ -10,7 +10,7 @@ name = "mzio_py" crate-type = ["cdylib"] [dependencies] -anyhow = "1.0.68" +anyhow = "1.0.75" fallible-iterator = "0.2.0" -mzio = { path = "../mzio-rs" } -pyo3 = { version = "0.17.3", features = ["extension-module", "anyhow"] } +pyo3 = { version = "0.20.0", features = ["extension-module", "anyhow"] } +mzio = { path = "../mzio-rs", features = ["fasta", "mgf"] } diff --git a/mzio-py/pyproject.toml b/mzio-py/pyproject.toml index 07c3332..98238c3 100755 --- a/mzio-py/pyproject.toml +++ b/mzio-py/pyproject.toml @@ -35,5 +35,5 @@ doc = [ ] [build-system] -requires = ["maturin>=0.14,<0.15"] +requires = ["maturin>=1.0.0,<1.3.0"] build-backend = "maturin" diff --git a/mzio-py/src/fasta/entry.rs b/mzio-py/src/fasta/entry.rs index 01031fc..7e75637 100644 --- a/mzio-py/src/fasta/entry.rs +++ b/mzio-py/src/fasta/entry.rs @@ -2,8 +2,9 @@ use std::collections::HashMap; // 3rd party imports +use anyhow::Result; use pyo3::prelude::*; -use mzio::fasta::entry::Entry as BaseEntry; +use mzio::fasta::entry::FastaEntry as BaseEntry; /// Wrapper for the rust implementation entry /// @@ -35,7 +36,8 @@ impl Entry { entry_name, protein_name, keyword_attributes, - sequence + sequence, + None ) } } @@ -43,29 +45,29 @@ impl Entry { /// Returns the database type /// #[getter] - pub fn database(&self) -> PyResult<&str> { - Ok(&self.base_entry.get_database()) + pub fn database(&self) -> Result<&String> { + Ok(self.base_entry.get_database()) } /// Returns the accession /// #[getter] - pub fn accession(&self) -> PyResult<&str> { - Ok(&self.base_entry.get_accession()) + pub fn accession(&self) -> Result<&String> { + Ok(self.base_entry.get_accession()) } /// Entry name /// #[getter] - pub fn entry_name(&self) -> PyResult<&str> { - Ok(&self.base_entry.get_entry_name()) + pub fn entry_name(&self) -> Result<&String> { + Ok(self.base_entry.get_entry_name()) } /// Returns the protein name /// #[getter] - pub fn protein_name(&self) -> PyResult<&str> { - Ok(&self.base_entry.get_protein_name()) + pub fn protein_name(&self) -> Result<&String> { + Ok(self.base_entry.get_protein_name()) } /// Returns additional keyword attributes, e.g @@ -74,7 +76,7 @@ impl Entry { /// // !!! TODO Reference to HasMap is no convertible to PyResult by default. #[getter] - pub fn keyword_attributes(&self) -> PyResult> { + pub fn keyword_attributes(&self) -> Result> { // TODO: avoid clone? Ok(self.base_entry.get_keyword_attributes().clone()) } @@ -82,8 +84,15 @@ impl Entry { /// Returns the amino acid sequence /// #[getter] - pub fn sequence(&self) -> PyResult<&str> { - Ok(&self.base_entry.get_sequence()) + pub fn sequence(&self) -> Result<&String> { + Ok(self.base_entry.get_sequence()) + } + + /// Returns the plain header (before parsing) + /// + #[getter] + pub fn plain_header(&self) -> Result<&String> { + Ok(self.base_entry.get_sequence()) } } diff --git a/mzio-py/src/fasta/reader.rs b/mzio-py/src/fasta/reader.rs index 6dad5be..a057786 100644 --- a/mzio-py/src/fasta/reader.rs +++ b/mzio-py/src/fasta/reader.rs @@ -1,10 +1,10 @@ // std imports use std::path::PathBuf; -// 3rd party modules -use pyo3::prelude::*; +// 3rd party imports use anyhow::Result; -use mzio::fasta::reader::Reader as BaseReader; +use pyo3::prelude::*; +use mzio::fasta::reader::FastaReader as BaseReader; // internal imports use crate::fasta::entry::Entry; @@ -17,8 +17,9 @@ pub struct Reader { #[pymethods] impl Reader { #[new] - fn new(fasta_file_path: PathBuf, buffer_size: usize) -> Result { - match BaseReader::new(&fasta_file_path, buffer_size) { + fn new(fasta_file_path: PathBuf, buffer_size: usize, keep_plain_header: bool) -> Result { + match BaseReader::new(&fasta_file_path, buffer_size, keep_plain_header + ) { Ok(base_reader) => Ok(Self{base_reader}), Err(err) => Err(err) } diff --git a/mzio-py/src/fasta/writer.rs b/mzio-py/src/fasta/writer.rs index 92cd91c..02183cf 100644 --- a/mzio-py/src/fasta/writer.rs +++ b/mzio-py/src/fasta/writer.rs @@ -1,15 +1,14 @@ // std imports use std::path::PathBuf; -// 3rd party modules +// 3rd party imports use anyhow::Result; use pyo3::prelude::*; -use mzio::fasta::writer::Writer as BaseWriter; +use mzio::fasta::writer::FastaWriter as BaseWriter; // internal imports use crate::fasta::entry::Entry; - #[pyclass] pub struct Writer { base_writer: BaseWriter @@ -24,15 +23,15 @@ impl Writer { /// * `fasta_file_path` - Path to FASTA file /// #[new] - pub fn new(fasta_file_path: PathBuf) -> PyResult { - match BaseWriter::new(&fasta_file_path) { + pub fn new(fasta_file_path: PathBuf, sort_keyword_attributes: bool) -> PyResult { + match BaseWriter::new_with_default_seq_formatting(&fasta_file_path, sort_keyword_attributes) { Ok(base_writer) => Ok(Self{base_writer}), Err(err) => Err(err.into()) } } - pub fn write_entry(&mut self, entry: &Entry, sort_keyword_attributes: bool) -> Result { - match self.base_writer.write_entry(entry.into(), sort_keyword_attributes) { + pub fn write_entry(&mut self, entry: &Entry) -> Result { + match self.base_writer.write_entry(entry.into()) { Ok(written_bytes) => Ok(written_bytes), Err(err) => Err(err) } diff --git a/mzio-py/src/lib.rs b/mzio-py/src/lib.rs index ae30b19..02dfcfe 100755 --- a/mzio-py/src/lib.rs +++ b/mzio-py/src/lib.rs @@ -34,9 +34,9 @@ fn register_fasta_module(py: Python, parent_module: &PyModule) -> PyResult<()> { /// `parent_module` - Parent module of the mgf module fn register_mgf_module(py: Python, parent_module: &PyModule) -> PyResult<()> { let child_module = PyModule::new(py, "mgf")?; - child_module.add_class::()?; - child_module.add_class::()?; - child_module.add_class::()?; + child_module.add_class::()?; + child_module.add_class::()?; + child_module.add_class::()?; parent_module.add_submodule(child_module)?; Ok(()) } diff --git a/mzio-py/src/mgf/reader.rs b/mzio-py/src/mgf/reader.rs index 1d12e08..d5be93b 100644 --- a/mzio-py/src/mgf/reader.rs +++ b/mzio-py/src/mgf/reader.rs @@ -1,39 +1,40 @@ // std imports use std::path::PathBuf; -// 3rd party modules +// 3rd party imports use pyo3::prelude::*; use anyhow::Result; -use mzio::mgf::reader::Reader as BaseReader; - use fallible_iterator::FallibleIterator; +use mzio::mgf::reader::MgfReader as BaseMgfReader; // internal imports -use crate::mgf::spectrum::Spectrum; +use crate::mgf::spectrum::MgfSpectrum; #[pyclass] -pub struct Reader { - base_reader: BaseReader +pub struct MgfReader { + base_reader: BaseMgfReader } #[pymethods] -impl Reader { +impl MgfReader { #[new] - #[args(buffer_size=4096)] + #[pyo3(signature = (mgf_file_path, buffer_size=4096))] fn new(mgf_file_path: PathBuf, buffer_size: usize) -> Result { - match BaseReader::new(&mgf_file_path, buffer_size) { + let base_reader = BaseMgfReader::new(&mgf_file_path, buffer_size)?; + Ok(Self{base_reader}) + /*match BaseReader::new(&mgf_file_path, buffer_size) { Ok(base_reader) => Ok(Self{base_reader}), Err(err) => Err(err) - } + }*/ } fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } - fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { + fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { match slf.base_reader.next().ok()? { - Some(base_spectrum) => Some(Spectrum::from(base_spectrum)), + Some(base_spectrum) => Some(MgfSpectrum::from(base_spectrum)), None => None } } diff --git a/mzio-py/src/mgf/spectrum.rs b/mzio-py/src/mgf/spectrum.rs index 129c383..82deb6a 100644 --- a/mzio-py/src/mgf/spectrum.rs +++ b/mzio-py/src/mgf/spectrum.rs @@ -1,17 +1,17 @@ // 3rd party imports use pyo3::prelude::*; -use mzio::mgf::spectrum::Spectrum as BaseSpectrum; - +use mzio::mgf::spectrum::MgfSpectrum as BaseMgfSpectrum; /// Wrapper for the rust implementation spectrum /// #[pyclass] -pub struct Spectrum { - base_spectrum: BaseSpectrum +#[derive(Clone, Debug)] +pub struct MgfSpectrum { + base_spectrum: BaseMgfSpectrum } #[pymethods] -impl Spectrum { +impl MgfSpectrum { /// Python constructor /// /// # Arguments @@ -24,10 +24,16 @@ impl Spectrum { /// * `intensity_list` - Intensity list /// #[new] - fn new(title: String, precursor_mz: f64, precursor_charge: Option, - retention_time: Option, mz_list: Vec, intensity_list: Vec) -> Self { + fn new( + mz_list: Vec, + intensity_list: Vec, + title: String, + precursor_mz: f64, + precursor_charge: Option, + retention_time: Option + ) -> Self { Self { - base_spectrum: BaseSpectrum::new( + base_spectrum: BaseMgfSpectrum::new( title, precursor_mz, precursor_charge, @@ -41,62 +47,62 @@ impl Spectrum { /// Returns the spectrum title /// #[getter] - pub fn title(&self) -> PyResult<&str> { - Ok(&self.base_spectrum.get_title()) + pub fn title(&self) -> String { + self.base_spectrum.header.get_title().to_owned() } /// Returns the precursor mz /// #[getter] - pub fn precursor_mz(&self) -> PyResult { - Ok(self.base_spectrum.get_precursor_mz()) + pub fn precursor_mz(&self) -> f64 { + self.base_spectrum.header.get_precursor_mz() } /// Returns the precursor charge /// #[getter] - pub fn precursor_charge(&self) -> PyResult> { - Ok(*self.base_spectrum.get_precursor_charge()) + pub fn precursor_charge(&self) -> Option { + self.base_spectrum.header.get_precursor_charge() } /// Returns the retention time /// #[getter] - pub fn retention_time(&self) -> PyResult> { - Ok(*self.base_spectrum.get_retention_time()) + pub fn retention_time(&self) -> Option { + self.base_spectrum.header.get_retention_time() } /// Returns the mzs /// #[getter] - pub fn mzs(&self) -> PyResult> { - Ok(self.base_spectrum.get_mz_list().to_vec()) + pub fn mzs(&self) -> Vec { + self.base_spectrum.get_mz_list().to_owned() } /// Returns the intensities /// #[getter] - pub fn intensities(&self) -> PyResult> { - Ok(self.base_spectrum.get_intensity_list().to_vec()) + pub fn intensities(&self) -> Vec { + self.base_spectrum.get_intensity_list().to_owned() } } -impl From for Spectrum { +impl From for MgfSpectrum { /// Convert entry from the Rust implementation to the python wrapper. /// /// # Arguments /// /// * `base_spectrum` - Spectrum from rust implementation - fn from(base_spectrum: BaseSpectrum) -> Self { + fn from(base_spectrum: BaseMgfSpectrum) -> Self { Self { base_spectrum } } } -impl<'a> Into<&'a BaseSpectrum> for &'a Spectrum { - fn into(self) -> &'a BaseSpectrum { +impl<'a> Into<&'a BaseMgfSpectrum> for &'a MgfSpectrum { + fn into(self) -> &'a BaseMgfSpectrum { &self.base_spectrum } } diff --git a/mzio-py/src/mgf/writer.rs b/mzio-py/src/mgf/writer.rs index a1f1244..681f799 100644 --- a/mzio-py/src/mgf/writer.rs +++ b/mzio-py/src/mgf/writer.rs @@ -1,22 +1,21 @@ // std imports use std::path::PathBuf; -// 3rd party modules +// 3rd party imports use anyhow::Result; use pyo3::prelude::*; -use mzio::mgf::writer::Writer as BaseWriter; +use crate::mgf::spectrum::MgfSpectrum; // internal imports -use crate::mgf::spectrum::Spectrum; - +use mzio::mgf::writer::MgfWriter as BaseMgfWriter; #[pyclass] -pub struct Writer { - base_writer: BaseWriter +pub struct MgfWriter { + base_writer: BaseMgfWriter } #[pymethods] -impl Writer { +impl MgfWriter { /// Creates a new Writer /// /// # Arguments @@ -24,25 +23,25 @@ impl Writer { /// * `mgf_file_path` - Path to MGF file /// #[new] - pub fn new(mgf_file_path: PathBuf) -> PyResult { - match BaseWriter::new(&mgf_file_path) { - Ok(base_writer) => Ok(Self{base_writer}), - Err(err) => Err(err.into()) - } + pub fn new(mgf_file_path: PathBuf) -> Result { + let base_writer = BaseMgfWriter::new(&mgf_file_path)?; + Ok(Self {base_writer}) } - pub fn write_spectrum(&mut self, spectrum: &Spectrum) -> Result { - match self.base_writer.write_spectrum(spectrum.into()) { + pub fn write_spectrum(&mut self, spectrum: &MgfSpectrum) -> Result { + self.base_writer.write_spectrum(spectrum.into()) + /*match self.base_writer.write_spectrum(spectrum.into()) { Ok(written_bytes) => Ok(written_bytes), Err(err) => Err(err) - } + }*/ } pub fn flush(&mut self) -> Result<()> { - match self.base_writer.flush() { + self.base_writer.flush() + /*match self.base_writer.flush() { Ok(_) => Ok(()), Err(err) => Err(err) - } + }*/ } } diff --git a/mzio-rs/Cargo.toml b/mzio-rs/Cargo.toml index 65a96f9..ebe8f9d 100755 --- a/mzio-rs/Cargo.toml +++ b/mzio-rs/Cargo.toml @@ -10,11 +10,17 @@ keywords = ["bioinformatics", "mass spectrometry", "proteomics", "eubic-ms"] categories = ["science"] publish = false -# [lib] -# name = "mzio" +[lib] +name = "mzio" # crate-type = ["cdylib"] [dependencies] -anyhow = "1.0.68" +anyhow = "1.0.75" fallible-iterator = "0.2.0" -fast-float = "0.2.0" +fast-float = { version = "0.2.0" , optional = true } +serde = "*" +mzcore = { path = "../../mzcore/mzcore-rs" } + +[features] +fasta = [] +mgf = ["dep:fast-float"] \ No newline at end of file diff --git a/mzio-rs/src/fasta/entry.rs b/mzio-rs/src/fasta/entry.rs index de4230f..24354f1 100755 --- a/mzio-rs/src/fasta/entry.rs +++ b/mzio-rs/src/fasta/entry.rs @@ -1,16 +1,17 @@ use std::collections::HashMap; /// Keeps all information of FASTA entry -pub struct Entry { +pub struct FastaEntry { database: String, accession: String, entry_name: String, protein_name: String, keyword_attributes: HashMap, - sequence: String + sequence: String, + plain_header: Option } -impl Entry { +impl FastaEntry { /// Creates a new FASTA entry /// # Arguments /// @@ -22,38 +23,39 @@ impl Entry { /// * `sequence` - Amino acid sequence /// pub fn new(database: String, accession: String, entry_name: String, protein_name: String, - keyword_attributes: HashMap, sequence: String) -> Self { + keyword_attributes: HashMap, sequence: String, plain_header: Option) -> Self { Self { database, accession, entry_name, protein_name, keyword_attributes, - sequence + sequence, + plain_header, } } /// Returns the database type /// - pub fn get_database(&self) -> &str { - &self.database.as_str() + pub fn get_database(&self) -> &String { + &self.database } /// Returns the accession /// - pub fn get_accession(&self) -> &str { + pub fn get_accession(&self) -> &String { &self.accession } /// Entry name /// - pub fn get_entry_name(&self) -> &str { + pub fn get_entry_name(&self) -> &String { &self.entry_name } /// Returns the protein name /// - pub fn get_protein_name(&self) -> &str { + pub fn get_protein_name(&self) -> &String { &self.protein_name } @@ -67,7 +69,13 @@ impl Entry { /// Returns the amino acid sequence /// - pub fn get_sequence(&self) -> &str { + pub fn get_sequence(&self) -> &String { &self.sequence } + + /// Returns the plain header (before parsing) + /// + pub fn get_plain_header(&self) -> &Option { + &self.plain_header + } } \ No newline at end of file diff --git a/mzio-rs/src/fasta/mod.rs b/mzio-rs/src/fasta/mod.rs index 561dbd7..6dd730f 100755 --- a/mzio-rs/src/fasta/mod.rs +++ b/mzio-rs/src/fasta/mod.rs @@ -1,6 +1,9 @@ pub mod entry; pub mod reader; pub mod writer; +pub mod prelude; + +pub use prelude::*; #[cfg(test)] mod test { @@ -9,9 +12,9 @@ mod test { use std::fs; use std::path::Path; - const FASTA_FILE_PATH_STR: &'static str = "./test_files/fasta/partial_mouse.fasta"; + const FASTA_FILE_PATH_STR: &'static str = "../test_files/fasta/partial_mouse.fasta"; const EXPECTED_NUM_PROTEINS: usize = 10; - const TEMP_FASTA_PATH_STR: &'static str = "./test_files/fasta/partial_mouse.fasta.tmp"; + const TEMP_FASTA_PATH_STR: &'static str = "../test_files/fasta/partial_mouse.fasta.tmp"; #[test] /// Reads a FASTA file, parses the proteins, @@ -20,26 +23,43 @@ mod test { let fasta_file_path = Path::new(FASTA_FILE_PATH_STR); let tmp_fasta_file_path = Path::new(TEMP_FASTA_PATH_STR); - let reader = reader::Reader::new( + assert!(fasta_file_path.exists(), "FASTA file not found at path: {}", FASTA_FILE_PATH_STR); + + let reader = FastaReader::new( fasta_file_path, - 1024 + 1024, + true ).unwrap(); - let entries: Vec = reader.into_iter().collect(); + let mut entries = Vec::with_capacity(1000); + + for entry in reader { + + let entry_as_string = FastaWriter::stringify_entry(&entry, true, None); + + assert_eq!( + [entry.get_plain_header().to_owned().unwrap(), entry.get_sequence().to_owned()].join("\n"), + entry_as_string, + "the formatted entries are not matching" + ); + + entries.push(entry); + } assert_eq!(entries.len(), EXPECTED_NUM_PROTEINS); - let mut writer = writer::Writer::new( - tmp_fasta_file_path + let mut writer = FastaWriter::new_with_default_seq_formatting( + tmp_fasta_file_path, + true ).unwrap(); - writer.write_all(entries.iter(), true).unwrap(); + writer.write_all(entries.iter()).unwrap(); writer.flush().unwrap(); let tmp_fasta_content = fs::read_to_string(tmp_fasta_file_path).unwrap().trim().to_string(); fs::remove_file(tmp_fasta_file_path).unwrap(); assert_eq!( - fs::read_to_string(fasta_file_path).unwrap().trim(), + fs::read_to_string(fasta_file_path).unwrap().trim().replace("\r\n", "\n"), tmp_fasta_content.as_str() ); } diff --git a/mzio-rs/src/fasta/prelude.rs b/mzio-rs/src/fasta/prelude.rs new file mode 100644 index 0000000..21f39e0 --- /dev/null +++ b/mzio-rs/src/fasta/prelude.rs @@ -0,0 +1,3 @@ +pub use crate::fasta::entry::FastaEntry; +pub use crate::fasta::reader::FastaReader; +pub use crate::fasta::writer::FastaWriter; \ No newline at end of file diff --git a/mzio-rs/src/fasta/reader.rs b/mzio-rs/src/fasta/reader.rs index 5ddc133..8bc32c6 100755 --- a/mzio-rs/src/fasta/reader.rs +++ b/mzio-rs/src/fasta/reader.rs @@ -1,30 +1,38 @@ +// std imports use std::collections::HashMap; use std::fs::File; use std::io::BufReader; use std::io::prelude::*; use std::path::Path; -use crate::fasta::entry::Entry; +// 3rd party imports use anyhow::Result; +// internal imports +use crate::fasta::entry::FastaEntry; + /// Reader for common FASTA files as distributed by UniProt (https://uniprot.org) -pub struct Reader { +pub struct FastaReader { internal_reader: BufReader, + keep_plain_header: bool, is_eof: bool, header: String, sequence: String } -impl Reader { +impl FastaReader { /// Creates a new Reader /// # Arguments /// /// * `fasta_file_path` - Path to FASTA file + /// * `buffer_size` - Buffer size to use when loading bytes from disk. + /// * `keep_plain_header` - Whether to keep or not the plain read header in the generated FastaEntry. /// - pub fn new(fasta_file_path: &Path, buffer_size: usize) -> Result { + pub fn new(fasta_file_path: &Path, buffer_size: usize, keep_plain_header: bool) -> Result { let fasta_file: File = File::open(fasta_file_path)?; Ok(Self { internal_reader: BufReader::with_capacity(buffer_size, fasta_file), + keep_plain_header, is_eof: false, header: String::new(), sequence: String::new() @@ -49,14 +57,15 @@ impl Reader { } } - /// Creates a new Entry from the given header and sequence. + /// Creates a new FastaEntry from the given header and sequence. /// /// # Arguments /// /// * `header` - A FASTA header /// * `sequence` - Amino acid sequence + /// * `keep_plain_header` - Whether to keep or not the plain read header in the generated FastaEntry. /// - pub fn create_entry(header: &str, sequence: &str) -> Option { + pub fn create_entry(header: &str, sequence: &str, keep_plain_header: bool) -> Option { // Split by '|' and extract database and accession let mut header_split = header.split("|").collect::>(); let mut database: String = header_split.remove(0).to_string(); @@ -93,7 +102,7 @@ impl Reader { current_attr.push_str(" "); current_attr.push_str(header_split.remove(0)); } else { - Reader::prep_and_add_attribute_to_keyword_attributes( + FastaReader::prep_and_add_attribute_to_keyword_attributes( ¤t_attr, &mut keyword_attributes ); @@ -104,25 +113,28 @@ impl Reader { } } // Process the remaining attribute - Reader::prep_and_add_attribute_to_keyword_attributes( + FastaReader::prep_and_add_attribute_to_keyword_attributes( ¤t_attr, &mut keyword_attributes ); } - return Some(Entry::new( + let plain_header_opt = if keep_plain_header {Some(header.to_string())} else {None}; + + return Some(FastaEntry::new( database, // database accession, // accession entry_name, protein_name, keyword_attributes, - sequence.replace("\n", "") + sequence.replace("\n", ""), + plain_header_opt )); } } -impl Iterator for Reader { - type Item = Entry; +impl Iterator for FastaReader { + type Item = FastaEntry; fn next(&mut self) -> Option { if self.is_eof { @@ -134,15 +146,15 @@ impl Iterator for Reader { if let Ok(num_bytes) = self.internal_reader.read_line(&mut line) { if num_bytes == 0 { self.is_eof = true; - return Reader::create_entry(&self.header, &self.sequence); + return FastaReader::create_entry(&self.header, &self.sequence, self.keep_plain_header); } line = line.as_mut_str().trim().to_string(); if !line.starts_with(">") && num_bytes > 0 { self.sequence.push_str(&line) } else { if self.header.len() > 0 { - let entry = Reader::create_entry(&self.header, &self.sequence); - self.header = line; // safe newly read header + let entry = FastaReader::create_entry(&self.header, &self.sequence, self.keep_plain_header); + self.header = line; // save newly read header return entry; } else { self.header = line; @@ -154,7 +166,6 @@ impl Iterator for Reader { } } - #[cfg(test)] mod test { use super::*; @@ -188,7 +199,7 @@ QRSGIVALDGERELAFGPDDEVTVTLHDHAFRSIDVAACMRHAGRHHLMRSLPQPAAVG"; /// Tests the creation of a FASTA entry from a header and a sequence. /// fn test_entry_creation() { - let entry = Reader::create_entry(TEST_HEADER, TEST_SEQUENCE).unwrap(); + let entry = FastaReader::create_entry(TEST_HEADER, TEST_SEQUENCE, false).unwrap(); assert_eq!(entry.get_database(), EXPECTED_DATABASE); assert_eq!(entry.get_accession(), EXPECTED_ACCESSION); assert_eq!(entry.get_entry_name(), EXPECTED_ENTRY_NAME); diff --git a/mzio-rs/src/fasta/writer.rs b/mzio-rs/src/fasta/writer.rs index 02bb567..1a2f501 100755 --- a/mzio-rs/src/fasta/writer.rs +++ b/mzio-rs/src/fasta/writer.rs @@ -1,30 +1,76 @@ +// std imports use std::fs::File; use std::io::BufWriter; use std::io::prelude::*; use std::path::Path; -use crate::fasta::entry::Entry; +// 3rd party imports use anyhow::Result; -/// Max amino acids per sequence line. -const MAX_AMINO_ACIDS_PER_LINE: usize = 60; +// internal imports +use crate::fasta::entry::FastaEntry; + +/// DEFAULT max amino acids per sequence line. +const DEFAULT_MAX_AMINO_ACIDS_PER_LINE: usize = 60; /// Writer for common FASTA files as distributed by UniProt (https://uniprot.org) /// Use flush() to mak ensure the buffer is written completely. -pub struct Writer { +pub struct FastaWriter { + /// Max amino acids per sequence line. + max_amino_acids_per_line: Option, + sort_keyword_attributes: bool, internal_writer: BufWriter } -impl Writer { +impl FastaWriter { /// Creates a new Writer /// /// # Arguments /// /// * `fasta_file_path` - Path to FASTA file + /// * `sort_keyword_attributes` - If true the keyword attributes will be sorted (for testing and readability reasons) + /// * `max_amino_acids_per_line` - If Some(), will format the sequence line to not exceed the given length. /// - pub fn new(fasta_file_path: &Path) -> Result { + pub fn new(fasta_file_path: &Path, sort_keyword_attributes: bool, max_amino_acids_per_line: Option) -> Result { let fasta_file: File = File::create(fasta_file_path)?; + Ok(Self { + max_amino_acids_per_line, + sort_keyword_attributes, + internal_writer: BufWriter::new(fasta_file), + }) + } + + /// Creates a new Writer + /// + /// # Arguments + /// + /// * `fasta_file_path` - Path to FASTA file + /// * `sort_keyword_attributes` - If true the keyword attributes will be sorted (for testing and readability reasons) + /// + pub fn new_with_default_seq_formatting(fasta_file_path: &Path, sort_keyword_attributes: bool) -> Result { + let fasta_file: File = File::create(fasta_file_path)?; + + Ok(Self { + max_amino_acids_per_line: Some(DEFAULT_MAX_AMINO_ACIDS_PER_LINE), + sort_keyword_attributes, + internal_writer: BufWriter::new(fasta_file) + }) + } + + /// Creates a new Writer + /// + /// # Arguments + /// + /// * `fasta_file_path` - Path to FASTA file + /// * `sort_keyword_attributes` - If true the keyword attributes will be sorted (for testing and readability reasons) + /// + pub fn new_without_seq_formatting(fasta_file_path: &Path, sort_keyword_attributes: bool) -> Result { + let fasta_file: File = File::create(fasta_file_path)?; + + Ok(Self { + max_amino_acids_per_line: None, + sort_keyword_attributes, internal_writer: BufWriter::new(fasta_file) }) } @@ -36,7 +82,7 @@ impl Writer { /// * `entry` - FASTA entry /// * `sort_keyword_attributes` - If true the keyword attributes will be sorted (for testing and readability reasons) /// - fn create_header(entry: &Entry, sort_keyword_attributes: bool) -> String { + fn create_header(entry: &FastaEntry, sort_keyword_attributes: bool) -> String { let mut header = ">".to_string(); header.push_str(entry.get_database()); header.push_str("|"); @@ -63,29 +109,50 @@ impl Writer { /// # Arguments /// /// * `sequence` - Amino acid sequence + /// * `max_amino_acids_per_line` - Maximum length of each line containing sequence amino acids. /// - fn format_sequence(sequence: &str) -> String { + fn format_sequence(sequence: &str, max_amino_acids_per_line: usize) -> String { return sequence.chars() .collect::>() - .chunks(MAX_AMINO_ACIDS_PER_LINE) + .chunks(max_amino_acids_per_line) .map(|c| c.iter().collect::()) .collect::>() .join("\n"); } /// Writes entry into the FASTA file. - /// + /// /// # Arguments /// /// * `entry` - FASTA entry /// * `sort_keyword_attributes` - If true the keyword attributes will be sorted (for testing and readability reasons) + /// * `max_amino_acids_per_line` - If Some(), will format the sequence line to not exceed the given length. + /// + pub fn stringify_entry(entry: &FastaEntry, sort_keyword_attributes: bool, max_amino_acids_per_line: Option) -> String { + + let header_as_string = Self::create_header(entry, sort_keyword_attributes); + + let seq_as_string = if max_amino_acids_per_line.is_some() { + Self::format_sequence(entry.get_sequence(), max_amino_acids_per_line.unwrap()) + } else { + entry.get_sequence().to_string() + }; + + [header_as_string, seq_as_string].join("\n") + } + + /// Writes entry into the FASTA file. /// - pub fn write_entry(&mut self, entry: &Entry, sort_keyword_attributes: bool) -> Result { - let mut written_bytes: usize = 0; - written_bytes += self.internal_writer.write(Self::create_header(entry, sort_keyword_attributes).as_bytes())?; - written_bytes += self.internal_writer.write(b"\n")?; - written_bytes += self.internal_writer.write(Self::format_sequence(entry.get_sequence()).as_bytes())?; - written_bytes += self.internal_writer.write(b"\n")?; + /// # Arguments + /// + /// * `entry` - FASTA entry + /// + pub fn write_entry(&mut self, entry: &FastaEntry) -> Result { + let mut entry_as_string = Self::stringify_entry(entry, self.sort_keyword_attributes, self.max_amino_acids_per_line); + entry_as_string.push_str("\n"); + + let written_bytes = self.internal_writer.write(entry_as_string.as_bytes())?; + return Ok(written_bytes); } @@ -93,16 +160,15 @@ impl Writer { /// /// # Arguments /// - /// * `entires` - Iterator of FASTA entries - /// * `sort_keyword_attributes` - If true the keyword attributes will be sorted (for testing and readability reasons) - /// - pub fn write_all<'b, I>(&mut self, entries: I, sort_keyword_attributes: bool) -> Result + /// * `entried` - Iterator of FASTA entries + /// + pub fn write_all<'b, I>(&mut self, entries: I) -> Result where - I: Iterator, + I: Iterator, { let mut written_bytes: usize = 0; for entry in entries { - written_bytes += self.write_entry(entry, sort_keyword_attributes)?; + written_bytes += self.write_entry(entry)?; } return Ok(written_bytes); } @@ -149,23 +215,24 @@ QRSGIVALDGERELAFGPDDEVTVTLHDHAFRSIDVAACMRHAGRHHLMRSLPQPAAVG"; #[test] /// Tests the creation of a FASTA entry from a header and a sequence. /// - fn test_seqeunce_formatting() { - let formatted_sequence = Writer::format_sequence(TEST_SEQUENCE); + fn test_sequence_formatting() { + let formatted_sequence = FastaWriter::format_sequence(TEST_SEQUENCE, DEFAULT_MAX_AMINO_ACIDS_PER_LINE); assert_eq!(formatted_sequence, EXPECTED_SEQUENCE) } #[test] /// Reads a FASTA file, parses the proteins and counts protein fn test_header_creation() { - let entry = Entry::new( + let entry = FastaEntry::new( TEST_DATABASE.to_string(), TEST_ACCESSION.to_string(), TEST_ENTRY_NAME.to_string(), TEST_PROTEIN_NAME.to_string(), TEST_KEYWORD_ATTRIBUTES.into_iter().map(|elem| (elem.0.to_string(), elem.1.to_string())).collect::>(), - TEST_SEQUENCE.to_string() + TEST_SEQUENCE.to_string(), + None ); - let header = Writer::create_header(&entry, true); + let header = FastaWriter::create_header(&entry, true); assert_eq!(header, EXPECTED_HEADER); } } diff --git a/mzio-rs/src/lib.rs b/mzio-rs/src/lib.rs index df1277f..ed81f4c 100755 --- a/mzio-rs/src/lib.rs +++ b/mzio-rs/src/lib.rs @@ -1,2 +1,4 @@ +#[cfg(feature = "fasta")] pub mod fasta; +#[cfg(feature = "mgf")] pub mod mgf; diff --git a/mzio-rs/src/mgf/mod.rs b/mzio-rs/src/mgf/mod.rs index 6f32af8..9ff4088 100644 --- a/mzio-rs/src/mgf/mod.rs +++ b/mzio-rs/src/mgf/mod.rs @@ -3,7 +3,9 @@ pub mod reader; pub mod spectrum; pub mod writer; +pub mod prelude; +pub use prelude::*; #[cfg(test)] mod test { @@ -13,8 +15,8 @@ mod test { use std::iter::zip; use std::path::Path; - use fallible_iterator::IntoFallibleIterator; - use fallible_iterator::FallibleIterator; + //use fallible_iterator::IntoFallibleIterator; + //use fallible_iterator::FallibleIterator; const MGF_FILE_PATH_STR: &'static str = "../test_files/mgf/Velos005137.mgf"; const EXPECTED_NUM_SPECTRA: usize = 100; @@ -27,20 +29,20 @@ mod test { let mgf_file_path = Path::new(MGF_FILE_PATH_STR); let tmp_mgf_file_path = Path::new(TEMP_MGF_PATH_STR); - let reader = reader::Reader::new( + let mgf_reader = MgfReader::new( mgf_file_path, 1024 ).unwrap(); - let entries: Vec = reader.into_fallible_iter().collect().unwrap(); + let entries: Vec = mgf_reader.into_fallible_iter().collect().unwrap(); assert_eq!(entries.len(), EXPECTED_NUM_SPECTRA); - let mut writer = writer::Writer::new( + let mut mgf_writer = MgfWriter::new( tmp_mgf_file_path ).unwrap(); - writer.write_all(entries.iter()).unwrap(); - writer.flush().unwrap(); + mgf_writer.write_all(entries.iter()).unwrap(); + mgf_writer.flush().unwrap(); let tmp_mgf_content = fs::read_to_string(tmp_mgf_file_path).unwrap().trim().to_string(); fs::remove_file(tmp_mgf_file_path).unwrap(); diff --git a/mzio-rs/src/mgf/prelude.rs b/mzio-rs/src/mgf/prelude.rs new file mode 100644 index 0000000..67f51b5 --- /dev/null +++ b/mzio-rs/src/mgf/prelude.rs @@ -0,0 +1,5 @@ +pub use fallible_iterator::IntoFallibleIterator; +pub use fallible_iterator::FallibleIterator; +pub use crate::mgf::spectrum::MgfSpectrum; +pub use crate::mgf::reader::MgfReader; +pub use crate::mgf::writer::MgfWriter; \ No newline at end of file diff --git a/mzio-rs/src/mgf/reader.rs b/mzio-rs/src/mgf/reader.rs index 9260ee6..1bdd2ee 100644 --- a/mzio-rs/src/mgf/reader.rs +++ b/mzio-rs/src/mgf/reader.rs @@ -10,14 +10,14 @@ use anyhow::{Result, bail}; use fallible_iterator::FallibleIterator; // internal imports -use crate::mgf::spectrum::Spectrum; +use crate::mgf::spectrum::MgfSpectrum; /// Reader for MGF -pub struct Reader { +pub struct MgfReader { internal_reader: BufReader } -impl Reader { +impl MgfReader { /// Creates a new Reader /// /// # Arguments @@ -32,8 +32,8 @@ impl Reader { } } -impl FallibleIterator for Reader { - type Item = Spectrum; +impl FallibleIterator for MgfReader { + type Item = MgfSpectrum; type Error = anyhow::Error; fn next(&mut self) -> Result> { @@ -55,36 +55,21 @@ impl FallibleIterator for Reader { } return Ok(None); } + line = line.as_mut_str().trim().to_string(); if line.is_empty() { continue } - if line.chars().nth(0).unwrap().is_numeric() { - let mut split = line.split_ascii_whitespace(); - - match split.next() { - Some(mz) => mz_list.push(fast_float::parse(mz)?), - None => bail!("mz value is missing") - }; - - match split.next() { - Some(intens) => intensity_list.push(fast_float::parse(intens)?), - None => bail!("intensity value is missing") - }; - - } else if line.starts_with("TITLE=") { - title = line[6..].to_owned(); - } else if line.starts_with("PEPMASS=") { - precursor_mz = fast_float::parse(&line[8..])?; - } else if line.starts_with("RTINSECONDS=") { - retention_time = Some(fast_float::parse(&line[12..])?); - } else if line.starts_with("CHARGE=") { - precursor_charge = Some(line[7..].parse()?); - } else if line == "BEGIN IONS" { + let first_char = line.chars().next().unwrap(); + + if first_char == 'B' && line.starts_with("BEGIN IONS") { in_spectrum = true; - } else if line == "END IONS" { - return Ok(Some(Spectrum::new( + } else if first_char == 'E' && line.starts_with("END IONS") { + + //in_spectrum = false; + + return Ok(Some(MgfSpectrum::new( title, precursor_mz, precursor_charge, @@ -92,8 +77,50 @@ impl FallibleIterator for Reader { mz_list, intensity_list ))); - } - } - } + } else if in_spectrum { + // if line contains a peak + if first_char.is_numeric() { + let mut split = line.split_ascii_whitespace(); + + match split.next() { + Some(mz) => mz_list.push(fast_float::parse(mz)?), + None => bail!("m/z value is missing") + }; + + match split.next() { + Some(intens) => intensity_list.push(fast_float::parse(intens)?), + None => bail!("intensity value is missing") + }; + + } else { + if line.starts_with("TITLE=") { + title = line[6..].to_owned(); + } else if line.starts_with("PEPMASS=") { + let prec_mz_str_opt = &line[8..].split_ascii_whitespace().next(); + precursor_mz = fast_float::parse(prec_mz_str_opt.unwrap_or_else(|| "0.0"))?; + } else if line.starts_with("RTINSECONDS=") { + retention_time = Some(fast_float::parse(&line[12..])?); + } else if line.starts_with("CHARGE=") { + // Locate the value and its sign within the string + let value = &line[7..]; + let mut chars = value.chars(); + let charge_sign_idx = chars.position(|c| !c.is_numeric()).unwrap_or(value.len()); + + // Parse the charge value + let charge_str = &value[0..charge_sign_idx]; + let mut charge = charge_str.parse()?; + + // Parse the charge sign and update the value accordingly + let sign = chars.nth(charge_sign_idx).unwrap_or('+'); + if sign == '-' { + charge *= -1; + } + + precursor_charge = Some(charge); + } + } + } // ends else if in_spectrum + } // ends read_line + } // ends loop } -} +} \ No newline at end of file diff --git a/mzio-rs/src/mgf/spectrum.rs b/mzio-rs/src/mgf/spectrum.rs index 8a0af7b..00893bd 100644 --- a/mzio-rs/src/mgf/spectrum.rs +++ b/mzio-rs/src/mgf/spectrum.rs @@ -1,14 +1,22 @@ + +// 3rd party imports +use serde::{Serialize, Deserialize}; + +// internal imports +use mzcore::ms::spectrum::SpectrumData; +use mzcore::ms::utils::mz_to_mass; + /// Spectrum representation for MGF files. -pub struct Spectrum { - title: String, - precursor_mz: f64, - precursor_charge: Option, - retention_time: Option, - mz_list: Vec, - intensity_list: Vec +#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +pub struct MgfSpectrumHeader { + pub title: String, + pub precursor_mz: f64, + pub precursor_charge: Option, + pub precursor_mass: Option, // Not in the header (for post-processing convenience) + pub retention_time: Option, } -impl Spectrum { +impl MgfSpectrumHeader { /// Creates a new spectrum /// /// # Arguments @@ -20,21 +28,24 @@ impl Spectrum { /// * `mz_list` - M/Z list /// * `intensity_list` - Intensity list /// - pub fn new(title: String, precursor_mz: f64, precursor_charge: Option, - retention_time: Option, mz_list: Vec, intensity_list: Vec) -> Self { + pub fn new( + title: String, + precursor_mz: f64, + precursor_charge: Option, + retention_time: Option + ) -> Self { Self { title, precursor_mz, precursor_charge, + precursor_mass: None, retention_time, - mz_list, - intensity_list, } } /// Returns the spectrum title /// - pub fn get_title(&self) -> &str { + pub fn get_title(&self) -> &String { &self.title } @@ -46,26 +57,90 @@ impl Spectrum { /// Returns precursor charge /// - pub fn get_precursor_charge(&self) -> &Option { - &self.precursor_charge + pub fn get_precursor_charge(&self) -> Option { + self.precursor_charge + } + + /// Returns precursor mass + /// + pub fn get_precursor_mass(&self) -> Option { + self.precursor_mass + } + + /// Sets precursor mass + /// + pub fn set_precursor_mass(&mut self, precursor_mass: f64) -> &MgfSpectrumHeader { + self.precursor_mass = Some(precursor_mass); + self + } + + /// Calculates and sets precursor mass + /// + pub fn calc_precursor_mass(&mut self) -> &MgfSpectrumHeader { + self.precursor_mass = self.precursor_charge.map(|z| mz_to_mass(self.precursor_mz, z as i32)); + self } /// Returns retention time /// - pub fn get_retention_time(&self) -> &Option { - &self.retention_time + pub fn get_retention_time(&self) -> Option { + self.retention_time + } + +} + +#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +pub struct MgfSpectrum { + pub header: MgfSpectrumHeader, + pub data: SpectrumData, +} + +impl MgfSpectrum { + /// Creates a new spectrum + /// + /// # Arguments + /// + /// * `title` - Specturm title + /// * `precursor_mz` - Precursor mass + /// * `precursor_charge` - Precursor charge + /// * `retention_time` - Retention time + /// * `mz_list` - M/Z list + /// * `intensity_list` - Intensity list + /// + pub fn new( + title: String, + precursor_mz: f64, + precursor_charge: Option, + retention_time: Option, + mz_list: Vec, + intensity_list: Vec + ) -> Self { + + let mgf_header = MgfSpectrumHeader::new(title, precursor_mz, precursor_charge, retention_time); + + let data = SpectrumData { + mz_list, + intensity_list, + }; + + Self { + header: mgf_header, + data: data, + } } /// Returns M/Z list - /// + /// pub fn get_mz_list(&self) -> &Vec { - &self.mz_list + &self.data.mz_list } /// Returns intensity list - /// + /// pub fn get_intensity_list(&self) -> &Vec { - &self.intensity_list + &self.data.intensity_list } -} \ No newline at end of file +} + + diff --git a/mzio-rs/src/mgf/writer.rs b/mzio-rs/src/mgf/writer.rs index 19540bf..02292ec 100644 --- a/mzio-rs/src/mgf/writer.rs +++ b/mzio-rs/src/mgf/writer.rs @@ -8,15 +8,15 @@ use std::path::Path; use anyhow::Result; // internal imports -use crate::mgf::spectrum::Spectrum; +use crate::mgf::spectrum::MgfSpectrum; /// Writer for MGF files /// Use flush() to make ensure the buffer is written completely. -pub struct Writer { +pub struct MgfWriter { internal_writer: BufWriter } -impl Writer { +impl MgfWriter { /// Creates a new Writer /// /// # Arguments @@ -36,22 +36,38 @@ impl Writer { /// /// * `spectrum` - Spectrum /// - pub fn write_spectrum(&mut self, spectrum: &Spectrum,) -> Result { + pub fn write_spectrum(&mut self, spectrum: &MgfSpectrum) -> Result { + let spec_header = &spectrum.header; + let mut written_bytes: usize = 0; - written_bytes += self.internal_writer.write("BEGIN IONS\n".as_bytes())?; - written_bytes += self.internal_writer.write(format!("TITLE={}\n", spectrum.get_title()).as_bytes())?; - written_bytes += self.internal_writer.write(format!("PEPMASS={}", spectrum.get_precursor_mz()).as_bytes())?; - if let Some(retention_time) = spectrum.get_retention_time() { - written_bytes += self.internal_writer.write(format!("\nRTINSECONDS={}", retention_time).as_bytes())?; + + written_bytes += self._write_str("BEGIN IONS\n")?; + written_bytes += self._write_string(format!("TITLE={}\n", spec_header.get_title()))?; + written_bytes += self._write_string(format!("PEPMASS={}", spec_header.get_precursor_mz()))?; + + if let Some(retention_time) = spec_header.get_retention_time() { + written_bytes += self._write_string(format!("\nRTINSECONDS={}", retention_time))?; } - if let Some(charge) = spectrum.get_precursor_charge() { - written_bytes += self.internal_writer.write(format!("\nCHARGE={}", charge).as_bytes())?; + if let Some(charge) = spec_header.get_precursor_charge() { + let charge_sign = if charge < 0 { '-'} else { '+' }; + written_bytes += self._write_string(format!("\nCHARGE={}{}", charge, charge_sign))?; } for (mz, intensity) in zip(spectrum.get_mz_list(), spectrum.get_intensity_list()) { - written_bytes += self.internal_writer.write(format!("\n{mz} {intensity}").as_bytes())?; + written_bytes += self._write_string(format!("\n{mz} {intensity}"))?; } - written_bytes += self.internal_writer.write("\nEND IONS\n".as_bytes())?; - return Ok(written_bytes); + written_bytes += self._write_str("\nEND IONS\n")?; + + Ok(written_bytes) + } + + #[inline(always)] + fn _write_str(&mut self, str: &str) -> Result { + Ok(self.internal_writer.write(str.as_bytes())?) + } + + #[inline(always)] + fn _write_string(&mut self, string: String) -> Result { + Ok(self.internal_writer.write(string.as_bytes())?) } /// Writes multiple spectra to file. @@ -62,7 +78,7 @@ impl Writer { /// pub fn write_all<'b, I>(&mut self, spectra: I) -> Result where - I: Iterator, + I: Iterator, { let mut written_bytes: usize = 0; for spectrum in spectra { diff --git a/mzio-rs/test_files/fasta/partial_mouse.fasta b/mzio-rs/test_files/fasta/partial_mouse.fasta deleted file mode 100644 index 462f2f6..0000000 --- a/mzio-rs/test_files/fasta/partial_mouse.fasta +++ /dev/null @@ -1,134 +0,0 @@ ->sp|A0A024B7W1|POLG_ZIKVF Genome polyprotein OS=Zika virus (isolate ZIKV/Human/French Polynesia/10087PF/2013) OX=2043570 PE=1 SV=1 -MKNPKKKSGGFRIVNMLKRGVARVSPFGGLKRLPAGLLLGHGPIRMVLAILAFLRFTAIK -PSLGLINRWGSVGKKEAMEIIKKFKKDLAAMLRIINARKEKKRRGADTSVGIVGLLLTTA -MAAEVTRRGSAYYMYLDRNDAGEAISFPTTLGMNKCYIQIMDLGHMCDATMSYECPMLDE -GVEPDDVDCWCNTTSTWVVYGTCHHKKGEARRSRRAVTLPSHSTRKLQTRSQTWLESREY -TKHLIRVENWIFRNPGFALAAAAIAWLLGSSTSQKVIYLVMILLIAPAYSIRCIGVSNRD -FVEGMSGGTWVDVVLEHGGCVTVMAQDKPTVDIELVTTTVSNMAEVRSYCYEASISDMAS -DSRCPTQGEAYLDKQSDTQYVCKRTLVDRGWGNGCGLFGKGSLVTCAKFACSKKMTGKSI -QPENLEYRIMLSVHGSQHSGMIVNDTGHETDENRAKVEITPNSPRAEATLGGFGSLGLDC -EPRTGLDFSDLYYLTMNNKHWLVHKEWFHDIPLPWHAGADTGTPHWNNKEALVEFKDAHA -KRQTVVVLGSQEGAVHTALAGALEAEMDGAKGRLSSGHLKCRLKMDKLRLKGVSYSLCTA -AFTFTKIPAETLHGTVTVEVQYAGTDGPCKVPAQMAVDMQTLTPVGRLITANPVITESTE -NSKMMLELDPPFGDSYIVIGVGEKKITHHWHRSGSTIGKAFEATVRGAKRMAVLGDTAWD -FGSVGGALNSLGKGIHQIFGAAFKSLFGGMSWFSQILIGTLLMWLGLNTKNGSISLMCLA -LGGVLIFLSTAVSADVGCSVDFSKKETRCGTGVFVYNDVEAWRDRYKYHPDSPRRLAAAV -KQAWEDGICGISSVSRMENIMWRSVEGELNAILEENGVQLTVVVGSVKNPMWRGPQRLPV -PVNELPHGWKAWGKSYFVRAAKTNNSFVVDGDTLKECPLKHRAWNSFLVEDHGFGVFHTS -VWLKVREDYSLECDPAVIGTAVKGKEAVHSDLGYWIESEKNDTWRLKRAHLIEMKTCEWP -KSHTLWTDGIEESDLIIPKSLAGPLSHHNTREGYRTQMKGPWHSEELEIRFEECPGTKVH -VEETCGTRGPSLRSTTASGRVIEEWCCRECTMPPLSFRAKDGCWYGMEIRPRKEPESNLV -RSMVTAGSTDHMDHFSLGVLVILLMVQEGLKKRMTTKIIISTSMAVLVAMILGGFSMSDL -AKLAILMGATFAEMNTGGDVAHLALIAAFKVRPALLVSFIFRANWTPRESMLLALASCLL -QTAISALEGDLMVLINGFALAWLAIRAMVVPRTDNITLAILAALTPLARGTLLVAWRAGL -ATCGGFMLLSLKGKGSVKKNLPFVMALGLTAVRLVDPINVVGLLLLTRSGKRSWPPSEVL -TAVGLICALAGGFAKADIEMAGPMAAVGLLIVSYVVSGKSVDMYIERAGDITWEKDAEVT -GNSPRLDVALDESGDFSLVEDDGPPMREIILKVVLMTICGMNPIAIPFAAGAWYVYVKTG -KRSGALWDVPAPKEVKKGETTDGVYRVMTRRLLGSTQVGVGVMQEGVFHTMWHVTKGSAL -RSGEGRLDPYWGDVKQDLVSYCGPWKLDAAWDGHSEVQLLAVPPGERARNIQTLPGIFKT -KDGDIGAVALDYPAGTSGSPILDKCGRVIGLYGNGVVIKNGSYVSAITQGRREEETPVEC -FEPSMLKKKQLTVLDLHPGAGKTRRVLPEIVREAIKTRLRTVILAPTRVVAAEMEEALRG -LPVRYMTTAVNVTHSGTEIVDLMCHATFTSRLLQPIRVPNYNLYIMDEAHFTDPSSIAAR -GYISTRVEMGEAAAIFMTATPPGTRDAFPDSNSPIMDTEVEVPERAWSSGFDWVTDHSGK -TVWFVPSVRNGNEIAACLTKAGKRVIQLSRKTFETEFQKTKHQEWDFVVTTDISEMGANF -KADRVIDSRRCLKPVILDGERVILAGPMPVTHASAAQRRGRIGRNPNKPGDEYLYGGGCA -ETDEDHAHWLEARMLLDNIYLQDGLIASLYRPEADKVAAIEGEFKLRTEQRKTFVELMKR -GDLPVWLAYQVASAGITYTDRRWCFDGTTNNTIMEDSVPAEVWTRHGEKRVLKPRWMDAR -VCSDHAALKSFKEFAAGKRGAAFGVMEALGTLPGHMTERFQEAIDNLAVLMRAETGSRPY -KAAAAQLPETLETIMLLGLLGTVSLGIFFVLMRNKGIGKMGFGMVTLGASAWLMWLSEIE -PARIACVLIVVFLLLVVLIPEPEKQRSPQDNQMAIIIMVAVGLLGLITANELGWLERTKS -DLSHLMGRREEGATIGFSMDIDLRPASAWAIYAALTTFITPAVQHAVTTSYNNYSLMAMA -TQAGVLFGMGKGMPFYAWDFGVPLLMIGCYSQLTPLTLIVAIILLVAHYMYLIPGLQAAA -ARAAQKRTAAGIMKNPVVDGIVVTDIDTMTIDPQVEKKMGQVLLIAVAVSSAILSRTAWG -WGEAGALITAATSTLWEGSPNKYWNSSTATSLCNIFRGSYLAGASLIYTVTRNAGLVKRR -GGGTGETLGEKWKARLNQMSALEFYSYKKSGITEVCREEARRALKDGVATGGHAVSRGSA -KLRWLVERGYLQPYGKVIDLGCGRGGWSYYAATIRKVQEVKGYTKGGPGHEEPMLVQSYG -WNIVRLKSGVDVFHMAAEPCDTLLCDIGESSSSPEVEEARTLRVLSMVGDWLEKRPGAFC -IKVLCPYTSTMMETLERLQRRYGGGLVRVPLSRNSTHEMYWVSGAKSNTIKSVSTTSQLL -LGRMDGPRRPVKYEEDVNLGSGTRAVVSCAEAPNMKIIGNRIERIRSEHAETWFFDENHP -YRTWAYHGSYEAPTQGSASSLINGVVRLLSKPWDVVTGVTGIAMTDTTPYGQQRVFKEKV -DTRVPDPQEGTRQVMSMVSSWLWKELGKHKRPRVCTKEEFINKVRSNAALGAIFEEEKEW -KTAVEAVNDPRFWALVDKEREHHLRGECQSCVYNMMGKREKKQGEFGKAKGSRAIWYMWL -GARFLEFEALGFLNEDHWMGRENSGGGVEGLGLQRLGYVLEEMSRIPGGRMYADDTAGWD -TRISRFDLENEALITNQMEKGHRALALAIIKYTYQNKVVKVLRPAEKGKTVMDIISRQDQ -RGSGQVVTYALNTFTNLVVQLIRNMEAEEVLEMQDLWLLRRSEKVTNWLQSNGWDRLKRM -AVSGDDCVVKPIDDRFAHALRFLNDMGKVRKDTQEWKPSTGWDNWEEVPFCSHHFNKLHL -KDGRSIVVPCRHQDELIGRARVSPGAGWSIRETACLAKSYAQMWQLLYFHRRDLRLMANA -ICSSVPVDWVPTGRTTWSIHGKGEWMTTEDMLVVWNRVWIEENDHMEDKTPVTKWTDIPY -LGKREDLWCGSLIGHRPRTTWAENIKNTVNMVRRIIGDEEKYMDYLSTQVRYLGEEGSTP -GVL ->sp|A0A087WPF7|AUTS2_MOUSE Autism susceptibility gene 2 protein homolog GN=Auts2 OS=Mus musculus OX=10090 PE=1 SV=2 -MDGPTRGHGLRKKRRSRSQRDRERRSRAGLGTGAAGGIGAGRTRAPSLASSSGSDKEDNG -KPPSSAPSRPRPPRRKRRESTSAEEDIIDGFAMTSFVTFEALEKDVAVKPQERAEKRQTP -LTKKKREALTNGLSFHSKKSRLSHSHHYSSDRENDRNLCQHLGKRKKMPKGLRQLKPGQN -SCRDSDSESASGESKGFQRSSSRERLSDSSAPSSLGTGYFCDSDSDQEEKASDASSEKLF -NTVLVNKDPELGVGALPEHNQDAGPIVPKISGLERSQEKSQDCCKEPVFEPVVLKDPHPQ -LPQLPSQAQAEPQLQIPSPGPDLVPRTEAPPQFPPPSTQPAQGPPEAQLQPAPLPQVQQR -PPRPQSPSHLLQQTLPPVQSHPSSQSLSQPLSAYNSSSLSLNSLSSRSSTPAKTQPAPPH -ISHHPSASPFPLSLPNHSPLHSFTPTLQPPAHSHHPNMFAPPTALPPPPPLTSGSLQVPG -HPAGSTYSEQDILRQELNTRFLASQSADRGASLGPPPYLRTEFHQHQHQHQHTHQHTHQH -TFTPFPHAIPPTAIMPTPAPPMFDKYPTKVDPFYRHSLFHSYPPAVSGIPPMIPPTGPFG -SLQGAFQPKTSNPIDVAARPGTVPHTLLQKDPRLTDPFRPMLRKPGKWCAMHVHIAWQIY -HHQQKVKKQMQSDPHKLDFGLKPEFLSRPPGPSLFGAIHHPHDLARPSTLFSAAGAAHPT -GTPFGPPPHHSNFLNPAAHLEPFNRPSTFTGLAAVGGNAFGGLGNPSVTPNSVFGHKDSP -SVQNFSNPHEPWNRLHRTPPSFPTPPPWLKPGELERSASAAAHDRDRDVDKRDSSVSKDD -KERESVEKRHPSHPSPAPPVPVSALGHNRSSTDPTTRGHLNTEAREKDKPKEKERDHSGS -RKDLTTEEHKAKESHLPERDGHSHEGRAAGEEPKQLSRVPSPYVRTPGVDSTRPNSTSSR -EAEPRKGEPAYENPKKNAEVKVKEERKEDHDLPTEAPQAHRTSEAPPPSSSASASVHPGP -LASMPMTVGVTGIHAMNSIGSLDRTRMVTPFMGLSPIPGGERFPYPSFHWDPMRDPLRDP -YRDLDMHRRDPLGRDFLLRNDPLHRLSTPRLYEADRSFRDREPHDYSHHHHHHHHPLAVD -PRREHERGGHLDERERLHVLREDYEHPRLHPVHPASLDGHLPHPSLLTPGLPSMHYPRIS -PTAGHQNGLLNKTPPTAALSAPPPLISTLGGRPGSPRRTTPLSAEIRERPPSHTLKDIEA -R ->sp|A0A088MLT8|IQIP1_MOUSE IQCJ-SCHIP1 readthrough transcript protein GN=Iqcj-Schip1 OS=Mus musculus OX=10090 PE=1 SV=2 -MRLEELKRLQNPLEQVDDGKYLLENHQLAMDVENNIENYPLSLQPLESKVKIIQRAWREY -LQRQDPLEKRSPSPPSVSSDKLSSSVSMNTFSDSSTPDYREDGMDLGSDAGSSSSSRASS -QSNSTKVTPCSECKSSSSPGGSLDLVSALEDYEEPFPVYQKKVIDEWAPEEDGEEEEEED -DRGYRDDGCPAREPGDVSARIGSSGSGSRSAATTMPSPMPNGNLHPHDPQDLRHNGNVVV -AGRPNASRVPRRPIQKTQPPGSRRGGRNRASGGLCLQPPDGGTRVPEEPPAPPMDWEALE -KHLAGLQFREQEVRNQGQARTNSTSAQKNERESIRQKLALGSFFDDGPGIYTSCSKSGKP -SLSARLQSGMNLQICFVNDSGSDKDSDADDSKTETSLDTPLSPMSKQSSSYSDRDTTEEE -SESLDDMDFLTRQKKLQAEAKMALAMAKPMAKMQVEVEKQNRKKSPVADLLPHMPHISEC -LMKRSLKPTDLRDMTIGQLQVIVNDLHSQIESLNEELVQLLLIRDELHTEQDAMLVDIED -LTRHAESQQKHMAEKMPAK ->sp|A0A0A7EPL0|PIAL1_ARATH E4 SUMO-protein ligase PIAL1 GN=PIAL1 OS=Arabidopsis thaliana OX=3702 PE=2 SV=1 -MVIPATSRFGFRAEFNTKEFQASCISLANEIDAAIGRNEVPGNIQELALILNNVCRRKCD -DYQTRAVVMALMISVKSACQLGWFPERETQELLAIIDLMWNGFSCPENVTSCVNSPVTLI -SQVIERFYPCVKLGHILVSFEAKPESKMMMKDFHISKKMPHSPKQKVGLFVVRTEDISRS -NCIVHPQGVSFLLNGKGIDKRVNISMESGPQLPTNVTALLNLGANLLQAIGCFGGSYLIA -IAFMDVIPLPNKPLLKDYVHPEVVGSNSDCDIIEGPSRISLSCPISRTRIKLPVKGHVCK -HLQCFDFWNYVNMNTRRPSWRCPHCNQSVCYTDIRVDQKLRKILEEVGRNAADVVISADG -TWMVETENDEDVELVPETTHDHGDPNSFINLGPTVKNPARDENEMETSTQVEEHNPCLSE -IQGPSNDTHRPASDYTMLNQSHTSTNTLPQLPRTLNAFDGQQFVNLPQVINTRDSPASQA -LPMTFSPTPSPQDILATNAANFGTSMPAAQSSQFQGSHVTSLGNCEGRTSDLMARWNHIY -GRVQTQFPPAPLSHHHYSMQNQSPSPAQQRPVPSYIAHPQTFHVNYGENADQRWMPSSIA -HPQTLPVNYGGNTNQRPIPSSIAHPQTLPVNYRGNTDHRSTPYSITHLQTLLNYGGNADQ -RPMPSSITNLQTLPATYGGYAHQRPMSSSITHPRTSPVNYGGTPDQRPMPSSITHPQTLP -VSYGGTTDQILNPGGAMGQFSSREFMNLTPANTENWRPQSRMRGSVAPGTGYDHMIIHPT -RPVHPQAQTPPAPLSTSYDGADEIQAFIGHPSYPVSNNETQAGTSSLPVAEGLGYSGSFW -SMPPETW ->sp|A0A0B4J1F4|ARRD4_MOUSE Arrestin domain-containing protein 4 GN=Arrdc4 OS=Mus musculus OX=10090 PE=1 SV=1 -MGGEAGADGPRGRVKSLGLVFEDESKGCYSSGETVAGHVLLEAAEPVALRGLRLEAQGRA -TSAWGPSAGARVCIGGGSPAASSEVEYLNLRLSLLEAPAGEGVTLLQPGKHEFPFRFQLP -SEPLATSFTGKYGSIQYCVRAVLERPQVPDQSVRRELQVVSHVDVNTPPLLTPMLKTQEK -MVGCWLFTSGPVSLSVKIERKGYCNGEAIPIYAEIENCSSRLVVPKAAIFQTQTYLASGK -TKTVRHMVANVRGNHIGSGSTDTWNGKMLKIPPVTPSILDCCIIRVDYSLAVYIHIPGAK -RLMLELPLVIGTIPYSGFGRRNSSVASQFSMDMCWLALALPEQPEAPPNYADVVSEEEFS -RHVPPYPQPSDCDGEACYSMFACIQEFRFQPPPLYSEVDPHPGDAQETQPVSFIL ->sp|A0A0B4J1G0|FCG3A_MOUSE Low affinity immunoglobulin gamma Fc region receptor III-A GN=Fcgr4 OS=Mus musculus OX=10090 PE=1 SV=1 -MWQLLLPTALVLTAFSGIQAGLQKAVVNLDPKWVRVLEEDSVTLRCQGTFSPEDNSIKWF -HNESLIPHQDANYVIQSARVKDSGMYRCQTALSTISDPVQLEVHMGWLLLQTTKWLFQEG -DPIHLRCHSWQNRPVRKVTYLQNGKGKKYFHENSELLIPKATHNDSGSYFCRGLIGHNNK -SSASFRISLGDPGSPSMFPPWHQITFCLLIGLLFAIDTVLYFSVRRGLQSPVADYEEPKI -QWSKEPQDK ->sp|A0A0B4J1N3|GP15L_MOUSE Protein GPR15LG GN=Gpr15lg OS=Mus musculus OX=10090 PE=2 SV=1 -MRLLALSGLLCMLLLCFCIFSSEGRRHPAKSLKLRRCCHLSPRSKLTTWKGNHTRPCRLC -RNKLPVKSWVVPGALPQI ->sp|A0A0B5A8P4|INS3A_CONGE Con-Ins G3 OS=Conus geographus OX=6491 PE=1 SV=1 -MTTSFYFLLVALGLLLYVCQSSFGNQHTRNSDTPKHRCGSELADQYVQLCHGKRNDAGKK -RGRASPLWQRQGFLSMLKAKRNEAFFLQRDGRGIVEVCCDNPCTVATLRTFCH ->sp|A0A0B5AC95|INS1A_CONGE Con-Ins G1a OS=Conus geographus OX=6491 PE=1 SV=1 -MTTSSYFLLMALGLLLYVCQSSFGNQHTRTFDTPKHRCGSEITNSYMDLCYRKRNDAGEK -RGRASPLWQRRGSLSKLKARAKRNGAFHLPRDGRGVVEHCCHRPCSNAEFKKYCG ->sp|A0A0C5B5G6|MOTSC_HUMAN Mitochondrial-derived peptide MOTS-c GN=MT-RNR1 OS=Homo sapiens OX=9606 PE=1 SV=1 -MRWQEMGYIFYPRKLR diff --git a/test_files/mgf/Velos005137.mgf b/test_files/mgf/Velos005137.mgf index f5b32d0..5406688 100644 --- a/test_files/mgf/Velos005137.mgf +++ b/test_files/mgf/Velos005137.mgf @@ -2,7 +2,7 @@ BEGIN IONS TITLE=824.836730957031_212.9232 PEPMASS=824.836730957031 RTINSECONDS=212.9232 -CHARGE=2 +CHARGE=2+ 118.936477661133 429.616 122.26781463623 354.588 138.923324584961 369.316 @@ -24,7 +24,7 @@ BEGIN IONS TITLE=567.810852050781_249.8916 PEPMASS=567.810852050781 RTINSECONDS=249.8916 -CHARGE=2 +CHARGE=2+ 115.411254882813 417.992 130.114776611328 334.547 137.004974365234 429.248 @@ -64,7 +64,7 @@ BEGIN IONS TITLE=521.822143554688_251.90179999998 PEPMASS=521.822143554688 RTINSECONDS=251.90179999998 -CHARGE=2 +CHARGE=2+ 113.44278717041 411.301 115.086448669434 8573.47 126.104721069336 349.371 @@ -213,7 +213,7 @@ BEGIN IONS TITLE=508.785949707031_252.8919 PEPMASS=508.785949707031 RTINSECONDS=252.8919 -CHARGE=2 +CHARGE=2+ 110.071319580078 4138.69 129.102127075195 3604.41 133.118576049805 386.48 @@ -272,7 +272,7 @@ BEGIN IONS TITLE=348.217102050781_253.2939 PEPMASS=348.217102050781 RTINSECONDS=253.2939 -CHARGE=3 +CHARGE=3+ 110.77604675293 383.386 115.08650970459 14251.9 116.089424133301 421.22 @@ -417,7 +417,7 @@ BEGIN IONS TITLE=533.798645019531_253.63249999998 PEPMASS=533.798645019531 RTINSECONDS=253.63249999998 -CHARGE=2 +CHARGE=2+ 107.466751098633 325.009 107.471633911133 368.402 108.353782653809 364.756 @@ -489,7 +489,7 @@ BEGIN IONS TITLE=590.796142578125_253.974 PEPMASS=590.796142578125 RTINSECONDS=253.974 -CHARGE=2 +CHARGE=2+ 106.689796447754 380.768 111.360305786133 342.855 119.679458618164 405.727 @@ -522,7 +522,7 @@ BEGIN IONS TITLE=548.782836914063_254.3199 PEPMASS=548.782836914063 RTINSECONDS=254.3199 -CHARGE=2 +CHARGE=2+ 123.30598449707 386.705 123.505279541016 363.283 129.10221862793 1867.57 @@ -575,7 +575,7 @@ BEGIN IONS TITLE=532.81298828125_255.19759999998 PEPMASS=532.81298828125 RTINSECONDS=255.19759999998 -CHARGE=2 +CHARGE=2+ 115.086166381836 1040.7 119.871856689453 334.196 125.393074035645 419.248 @@ -637,7 +637,7 @@ BEGIN IONS TITLE=378.875793457031_255.6063 PEPMASS=378.875793457031 RTINSECONDS=255.6063 -CHARGE=3 +CHARGE=3+ 110.070991516113 1584.76 118.271049499512 352.013 128.195709228516 361.84 @@ -706,7 +706,7 @@ BEGIN IONS TITLE=543.804138183594_255.94519999998 PEPMASS=543.804138183594 RTINSECONDS=255.94519999998 -CHARGE=2 +CHARGE=2+ 106.239685058594 372.99 125.46981048584 424.569 137.330490112305 485.604 @@ -742,7 +742,7 @@ BEGIN IONS TITLE=450.784790039063_256.29580000002 PEPMASS=450.784790039063 RTINSECONDS=256.29580000002 -CHARGE=2 +CHARGE=2+ 106.78239440918 369.437 129.102279663086 1181.79 167.518585205078 433.717 @@ -767,7 +767,7 @@ BEGIN IONS TITLE=581.795532226563_256.63210000002 PEPMASS=581.795532226563 RTINSECONDS=256.63210000002 -CHARGE=2 +CHARGE=2+ 106.766052246094 328.993 114.79670715332 442.721 116.979766845703 356.295 @@ -799,7 +799,7 @@ BEGIN IONS TITLE=579.788879394531_259.04899999998 PEPMASS=579.788879394531 RTINSECONDS=259.04899999998 -CHARGE=2 +CHARGE=2+ 114.838607788086 372.679 119.532539367676 303.983 122.92317199707 375.674 @@ -846,7 +846,7 @@ BEGIN IONS TITLE=578.800903320313_261.0375 PEPMASS=578.800903320313 RTINSECONDS=261.0375 -CHARGE=2 +CHARGE=2+ 108.590911865234 447.514 112.171318054199 365.201 113.935180664063 346.134 @@ -895,7 +895,7 @@ BEGIN IONS TITLE=567.810180664063_262.50829999998 PEPMASS=567.810180664063 RTINSECONDS=262.50829999998 -CHARGE=2 +CHARGE=2+ 112.086898803711 1606.55 122.985260009766 392.529 137.626373291016 427.373 @@ -974,7 +974,7 @@ BEGIN IONS TITLE=528.831726074219_266.57260000002 PEPMASS=528.831726074219 RTINSECONDS=266.57260000002 -CHARGE=2 +CHARGE=2+ 114.677665710449 350.081 120.631484985352 382.567 123.69970703125 324.96 @@ -1012,7 +1012,7 @@ BEGIN IONS TITLE=378.876037597656_267.53500000002 PEPMASS=378.876037597656 RTINSECONDS=267.53500000002 -CHARGE=3 +CHARGE=3+ 110.071144104004 3694.18 110.398712158203 344.731 123.969955444336 432.291 @@ -1087,7 +1087,7 @@ BEGIN IONS TITLE=693.848693847656_267.95089999998 PEPMASS=693.848693847656 RTINSECONDS=267.95089999998 -CHARGE=2 +CHARGE=2+ 110.256965637207 369.46 122.674407958984 398.708 137.420562744141 364.678 @@ -1133,7 +1133,7 @@ BEGIN IONS TITLE=636.79052734375_270.38680000002 PEPMASS=636.79052734375 RTINSECONDS=270.38680000002 -CHARGE=2 +CHARGE=2+ 118.022270202637 392.967 135.761047363281 419.837 148.161483764648 349.155 @@ -1155,7 +1155,7 @@ BEGIN IONS TITLE=622.314025878906_271.34890000002 PEPMASS=622.314025878906 RTINSECONDS=271.34890000002 -CHARGE=2 +CHARGE=2+ 125.879203796387 371.084 175.120193481445 412.761 200.138748168945 1407.2 @@ -1195,7 +1195,7 @@ BEGIN IONS TITLE=560.811340332031_272.3112 PEPMASS=560.811340332031 RTINSECONDS=272.3112 -CHARGE=2 +CHARGE=2+ 105.51545715332 482.135 112.228828430176 351.211 114.104118347168 387.757 @@ -1244,7 +1244,7 @@ BEGIN IONS TITLE=425.262145996094_273.2874 PEPMASS=425.262145996094 RTINSECONDS=273.2874 -CHARGE=2 +CHARGE=2+ 120.40306854248 336.295 124.02220916748 398.925 129.102203369141 1133.46 @@ -1286,7 +1286,7 @@ BEGIN IONS TITLE=567.810241699219_274.7619 PEPMASS=567.810241699219 RTINSECONDS=274.7619 -CHARGE=2 +CHARGE=2+ 134.255859375 394.318 152.385223388672 386.856 157.108276367188 927.317 @@ -1342,7 +1342,7 @@ BEGIN IONS TITLE=475.785766601563_277.8012 PEPMASS=475.785766601563 RTINSECONDS=277.8012 -CHARGE=2 +CHARGE=2+ 110.071006774902 644.949 134.471740722656 411.382 158.857971191406 367.942 @@ -1374,7 +1374,7 @@ BEGIN IONS TITLE=674.343444824219_279.79780000002 PEPMASS=674.343444824219 RTINSECONDS=279.79780000002 -CHARGE=2 +CHARGE=2+ 110.071144104004 2459.68 130.532363891602 368.306 147.458999633789 417.086 @@ -1437,7 +1437,7 @@ BEGIN IONS TITLE=699.8671875_280.76260000002 PEPMASS=699.8671875 RTINSECONDS=280.76260000002 -CHARGE=2 +CHARGE=2+ 113.523498535156 328.629 115.735328674316 331.534 122.736366271973 350.947 @@ -1483,7 +1483,7 @@ BEGIN IONS TITLE=378.875946044922_281.187 PEPMASS=378.875946044922 RTINSECONDS=281.187 -CHARGE=3 +CHARGE=3+ 105.07398223877 414.392 110.071250915527 1513.06 129.102294921875 4518.84 @@ -1546,7 +1546,7 @@ BEGIN IONS TITLE=466.912109375_282.06700000002 PEPMASS=466.912109375 RTINSECONDS=282.06700000002 -CHARGE=3 +CHARGE=3+ 109.140548706055 426.668 129.102294921875 2730.79 134.508697509766 366.727 @@ -1609,7 +1609,7 @@ BEGIN IONS TITLE=702.854431152344_282.47800000002 PEPMASS=702.854431152344 RTINSECONDS=282.47800000002 -CHARGE=2 +CHARGE=2+ 106.833236694336 315.947 106.836730957031 312.254 123.75025177002 351.973 @@ -1653,7 +1653,7 @@ BEGIN IONS TITLE=580.357971191406_282.8244 PEPMASS=580.357971191406 RTINSECONDS=282.8244 -CHARGE=2 +CHARGE=2+ 110.88557434082 385.623 112.139701843262 472.638 112.641830444336 393.265 @@ -1695,7 +1695,7 @@ BEGIN IONS TITLE=449.89697265625_283.7052 PEPMASS=449.89697265625 RTINSECONDS=283.7052 -CHARGE=3 +CHARGE=3+ 110.071189880371 17573.6 119.505928039551 357.642 129.102203369141 17217.3 @@ -1877,7 +1877,7 @@ BEGIN IONS TITLE=492.249877929688_284.11219999998 PEPMASS=492.249877929688 RTINSECONDS=284.11219999998 -CHARGE=2 +CHARGE=2+ 110.113479614258 394.34 111.168807983398 397.417 126.025329589844 389.02 @@ -1911,7 +1911,7 @@ BEGIN IONS TITLE=421.799743652344_284.45689999998 PEPMASS=421.799743652344 RTINSECONDS=284.45689999998 -CHARGE=2 +CHARGE=2+ 115.735298156738 382.56 117.13256072998 350.052 124.393569946289 425.085 @@ -1945,7 +1945,7 @@ BEGIN IONS TITLE=483.747039794922_284.79850000002 PEPMASS=483.747039794922 RTINSECONDS=284.79850000002 -CHARGE=2 +CHARGE=2+ 105.64429473877 350.778 118.950996398926 357.649 120.448867797852 382.573 @@ -1973,7 +1973,7 @@ BEGIN IONS TITLE=662.347534179688_285.1416 PEPMASS=662.347534179688 RTINSECONDS=285.1416 -CHARGE=2 +CHARGE=2+ 129.571090698242 475.121 132.049468994141 313.045 147.58837890625 359.033 @@ -2003,7 +2003,7 @@ BEGIN IONS TITLE=541.291259765625_286.00840000002 PEPMASS=541.291259765625 RTINSECONDS=286.00840000002 -CHARGE=2 +CHARGE=2+ 110.071281433105 928.263 113.47233581543 409.692 116.813377380371 364.621 @@ -2042,7 +2042,7 @@ BEGIN IONS TITLE=743.318176269531_286.40659999998 PEPMASS=743.318176269531 RTINSECONDS=286.40659999998 -CHARGE=2 +CHARGE=2+ 106.506172180176 369.839 117.474586486816 383.208 126.814880371094 371.719 @@ -2067,7 +2067,7 @@ BEGIN IONS TITLE=472.761871337891_286.7577 PEPMASS=472.761871337891 RTINSECONDS=286.7577 -CHARGE=2 +CHARGE=2+ 120.429382324219 371.704 125.874450683594 350.494 129.102142333984 11648.1 @@ -2115,7 +2115,7 @@ BEGIN IONS TITLE=337.674468994141_287.10010000002 PEPMASS=337.674468994141 RTINSECONDS=287.10010000002 -CHARGE=4 +CHARGE=4+ 108.259536743164 377.351 110.07120513916 8091.91 121.915901184082 361.657 @@ -2366,7 +2366,7 @@ BEGIN IONS TITLE=693.31640625_287.43679999998 PEPMASS=693.31640625 RTINSECONDS=287.43679999998 -CHARGE=2 +CHARGE=2+ 114.71460723877 353.275 118.063507080078 481.206 120.554710388184 418.997 @@ -2413,7 +2413,7 @@ BEGIN IONS TITLE=552.775329589844_287.91490000002 PEPMASS=552.775329589844 RTINSECONDS=287.91490000002 -CHARGE=2 +CHARGE=2+ 110.071128845215 1868.03 117.103889465332 372.902 129.101898193359 863.973 @@ -2456,7 +2456,7 @@ BEGIN IONS TITLE=615.830383300781_288.2091 PEPMASS=615.830383300781 RTINSECONDS=288.2091 -CHARGE=2 +CHARGE=2+ 100.658645629883 452.634 103.570503234863 413.005 114.473403930664 403.995 @@ -2491,7 +2491,7 @@ BEGIN IONS TITLE=705.296997070313_288.54979999998 PEPMASS=705.296997070313 RTINSECONDS=288.54979999998 -CHARGE=2 +CHARGE=2+ 100.75643157959 333.13 101.396522521973 348.792 102.721160888672 377.641 @@ -2530,7 +2530,7 @@ BEGIN IONS TITLE=607.616271972656_288.89419999998 PEPMASS=607.616271972656 RTINSECONDS=288.89419999998 -CHARGE=3 +CHARGE=3+ 108.026947021484 378.553 118.626686096191 407.499 119.336906433105 386.168 @@ -2569,7 +2569,7 @@ BEGIN IONS TITLE=782.314697265625_289.23619999998 PEPMASS=782.314697265625 RTINSECONDS=289.23619999998 -CHARGE=2 +CHARGE=2+ 125.3427734375 366.535 130.948745727539 358.136 130.973556518555 358.117 @@ -2595,7 +2595,7 @@ BEGIN IONS TITLE=436.740814208984_290.11099999998 PEPMASS=436.740814208984 RTINSECONDS=290.11099999998 -CHARGE=2 +CHARGE=2+ 108.727874755859 397.494 110.071182250977 5601.01 115.705322265625 389.892 @@ -2673,7 +2673,7 @@ BEGIN IONS TITLE=697.311645507813_290.49460000002 PEPMASS=697.311645507813 RTINSECONDS=290.49460000002 -CHARGE=2 +CHARGE=2+ 122.839836120605 359.721 134.306716918945 404.118 139.666702270508 397.469 @@ -2743,7 +2743,7 @@ BEGIN IONS TITLE=645.339294433594_290.8386 PEPMASS=645.339294433594 RTINSECONDS=290.8386 -CHARGE=2 +CHARGE=2+ 117.365119934082 341.327 124.882347106934 327.256 173.110305786133 398.408 @@ -2783,7 +2783,7 @@ BEGIN IONS TITLE=734.318969726563_291.18040000002 PEPMASS=734.318969726563 RTINSECONDS=291.18040000002 -CHARGE=2 +CHARGE=2+ 122.338882446289 415.044 135.210235595703 363.027 187.462905883789 356.458 @@ -2808,7 +2808,7 @@ BEGIN IONS TITLE=596.290405273438_291.52459999998 PEPMASS=596.290405273438 RTINSECONDS=291.52459999998 -CHARGE=2 +CHARGE=2+ 105.084838867188 363.197 113.4453125 370.928 115.990158081055 358.62 @@ -2847,7 +2847,7 @@ BEGIN IONS TITLE=704.308410644531_292.00489999998 PEPMASS=704.308410644531 RTINSECONDS=292.00489999998 -CHARGE=2 +CHARGE=2+ 132.332656860352 414.824 177.180709838867 339.586 197.408660888672 363.393 @@ -2876,7 +2876,7 @@ BEGIN IONS TITLE=793.303161621094_292.2972 PEPMASS=793.303161621094 RTINSECONDS=292.2972 -CHARGE=2 +CHARGE=2+ 103.002265930176 392.691 120.38321685791 378.737 122.664451599121 385.351 @@ -2904,7 +2904,7 @@ BEGIN IONS TITLE=674.342590332031_293.17330000002 PEPMASS=674.342590332031 RTINSECONDS=293.17330000002 -CHARGE=2 +CHARGE=2+ 110.071128845215 34360 111.074440002441 1002.19 112.08666229248 902.875 @@ -3061,7 +3061,7 @@ BEGIN IONS TITLE=455.272766113281_293.57470000002 PEPMASS=455.272766113281 RTINSECONDS=293.57470000002 -CHARGE=2 +CHARGE=2+ 109.097259521484 372.423 112.086959838867 707.154 115.086013793945 1026.14 @@ -3143,7 +3143,7 @@ BEGIN IONS TITLE=567.809631347656_293.916 PEPMASS=567.809631347656 RTINSECONDS=293.916 -CHARGE=2 +CHARGE=2+ 107.351600646973 341.719 121.45809173584 363.762 124.779815673828 384.43 @@ -3184,7 +3184,7 @@ BEGIN IONS TITLE=303.850555419922_294.2646 PEPMASS=303.850555419922 RTINSECONDS=294.2646 -CHARGE=3 +CHARGE=3+ 112.086494445801 1102.93 113.071166992188 658.821 114.228637695313 370.5 @@ -3274,7 +3274,7 @@ BEGIN IONS TITLE=585.788818359375_294.60049999998 PEPMASS=585.788818359375 RTINSECONDS=294.60049999998 -CHARGE=2 +CHARGE=2+ 112.254219055176 382.375 113.088973999023 378.031 115.260894775391 365.62 @@ -3299,7 +3299,7 @@ BEGIN IONS TITLE=483.743072509766_295.0749 PEPMASS=483.743072509766 RTINSECONDS=295.0749 -CHARGE=2 +CHARGE=2+ 104.940979003906 374.249 105.237228393555 366.519 129.415893554688 391.892 @@ -3329,7 +3329,7 @@ BEGIN IONS TITLE=598.31982421875_295.36849999998 PEPMASS=598.31982421875 RTINSECONDS=295.36849999998 -CHARGE=2 +CHARGE=2+ 113.037879943848 337.178 118.83309173584 381.274 119.717475891113 377.961 @@ -3367,7 +3367,7 @@ BEGIN IONS TITLE=621.813293457031_295.7109 PEPMASS=621.813293457031 RTINSECONDS=295.7109 -CHARGE=2 +CHARGE=2+ 102.054618835449 1178.38 107.883415222168 351.177 113.398735046387 397.5 @@ -3437,7 +3437,7 @@ BEGIN IONS TITLE=533.276733398438_296.05699999998 PEPMASS=533.276733398438 RTINSECONDS=296.05699999998 -CHARGE=2 +CHARGE=2+ 117.758491516113 366.987 133.485305786133 388.205 177.895492553711 455.038 @@ -3460,7 +3460,7 @@ BEGIN IONS TITLE=378.875885009766_296.4018 PEPMASS=378.875885009766 RTINSECONDS=296.4018 -CHARGE=3 +CHARGE=3+ 101.503700256348 386.823 110.070770263672 1110.43 120.493438720703 383.888 @@ -3515,7 +3515,7 @@ BEGIN IONS TITLE=449.897155761719_297.28729999998 PEPMASS=449.897155761719 RTINSECONDS=297.28729999998 -CHARGE=3 +CHARGE=3+ 110.071197509766 9013.02 121.511032104492 419.984 124.109031677246 342.651 @@ -3658,7 +3658,7 @@ BEGIN IONS TITLE=432.743865966797_297.6789 PEPMASS=432.743865966797 RTINSECONDS=297.6789 -CHARGE=2 +CHARGE=2+ 109.085861206055 395.247 110.071189880371 1974.13 112.086860656738 1459.82 @@ -3739,7 +3739,7 @@ BEGIN IONS TITLE=417.253479003906_298.0212 PEPMASS=417.253479003906 RTINSECONDS=298.0212 -CHARGE=2 +CHARGE=2+ 110.071197509766 4816.06 126.481460571289 359.207 129.102172851563 27089 @@ -3813,7 +3813,7 @@ BEGIN IONS TITLE=376.200714111328_298.37110000002 PEPMASS=376.200714111328 RTINSECONDS=298.37110000002 -CHARGE=2 +CHARGE=2+ 118.11287689209 398.669 119.280426025391 411.525 129.102416992188 865.465 @@ -3851,7 +3851,7 @@ BEGIN IONS TITLE=466.264678955078_298.70920000002 PEPMASS=466.264678955078 RTINSECONDS=298.70920000002 -CHARGE=2 +CHARGE=2+ 123.882957458496 362.16 125.283592224121 443.782 129.102661132813 1089.96 @@ -3886,7 +3886,7 @@ BEGIN IONS TITLE=633.793212890625_299.115 PEPMASS=633.793212890625 RTINSECONDS=299.115 -CHARGE=2 +CHARGE=2+ 110.144966125488 355.213 115.02188873291 358.758 116.733589172363 336.112 @@ -3920,7 +3920,7 @@ BEGIN IONS TITLE=712.296936035156_299.4072 PEPMASS=712.296936035156 RTINSECONDS=299.4072 -CHARGE=2 +CHARGE=2+ 101.357307434082 367.483 133.048233032227 366.259 137.101852416992 380.959 @@ -3947,7 +3947,7 @@ BEGIN IONS TITLE=483.292816162109_300.2925 PEPMASS=483.292816162109 RTINSECONDS=300.2925 -CHARGE=2 +CHARGE=2+ 110.071182250977 1804.14 129.102127075195 2580.77 130.086456298828 647.685 @@ -4030,7 +4030,7 @@ BEGIN IONS TITLE=508.798187255859_300.68839999998 PEPMASS=508.798187255859 RTINSECONDS=300.68839999998 -CHARGE=2 +CHARGE=2+ 106.386688232422 351.56 110.071311950684 1471.97 129.102127075195 19768.5 @@ -4114,7 +4114,7 @@ BEGIN IONS TITLE=646.866577148438_301.02739999998 PEPMASS=646.866577148438 RTINSECONDS=301.02739999998 -CHARGE=2 +CHARGE=2+ 115.780769348145 337.386 116.994407653809 368.776 129.102188110352 15845.4 @@ -4182,7 +4182,7 @@ BEGIN IONS TITLE=667.3291015625_301.37059999998 PEPMASS=667.3291015625 RTINSECONDS=301.37059999998 -CHARGE=2 +CHARGE=2+ 110.07103729248 916.218 115.962097167969 400.988 120.193977355957 414.499 @@ -4317,7 +4317,7 @@ BEGIN IONS TITLE=629.355651855469_301.71319999998 PEPMASS=629.355651855469 RTINSECONDS=301.71319999998 -CHARGE=2 +CHARGE=2+ 122.69425201416 340.62 216.55876159668 396.029 251.93798828125 356.94 @@ -4337,7 +4337,7 @@ BEGIN IONS TITLE=468.268646240234_302.19520000002 PEPMASS=468.268646240234 RTINSECONDS=302.19520000002 -CHARGE=2 +CHARGE=2+ 112.332969665527 369.152 112.685974121094 332.509 125.145973205566 399.683 @@ -4379,7 +4379,7 @@ BEGIN IONS TITLE=475.236663818359_302.49070000002 PEPMASS=475.236663818359 RTINSECONDS=302.49070000002 -CHARGE=2 +CHARGE=2+ 104.503509521484 362.604 110.07120513916 1475.27 120.387550354004 364.051 @@ -4415,7 +4415,7 @@ BEGIN IONS TITLE=543.805114746094_302.8344 PEPMASS=543.805114746094 RTINSECONDS=302.8344 -CHARGE=2 +CHARGE=2+ 103.456977844238 343.592 129.101699829102 539.994 132.283889770508 367.289 @@ -4440,7 +4440,7 @@ BEGIN IONS TITLE=625.304077148438_303.1749 PEPMASS=625.304077148438 RTINSECONDS=303.1749 -CHARGE=2 +CHARGE=2+ 109.335235595703 364.051 110.071166992188 622.164 131.273040771484 429.434 @@ -4469,7 +4469,7 @@ BEGIN IONS TITLE=580.827575683594_303.5175 PEPMASS=580.827575683594 RTINSECONDS=303.5175 -CHARGE=2 +CHARGE=2+ 100.834747314453 366.762 129.101760864258 1094.77 131.334747314453 464.641 @@ -4509,7 +4509,7 @@ BEGIN IONS TITLE=445.221618652344_304.36840000002 PEPMASS=445.221618652344 RTINSECONDS=304.36840000002 -CHARGE=3 +CHARGE=3+ 110.071044921875 4609.02 111.58162689209 430.601 117.065689086914 14042.2 @@ -4840,7 +4840,7 @@ BEGIN IONS TITLE=679.308288574219_304.7703 PEPMASS=679.308288574219 RTINSECONDS=304.7703 -CHARGE=2 +CHARGE=2+ 116.131713867188 400.156 129.102142333984 3115.75 130.085845947266 791.841 @@ -4985,7 +4985,7 @@ BEGIN IONS TITLE=420.734558105469_305.118 PEPMASS=420.734558105469 RTINSECONDS=305.118 -CHARGE=2 +CHARGE=2+ 106.182502746582 397.09 110.07096862793 695.72 112.08659362793 1288.63 @@ -5063,7 +5063,7 @@ BEGIN IONS TITLE=529.7548828125_305.45830000002 PEPMASS=529.7548828125 RTINSECONDS=305.45830000002 -CHARGE=2 +CHARGE=2+ 110.071884155273 478.997 112.218811035156 411.678 129.102294921875 1755.38 @@ -5098,7 +5098,7 @@ BEGIN IONS TITLE=690.296936035156_305.79820000002 PEPMASS=690.296936035156 RTINSECONDS=305.79820000002 -CHARGE=2 +CHARGE=2+ 113.36735534668 401.815 121.50080871582 397.076 122.001220703125 351.687 @@ -5170,7 +5170,7 @@ BEGIN IONS TITLE=546.776123046875_306.27550000002 PEPMASS=546.776123046875 RTINSECONDS=306.27550000002 -CHARGE=2 +CHARGE=2+ 106.540412902832 361.798 110.070289611816 584.799 116.288566589355 393.976 @@ -5201,7 +5201,7 @@ BEGIN IONS TITLE=334.167877197266_306.5745 PEPMASS=334.167877197266 RTINSECONDS=306.5745 -CHARGE=4 +CHARGE=4+ 102.054786682129 998.556 102.16039276123 385.414 110.071403503418 2044.73 @@ -5428,7 +5428,7 @@ BEGIN IONS TITLE=595.303039550781_306.93040000002 PEPMASS=595.303039550781 RTINSECONDS=306.93040000002 -CHARGE=2 +CHARGE=2+ 105.706916809082 421.246 109.228050231934 397.321 118.714744567871 425.206 @@ -5456,7 +5456,7 @@ BEGIN IONS TITLE=455.275421142578_307.25959999998 PEPMASS=455.275421142578 RTINSECONDS=307.25959999998 -CHARGE=2 +CHARGE=2+ 104.091484069824 377.437 109.484176635742 418.414 129.102264404297 1703.59 @@ -5497,7 +5497,7 @@ BEGIN IONS TITLE=436.741088867188_307.60549999998 PEPMASS=436.741088867188 RTINSECONDS=307.60549999998 -CHARGE=2 +CHARGE=2+ 100.326446533203 404.957 108.857521057129 356.627 110.071159362793 3441.25 @@ -5552,7 +5552,7 @@ BEGIN IONS TITLE=382.715484619141_308.4648 PEPMASS=382.715484619141 RTINSECONDS=308.4648 -CHARGE=2 +CHARGE=2+ 110.071159362793 6905.79 111.161727905273 416.129 122.848152160645 350.032 @@ -5640,7 +5640,7 @@ BEGIN IONS TITLE=674.342346191406_308.87200000002 PEPMASS=674.342346191406 RTINSECONDS=308.87200000002 -CHARGE=2 +CHARGE=2+ 110.071144104004 3072.22 138.167037963867 382.726 175.119995117188 626.069 @@ -5690,7 +5690,7 @@ BEGIN IONS TITLE=623.812622070313_309.1938 PEPMASS=623.812622070313 RTINSECONDS=309.1938 -CHARGE=2 +CHARGE=2+ 122.174713134766 349.135 138.743209838867 390.376 172.15673828125 381.718 @@ -5720,7 +5720,7 @@ BEGIN IONS TITLE=686.301208496094_309.53860000002 PEPMASS=686.301208496094 RTINSECONDS=309.53860000002 -CHARGE=2 +CHARGE=2+ 105.220878601074 376.918 106.325302124023 355.535 118.83349609375 341.905 @@ -5767,7 +5767,7 @@ BEGIN IONS TITLE=551.795776367188_309.88009999998 PEPMASS=551.795776367188 RTINSECONDS=309.88009999998 -CHARGE=2 +CHARGE=2+ 114.653823852539 398.198 175.117172241211 421.907 192.789566040039 396.672 @@ -5791,7 +5791,7 @@ BEGIN IONS TITLE=473.764495849609_310.35490000002 PEPMASS=473.764495849609 RTINSECONDS=310.35490000002 -CHARGE=2 +CHARGE=2+ 118.722053527832 359.02 124.127540588379 360.399 126.812232971191 357.418 @@ -5822,7 +5822,7 @@ BEGIN IONS TITLE=701.291564941406_310.6467 PEPMASS=701.291564941406 RTINSECONDS=310.6467 -CHARGE=2 +CHARGE=2+ 107.296096801758 372.232 107.992027282715 358.725 132.809127807617 445.836 @@ -5865,7 +5865,7 @@ BEGIN IONS TITLE=317.195678710938_311.00149999998 PEPMASS=317.195678710938 RTINSECONDS=311.00149999998 -CHARGE=2 +CHARGE=2+ 110.070816040039 954.02 119.863815307617 335.692 129.102111816406 1111.66 @@ -5895,7 +5895,7 @@ BEGIN IONS TITLE=478.246124267578_311.3394 PEPMASS=478.246124267578 RTINSECONDS=311.3394 -CHARGE=2 +CHARGE=2+ 101.702697753906 407.752 103.817451477051 386.489 107.570610046387 363.651 @@ -5919,7 +5919,7 @@ BEGIN IONS TITLE=727.300903320313_311.67700000002 PEPMASS=727.300903320313 RTINSECONDS=311.67700000002 -CHARGE=2 +CHARGE=2+ 106.174003601074 382.237 111.207046508789 376.96 114.230239868164 372.559 diff --git a/test_files/mgf/example.mgf b/test_files/mgf/example.mgf new file mode 100644 index 0000000..c778bbc --- /dev/null +++ b/test_files/mgf/example.mgf @@ -0,0 +1,12 @@ +BEGIN IONS +PEPMASS=413.26611887841 +CHARGE=1+ +TITLE=MS/MS scan at 1.535 min with Intensity: 604.0 + +189.48956 5050.0 +283.62076 5050.0 +301.22977 5050.0 +311.08008 5050.0 +399.99106 5050.0 + +END IONS \ No newline at end of file