use std::{
collections::HashMap,
ops::{Deref, DerefMut},
};
use crate::meta::ScanSettings;
use super::{
DataProcessing, FileDescription, InstrumentConfiguration, MassSpectrometryRun, Sample, Software,
};
pub trait MSDataFileMetadata {
fn data_processings(&self) -> &Vec<DataProcessing>;
fn instrument_configurations(&self) -> &HashMap<u32, InstrumentConfiguration>;
fn file_description(&self) -> &FileDescription;
fn softwares(&self) -> &Vec<Software>;
fn samples(&self) -> &Vec<Sample>;
fn scan_settings(&self) -> Option<&Vec<ScanSettings>> {
None
}
fn data_processings_mut(&mut self) -> &mut Vec<DataProcessing>;
fn instrument_configurations_mut(&mut self) -> &mut HashMap<u32, InstrumentConfiguration>;
fn file_description_mut(&mut self) -> &mut FileDescription;
fn softwares_mut(&mut self) -> &mut Vec<Software>;
fn samples_mut(&mut self) -> &mut Vec<Sample>;
fn scan_settings_mut(&mut self) -> Option<&mut Vec<ScanSettings>> {
None
}
fn copy_metadata_from(&mut self, source: &impl MSDataFileMetadata)
where
Self: Sized,
{
*self.data_processings_mut() = source.data_processings().clone();
*self.instrument_configurations_mut() = source.instrument_configurations().clone();
*self.file_description_mut() = source.file_description().clone();
*self.softwares_mut() = source.softwares().clone();
*self.samples_mut() = source.samples().clone();
self.set_spectrum_count_hint(source.spectrum_count_hint());
if let Some(settings) = source.scan_settings() {
match self.scan_settings_mut() {
Some(mine) => *mine = settings.clone(),
None => {
log::debug!("Cannot store scan settings on this type of data file");
}
}
}
match source.run_description() {
Some(run) => {
let desc = self.run_description_mut();
if let Some(r) = desc {
*r = run.clone();
};
}
None => {
let mut desc = self.run_description_mut();
desc.take();
}
}
}
fn spectrum_count_hint(&self) -> Option<u64> {
None
}
fn set_spectrum_count_hint(&mut self, _value: Option<u64>) {}
fn run_description(&self) -> Option<&MassSpectrometryRun> {
None
}
fn run_description_mut(&mut self) -> Option<&mut MassSpectrometryRun> {
None
}
fn source_file_name(&self) -> Option<&str> {
self.file_description()
.source_files
.first()
.map(|s| s.name.as_str())
}
}
#[derive(Debug, Default, Clone)]
pub struct FileMetadataConfig {
pub(crate) file_description: FileDescription,
pub(crate) instrument_configurations: HashMap<u32, InstrumentConfiguration>,
pub(crate) softwares: Vec<Software>,
pub(crate) samples: Vec<Sample>,
pub(crate) scan_settings: Vec<ScanSettings>,
pub(crate) data_processings: Vec<DataProcessing>,
pub(crate) run: MassSpectrometryRun,
pub(crate) num_spectra: Option<u64>,
}
impl FileMetadataConfig {
#[allow(clippy::too_many_arguments)]
pub fn new(
file_description: FileDescription,
instrument_configurations: HashMap<u32, InstrumentConfiguration>,
softwares: Vec<Software>,
samples: Vec<Sample>,
scan_settings: Vec<ScanSettings>,
data_processings: Vec<DataProcessing>,
run: MassSpectrometryRun,
num_spectra: Option<u64>,
) -> Self {
Self {
file_description,
instrument_configurations,
softwares,
samples,
scan_settings,
data_processings,
run,
num_spectra,
}
}
}
impl<T> From<&T> for FileMetadataConfig
where
T: MSDataFileMetadata,
{
fn from(value: &T) -> Self {
let mut this = Self::default();
this.copy_metadata_from(value);
this
}
}
impl MSDataFileMetadata for FileMetadataConfig {
crate::impl_metadata_trait!();
fn scan_settings(&self) -> Option<&Vec<ScanSettings>> {
Some(&self.scan_settings)
}
fn scan_settings_mut(&mut self) -> Option<&mut Vec<ScanSettings>> {
Some(&mut self.scan_settings)
}
fn run_description(&self) -> Option<&MassSpectrometryRun> {
Some(&self.run)
}
fn run_description_mut(&mut self) -> Option<&mut MassSpectrometryRun> {
Some(&mut self.run)
}
fn set_spectrum_count_hint(&mut self, _value: Option<u64>) {
self.num_spectra = _value
}
fn spectrum_count_hint(&self) -> Option<u64> {
self.num_spectra
}
}
#[macro_export]
macro_rules! impl_metadata_trait {
(extended) => {
$crate::impl_metadata_trait();
fn spectrum_count_hint(&self) -> Option<u64> {
self.num_spectra
}
fn run_description(&self) -> Option<&$crate::meta::MassSpectrometryRun> {
Some(&self.run)
}
fn run_description_mut(&mut self) -> Option<&mut $crate::meta::MassSpectrometryRun> {
Some(&mut self.run)
}
};
() => {
fn data_processings(&self) -> &Vec<$crate::meta::DataProcessing> {
&self.data_processings
}
fn instrument_configurations(
&self,
) -> &std::collections::HashMap<u32, $crate::meta::InstrumentConfiguration> {
&self.instrument_configurations
}
fn file_description(&self) -> &$crate::meta::FileDescription {
&self.file_description
}
fn softwares(&self) -> &Vec<$crate::meta::Software> {
&self.softwares
}
fn data_processings_mut(&mut self) -> &mut Vec<$crate::meta::DataProcessing> {
&mut self.data_processings
}
fn instrument_configurations_mut(
&mut self,
) -> &mut std::collections::HashMap<u32, $crate::meta::InstrumentConfiguration> {
&mut self.instrument_configurations
}
fn file_description_mut(&mut self) -> &mut $crate::meta::FileDescription {
&mut self.file_description
}
fn softwares_mut(&mut self) -> &mut Vec<$crate::meta::Software> {
&mut self.softwares
}
fn samples(&self) -> &Vec<$crate::meta::Sample> {
&self.samples
}
fn samples_mut(&mut self) -> &mut Vec<$crate::meta::Sample> {
&mut self.samples
}
};
}
#[macro_export]
macro_rules! delegate_impl_metadata_trait {
(expr, $self:ident => $impl:tt, &mut => $mut_impl:tt) => {
fn data_processings(&self) -> &Vec<$crate::meta::DataProcessing> {
let $self = self;
let step = $impl;
step.data_processings()
}
fn instrument_configurations(&self) -> &std::collections::HashMap<u32, $crate::meta::InstrumentConfiguration> {
let $self = self;
let step = $impl;
step.instrument_configurations()
}
fn file_description(&self) -> &$crate::meta::FileDescription {
let $self = self;
let step = $impl;
step.file_description()
}
fn softwares(&self) -> &Vec<$crate::meta::Software> {
let $self = self;
let step = $impl;
step.softwares()
}
fn samples(&self) -> &Vec<$crate::meta::Sample> {
let $self = self;
let step = $impl;
step.samples()
}
fn data_processings_mut(&mut self) -> &mut Vec<$crate::meta::DataProcessing> {
let $self = self;
let step = $mut_impl;
step.data_processings_mut()
}
fn instrument_configurations_mut(&mut self) -> &mut std::collections::HashMap<u32, $crate::meta::InstrumentConfiguration> {
let $self = self;
let step = $mut_impl;
step.instrument_configurations_mut()
}
fn file_description_mut(&mut self) -> &mut $crate::meta::FileDescription {
let $self = self;
let step = $mut_impl;
step.file_description_mut()
}
fn softwares_mut(&mut self) -> &mut Vec<$crate::meta::Software> {
let $self = self;
let step = $mut_impl;
step.softwares_mut()
}
fn samples_mut(&mut self) -> &mut Vec<$crate::meta::Sample> {
let $self = self;
let step = $mut_impl;
step.samples_mut()
}
fn spectrum_count_hint(&self) -> Option<u64> {
let $self = self;
let step = $impl;
step.spectrum_count_hint()
}
fn run_description(&self) -> Option<&$crate::meta::MassSpectrometryRun> {
let $self = self;
let step = $impl;
step.run_description()
}
fn run_description_mut(&mut self) -> Option<&mut $crate::meta::MassSpectrometryRun> {
let $self = self;
let step = $mut_impl;
step.run_description_mut()
}
fn source_file_name(&self) -> Option<&str> {
let $self = self;
let step = $impl;
step.source_file_name()
}
};
($src:tt, extended) => {
$crate::delegate_impl_metadata_trait($src);
};
($src:tt) => {
$crate::delegate_impl_metadata_trait!(expr, this => { &this.$src }, &mut => { &mut this.$src });
};
}
impl<T: MSDataFileMetadata> MSDataFileMetadata for Box<T> {
delegate_impl_metadata_trait!(expr, x => { x.deref() }, &mut => { x.deref_mut() });
}
impl<T: MSDataFileMetadata> MSDataFileMetadata for std::sync::Arc<T> {
delegate_impl_metadata_trait!(expr, x => { x.deref() }, &mut => { std::sync::Arc::get_mut(x).unwrap_or_else(|| panic!("Attempting to modify `MSDataFileMetadata` via a shared reference")) });
}