use std::io::prelude::*;
use std::io::Lines;
use traits::*;
use util::*;
use super::mgf::MgfRecordIter;
use super::peak::Peak;
use super::re::*;
use super::record::Record;
#[inline]
pub(crate) fn estimate_fullms_mgf_record_size(record: &Record) -> usize {
const MGF_VOCABULARY_SIZE: usize = 175;
const MGF_PEAK_SIZE: usize = 25;
MGF_VOCABULARY_SIZE + MGF_PEAK_SIZE * record.peaks.len()
}
#[inline(always)]
fn to_mgf<'a, T: Write>(writer: &mut T, record: &'a Record)
-> ResultType<()>
{
record_to_fullms_mgf(writer, record)
}
#[inline(always)]
fn export_scan<T: Write>(writer: &mut T, record: &Record)
-> ResultType<()>
{
let num = record.num.ntoa()?;
write_alls!(writer, b"Scan#: ", num.as_bytes(), b"\n")?;
Ok(())
}
#[inline(always)]
fn export_rt<T: Write>(writer: &mut T, record: &Record)
-> ResultType<()>
{
let rt = record.rt.ntoa()?;
write_alls!(writer, b"Ret.Time: ", rt.as_bytes(), b"\n")?;
Ok(())
}
#[inline(always)]
#[allow(unused)] fn export_basepeak_mz<T: Write>(writer: &mut T, record: &Record)
-> ResultType<()>
{
Ok(())
}
#[inline(always)]
#[allow(unused)] fn export_basepeak_intensity<T: Write>(writer: &mut T, record: &Record)
-> ResultType<()>
{
Ok(())
}
#[inline(always)]
fn export_spectra<T: Write>(writer: &mut T, record: &Record)
-> ResultType<()>
{
for peak in record.peaks.iter() {
let mz = peak.mz.ntoa()?;
let intensity = peak.intensity.ntoa()?;
write_alls!(writer, mz.as_bytes(), b"\t", intensity.as_bytes(), b"\n")?;
}
Ok(())
}
pub(crate) fn record_to_fullms_mgf<T: Write>(writer: &mut T, record: &Record)
-> ResultType<()>
{
export_scan(writer, record)?;
export_rt(writer, record)?;
writer.write_all(b"IonInjectionTime(ms): 0.0\nTotalIonCurrent: 0\n")?;
export_basepeak_mz(writer, record)?;
export_basepeak_intensity(writer, record)?;
export_spectra(writer, record)?;
writer.write_all(b"\n\n")?;
Ok(())
}
#[inline(always)]
fn init_cb<T: Write>(writer: &mut T, delimiter: u8)
-> ResultType<TextWriterState<T>>
{
Ok(TextWriterState::new(writer, delimiter))
}
#[inline(always)]
fn export_cb<'a, T: Write>(writer: &mut TextWriterState<T>, record: &'a Record)
-> ResultType<()>
{
writer.export(record, &to_mgf)
}
#[inline(always)]
fn dest_cb<T: Write>(_: &mut TextWriterState<T>)
-> ResultType<()>
{
Ok(())
}
#[inline(always)]
pub(crate) fn reference_iterator_to_fullms_mgf<'a, Iter, T>(writer: &mut T, iter: Iter)
-> ResultType<()>
where T: Write,
Iter: Iterator<Item = &'a Record>
{
reference_iterator_export(writer, iter, b'\n', &init_cb, &export_cb, &dest_cb)
}
#[inline(always)]
pub(crate) fn value_iterator_to_fullms_mgf<Iter, T>(writer: &mut T, iter: Iter)
-> ResultType<()>
where T: Write,
Iter: Iterator<Item = ResultType<Record>>
{
value_iterator_export(writer, iter, b'\n', &init_cb, &export_cb, &dest_cb)
}
#[inline(always)]
pub(crate) fn reference_iterator_to_fullms_mgf_strict<'a, Iter, T>(writer: &mut T, iter: Iter)
-> ResultType<()>
where T: Write,
Iter: Iterator<Item = &'a Record>
{
reference_iterator_export_strict(writer, iter, b'\n', &init_cb, &export_cb, &dest_cb)
}
#[inline(always)]
pub(crate) fn value_iterator_to_fullms_mgf_strict<Iter, T>(writer: &mut T, iter: Iter)
-> ResultType<()>
where T: Write,
Iter: Iterator<Item = ResultType<Record>>
{
value_iterator_export_strict(writer, iter, b'\n', &init_cb, &export_cb, &dest_cb)
}
#[inline(always)]
pub(crate) fn reference_iterator_to_fullms_mgf_lenient<'a, Iter, T>(writer: &mut T, iter: Iter)
-> ResultType<()>
where T: Write,
Iter: Iterator<Item = &'a Record>
{
reference_iterator_export_lenient(writer, iter, b'\n', &init_cb, &export_cb, &dest_cb)
}
#[inline(always)]
pub(crate) fn value_iterator_to_fullms_mgf_lenient<Iter, T>(writer: &mut T, iter: Iter)
-> ResultType<()>
where T: Write,
Iter: Iterator<Item = ResultType<Record>>
{
value_iterator_export_lenient(writer, iter, b'\n', &init_cb, &export_cb, &dest_cb)
}
#[inline(always)]
fn parse_scan_line<T: BufRead>(lines: &mut Lines<T>, record: &mut Record)
-> ResultType<()>
{
type Scan = FullMsMgfScanRegex;
let line = none_to_error!(lines.next(), InvalidInput)?;
let captures = none_to_error!(Scan::extract().captures(&line), InvalidInput);
let num = capture_as_str(&captures, Scan::NUM_INDEX);
record.num = num.parse::<u32>()?;
Ok(())
}
#[inline(always)]
fn parse_rt_line<T: BufRead>(lines: &mut Lines<T>, record: &mut Record)
-> ResultType<()>
{
type Rt = FullMsMgfRtRegex;
let line = none_to_error!(lines.next(), InvalidInput)?;
let captures = none_to_error!(Rt::extract().captures(&line), InvalidInput);
let rt = capture_as_str(&captures, Rt::RT_INDEX);
record.rt = rt.parse::<f64>()?;
Ok(())
}
#[inline(always)]
fn parse_ion_injection_time_line<T: BufRead>(lines: &mut Lines<T>, _: &mut Record)
-> ResultType<()>
{
let line = none_to_error!(lines.next(), InvalidInput)?;
bool_to_error!(line.starts_with("IonInjectionTime(ms): "), InvalidInput);
Ok(())
}
#[inline(always)]
fn parse_total_ion_current_line<T: BufRead>(lines: &mut Lines<T>, _: &mut Record)
-> ResultType<()>
{
let line = none_to_error!(lines.next(), InvalidInput)?;
bool_to_error!(line.starts_with("TotalIonCurrent: "), InvalidInput);
Ok(())
}
#[inline(always)]
fn parse_basepeak_mass_line<T: BufRead>(lines: &mut Lines<T>, _: &mut Record)
-> ResultType<()>
{
let line = none_to_error!(lines.next(), InvalidInput)?;
bool_to_error!(line.starts_with("BasePeakMass: "), InvalidInput);
Ok(())
}
#[inline(always)]
fn parse_basepeak_intensity_line<T: BufRead>(lines: &mut Lines<T>, _: &mut Record)
-> ResultType<()>
{
let line = none_to_error!(lines.next(), InvalidInput)?;
bool_to_error!(line.starts_with("BasePeakIntensity: "), InvalidInput);
Ok(())
}
#[inline(always)]
fn parse_spectra<T: BufRead>(lines: &mut Lines<T>, record: &mut Record)
-> ResultType<()>
{
for result in lines {
let line = result?;
if line.is_empty() {
break;
}
let mut items = line.split('\t');
let mz = none_to_error!(items.next(), InvalidInput);
let intensity = none_to_error!(items.next(), InvalidInput);
bool_to_error!(items.next().is_none(), InvalidInput);
record.peaks.push(Peak {
mz: mz.parse::<f64>()?,
intensity: intensity.parse::<f64>()?,
z: 0,
});
}
Ok(())
}
pub(crate) fn record_from_fullms_mgf<T: BufRead>(reader: &mut T)
-> ResultType<Record>
{
let mut lines = reader.lines();
let mut record = Record::with_peak_capacity(50);
parse_scan_line(&mut lines, &mut record)?;
parse_rt_line(&mut lines, &mut record)?;
parse_ion_injection_time_line(&mut lines, &mut record)?;
parse_total_ion_current_line(&mut lines, &mut record)?;
parse_basepeak_mass_line(&mut lines, &mut record)?;
parse_basepeak_intensity_line(&mut lines, &mut record)?;
parse_spectra(&mut lines, &mut record)?;
record.peaks.shrink_to_fit();
Ok(record)
}
#[inline(always)]
pub(crate) fn iterator_from_fullms_mgf<T: BufRead>(reader: T)
-> MgfRecordIter<T>
{
MgfRecordIter::new(reader, "Scan#:", MgfKind::FullMs)
}