libpappsomspp
Library for mass spectrometry
Loading...
Searching...
No Matches
mzcborspectrumcollectionreader.cpp
Go to the documentation of this file.
1/**
2 * \file pappsomspp/core/processing/cbor/mzcbor/mzcborspectrumcollectionreader.cpp
3 * \date 22/11/2025
4 * \author Olivier Langella
5 * \brief read mzcbor for spectrum collection m_SpectrumCollectionHandlerInterface
6 */
7
8/*******************************************************************************
9 * Copyright (c) 2025 Olivier Langella <Olivier.Langella@universite-paris-saclay.fr>.
10 *
11 * This file is part of PAPPSOms-tools.
12 *
13 * PAPPSOms-tools is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * PAPPSOms-tools is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with PAPPSOms-tools. If not, see <http://www.gnu.org/licenses/>.
25 *
26 ******************************************************************************/
27
28
30#include "spectrum.h"
32#include <qobject.h>
33
34
42
46
47void
53
54void
56 const std::map<QString, std::size_t> *nativeId2SpectrumIndexMap)
57{
58 mp_nativeId2SpectrumIndexMap = nativeId2SpectrumIndexMap;
59}
60
61
62void
64{
65 // qDebug();
66
67 mpa_cborReader->enterContainer();
68 bool ms_run_to_read = false;
69
70 while(getExpectedString())
71 {
72 if(m_expectedString == "id")
73 {
75
76 if((m_expectedString == m_xmlMzMlRunId) || (m_xmlMzMlRunId.isEmpty()))
77 {
78 ms_run_to_read = true;
79 }
80 }
81 else if(m_expectedString == "spectrumList")
82 {
83 if(ms_run_to_read)
84 {
86 }
87 else
88 {
89 mpa_cborReader->next();
90 }
91 }
92 else
93 {
94 mpa_cborReader->next();
95 }
96 }
97
98 mpa_cborReader->leaveContainer();
99}
100
101void
103{
104 mpa_cborReader->enterContainer();
105 // We want to iterate in the pwiz-spectrum-list and for each pwiz-spectrum
106 // create a pappso-spectrum (QualifiedMassSpectrum). Once the pappso mass
107 // spectrum has been fully qualified (that is, the member data have been
108 // set), it is transferred to the m_SpectrumCollectionHandlerInterface passed as parameter to this
109 // function for the consumer to do what it wants with it.
110
111 // Does the m_SpectrumCollectionHandlerInterface consuming the mass spectra read from file want
112 // these mass spectra to hold the binary data arrays (mz/i vectors)?
113
114 const bool want_binary_data = m_msRunReadConfig.needPeakList();
115
116
117 // qDebug();
118
119 // We'll need it to perform the looping in the spectrum list.
120 std::size_t spectrum_list_size = 0;
121
122 // qDebug() << "The spectrum list has size:" << spectrum_list_size;
123
124 while(getExpectedString())
125 {
126
127 qDebug() << m_expectedString;
128 if(m_expectedString == "count")
129 {
130 if(mpa_cborReader->isUnsignedInteger())
131 {
132 spectrum_list_size = mpa_cborReader->toUnsignedInteger();
133 mpa_cborReader->next();
134 qDebug() << "spectrum count=" << spectrum_list_size;
135 }
136
137 // Inform the m_SpectrumCollectionHandlerInterface of the spectrum list so that it can
138 // handle feedback to the user.
139 m_SpectrumCollectionHandlerInterface.spectrumListHasSize(spectrum_list_size);
140 }
141 else if(m_expectedString == "spectrum")
142 {
143
144 mpa_cborReader->enterContainer(); // start array
145
146 std::size_t index_count = 0;
147 while(mpa_cborReader->hasNext())
148 {
149 // If the user of this reader instance wants to stop reading the
150 // spectra, then break this loop.
152 {
153 qDebug() << "The operation was cancelled. Breaking the loop.";
154 m_stopParsing = true;
155 return;
156 }
157
158 readSpectrum(index_count, want_binary_data);
159 index_count++;
160 }
161
162 mpa_cborReader->leaveContainer(); // stop array
163 }
164 else
165 {
166 mpa_cborReader->next();
167 }
168 }
169
170
171 qDebug() << "Loading ended";
173
174 mpa_cborReader->leaveContainer();
175 m_stopParsing = true;
176}
177
178
179void
181 bool want_binary_data)
182{
183
184 qDebug() << index_count << " " << want_binary_data;
185 try
186 {
187 Spectrum cbor_spectrum;
188 cbor_spectrum.fromCbor(*mpa_cborReader, want_binary_data);
189 //<spectrum id="controllerType=0 controllerNumber=1 scan=1" index="0"
190 // defaultArrayLength="1552">
191
192
193 // Now, with or without the peak list, we have to craft a qualified mass
194 // spectrum that will hold all the metadata about the data potentially
195 // found in it.
196 QualifiedMassSpectrum qualified_mass_spectrum;
197
198 MassSpectrumId spectrum_id(mcsp_msRunId, cbor_spectrum.index);
199 spectrum_id.setNativeId(cbor_spectrum.id);
200
201 spectrum_id.setSpectrumIndex(cbor_spectrum.index);
202
203 qualified_mass_spectrum.setMassSpectrumId(spectrum_id);
204 qualified_mass_spectrum.setRtInSeconds(cbor_spectrum.getRtInSeconds());
205
206
207 if(cbor_spectrum.precursorList.size() > 0)
208 {
209 qualified_mass_spectrum.setPrecursorNativeId(
210 cbor_spectrum.precursorList.at(0).spectrumRef);
211 if(mp_nativeId2SpectrumIndexMap != nullptr)
212 {
213 auto it =
214 mp_nativeId2SpectrumIndexMap->find(cbor_spectrum.precursorList.at(0).spectrumRef);
215 if(it != mp_nativeId2SpectrumIndexMap->end())
216 {
217 qualified_mass_spectrum.setPrecursorSpectrumIndex(it->second);
218 }
219 }
220
221 for(auto &precursor : cbor_spectrum.precursorList)
222 {
223 PrecursorIonData ion_data;
224 ion_data.mz = precursor.isolationWindow.getTargetMz();
225 for(auto &selected_ion : precursor.selectedIonList)
226 {
227 ion_data.charge = selected_ion.getChargeState();
228
229 bool is_ok;
230 ion_data.intensity = selected_ion.getIntensity(&is_ok);
231 ion_data.mz = selected_ion.getMz();
232
233 qualified_mass_spectrum.appendPrecursorIonData(ion_data);
234 }
235 }
236 }
237
238
239 qualified_mass_spectrum.setMsLevel(cbor_spectrum.getMsLevel());
240 qualified_mass_spectrum.setEmptyMassSpectrum(!cbor_spectrum.defaultArrayLength);
241
242 if(cbor_spectrum.binaryDataArrayList.size() == 2)
243 {
244 MassSpectrumSPtr mass_spectrum_sp = std::make_shared<MassSpectrum>();
245 cbor_spectrum.decodeTrace(*(mass_spectrum_sp.get()));
246 qualified_mass_spectrum.setMassSpectrumSPtr(mass_spectrum_sp);
247 }
248
249 qDebug() << "spectrum_id.getNativeId()=" << spectrum_id.getNativeId();
250 qDebug() << "rt=" << qualified_mass_spectrum.getRtInSeconds();
251 qDebug() << "mslevel=" << qualified_mass_spectrum.getMsLevel();
252
253 if(m_msRunReadConfig.acceptMsLevel(qualified_mass_spectrum.getMsLevel()))
254 {
255 if(m_msRunReadConfig.acceptRetentionTimeInSeconds(
256 qualified_mass_spectrum.getRtInSeconds()))
257 {
258
259 if(qualified_mass_spectrum.getMassSpectrumId().getSpectrumIndex() ==
260 std::numeric_limits<std::size_t>::max())
261 {
263 QObject::tr("ERROR in %1 spectrum index not initialised").arg(__FUNCTION__));
264 }
265 m_SpectrumCollectionHandlerInterface.setQualifiedMassSpectrum(
266 qualified_mass_spectrum);
267 }
268 }
269
270 /*
271 *
272 <cvParam cvRef="MS" accession="MS:1000579" value="" name="MS1 spectrum" />
273 <cvParam cvRef="MS" accession="MS:1000130" value="" name="positive scan" />
274 <cvParam cvRef="MS" accession="MS:1000285" value="17377980" name="total ion current" />
275 <cvParam cvRef="MS" accession="MS:1000127" value="" name="centroid spectrum" />
276 <cvParam cvRef="MS" accession="MS:1000504" value="519.138854980469" name="base peak m/z"
277 unitAccession="MS:1000040" unitName="m/z" unitCvRef="MS" />
278 <cvParam cvRef="MS"
279 accession="MS:1000505" value="1702482.375" name="base peak intensity"
280 unitAccession="MS:1000131" unitName="number of detector counts" unitCvRef="MS" /> <cvParam
281 cvRef="MS" accession="MS:1000528" value="400.153411865234" name="lowest observed m/z"
282 unitAccession="MS:1000040" unitName="m/z" unitCvRef="MS" /> <cvParam cvRef="MS"
283 accession="MS:1000527" value="1013.12335205078" name="highest observed m/z"
284 unitAccession="MS:1000040" unitName="m/z" unitCvRef="MS" /> <scanList count="1"> <cvParam
285 cvRef="MS" accession="MS:1000795" value="" name="no combination" /> <scan
286 instrumentConfigurationRef="IC1"> <cvParam cvRef="MS" accession="MS:1000016"
287 value="0.0048758833" name="scan start time" unitAccession="UO:0000031" unitName="minute"
288 unitCvRef="UO" /> <cvParam cvRef="MS" accession="MS:1000512" value="FTMS + p NSI Full lock ms
289 [400.00-1400.00]" name="filter string" /> <cvParam cvRef="MS" accession="MS:1000927"
290 value="250" name="ion injection time" unitAccession="UO:0000028" unitName="millisecond"
291 unitCvRef="UO" /> <scanWindowList count="1"> <scanWindow> <cvParam cvRef="MS"
292 accession="MS:1000501" value="400" name="scan window lower limit" unitAccession="MS:1000040"
293 unitName="m/z" unitCvRef="MS" /> <cvParam cvRef="MS" accession="MS:1000500" value="1400"
294 name="scan window upper limit" unitAccession="MS:1000040" unitName="m/z" unitCvRef="MS" />
295 </scanWindow>
296 </scanWindowList>
297 </scan>
298 </scanList>
299 <binaryDataArrayList count="2">
300 */
301
302 // qDebug();
303 // Get the native pwiz-spectrum from the spectrum list.
304 // Note that this pointer is a shared pointer from pwiz.
305 /*
306 pwiz::msdata::SpectrumPtr native_pwiz_spectrum_sp =
307 getPwizSpectrumPtr(spectrum_list_p.get(), iter, want_binary_data);
308 // qDebug();
309
310 // Instantiate the mass spectrum id that will hold critical information
311 // like the the native id string and the spectrum index.
312
313 MassSpectrumId massSpectrumId(mcsp_msRunId, iter);
314
315 // qDebug();
316 // Get the spectrum native id as a QString to store it in the mass
317 // spectrum id class. This is will allow later to refer to the same
318 // spectrum starting back from the file.
319
320 QString native_id = QString::fromStdString(native_pwiz_spectrum_sp->id);
321 massSpectrumId.setNativeId(native_id);
322
323 // Finally, instantiate the qualified mass spectrum with its id. This
324 // function will continue performing pappso-spectrum detailed
325 // qualification.
326
327 bool ok = false;
328
329 QualifiedMassSpectrum qualified_mass_spectrum = qualifiedMassSpectrumFromPwizSpectrumPtr(
330 massSpectrumId, native_pwiz_spectrum_sp.get(), want_binary_data, ok);
331
332 if(!ok)
333 {
334 // qDebug() << "Encountered a mass spectrum for which the returned "
335 //"status is bad.";
336 continue;
337 }
338
339 // qDebug();
340 // Before handing the mass spectrum out to the m_SpectrumCollectionHandlerInterface, see if
341 // the native mass spectrum was empty or not.
342
343 // if(!native_pwiz_spectrum_sp->defaultArrayLength)
344 // qDebug() << "The mass spectrum has not defaultArrayLength";
345
346 qualified_mass_spectrum.setEmptyMassSpectrum(!native_pwiz_spectrum_sp->defaultArrayLength);
347
348 // The m_SpectrumCollectionHandlerInterface will receive the index of the mass spectrum in
349 the
350 // current run via the mass spectrum id member datum.
351
352 // qDebug();
353 */
354 }
355 catch(pappso::PappsoException &error)
356 {
358 QObject::tr("ERROR reading spectrum index %1 :\%2").arg(index_count).arg(error.qwhat()));
359 }
360}
361
362std::map<QString, pappso::cbor::mzcbor::CvParam>
364{
365 std::map<QString, CvParam> cv_params;
366 mpa_cborReader->enterContainer();
367 while(getExpectedString())
368 {
369 qDebug() << m_expectedString;
370 if(m_expectedString == "cvParam")
371 {
372 cv_params = getCvParamsMap();
373 }
374 else
375 {
376 mpa_cborReader->next();
377 }
378 }
379 mpa_cborReader->leaveContainer();
380 return cv_params;
381}
void setNativeId(const QString &native_id)
std::size_t getSpectrumIndex() const
void setSpectrumIndex(std::size_t index)
const QString & getNativeId() const
virtual const QString & qwhat() const
Class representing a fully specified mass spectrum.
uint getMsLevel() const
Get the mass spectrum level.
void setPrecursorNativeId(const QString &native_id)
Set the scan native id of the precursor ion.
void appendPrecursorIonData(const PrecursorIonData &precursor_ion_data)
const MassSpectrumId & getMassSpectrumId() const
Get the MassSpectrumId.
void setMassSpectrumId(const MassSpectrumId &iD)
Set the MassSpectrumId.
void setMsLevel(uint ms_level)
Set the mass spectrum level.
void setPrecursorSpectrumIndex(std::size_t precursor_scan_num)
Set the scan number of the precursor ion.
void setMassSpectrumSPtr(MassSpectrumSPtr massSpectrum)
Set the MassSpectrumSPtr.
void setRtInSeconds(pappso_double rt)
Set the retention time in seconds.
pappso_double getRtInSeconds() const
Get the retention time in seconds.
void setEmptyMassSpectrum(bool is_empty_mass_spectrum)
interface to collect spectrums from the MsRunReader class
std::map< QString, CvParam > getCvParamsMap()
read the array containing cvParams to give accessions and values
SpectrumCollectionHandlerInterface & m_SpectrumCollectionHandlerInterface
void readSpectrum(std::size_t index_count, bool want_binary_data)
read each spectrum in the targeted msrun (msrunId)
MzcborSpectrumCollectionReader(const MsRunReadConfig &config, SpectrumCollectionHandlerInterface &handler)
void setNativeId2SpectrumIndexMapPtr(const std::map< QString, std::size_t > *nativeId2SpectrumIndexMap)
void readSpectrumListAndLeave()
only the spectrum list of targeted msrun, then stop parsing
const std::map< QString, std::size_t > * mp_nativeId2SpectrumIndexMap
virtual void readMsrun() override
read only the targeted msrun
read mzcbor for spectrum collection handler
std::shared_ptr< const MsRunId > MsRunIdCstSPtr
Definition msrunid.h:46
std::shared_ptr< MassSpectrum > MassSpectrumSPtr
PSI spectrum object for mzML/mzCBOR.
std::vector< Precursor > precursorList
Definition spectrum.h:81
void fromCbor(CborStreamReader &reader, bool want_binary_data)
fill the structure reading data from a CBOR stream
Definition spectrum.cpp:40
void decodeTrace(pappso::Trace &trace) const
Definition spectrum.cpp:353
std::vector< BinaryDataArray > binaryDataArrayList
Definition spectrum.h:82