libpappsomspp
Library for mass spectrometry
trace.cpp
Go to the documentation of this file.
1 #include <numeric>
2 #include <limits>
3 #include <vector>
4 #include <map>
5 #include <cmath>
6 #include <algorithm>
7 #include <iostream>
8 #include <iomanip>
9 
10 #include <QDebug>
11 
12 #include "trace.h"
13 #include "maptrace.h"
14 #include "../processing/combiners/tracepluscombiner.h"
15 #include "../processing/combiners/traceminuscombiner.h"
16 #include "../types.h"
17 #include "../pappsoexception.h"
18 #include "../exception/exceptionoutofrange.h"
19 #include "../exception/exceptionnotpossible.h"
20 #include "../processing/filters/filterresample.h"
21 #include "../processing/filters/filterpass.h"
22 
23 
24 int traceMetaTypeId = qRegisterMetaType<pappso::Trace>("pappso::Trace");
25 int tracePtrMetaTypeId = qRegisterMetaType<pappso::Trace *>("pappso::Trace *");
26 
27 
28 namespace pappso
29 {
30 
31 std::vector<DataPoint>::iterator
32 findFirstEqualOrGreaterX(std::vector<DataPoint>::iterator begin,
33  std::vector<DataPoint>::iterator end,
34  const double &value)
35 {
36  return std::find_if(begin, end, [value](const DataPoint &to_compare) {
37  if(to_compare.x < value)
38  {
39  return false;
40  }
41  return true;
42  });
43 }
44 
45 std::vector<DataPoint>::const_iterator
46 findFirstEqualOrGreaterX(std::vector<DataPoint>::const_iterator begin,
47  std::vector<DataPoint>::const_iterator end,
48  const double &value)
49 {
50  return std::find_if(begin, end, [value](const DataPoint &to_compare) {
51  if(to_compare.x < value)
52  {
53  return false;
54  }
55  return true;
56  });
57 }
58 
59 std::vector<DataPoint>::iterator
60 findFirstGreaterX(std::vector<DataPoint>::iterator begin,
61  std::vector<DataPoint>::iterator end,
62  const double &value)
63 {
64  return std::find_if(begin, end, [value](const DataPoint &to_compare) {
65  if(to_compare.x > value)
66  {
67  return true;
68  }
69  return false;
70  });
71 }
72 
73 std::vector<DataPoint>::const_iterator
74 findFirstGreaterX(std::vector<DataPoint>::const_iterator begin,
75  std::vector<DataPoint>::const_iterator end,
76  const double &value)
77 {
78  return std::find_if(begin, end, [value](const DataPoint &to_compare) {
79  if(to_compare.x > value)
80  {
81  return true;
82  }
83  return false;
84  });
85 }
86 
87 std::vector<DataPoint>::iterator
88 findDifferentYvalue(std::vector<DataPoint>::iterator begin,
89  std::vector<DataPoint>::iterator end,
90  const double &y_value)
91 {
92  return std::find_if(begin, end, [y_value](const DataPoint &to_compare) {
93  if(to_compare.y != y_value)
94  {
95  return true;
96  }
97 
98  return false;
99  });
100 }
101 
102 std::vector<DataPoint>::const_iterator
103 findDifferentYvalue(std::vector<DataPoint>::const_iterator begin,
104  std::vector<DataPoint>::const_iterator end,
105  const double &y_value)
106 {
107  return std::find_if(begin, end, [y_value](const DataPoint &to_compare) {
108  if(to_compare.y != y_value)
109  {
110  return true;
111  }
112 
113  return false;
114  });
115 }
116 
117 
118 std::vector<DataPoint>::const_iterator
119 minYDataPoint(std::vector<DataPoint>::const_iterator begin,
120  std::vector<DataPoint>::const_iterator end)
121 {
122  return std::min_element(
123  begin, end, [](const DataPoint &a, const DataPoint &b) {
124  return a.y < b.y;
125  });
126 }
127 
128 
129 std::vector<DataPoint>::iterator
130 minYDataPoint(std::vector<DataPoint>::iterator begin,
131  std::vector<DataPoint>::iterator end)
132 {
133  return std::min_element(
134  begin, end, [](const DataPoint &a, const DataPoint &b) {
135  return a.y < b.y;
136  });
137 }
138 
139 
140 std::vector<DataPoint>::const_iterator
141 maxYDataPoint(std::vector<DataPoint>::const_iterator begin,
142  std::vector<DataPoint>::const_iterator end)
143 {
144  return std::max_element(
145  begin, end, [](const DataPoint &a, const DataPoint &b) {
146  return a.y < b.y;
147  });
148 }
149 
150 
151 std::vector<DataPoint>::iterator
152 maxYDataPoint(std::vector<DataPoint>::iterator begin,
153  std::vector<DataPoint>::iterator end)
154 {
155  return std::max_element(
156  begin, end, [](const DataPoint &a, const DataPoint &b) {
157  return a.y < b.y;
158  });
159 }
160 
161 
162 // As long as next DataPoint has its y value less or equal to prev's,
163 // move along down the container. That is, continue moving is
164 // direction is downhill to the end of the container (its back).
165 std::vector<DataPoint>::const_iterator
167  std::vector<DataPoint>::const_iterator begin)
168 {
169  if(begin == trace.end())
170  return begin;
171  auto it = begin + 1;
172  auto result = begin;
173  // Move along as long as next point's y value is less
174  // or equal to prev point's y value (FR, check).
175  while((it != trace.end()) && (it->y <= result->y))
176  {
177  it++;
178  result++;
179  }
180  return result;
181 }
182 
183 std::vector<DataPoint>::const_iterator
185  std::vector<DataPoint>::const_iterator begin)
186 {
187  if(begin == trace.begin())
188  return begin;
189  auto it = begin - 1;
190  auto result = begin;
191 
192  // As long as prev datapoint has y value less or equal to next,
193  // move along up the container. That is, continue moving if
194  // direction is downhill to the beginning of the container (its front).
195  while((it != trace.begin()) && (it->y <= result->y))
196  {
197  it--;
198  result--;
199  }
200  return result;
201 }
202 
203 
204 double
205 sumYTrace(std::vector<DataPoint>::const_iterator begin,
206  std::vector<DataPoint>::const_iterator end,
207  double init)
208 {
209  return std::accumulate(
210  begin, end, init, [](double a, const DataPoint &b) { return a + b.y; });
211 }
212 
213 double
214 meanYTrace(std::vector<DataPoint>::const_iterator begin,
215  std::vector<DataPoint>::const_iterator end)
216 {
217  pappso_double nb_element = distance(begin, end);
218  if(nb_element == 0)
219  throw ExceptionOutOfRange(
220  QObject::tr("unable to compute mean on a trace of size 0"));
221  return (sumYTrace(begin, end, 0) / nb_element);
222 }
223 
224 
225 double
226 quantileYTrace(std::vector<DataPoint>::const_iterator begin,
227  std::vector<DataPoint>::const_iterator end,
228  double quantile)
229 {
230  std::size_t nb_element = distance(begin, end);
231  if(nb_element == 0)
232  throw ExceptionOutOfRange(
233  QObject::tr("unable to compute quantile on a trace of size 0"));
234 
235 
236  std::size_t ieth_element = std::round((double)nb_element * quantile);
237  if(ieth_element > nb_element)
238  throw ExceptionOutOfRange(
239  QObject::tr("quantile value must be lower than 1"));
240 
241 
242  std::vector<DataPoint> data(begin, end);
243  std::nth_element(
244  data.begin(),
245  data.begin() + ieth_element,
246  data.end(),
247  [](const DataPoint &a, const DataPoint &b) { return a.y < b.y; });
248  return data[ieth_element].y;
249 }
250 
251 double
252 medianYTrace(std::vector<DataPoint>::const_iterator begin,
253  std::vector<DataPoint>::const_iterator end)
254 {
255  std::size_t nb_element = distance(begin, end);
256  if(nb_element == 0)
257  throw ExceptionOutOfRange(
258  QObject::tr("unable to compute median on a trace of size 0"));
259 
260  std::vector<DataPoint> data(begin, end);
261  std::nth_element(
262  data.begin(),
263  data.begin() + data.size() / 2,
264  data.end(),
265  [](const DataPoint &a, const DataPoint &b) { return a.y < b.y; });
266  return data[data.size() / 2].y;
267 }
268 
269 double
270 areaTrace(std::vector<DataPoint>::const_iterator begin,
271  std::vector<DataPoint>::const_iterator end)
272 {
273 
274  if(begin == end)
275  return 0;
276  auto previous = begin;
277  auto next = begin + 1;
278  double area = 0;
279  while(next != end)
280  {
281  area += ((next->x - previous->x) * (previous->y + next->y)) / (double)2;
282  previous++;
283  next++;
284  }
285  return area;
286 }
287 
288 
289 double
290 areaTraceMinusBase(std::vector<DataPoint>::const_iterator begin,
291  std::vector<DataPoint>::const_iterator end)
292 {
293 
294  if(begin == end)
295  return 0;
296  auto previous = begin;
297  auto next = begin + 1;
298  auto last = next;
299  double area = 0;
300  while(next != end)
301  {
302  last = next;
303  area += ((next->x - previous->x) * (previous->y + next->y)) / (double)2;
304  previous++;
305  next++;
306  }
307  if(area > 0)
308  {
309  // remove base peak area
310  area -= (((last->y + begin->y) * (last->x - begin->x)) / 2);
311  if(area < 0)
312  return 0;
313  }
314  return area;
315 }
316 
317 
318 Trace
319 flooredLocalMaxima(std::vector<DataPoint>::const_iterator begin,
320  std::vector<DataPoint>::const_iterator end,
321  double y_floor)
322 {
323  Trace local_maxima_trace;
324 
325  Trace single_peak_trace;
326 
327  DataPoint previous_data_point;
328 
329  for(auto iter = begin; iter != end; ++iter)
330  {
331  DataPoint iterated_data_point(iter->x, iter->y);
332 
333  // qDebug().noquote() << "Current data point:"
334  //<< iterated_data_point.toString();
335 
336  if(iterated_data_point.y < y_floor)
337  {
338  // qDebug() << "under the floor";
339 
340  if(single_peak_trace.size())
341  {
342  // qDebug() << "There was a single peak trace cooking";
343 
344  local_maxima_trace.push_back(single_peak_trace.maxYDataPoint());
345 
346  // qDebug().noquote() << "pushed back local maximum point:"
347  //<< local_maxima_trace.back().toString();
348 
349  // Clean and set the context.
350  single_peak_trace.clear();
351 
352  previous_data_point = iterated_data_point;
353 
354  continue;
355  }
356  else
357  {
358  // qDebug() << "no single peak trace cooking";
359 
360  previous_data_point = iterated_data_point;
361 
362  continue;
363  }
364  }
365  else
366  {
367  // qDebug() << "over the floor";
368 
369  // The iterated value is greater than the y_floor value, so we need to
370  // handle it.
371 
372  if(iterated_data_point.y == previous_data_point.y)
373  {
374  // We are in a flat region, no need to change anything to the
375  // context, just skip the point.
376  continue;
377  }
378  else if(iterated_data_point.y > previous_data_point.y)
379  {
380  // qDebug().noquote() << "ascending in a peak";
381 
382  // The previously iterated y value was smaller than the presently
383  // iterated one, so we are ascending in a peak.
384 
385  // All we need to do is set the context.
386 
387  single_peak_trace.push_back(iterated_data_point);
388 
389  // qDebug().noquote() << "pushed back normal point:"
390  //<< single_peak_trace.back().toString();
391 
392  previous_data_point = iterated_data_point;
393 
394  continue;
395  }
396  else
397  {
398  // qDebug().noquote() << "started descending in a peak";
399 
400  // No, the currently iterated y value is less than the previously
401  // iterated value.
402 
403  single_peak_trace.push_back(iterated_data_point);
404 
405  // qDebug().noquote() << "pushed back normal point:"
406  //<< single_peak_trace.back().toString();
407 
408  previous_data_point = iterated_data_point;
409 
410  continue;
411  }
412  }
413  }
414  // End of
415  // for(auto iter = begin; iter != end; ++iter)
416 
417  // Attention, we might arrive here with a peak being created, we need to get
418  // its maximum if that peak is non-empty;
419 
420  if(single_peak_trace.size())
421  {
422 
423  local_maxima_trace.push_back(single_peak_trace.maxYDataPoint());
424 
425  // qDebug().noquote()
426  //<< "was cooking a peak: pushed back local maximum point:"
427  //<< local_maxima_trace.back().toString();
428  }
429 
430  return local_maxima_trace;
431 }
432 
433 
435 {
436 }
437 
438 
439 Trace::Trace(const std::vector<pappso_double> &xVector,
440  const std::vector<pappso_double> &yVector)
441 {
442  initialize(xVector, yVector);
443 }
444 
445 
447  const std::vector<std::pair<pappso_double, pappso_double>> &dataPoints)
448 {
449  reserve(dataPoints.size());
450 
451  for(auto &dataPoint : dataPoints)
452  {
453  push_back(DataPoint(dataPoint));
454  }
455 
456  sortX();
457  // std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
458  // return (a.x < b.x);
459  //});
460 }
461 
462 
463 Trace::Trace(const std::vector<DataPoint> &dataPoints)
464  : std::vector<DataPoint>(dataPoints)
465 {
466  sortX();
467  // std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
468  // return (a.x < b.x);
469  //});
470 }
471 
472 
473 Trace::Trace(const std::vector<DataPoint> &&dataPoints)
474  : std::vector<DataPoint>(std::move(dataPoints))
475 {
476  // This constructor used by the MassSpectrum && constructor.
477 
478  sortX();
479  // std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
480  // return (a.x < b.x);
481  //});
482 }
483 
484 
485 Trace::Trace(const MapTrace &map_trace)
486 {
487  for(auto &&item : map_trace)
488  push_back(DataPoint(item.first, item.second));
489 
490  // No need to sort, maps are sorted by key (that is, x).
491 }
492 
493 Trace::Trace(const Trace &other) : std::vector<DataPoint>(other)
494 {
495 }
496 
497 
498 Trace::Trace(const Trace &&other) : std::vector<DataPoint>(std::move(other))
499 {
500  // This constructor used by the MassSpectrum && constructor.
501 }
502 
503 
505 {
506  // Calls the destructor for each DataPoint object in the vector.
507  clear();
508 }
509 
510 
511 size_t
512 Trace::initialize(const std::vector<pappso_double> &xVector,
513  const std::vector<pappso_double> &yVector)
514 {
515  // Sanity check
516  if(xVector.size() != yVector.size())
517  throw ExceptionNotPossible(
518  "trace.cpp -- ERROR xVector and yVector must have the same size.");
519 
520  // We are initializing, not appending.
521  erase(begin(), end());
522 
523  for(std::size_t iter = 0; iter < xVector.size(); ++iter)
524  {
525  push_back(DataPoint(xVector.at(iter), yVector.at(iter)));
526  }
527 
528  sortX();
529  // std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
530  // return (a.x < b.x);
531  //});
532 
533 #if 0
534  for(auto &item : *this)
535  {
536  std::cout << item.x << "-" << item.y;
537  }
538 #endif
539 
540  return size();
541 }
542 
543 
544 size_t
545 Trace::initialize(const std::map<pappso_double, pappso_double> &map)
546 {
547 
548  // We are initializing, not appending.
549  erase(begin(), end());
550 
551  for(auto &&item : map)
552  {
553  push_back(DataPoint(item.first, item.second));
554  }
555 
556  // No need to sort, maps are sorted by key (that is, x).
557 
558  return size();
559 }
560 
561 
562 size_t
564 {
565  *this = other;
566 
567  return size();
568 }
569 
570 
571 Trace &
572 Trace::operator=(const Trace &other)
573 {
574  assign(other.begin(), other.end());
575 
576  return *this;
577 }
578 
579 
580 Trace &
582 {
583  vector<DataPoint>::operator=(std::move(other));
584  return *this;
585 }
586 
587 
588 TraceSPtr
590 {
591  return std::make_shared<Trace>(*this);
592 }
593 
594 
597 {
598  return std::make_shared<const Trace>(*this);
599 }
600 
601 
602 std::vector<pappso_double>
604 {
605  std::vector<pappso_double> values;
606 
607  for(auto &&dataPoint : *this)
608  {
609  values.push_back(dataPoint.x);
610  }
611 
612  return values;
613 }
614 
615 
616 std::vector<pappso_double>
618 {
619  std::vector<pappso_double> values;
620 
621  for(auto &&dataPoint : *this)
622  {
623  values.push_back(dataPoint.y);
624  }
625 
626  return values;
627 }
628 
629 
630 std::map<pappso_double, pappso_double>
632 {
633  std::map<pappso_double, pappso_double> map;
634 
635  std::pair<std::map<pappso_double, pappso_double>::iterator, bool> ret;
636 
637  for(auto &&dataPoint : *this)
638  {
639  ret = map.insert(
640  std::pair<pappso_double, pappso_double>(dataPoint.x, dataPoint.y));
641 
642  if(ret.second == false)
643  {
644  qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()"
645  << "It is odd that the Trace contains multiple same keys.";
646 
647  // No insertion, then increment the y value.
648  ret.first->second += dataPoint.y;
649  }
650  }
651 
652  return map;
653 }
654 
655 
656 // const DataPoint &
657 // Trace::dataPointWithX(pappso_double value) const
658 //{
659 // auto iterator =
660 // std::find_if(begin(), end(), [value](const DataPoint &dataPoint) {
661 // return (dataPoint.x == value);
662 //});
663 
664 // if(iterator != end())
665 //{
666 //// The returned data point is valid.
667 // return *iterator;
668 //}
669 // else
670 //{
671 //// The returned data point is invalid because it is not initialized.
672 // return DataPoint();
673 //}
674 //}
675 
676 
677 std::vector<DataPoint>::iterator
679 {
680  auto iterator =
681  std::find_if(begin(), end(), [value](const DataPoint &dataPoint) {
682  return (dataPoint.x == value);
683  });
684 
685  return iterator;
686 }
687 
688 
689 std::vector<DataPoint>::const_iterator
691 {
692  auto iterator =
693  std::find_if(begin(), end(), [value](const DataPoint &dataPoint) {
694  return (dataPoint.x == value);
695  });
696 
697  return iterator;
698 }
699 
700 
701 std::size_t
703 {
704  std::vector<DataPoint>::const_iterator iterator =
706 
707  if(iterator != end())
708  return std::distance(begin(), iterator);
709 
710  return std::numeric_limits<std::size_t>::max();
711 }
712 
713 
714 DataPoint
715 Trace::containsX(pappso_double value, PrecisionPtr precision_p) const
716 {
717  // std::cout << std::setprecision(10) << "getting value: " << value
718  //<< " and precision: " << precision_p->getNominal() << std::endl;
719 
720  pappso_double delta = precision_p->delta(value);
721 
722  double left_most = value - delta;
723  double right_most = value + delta;
724 
725  // std::cout << std::setprecision(10) << "delta: " << delta
726  //<< " left_most: " << left_most << " right_most: " << right_most
727  //<< std::endl;
728 
729  auto iterator =
730  std::find_if(begin(),
731  end(),
732  [value, precision_p, delta, left_most, right_most](
733  const DataPoint &data_point) {
734  if(precision_p)
735  {
736 
737  // FIXME: unbelievable behaviour: when building in
738  // release mode this code, under i386 (but not x86_64),
739  // this code fails if the following cout statement is
740  // missing.
741 
742  // std::cout << std::setprecision(10)
743  //<< "Testing data_point.x: " << data_point.x
744  //<< std::endl;
745 
746  // For this reason I had to deactivate the related tests
747  // for i386 in tests/test_trace.cpp
748 
749  double diff_to_left_most = data_point.x - left_most;
750  double diff_to_right_most = data_point.x - right_most;
751 
752  // std::cout << std::setprecision(10)
753  //<< "diff_to_left_most: " << diff_to_left_most
754  //<< " diff_to_right_most: " << diff_to_right_most <<
755  // std::endl;
756 
757  // if(diff_to_left_most > 0)
758  //{
759  // std::cout << std::setprecision(10)
760  //<< " point is right of left_most: " <<
761  // diff_to_left_most
762  //<< std::endl;
763  //}
764  // if(diff_to_left_most < 0)
765  //{
766  // std::cout << std::setprecision(10)
767  //<< "point is left of left_most: " << diff_to_left_most
768  //<< std::endl;
769  //}
770  // if(!diff_to_left_most)
771  //{
772  // std::cout << std::setprecision(10)
773  //<< "point is spot on left_most: " << diff_to_left_most
774  //<< std::endl;
775  //}
776 
777  // if(diff_to_right_most > 0)
778  //{
779  // std::cout << std::setprecision(10)
780  //<< "point is right of right_most: " <<
781  // diff_to_right_most
782  //<< std::endl;
783  //}
784  // if(diff_to_right_most < 0)
785  //{
786  // std::cout << std::setprecision(10)
787  //<< "point is left or of right_most: "
788  //<< diff_to_right_most << std::endl;
789  //}
790  // if(!diff_to_right_most)
791  //{
792  // std::cout << std::setprecision(10)
793  //<< "point is spot on right_most: " <<
794  // diff_to_right_most
795  //<< std::endl;
796  //}
797 
798  if(diff_to_left_most >= 0 && diff_to_right_most <= 0)
799  {
800  // std::cout << "The point is inside the range,
801  // should return true."
802  //<< std::endl;
803  return true;
804  }
805  else
806  {
807  // std::cout
808  //<< "The point is outside the range, should return
809  // false."
810  //<< std::endl;
811  return false;
812  }
813  }
814  else
815  {
816  return (data_point.x == value);
817  }
818  });
819 
820  if(iterator != end())
821  {
822  // The returned data point is valid.
823  return *iterator;
824  }
825  else
826  {
827  // The returned data point is invalid because it is not initialized.
828  return DataPoint();
829  }
830 }
831 
832 
833 const DataPoint &
835 {
836  auto dataPoint = std::min_element(
837  begin(), end(), [](const DataPoint &a, const DataPoint &b) {
838  return (a.y < b.y);
839  });
840 
841  if(dataPoint == end())
842  {
843  throw ExceptionOutOfRange(
844  QObject::tr("unable to get min peak intensity on spectrum size %1")
845  .arg(size()));
846  }
847 
848  return (*dataPoint);
849 }
850 
851 
852 const DataPoint &
854 {
855  auto dataPoint = std::max_element(
856  begin(), end(), [](const DataPoint &a, const DataPoint &b) {
857  return (a.y < b.y);
858  });
859 
860  if(dataPoint == end())
861  {
862  throw ExceptionOutOfRange(
863  QObject::tr("unable to get max peak intensity on spectrum size %1")
864  .arg(size()));
865  }
866 
867  return (*dataPoint);
868 }
869 
870 
872 Trace::minY() const
873 {
874  return minYDataPoint().y;
875 }
876 
877 
879 Trace::maxY() const
880 {
881  return maxYDataPoint().y;
882 }
883 
884 
886 Trace::sumY() const
887 {
888  // double sum = 0;
889 
890  // for(auto &&dp : m_dataPoints)
891  // sum += dp.y;
892 
893  // qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << " ()"
894  //<< "Returning sum/tic:" << sum;
895 
896  // return sum;
897 
898  return std::accumulate(begin(),
899  end(),
900  (double)0,
901  [](pappso_double sum, const DataPoint &dataPoint) {
902  return (sum + dataPoint.y);
903  });
904 }
905 
906 
908 Trace::sumY(double mzStart, double mzEnd) const
909 {
910  auto begin_it = findFirstEqualOrGreaterX(this->begin(), this->end(), mzStart);
911  auto end_it = findFirstGreaterX(begin_it, this->end(), mzEnd);
912 
913  return sumYTrace(begin_it, end_it, 0);
914 }
915 
916 
918 Trace::maxY(double mzStart, double mzEnd) const
919 {
920  std::vector<DataPoint>::const_iterator begin_it =
921  findFirstEqualOrGreaterX(this->begin(), this->end(), mzStart);
922 
923  double max_y = 0;
924 
925  while(begin_it != findFirstGreaterX(begin_it, this->end(), mzEnd))
926  {
927  if(begin_it->y > max_y)
928  max_y = begin_it->y;
929  begin_it++;
930  }
931  return max_y;
932 }
933 
934 
935 void
937 {
938  std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
939  return (a.x < b.x);
940  });
941 }
942 
943 void
945 {
946  std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
947  return (a.y > b.y);
948  });
949 }
950 
951 void
953 {
954  auto last =
955  std::unique(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
956  return (a.x == b.x);
957  });
958 
959  erase(last, end());
960 }
961 
962 
963 QString
965 {
966  // Even if the spectrum is empty, we should return an empty string.
967  QString text;
968 
969  for(auto &&dataPoint : *this)
970  {
971  text.append(QString("%1 %2\n")
972  .arg(dataPoint.x, 0, 'f', 10)
973  .arg(dataPoint.y, 0, 'f', 10));
974  }
975 
976  return text;
977 }
978 
979 
980 Trace &
982 {
983  return filter.filter(*this);
984 }
985 
986 } // 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:147
virtual Trace & operator=(const Trace &x)
Definition: trace.cpp:572
void unique()
Definition: trace.cpp:952
pappso_double maxY() const
Definition: trace.cpp:879
pappso_double sumY() const
Definition: trace.cpp:886
void sortY()
Definition: trace.cpp:944
const DataPoint & maxYDataPoint() const
Definition: trace.cpp:853
std::map< pappso_double, pappso_double > toMap() const
Definition: trace.cpp:631
std::vector< pappso_double > xValues() const
Definition: trace.cpp:603
void sortX()
Definition: trace.cpp:936
TraceCstSPtr makeTraceCstSPtr() const
Definition: trace.cpp:596
virtual Trace & filter(const FilterInterface &filter) final
apply a filter on this trace
Definition: trace.cpp:981
DataPoint containsX(pappso_double value, PrecisionPtr precision_p=nullptr) const
Definition: trace.cpp:715
std::vector< pappso_double > yValues() const
Definition: trace.cpp:617
pappso_double minY() const
Definition: trace.cpp:872
virtual ~Trace()
Definition: trace.cpp:504
size_t initialize(const std::vector< pappso_double > &xVector, const std::vector< pappso_double > &yVector)
Definition: trace.cpp:512
std::size_t dataPointIndexWithX(pappso_double value) const
Definition: trace.cpp:702
std::vector< DataPoint >::const_iterator dataPointCstIteratorWithX(pappso_double value) const
find datapoint with exactly x value
Definition: trace.cpp:690
std::vector< DataPoint >::iterator dataPointIteratorWithX(pappso_double value)
Definition: trace.cpp:678
const DataPoint & minYDataPoint() const
Definition: trace.cpp:834
TraceSPtr makeTraceSPtr() const
Definition: trace.cpp:589
QString toString() const
Definition: trace.cpp:964
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:135
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:88
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:32
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:60
std::vector< DataPoint >::const_iterator moveLowerYLeftDataPoint(const Trace &trace, std::vector< DataPoint >::const_iterator begin)
Move left to the lower value.
Definition: trace.cpp:184
std::vector< DataPoint >::const_iterator maxYDataPoint(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end)
Definition: trace.cpp:141
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:252
double areaTrace(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end)
calculate the area of a trace
Definition: trace.cpp:270
std::shared_ptr< Trace > TraceSPtr
Definition: trace.h:134
double pappso_double
A type definition for doubles.
Definition: types.h:48
double areaTraceMinusBase(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end)
Definition: trace.cpp:290
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:214
std::vector< DataPoint >::const_iterator moveLowerYRigthDataPoint(const Trace &trace, std::vector< DataPoint >::const_iterator begin)
Move right to the lower value.
Definition: trace.cpp:166
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:205
std::vector< DataPoint >::const_iterator minYDataPoint(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end)
Definition: trace.cpp:119
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:226
@ sum
sum of intensities
Trace flooredLocalMaxima(std::vector< DataPoint >::const_iterator begin, std::vector< DataPoint >::const_iterator end, double y_floor)
Definition: trace.cpp:319
pappso_double x
Definition: datapoint.h:22
pappso_double y
Definition: datapoint.h:23
int traceMetaTypeId
Definition: trace.cpp:24
int tracePtrMetaTypeId
Definition: trace.cpp:25