1use mscore::data::peptide::PeptideSequence;
2use mscore::data::spectrum::{MsType, MzSpectrum};
3use rand::distributions::{Distribution, Uniform};
4use serde::{Deserialize, Serialize};
5
6#[derive(Serialize, Deserialize, Debug, Clone)]
7pub struct SignalDistribution {
8 pub mean: f32,
9 pub variance: f32,
10 pub error: f32,
11 pub occurrence: Vec<u32>,
12 pub abundance: Vec<f32>,
13}
14
15impl SignalDistribution {
16 pub fn new(
17 mean: f32,
18 variance: f32,
19 error: f32,
20 occurrence: Vec<u32>,
21 abundance: Vec<f32>,
22 ) -> Self {
23 SignalDistribution {
24 mean,
25 variance,
26 error,
27 occurrence,
28 abundance,
29 }
30 }
31
32 pub fn add_noise(&self, noise_level: f32) -> Vec<f32> {
33 let mut rng = rand::thread_rng();
34 let noise_dist = Uniform::new(0.0, noise_level);
35
36 let noise: Vec<f32> = self
37 .abundance
38 .iter()
39 .map(|_| noise_dist.sample(&mut rng))
40 .collect();
41 let noise_relative: Vec<f32> = self
42 .abundance
43 .iter()
44 .zip(noise.iter())
45 .map(|(&abu, &noise)| abu * noise)
46 .collect();
47 let noised_signal: Vec<f32> = self
48 .abundance
49 .iter()
50 .zip(noise_relative.iter())
51 .map(|(&abu, &noise_rel)| abu + noise_rel)
52 .collect();
53
54 let sum_noised_signal: f32 = noised_signal.iter().sum();
55 let sum_rt_abu: f32 = self.abundance.iter().sum();
56
57 noised_signal
58 .iter()
59 .map(|&x| (x / sum_noised_signal) * sum_rt_abu)
60 .collect()
61 }
62}
63
64#[derive(Debug, Clone)]
65pub struct PeptidesSim {
66 pub protein_id: u32,
67 pub peptide_id: u32,
68 pub sequence: PeptideSequence,
69 pub proteins: String,
70 pub decoy: bool,
71 pub missed_cleavages: i8,
72 pub n_term: Option<bool>,
73 pub c_term: Option<bool>,
74 pub mono_isotopic_mass: f32,
75 pub retention_time: f32,
76 pub events: f32,
77 pub frame_start: u32,
78 pub frame_end: u32,
79 pub frame_distribution: SignalDistribution,
80}
81
82impl PeptidesSim {
83 pub fn new(
84 protein_id: u32,
85 peptide_id: u32,
86 sequence: String,
87 proteins: String,
88 decoy: bool,
89 missed_cleavages: i8,
90 n_term: Option<bool>,
91 c_term: Option<bool>,
92 mono_isotopic_mass: f32,
93 retention_time: f32,
94 events: f32,
95 frame_start: u32,
96 frame_end: u32,
97 frame_occurrence: Vec<u32>,
98 frame_abundance: Vec<f32>,
99 ) -> Self {
100 PeptidesSim {
101 protein_id,
102 peptide_id,
103 sequence: PeptideSequence::new(sequence, Some(peptide_id as i32)),
104 proteins,
105 decoy,
106 missed_cleavages,
107 n_term,
108 c_term,
109 mono_isotopic_mass,
110 retention_time,
111 events,
112 frame_start,
113 frame_end,
114 frame_distribution: SignalDistribution::new(
115 0.0,
116 0.0,
117 0.0,
118 frame_occurrence,
119 frame_abundance,
120 ),
121 }
122 }
123}
124
125#[derive(Debug, Clone)]
126pub struct WindowGroupSettingsSim {
127 pub window_group: u32,
128 pub scan_start: u32,
129 pub scan_end: u32,
130 pub isolation_mz: f32,
131 pub isolation_width: f32,
132 pub collision_energy: f32,
133}
134
135impl WindowGroupSettingsSim {
136 pub fn new(
137 window_group: u32,
138 scan_start: u32,
139 scan_end: u32,
140 isolation_mz: f32,
141 isolation_width: f32,
142 collision_energy: f32,
143 ) -> Self {
144 WindowGroupSettingsSim {
145 window_group,
146 scan_start,
147 scan_end,
148 isolation_mz,
149 isolation_width,
150 collision_energy,
151 }
152 }
153}
154
155#[derive(Debug, Clone)]
156pub struct FrameToWindowGroupSim {
157 pub frame_id: u32,
158 pub window_group: u32,
159}
160
161impl FrameToWindowGroupSim {
162 pub fn new(frame_id: u32, window_group: u32) -> Self {
163 FrameToWindowGroupSim {
164 frame_id,
165 window_group,
166 }
167 }
168}
169
170#[derive(Debug, Clone)]
171pub struct IonSim {
172 pub ion_id: u32,
173 pub peptide_id: u32,
174 pub sequence: String,
175 pub charge: i8,
176 pub relative_abundance: f32,
177 pub mobility: f32,
178 pub simulated_spectrum: MzSpectrum,
179 pub scan_distribution: SignalDistribution,
180}
181
182impl IonSim {
183 pub fn new(
184 ion_id: u32,
185 peptide_id: u32,
186 sequence: String,
187 charge: i8,
188 relative_abundance: f32,
189 mobility: f32,
190 simulated_spectrum: MzSpectrum,
191 scan_occurrence: Vec<u32>,
192 scan_abundance: Vec<f32>,
193 ) -> Self {
194 IonSim {
195 ion_id,
196 peptide_id,
197 sequence,
198 charge,
199 relative_abundance,
200 mobility,
201 simulated_spectrum,
202 scan_distribution: SignalDistribution::new(
203 0.0,
204 0.0,
205 0.0,
206 scan_occurrence,
207 scan_abundance,
208 ),
209 }
210 }
211}
212
213#[derive(Debug, Clone)]
214pub struct ScansSim {
215 pub scan: u32,
216 pub mobility: f32,
217}
218
219impl ScansSim {
220 pub fn new(scan: u32, mobility: f32) -> Self {
221 ScansSim { scan, mobility }
222 }
223}
224
225#[derive(Debug, Clone)]
226pub struct FramesSim {
227 pub frame_id: u32,
228 pub time: f32,
229 pub ms_type: i64,
230}
231
232impl FramesSim {
233 pub fn new(frame_id: u32, time: f32, ms_type: i64) -> Self {
234 FramesSim {
235 frame_id,
236 time,
237 ms_type,
238 }
239 }
240 pub fn parse_ms_type(&self) -> MsType {
241 match self.ms_type {
242 0 => MsType::Precursor,
243 8 => MsType::FragmentDda,
244 9 => MsType::FragmentDia,
245 _ => MsType::Unknown,
246 }
247 }
248}
249
250pub struct FragmentIonSim {
251 pub peptide_id: u32,
252 pub ion_id: u32,
253 pub collision_energy: f64,
254 pub charge: i8,
255 pub indices: Vec<u32>,
256 pub values: Vec<f64>,
257}
258
259impl FragmentIonSim {
260 pub fn new(
261 peptide_id: u32,
262 ion_id: u32,
263 collision_energy: f64,
264 charge: i8,
265 indices: Vec<u32>,
266 values: Vec<f64>,
267 ) -> Self {
268 FragmentIonSim {
269 peptide_id,
270 ion_id,
271 charge,
272 collision_energy,
273 indices,
274 values,
275 }
276 }
277
278 pub fn to_dense(&self, length: usize) -> Vec<f64> {
279 let mut dense = vec![0.0; length];
280 for (i, &idx) in self.indices.iter().enumerate() {
281 dense[idx as usize] = self.values[i];
282 }
283 dense
284 }
285}
286
287#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
289pub enum IsotopeTransmissionMode {
290 None,
292 PrecursorScaling,
296 PerFragment,
301}
302
303impl Default for IsotopeTransmissionMode {
304 fn default() -> Self {
305 Self::None
306 }
307}
308
309#[derive(Debug, Clone, Serialize, Deserialize)]
315pub struct IsotopeTransmissionConfig {
316 pub mode: IsotopeTransmissionMode,
318 pub min_probability: f64,
320 pub max_isotopes: usize,
322 pub precursor_survival_min: f64,
324 pub precursor_survival_max: f64,
326}
327
328impl Default for IsotopeTransmissionConfig {
329 fn default() -> Self {
330 Self {
331 mode: IsotopeTransmissionMode::None,
332 min_probability: 0.5,
333 max_isotopes: 10,
334 precursor_survival_min: 0.0,
335 precursor_survival_max: 0.0,
336 }
337 }
338}
339
340impl IsotopeTransmissionConfig {
341 pub fn new(
342 mode: IsotopeTransmissionMode,
343 min_probability: f64,
344 max_isotopes: usize,
345 precursor_survival_min: f64,
346 precursor_survival_max: f64,
347 ) -> Self {
348 Self {
349 mode,
350 min_probability,
351 max_isotopes,
352 precursor_survival_min,
353 precursor_survival_max,
354 }
355 }
356
357 pub fn precursor_scaling(min_probability: f64) -> Self {
359 Self {
360 mode: IsotopeTransmissionMode::PrecursorScaling,
361 min_probability,
362 max_isotopes: 10,
363 precursor_survival_min: 0.0,
364 precursor_survival_max: 0.0,
365 }
366 }
367
368 pub fn per_fragment(min_probability: f64, max_isotopes: usize) -> Self {
370 Self {
371 mode: IsotopeTransmissionMode::PerFragment,
372 min_probability,
373 max_isotopes,
374 precursor_survival_min: 0.0,
375 precursor_survival_max: 0.0,
376 }
377 }
378
379 pub fn has_precursor_survival(&self) -> bool {
381 self.precursor_survival_max > 0.0
382 }
383
384 pub fn is_enabled(&self) -> bool {
386 self.mode != IsotopeTransmissionMode::None
387 }
388}