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