GCC Code Coverage Report


source/XpertMassCore/src/
File: source/XpertMassCore/src/MassPeakShaperConfig.cpp
Date: 2025-11-20 01:41:33
Lines:
0/265
0.0%
Functions:
0/39
0.0%
Branches:
0/153
0.0%

Line Branch Exec Source
1 /* BEGIN software license
2 *
3 * MsXpertSuite - mass spectrometry software suite
4 * -----------------------------------------------
5 * Copyright (C) 2009--2020 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 <cmath>
36
37
38 /////////////////////// Qt includes
39 #include <QDebug>
40
41
42 /////////////////////// pappsomspp includes
43
44
45 /////////////////////// Local includes
46 #include "MsXpS/libXpertMassCore/MassPeakShaperConfig.hpp"
47
48 namespace MsXpS
49 {
50 namespace libXpertMassCore
51 {
52
53
54 /*!
55 \variable MsXpS::libXpertMassCore::FWHM_PEAK_SPAN_FACTOR
56
57 \brief The compounding factor to account for when shaping the sides of the
58 peak.
59
60 The shape of the peak needs to reflect a real mass peak. In particular,
61 the shape of the peak has to return, \e{on each one of both sides}, to the
62 baseline, thus mimicking the baseline for a m/z distance equivalent to
63 FWHM_PEAK_SPAN_FACTOR times the FWHM m/z range from left to right. That means
64 that the simulated peak region at the left hand side of the centroid value will
65 span (FWHM_PEAK_SPAN_FACTOR/2) times the FWHM and the same one right.
66 Empirically, a good FWHM_PEAK_SPAN_FACTOR is \c 4, meaning that the left half
67 of the peak (that is centered on the centroid) will have a size corresponding
68 to two times the FHWM, and the same for the right half of the peak.
69
70 This is best exemplified as follows:
71
72 \code
73 Centroid value
74 ^
75 |
76 [ m/z - (2 * FWHM) <-|-> m/z + (2 * FWHM) ]
77 <----- width of the whole peak shape ----->
78 \endcode
79 */
80
81 int FWHM_PEAK_SPAN_FACTOR = 4;
82
83 /*!
84 \class MsXpS::libXpertMassCore::MassPeakShaperConfig
85 \inmodule libXpertMassCore
86 \ingroup XpertMassCoreMassCalculations
87 \inheaderfile MassPeakShaperConfig.hpp
88
89 \brief The MassPeakShaperConfig class provides the features required to
90 configure the shaping of a mass peak centroid into a Gaussian or a Lorentzian
91 fully profiled shape.
92
93 \e{Shaping a peak} means creating a shape around a centroid m/z value such that
94 the m/z peak is represented like it appears in a mass spectrum displayed in
95 "profile" mode.
96
97 \details{The peak shaping process}
98
99 The model used to craft the "profiled" mass peak can be of two types:
100
101 \list
102 \li \l{https://en.wikipedia.org/wiki/Gaussian_function}{Gaussian}
103 \li \l{https://en.wikipedia.org/wiki/Cauchy_distribution}{Lorentzian}
104 \endlist
105
106 The starting parameters are the (m/z,intensity) values of the peak centroid and
107 the full width at half maximum (FWHM) value that will govern the width of the
108 shape at 50% height of the peak. The width of the peak will be an inverse
109 representation of the resolving power of the instrument: the instrument with
110 the greatest resolving power will yield mass peaks with the smallest width.
111 Conversely, a very old instrument will produce mass spectra where the peaks
112 will be broad.
113
114 There are thus two possiblities for configuring the peak shape:
115
116 \list
117
118 \li Provide the FWHM value itself.
119 \li Provide the resolving power of the instrument that the peak simulation
120 should emulate.
121
122 \endlist
123
124 \enddetails
125 */
126
127 /*!
128 \variable MsXpS::libXpertMassCore::MassPeakShaperConfig::m_resolution
129
130 \brief Resolving power of the instrument.
131 */
132
133 /*!
134 \variable MsXpS::libXpertMassCore::MassPeakShaperConfig::m_fwhm
135
136 \brief Full width at half maximum of the shaped peak.
137 */
138
139 /*!
140 \variable MsXpS::libXpertMassCore::MassPeakShaperConfig::m_massPeakWidthLogic
141
142 \brief Describes the logic used to compute the peak shape width.
143 */
144
145 /*!
146 \variable MsXpS::libXpertMassCore::MassPeakShaperConfig::m_referencePeakMz
147
148 \brief The m/z value to be used when computing the FWHM value starting from a
149 mass spectrometer resolving power.
150 */
151
152 /*!
153 \variable MsXpS::libXpertMassCore::MassPeakShaperConfig::m_pointCount
154
155 \brief The count of points used to shape the peak. Typically between 150 and
156 300.
157 */
158
159 /*!
160 \variable MsXpS::libXpertMassCore::MassPeakShaperConfig::m_withBins
161
162 \brief Tells if bins are requested for the computation.
163
164 There is no need in the context of the calculations performed by the
165 MassPeakShaperConfig class to know if bins are required or not. This variable
166 is useful when multiple peak shapes are combined into a more complex trace or
167 mass spectrum, typically when simulating an isotopic cluster. In this case,
168 each cluster peak centroid is shaped in sequence and then they are all merged
169 into a single trace (no bins) or mass spectrum (binning). The width of the bins
170 is defined using this m_withBins variable.
171 */
172
173 /*!
174 \variable MsXpS::libXpertMassCore::MassPeakShaperConfig::m_binSizeDivisor
175
176 \brief Empirical division factor to apply to \l m_binSize to reduce the size of
177 the bins after the bin size calculation.
178
179 Empirically, a good value is \c 6.
180 */
181
182 /*!
183 \variable MsXpS::libXpertMassCore::MassPeakShaperConfig::m_binSize
184
185 \brief The size of the m/z bins.
186 */
187
188 /*!
189 \variable MsXpS::libXpertMassCore::MassPeakShaperConfig::m_isBinSizeFixed
190
191 \brief Tells if the size of the m/z bins is fixed.
192 */
193
194 /*!
195 \variable MsXpS::libXpertMassCore::MassPeakShaperConfig::m_mzStep
196
197 \brief The m/z distance (a Delta) between to consecutive data points in the
198 shaped mass peak.
199 */
200
201 /*!
202 \variable MsXpS::libXpertMassCore::MassPeakShaperConfig::m_massPeakShapeType
203
204 \brief The requested shape of the mass peak.
205 */
206
207
208 /*!
209 \brief Constructs a MassPeakShaperConfig instance.
210 */
211 MassPeakShaperConfig::MassPeakShaperConfig(QObject *parent): QObject(parent)
212 {
213 reset();
214 }
215
216 /*!
217 \brief Constructs a MassPeakShaperConfig instance as a copy of \a other.
218 */
219 MassPeakShaperConfig::MassPeakShaperConfig(const MassPeakShaperConfig &other,
220 QObject *parent)
221 : QObject(parent),
222 m_resolution(other.m_resolution),
223 m_fwhm(other.m_fwhm),
224 m_massPeakWidthLogic(other.m_massPeakWidthLogic),
225 m_referencePeakMz(other.m_referencePeakMz),
226 m_pointCount(other.m_pointCount),
227 m_withBins(other.m_withBins),
228 m_binSizeDivisor(other.m_binSizeDivisor),
229 m_binSize(other.m_binSize),
230 m_isBinSizeFixed(other.m_isBinSizeFixed),
231 m_mzStep(other.m_mzStep),
232 m_massPeakShapeType(other.m_massPeakShapeType)
233 {
234 }
235
236 /*!
237 \brief Destructs this MassPeakShaperConfig instance.
238 */
239 MassPeakShaperConfig::~MassPeakShaperConfig()
240 {
241 }
242
243 /*!
244 \brief Assigns \a other to this MassPeakShaperConfig instance.
245 */
246 MassPeakShaperConfig &
247 MassPeakShaperConfig::initialize(const MassPeakShaperConfig &other)
248 {
249 if(this == &other)
250 return *this;
251
252 m_resolution = other.m_resolution;
253 m_fwhm = other.m_fwhm;
254 m_massPeakWidthLogic = other.m_massPeakWidthLogic;
255 m_referencePeakMz = other.m_referencePeakMz;
256 m_pointCount = other.m_pointCount;
257 m_withBins = other.m_withBins;
258 m_binSizeDivisor = other.m_binSizeDivisor;
259 m_binSize = other.m_binSize;
260 m_isBinSizeFixed = other.m_isBinSizeFixed;
261 m_mzStep = other.m_mzStep;
262 m_massPeakShapeType = other.m_massPeakShapeType;
263
264 return *this;
265 }
266
267 /*!
268 \brief Returns a newly allocated MassPeakShaperConfig instance initialized using
269 \a other and with parent set to \a parent.
270 */
271 MassPeakShaperConfig *
272 MassPeakShaperConfig::clone(const MassPeakShaperConfig &other,
273 QObject *parent) const
274 {
275 MassPeakShaperConfig *copy_p = new MassPeakShaperConfig(parent);
276 copy_p->initialize(other);
277
278 return copy_p;
279 }
280
281 /*!
282 \brief Sets the \a resolution (the resolving power of the instrument).
283 */
284 void
285 MassPeakShaperConfig::setResolution(int resolution)
286 {
287 m_resolution = resolution;
288 }
289
290 /*!
291 \brief Returns the resolution (the resolving power of the instrument).
292 */
293 double
294 MassPeakShaperConfig::getResolution() const
295 {
296 return m_resolution;
297 }
298
299 /*!
300 \brief Calculates the resolution (resolving power of the instrument).
301
302 The calculation involves using the FWHM (m_fwhm) member datum and the m/z value
303 that is considered to be the reference for the calculation (m_referencePeakMz).
304
305 If any of these two values is not set, then this function returns 0 and sets \a
306 ok to false.
307
308 The calculation is that simple:
309
310 \code
311 m_resolution = m_referencePeakMz / m_fwhm;
312 \endcode
313
314 Because we used the FWHM to compute the resolution and set the calculated value
315 to the \l m_resolution member datum, we keep a record of this by:
316
317 \code
318 m_massPeakWidthLogic = Enums::MassPeakWidthLogic::FWHM;
319 \endcode
320
321 Returns the resolving power as set in \l m_resolution and sets \a ok to true.
322 */
323 int
324 MassPeakShaperConfig::resolution(bool *ok)
325 {
326 if(ok == nullptr)
327 qFatal("The pointer cannot be nullptr.");
328
329 // If we want to compute the resolution that means that we have to have
330 // m_fwhm.
331 if(!m_fwhm)
332 {
333 *ok = false;
334 return 0;
335 }
336
337 if(!m_referencePeakMz)
338 {
339 *ok = false;
340 return 0;
341 }
342
343 m_resolution = m_referencePeakMz / m_fwhm;
344
345 *ok = true;
346
347 // We used the FWHM to compute the resolving power.
348 m_massPeakWidthLogic = Enums::MassPeakWidthLogic::FWHM;
349
350 return m_resolution;
351 }
352
353 /*!
354 \brief Sets the \a fwhm (full width at half maximum).
355 */
356 void
357 MassPeakShaperConfig::setFwhm(double fwhm)
358 {
359 m_fwhm = fwhm;
360 }
361
362 /*!
363 \brief Gets the fwhm (full width at half maximum).
364 */
365 double
366 MassPeakShaperConfig::getFwhm() const
367 {
368 return m_fwhm;
369 }
370
371 /*!
372 \brief Calculates the fwhm (full width at half maximum).
373
374 The calculation involves using the instrument's resolving power (m_resolution)
375 member datum and the m/z value that is considered to be the reference for the
376 calculation (m_referencePeakMz).
377
378 If any of these two values is not set, then this function returns 0 and sets \a
379 ok to false.
380
381 The calculation is that simple:
382
383 \code
384 m_fwhm = m_referencePeakMz / m_resolution;
385 \endcode
386
387 Because we used the resolution to compute the FWHM and set the calculated
388 value
389 to the \l m_fwhm member datum, we keep a record of this by:
390
391 \code
392 m_massPeakWidthLogic = Enums::MassPeakWidthLogic::RESOLUTION;
393 \endcode
394
395 Returns the FWHM value as set in \l m_fwhm and sets \a ok to true.
396 */
397 double
398 MassPeakShaperConfig::fwhm(bool *ok)
399 {
400 if(ok == nullptr)
401 qFatal("The pointer cannot be nullptr.");
402
403 // Or we need to compute it using the mz passed as parameter and the
404 // resolution.
405 if(!m_resolution)
406 {
407 *ok = false;
408 return 0;
409 }
410
411 if(!m_referencePeakMz)
412 {
413 // qDebug() << "There is no reference peak centroid!";
414
415 *ok = false;
416 return 0;
417 }
418
419 m_fwhm = m_referencePeakMz / m_resolution;
420 *ok = true;
421
422 // We used the resolving power to compute the FWHM.
423 m_massPeakWidthLogic = Enums::MassPeakWidthLogic::RESOLUTION;
424
425 return m_fwhm;
426 }
427
428 /*!
429 \brief Returns the half of the FWMH (m_fwhm) for use in the Lorentzian shape
430 calculation.
431
432 Uses the \l fwhm() function to compute the FWHM value. If the
433 FWHM calculation fails, returns 0 and \a ok is set to false, otherwise returns
434 half of FWHM and \a ok is set to true.
435
436 \sa fwhm()
437 */
438 double
439 MassPeakShaperConfig::halfFwhm(bool *ok)
440 {
441 double fwhm_value = fwhm(ok);
442
443 if(!*ok)
444 return 0;
445
446 return (fwhm_value / 2);
447 }
448
449 /*!
450 \brief Sets the reference m/z value required for calculations to \a mz.
451 */
452 void
453 MassPeakShaperConfig::setReferencePeakMz(double mz)
454 {
455 m_referencePeakMz = mz;
456 }
457
458 /*!
459 \brief Gets the reference m/z value required for calculations.
460 */
461 double
462 MassPeakShaperConfig::getReferencePeakMz() const
463 {
464 return m_referencePeakMz;
465 }
466
467 /*!
468 \brief Sets the requirement to prepare m/z bins at a later computing stage to
469 \a with_bins.
470
471 \sa IsotopicClusterShaper::run(), isWithBins()
472 */
473 void
474 MassPeakShaperConfig::setWithBins(bool with_bins)
475 {
476 m_withBins = with_bins;
477 }
478
479 /*!
480 \brief Returns the requirement to prepare m/z bins at a later computing stage.
481
482 \sa IsotopicClusterShaper::run(), setWithBins()
483 */
484 bool
485 MassPeakShaperConfig::isWithBins() const
486 {
487 return m_withBins;
488 }
489
490 /*!
491 \brief Sets the \a bin_size.
492 */
493 void
494 MassPeakShaperConfig::setBinSize(double bin_size)
495 {
496 m_binSize = bin_size;
497 }
498
499 /*!
500 \brief Computes the bin size.
501
502 If there is no requirement for bins (m_withBins is false), returns 0 and set \a
503 ok to true.
504
505 In order to compute the bin size we need that at least the FWHM (m_fwhm) or the
506 resolving power (m_resolution) be set. If none of these values are set, this
507 function returns 0 and sets \a ok to false.
508
509 If the bin size was fixed (m_isBinSizeFixed is true), then the bin size
510 (m_binSize) must be set. If that is not the case, the function returns 0 and
511 sets \a ok to false.
512
513 If the FWHM value (m_fwhm) is set, then it is used right away. Otherwise, the
514 FWHM is computed starting from the resolving power (m_resolution). If that
515 computation fails, the function returns 0 and sets \a ok to false.
516
517 Starting from the FWHM value (m_fwhm), the bin size calculation requires that
518 the m_binSizeDivisor be > 1. The bin size is thus computed as the ratio FWHM /
519 m_binSizeDivisor, and the obtained value is set to m_binSize.
520
521 Empirically, a value of 6 for m_binSizeDivisor, yields bin sizes that allow
522 combining correctly multiple peak shapes into a mass spectrum. Essentially,
523 that means that 6 individual m/z bins are required to combine nicely all the
524 peaks shapes obtained for all the peak centroids in a given isotopic cluster,
525 for example.
526
527 At this point, the function returns the bin size and sets \a ok to true.
528
529 \sa setBinSizeDivisor()
530 */
531 double
532 MassPeakShaperConfig::binSize(bool *ok)
533 {
534 if(ok == nullptr)
535 qFatal("The pointer cannot be nullptr.");
536
537 // If the bin size was set before, then, just return it.
538 // if(m_binSize)
539 //{
540 //*ok = true;
541 // return m_binSize;
542 //}
543
544 if(!m_withBins)
545 {
546 // qDebug() << "Bins are not requested, just return 0 and set true.";
547 *ok = true;
548 return 0;
549 }
550
551 // In order to compute the bin Size, we need the FWHM and the number of
552 // points.
553
554 if(!m_resolution && !m_fwhm)
555 {
556 // qDebug() << "That's an error when neither resolution nor FWHM is set.";
557 *ok = false;
558 return 0;
559 }
560
561 if(m_fwhm)
562 {
563 // FWHM is fine, we can use that immediately.
564
565 // qDebug() << "FWHM:" << m_fwhm;
566
567 if(!m_pointCount)
568 {
569 // qDebug() << "That's an error that the point count is 0.";
570 *ok = false;
571 return 0;
572 }
573 }
574 else
575 {
576 // We have to work with the resolution.
577
578 // qDebug() << "Resolution:" << m_resolution;
579
580 fwhm(ok);
581
582 if(!*ok)
583 {
584 // qDebug()
585 //<< "Could not compute FWHM on the basis of the resolution.";
586
587 if(!m_pointCount)
588 {
589 // qDebug() << "That's an error that the point count is 0.";
590 *ok = false;
591 return 0;
592 }
593 }
594 }
595
596 if(m_isBinSizeFixed)
597 {
598 // The bin size has to be set and must not be changed, as the user has
599 // set it manually.
600
601 if(!m_binSize)
602 {
603 // qDebug() << "The bin size should be set manually but is not set.";
604 *ok = false;
605 return 0;
606 }
607 }
608 else
609 {
610 m_binSize = m_fwhm / m_binSizeDivisor;
611
612 // qDebug() << "The bin size was computed:" << m_binSize;
613 }
614
615 *ok = true;
616 return m_binSize;
617 }
618
619 /*!
620 \brief Returns (no computation) the bin size.
621 */
622 double
623 MassPeakShaperConfig::getBinSize() const
624 {
625 return m_binSize;
626 }
627
628 /*!
629 \brief Sets the requirement that the bin size be set and fixed (not modifiable
630 by computations) to \a is_fixed.
631
632 When \a is_fixed is true, the \l binSize() function returns the bin size
633 without trying to compute it.
634
635 \sa binSize()
636 */
637 void
638 MassPeakShaperConfig::setBinSizeFixed(bool is_fixed)
639 {
640 m_isBinSizeFixed = is_fixed;
641 }
642
643 /*
644 \brief Gets the requirement that the bin size be set and fixed (not modifiable
645 by computations).
646 */
647 bool
648 MassPeakShaperConfig::getBinSizeFixed()
649 {
650 return m_isBinSizeFixed;
651 }
652
653 /*!
654 \brief Sets the bin size computation dividing \a factor.
655
656 When the bin size is computed (m_isBinSizeFixed is false), that value is
657 determined by dividing the FWHM value by this \a factor (m_binSizeDivisor).
658
659 Empirically, a value of 6 for m_binSizeDivisor, yields bin sizes that allow
660 combining correctly multiple peak shapes into a mass spectrum. Essentially,
661 that means that 6 individual m/z bins are required to combine nicely all the
662 peaks shapes obtained for all the peak centroids in a given isotopic cluster,
663 for example.
664 */
665 void
666 MassPeakShaperConfig::setBinSizeDivisor(int factor)
667 {
668 if(std::abs(factor) < 1)
669 qFatal("Programming error.");
670
671 m_binSizeDivisor = std::abs(factor);
672 }
673
674 /*!
675 \brief Returns the bin size computation dividing factor.
676
677 \sa setBinSizeDivisor()
678 */
679 int
680 MassPeakShaperConfig::getBinSizeDivisor() const
681 {
682 return m_binSizeDivisor;
683 }
684
685 /*!
686 \brief Sets the \a point_count to be used to shape the mass peak
687 around the m/z centroid value.
688
689 Typically, a value between 150 and 200 points is fine to nicely shape a m/z
690 peak centroid.
691 */
692 void
693 MassPeakShaperConfig::setPointCount(int point_count)
694 {
695 m_pointCount = point_count;
696 }
697
698 /*!
699 \brief Gets the count of points to be used to shape the mass peak around the
700 m/z centroid value.
701 */
702 int
703 MassPeakShaperConfig::getPointCount() const
704 {
705 return m_pointCount;
706 }
707
708 /*!
709 \brief Sets the type of mass peak shape to \a mass_peak_shape_type.
710
711 \sa MsXpS::libXpertMassCore::Enums::MassPeakShapeType
712 */
713 void
714 MassPeakShaperConfig::setMassPeakShapeType(
715 Enums::MassPeakShapeType mass_peak_shape_type)
716 {
717 m_massPeakShapeType = mass_peak_shape_type;
718 }
719
720 /*!
721 \brief Gets the type of mass peak shape.
722
723 \sa MsXpS::libXpertMassCore::Enums::MassPeakShapeType
724 */
725 Enums::MassPeakShapeType
726 MassPeakShaperConfig::getMassPeakShapeType() const
727 {
728 return m_massPeakShapeType;
729 }
730
731 /*!
732 \brief Sets the mass peak width calculation \a logic.
733
734 The full mass peak width at half peak maximum (FWHM) can either be set manually
735 or be computed from a reference m/z value and the instrument's resolving power.
736
737 \sa MsXpS::libXpertMassCore::Enums::MassPeakWidthLogic
738 */
739 void
740 MassPeakShaperConfig::setMassPeakWidthLogic(Enums::MassPeakWidthLogic logic)
741 {
742 m_massPeakWidthLogic = logic;
743 }
744
745 /*!
746 \brief Gets the mass peak width calculation logic.
747
748 \sa MsXpS::libXpertMassCore::Enums::MassPeakWidthLogic
749 */
750 Enums::MassPeakWidthLogic
751 MassPeakShaperConfig::getMassPeakWidthLogic() const
752 {
753 return m_massPeakWidthLogic;
754 }
755
756 double
757 MassPeakShaperConfig::c(bool *ok)
758 {
759 // c in the Gaussian curve is related to the fwhm value:
760
761 fwhm(ok);
762
763 if(!*ok)
764 {
765 return 0;
766 }
767
768 double c = m_fwhm / (2 * sqrt(2 * log(2)));
769
770 // qDebug() << "c:" << c;
771
772 *ok = true;
773
774 return c;
775 }
776
777 double
778 MassPeakShaperConfig::a(bool *ok)
779 {
780 // double pi = 3.1415926535897932384626433832795029;
781
782 double c_value = c(ok);
783
784 if(!*ok)
785 {
786 return 0;
787 }
788
789 double a = (1 / (c_value * sqrt(2 * M_PI)));
790
791 // qDebug() << "a:" << a;
792
793 *ok = true;
794
795 return a;
796 }
797
798 double
799 MassPeakShaperConfig::gamma(bool *ok)
800 {
801 fwhm(ok);
802
803 if(!*ok)
804 {
805 return 0;
806 }
807
808 double gamma = m_fwhm / 2;
809
810 // qDebug() << "gamma:" << gamma;
811
812 *ok = true;
813
814 return gamma;
815 }
816
817 /*!
818 \brief Sets the \a mz_step.
819
820 The m/z step value is the distance between two consecutive points in the peak
821 shape.
822
823 \sa getMzStep()
824 */
825 void
826 MassPeakShaperConfig::setMzStep(double mz_step)
827 {
828 m_mzStep = mz_step;
829 }
830
831 /*!
832 \brief Gets the m/z step.
833
834 The m/z step value is the distance between two consecutive points in the peak
835 shape.
836
837 \sa setMzStep()
838 */
839 double
840 MassPeakShaperConfig::getMzStep() const
841 {
842 return m_mzStep;
843 }
844
845 /*!
846 \brief Calculates the m/z step.
847
848
849 The m/z step value is the distance between two consecutive points in the peak
850 shape. To compute that value, the full m/z width of the calculated shape (not
851 only the width at half maximum, FWHM) is divided by the total number of data
852 points that make the final shape of the m/z peak.
853
854 The first variable is FWHM_PEAK_SPAN_FACTOR * m_fwhm, and the second
855 variable is m_pointCount. The calculation is thus:
856
857 \code
858 m_mzStep = (FWHM_PEAK_SPAN_FACTOR * m_fwhm) / m_pointCount;
859 \endcode
860
861 The first step is to compute the FWHM and then to check the value of
862 m_pointCount (that cannot be 0). If any of these fails, the function returns 0
863 and set \a ok to false, otherwise the computed value is set to m_mzStep and
864 returned, while \a ok is set to true.
865
866 \sa FWHM_PEAK_SPAN_FACTOR
867 */
868 double
869 MassPeakShaperConfig::mzStep(bool *ok)
870 {
871 // But what is the mz step ?
872 //
873 // We want the shape to be able to go down to baseline. Thus we want that
874 // the shape to have a "basis" (or, better, a "ground") corresponding to
875 // twice the FWHM on the left of the centroid and to twice the FWHM on the
876 // right (that makes in total FWHM_PEAK_SPAN_FACTOR * FWHM, that is,
877 // FWHM_PEAK_SPAN_FACTOR = 4).
878
879 fwhm(ok);
880
881 if(!*ok)
882 {
883 return 0;
884 }
885
886 if(!m_pointCount)
887 {
888 *ok = false;
889 return 0;
890 }
891
892 m_mzStep = (FWHM_PEAK_SPAN_FACTOR * m_fwhm) / m_pointCount;
893
894 return m_mzStep;
895 }
896
897 /*!
898 \brief Resets this MassPeakShaperConfig instance to default values like at
899 construction time.
900 */
901 void
902 MassPeakShaperConfig::reset()
903 {
904 // Values to start over.
905
906 m_resolution = 0;
907 m_fwhm = 0;
908 m_referencePeakMz = 0;
909 m_pointCount = 0;
910 m_withBins = false;
911 m_binSizeDivisor = 6;
912 m_binSize = 0;
913 m_isBinSizeFixed = false;
914 m_mzStep = 0;
915 m_massPeakShapeType = Enums::MassPeakShapeType::NOT_SET;
916 }
917
918 /*!
919 \brief Calculates the various parameters of the peak shape using member data.
920
921 This function first checks that all the required data are set. Then this
922 functions computes the FWHM value required to shape the peak centroid. Once the
923 basic data have been computed or set, the parameters of the shape are computed:
924 c, a, gamma.
925
926 Returns true if the computation was successful, false otherwise.
927 */
928 bool
929 MassPeakShaperConfig::resolve(libXpertMassCore::ErrorList &error_list)
930 {
931 // We need to try to set all the relevant parameters by calculation.
932
933 bool ok = false;
934
935 // These are the essential parameters:
936
937 if(!m_referencePeakMz)
938 {
939 error_list.append("Missing reference peak m/z value");
940 return false;
941 }
942
943 if(!m_fwhm && !m_resolution)
944 {
945 error_list.append("Both FWHM and resolution are naught");
946 return false;
947 }
948
949 if(!m_pointCount)
950 {
951 error_list.append("The count of points to shape the peak is naught");
952 return false;
953 }
954
955 // At this point we should be able to compute the relevant data.
956
957 // The FWHM is the *leading* value for the determination of the peak shape's
958 // width at half maximum. If that FWHM value is 0, then we resort to the
959 // resolution. Both R and FWHM cannot be 0!
960 if(m_fwhm)
961 {
962 // If we have FWHM, immediately try to compute the resolution as we'll
963 // need it later. FWHM takes precedence over resolution!
964 resolution(&ok);
965
966 if(!ok)
967 {
968 error_list.append("Failed to compute resolution value");
969 return false;
970 }
971 }
972 else
973 {
974 // We should be able to compute FWHM by resorting to the resolution.
975
976 fwhm(&ok);
977
978 if(!ok)
979 {
980 error_list.append("Failed to compute FWHM value");
981 return false;
982 }
983 }
984
985 // Now check if we have and can compute the bins.
986 // But we do this only if the user has not stated that the bin size has to
987 // be set manually.
988
989 // qDebug() << "In the resolve, check the bin size";
990
991 binSize(&ok);
992
993 if(!ok)
994 {
995 error_list.append("Failed to compute the bin size");
996 return false;
997 }
998
999 mzStep(&ok);
1000
1001 if(!ok)
1002 {
1003 error_list.append("Failed to compute the m/z step");
1004 return false;
1005 }
1006 // Now the other parameters for the shape.
1007
1008 c(&ok);
1009
1010 if(!ok)
1011 {
1012 error_list.append("Failed to compute the c parameter");
1013 return false;
1014 }
1015
1016 a(&ok);
1017
1018 if(!ok)
1019 {
1020 error_list.append("Failed to compute the a parameter");
1021 return false;
1022 }
1023
1024 gamma(&ok);
1025
1026 if(!ok)
1027 {
1028 error_list.append("Failed to compute the gamma parameter");
1029 return false;
1030 }
1031
1032 return true;
1033 }
1034
1035 /*!
1036 \brief Returns a string representing this MassPeakShaperConfig instance.
1037
1038 The configuration of the MassPeakShaper is first resolved. If that step fails,
1039 an empty string is returned, otherwise the configuration is returned as a
1040 string.
1041 */
1042 QString
1043 MassPeakShaperConfig::toString()
1044 {
1045 QString string;
1046
1047 libXpertMassCore::ErrorList error_list;
1048 bool ok = resolve(error_list);
1049
1050 if(!ok)
1051 return QString();
1052
1053 QString peak_shape_text;
1054 if(m_massPeakShapeType == Enums::MassPeakShapeType::GAUSSIAN)
1055 peak_shape_text = "Gaussian";
1056 if(m_massPeakShapeType == Enums::MassPeakShapeType::LORENTZIAN)
1057 peak_shape_text = "Lorentzian";
1058
1059 QString with_bins_text;
1060 if(m_withBins)
1061 with_bins_text +=
1062 QString("With bins of size: %1 m/z.\n").arg(m_binSize, 0, 'f', 10);
1063 else
1064 with_bins_text = "Without bins.\n";
1065
1066 string = QString(
1067 "%1 peak shaping:\n"
1068 "Configuration for reference m/z value: %2\n"
1069 "Resolution: %3\n"
1070 "FWHM: %4\n"
1071 "%5\n"
1072 "Number of points to shape the peak: %6\n"
1073 "c: %7\n"
1074 "c^2: %8\n"
1075 "mz step: %9\n\n")
1076 .arg(peak_shape_text)
1077 .arg(m_referencePeakMz, 0, 'f', 5)
1078 .arg(m_resolution)
1079 .arg(m_fwhm, 0, 'f', 5)
1080 .arg(with_bins_text)
1081 .arg(m_pointCount)
1082 .arg(c(&ok), 0, 'f', 5)
1083 .arg(c(&ok) * c(&ok), 0, 'f', 5)
1084 .arg(m_mzStep, 0, 'f', 5);
1085
1086 return string;
1087 }
1088
1089 void
1090 MassPeakShaperConfig::registerJsConstructor(QJSEngine *engine)
1091
1092 {
1093 if(!engine)
1094 {
1095 qWarning()
1096 << "Cannot register MassPeakShaperConfig class: engine is null";
1097 return;
1098 }
1099
1100 // Register the meta object as a constructor
1101
1102 QJSValue jsMetaObject =
1103 engine->newQMetaObject(&MassPeakShaperConfig::staticMetaObject);
1104 engine->globalObject().setProperty("MassPeakShaperConfig", jsMetaObject);
1105 }
1106
1107
1108 } // namespace libXpertMassCore
1109
1110 } // namespace MsXpS
1111