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