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 #include <QObject>
12 
13 #include "trace.h"
14 #include "maptrace.h"
15 #include "../processing/combiners/tracepluscombiner.h"
16 #include "../processing/combiners/traceminuscombiner.h"
17 #include "../types.h"
18 #include "../pappsoexception.h"
19 #include "../exception/exceptionoutofrange.h"
20 #include "../exception/exceptionnotpossible.h"
21 #include "../processing/filters/filterresample.h"
22 #include "../processing/filters/filterpass.h"
23 
24 
25 int traceMetaTypeId = qRegisterMetaType<pappso::Trace>("pappso::Trace");
26 int tracePtrMetaTypeId = qRegisterMetaType<pappso::Trace *>("pappso::Trace *");
27 
28 
29 namespace pappso
30 {
31 
32 QDataStream &
33 operator<<(QDataStream &out, const Trace &trace)
34 {
35  for(auto &dataPoint : trace)
36  {
37  out << dataPoint.x;
38  out << dataPoint.y;
39  out << "\n";
40  }
41  out << "\n";
42 
43  return out;
44 }
45 
46 
47 QDataStream &
48 operator>>(QDataStream &in, Trace &trace)
49 {
50  if(in.atEnd())
51  {
52  throw PappsoException(
53  QString("error in QDataStream unserialize operator>> of trace:\n"
54  "read datastream failed status=%1")
55  .arg(in.status()));
56  }
57 
58  for(auto &dataPoint : trace)
59  {
60  in >> dataPoint.x;
61  in >> dataPoint.y;
62  }
63 
64  return in;
65 }
66 
67 
68 std::vector<DataPoint>::iterator
69 findFirstEqualOrGreaterX(std::vector<DataPoint>::iterator begin,
70  std::vector<DataPoint>::iterator end,
71  const double &value)
72 {
73  return std::find_if(begin, end, [value](const DataPoint &to_compare) {
74  if(to_compare.x < value)
75  {
76  return false;
77  }
78  return true;
79  });
80 }
81 
82 std::vector<DataPoint>::const_iterator
83 findFirstEqualOrGreaterX(std::vector<DataPoint>::const_iterator begin,
84  std::vector<DataPoint>::const_iterator end,
85  const double &value)
86 {
87  return std::find_if(begin, end, [value](const DataPoint &to_compare) {
88  if(to_compare.x < value)
89  {
90  return false;
91  }
92  return true;
93  });
94 }
95 
96 std::vector<DataPoint>::iterator
97 findFirstGreaterX(std::vector<DataPoint>::iterator begin,
98  std::vector<DataPoint>::iterator end,
99  const double &value)
100 {
101  return std::find_if(begin, end, [value](const DataPoint &to_compare) {
102  if(to_compare.x > value)
103  {
104  return true;
105  }
106  return false;
107  });
108 }
109 
110 std::vector<DataPoint>::const_iterator
111 findFirstGreaterX(std::vector<DataPoint>::const_iterator begin,
112  std::vector<DataPoint>::const_iterator end,
113  const double &value)
114 {
115  return std::find_if(begin, end, [value](const DataPoint &to_compare) {
116  if(to_compare.x > value)
117  {
118  return true;
119  }
120  return false;
121  });
122 }
123 
124 std::vector<DataPoint>::iterator
125 findDifferentYvalue(std::vector<DataPoint>::iterator begin,
126  std::vector<DataPoint>::iterator end,
127  const double &y_value)
128 {
129  return std::find_if(begin, end, [y_value](const DataPoint &to_compare) {
130 
131  if(to_compare.y != y_value)
132  {
133  return true;
134  }
135 
136  return false;
137  });
138 }
139 
140 std::vector<DataPoint>::const_iterator
141 findDifferentYvalue(std::vector<DataPoint>::const_iterator begin,
142  std::vector<DataPoint>::const_iterator end,
143  const double &y_value)
144 {
145  return std::find_if(begin, end, [y_value](const DataPoint &to_compare) {
146 
147  if(to_compare.y != y_value)
148  {
149  return true;
150  }
151 
152  return false;
153  });
154 }
155 
156 
157 std::vector<DataPoint>::const_iterator
158 minYDataPoint(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 
168 std::vector<DataPoint>::iterator
169 minYDataPoint(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 
179 std::vector<DataPoint>::const_iterator
180 maxYDataPoint(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 
190 std::vector<DataPoint>::iterator
191 maxYDataPoint(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).
204 std::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 
222 std::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 
243 double
244 sumYTrace(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 
252 double
253 meanYTrace(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)
258  throw ExceptionOutOfRange(
259  QObject::tr("unable to compute mean on a trace of size 0"));
260  return (sumYTrace(begin, end, 0) / nb_element);
261 }
262 
263 
264 double
265 quantileYTrace(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)
271  throw ExceptionOutOfRange(
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)
277  throw ExceptionOutOfRange(
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 
290 double
291 medianYTrace(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)
296  throw ExceptionOutOfRange(
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 
308 double
309 areaTrace(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 
328 Trace
329 flooredLocalMaxima(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 
449 Trace::Trace(const std::vector<pappso_double> &xVector,
450  const std::vector<pappso_double> &yVector)
451 {
452  initialize(xVector, yVector);
453 }
454 
455 
457  const std::vector<std::pair<pappso_double, pappso_double>> &dataPoints)
458 {
459  reserve(dataPoints.size());
460 
461  for(auto &dataPoint : dataPoints)
462  {
463  push_back(DataPoint(dataPoint));
464  }
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>(dataPoints)
475 {
476  sortX();
477  // std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
478  // return (a.x < b.x);
479  //});
480 }
481 
482 
483 Trace::Trace(const std::vector<DataPoint> &&dataPoints)
484  : std::vector<DataPoint>(std::move(dataPoints))
485 {
486  // This constructor used by the MassSpectrum && constructor.
487 
488  sortX();
489  // std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
490  // return (a.x < b.x);
491  //});
492 }
493 
494 
495 Trace::Trace(const MapTrace &map_trace)
496 {
497  for(auto &&item : map_trace)
498  push_back(DataPoint(item.first, item.second));
499 
500  // No need to sort, maps are sorted by key (that is, x).
501 }
502 
503 Trace::Trace(const Trace &other) : std::vector<DataPoint>(other)
504 {
505 }
506 
507 
508 Trace::Trace(const Trace &&other)
509  : std::vector<DataPoint>(std::move(other))
510 {
511  // This constructor used by the MassSpectrum && constructor.
512 }
513 
514 
516 {
517  // Calls the destructor for each DataPoint object in the vector.
518  clear();
519 }
520 
521 
522 size_t
523 Trace::initialize(const std::vector<pappso_double> &xVector,
524  const std::vector<pappso_double> &yVector)
525 {
526  // Sanity check
527  if(xVector.size() != yVector.size())
528  throw ExceptionNotPossible(
529  "trace.cpp -- ERROR xVector and yVector must have the same size.");
530 
531  // We are initializing, not appending.
532  erase(begin(), end());
533 
534  for(std::size_t iter = 0; iter < xVector.size(); ++iter)
535  {
536  push_back(DataPoint(xVector.at(iter), yVector.at(iter)));
537  }
538 
539  sortX();
540  // std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
541  // return (a.x < b.x);
542  //});
543 
544 #if 0
545  for(auto &item : *this)
546  {
547  std::cout << item.x << "-" << item.y;
548  }
549 #endif
550 
551  return size();
552 }
553 
554 
555 size_t
556 Trace::initialize(const std::map<pappso_double, pappso_double> &map)
557 {
558 
559  // We are initializing, not appending.
560  erase(begin(), end());
561 
562  for(auto &&item : map)
563  {
564  push_back(DataPoint(item.first, item.second));
565  }
566 
567  // No need to sort, maps are sorted by key (that is, x).
568 
569  return size();
570 }
571 
572 
573 size_t
575 {
576  *this = other;
577 
578  return size();
579 }
580 
581 
582 size_t
583 Trace::append(const DataPoint &data_point)
584 {
585  push_back(data_point);
586 
587  return size();
588 }
589 
590 
591 Trace &
592 Trace::operator=(const Trace &other)
593 {
594  assign(other.begin(), other.end());
595 
596  return *this;
597 }
598 
599 
600 Trace &
602 {
603  vector<DataPoint>::operator=(std::move(other));
604  return *this;
605 }
606 
607 
608 TraceSPtr
610 {
611  return std::make_shared<Trace>(*this);
612 }
613 
614 
617 {
618  return std::make_shared<const Trace>(*this);
619 }
620 
621 
622 std::vector<pappso_double>
624 {
625  std::vector<pappso_double> values;
626 
627  for(auto &&dataPoint : *this)
628  {
629  values.push_back(dataPoint.x);
630  }
631 
632  return values;
633 }
634 
635 
636 std::vector<pappso_double>
638 {
639  std::vector<pappso_double> values;
640 
641  for(auto &&dataPoint : *this)
642  {
643  values.push_back(dataPoint.y);
644  }
645 
646  return values;
647 }
648 
649 
650 std::map<pappso_double, pappso_double>
652 {
653  std::map<pappso_double, pappso_double> map;
654 
655  std::pair<std::map<pappso_double, pappso_double>::iterator, bool> ret;
656 
657  for(auto &&dataPoint : *this)
658  {
659  ret = map.insert(
660  std::pair<pappso_double, pappso_double>(dataPoint.x, dataPoint.y));
661 
662  if(ret.second == false)
663  {
664  qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()"
665  << "It is odd that the Trace contains multiple same keys.";
666 
667  // No insertion, then increment the y value.
668  ret.first->second += dataPoint.y;
669  }
670  }
671 
672  return map;
673 }
674 
675 
676 // const DataPoint &
677 // Trace::dataPointWithX(pappso_double value) const
678 //{
679 // auto iterator =
680 // std::find_if(begin(), end(), [value](const DataPoint &dataPoint) {
681 // return (dataPoint.x == value);
682 //});
683 
684 // if(iterator != end())
685 //{
686 //// The returned data point is valid.
687 // return *iterator;
688 //}
689 // else
690 //{
691 //// The returned data point is invalid because it is not initialized.
692 // return DataPoint();
693 //}
694 //}
695 
696 
697 std::vector<DataPoint>::iterator
699 {
700  auto iterator =
701  std::find_if(begin(), end(), [value](const DataPoint &dataPoint) {
702  return (dataPoint.x == value);
703  });
704 
705  return iterator;
706 }
707 
708 
709 std::vector<DataPoint>::const_iterator
711 {
712  auto iterator =
713  std::find_if(begin(), end(), [value](const DataPoint &dataPoint) {
714  return (dataPoint.x == value);
715  });
716 
717  return iterator;
718 }
719 
720 
721 std::size_t
723 {
724  std::vector<DataPoint>::const_iterator iterator =
726 
727  if(iterator != end())
728  return std::distance(begin(), iterator);
729 
730  return std::numeric_limits<std::size_t>::max();
731 }
732 
733 
734 DataPoint
735 Trace::containsX(pappso_double value, PrecisionPtr precision_p) const
736 {
737  // std::cout << std::setprecision(10) << "getting value: " << value
738  //<< " and precision: " << precision_p->getNominal() << std::endl;
739 
740  pappso_double delta = precision_p->delta(value);
741 
742  double left_most = value - delta;
743  double right_most = value + delta;
744 
745  // std::cout << std::setprecision(10) << "delta: " << delta
746  //<< " left_most: " << left_most << " right_most: " << right_most
747  //<< std::endl;
748 
749  auto iterator =
750  std::find_if(begin(),
751  end(),
752  [value, precision_p, delta, left_most, right_most](
753  const DataPoint &data_point) {
754  if(precision_p)
755  {
756 
757  // FIXME: unbelievable behaviour: when building in
758  // release mode this code, under i386 (but not x86_64),
759  // this code fails if the following cout statement is
760  // missing.
761 
762  // std::cout << std::setprecision(10)
763  //<< "Testing data_point.x: " << data_point.x
764  //<< std::endl;
765 
766  // For this reason I had to deactivate the related tests
767  // for i386 in tests/test_trace.cpp
768 
769  double diff_to_left_most = data_point.x - left_most;
770  double diff_to_right_most = data_point.x - right_most;
771 
772  // std::cout << std::setprecision(10)
773  //<< "diff_to_left_most: " << diff_to_left_most
774  //<< " diff_to_right_most: " << diff_to_right_most <<
775  // std::endl;
776 
777  // if(diff_to_left_most > 0)
778  //{
779  // std::cout << std::setprecision(10)
780  //<< " point is right of left_most: " <<
781  // diff_to_left_most
782  //<< std::endl;
783  //}
784  // if(diff_to_left_most < 0)
785  //{
786  // std::cout << std::setprecision(10)
787  //<< "point is left of left_most: " << diff_to_left_most
788  //<< std::endl;
789  //}
790  // if(!diff_to_left_most)
791  //{
792  // std::cout << std::setprecision(10)
793  //<< "point is spot on left_most: " << diff_to_left_most
794  //<< std::endl;
795  //}
796 
797  // if(diff_to_right_most > 0)
798  //{
799  // std::cout << std::setprecision(10)
800  //<< "point is right of right_most: " <<
801  // diff_to_right_most
802  //<< std::endl;
803  //}
804  // if(diff_to_right_most < 0)
805  //{
806  // std::cout << std::setprecision(10)
807  //<< "point is left or of right_most: "
808  //<< diff_to_right_most << std::endl;
809  //}
810  // if(!diff_to_right_most)
811  //{
812  // std::cout << std::setprecision(10)
813  //<< "point is spot on right_most: " <<
814  // diff_to_right_most
815  //<< std::endl;
816  //}
817 
818  if(diff_to_left_most >= 0 && diff_to_right_most <= 0)
819  {
820  // std::cout << "The point is inside the range,
821  // should return true."
822  //<< std::endl;
823  return true;
824  }
825  else
826  {
827  // std::cout
828  //<< "The point is outside the range, should return
829  // false."
830  //<< std::endl;
831  return false;
832  }
833  }
834  else
835  {
836  return (data_point.x == value);
837  }
838  });
839 
840  if(iterator != end())
841  {
842  // The returned data point is valid.
843  return *iterator;
844  }
845  else
846  {
847  // The returned data point is invalid because it is not initialized.
848  return DataPoint();
849  }
850 }
851 
852 
853 const DataPoint &
855 {
856  auto dataPoint = std::min_element(
857  begin(), end(), [](const DataPoint &a, const DataPoint &b) {
858  return (a.y < b.y);
859  });
860 
861  if(dataPoint == end())
862  {
863  throw ExceptionOutOfRange(
864  QObject::tr("unable to get min peak intensity on spectrum size %1")
865  .arg(size()));
866  }
867 
868  return (*dataPoint);
869 }
870 
871 
872 const DataPoint &
874 {
875  auto dataPoint = std::max_element(
876  begin(), end(), [](const DataPoint &a, const DataPoint &b) {
877  return (a.y < b.y);
878  });
879 
880  if(dataPoint == end())
881  {
882  throw ExceptionOutOfRange(
883  QObject::tr("unable to get max peak intensity on spectrum size %1")
884  .arg(size()));
885  }
886 
887  return (*dataPoint);
888 }
889 
890 
892 Trace::minY() const
893 {
894  return minYDataPoint().y;
895 }
896 
897 
899 Trace::maxY() const
900 {
901  return maxYDataPoint().y;
902 }
903 
904 
906 Trace::sumY() const
907 {
908  // double sum = 0;
909 
910  // for(auto &&dp : m_dataPoints)
911  // sum += dp.y;
912 
913  // qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << " ()"
914  //<< "Returning sum/tic:" << sum;
915 
916  // return sum;
917 
918  return std::accumulate(begin(),
919  end(),
920  (double)0,
921  [](pappso_double sum, const DataPoint &dataPoint) {
922  return (sum + dataPoint.y);
923  });
924 }
925 
926 
928 Trace::sumY(double mzStart, double mzEnd) const
929 {
930  auto begin_it = findFirstEqualOrGreaterX(this->begin(), this->end(), mzStart);
931  auto end_it = findFirstGreaterX(begin_it, this->end(), mzEnd);
932 
933  return sumYTrace(begin_it, end_it, 0);
934 }
935 
936 
938 Trace::maxY(double mzStart, double mzEnd) const
939 {
940  std::vector<DataPoint>::const_iterator begin_it =
941  findFirstEqualOrGreaterX(this->begin(), this->end(), mzStart);
942 
943  double max_y = 0;
944 
945  while(begin_it != findFirstGreaterX(begin_it, this->end(), mzEnd))
946  {
947  if(begin_it->y > max_y)
948  max_y = begin_it->y;
949  begin_it++;
950  }
951  return max_y;
952 }
953 
954 
955 void
957 {
958  std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
959  return (a.x < b.x);
960  });
961 }
962 
963 void
965 {
966  std::sort(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
967  return (a.y > b.y);
968  });
969 }
970 
971 void
973 {
974  auto last =
975  std::unique(begin(), end(), [](const DataPoint &a, const DataPoint &b) {
976  return (a.x == b.x);
977  });
978 
979  erase(last, end());
980 }
981 
982 
983 QString
985 {
986  // Even if the spectrum is empty, we should return an empty string.
987  QString text;
988 
989  for(auto &&dataPoint : *this)
990  {
991  text.append(QString("%1 %2\n")
992  .arg(dataPoint.x, 0, 'f', 10)
993  .arg(dataPoint.y, 0, 'f', 10));
994  }
995 
996  return text;
997 }
998 
999 
1000 Trace &
1002 {
1003  return filter.filter(*this);
1004 }
1005 
1006 } // 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:592
void unique()
Definition: trace.cpp:972
pappso_double maxY() const
Definition: trace.cpp:899
pappso_double sumY() const
Definition: trace.cpp:906
void sortY()
Definition: trace.cpp:964
const DataPoint & maxYDataPoint() const
Definition: trace.cpp:873
std::map< pappso_double, pappso_double > toMap() const
Definition: trace.cpp:651
std::vector< pappso_double > xValues() const
Definition: trace.cpp:623
void sortX()
Definition: trace.cpp:956
TraceCstSPtr makeTraceCstSPtr() const
Definition: trace.cpp:616
virtual Trace & filter(const FilterInterface &filter) final
apply a filter on this trace
Definition: trace.cpp:1001
DataPoint containsX(pappso_double value, PrecisionPtr precision_p=nullptr) const
Definition: trace.cpp:735
std::vector< pappso_double > yValues() const
Definition: trace.cpp:637
pappso_double minY() const
Definition: trace.cpp:892
virtual ~Trace()
Definition: trace.cpp:515
size_t initialize(const std::vector< pappso_double > &xVector, const std::vector< pappso_double > &yVector)
Definition: trace.cpp:523
size_t append(const DataPoint &data_point)
appends a datapoint and return new size
Definition: trace.cpp:583
std::size_t dataPointIndexWithX(pappso_double value) const
Definition: trace.cpp:722
std::vector< DataPoint >::const_iterator dataPointCstIteratorWithX(pappso_double value) const
find datapoint with exactly x value
Definition: trace.cpp:710
std::vector< DataPoint >::iterator dataPointIteratorWithX(pappso_double value)
Definition: trace.cpp:698
const DataPoint & minYDataPoint() const
Definition: trace.cpp:854
TraceSPtr makeTraceSPtr() const
Definition: trace.cpp:609
QString toString() const
Definition: trace.cpp:984
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:125
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:69
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:97
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
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
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:25
int tracePtrMetaTypeId
Definition: trace.cpp:26