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}