libpappsomspp
Library for mass spectrometry
Loading...
Searching...
No Matches
trace.cpp
Go to the documentation of this file.
1#include <numeric>
2#include <limits>
3#include <qnamespace.h>
4#include <vector>
5#include <map>
6#include <cmath>
7#include <algorithm>
8#include <iostream>
9#include <iomanip>
10
11#include <QDebug>
12#include <QObject>
13
15#include "trace.h"
16#include "maptrace.h"
25
26
27int traceMetaTypeId = qRegisterMetaType<pappso::Trace>("pappso::Trace");
28int tracePtrMetaTypeId = qRegisterMetaType<pappso::Trace *>("pappso::Trace *");
29
30
31namespace pappso
32{
33
34QDataStream &
35operator<<(QDataStream &out, const Trace &trace)
36{
37 for(auto &dataPoint : trace)
38 {
39 out << dataPoint.x;
40 out << dataPoint.y;
41 out << "\n";
42 }
43 out << "\n";
44
45 return out;
46}
47
48
49QDataStream &
50operator>>(QDataStream &in, Trace &trace)
51{
52 if(in.atEnd())
53 {
54 throw PappsoException(QString("error in QDataStream unserialize operator>> of trace:\n"
55 "read datastream failed status=%1")
56 .arg(in.status()));
57 }
58
59 for(auto &dataPoint : trace)
60 {
61 in >> dataPoint.x;
62 in >> dataPoint.y;
63 }
64
65 return in;
66}
67
68
69std::vector<DataPoint>::iterator
70findFirstEqualOrGreaterX(std::vector<DataPoint>::iterator begin,
71 std::vector<DataPoint>::iterator end,
72 const double &value)
73{
74 return std::find_if(begin, end, [value](const DataPoint &to_compare) {
75 if(to_compare.x < value)
76 {
77 return false;
78 }
79 return true;
80 });
81}
82
83std::vector<DataPoint>::const_iterator
84findFirstEqualOrGreaterX(std::vector<DataPoint>::const_iterator begin,
85 std::vector<DataPoint>::const_iterator end,
86 const double &value)
87{
88 return std::find_if(begin, end, [value](const DataPoint &to_compare) {
89 if(to_compare.x < value)
90 {
91 return false;
92 }
93 return true;
94 });
95}
96
97std::vector<DataPoint>::iterator
98findFirstGreaterX(std::vector<DataPoint>::iterator begin,
99 std::vector<DataPoint>::iterator end,
100 const double &value)
101{
102 return std::find_if(begin, end, [value](const DataPoint &to_compare) {
103 if(to_compare.x > value)
104 {
105 return true;
106 }
107 return false;
108 });
109}
110
111std::vector<DataPoint>::const_iterator
112findFirstGreaterX(std::vector<DataPoint>::const_iterator begin,
113 std::vector<DataPoint>::const_iterator end,
114 const double &value)
115{
116 return std::find_if(begin, end, [value](const DataPoint &to_compare) {
117 if(to_compare.x > value)
118 {
119 return true;
120 }
121 return false;
122 });
123}
124
125std::vector<DataPoint>::iterator
126findDifferentYvalue(std::vector<DataPoint>::iterator begin,
127 std::vector<DataPoint>::iterator end,
128 const double &y_value)
129{
130 return std::find_if(begin, end, [y_value](const DataPoint &to_compare) {
131 if(to_compare.y != y_value)
132 {
133 return true;
134 }
135
136 return false;
137 });
138}
139
140std::vector<DataPoint>::const_iterator
141findDifferentYvalue(std::vector<DataPoint>::const_iterator begin,
142 std::vector<DataPoint>::const_iterator end,
143 const double &y_value)
144{
145 return std::find_if(begin, end, [y_value](const DataPoint &to_compare) {
146 if(to_compare.y != y_value)
147 {
148 return true;
149 }
150
151 return false;
152 });
153}
154
155
156std::vector<DataPoint>::const_iterator
157minYDataPoint(std::vector<DataPoint>::const_iterator begin,
158 std::vector<DataPoint>::const_iterator end)
159{
160 return std::min_element(
161 begin, end, [](const DataPoint &a, const DataPoint &b) { return a.y < b.y; });
162}
163
164
165std::vector<DataPoint>::iterator
166minYDataPoint(std::vector<DataPoint>::iterator begin, std::vector<DataPoint>::iterator end)
167{
168 return std::min_element(
169 begin, end, [](const DataPoint &a, const DataPoint &b) { return a.y < b.y; });
170}
171
172
173std::vector<DataPoint>::const_iterator
174maxYDataPoint(std::vector<DataPoint>::const_iterator begin,
175 std::vector<DataPoint>::const_iterator end)
176{
177 return std::max_element(
178 begin, end, [](const DataPoint &a, const DataPoint &b) { return a.y < b.y; });
181
182std::vector<DataPoint>::iterator
183maxYDataPoint(std::vector<DataPoint>::iterator begin, std::vector<DataPoint>::iterator end)
184{
185 return std::max_element(
186 begin, end, [](const DataPoint &a, const DataPoint &b) { return a.y < b.y; });
187}
188
189
190// As long as next DataPoint has its y value less or equal to prev's,
191// move along down the container. That is, continue moving is
192// direction is downhill to the end of the container (its back).
193std::vector<DataPoint>::const_iterator
194moveLowerYRigthDataPoint(const Trace &trace, std::vector<DataPoint>::const_iterator begin)
195{
196 if(begin == trace.end())
197 return begin;
198 auto it = begin + 1;
199 auto result = begin;
200 // Move along as long as next point's y value is less
201 // or equal to prev point's y value (FR, check).
202 while((it != trace.end()) && (it->y <= result->y))
203 {
204 it++;
205 result++;
206 }
207 return result;
208}
209
210std::vector<DataPoint>::const_iterator
211moveLowerYLeftDataPoint(const Trace &trace, std::vector<DataPoint>::const_iterator begin)
212{
213 if(begin == trace.begin())
214 return begin;
215 auto it = begin - 1;
216 auto result = begin;
217
218 // As long as prev datapoint has y value less or equal to next,
219 // move along up the container. That is, continue moving if
220 // direction is downhill to the beginning of the container (its front).
221 while((it != trace.begin()) && (it->y <= result->y))
222 {
223 it--;
224 result--;
225 }
226 return result;
227}
228
229
230double
231sumYTrace(std::vector<DataPoint>::const_iterator begin,
232 std::vector<DataPoint>::const_iterator end,
233 double init)
234{
235 return std::accumulate(begin, end, init, [](double a, const DataPoint &b) { return a + b.y; });
236}
237
238double
239meanYTrace(std::vector<DataPoint>::const_iterator begin, std::vector<DataPoint>::const_iterator end)
240{
241 pappso_double nb_element = distance(begin, end);
242 if(nb_element == 0)
243 throw ExceptionOutOfRange(QObject::tr("unable to compute mean on a trace of size 0"));
244 return (sumYTrace(begin, end, 0) / nb_element);
245}
246
247
248double
249quantileYTrace(std::vector<DataPoint>::const_iterator begin,
250 std::vector<DataPoint>::const_iterator end,
251 double quantile)
252{
253 std::size_t nb_element = distance(begin, end);
254 if(nb_element == 0)
255 throw ExceptionOutOfRange(QObject::tr("unable to compute quantile on a trace of size 0"));
256
257
258 std::size_t ieth_element = std::round((double)nb_element * quantile);
259 if(ieth_element > nb_element)
260 throw ExceptionOutOfRange(QObject::tr("quantile value must be lower than 1"));
261
262
263 std::vector<DataPoint> data(begin, end);
264 std::nth_element(data.begin(),
265 data.begin() + ieth_element,
266 data.end(),
267 [](const DataPoint &a, const DataPoint &b) { return a.y < b.y; });
268 return data[ieth_element].y;
269}
270
271double
272medianYTrace(std::vector<DataPoint>::const_iterator begin,
273 std::vector<DataPoint>::const_iterator end)
274{
275 std::size_t nb_element = distance(begin, end);
276 if(nb_element == 0)
277 throw ExceptionOutOfRange(QObject::tr("unable to compute median on a trace of size 0"));
278
279 std::vector<DataPoint> data(begin, end);
280 std::nth_element(data.begin(),
281 data.begin() + data.size() / 2,
282 data.end(),
283 [](const DataPoint &a, const DataPoint &b) { return a.y < b.y; });
284 return data[data.size() / 2].y;
285}
286
287double
288areaTrace(std::vector<DataPoint>::const_iterator begin, std::vector<DataPoint>::const_iterator end)
289{
290
291 if(begin == end)
292 return 0;
293 auto previous = begin;
294 auto next = begin + 1;
295 double area = 0;
296 while(next != end)
297 {
298 area += ((next->x - previous->x) * (previous->y + next->y)) / (double)2;
299 previous++;
300 next++;
301 }
302 return area;
303}
304
305
306Trace
307flooredLocalMaxima(std::vector<DataPoint>::const_iterator begin,
308 std::vector<DataPoint>::const_iterator end,
309 double y_floor)
310{
311 Trace local_maxima_trace;
312
313 Trace single_peak_trace;
314
315 DataPoint previous_data_point;
316
317 for(auto iter = begin; iter != end; ++iter)
318 {
319 DataPoint iterated_data_point(iter->x, iter->y);
320
321 // qDebug().noquote() << "Current data point:"
322 //<< iterated_data_point.toString();
323
324 if(iterated_data_point.y < y_floor)
325 {
326 // qDebug() << "under the floor";
327
328 if(single_peak_trace.size())
329 {
330 // qDebug() << "There was a single peak trace cooking";
331
332 local_maxima_trace.push_back(single_peak_trace.maxYDataPoint());
333
334 // qDebug().noquote() << "pushed back local maximum point:"
335 //<< local_maxima_trace.back().toString();
336
337 // Clean and set the context.
338 single_peak_trace.clear();
339
340 previous_data_point = iterated_data_point;
341
342 continue;
343 }
344 else
345 {
346 // qDebug() << "no single peak trace cooking";
347
348 previous_data_point = iterated_data_point;
349
350 continue;
351 }
352 }
353 else
354 {
355 // qDebug() << "over the floor";
356
357 // The iterated value is greater than the y_floor value, so we need to
358 // handle it.
359
360 if(iterated_data_point.y == previous_data_point.y)
361 {
362 // We are in a flat region, no need to change anything to the
363 // context, just skip the point.
364 continue;
365 }
366 else if(iterated_data_point.y > previous_data_point.y)
367 {
368 // qDebug().noquote() << "ascending in a peak";
369
370 // The previously iterated y value was smaller than the presently
371 // iterated one, so we are ascending in a peak.
372
373 // All we need to do is set the context.
374
375 single_peak_trace.push_back(iterated_data_point);
376
377 // qDebug().noquote() << "pushed back normal point:"
378 //<< single_peak_trace.back().toString();
379
380 previous_data_point = iterated_data_point;
381
382 continue;
383 }
384 else
385 {
386 // qDebug().noquote() << "started descending in a peak";
387
388 // No, the currently iterated y value is less than the previously
389 // iterated value.
390
391 single_peak_trace.push_back(iterated_data_point);
392
393 // qDebug().noquote() << "pushed back normal point:"
394 //<< single_peak_trace.back().toString();
395
396 previous_data_point = iterated_data_point;
397
398 continue;
399 }
400 }
401 }
402 // End of
403 // for(auto iter = begin; iter != end; ++iter)
404
405 // Attention, we might arrive here with a peak being created, we need to get
406 // its maximum if that peak is non-empty;
407
408 if(single_peak_trace.size())
409 {
410
411 local_maxima_trace.push_back(single_peak_trace.maxYDataPoint());
412
413 // qDebug().noquote()
414 //<< "was cooking a peak: pushed back local maximum point:"
415 //<< local_maxima_trace.back().toString();
416 }
417
418 return local_maxima_trace;
419}
420
421
423{
424}
425
426
427Trace::Trace(const QString &text)
428{
429 initialize(text);
430}
431
432
433Trace::Trace(const std::vector<pappso_double> &xVector, const std::vector<pappso_double> &yVector)
434{
435 initialize(xVector, yVector);
436}
437
438
439size_t
440Trace::initialize(const QString &space_sep_text)
441{
442 QStringList string_list = space_sep_text.split("\n", Qt::SkipEmptyParts);
443
444 // qDebug() << "Split text into" << string_list.size()
445 //<< "substrings:" << string_list;
446
447 for(int iter = 0; iter < string_list.size(); ++iter)
448 {
449 QString line = string_list.at(iter);
450 // qDebug() << "Now processing line:" << line;
451
452 // Returns a string that has whitespace removed from the start and the
453 // end, and that has each sequence of internal whitespace replaced with a
454 // single space.
455 line = line.simplified();
456
457 // Remove any parentheses and replace comma and semicolumn with space.
458 // line.remove(QChar('('));
459 // line.remove(QChar(')'));
460
461 // line.replace(QChar(','), QChar(' '));
462 // line.replace(QChar(';'), QChar(' '));
463
464 qDebug() << "Now appending DataPoint as this line:" << line;
466 }
467
468 return size();
469}
470
471
472size_t
473Trace::initialize(const QString &x_text, const QString &y_text)
474{
475 QStringList x_string_list = x_text.split("\n", Qt::SkipEmptyParts);
476 QStringList y_string_list = y_text.split("\n", Qt::SkipEmptyParts);
477
478 if(x_string_list.size() != y_string_list.size())
480 "trace.cpp -- ERROR x_text and y_text must have the same number of "
481 "lines.");
482
483 for(int iter = 0; iter < x_string_list.size(); ++iter)
484 {
485 QString x_line = x_string_list.at(iter);
486 QString y_line = y_string_list.at(iter);
487
488 // Returns a string that has whitespace removed from the start and the
489 // end, and that has each sequence of internal whitespace replaced with a
490 // single space.
491 x_line = x_line.simplified();
492 y_line = y_line.simplified();
493
494 append(DataPoint(x_line + " " + y_line));
495 }
496 return size();
497}
498
499
500Trace::Trace(const std::vector<std::pair<pappso_double, pappso_double>> &dataPoints)
501{
502 reserve(dataPoints.size());
503
504 for(auto &dataPoint : dataPoints)
505 {
506 push_back(DataPoint(dataPoint));
507 }
508
509 sortX();
510 // std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
511 // return (a.x < b.x);
512 //});
513}
514
515
516Trace::Trace(const std::vector<DataPoint> &dataPoints) : std::vector<DataPoint>(dataPoints)
517{
518 sortX();
519 // std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
520 // return (a.x < b.x);
521 //});
522}
523
524
525Trace::Trace(const std::vector<DataPoint> &&dataPoints)
526 : std::vector<DataPoint>(std::move(dataPoints))
527{
528 // This constructor used by the MassSpectrum && constructor.
529
530 sortX();
531 // std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
532 // return (a.x < b.x);
533 //});
534}
535
536
537Trace::Trace(const MapTrace &map_trace)
538{
539 for(auto &&item : map_trace)
540 push_back(DataPoint(item.first, item.second));
541
542 // No need to sort, maps are sorted by key (that is, x).
543}
544
545Trace::Trace(const Trace &other) : std::vector<DataPoint>(other)
546{
547}
548
549
550Trace::Trace(const Trace &&other) : std::vector<DataPoint>(std::move(other))
551{
552 // This constructor used by the MassSpectrum && constructor.
553}
554
555
557{
558 // Calls the destructor for each DataPoint object in the vector.
559 clear();
560}
561
562
563size_t
564Trace::initialize(const std::vector<pappso_double> &xVector,
565 const std::vector<pappso_double> &yVector)
566{
567 // Sanity check
568 if(xVector.size() != yVector.size())
569 throw ExceptionNotPossible("trace.cpp -- ERROR xVector and yVector must have the same size.");
570
571 // We are initializing, not appending.
572 erase(begin(), end());
573
574 for(std::size_t iter = 0; iter < xVector.size(); ++iter)
575 {
576 push_back(DataPoint(xVector.at(iter), yVector.at(iter)));
577 }
578
579 sortX();
580 // std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
581 // return (a.x < b.x);
582 //});
583
584#if 0
585 for(auto &item : *this)
586 {
587 std::cout << item.x << "-" << item.y;
588 }
589#endif
590
591 return size();
592}
593
594
595size_t
596Trace::initialize(const std::map<pappso_double, pappso_double> &map)
597{
598
599 // We are initializing, not appending.
600 erase(begin(), end());
601
602 for(auto &&item : map)
603 {
604 push_back(DataPoint(item.first, item.second));
605 }
606
607 // No need to sort, maps are sorted by key (that is, x).
608
609 return size();
610}
611
612
613size_t
615{
616 *this = other;
617
618 return size();
619}
620
621
622size_t
623Trace::append(const DataPoint &data_point)
624{
625 push_back(data_point);
626
627 return size();
628}
629
630
631Trace &
633{
634 assign(other.begin(), other.end());
635
636 return *this;
637}
638
639
640Trace &
642{
643 vector<DataPoint>::operator=(std::move(other));
644 return *this;
645}
646
647
650{
651 return std::make_shared<Trace>(*this);
652}
653
654
657{
658 return std::make_shared<const Trace>(*this);
659}
660
661
662std::vector<pappso_double>
664{
665 std::vector<pappso_double> values;
666
667 for(auto &&dataPoint : *this)
668 {
669 values.push_back(dataPoint.x);
670 }
671
672 return values;
673}
674
675
676std::vector<pappso_double>
678{
679 std::vector<pappso_double> values;
680
681 for(auto &&dataPoint : *this)
682 {
683 values.push_back(dataPoint.y);
684 }
685
686 return values;
687}
688
689
690std::map<pappso_double, pappso_double>
692{
693 std::map<pappso_double, pappso_double> map;
694
695 std::pair<std::map<pappso_double, pappso_double>::iterator, bool> ret;
696
697 for(auto &&dataPoint : *this)
698 {
699 ret = map.insert(std::pair<pappso_double, pappso_double>(dataPoint.x, dataPoint.y));
700
701 if(ret.second == false)
702 {
703 qDebug() << "It is odd that the Trace contains multiple same keys.";
704
705 // No insertion, then increment the y value.
706 ret.first->second += dataPoint.y;
707 }
708 }
709
710 return map;
711}
712
713
714// const DataPoint &
715// Trace::dataPointWithX(pappso_double value) const
716//{
717// auto iterator =
718// std::find_if(begin(), end(), [value](const DataPoint &dataPoint) {
719// return (dataPoint.x == value);
720//});
721
722// if(iterator != end())
723//{
724//// The returned data point is valid.
725// return *iterator;
726//}
727// else
728//{
729//// The returned data point is invalid because it is not initialized.
730// return DataPoint();
731//}
732//}
733
734
735std::vector<DataPoint>::iterator
737{
738 auto iterator = std::find_if(
739 begin(), end(), [value](const DataPoint &dataPoint) { return (dataPoint.x == value); });
740
741 return iterator;
742}
743
744
745std::vector<DataPoint>::const_iterator
747{
748 auto iterator = std::find_if(
749 begin(), end(), [value](const DataPoint &dataPoint) { return (dataPoint.x == value); });
750
751 return iterator;
752}
753
754
755std::size_t
757{
758 std::vector<DataPoint>::const_iterator iterator = dataPointCstIteratorWithX(value);
759
760 if(iterator != end())
761 return std::distance(begin(), iterator);
762
763 return std::numeric_limits<std::size_t>::max();
764}
765
766
769{
770 // std::cout << std::setprecision(10) << "getting value: " << value
771 //<< " and precision: " << precision_p->getNominal() << std::endl;
772
773 pappso_double delta = precision_p->delta(value);
774
775 double left_most = value - delta;
776 double right_most = value + delta;
777
778 // std::cout << std::setprecision(10) << "delta: " << delta
779 //<< " left_most: " << left_most << " right_most: " << right_most
780 //<< std::endl;
781
782 auto iterator =
783 std::find_if(begin(),
784 end(),
785 [value, precision_p, delta, left_most, right_most](const DataPoint &data_point) {
786 if(precision_p)
787 {
788
789 // FIXME: unbelievable behaviour: when building in
790 // release mode this code, under i386 (but not x86_64),
791 // this code fails if the following%S statement is
792 // missing.
793
794 // std::cout << std::setprecision(10)
795 //<< "Testing data_point.x: " << data_point.x
796 //<< std::endl;
797
798 // For this reason I had to deactivate the related tests
799 // for i386 in tests/test_trace.cpp
800
801 double diff_to_left_most = data_point.x - left_most;
802 double diff_to_right_most = data_point.x - right_most;
803
804 // std::cout << std::setprecision(10)
805 //<< "diff_to_left_most: " << diff_to_left_most
806 //<< " diff_to_right_most: " << diff_to_right_most <<
807 // std::endl;
808
809 // if(diff_to_left_most > 0)
810 //{
811 // std::cout << std::setprecision(10)
812 //<< " point is right of left_most: " <<
813 // diff_to_left_most
814 //<< std::endl;
815 //}
816 // if(diff_to_left_most < 0)
817 //{
818 // std::cout << std::setprecision(10)
819 //<< "point is left of left_most: " << diff_to_left_most
820 //<< std::endl;
821 //}
822 // if(!diff_to_left_most)
823 //{
824 // std::cout << std::setprecision(10)
825 //<< "point is spot on left_most: " << diff_to_left_most
826 //<< std::endl;
827 //}
828
829 // if(diff_to_right_most > 0)
830 //{
831 // std::cout << std::setprecision(10)
832 //<< "point is right of right_most: " <<
833 // diff_to_right_most
834 //<< std::endl;
835 //}
836 // if(diff_to_right_most < 0)
837 //{
838 // std::cout << std::setprecision(10)
839 //<< "point is left or of right_most: "
840 //<< diff_to_right_most << std::endl;
841 //}
842 // if(!diff_to_right_most)
843 //{
844 // std::cout << std::setprecision(10)
845 //<< "point is spot on right_most: " <<
846 // diff_to_right_most
847 //<< std::endl;
848 //}
849
850 if(diff_to_left_most >= 0 && diff_to_right_most <= 0)
851 {
852 // std::cout << "The point is inside the range,
853 // should return true."
854 //<< std::endl;
855 return true;
856 }
857 else
858 {
859 // std::cout
860 //<< "The point is outside the range, should return
861 // false."
862 //<< std::endl;
863 return false;
864 }
865 }
866 else
867 {
868 return (data_point.x == value);
869 }
870 });
871
872 if(iterator != end())
873 {
874 // The returned data point is valid.
875 return *iterator;
876 }
877 else
878 {
879 // The returned data point is invalid because it is not initialized.
880 return DataPoint();
881 }
882}
883
884
885const DataPoint &
887{
888 auto dataPoint = std::min_element(
889 begin(), end(), [](const DataPoint &a, const DataPoint &b) { return (a.x < b.x); });
890
891 if(dataPoint == end())
892 {
894 QObject::tr("unable to get min peak x on spectrum size %1").arg(size()));
895 }
896
897 return (*dataPoint);
898}
899
900
901const DataPoint &
903{
904 auto dataPoint = std::max_element(
905 begin(), end(), [](const DataPoint &a, const DataPoint &b) { return (a.x < b.x); });
906
907 if(dataPoint == end())
908 {
910 QObject::tr("unable to get max peak x on spectrum size %1").arg(size()));
911 }
912
913 return (*dataPoint);
914}
915
916
917const DataPoint &
919{
920 auto dataPoint = std::min_element(
921 begin(), end(), [](const DataPoint &a, const DataPoint &b) { return (a.y < b.y); });
922
923 if(dataPoint == end())
924 {
926 QObject::tr("unable to get min peak intensity on spectrum size %1").arg(size()));
927 }
928
929 return (*dataPoint);
930}
931
932
933const DataPoint &
935{
936 auto dataPoint = std::max_element(
937 begin(), end(), [](const DataPoint &a, const DataPoint &b) { return (a.y < b.y); });
938
939 if(dataPoint == end())
940 {
942 QObject::tr("unable to get max peak intensity on spectrum size %1").arg(size()));
943 }
944
945 return (*dataPoint);
946}
947
948
951{
952 return minXDataPoint().x;
953}
954
955
958{
959 return maxXDataPoint().x;
960}
961
962
965{
966 return minYDataPoint().y;
967}
968
969
972{
973 return maxYDataPoint().y;
974}
975
976
979{
980 // double sum = 0;
981
982 // for(auto &&dp : m_dataPoints)
983 // sum += dp.y;
984
985 // qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << " ()"
986 //<< "Returning sum/tic:" << sum;
987
988 // return sum;
989
990 return std::accumulate(
991 begin(), end(), (double)0, [](pappso_double sum, const DataPoint &dataPoint) {
992 return (sum + dataPoint.y);
993 });
994}
995
996
998Trace::sumY(double mzStart, double mzEnd) const
999{
1000 auto begin_it = findFirstEqualOrGreaterX(this->begin(), this->end(), mzStart);
1001 auto end_it = findFirstGreaterX(begin_it, this->end(), mzEnd);
1002
1003 return sumYTrace(begin_it, end_it, 0);
1004}
1005
1006
1008Trace::maxY(double mzStart, double mzEnd) const
1009{
1010 std::vector<DataPoint>::const_iterator begin_it =
1011 findFirstEqualOrGreaterX(this->begin(), this->end(), mzStart);
1012
1013 double max_y = 0;
1014
1015 while(begin_it != findFirstGreaterX(begin_it, this->end(), mzEnd))
1016 {
1017 if(begin_it->y > max_y)
1018 max_y = begin_it->y;
1019 begin_it++;
1020 }
1021 return max_y;
1022}
1023
1024
1025void
1027{
1028 if(sort_type == Enums::SortType::none)
1029 return;
1030
1031 if(sort_type == Enums::SortType::x)
1032 return sortX(sort_order);
1033 else
1034 return sortY(sort_order);
1035}
1036
1037
1038void
1040{
1041 if(sort_order == Enums::SortOrder::ascending)
1042 std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) { return (a.x < b.x); });
1043 else
1044 std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) { return (a.x > b.x); });
1045}
1046
1047
1048void
1050{
1051 if(sort_order == Enums::SortOrder::ascending)
1052 std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) { return (a.y < b.y); });
1053 else
1054 std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) { return (a.y > b.y); });
1055}
1056
1057
1058void
1060{
1061 auto last = std::unique(
1062 begin(), end(), [](const DataPoint &a, const DataPoint &b) { return (a.x == b.x); });
1063
1064 erase(last, end());
1065}
1066
1067
1068std::size_t
1070{
1071 qDebug();
1072
1073 auto it = begin();
1074 auto end_it = end();
1075
1076 std::size_t count = 0;
1077
1078 while(it != end_it)
1079 {
1080 if(Utils::almostEqual(it->y, 0))
1081 {
1082 // erase returns an iterator to the next item in the vector.
1083 it = erase(it);
1084 ++count;
1085 }
1086 else
1087 // We need to increment (no call to erase here).
1088 ++it;
1089 }
1090
1091 return count;
1092}
1093
1094
1095QString
1097{
1098 // Even if the spectrum is empty, we should return an empty string.
1099 QString text;
1100
1101 for(auto &&dataPoint : *this)
1102 {
1103 text.append(QString("%1\n").arg(dataPoint.toString()));
1104 }
1105
1106 return text;
1107}
1108
1109
1110QByteArray
1112{
1113 QByteArray unencoded_array;
1114
1115 for(auto &&data_point : *this)
1116 {
1117 QByteArray local_array;
1118 local_array.setNum(data_point.x, 'f', 12);
1119 local_array.append("\n");
1120
1121 unencoded_array.append(local_array);
1122 }
1123
1124 QByteArray base64_encoded_array =
1125 unencoded_array.toBase64(QByteArray::Base64Encoding | QByteArray::OmitTrailingEquals);
1126
1127 return base64_encoded_array;
1128}
1129
1130
1131QByteArray
1133{
1134 QByteArray unencoded_array;
1135
1136 for(auto &&data_point : *this)
1137 {
1138 QByteArray local_array;
1139 local_array.setNum(data_point.y, 'f', 12);
1140 local_array.append("\n");
1141
1142 unencoded_array.append(local_array);
1143 }
1144
1145 QByteArray base64_encoded_array =
1146 unencoded_array.toBase64(QByteArray::Base64Encoding | QByteArray::OmitTrailingEquals);
1147
1148 return base64_encoded_array;
1149}
1150
1151
1152Trace &
1154{
1155 return filter.filter(*this);
1156}
1157
1158} // namespace pappso
generic interface to apply a filter on a trace
virtual pappso_double delta(pappso_double value) const =0
A simple container of DataPoint instances.
Definition trace.h:148
virtual Trace & operator=(const Trace &x)
Definition trace.cpp:632
void unique()
Definition trace.cpp:1059
pappso_double maxY() const
Definition trace.cpp:971
pappso_double sumY() const
Definition trace.cpp:978
const DataPoint & maxYDataPoint() const
Definition trace.cpp:934
std::map< pappso_double, pappso_double > toMap() const
Definition trace.cpp:691
std::vector< pappso_double > xValues() const
Definition trace.cpp:663
const DataPoint & maxXDataPoint() const
Definition trace.cpp:902
pappso_double minX() const
Definition trace.cpp:950
QByteArray yAsBase64Encoded() const
Definition trace.cpp:1132
pappso_double maxX() const
Definition trace.cpp:957
void sort(Enums::SortType sort_type, Enums::SortOrder sort_order=Enums::SortOrder::ascending)
Definition trace.cpp:1026
QByteArray xAsBase64Encoded() const
Definition trace.cpp:1111
void sortY(Enums::SortOrder sort_order=Enums::SortOrder::ascending)
Definition trace.cpp:1049
TraceCstSPtr makeTraceCstSPtr() const
Definition trace.cpp:656
virtual Trace & filter(const FilterInterface &filter) final
apply a filter on this trace
Definition trace.cpp:1153
DataPoint containsX(pappso_double value, PrecisionPtr precision_p=nullptr) const
Definition trace.cpp:768
std::vector< pappso_double > yValues() const
Definition trace.cpp:677
pappso_double minY() const
Definition trace.cpp:964
virtual ~Trace()
Definition trace.cpp:556
size_t initialize(const std::vector< pappso_double > &xVector, const std::vector< pappso_double > &yVector)
Definition trace.cpp:564
void sortX(Enums::SortOrder sort_order=Enums::SortOrder::ascending)
Definition trace.cpp:1039
size_t append(const DataPoint &data_point)
appends a datapoint and return new size
Definition trace.cpp:623
std::size_t dataPointIndexWithX(pappso_double value) const
Definition trace.cpp:756
const DataPoint & minXDataPoint() const
Definition trace.cpp:886
std::vector< DataPoint >::const_iterator dataPointCstIteratorWithX(pappso_double value) const
find datapoint with exactly x value
Definition trace.cpp:746
std::vector< DataPoint >::iterator dataPointIteratorWithX(pappso_double value)
Definition trace.cpp:736
const DataPoint & minYDataPoint() const
Definition trace.cpp:918
TraceSPtr makeTraceSPtr() const
Definition trace.cpp:649
std::size_t removeZeroYDataPoints()
Definition trace.cpp:1069
QString toString() const
Definition trace.cpp:1096
static bool almostEqual(double value1, double value2, int decimalPlaces=10)
Definition utils.cpp:299
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition aa.cpp:39
std::shared_ptr< const Trace > TraceCstSPtr
Definition trace.h:136
std::vector< DataPoint >::iterator findDifferentYvalue(std::vector< DataPoint >::iterator begin, std::vector< DataPoint >::iterator end, const double &y_value)
find the first element in which Y is different of value
Definition trace.cpp:126
std::vector< DataPoint >::iterator findFirstEqualOrGreaterX(std::vector< DataPoint >::iterator begin, std::vector< DataPoint >::iterator end, const double &value)
find the first element in which X is equal or greater than the value searched important : it implies ...
Definition trace.cpp:70
std::vector< DataPoint >::iterator findFirstGreaterX(std::vector< DataPoint >::iterator begin, std::vector< DataPoint >::iterator end, const double &value)
find the first element in which X is greater than the value searched important : it implies that Trac...
Definition trace.cpp:98
QDataStream & operator<<(QDataStream &outstream, const MassSpectrum &massSpectrum)
QDataStream & operator>>(QDataStream &instream, MassSpectrum &massSpectrum)
std::vector< DataPoint >::const_iterator moveLowerYLeftDataPoint(const Trace &trace, std::vector< DataPoint >::const_iterator begin)
Move left to the lower value.
Definition trace.cpp:211
std::vector< DataPoint >::const_iterator maxYDataPoint(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end)
Definition trace.cpp:174
double medianYTrace(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end)
calculate the median of y value of a trace
Definition trace.cpp:272
double areaTrace(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end)
calculate the area of a trace
Definition trace.cpp:288
std::shared_ptr< Trace > TraceSPtr
Definition trace.h:135
double pappso_double
A type definition for doubles.
Definition types.h:61
double meanYTrace(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end)
calculate the mean of y value of a trace
Definition trace.cpp:239
const PrecisionBase * PrecisionPtr
Definition precision.h:122
std::vector< DataPoint >::const_iterator moveLowerYRigthDataPoint(const Trace &trace, std::vector< DataPoint >::const_iterator begin)
Move right to the lower value.
Definition trace.cpp:194
double sumYTrace(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end, double init)
calculate the sum of y value of a trace
Definition trace.cpp:231
std::vector< DataPoint >::const_iterator minYDataPoint(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end)
Definition trace.cpp:157
double quantileYTrace(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end, double quantile)
calculate the quantile of y value of a trace
Definition trace.cpp:249
Trace flooredLocalMaxima(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end, double y_floor)
Definition trace.cpp:307
pappso_double x
Definition datapoint.h:24
pappso_double y
Definition datapoint.h:25
int traceMetaTypeId
Definition trace.cpp:27
int tracePtrMetaTypeId
Definition trace.cpp:28