libpappsomspp
Library for mass spectrometry
mzintegrationparams.cpp
Go to the documentation of this file.
1/* BEGIN software license
2 *
3 * msXpertSuite - mass spectrometry software suite
4 * -----------------------------------------------
5 * Copyright(C) 2009,...,2018 Filippo Rusconi
6 *
7 * http://www.msxpertsuite.org
8 *
9 * This file is part of the msXpertSuite project.
10 *
11 * The msXpertSuite project is the successor of the massXpert project. This
12 * project now includes various independent modules:
13 *
14 * - massXpert, model polymer chemistries and simulate mass spectrometric data;
15 * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
16 *
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 *
30 * END software license
31 */
32
33
34/////////////////////// StdLib includes
35#include <map>
36#include <cmath>
37
38
39/////////////////////// Qt includes
40#include <QDebug>
41#include <QString>
42#include <QFile>
43#include <QDateTime>
44
45
46/////////////////////// pappsomspp includes
47#include "../../utils.h"
48#include "../../massspectrum/massspectrum.h"
49
50
51/////////////////////// Local includes
52#include "mzintegrationparams.h"
53
54
56 qRegisterMetaType<pappso::MzIntegrationParams>("pappso::MzIntegrationParams");
58 qRegisterMetaType<pappso::MzIntegrationParams *>(
59 "pappso::MzIntegrationParams *");
60
61
62namespace pappso
63{
64
65
66//! Map relating the BinningType to a textual representation
67std::map<BinningType, QString> binningTypeMap{
68 {BinningType::NONE, "NONE"},
69 {BinningType::DATA_BASED, "DATA_BASED"},
70 {BinningType::ARBITRARY, "ARBITRARY"}};
71
72
74{
77}
78
79
82 BinningType binningType,
83 int decimalPlaces,
84 pappso::PrecisionPtr precisionPtr,
85 bool applyMzShift,
87 bool removeZeroValDataPoints)
88 : m_smallestMz(minMz),
89 m_greatestMz(maxMz),
90 m_binningType(binningType),
91 m_decimalPlaces(decimalPlaces),
92 mp_precision(precisionPtr),
93 m_applyMzShift(applyMzShift),
94 m_mzShift(mzShift),
95 m_removeZeroValDataPoints(removeZeroValDataPoints)
96{
97 if(mp_precision == nullptr)
99}
100
101
103 : m_smallestMz(other.m_smallestMz),
104 m_greatestMz(other.m_greatestMz),
105 m_binningType(other.m_binningType),
106 m_decimalPlaces(other.m_decimalPlaces),
107 mp_precision(other.mp_precision),
108 m_applyMzShift(other.m_applyMzShift),
109 m_mzShift(other.m_mzShift),
110 m_removeZeroValDataPoints(other.m_removeZeroValDataPoints)
111{
112 if(mp_precision == nullptr)
114}
115
116
118{
119}
120
121
124{
125 if(this == &other)
126 return *this;
127
131
133
135 if(mp_precision == nullptr)
137
139 m_mzShift = other.m_mzShift;
141
142 return *this;
143}
144
145
146void
148{
149 m_smallestMz = value;
150}
151
152
153void
155{
156 m_smallestMz = m_smallestMz > value ? value : m_smallestMz;
157}
158
159
162{
163 return m_smallestMz;
164}
165
166
167void
169{
170 m_greatestMz = value;
171}
172
173
174void
176{
177 m_greatestMz = m_greatestMz < value ? value : m_greatestMz;
178}
179
180
183{
184 return m_greatestMz;
185}
186
187void
189{
190 m_binningType = binningType;
191}
192
195{
196 return m_binningType;
197}
198
199void
201{
202 m_decimalPlaces = decimal_places;
203}
204
205
206int
208{
209 return m_decimalPlaces;
210}
211
212void
214{
215 mp_precision = precisionPtr;
216
217 if(mp_precision == nullptr)
219}
220
223{
224 return mp_precision;
225}
226
227
228void
230{
231 m_applyMzShift = applyMzShift;
232}
233
234
235bool
237{
238 return m_applyMzShift;
239}
240
241
242void
244{
245 m_removeZeroValDataPoints = removeOrNot;
246}
247
248
249bool
251{
253}
254
255
256void
258{
259 m_mzShift = value;
260}
261
262
263double
265{
266 return m_mzShift;
267}
268
269
270//! Reset the instance to default values.
271void
273{
274 m_smallestMz = std::numeric_limits<double>::min();
275 m_greatestMz = std::numeric_limits<double>::min();
277
278 // Special case for this member datum
280
281 m_applyMzShift = false;
282 m_mzShift = 0;
284}
285
286
287bool
289{
290 int errors = 0;
291
293 {
294 // qDebug() << "m_smallestMz:" << m_smallestMz;
295 // qDebug() << "smallest is max:" << (m_smallestMz ==
296 // std::numeric_limits<double>::max());
297
298 errors += (m_smallestMz == std::numeric_limits<double>::max() ? 1 : 0);
299
300 // qDebug() << "m_greatestMz:" << m_greatestMz;
301 // qDebug() << "greatest is min:" << (m_greatestMz ==
302 // std::numeric_limits<double>::min());
303 errors += (m_greatestMz == std::numeric_limits<double>::min() ? 1 : 0);
304
305 // if(mp_precision != nullptr)
306 // qDebug() << mp_precision->toString();
307
308 errors += (mp_precision == nullptr ? 1 : 0);
309 }
310
311 if(errors)
312 {
313 qDebug()
314 << "The m/z integration parameters are not valid or do not apply...";
315 }
316
317 return !errors;
318}
319
320
321bool
323{
324 return (m_smallestMz != std::numeric_limits<double>::max()) &&
325 (m_greatestMz != std::numeric_limits<double>::min());
326}
327
328
329std::vector<double>
331{
332
333 // qDebug();
334
335 std::vector<double> bins;
336
338 {
339 // If no binning is to be performed, fine.
340 return bins;
341 }
343 {
344 // Use only data in the MzIntegrationParams member data.
345 return createArbitraryBins();
346 }
348 {
349 // qDebug();
350
351 qFatal("Programming error.");
352 }
353
354 return bins;
355}
356
357
358std::vector<double>
360{
361
362 // qDebug();
363
364 std::vector<double> bins;
365
367 {
368 // If no binning is to be performed, fine.
369 return bins;
370 }
372 {
373 // Use only data in the MzIntegrationParams member data.
374 return createArbitraryBins();
375 }
377 {
378 // qDebug();
379
380 // Use the first spectrum to perform the data-based bins
381
382 return createDataBasedBins(mass_spectrum_csp);
383 }
384
385 return bins;
386}
387
388
389std::vector<double>
391{
392
393 // qDebug();
394
395 // Now starts the tricky stuff. Depending on how the binning has been
396 // configured, we need to take diverse actions.
397
398 // qDebug() << "Bin specification:" << mp_precision->toString();
399
402
403 // qDebug() << QString::asprintf("min_mz: %.6f\n", min_mz)
404 //<< QString::asprintf("max_mz: %.6f\n", max_mz);
405
406 pappso::pappso_double binSize = mp_precision->delta(min_mz);
407
408 // qDebug() << QString::asprintf(
409 //"binSize is the precision delta for min_mz: %.6f\n", binSize);
410
411 // Only compute the decimal places if they were not configured already.
412 if(m_decimalPlaces == -1)
413 {
414 qDebug() << "Now checking how many decimal places are needed.";
415
416 // We want as many decimal places as there are 0s between the integral
417 // part of the double and the first non-0 cipher. For example, if
418 // binSize is 0.004, zero decimals is 2 and m_decimalPlaces is set to 3,
419 // because we want decimals up to 4 included.
420
422
423 //qDebug() << "With binSize" << binSize
424 //<< " m_decimalPlaces was computed to be:" << m_decimalPlaces;
425 }
426 //else
427 //qDebug() << "m_decimalPlaces: " << m_decimalPlaces;
428
429 // Now that we have defined the value of m_decimalPlaces, let's use that
430 // value.
431
432 double first_mz = ceil((min_mz * std::pow(10, m_decimalPlaces)) - 0.49) /
433 pow(10, m_decimalPlaces);
434 double last_mz =
435 ceil((max_mz * pow(10, m_decimalPlaces)) - 0.49) / pow(10, m_decimalPlaces);
436
437 // qDebug() << "After having accounted for the decimals, new min/max values:"
438 //<< QString::asprintf("Very first data point: %.6f\n", first_mz)
439 //<< QString::asprintf("Very last data point to reach: %.6f\n",
440 // last_mz);
441
442 // Instanciate the vector of mz double_s that we'll feed with the bins.
443
444 std::vector<pappso::pappso_double> bins;
445
446 // Store that very first value for later use in the loop.
447 // The bins are notking more than:
448 //
449 // 1. The first mz (that is the smallest mz value found in all the spectra
450 // 2. A sequence of mz values corresponding to that first mz value
451 // incremented by the bin size.
452
453 // Seed the root of the bin vector with the first mz value rounded above as
454 // requested.
455 pappso::pappso_double previous_mz_bin = first_mz;
456
457 bins.push_back(previous_mz_bin);
458
459 // Now continue adding mz values until we have reached the end of the
460 // spectrum, that is the max_mz value, as converted using the decimals to
461 // last_mz.
462
463 // debugCount value used below for debugging purposes.
464 // int debugCount = 0;
465
466 while(previous_mz_bin <= last_mz)
467 {
468
469 // qDebug() << "Now starting the bin creation loop.";
470
471 // Calculate dynamically the precision delta according to the current mz
472 // value.
473
474 // double precision_delta = mp_precision->delta(previous_mz_bin);
475 // qDebug() << "precision_delta: " << precision_delta;
476
477 double current_mz =
478 previous_mz_bin + mp_precision->delta(previous_mz_bin);
479
480 // qDebug() << QString::asprintf(
481 //"previous_mzBin: %.6f and current_mz: %.6f\n",
482 // previous_mz_bin,
483 // current_mz);
484
485 // Now apply on the obtained mz value the decimals that were either set
486 // or computed earlier.
487
488 double current_rounded_mz =
489 ceil((current_mz * pow(10, m_decimalPlaces)) - 0.49) /
490 pow(10, m_decimalPlaces);
491
492 // qDebug() << QString::asprintf(
493 //"current_mz: %.6f and current_rounded_mz: %.6f and previous_mzBin "
494 //": % .6f\n ",
495 // current_mz,
496 // current_rounded_mz,
497 // previous_mz_bin);
498
499 // If rounding makes the new value identical to the previous one, then
500 // that means that we need to decrease roughness.
501
502 if(current_rounded_mz == previous_mz_bin)
503 {
505
506 current_rounded_mz =
507 ceil((current_mz * pow(10, m_decimalPlaces)) - 0.49) /
508 pow(10, m_decimalPlaces);
509
510 // qDebug().noquote()
511 //<< "Had to increment decimal places by one while creating the bins "
512 //"in BinningType::ARBITRARY mode..";
513 }
514
515 bins.push_back(current_rounded_mz);
516
517 // Use the local_mz value for the storage of the previous mz bin.
518 previous_mz_bin = current_rounded_mz;
519 }
520
521
522#if 0
523
524 QString fileName = "/tmp/massSpecArbitraryBins.txt-at-" +
525 QDateTime::currentDateTime().toString("yyyyMMdd-HH-mm-ss");
526
527 qDebug() << "Writing the list of bins setup in the "
528 "mass spectrum in file "
529 << fileName;
530
531 QFile file(fileName);
532 file.open(QIODevice::WriteOnly);
533
534 QTextStream fileStream(&file);
535
536 for(auto &&bin : bins)
537 fileStream << QString("%1\n").arg(bin, 0, 'f', 10);
538
539 fileStream.flush();
540 file.close();
541
542#endif
543
544 // qDebug() << "Prepared bins with " << bins.size() << "elements."
545 //<< "starting with mz" << bins.front() << "ending with mz"
546 //<< bins.back();
547
548 return bins;
549}
550
551
552std::vector<double>
554 pappso::MassSpectrumCstSPtr mass_spectrum_csp)
555{
556 // qDebug();
557
558 // The bins in *this mass spectrum must be calculated starting from the
559 // data in the mass_spectrum_csp parameter.
560
561 // Instanciate the vector of mz double_s that we'll feed with the bins.
562
563 std::vector<pappso::pappso_double> bins;
564
565 if(mass_spectrum_csp->size() < 2)
566 return bins;
567
568 // Make sure the spectrum is sorted, as this functions takes for granted
569 // that the DataPoint instances are sorted in ascending x (== mz) value
570 // order.
571 pappso::MassSpectrum local_mass_spectrum = *mass_spectrum_csp;
572 local_mass_spectrum.sortMz();
573
575
576 // qDebug() << "The min_mz:" << min_mz;
577
578 if(m_decimalPlaces != -1)
579 min_mz = ceil((min_mz * pow(10, m_decimalPlaces)) - 0.49) /
580 pow(10, m_decimalPlaces);
581
582
583 // Two values for the definition of a MassSpectrumBin.
584
585 // The first value of the mz range that defines the bin. This value is part
586 // of the bin.
587 pappso::pappso_double start_mz_in = min_mz;
588
589 // The second value of the mz range that defines the bin. This value is
590 // *not* part of the bin.
591 pappso::pappso_double end_mz_out;
592
593 std::vector<pappso::DataPoint>::const_iterator it =
594 local_mass_spectrum.begin();
595
596 pappso::pappso_double prev_mz = it->x;
597
598 if(m_decimalPlaces != -1)
599 prev_mz = ceil((prev_mz * pow(10, m_decimalPlaces)) - 0.49) /
600 pow(10, m_decimalPlaces);
601
602 ++it;
603
604 while(it != local_mass_spectrum.end())
605 {
606 pappso::pappso_double next_mz = it->x;
607
608 if(m_decimalPlaces != -1)
609 next_mz = ceil((next_mz * pow(10, m_decimalPlaces)) - 0.49) /
610 pow(10, m_decimalPlaces);
611
612 pappso::pappso_double step = next_mz - prev_mz;
613 end_mz_out = start_mz_in + step;
614
615 if(m_decimalPlaces != -1)
616 end_mz_out = ceil((end_mz_out * pow(10, m_decimalPlaces)) - 0.49) /
617 pow(10, m_decimalPlaces);
618
619 // The data point that is crafted has a 0 y-value. The binning must
620 // indeed not create artificial intensity data.
621
622 // qDebug() << "Pushing back bin:" << start_mz_in << end_mz_out;
623
624 bins.push_back(start_mz_in);
625
626 // Prepare next bin
627 start_mz_in = end_mz_out;
628
629 // Update prev_mz to be the current one for next iteration.
630 prev_mz = next_mz;
631
632 // Now got the next DataPoint instance.
633 ++it;
634 }
635
636#if 0
637
638 QString fileName = "/tmp/massSpecDataBasedBins.txt";
639
640 qDebug() << "Writing the list of bins setup in the "
641 "mass spectrum in file "
642 << fileName;
643
644 QFile file(fileName);
645 file.open(QIODevice::WriteOnly);
646
647 QTextStream fileStream(&file);
648
649 for(auto &&bin : m_bins)
650 fileStream << QString("[%1-%2]\n")
651 .arg(bin.startMzIn, 0, 'f', 10)
652 .arg(bin.endMzOut, 0, 'f', 10);
653
654 fileStream.flush();
655 file.close();
656
657 qDebug() << "elements."
658 << "starting with mz" << m_bins.front().startMzIn << "ending with mz"
659 << m_bins.back().endMzOut;
660
661#endif
662
663 return bins;
664}
665
666
667QString
668MzIntegrationParams::toString(int offset, const QString &spacer) const
669{
670 QString lead;
671
672 for(int iter = 0; iter < offset; ++iter)
673 lead += spacer;
674
675 QString text = lead;
676 text += "m/z integration parameters:\n";
677
678 text += lead;
679 text += spacer;
680 if(m_smallestMz != std::numeric_limits<double>::max())
681 text.append(
682 QString::asprintf("Smallest (first) m/z: %.6f\n", m_smallestMz));
683
684 text += lead;
685 text += spacer;
686 if(m_greatestMz != std::numeric_limits<double>::min())
687 text.append(QString::asprintf("Greatest (last) m/z: %.6f\n", m_greatestMz));
688
689 text += lead;
690 text += spacer;
691 text.append(QString("Decimal places: %1\n").arg(m_decimalPlaces));
692
693 std::map<BinningType, QString>::iterator it;
694 it = binningTypeMap.find(m_binningType);
695
696 if(it == binningTypeMap.end())
697 qFatal("Programming error.");
698
699 text += lead;
700 text += spacer;
701 text.append(QString("Binning type: %1\n").arg(it->second.toLatin1().data()));
702
703 // Only provide the details relative to the ARBITRARY binning type.
704
706 {
707 text += lead;
708 text += spacer;
709 text += spacer;
710 text.append(QString("Bin nominal size: %1\n")
711 .arg(mp_precision->getNominal(), 0, 'f', 6));
712
713 text += lead;
714 text += spacer;
715 text += spacer;
716 text.append(QString("Bin size: %2\n")
717 .arg(mp_precision->toString().toLatin1().data()));
718 }
719
720 // Now other data that are independent of the bin settings.
721
722 text += lead;
723 text += spacer;
724 text +=
725 QString("Apply m/z shift: %1\n").arg(m_applyMzShift ? "true" : "false");
726
728 {
729 text += lead;
730 text += spacer;
731 text += spacer;
732 text += QString("m/z shift: %1").arg(m_mzShift, 0, 'f', 6);
733 }
734
735 text += lead;
736 text += spacer;
737 text += QString("Remove 0-val data points: %1\n")
738 .arg(m_removeZeroValDataPoints ? "true" : "false");
739
740 return text;
741}
742
743} // namespace pappso
744
Class to represent a mass spectrum.
Definition: massspectrum.h:71
void sortMz()
Sort the DataPoint instances of this spectrum.
The MzIntegrationParams class provides the parameters definining how m/z !
Q_INVOKABLE BinningType getBinningType() const
Q_INVOKABLE int getDecimalPlaces() const
pappso::pappso_double getSmallestMz() const
pappso::pappso_double m_smallestMz
MzIntegrationParams & operator=(const MzIntegrationParams &other)
Q_INVOKABLE pappso::pappso_double getGreatestMz() const
pappso::pappso_double m_greatestMz
Q_INVOKABLE pappso::PrecisionPtr getPrecision() const
Q_INVOKABLE bool isApplyMzShift() const
std::vector< double > createArbitraryBins()
Q_INVOKABLE void setPrecision(pappso::PrecisionPtr precisionPtr)
Q_INVOKABLE double getMzShift() const
Q_INVOKABLE void updateSmallestMz(pappso::pappso_double value)
Q_INVOKABLE void updateGreatestMz(pappso::pappso_double value)
Q_INVOKABLE bool isRemoveZeroValDataPoints() const
Q_INVOKABLE bool isValid() const
Q_INVOKABLE bool hasValidMzRange() const
Q_INVOKABLE QString toString(int offset=0, const QString &spacer=QString()) const
pappso::PrecisionPtr mp_precision
Q_INVOKABLE void setSmallestMz(pappso::pappso_double value)
Q_INVOKABLE void setBinningType(BinningType binningType)
Q_INVOKABLE void reset()
Reset the instance to default values.
std::vector< double > createDataBasedBins(pappso::MassSpectrumCstSPtr massSpectrum)
Q_INVOKABLE void setApplyMzShift(bool applyMzShift)
Q_INVOKABLE void setDecimalPlaces(int decimal_places)
Q_INVOKABLE std::vector< pappso::pappso_double > createBins()
Q_INVOKABLE void setMzShift(double value)
Q_INVOKABLE void setRemoveZeroValDataPoints(bool removeOrNot=true)
Q_INVOKABLE void setGreatestMz(pappso::pappso_double value)
pappso::pappso_double m_mzShift
virtual QString toString() const =0
virtual pappso_double getNominal() const final
Definition: precision.cpp:65
virtual pappso_double delta(pappso_double value) const =0
static PrecisionPtr getPpmInstance(pappso_double value)
get a ppm precision pointer
Definition: precision.cpp:150
static PrecisionPtr getDaltonInstance(pappso_double value)
get a Dalton precision pointer
Definition: precision.cpp:130
static int zeroDecimalsInValue(pappso_double value)
0.11 would return 0 (no empty decimal) 2.001 would return 2 1000.0001254 would return 3
Definition: utils.cpp:82
int mzIntegrationParamsMetaTypeId
int mzIntegrationParamsPtrMetaTypeId
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition: aa.cpp:39
BinningType
Type of binning when performing integrations to a mass spectrum.
@ DATA_BASED
binning based on mass spectral data
@ ARBITRARY
binning based on arbitrary bin size value
@ NONE
< no binning
double pappso_double
A type definition for doubles.
Definition: types.h:49
std::shared_ptr< const MassSpectrum > MassSpectrumCstSPtr
Definition: massspectrum.h:55
std::map< BinningType, QString > binningTypeMap
Map relating the BinningType to a textual representation.