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