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 <qlogging.h>
33#include <qobject.h>
34
36
44
48
49void
55
56void
58 const std::map<QString, std::size_t> *nativeId2SpectrumIndexMap)
59{
60 mp_nativeId2SpectrumIndexMap = nativeId2SpectrumIndexMap;
61}
62
63
64void
66{
67 // qDebug();
68
69 mpa_cborReader->enterContainer();
70 bool ms_run_to_read = false;
71
72 while(getExpectedString())
73 {
74 if(m_expectedString == "id")
75 {
77
78 if((m_expectedString == m_xmlMzMlRunId) || (m_xmlMzMlRunId.isEmpty()))
79 {
80 ms_run_to_read = true;
81 }
82 }
83 else if(m_expectedString == "spectrumList")
84 {
85 if(ms_run_to_read)
86 {
88 }
89 else
90 {
91 mpa_cborReader->next();
92 }
93 }
94 else
95 {
96 mpa_cborReader->next();
97 }
98 }
99
100 mpa_cborReader->leaveContainer();
101}
102
103void
105{
106 mpa_cborReader->enterContainer();
107 // We want to iterate in the pwiz-spectrum-list and for each pwiz-spectrum
108 // create a pappso-spectrum (QualifiedMassSpectrum). Once the pappso mass
109 // spectrum has been fully qualified (that is, the member data have been
110 // set), it is transferred to the m_SpectrumCollectionHandlerInterface passed as parameter to this
111 // function for the consumer to do what it wants with it.
112
113 // Does the m_SpectrumCollectionHandlerInterface consuming the mass spectra read from file want
114 // these mass spectra to hold the binary data arrays (mz/i vectors)?
115
116 const bool want_binary_data = m_msRunReadConfig.needPeakList();
117
118
119 // qDebug();
120
121 // We'll need it to perform the looping in the spectrum list.
122 std::size_t spectrum_list_size = 0;
123
124 // qDebug() << "The spectrum list has size:" << spectrum_list_size;
125
126 while(getExpectedString())
127 {
128
129 qDebug() << m_expectedString;
130 if(m_expectedString == "count")
131 {
132 if(mpa_cborReader->isUnsignedInteger())
133 {
134 spectrum_list_size = mpa_cborReader->toUnsignedInteger();
135 mpa_cborReader->next();
136 qDebug() << "spectrum count=" << spectrum_list_size;
137 }
138
139 // Inform the m_SpectrumCollectionHandlerInterface of the spectrum list so that it can
140 // handle feedback to the user.
141 m_SpectrumCollectionHandlerInterface.spectrumListHasSize(spectrum_list_size);
142 }
143 else if(m_expectedString == "spectrum")
144 {
145
146 mpa_cborReader->enterContainer(); // start array
147
148 std::size_t index_count = 0;
149 while(mpa_cborReader->hasNext())
150 {
151 // If the user of this reader instance wants to stop reading the
152 // spectra, then break this loop.
154 {
155 qDebug() << "The operation was cancelled. Breaking the loop.";
156 m_stopParsing = true;
157 return;
158 }
159
160 readSpectrum(index_count, want_binary_data);
161 index_count++;
162 }
163
164 mpa_cborReader->leaveContainer(); // stop array
165 }
166 else
167 {
168 mpa_cborReader->next();
169 }
170 }
171
172
173 qDebug() << "Loading ended";
175
176 mpa_cborReader->leaveContainer();
177 m_stopParsing = true;
178}
179
180
181void
183 bool want_binary_data)
184{
185
186 qDebug() << index_count << " " << want_binary_data;
187 try
188 {
189 Spectrum cbor_spectrum;
190 cbor_spectrum.fromCbor(*mpa_cborReader, want_binary_data);
191 //<spectrum id="controllerType=0 controllerNumber=1 scan=1" index="0"
192 // defaultArrayLength="1552">
193
194
195 // Now, with or without the peak list, we have to craft a qualified mass
196 // spectrum that will hold all the metadata about the data potentially
197 // found in it.
198 QualifiedMassSpectrum qualified_mass_spectrum;
199
200 MassSpectrumId spectrum_id(mcsp_msRunId, cbor_spectrum.index);
201 spectrum_id.setNativeId(cbor_spectrum.id);
202
203 spectrum_id.setSpectrumIndex(cbor_spectrum.index);
204
205 qualified_mass_spectrum.setMassSpectrumId(spectrum_id);
206 qualified_mass_spectrum.setRtInSeconds(cbor_spectrum.getRtInSeconds());
207
208
209 if(cbor_spectrum.precursorList.size() > 0)
210 {
211 qualified_mass_spectrum.setPrecursorNativeId(
212 cbor_spectrum.precursorList.at(0).spectrumRef);
213 if(mp_nativeId2SpectrumIndexMap != nullptr)
214 {
215 auto it =
216 mp_nativeId2SpectrumIndexMap->find(cbor_spectrum.precursorList.at(0).spectrumRef);
217 if(it != mp_nativeId2SpectrumIndexMap->end())
218 {
219 qualified_mass_spectrum.setPrecursorSpectrumIndex(it->second);
220 }
221 }
222
223 for(auto &precursor : cbor_spectrum.precursorList)
224 {
225 // *****************************************************
226 // get isolation window (very simplified)
227 // *****************************************************
228
229 try
230 {
231 // qWarning() << "pappso::MzcborMsRunReader::qualifiedMassSpectrum";
232 qualified_mass_spectrum.setParameterValue(
234 precursor.isolationWindow.getTargetMz());
235
236
237 auto it = precursor.isolationWindow.cvParamMap.find("MS:1000828");
238
239 if(it == precursor.isolationWindow.cvParamMap.end())
240 {
241 throw pappso::ExceptionNotFound(QObject::tr(
242 "isolation window lower offset MS:1000828 not found in cvParam map"));
243 }
244 qualified_mass_spectrum.setParameterValue(
246 it->second.valueDouble);
247
248
249 it = precursor.isolationWindow.cvParamMap.find("MS:1000829");
250
251 if(it == precursor.isolationWindow.cvParamMap.end())
252 {
253 throw pappso::ExceptionNotFound(QObject::tr(
254 "isolation window upper offset MS:1000829 not found in cvParam map"));
255 }
256
257 qualified_mass_spectrum.setParameterValue(
259 it->second.valueDouble);
260 }
261 catch(const pappso::ExceptionNotFound &not_found)
262 {
263 // isolation window not available
264 // throw not_found;
265 }
266 // *****************************************************
267 // end get isolation window (very simplified)
268 // *****************************************************
269
270 PrecursorIonData ion_data;
271 ion_data.mz = precursor.isolationWindow.getTargetMz();
272 for(auto &selected_ion : precursor.selectedIonList)
273 {
274 ion_data.charge = selected_ion.getChargeState();
275
276 bool is_ok;
277 ion_data.intensity = selected_ion.getIntensity(&is_ok);
278 ion_data.mz = selected_ion.getMz();
279
280 qualified_mass_spectrum.appendPrecursorIonData(ion_data);
281 }
282 }
283 }
284
285 qDebug();
286 qualified_mass_spectrum.setMsLevel(cbor_spectrum.getMsLevel());
287
288 qDebug();
289 qualified_mass_spectrum.setEmptyMassSpectrum(!cbor_spectrum.defaultArrayLength);
290
291 if(cbor_spectrum.binaryDataArrayList.size() == 2)
292 {
293 qDebug();
294 MassSpectrumSPtr mass_spectrum_sp = std::make_shared<MassSpectrum>();
295 qDebug();
296 cbor_spectrum.decodeTrace(*(mass_spectrum_sp.get()));
297 qDebug();
298 qualified_mass_spectrum.setMassSpectrumSPtr(mass_spectrum_sp);
299 qDebug();
300 }
301
302 qDebug() << "spectrum_id.getNativeId()=" << spectrum_id.getNativeId();
303 qDebug() << "rt=" << qualified_mass_spectrum.getRtInSeconds();
304 qDebug() << "mslevel=" << qualified_mass_spectrum.getMsLevel();
305
306 if(m_msRunReadConfig.acceptMsLevel(qualified_mass_spectrum.getMsLevel()))
307 {
308 if(m_msRunReadConfig.acceptRetentionTimeInSeconds(
309 qualified_mass_spectrum.getRtInSeconds()))
310 {
311
312 if(qualified_mass_spectrum.getMassSpectrumId().getSpectrumIndex() ==
313 std::numeric_limits<std::size_t>::max())
314 {
316 QObject::tr("ERROR in %1 spectrum index not initialised").arg(__FUNCTION__));
317 }
318 m_SpectrumCollectionHandlerInterface.setQualifiedMassSpectrum(
319 qualified_mass_spectrum);
320 }
321 }
322
323 /*
324 *
325 <cvParam cvRef="MS" accession="MS:1000579" value="" name="MS1 spectrum" />
326 <cvParam cvRef="MS" accession="MS:1000130" value="" name="positive scan" />
327 <cvParam cvRef="MS" accession="MS:1000285" value="17377980" name="total ion current" />
328 <cvParam cvRef="MS" accession="MS:1000127" value="" name="centroid spectrum" />
329 <cvParam cvRef="MS" accession="MS:1000504" value="519.138854980469" name="base peak m/z"
330 unitAccession="MS:1000040" unitName="m/z" unitCvRef="MS" />
331 <cvParam cvRef="MS"
332 accession="MS:1000505" value="1702482.375" name="base peak intensity"
333 unitAccession="MS:1000131" unitName="number of detector counts" unitCvRef="MS" /> <cvParam
334 cvRef="MS" accession="MS:1000528" value="400.153411865234" name="lowest observed m/z"
335 unitAccession="MS:1000040" unitName="m/z" unitCvRef="MS" /> <cvParam cvRef="MS"
336 accession="MS:1000527" value="1013.12335205078" name="highest observed m/z"
337 unitAccession="MS:1000040" unitName="m/z" unitCvRef="MS" /> <scanList count="1"> <cvParam
338 cvRef="MS" accession="MS:1000795" value="" name="no combination" /> <scan
339 instrumentConfigurationRef="IC1"> <cvParam cvRef="MS" accession="MS:1000016"
340 value="0.0048758833" name="scan start time" unitAccession="UO:0000031" unitName="minute"
341 unitCvRef="UO" /> <cvParam cvRef="MS" accession="MS:1000512" value="FTMS + p NSI Full lock ms
342 [400.00-1400.00]" name="filter string" /> <cvParam cvRef="MS" accession="MS:1000927"
343 value="250" name="ion injection time" unitAccession="UO:0000028" unitName="millisecond"
344 unitCvRef="UO" /> <scanWindowList count="1"> <scanWindow> <cvParam cvRef="MS"
345 accession="MS:1000501" value="400" name="scan window lower limit" unitAccession="MS:1000040"
346 unitName="m/z" unitCvRef="MS" /> <cvParam cvRef="MS" accession="MS:1000500" value="1400"
347 name="scan window upper limit" unitAccession="MS:1000040" unitName="m/z" unitCvRef="MS" />
348 </scanWindow>
349 </scanWindowList>
350 </scan>
351 </scanList>
352 <binaryDataArrayList count="2">
353 */
354
355 // qDebug();
356 // Get the native pwiz-spectrum from the spectrum list.
357 // Note that this pointer is a shared pointer from pwiz.
358 /*
359 pwiz::msdata::SpectrumPtr native_pwiz_spectrum_sp =
360 getPwizSpectrumPtr(spectrum_list_p.get(), iter, want_binary_data);
361 // qDebug();
362
363 // Instantiate the mass spectrum id that will hold critical information
364 // like the the native id string and the spectrum index.
365
366 MassSpectrumId massSpectrumId(mcsp_msRunId, iter);
367
368 // qDebug();
369 // Get the spectrum native id as a QString to store it in the mass
370 // spectrum id class. This is will allow later to refer to the same
371 // spectrum starting back from the file.
372
373 QString native_id = QString::fromStdString(native_pwiz_spectrum_sp->id);
374 massSpectrumId.setNativeId(native_id);
375
376 // Finally, instantiate the qualified mass spectrum with its id. This
377 // function will continue performing pappso-spectrum detailed
378 // qualification.
379
380 bool ok = false;
381
382 QualifiedMassSpectrum qualified_mass_spectrum = qualifiedMassSpectrumFromPwizSpectrumPtr(
383 massSpectrumId, native_pwiz_spectrum_sp.get(), want_binary_data, ok);
384
385 if(!ok)
386 {
387 // qDebug() << "Encountered a mass spectrum for which the returned "
388 //"status is bad.";
389 continue;
390 }
391
392 // qDebug();
393 // Before handing the mass spectrum out to the m_SpectrumCollectionHandlerInterface, see if
394 // the native mass spectrum was empty or not.
395
396 // if(!native_pwiz_spectrum_sp->defaultArrayLength)
397 // qDebug() << "The mass spectrum has not defaultArrayLength";
398
399 qualified_mass_spectrum.setEmptyMassSpectrum(!native_pwiz_spectrum_sp->defaultArrayLength);
400
401 // The m_SpectrumCollectionHandlerInterface will receive the index of the mass spectrum in
402 the
403 // current run via the mass spectrum id member datum.
404
405 // qDebug();
406 */
407 }
408 catch(pappso::PappsoException &error)
409 {
411 QObject::tr("ERROR reading spectrum index %1 :\%2").arg(index_count).arg(error.qwhat()));
412 }
413}
414
415std::map<QString, pappso::cbor::mzcbor::CvParam>
417{
418 std::map<QString, CvParam> cv_params;
419 mpa_cborReader->enterContainer();
420 while(getExpectedString())
421 {
422 qDebug() << m_expectedString;
423 if(m_expectedString == "cvParam")
424 {
425 cv_params = getCvParamsMap();
426 }
427 else
428 {
429 mpa_cborReader->next();
430 }
431 }
432 mpa_cborReader->leaveContainer();
433 return cv_params;
434}
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 setParameterValue(QualifiedMassSpectrumParameter parameter, const QVariant &value)
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
@ IsolationWindowTargetMz
Isolation m/z value isolation window target m/z (thomson).
@ IsolationWindowUpperOffset
isolation window upper offset (thomson)
@ IsolationWindowLowerOffset
isolation window lower offset (thomson)
std::shared_ptr< MassSpectrum > MassSpectrumSPtr
PSI spectrum object for mzML/mzCBOR.
std::vector< Precursor > precursorList
Definition spectrum.h:89
void fromCbor(CborStreamReader &reader, bool want_binary_data)
fill the structure reading data from a CBOR stream
Definition spectrum.cpp:43
void decodeTrace(pappso::Trace &trace) const
Definition spectrum.cpp:356
std::vector< BinaryDataArray > binaryDataArrayList
Definition spectrum.h:90