37 #include <OpenMS/config.h>
98 double apex_pos = 0.0;
133 double width_at_5 = 0.0;
137 double width_at_10 = 0.0;
141 double width_at_50 = 0.0;
145 double start_position_at_5 = 0.0;
149 double start_position_at_10 = 0.0;
153 double start_position_at_50 = 0.0;
157 double end_position_at_5 = 0.0;
161 double end_position_at_10 = 0.0;
165 double end_position_at_50 = 0.0;
169 double total_width = 0.0;
183 double tailing_factor = 0.0;
193 double asymmetry_factor = 0.0;
198 double slope_of_baseline = 0.0;
203 double baseline_delta_2_height = 0.0;
207 Int points_across_baseline = 0;
211 Int points_across_half_height = 0;
220 static constexpr
const char* INTEGRATION_TYPE_INTENSITYSUM =
"intensity_sum";
224 static constexpr
const char* INTEGRATION_TYPE_TRAPEZOID =
"trapezoid";
226 static constexpr
const char* INTEGRATION_TYPE_SIMPSON =
"simpson";
228 static constexpr
const char* BASELINE_TYPE_BASETOBASE =
"base_to_base";
230 static constexpr
const char* BASELINE_TYPE_VERTICALDIVISION =
"vertical_division";
232 static constexpr
const char* BASELINE_TYPE_VERTICALDIVISION_MIN =
"vertical_division_min";
234 static constexpr
const char* BASELINE_TYPE_VERTICALDIVISION_MAX =
"vertical_division_max";
256 const MSChromatogram& chromatogram,
const double left,
const double right
300 const MSSpectrum& spectrum,
const double left,
const double right
350 const MSChromatogram& chromatogram,
const double left,
const double right,
351 const double peak_apex_pos
380 const double peak_apex_pos
408 const MSSpectrum& spectrum,
const double left,
const double right,
409 const double peak_apex_pos
438 const double peak_apex_pos
461 const MSChromatogram& chromatogram,
const double left,
const double right,
462 const double peak_height,
const double peak_apex_pos
486 const double peak_height,
const double peak_apex_pos
509 const MSSpectrum& spectrum,
const double left,
const double right,
510 const double peak_height,
const double peak_apex_pos
534 const double peak_height,
const double peak_apex_pos
537 void getDefaultParameters(
Param& params);
540 void updateMembers_();
542 template <
typename PeakContainerT>
545 OPENMS_PRECONDITION(left <= right,
"Left peak boundary must be smaller than right boundary!")
546 PeakContainerT emg_pc;
547 const PeakContainerT& p = EMGPreProcess_(pc, emg_pc, left, right);
549 std::function<
double(
const double,
const double)>
550 compute_peak_area_trapezoid = [&p](
const double left,
const double right)
552 double peak_area { 0.0 };
553 for (
typename PeakContainerT::ConstIterator it = p.PosBegin(left); it != p.PosEnd(right) - 1; ++it)
555 peak_area += ((it + 1)->getPos() - it->getPos()) * ((it->getIntensity() + (it + 1)->getIntensity()) / 2.0);
560 std::function<
double(
const double,
const double)>
561 compute_peak_area_intensity_sum = [&p](
const double left,
const double right)
564 double peak_area { 0.0 };
565 for (
typename PeakContainerT::ConstIterator it = p.PosBegin(left); it != p.PosEnd(right); ++it)
567 peak_area += it->getIntensity();
574 UInt n_points = std::distance(p.PosBegin(left), p.PosEnd(right));
575 for (
auto it = p.PosBegin(left); it != p.PosEnd(right); ++it)
578 if (pa.
height < it->getIntensity())
580 pa.
height = it->getIntensity();
585 if (integration_type_ == INTEGRATION_TYPE_TRAPEZOID)
589 pa.
area = compute_peak_area_trapezoid(left, right);
592 else if (integration_type_ == INTEGRATION_TYPE_SIMPSON)
597 "number of points is 2, falling back to `trapezoid`." << std::endl;
598 pa.
area = compute_peak_area_trapezoid(left, right);
600 else if (n_points > 2)
604 pa.
area = simpson_(p.PosBegin(left), p.PosEnd(right));
608 double areas[4] = {-1.0, -1.0, -1.0, -1.0};
609 areas[0] = simpson_(p.PosBegin(left), p.PosEnd(right) - 1);
610 areas[1] = simpson_(p.PosBegin(left) + 1, p.PosEnd(right));
611 if (p.begin() <= p.PosBegin(left) - 1)
613 areas[2] = simpson_(p.PosBegin(left) - 1, p.PosEnd(right));
615 if (p.PosEnd(right) < p.end())
617 areas[3] = simpson_(p.PosBegin(left), p.PosEnd(right) + 1);
620 for (
const auto& area : areas)
632 else if (integration_type_ == INTEGRATION_TYPE_INTENSITYSUM)
634 pa.
area = compute_peak_area_intensity_sum(left, right);
638 throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
"Please set a valid value for the parameter \"integration_type\".");
646 template <
typename PeakContainerT>
648 const PeakContainerT& pc,
double left,
double right,
649 const double peak_apex_pos
652 PeakContainerT emg_pc;
653 const PeakContainerT& p = EMGPreProcess_(pc, emg_pc, left, right);
655 const double int_l = p.PosBegin(left)->getIntensity();
656 const double int_r = (p.PosEnd(right) - 1)->getIntensity();
657 const double delta_int = int_r - int_l;
658 const double delta_pos = (p.PosEnd(right) - 1)->getPos() - p.PosBegin(left)->getPos();
659 const double min_int_pos = int_r <= int_l ? (p.PosEnd(right) - 1)->getPos() : p.PosBegin(left)->getPos();
660 const double delta_int_apex = std::fabs(delta_int) * std::fabs(min_int_pos - peak_apex_pos) / delta_pos;
663 if (baseline_type_ == BASELINE_TYPE_BASETOBASE)
665 height = std::min(int_r, int_l) + delta_int_apex;
666 if (integration_type_ == INTEGRATION_TYPE_TRAPEZOID || integration_type_ == INTEGRATION_TYPE_SIMPSON)
670 area = delta_pos * (std::min(int_r, int_l) + 0.5 * std::fabs(delta_int));
672 else if (integration_type_ == INTEGRATION_TYPE_INTENSITYSUM)
679 double pos_sum = 0.0;
680 for (
auto it = p.PosBegin(left); it != p.PosEnd(right); ++it)
682 pos_sum += it->getPos();
684 UInt n_points = std::distance(p.PosBegin(left), p.PosEnd(right));
689 const double rectangle_area = n_points * int_l;
690 const double slope = delta_int / delta_pos;
691 const double triangle_area = (pos_sum - n_points * p.PosBegin(left)->getPos()) * slope;
692 area = triangle_area + rectangle_area;
695 else if (baseline_type_ == BASELINE_TYPE_VERTICALDIVISION || baseline_type_ == BASELINE_TYPE_VERTICALDIVISION_MIN)
697 height = std::min(int_r, int_l);
698 if (integration_type_ == INTEGRATION_TYPE_TRAPEZOID || integration_type_ == INTEGRATION_TYPE_SIMPSON)
700 area = delta_pos * std::min(int_r, int_l);
702 else if (integration_type_ == INTEGRATION_TYPE_INTENSITYSUM)
704 area = std::min(int_r, int_l) * std::distance(p.PosBegin(left), p.PosEnd(right));;
707 else if (baseline_type_ == BASELINE_TYPE_VERTICALDIVISION_MAX)
709 height = std::max(int_r, int_l);
710 if (integration_type_ == INTEGRATION_TYPE_TRAPEZOID || integration_type_ == INTEGRATION_TYPE_SIMPSON)
712 area = delta_pos * std::max(int_r, int_l);
714 else if (integration_type_ == INTEGRATION_TYPE_INTENSITYSUM)
716 area = std::max(int_r, int_l) * std::distance(p.PosBegin(left), p.PosEnd(right));
721 throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
"Please set a valid value for the parameter \"baseline_type\".");
743 template <
typename PeakContainerConstIteratorT>
744 double simpson_(PeakContainerConstIteratorT it_begin, PeakContainerConstIteratorT it_end)
const
746 double integral = 0.0;
747 for (
auto it = it_begin + 1; it < it_end - 1; it = it + 2)
749 const double h = it->getPos() - (it - 1)->getPos();
750 const double k = (it + 1)->getPos() - it->getPos();
751 const double y_h = (it - 1)->getIntensity();
752 const double y_0 = it->getIntensity();
753 const double y_k = (it + 1)->getIntensity();
754 integral += (1.0 / 6.0) * (
h +
k) * ((2.0 -
k /
h) * y_h + (pow(
h +
k, 2) / (
h *
k)) * y_0 + (2.0 -
h /
k) * y_k);
760 template <
typename PeakContainerT>
762 const PeakContainerT& pc,
double left,
double right,
763 const double peak_height,
const double peak_apex_pos
768 if (pc.empty())
return psm;
771 if (!(left <= peak_apex_pos && peak_apex_pos <= right))
throw Exception::InvalidRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
773 PeakContainerT emg_pc;
774 const PeakContainerT& p = EMGPreProcess_(pc, emg_pc, left, right);
776 typename PeakContainerT::ConstIterator it_PosBegin_l = p.PosBegin(left);
777 typename PeakContainerT::ConstIterator it_PosEnd_apex = p.PosBegin(peak_apex_pos);
778 typename PeakContainerT::ConstIterator it_PosEnd_r = p.PosEnd(right);
779 for (
auto it = it_PosBegin_l; it != it_PosEnd_r; ++it)
783 if (it->getIntensity() >= 0.5 * peak_height)
789 psm.
start_position_at_5 = findPosAtPeakHeightPercent_(it_PosBegin_l, it_PosEnd_apex, p.end(), peak_height, 0.05,
true);
790 psm.
start_position_at_10 = findPosAtPeakHeightPercent_(it_PosBegin_l, it_PosEnd_apex, p.end(), peak_height, 0.1,
true);
791 psm.
start_position_at_50 = findPosAtPeakHeightPercent_(it_PosBegin_l, it_PosEnd_apex, p.end(), peak_height, 0.5,
true);
792 psm.
end_position_at_5 = findPosAtPeakHeightPercent_(it_PosEnd_apex, it_PosEnd_r, p.end(), peak_height, 0.05,
false);
793 psm.
end_position_at_10 = findPosAtPeakHeightPercent_(it_PosEnd_apex, it_PosEnd_r, p.end(), peak_height, 0.1,
false);
794 psm.
end_position_at_50 = findPosAtPeakHeightPercent_(it_PosEnd_apex, it_PosEnd_r, p.end(), peak_height, 0.5,
false);
799 psm.
total_width = (p.PosEnd(right) - 1)->getPos() - p.PosBegin(left)->getPos();
800 psm.
slope_of_baseline = (p.PosEnd(right) - 1)->getIntensity() - p.PosBegin(left)->getIntensity();
831 template <
typename PeakContainerConstIteratorT>
833 PeakContainerConstIteratorT it_left,
834 PeakContainerConstIteratorT it_right,
835 PeakContainerConstIteratorT it_end,
836 const double peak_height,
837 const double percent,
838 const bool is_left_half)
const
844 if (it_left == it_right)
return it_left->getPos();
846 const double percent_intensity = peak_height * percent;
847 PeakContainerConstIteratorT closest;
852 PeakContainerConstIteratorT it = it_left;
853 it < it_right && it->getIntensity() <= percent_intensity;
859 closest = it_right - 1;
861 PeakContainerConstIteratorT it = it_right - 1;
862 it >= it_left && it->getIntensity() <= percent_intensity;
866 return closest->getPos();
879 String integration_type_ = INTEGRATION_TYPE_INTENSITYSUM;
884 String baseline_type_ = BASELINE_TYPE_BASETOBASE;
905 template <
typename PeakContainerT>
907 const PeakContainerT& pc,
908 PeakContainerT& emg_pc,
916 left = emg_pc.front().getPos();
917 right = emg_pc.back().getPos();