use crate::{
error::CustomError,
identification::{IdentifiedPeptide, IdentifiedPeptideSource, MetaData},
modification::Ontology,
ontologies::CustomDatabase,
system::{usize::Charge, MassOverCharge},
Peptidoform, SemiAmbiguous, SloppyParsingParameters,
};
use std::path::{Path, PathBuf};
use serde::{Deserialize, Serialize};
use super::{
common_parser::Location,
csv::{parse_csv, CsvLine},
BoxedIdentifiedPeptideIter,
};
static NUMBER_ERROR: (&str, &str) = (
"Invalid InstaNovo line",
"This column is not a number but it is required to be a number in this format",
);
static BUILT_IN_MODIFICATIONS: std::sync::OnceLock<SloppyParsingParameters> =
std::sync::OnceLock::new();
format_family!(
InstaNovoFormat,
InstaNovoData,
InstaNovoVersion, [&INSTANOVO_V1_0_0], b',', None;
required {
scan_number: usize, |location: Location, _| location.parse(NUMBER_ERROR);
mz: MassOverCharge, |location: Location, _| location.parse::<f64>(NUMBER_ERROR).map(MassOverCharge::new::<crate::system::mz>);
z: Charge, |location: Location, _| location.parse::<usize>(NUMBER_ERROR).map(Charge::new::<crate::system::e>);
raw_file: PathBuf, |location: Location, _| Ok(Path::new(&location.get_string()).to_owned());
peptide: Peptidoform<SemiAmbiguous>, |location: Location, custom_database: Option<&CustomDatabase>| Peptidoform::sloppy_pro_forma(
location.full_line(),
location.location.clone(),
custom_database,
BUILT_IN_MODIFICATIONS.get_or_init(|| SloppyParsingParameters {
replace_mass_modifications: Some(
vec![Ontology::Unimod.find_id(35, None).unwrap(), Ontology::Unimod.find_id(21, None).unwrap(), Ontology::Unimod.find_id(4, None).unwrap()]
),
..Default::default()
}
));
score: f64, |location: Location, _| location.parse::<f64>(NUMBER_ERROR);
local_confidence: Vec<f64>, |location: Location, _| location
.trim_start_matches("[").trim_end_matches("]")
.array(',')
.map(|l| l.parse::<f64>(NUMBER_ERROR))
.collect::<Result<Vec<_>, _>>();
}
optional { }
);
impl From<InstaNovoData> for IdentifiedPeptide {
fn from(value: InstaNovoData) -> Self {
Self {
score: Some(2.0 / (1.0 + 1.01_f64.powf(-value.score))),
local_confidence: Some(
value
.local_confidence
.iter()
.map(|v| 2.0 / (1.0 + 1.25_f64.powf(-v)))
.collect(),
),
metadata: MetaData::InstaNovo(value),
}
}
}
pub const INSTANOVO_V1_0_0: InstaNovoFormat = InstaNovoFormat {
version: InstaNovoVersion::V1_0_0,
scan_number: "scan_number",
mz: "precursor_mz",
z: "precursor_charge",
raw_file: "experiment_name",
peptide: "preds",
score: "log_probs",
local_confidence: "token_log_probs",
};
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default, Serialize, Deserialize)]
pub enum InstaNovoVersion {
#[default]
V1_0_0,
}
impl std::fmt::Display for InstaNovoVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
write!(
f,
"{}",
match self {
Self::V1_0_0 => "v1.0.0",
}
)
}
}