OpenMS
Loading...
Searching...
No Matches
MRMTransitionGroupPicker.h
Go to the documentation of this file.
1// Copyright (c) 2002-present, OpenMS Inc. -- EKU Tuebingen, ETH Zurich, and FU Berlin
2// SPDX-License-Identifier: BSD-3-Clause
3//
4// --------------------------------------------------------------------------
5// $Maintainer: Hannes Roest $
6// $Authors: Hannes Roest $
7// --------------------------------------------------------------------------
8
9#pragma once
10
19
22
25
26// Cross-correlation
29
30#include <numeric>
31
32//#define DEBUG_TRANSITIONGROUPPICKER
33
34namespace OpenMS
35{
36
37 // Shared thread-local pools used by MRMTransitionGroupPicker to avoid
38 // repeated allocations across nested helpers (pickTransitionGroup, computeQuality_)
40 {
41 std::vector<MSChromatogram> picked_chroms;
42 std::vector<MSChromatogram> smoothed_chroms;
43 std::vector<const MSChromatogram*> picked_input_chromatograms;
44 std::vector<const MSChromatogram*> transition_chromatograms;
45 std::vector<MRMFeature> features;
46 std::vector<double> left_edges;
47 std::vector<double> right_edges;
48 std::vector<std::vector<double>> all_ints;
49 std::vector<double> mean_shapes;
50 std::vector<double> mean_coel;
51 std::vector<double> left_borders;
52 std::vector<double> right_borders;
53 std::vector<int> largest_peak_indices;
54 std::vector<double> transition_total_xics;
55
56 void reset()
57 {
58 picked_chroms.clear();
59 smoothed_chroms.clear();
62 features.clear();
63 left_edges.clear();
64 right_edges.clear();
65 all_ints.clear();
66 mean_shapes.clear();
67 mean_coel.clear();
68 left_borders.clear();
69 right_borders.clear();
72 }
73 };
74
75 // Per-thread instance of the shared pools. Wrapped in a function so the
76 // function-local `thread_local static` is the single point of definition
77 // across all translation units / DLLs and we don't have to deal with
78 // platform-specific behavior of namespace-scope `inline thread_local`
79 // (duplicate TLS init wrapper on macOS clang) or `extern thread_local`
80 // exported from a DLL (MSVC LNK2019 on TOPP-tool consumers).
82 {
83 thread_local PickerPoolShared instance;
84 return instance;
85 }
86
87 namespace MRMTransitionGroupPickerMeta
88 {
90 {
91 static const UInt id = MetaInfo::registry().registerName("area_background_level");
92 return id;
93 }
94
96 {
97 static const UInt id = MetaInfo::registry().registerName("asymmetry_factor");
98 return id;
99 }
100
102 {
103 static const UInt id = MetaInfo::registry().registerName("baseline_delta_2_height");
104 return id;
105 }
106
108 {
109 static const UInt id = MetaInfo::registry().registerName("end_position_at_5");
110 return id;
111 }
112
114 {
115 static const UInt id = MetaInfo::registry().registerName("end_position_at_10");
116 return id;
117 }
118
120 {
121 static const UInt id = MetaInfo::registry().registerName("end_position_at_50");
122 return id;
123 }
124
126 {
127 static const UInt id = MetaInfo::registry().registerName("initialPeakQuality");
128 return id;
129 }
130
132 {
133 static const UInt id = MetaInfo::registry().registerName("leftWidth");
134 return id;
135 }
136
137 inline UInt nativeID()
138 {
139 static const UInt id = MetaInfo::registry().registerName("native_id");
140 return id;
141 }
142
144 {
145 static const UInt id = MetaInfo::registry().registerName("noise_background_level");
146 return id;
147 }
148
150 {
151 static const UInt id = MetaInfo::registry().registerName("peak_apex_int");
152 return id;
153 }
154
156 {
157 static const UInt id = MetaInfo::registry().registerName("peak_apex_position");
158 return id;
159 }
160
162 {
163 static const UInt id = MetaInfo::registry().registerName("peak_apices_sum");
164 return id;
165 }
166
168 {
169 static const UInt id = MetaInfo::registry().registerName("PeptideRef");
170 return id;
171 }
172
174 {
175 static const UInt id = MetaInfo::registry().registerName("points_across_baseline");
176 return id;
177 }
178
180 {
181 static const UInt id = MetaInfo::registry().registerName("points_across_half_height");
182 return id;
183 }
184
186 {
187 static const UInt id = MetaInfo::registry().registerName("potentialOutlier");
188 return id;
189 }
190
192 {
193 static const UInt id = MetaInfo::registry().registerName("rightWidth");
194 return id;
195 }
196
198 {
199 static const UInt id = MetaInfo::registry().registerName("slope_of_baseline");
200 return id;
201 }
202
204 {
205 static const UInt id = MetaInfo::registry().registerName("start_position_at_5");
206 return id;
207 }
208
210 {
211 static const UInt id = MetaInfo::registry().registerName("start_position_at_10");
212 return id;
213 }
214
216 {
217 static const UInt id = MetaInfo::registry().registerName("start_position_at_50");
218 return id;
219 }
220
222 {
223 static const UInt id = MetaInfo::registry().registerName("tailing_factor");
224 return id;
225 }
226
227 inline UInt totalMI()
228 {
229 static const UInt id = MetaInfo::registry().registerName("total_mi");
230 return id;
231 }
232
234 {
235 static const UInt id = MetaInfo::registry().registerName("total_width");
236 return id;
237 }
238
239 inline UInt totalXIC()
240 {
241 static const UInt id = MetaInfo::registry().registerName("total_xic");
242 return id;
243 }
244
245 inline UInt widthAt5()
246 {
247 static const UInt id = MetaInfo::registry().registerName("width_at_5");
248 return id;
249 }
250
252 {
253 static const UInt id = MetaInfo::registry().registerName("width_at_10");
254 return id;
255 }
256
258 {
259 static const UInt id = MetaInfo::registry().registerName("width_at_50");
260 return id;
261 }
262 }
263
264
283 class OPENMS_DLLAPI MRMTransitionGroupPicker :
285 {
286
287public:
288
290
292
296
316 template <typename SpectrumT, typename TransitionT>
318 {
319 OPENMS_PRECONDITION(transition_group.isInternallyConsistent(), "Consistent state required")
320 OPENMS_PRECONDITION(transition_group.chromatogramIdsMatch(), "Chromatogram native IDs need to match keys in transition group")
321
322 // Reuse thread-local pools for large temporary containers to avoid
323 // per-call allocations in multi-threaded runs.
324 // Use shared per-thread pool declared at file scope to allow nested
325 // helpers (computeQuality_, pickFragmentChromatograms, ...) to reuse
326 // the same buffers and avoid repeated allocations.
327 auto &picker_pool = g_picker_pool_shared();
328 picker_pool.reset();
329 auto &picked_chroms = picker_pool.picked_chroms;
330 auto &smoothed_chroms = picker_pool.smoothed_chroms;
331 auto &picked_input_chromatograms = picker_pool.picked_input_chromatograms;
332 const Size expected_chrom_count = transition_group.getChromatograms().size() +
333 (use_precursors_ ? transition_group.getPrecursorChromatograms().size() : 0);
334 picked_chroms.reserve(expected_chrom_count);
335 smoothed_chroms.reserve(expected_chrom_count);
336 picked_input_chromatograms.reserve(expected_chrom_count);
337
338 // Pick fragment ion chromatograms
339 for (Size k = 0; k < transition_group.getChromatograms().size(); k++)
340 {
341 MSChromatogram& chromatogram = transition_group.getChromatograms()[k];
342 std::string native_id = chromatogram.getNativeID();
343
344 // only pick detecting transitions (skip all others)
345 if (transition_group.getTransitions().size() > 0 &&
346 transition_group.hasTransition(native_id) &&
347 !transition_group.getTransition(native_id).isDetectingTransition() )
348 {
349 continue;
350 }
351
352 MSChromatogram picked_chrom, smoothed_chrom;
353 smoothed_chrom.setNativeID(native_id);
354 picker_.pickChromatogram(chromatogram, picked_chrom, smoothed_chrom);
355 picked_chrom.sortByIntensity();
356 picked_input_chromatograms.push_back(&chromatogram);
357 picked_chroms.push_back(std::move(picked_chrom));
358 smoothed_chroms.push_back(std::move(smoothed_chrom));
359 }
360
361 // Pick precursor chromatograms
362 if (use_precursors_)
363 {
364 for (Size k = 0; k < transition_group.getPrecursorChromatograms().size(); k++)
365 {
366 SpectrumT picked_chrom, smoothed_chrom;
367 SpectrumT& chromatogram = transition_group.getPrecursorChromatograms()[k];
368
369 picker_.pickChromatogram(chromatogram, picked_chrom, smoothed_chrom);
370 picked_chrom.sortByIntensity();
371 picked_input_chromatograms.push_back(&chromatogram);
372 picked_chroms.push_back(std::move(picked_chrom));
373 smoothed_chroms.push_back(std::move(smoothed_chrom));
374 }
375 }
376
377 auto& transition_total_xics = picker_pool.transition_total_xics;
378 transition_total_xics.reserve(transition_group.getTransitions().size());
379 auto& transition_chromatograms = picker_pool.transition_chromatograms;
380 transition_chromatograms.reserve(transition_group.getTransitions().size());
381 double detecting_total_xic = 0.0;
382 for (const TransitionT& transition : transition_group.getTransitions())
383 {
384 const SpectrumT& chromatogram = selectChromHelper_(transition_group, transition.getNativeID());
385 transition_chromatograms.push_back(&chromatogram);
386 const double transition_total_xic = std::accumulate(chromatogram.begin(), chromatogram.end(), 0.0,
387 [](double total, const auto& peak)
388 {
389 return total + peak.getIntensity();
390 });
391 transition_total_xics.push_back(transition_total_xic);
392 if (transition.isDetectingTransition())
393 {
394 detecting_total_xic += transition_total_xic;
395 }
396 }
397
398 auto& largest_peak_indices = picker_pool.largest_peak_indices;
399 if (boundary_selection_method_ == "largest")
400 {
401 largest_peak_indices.reserve(picked_chroms.size());
402 for (const SpectrumT& chromatogram : picked_chroms)
403 {
404 largest_peak_indices.push_back(chromatogram.empty() ? -1 : static_cast<int>(chromatogram.size() - 1));
405 }
406 }
407
408 // Find features (peak groups) in this group of transitions.
409 // While there are still peaks left, one will be picked and used to create
410 // a feature. Whenever we run out of peaks, we will get -1 back as index
411 // and terminate.
412 int chr_idx, peak_idx, cnt = 0;
413 auto &features = picker_pool.features;
414 while (true)
415 {
416 chr_idx = -1; peak_idx = -1;
417
418 if (boundary_selection_method_ == "largest")
419 {
420 findLargestPeakCached_(picked_chroms, largest_peak_indices, chr_idx, peak_idx);
421 }
422 else if (boundary_selection_method_ == "widest")
423 {
424 findWidestPeakIndices(picked_chroms, chr_idx, peak_idx);
425 }
426
427 if (chr_idx == -1 && peak_idx == -1)
428 {
429 OPENMS_LOG_DEBUG << "**** No more peaks left. Nr. chroms: " << picked_chroms.size() << std::endl;
430 break;
431 }
432
433 // Compute a feature from the individual chromatograms and add non-zero features
434 MRMFeature mrm_feature = createMRMFeature(transition_group, picked_chroms, smoothed_chroms,
435 transition_total_xics, detecting_total_xic,
436 transition_chromatograms,
437 picked_input_chromatograms,
438 chr_idx, peak_idx);
439 double total_xic = 0;
440 double intensity = mrm_feature.getIntensity();
441 if (intensity > 0)
442 {
443 total_xic = mrm_feature.getMetaValue(MRMTransitionGroupPickerMeta::totalXIC());
444 features.push_back(std::move(mrm_feature));
445 cnt++;
446 }
447
448 if (stop_after_feature_ > 0 && cnt > stop_after_feature_) {
449 // If you set this, you only expect one feature anyway. No logging necessary why it stopped.
450 break;
451 }
452 if (intensity > 0 && intensity / total_xic < stop_after_intensity_ratio_)
453 {
454 OPENMS_LOG_DEBUG << "**** Minimum intensity ratio reached. Nr. chroms: " << picked_chroms.size() << std::endl;
455 break;
456 }
457 }
458
459 // Check for completely overlapping features
460 for (Size i = 0; i < features.size(); i++)
461 {
462 MRMFeature& mrm_feature = features[i];
463 bool skip = false;
464 for (Size j = 0; j < i; j++)
465 {
466 if ((double)mrm_feature.getMetaValue(MRMTransitionGroupPickerMeta::leftWidth()) >= (double)features[j].getMetaValue(MRMTransitionGroupPickerMeta::leftWidth()) &&
467 (double)mrm_feature.getMetaValue(MRMTransitionGroupPickerMeta::rightWidth()) <= (double)features[j].getMetaValue(MRMTransitionGroupPickerMeta::rightWidth()))
468 { skip = true; }
469 }
470 if (mrm_feature.getIntensity() > 0 && !skip)
471 {
472 transition_group.addFeature(mrm_feature);
473 }
474 }
475
476 }
477
494 template <typename SpectrumT, typename TransitionT>
496 std::vector<SpectrumT>& picked_chroms,
497 const std::vector<SpectrumT>& smoothed_chroms,
498 const int chr_idx,
499 const int peak_idx)
500 {
501 std::vector<double> transition_total_xics;
502 transition_total_xics.reserve(transition_group.getTransitions().size());
503 std::vector<const SpectrumT*> transition_chromatograms;
504 transition_chromatograms.reserve(transition_group.getTransitions().size());
505 double detecting_total_xic = 0.0;
506 for (const TransitionT& transition : transition_group.getTransitions())
507 {
508 const SpectrumT& chromatogram = selectChromHelper_(transition_group, transition.getNativeID());
509 transition_chromatograms.push_back(&chromatogram);
510 const double transition_total_xic = std::accumulate(chromatogram.begin(), chromatogram.end(), 0.0,
511 [](double total, const auto& peak)
512 {
513 return total + peak.getIntensity();
514 });
515 transition_total_xics.push_back(transition_total_xic);
516 if (transition.isDetectingTransition())
517 {
518 detecting_total_xic += transition_total_xic;
519 }
520 }
521
522 std::vector<const SpectrumT*> picked_input_chromatograms;
523 picked_input_chromatograms.reserve(picked_chroms.size());
524 for (const SpectrumT& picked_chrom : picked_chroms)
525 {
526 picked_input_chromatograms.push_back(&selectChromHelper_(transition_group, picked_chrom.getNativeID()));
527 }
528
529 return createMRMFeature(transition_group, picked_chroms, smoothed_chroms,
530 transition_total_xics, detecting_total_xic,
531 transition_chromatograms, picked_input_chromatograms,
532 chr_idx, peak_idx);
533 }
534
555 template <typename SpectrumT, typename TransitionT>
557 std::vector<SpectrumT>& picked_chroms,
558 const std::vector<SpectrumT>& smoothed_chroms,
559 const std::vector<double>& transition_total_xics,
560 double detecting_total_xic,
561 const std::vector<const SpectrumT*>& transition_chromatograms,
562 const std::vector<const SpectrumT*>& picked_input_chromatograms,
563 const int chr_idx,
564 const int peak_idx)
565 {
566 OPENMS_PRECONDITION(transition_group.isInternallyConsistent(), "Consistent state required")
567 OPENMS_PRECONDITION(transition_group.chromatogramIdsMatch(), "Chromatogram native IDs need to match keys in transition group")
568
569 MRMFeature mrmFeature;
570 mrmFeature.setIntensity(0.0);
571 double best_left = picked_chroms[chr_idx].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][peak_idx];
572 double best_right = picked_chroms[chr_idx].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][peak_idx];
573 double peak_apex = picked_chroms[chr_idx][peak_idx].getRT();
574 OPENMS_LOG_DEBUG << "**** Creating MRMFeature for peak " << peak_idx << " in chrom. " << chr_idx << " with " <<
575 picked_chroms[chr_idx][peak_idx] << " and borders " << best_left << " " <<
576 best_right << " (" << best_right - best_left << ")" << std::endl;
577
578 if (use_consensus_ && recalculate_peaks_)
579 {
580 // This may change best_left / best_right
581 recalculatePeakBorders_(picked_chroms, best_left, best_right, recalculate_peaks_max_z_);
582 if (peak_apex < best_left || peak_apex > best_right)
583 {
584 // apex fell out of range, lets correct it
585 peak_apex = (best_left + best_right) / 2.0;
586 }
587 }
588
589 // Use a small thread-local pool for these per-feature vectors to avoid
590 // frequent allocations when called repeatedly.
591 struct CreateFeaturePool
592 {
593 std::vector<double> left_edges;
594 std::vector<double> right_edges;
595 void reset() { left_edges.clear(); right_edges.clear(); }
596 };
597 thread_local CreateFeaturePool create_feat_pool;
598 create_feat_pool.reset();
599 auto &left_edges = create_feat_pool.left_edges;
600 auto &right_edges = create_feat_pool.right_edges;
601 double min_left = best_left;
602 double max_right = best_right;
603 if (use_consensus_)
604 {
605 // Remove other, overlapping, picked peaks (in this and other
606 // chromatograms) and then ensure that at least one peak is set to zero
607 // (the currently best peak).
608 remove_overlapping_features(picked_chroms, best_left, best_right);
609 }
610 else
611 {
612 pickApex(picked_chroms, best_left, best_right, peak_apex,
613 min_left, max_right, left_edges, right_edges);
614
615 } // end !use_consensus_
616 picked_chroms[chr_idx][peak_idx].setIntensity(0.0); // ensure that we set at least one peak to zero
617
618 // Check for minimal peak width -> return empty feature (Intensity zero)
619 if (use_consensus_)
620 {
621 if (min_peak_width_ > 0.0 && std::fabs(best_right - best_left) < min_peak_width_)
622 {
623 return mrmFeature;
624 }
625
626 if (compute_peak_quality_)
627 {
628 std::string outlier = "none";
629 double qual = computeQuality_(transition_group, picked_chroms, picked_input_chromatograms,
630 chr_idx, best_left, best_right, outlier);
631 if (qual < min_qual_)
632 {
633 return mrmFeature;
634 }
635 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::potentialOutlier(), outlier);
636 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::initialPeakQuality(), qual);
637 mrmFeature.setOverallQuality(qual);
638 }
639 }
640
641 // Prepare linear resampling of all the chromatograms, here creating the
642 // empty master_peak_container with the same RT (m/z) values as the
643 // reference chromatogram. We use the overall minimal left boundary and
644 // maximal right boundary to prepare the container.
645 SpectrumT master_peak_container;
646 const SpectrumT& ref_chromatogram = *picked_input_chromatograms[chr_idx];
647 prepareMasterContainer_(ref_chromatogram, master_peak_container, min_left, max_right);
648
649 // Iterate over initial transitions / chromatograms (note that we may
650 // have a different number of picked chromatograms than total transitions
651 // as not all are detecting transitions).
652 double total_intensity = 0; double total_peak_apices = 0; double total_xic = 0; double total_mi = 0;
653 pickFragmentChromatograms(transition_group, picked_chroms, mrmFeature, smoothed_chroms,
654 best_left, best_right, use_consensus_,
655 total_intensity, total_xic, total_mi, total_peak_apices,
656 master_peak_container, left_edges, right_edges,
657 transition_total_xics, detecting_total_xic,
658 transition_chromatograms,
659 chr_idx, peak_idx);
660
661 // Also pick the precursor chromatogram(s); note total_xic is not
662 // extracted here, only for fragment traces
663 pickPrecursorChromatograms(transition_group,
664 picked_chroms, mrmFeature, smoothed_chroms,
665 best_left, best_right, use_consensus_,
666 total_intensity, master_peak_container, left_edges, right_edges,
667 chr_idx, peak_idx);
668
669 mrmFeature.setRT(peak_apex);
670 mrmFeature.setIntensity(total_intensity);
671 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::peptideRef(), transition_group.getTransitionGroupID());
672 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::leftWidth(), best_left);
673 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::rightWidth(), best_right);
674 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::totalXIC(), total_xic);
675 if (compute_total_mi_)
676 {
677 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::totalMI(), total_mi);
678 }
679 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::peakApicesSum(), total_peak_apices);
680
681 mrmFeature.ensureUniqueId();
682 return mrmFeature;
683 }
684
697 template <typename SpectrumT>
698 void pickApex(std::vector<SpectrumT>& picked_chroms,
699 const double best_left, const double best_right, const double peak_apex,
700 double &min_left, double &max_right,
701 std::vector< double > & left_edges, std::vector< double > & right_edges)
702 {
703 for (Size k = 0; k < picked_chroms.size(); k++)
704 {
705 double peak_apex_dist_min = std::numeric_limits<double>::max();
706 int min_dist = -1;
707 for (Size i = 0; i < picked_chroms[k].size(); i++)
708 {
709 PeakIntegrator::PeakArea pa_tmp = pi_.integratePeak( // get the peak apex
710 picked_chroms[k],
711 picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][i],
712 picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][i]);
713 if (pa_tmp.apex_pos > 1e-11 && std::fabs(pa_tmp.apex_pos - peak_apex) < peak_apex_dist_min)
714 { // update best candidate
715 peak_apex_dist_min = std::fabs(pa_tmp.apex_pos - peak_apex);
716 min_dist = (int)i;
717 }
718 }
719
720 // Select master peak boundaries, or in the case we found at least one peak, the local peak boundaries
721 double l = best_left;
722 double r = best_right;
723 if (min_dist >= 0)
724 {
725 l = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][min_dist];
726 r = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][min_dist];
727 picked_chroms[k][min_dist].setIntensity(0.0); // only remove one peak per transition
728 }
729
730 left_edges.push_back(l);
731 right_edges.push_back(r);
732 // ensure we remember the overall maxima / minima
733 if (l < min_left) {min_left = l;}
734 if (r > max_right) {max_right = r;}
735 }
736 }
737
738 template <typename SpectrumT, typename TransitionT>
740 const std::vector<SpectrumT>& picked_chroms,
741 MRMFeature& mrmFeature,
742 const std::vector<SpectrumT>& smoothed_chroms,
743 const double best_left, const double best_right,
744 const bool use_consensus_,
745 double & total_intensity,
746 double & total_xic,
747 double & total_mi,
748 double & total_peak_apices,
749 const SpectrumT & master_peak_container,
750 const std::vector< double > & left_edges,
751 const std::vector< double > & right_edges,
752 const std::vector<double>& transition_total_xics,
753 double detecting_total_xic,
754 const std::vector<const SpectrumT*>& transition_chromatograms,
755 const int chr_idx,
756 const int peak_idx)
757 {
758 total_xic += detecting_total_xic;
759 for (Size k = 0; k < transition_group.getTransitions().size(); k++)
760 {
761
762 double local_left = best_left;
763 double local_right = best_right;
764 if (!use_consensus_)
765 {
766 // We cannot have any non-detecting transitions (otherwise we have
767 // too few left / right edges) as we skipped those when doing peak
768 // picking and smoothing.
769 if (!transition_group.getTransitions()[k].isDetectingTransition())
770 {
771 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
772 "When using non-consensus peak picker, all transitions need to be detecting transitions.");
773 }
774 local_left = left_edges[k];
775 local_right = right_edges[k];
776 }
777
778 const SpectrumT& chromatogram = *transition_chromatograms[k];
779
780 // Compute total intensity on transition-level
781 const double transition_total_xic = transition_total_xics[k];
782
783 // Compute total mutual information on transition-level.
784 double transition_total_mi = 0;
785 if (compute_total_mi_)
786 {
787 // reuse thread-local temporaries to avoid repeated allocations
788 thread_local std::vector<unsigned int> chrom_vect_id_ranked;
789 thread_local std::vector<unsigned int> chrom_vect_det_ranked;
790 thread_local std::vector<double> chrom_vect_id;
791 thread_local std::vector<double> chrom_vect_det;
792 chrom_vect_id.clear(); chrom_vect_det.clear(); chrom_vect_id_ranked.clear(); chrom_vect_det_ranked.clear();
793 for (typename SpectrumT::const_iterator it = chromatogram.begin(); it != chromatogram.end(); it++)
794 {
795 chrom_vect_id.push_back(it->getIntensity());
796 }
797 unsigned int max_rank_det = OpenSwath::Scoring::computeAndAppendRank(chrom_vect_id, chrom_vect_det_ranked);
798 // compute baseline mutual information
799 int transition_total_mi_norm = 0;
800 for (Size m = 0; m < transition_group.getTransitions().size(); m++)
801 {
802 if (transition_group.getTransitions()[m].isDetectingTransition())
803 {
804 const SpectrumT& chromatogram_det = *transition_chromatograms[m];
805 chrom_vect_det.clear();
806 for (typename SpectrumT::const_iterator it = chromatogram_det.begin(); it != chromatogram_det.end(); it++)
807 {
808 chrom_vect_det.push_back(it->getIntensity());
809 }
810 unsigned int max_rank_id = OpenSwath::Scoring::computeAndAppendRank(chrom_vect_det, chrom_vect_id_ranked);
811 transition_total_mi += OpenSwath::Scoring::rankedMutualInformation(chrom_vect_id_ranked, chrom_vect_det_ranked, max_rank_id, max_rank_det);
812 transition_total_mi_norm++;
813 }
814 }
815 if (transition_total_mi_norm > 0) { transition_total_mi /= transition_total_mi_norm; }
816
817 if (transition_group.getTransitions()[k].isDetectingTransition())
818 {
819 // sum up all transition-level total MI and divide by the number of detection transitions to have peak group level total MI
820 total_mi += transition_total_mi / transition_total_mi_norm;
821 }
822 }
823
824 SpectrumT used_chromatogram;
825 // resample the current chromatogram
826 if (peak_integration_ == "original")
827 {
828 used_chromatogram = resampleChromatogram_(chromatogram, master_peak_container, local_left, local_right);
829 }
830 else if (peak_integration_ == "smoothed")
831 {
832 if (smoothed_chroms.size() <= k)
833 {
834 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
835 "Tried to calculate peak area and height without any smoothed chromatograms");
836 }
837 used_chromatogram = resampleChromatogram_(smoothed_chroms[k], master_peak_container, local_left, local_right);
838 }
839 else
840 {
841 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
842 std::string("Peak integration chromatogram ") + peak_integration_ + " is not a valid method for MRMTransitionGroupPicker");
843 }
844
845 Feature f;
846 double quality = 0;
847 f.setQuality(0, quality);
848 f.setOverallQuality(quality);
849
850 PeakIntegrator::PeakArea pa = pi_.integratePeak(used_chromatogram, local_left, local_right);
851 double peak_integral = pa.area;
852 double peak_apex_int = pa.height;
853 f.setMetaValue(MRMTransitionGroupPickerMeta::peakApexPosition(), pa.apex_pos);
854
855 // In non-consensus mode, override hull_points with the full resampled
856 // chromatogram so all transitions produce equal-sized intensity vectors
857 // for cross-correlation scoring. Area/height/apex are already correct
858 // from the per-transition integration above.
859 if (!use_consensus_)
860 {
861 pa.hull_points.clear();
862 for (const auto& p : used_chromatogram)
863 {
864 pa.hull_points.push_back(DPosition<2>(p.getPos(), p.getIntensity()));
865 }
866 }
867
868 if (background_subtraction_ != "none")
869 {
870 double background{0};
871 double avg_noise_level{0};
872 if (background_subtraction_ == "original")
873 {
874 const double intensity_left = chromatogram.PosBegin(local_left)->getIntensity();
875 const double intensity_right = (chromatogram.PosEnd(local_right) - 1)->getIntensity();
876 const UInt n_points = std::distance(chromatogram.PosBegin(local_left), chromatogram.PosEnd(local_right));
877 avg_noise_level = (intensity_right + intensity_left) / 2;
878 background = avg_noise_level * n_points;
879 }
880 else if (background_subtraction_ == "exact")
881 {
882 PeakIntegrator::PeakBackground pb = pi_.estimateBackground(used_chromatogram, local_left, local_right, pa.apex_pos);
883 background = pb.area;
884 avg_noise_level = pb.height;
885 }
886 peak_integral -= background;
887 peak_apex_int -= avg_noise_level;
888 if (peak_integral < 0) {peak_integral = 0;}
889 if (peak_apex_int < 0) {peak_apex_int = 0;}
890
891 f.setMetaValue(MRMTransitionGroupPickerMeta::areaBackgroundLevel(), background);
892 f.setMetaValue(MRMTransitionGroupPickerMeta::noiseBackgroundLevel(), avg_noise_level);
893 } // end background
894
895 f.setRT(picked_chroms[chr_idx][peak_idx].getPos());
896 f.setIntensity(peak_integral);
897 ConvexHull2D hull;
898 hull.setHullPoints(pa.hull_points);
899 f.getConvexHulls().push_back(hull);
900
901 f.setMZ(chromatogram.getProduct().getMZ());
902 mrmFeature.setMZ(chromatogram.getPrecursor().getMZ());
903
904 if (chromatogram.metaValueExists("product_mz")) // legacy code (ensures that old tests still work)
905 {
906 f.setMetaValue("MZ", chromatogram.getMetaValue("product_mz"));
907 f.setMZ(chromatogram.getMetaValue("product_mz"));
908 }
909
910 f.setMetaValue(MRMTransitionGroupPickerMeta::nativeID(), chromatogram.getNativeID());
911 f.setMetaValue(MRMTransitionGroupPickerMeta::peakApexInt(), peak_apex_int);
912 f.setMetaValue(MRMTransitionGroupPickerMeta::totalXIC(), transition_total_xic);
913 if (compute_total_mi_)
914 {
915 f.setMetaValue(MRMTransitionGroupPickerMeta::totalMI(), transition_total_mi);
916 }
917
918 if (transition_group.getTransitions()[k].isQuantifyingTransition())
919 {
920 total_intensity += peak_integral;
921 total_peak_apices += peak_apex_int;
922 }
923
924 // for backwards compatibility with TOPP tests
925 // Calculate peak shape metrics that will be used for later QC
926 PeakIntegrator::PeakShapeMetrics psm = pi_.calculatePeakShapeMetrics(used_chromatogram, local_left, local_right, peak_apex_int, pa.apex_pos);
927 f.setMetaValue(MRMTransitionGroupPickerMeta::widthAt50(), psm.width_at_50);
928 if (compute_peak_shape_metrics_)
929 {
930 f.setMetaValue(MRMTransitionGroupPickerMeta::widthAt5(), psm.width_at_5);
931 f.setMetaValue(MRMTransitionGroupPickerMeta::widthAt10(), psm.width_at_10);
932 f.setMetaValue(MRMTransitionGroupPickerMeta::startPositionAt5(), psm.start_position_at_5);
933 f.setMetaValue(MRMTransitionGroupPickerMeta::startPositionAt10(), psm.start_position_at_10);
934 f.setMetaValue(MRMTransitionGroupPickerMeta::startPositionAt50(), psm.start_position_at_50);
935 f.setMetaValue(MRMTransitionGroupPickerMeta::endPositionAt5(), psm.end_position_at_5);
936 f.setMetaValue(MRMTransitionGroupPickerMeta::endPositionAt10(), psm.end_position_at_10);
937 f.setMetaValue(MRMTransitionGroupPickerMeta::endPositionAt50(), psm.end_position_at_50);
938 f.setMetaValue(MRMTransitionGroupPickerMeta::totalWidth(), psm.total_width);
939 f.setMetaValue(MRMTransitionGroupPickerMeta::tailingFactor(), psm.tailing_factor);
940 f.setMetaValue(MRMTransitionGroupPickerMeta::asymmetryFactor(), psm.asymmetry_factor);
941 f.setMetaValue(MRMTransitionGroupPickerMeta::slopeOfBaseline(), psm.slope_of_baseline);
942 f.setMetaValue(MRMTransitionGroupPickerMeta::baselineDelta2Height(), psm.baseline_delta_2_height);
943 f.setMetaValue(MRMTransitionGroupPickerMeta::pointsAcrossBaseline(), psm.points_across_baseline);
944 f.setMetaValue(MRMTransitionGroupPickerMeta::pointsAcrossHalfHeight(), psm.points_across_half_height);
945 }
946
947 mrmFeature.addFeature(f, chromatogram.getNativeID()); //map index and feature
948 }
949 }
950
951 template <typename SpectrumT, typename TransitionT>
953 const std::vector<SpectrumT>& picked_chroms,
954 MRMFeature& mrmFeature,
955 const std::vector<SpectrumT>& smoothed_chroms,
956 const double best_left, const double best_right,
957 const bool use_consensus_,
958 double & total_intensity,
959 const SpectrumT & master_peak_container,
960 const std::vector< double > & left_edges,
961 const std::vector< double > & right_edges,
962 const int chr_idx,
963 const int peak_idx)
964 {
965 for (Size k = 0; k < transition_group.getPrecursorChromatograms().size(); k++)
966 {
967 const SpectrumT& chromatogram = transition_group.getPrecursorChromatograms()[k];
968
969 // Identify precursor index
970 // note: this is only valid if all transitions are detecting transitions
971 Size prec_idx = transition_group.getChromatograms().size() + k;
972
973 double local_left = best_left;
974 double local_right = best_right;
975 if (!use_consensus_ && right_edges.size() > prec_idx && left_edges.size() > prec_idx)
976 {
977 local_left = left_edges[prec_idx];
978 local_right = right_edges[prec_idx];
979 }
980
981 SpectrumT used_chromatogram;
982 // resample the current chromatogram
983 if (peak_integration_ == "original")
984 {
985 used_chromatogram = resampleChromatogram_(chromatogram, master_peak_container, local_left, local_right);
986 // const SpectrumT& used_chromatogram = chromatogram; // instead of resampling
987 }
988 else if (peak_integration_ == "smoothed" && smoothed_chroms.size() <= prec_idx)
989 {
990 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
991 "Tried to calculate peak area and height without any smoothed chromatograms for precursors");
992 }
993 else if (peak_integration_ == "smoothed")
994 {
995 used_chromatogram = resampleChromatogram_(smoothed_chroms[prec_idx], master_peak_container, local_left, local_right);
996 }
997 else
998 {
999 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
1000 std::string("Peak integration chromatogram ") + peak_integration_ + " is not a valid method for MRMTransitionGroupPicker");
1001 }
1002
1003 Feature f;
1004 double quality = 0;
1005 f.setQuality(0, quality);
1006 f.setOverallQuality(quality);
1007
1008 PeakIntegrator::PeakArea pa = pi_.integratePeak(used_chromatogram, local_left, local_right);
1009 double peak_integral = pa.area;
1010 double peak_apex_int = pa.height;
1011
1012 // In non-consensus mode, override hull_points with the full resampled
1013 // chromatogram so all precursors produce equal-sized intensity vectors
1014 // for cross-correlation scoring (see pickFragmentChromatograms).
1015 if (!use_consensus_)
1016 {
1017 pa.hull_points.clear();
1018 for (const auto& p : used_chromatogram)
1019 {
1020 pa.hull_points.push_back(DPosition<2>(p.getPos(), p.getIntensity()));
1021 }
1022 }
1023
1024 if (background_subtraction_ != "none")
1025 {
1026 double background{0};
1027 double avg_noise_level{0};
1028 if ((peak_integration_ == "smoothed") && smoothed_chroms.size() <= prec_idx)
1029 {
1030 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
1031 "Tried to calculate background estimation without any smoothed chromatograms");
1032 }
1033 else if (background_subtraction_ == "original")
1034 {
1035 const double intensity_left = chromatogram.PosBegin(local_left)->getIntensity();
1036 const double intensity_right = (chromatogram.PosEnd(local_right) - 1)->getIntensity();
1037 const UInt n_points = std::distance(chromatogram.PosBegin(local_left), chromatogram.PosEnd(local_right));
1038 avg_noise_level = (intensity_right + intensity_left) / 2;
1039 background = avg_noise_level * n_points;
1040 }
1041 else if (background_subtraction_ == "exact")
1042 {
1043 PeakIntegrator::PeakBackground pb = pi_.estimateBackground(used_chromatogram, local_left, local_right, pa.apex_pos);
1044 background = pb.area;
1045 avg_noise_level = pb.height;
1046 }
1047 peak_integral -= background;
1048 peak_apex_int -= avg_noise_level;
1049 if (peak_integral < 0) {peak_integral = 0;}
1050 if (peak_apex_int < 0) {peak_apex_int = 0;}
1051
1052 f.setMetaValue(MRMTransitionGroupPickerMeta::areaBackgroundLevel(), background);
1053 f.setMetaValue(MRMTransitionGroupPickerMeta::noiseBackgroundLevel(), avg_noise_level);
1054 }
1055
1056 f.setMZ(chromatogram.getPrecursor().getMZ());
1057 if (k == 0) {mrmFeature.setMZ(chromatogram.getPrecursor().getMZ());} // only use m/z if first (monoisotopic) isotope
1058
1059 if (chromatogram.metaValueExists("precursor_mz")) // legacy code (ensures that old tests still work)
1060 {
1061 f.setMZ(chromatogram.getMetaValue("precursor_mz"));
1062 if (k == 0) {mrmFeature.setMZ(chromatogram.getMetaValue("precursor_mz"));} // only use m/z if first (monoisotopic) isotope
1063 }
1064
1065 f.setRT(picked_chroms[chr_idx][peak_idx].getPos());
1066 f.setIntensity(peak_integral);
1067 ConvexHull2D hull;
1068 hull.setHullPoints(pa.hull_points);
1069 f.getConvexHulls().push_back(hull);
1070 f.setMetaValue(MRMTransitionGroupPickerMeta::nativeID(), chromatogram.getNativeID());
1071 f.setMetaValue(MRMTransitionGroupPickerMeta::peakApexInt(), peak_apex_int);
1072
1073 if (use_precursors_ && transition_group.getTransitions().empty())
1074 {
1075 total_intensity += peak_integral;
1076 }
1077
1078 mrmFeature.addPrecursorFeature(f, chromatogram.getNativeID());
1079 }
1080 }
1081
1082 // maybe private, but we have tests
1083
1095 template <typename SpectrumT>
1096 void remove_overlapping_features(std::vector<SpectrumT>& picked_chroms, double best_left, double best_right)
1097 {
1098 // delete all seeds that lie within the current seed
1099 Size count_inside = 0;
1100 for (Size k = 0; k < picked_chroms.size(); k++)
1101 {
1102 for (Size i = 0; i < picked_chroms[k].size(); i++)
1103 {
1104 if (picked_chroms[k][i].getPos() >= best_left && picked_chroms[k][i].getPos() <= best_right)
1105 {
1106 picked_chroms[k][i].setIntensity(0.0);
1107 count_inside++;
1108 }
1109 }
1110 }
1111
1112 Size count_overlap = 0;
1113 // delete all seeds that overlap within the current seed
1114 for (Size k = 0; k < picked_chroms.size(); k++)
1115 {
1116 for (Size i = 0; i < picked_chroms[k].size(); i++)
1117 {
1118 if (picked_chroms[k][i].getIntensity() <= 1e-11) {continue; }
1119
1120 double left = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][i];
1121 double right = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][i];
1122 if ((left > best_left && left < best_right)
1123 || (right > best_left && right < best_right))
1124 {
1125 picked_chroms[k][i].setIntensity(0.0);
1126 count_overlap++;
1127 }
1128 }
1129 }
1130 OPENMS_LOG_DEBUG << " ** Removed " << count_inside << " peaks enclosed in and " <<
1131 count_overlap << " peaks overlapping with added feature." << std::endl;
1132 }
1133
1135 void findLargestPeak(const std::vector<MSChromatogram >& picked_chroms, int& chr_idx, int& peak_idx);
1136
1137 template <typename SpectrumT>
1138 void findLargestPeakCached_(const std::vector<SpectrumT>& picked_chroms,
1139 std::vector<int>& largest_peak_indices,
1140 int& chr_idx,
1141 int& peak_idx) const
1142 {
1143 OPENMS_PRECONDITION(largest_peak_indices.size() == picked_chroms.size(),
1144 "Cached largest peak indices must match picked chromatogram count.");
1145 double largest = 0.0;
1146 for (Size k = 0; k < picked_chroms.size(); k++)
1147 {
1148 int candidate_idx = largest_peak_indices[k];
1149 while (candidate_idx >= 0 && picked_chroms[k][candidate_idx].getIntensity() <= 0.0)
1150 {
1151 --candidate_idx;
1152 }
1153 largest_peak_indices[k] = candidate_idx;
1154 if (candidate_idx < 0)
1155 {
1156 continue;
1157 }
1158 const double intensity = picked_chroms[k][candidate_idx].getIntensity();
1159 if (intensity > largest)
1160 {
1161 largest = intensity;
1162 chr_idx = static_cast<int>(k);
1163 peak_idx = candidate_idx;
1164 }
1165 }
1166 }
1167
1176 void findWidestPeakIndices(const std::vector<MSChromatogram>& picked_chroms, Int& chrom_idx, Int& point_idx) const;
1177
1178protected:
1179
1181 void updateMembers_() override;
1182
1185
1189 template <typename SpectrumT, typename TransitionT>
1190 const SpectrumT& selectChromHelper_(const MRMTransitionGroup<SpectrumT, TransitionT>& transition_group, const std::string& native_id)
1191 {
1192 if (transition_group.hasChromatogram(native_id))
1193 {
1194 return transition_group.getChromatogram(native_id);
1195 }
1196 else if (transition_group.hasPrecursorChromatogram(native_id))
1197 {
1198 return transition_group.getPrecursorChromatogram(native_id);
1199 }
1200 else
1201 {
1202 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Did not find chromatogram for id '" + native_id + "'.");
1203 }
1204 }
1205
1222 template <typename SpectrumT, typename TransitionT>
1224 const std::vector<SpectrumT>& picked_chroms,
1225 const std::vector<const SpectrumT*>& picked_input_chromatograms,
1226 const int chr_idx,
1227 const double best_left,
1228 const double best_right,
1229 std::string& outlier)
1230 {
1231 // Resample all chromatograms around the current estimated peak and
1232 // collect the raw intensities. For resampling, use a bit more on either
1233 // side to correctly identify shoulders etc.
1234 double resample_boundary = resample_boundary_; // sample 15 seconds more on each side
1235 SpectrumT master_peak_container;
1236 const SpectrumT& ref_chromatogram = *picked_input_chromatograms[chr_idx];
1237 prepareMasterContainer_(ref_chromatogram, master_peak_container, best_left - resample_boundary, best_right + resample_boundary);
1238 // Reuse the shared per-thread pool's containers for quality computation
1239 auto &pool = g_picker_pool_shared();
1240 auto &all_ints = pool.all_ints;
1241 all_ints.clear();
1242 for (Size k = 0; k < picked_chroms.size(); k++)
1243 {
1244 const SpectrumT& chromatogram = *picked_input_chromatograms[k];
1245 const SpectrumT used_chromatogram = resampleChromatogram_(chromatogram,
1246 master_peak_container, best_left - resample_boundary, best_right + resample_boundary);
1247
1248 std::vector<double> int_here;
1249 for (const auto& peak : used_chromatogram) int_here.push_back(peak.getIntensity());
1250 // Remove chromatograms without a single peak
1251 double tic = std::accumulate(int_here.begin(), int_here.end(), 0.0);
1252 if (tic > 1e-11) all_ints.push_back(int_here);
1253 }
1254
1255 // Compute the cross-correlation for the collected intensities
1256 auto &mean_shapes = pool.mean_shapes;
1257 auto &mean_coel = pool.mean_coel;
1258 mean_shapes.clear();
1259 mean_coel.clear();
1260 for (Size k = 0; k < all_ints.size(); k++)
1261 {
1262 std::vector<double> shapes;
1263 std::vector<double> coel;
1264 for (Size i = 0; i < all_ints.size(); i++)
1265 {
1266 if (i == k) {continue;}
1268 = OpenSwath::Scoring::normalizedCrossCorrelation(all_ints[k], all_ints[i], OpenMS::checkedCast<int>(all_ints[i].size()), 1);
1269
1270 // the first value is the x-axis (retention time) and should be an int -> it show the lag between the two
1271 double res_coelution = std::abs(OpenSwath::Scoring::xcorrArrayGetMaxPeak(res)->first);
1272 double res_shape = std::abs(OpenSwath::Scoring::xcorrArrayGetMaxPeak(res)->second);
1273
1274 shapes.push_back(res_shape);
1275 coel.push_back(res_coelution);
1276 }
1277
1278 // We have computed the cross-correlation of chromatogram k against
1279 // all others. Use the mean of these computations as the value for k.
1281 msc = std::for_each(shapes.begin(), shapes.end(), msc);
1282 double shapes_mean = msc.mean();
1283 msc = std::for_each(coel.begin(), coel.end(), msc);
1284 double coel_mean = msc.mean();
1285
1286 // mean shape scores below 0.5-0.6 should be a real sign of trouble ... !
1287 // mean coel scores above 3.5 should be a real sign of trouble ... !
1288 mean_shapes.push_back(shapes_mean);
1289 mean_coel.push_back(coel_mean);
1290 }
1291
1292 // find the chromatogram with the minimal shape score and the maximal
1293 // coelution score -> if it is the same chromatogram, the chance is
1294 // pretty good that it is different from the others...
1295 int min_index_shape = std::distance(mean_shapes.begin(), std::min_element(mean_shapes.begin(), mean_shapes.end()));
1296 int max_index_coel = std::distance(mean_coel.begin(), std::max_element(mean_coel.begin(), mean_coel.end()));
1297
1298 // Look at the picked peaks that are within the current left/right borders
1299 int missing_peaks = 0;
1300 int multiple_peaks = 0;
1301
1302 // collect all seeds that lie within the current seed
1303 auto &left_borders = pool.left_borders;
1304 auto &right_borders = pool.right_borders;
1305 left_borders.clear();
1306 right_borders.clear();
1307 for (Size k = 0; k < picked_chroms.size(); k++)
1308 {
1309 double l_tmp;
1310 double r_tmp;
1311 double max_int = -1;
1312
1313 int pfound = 0;
1314 l_tmp = -1;
1315 r_tmp = -1;
1316 for (Size i = 0; i < picked_chroms[k].size(); i++)
1317 {
1318 if (picked_chroms[k][i].getPos() >= best_left && picked_chroms[k][i].getPos() <= best_right)
1319 {
1320 pfound++;
1321 if (picked_chroms[k][i].getIntensity() > max_int)
1322 {
1323 max_int = picked_chroms[k][i].getIntensity() > max_int;
1324 l_tmp = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][i];
1325 r_tmp = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][i];
1326 }
1327 }
1328 }
1329
1330 if (l_tmp > 1e-11) left_borders.push_back(l_tmp);
1331 if (r_tmp > 1e-11) right_borders.push_back(r_tmp);
1332
1333 if (pfound == 0) missing_peaks++;
1334 if (pfound > 1) multiple_peaks++;
1335 }
1336
1337 // Check how many chromatograms had exactly one peak picked between our
1338 // current left/right borders -> this would be a sign of consistency.
1339 OPENMS_LOG_DEBUG << " Overall found missing : " << missing_peaks << " and multiple : " << multiple_peaks << std::endl;
1340
1342
1343 // Is there one transitions that is very different from the rest (e.g.
1344 // the same element has a bad shape and a bad coelution score) -> potential outlier
1345 if (min_index_shape == max_index_coel)
1346 {
1347 OPENMS_LOG_DEBUG << " Element " << min_index_shape << " is a candidate for removal ... " << std::endl;
1348 outlier =std::string(picked_chroms[min_index_shape].getNativeID());
1349 }
1350 else
1351 {
1352 outlier = "none";
1353 }
1354
1355 // For the final score (larger is better), consider these scores:
1356 // - missing_peaks (the more peaks are missing, the worse)
1357 // - multiple_peaks
1358 // - mean of the shapes (1 is very good, 0 is bad)
1359 // - mean of the co-elution scores (0 is good, 1 is ok, above 1 is pretty bad)
1360 double shape_score = std::accumulate(mean_shapes.begin(), mean_shapes.end(), 0.0) / mean_shapes.size();
1361 double coel_score = std::accumulate(mean_coel.begin(), mean_coel.end(), 0.0) / mean_coel.size();
1362 coel_score = (coel_score - 1.0) / 2.0;
1363
1364 double score = shape_score - coel_score - 1.0 * missing_peaks / picked_chroms.size();
1365
1366 OPENMS_LOG_DEBUG << " Computed score " << score << " (from " << shape_score <<
1367 " - " << coel_score << " - " << 1.0 * missing_peaks / picked_chroms.size() << ")" << std::endl;
1368
1369 return score;
1370 }
1371
1381 template <typename SpectrumT>
1382 void recalculatePeakBorders_(const std::vector<SpectrumT>& picked_chroms, double& best_left, double& best_right, double max_z)
1383 {
1384 // 1. Collect all seeds that lie within the current seed
1385 // - Per chromatogram only the most intense one counts, otherwise very
1386 // - low intense peaks can contribute disproportionally to the voting
1387 // - procedure.
1388 // TODO Especially with DDA MS1 "transitions" from FFID, you often have exactly the same
1389 // borders and the logs get confusing and you get -Nan CVs. You also might save time if you use a set here.
1390 std::vector<double> left_borders;
1391 std::vector<double> right_borders;
1392 for (Size k = 0; k < picked_chroms.size(); k++)
1393 {
1394 double max_int = -1;
1395 double left = -1;
1396 double right = -1;
1397 for (Size i = 0; i < picked_chroms[k].size(); i++)
1398 {
1399 if (picked_chroms[k][i].getPos() >= best_left && picked_chroms[k][i].getPos() <= best_right)
1400 {
1401 if (picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_ABUNDANCE][i] > max_int)
1402 {
1403 max_int = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_ABUNDANCE][i];
1404 left = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][i];
1405 right = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][i];
1406 }
1407 }
1408 }
1409 if (max_int > -1 )
1410 {
1411 left_borders.push_back(left);
1412 right_borders.push_back(right);
1413 OPENMS_LOG_DEBUG << " * peak " << k << " left boundary " << left_borders.back() << " with inty " << max_int << std::endl;
1414 OPENMS_LOG_DEBUG << " * peak " << k << " right boundary " << right_borders.back() << " with inty " << max_int << std::endl;
1415 }
1416 }
1417
1418 // Return for empty peak list
1419 if (right_borders.empty())
1420 {
1421 return;
1422 }
1423
1424 // FEATURE IDEA: instead of Z-score use modified Z-score for small data sets
1425 // http://d-scholarship.pitt.edu/7948/1/Seo.pdf
1426 // http://www.itl.nist.gov/div898/handbook/eda/section3/eda35h.htm
1427 // 1. calculate median
1428 // 2. MAD = calculate difference to median for each value -> take median of that
1429 // 3. Mi = 0.6745*(xi - median) / MAD
1430
1431 // 2. Calculate mean and standard deviation
1432 // If the coefficient of variation is too large for one border, we use a
1433 // "pseudo-median" instead of the border of the most intense peak.
1434 double mean, stdev;
1435
1436 // Right borders
1437 mean = std::accumulate(right_borders.begin(), right_borders.end(), 0.0) / (double) right_borders.size();
1438 stdev = std::sqrt(std::inner_product(right_borders.begin(), right_borders.end(), right_borders.begin(), 0.0)
1439 / right_borders.size() - mean * mean);
1440 std::sort(right_borders.begin(), right_borders.end());
1441
1442 OPENMS_LOG_DEBUG << " - Recalculating right peak boundaries " << mean << " mean / best "
1443 << best_right << " std " << stdev << " : " << std::fabs(best_right - mean) / stdev
1444 << " coefficient of variation" << std::endl;
1445
1446 // Compare right borders of best transition with the mean
1447 if (std::fabs(best_right - mean) / stdev > max_z)
1448 {
1449 best_right = right_borders[right_borders.size() / 2]; // pseudo median
1450 OPENMS_LOG_DEBUG << " - CV too large: correcting right boundary to " << best_right << std::endl;
1451 }
1452
1453 // Left borders
1454 mean = std::accumulate(left_borders.begin(), left_borders.end(), 0.0) / (double) left_borders.size();
1455 stdev = std::sqrt(std::inner_product(left_borders.begin(), left_borders.end(), left_borders.begin(), 0.0)
1456 / left_borders.size() - mean * mean);
1457 std::sort(left_borders.begin(), left_borders.end());
1458
1459 OPENMS_LOG_DEBUG << " - Recalculating left peak boundaries " << mean << " mean / best "
1460 << best_left << " std " << stdev << " : " << std::fabs(best_left - mean) / stdev
1461 << " coefficient of variation" << std::endl;
1462
1463 // Compare left borders of best transition with the mean
1464 if (std::fabs(best_left - mean) / stdev > max_z)
1465 {
1466 best_left = left_borders[left_borders.size() / 2]; // pseudo median
1467 OPENMS_LOG_DEBUG << " - CV too large: correcting left boundary to " << best_left << std::endl;
1468 }
1469
1470 }
1471
1473
1474
1489 template <typename PeakContainerT>
1490 void prepareMasterContainer_(const PeakContainerT& ref_chromatogram,
1491 PeakContainerT& master_peak_container,
1492 double left_boundary,
1493 double right_boundary)
1494 {
1495 OPENMS_PRECONDITION(master_peak_container.empty(), "Master peak container must be empty")
1496
1497 // get the start / end point of this chromatogram => then add one more
1498 // point beyond the two boundaries to make the resampling accurate also
1499 // at the edge.
1500 auto begin = ref_chromatogram.begin();
1501 while (begin != ref_chromatogram.end() && begin->getPos() < left_boundary) {begin++; }
1502 if (begin != ref_chromatogram.begin()) { begin--; }
1503
1504 auto end = begin;
1505 while (end != ref_chromatogram.end() && end->getPos() < right_boundary) {end++; }
1506 if (end != ref_chromatogram.end()) { end++; }
1507
1508 // resize the master container and set the m/z values to the ones of the master container
1509 master_peak_container.resize(distance(begin, end)); // initialize to zero
1510 auto it = master_peak_container.begin();
1511 for (auto chrom_it = begin; chrom_it != end; chrom_it++, it++)
1512 {
1513 it->setPos(chrom_it->getPos());
1514 }
1515 }
1516
1527 template <typename PeakContainerT>
1528 PeakContainerT resampleChromatogram_(const PeakContainerT& chromatogram,
1529 const PeakContainerT& master_peak_container,
1530 double left_boundary,
1531 double right_boundary)
1532 {
1533 // get the start / end point of this chromatogram => then add one more
1534 // point beyond the two boundaries to make the resampling accurate also
1535 // at the edge.
1536 auto begin = chromatogram.begin();
1537 while (begin != chromatogram.end() && begin->getPos() < left_boundary) {begin++;}
1538 if (begin != chromatogram.begin()) { begin--; }
1539
1540 auto end = begin;
1541 while (end != chromatogram.end() && end->getPos() < right_boundary) {end++;}
1542 if (end != chromatogram.end()) { end++; }
1543
1544 auto resampled_peak_container = master_peak_container; // copy the master container, which contains the RT values
1545 LinearResamplerAlign lresampler;
1546 lresampler.raster(begin, end, resampled_peak_container.begin(), resampled_peak_container.end());
1547
1548 return resampled_peak_container;
1549 }
1550
1552
1553 // Members
1563
1569
1576
1579 };
1580}
#define OPENMS_LOG_DEBUG
Definition LogStream.h:714
const std::string & getNativeID() const
returns the native identifier for the spectrum, used by the acquisition software.
void setNativeID(const std::string &native_id)
sets the native identifier for the spectrum, used by the acquisition software.
Definition ConvexHull2D.h:49
void setHullPoints(const PointArrayType &points)
accessor for the outer(!) points (no checking is performed if this is actually a convex hull)
Representation of a coordinate in D-dimensional space.
Definition DPosition.h:32
A base class for all classes handling default parameters.
Definition DefaultParamHandler.h:66
A method or algorithm argument contains illegal values.
Definition Exception.h:633
An LC-MS feature.
Definition Feature.h:46
const std::vector< ConvexHull2D > & getConvexHulls() const
Non-mutable access to the convex hulls.
void setQuality(Size index, QualityType q)
Set the quality in dimension c.
void setOverallQuality(QualityType q)
Set the overall quality.
Linear Resampling of raw data with alignment.
Definition LinearResamplerAlign.h:72
void raster(PeakContainerT &container)
Applies the resampling algorithm to a container (MSSpectrum or MSChromatogram).
Definition LinearResamplerAlign.h:92
A multi-chromatogram MRM feature.
Definition MRMFeature.h:26
void addFeature(const Feature &feature, const std::string &key)
Adds an feature from a single chromatogram into the feature.
void addPrecursorFeature(const Feature &feature, const std::string &key)
Adds a precursor feature from a single chromatogram into the feature.
The MRMTransitionGroupPicker finds peaks in chromatograms that belong to the same precursors.
Definition MRMTransitionGroupPicker.h:285
void findLargestPeak(const std::vector< MSChromatogram > &picked_chroms, int &chr_idx, int &peak_idx)
Find largest peak in a vector of chromatograms.
void prepareMasterContainer_(const PeakContainerT &ref_chromatogram, PeakContainerT &master_peak_container, double left_boundary, double right_boundary)
Create an empty master peak container that has the correct mz / RT values set.
Definition MRMTransitionGroupPicker.h:1490
void findLargestPeakCached_(const std::vector< SpectrumT > &picked_chroms, std::vector< int > &largest_peak_indices, int &chr_idx, int &peak_idx) const
Definition MRMTransitionGroupPicker.h:1138
bool compute_total_mi_
Definition MRMTransitionGroupPicker.h:1561
std::string peak_integration_
Definition MRMTransitionGroupPicker.h:1554
bool compute_peak_quality_
Definition MRMTransitionGroupPicker.h:1559
bool use_precursors_
Definition MRMTransitionGroupPicker.h:1557
PeakContainerT resampleChromatogram_(const PeakContainerT &chromatogram, const PeakContainerT &master_peak_container, double left_boundary, double right_boundary)
Resample a container at the positions indicated by the master peak container.
Definition MRMTransitionGroupPicker.h:1528
void pickApex(std::vector< SpectrumT > &picked_chroms, const double best_left, const double best_right, const double peak_apex, double &min_left, double &max_right, std::vector< double > &left_edges, std::vector< double > &right_edges)
Apex-based peak picking.
Definition MRMTransitionGroupPicker.h:698
std::string background_subtraction_
Definition MRMTransitionGroupPicker.h:1555
const SpectrumT & selectChromHelper_(const MRMTransitionGroup< SpectrumT, TransitionT > &transition_group, const std::string &native_id)
Select matching precursor or fragment ion chromatogram.
Definition MRMTransitionGroupPicker.h:1190
double min_peak_width_
Definition MRMTransitionGroupPicker.h:1566
void remove_overlapping_features(std::vector< SpectrumT > &picked_chroms, double best_left, double best_right)
Remove overlapping features.
Definition MRMTransitionGroupPicker.h:1096
void recalculatePeakBorders_(const std::vector< SpectrumT > &picked_chroms, double &best_left, double &best_right, double max_z)
Recalculate the borders of the peak.
Definition MRMTransitionGroupPicker.h:1382
int stop_after_feature_
Definition MRMTransitionGroupPicker.h:1564
PeakPickerChromatogram picker_
Definition MRMTransitionGroupPicker.h:1577
double recalculate_peaks_max_z_
Definition MRMTransitionGroupPicker.h:1567
PeakIntegrator pi_
Definition MRMTransitionGroupPicker.h:1578
void findWidestPeakIndices(const std::vector< MSChromatogram > &picked_chroms, Int &chrom_idx, Int &point_idx) const
Given a vector of chromatograms, find the indices of the chromatogram containing the widest peak and ...
double min_qual_
Definition MRMTransitionGroupPicker.h:1562
double resample_boundary_
Definition MRMTransitionGroupPicker.h:1568
MRMFeature createMRMFeature(const MRMTransitionGroup< SpectrumT, TransitionT > &transition_group, std::vector< SpectrumT > &picked_chroms, const std::vector< SpectrumT > &smoothed_chroms, const int chr_idx, const int peak_idx)
Create a feature from picked chromatograms and a specified peak.
Definition MRMTransitionGroupPicker.h:495
~MRMTransitionGroupPicker() override
Destructor.
void pickFragmentChromatograms(const MRMTransitionGroup< SpectrumT, TransitionT > &transition_group, const std::vector< SpectrumT > &picked_chroms, MRMFeature &mrmFeature, const std::vector< SpectrumT > &smoothed_chroms, const double best_left, const double best_right, const bool use_consensus_, double &total_intensity, double &total_xic, double &total_mi, double &total_peak_apices, const SpectrumT &master_peak_container, const std::vector< double > &left_edges, const std::vector< double > &right_edges, const std::vector< double > &transition_total_xics, double detecting_total_xic, const std::vector< const SpectrumT * > &transition_chromatograms, const int chr_idx, const int peak_idx)
Definition MRMTransitionGroupPicker.h:739
MRMFeature createMRMFeature(const MRMTransitionGroup< SpectrumT, TransitionT > &transition_group, std::vector< SpectrumT > &picked_chroms, const std::vector< SpectrumT > &smoothed_chroms, const std::vector< double > &transition_total_xics, double detecting_total_xic, const std::vector< const SpectrumT * > &transition_chromatograms, const std::vector< const SpectrumT * > &picked_input_chromatograms, const int chr_idx, const int peak_idx)
Create a feature from picked chromatograms and precomputed transition data.
Definition MRMTransitionGroupPicker.h:556
void updateMembers_() override
Synchronize members with param class.
double stop_after_intensity_ratio_
Definition MRMTransitionGroupPicker.h:1565
void pickTransitionGroup(MRMTransitionGroup< SpectrumT, TransitionT > &transition_group)
Pick a group of chromatograms belonging to the same peptide.
Definition MRMTransitionGroupPicker.h:317
MRMTransitionGroupPicker & operator=(const MRMTransitionGroupPicker &rhs)
Assignment operator is protected for algorithm.
bool use_consensus_
Definition MRMTransitionGroupPicker.h:1558
std::string boundary_selection_method_
Which method to use for selecting peaks' boundaries.
Definition MRMTransitionGroupPicker.h:1575
bool recalculate_peaks_
Definition MRMTransitionGroupPicker.h:1556
void pickPrecursorChromatograms(const MRMTransitionGroup< SpectrumT, TransitionT > &transition_group, const std::vector< SpectrumT > &picked_chroms, MRMFeature &mrmFeature, const std::vector< SpectrumT > &smoothed_chroms, const double best_left, const double best_right, const bool use_consensus_, double &total_intensity, const SpectrumT &master_peak_container, const std::vector< double > &left_edges, const std::vector< double > &right_edges, const int chr_idx, const int peak_idx)
Definition MRMTransitionGroupPicker.h:952
bool compute_peak_shape_metrics_
Definition MRMTransitionGroupPicker.h:1560
double computeQuality_(const MRMTransitionGroup< SpectrumT, TransitionT > &, const std::vector< SpectrumT > &picked_chroms, const std::vector< const SpectrumT * > &picked_input_chromatograms, const int chr_idx, const double best_left, const double best_right, std::string &outlier)
Compute transition group quality (higher score is better)
Definition MRMTransitionGroupPicker.h:1223
The representation of a group of transitions in a targeted proteomics experiment.
Definition MRMTransitionGroup.h:41
bool hasPrecursorChromatogram(const std::string &key) const
Definition MRMTransitionGroup.h:241
const std::vector< TransitionType > & getTransitions() const
Definition MRMTransitionGroup.h:115
ChromatogramType & getPrecursorChromatogram(const std::string &key)
Definition MRMTransitionGroup.h:246
const TransitionType & getTransition(const std::string &key)
Definition MRMTransitionGroup.h:148
ChromatogramType & getChromatogram(const std::string &key)
Definition MRMTransitionGroup.h:192
bool isInternallyConsistent() const
Check whether internal state is consistent, e.g. same number of chromatograms and transitions are pre...
Definition MRMTransitionGroup.h:290
bool chromatogramIdsMatch() const
Ensure that chromatogram native ids match their keys in the map.
Definition MRMTransitionGroup.h:299
const std::string & getTransitionGroupID() const
Definition MRMTransitionGroup.h:103
void addFeature(const MRMFeature &feature)
Definition MRMTransitionGroup.h:274
std::vector< ChromatogramType > & getPrecursorChromatograms()
Definition MRMTransitionGroup.h:210
std::vector< ChromatogramType > & getChromatograms()
Definition MRMTransitionGroup.h:159
bool hasChromatogram(const std::string &key) const
Definition MRMTransitionGroup.h:187
bool hasTransition(const std::string &key) const
Definition MRMTransitionGroup.h:143
The representation of a chromatogram.
Definition MSChromatogram.h:33
void sortByIntensity(bool reverse=false)
Lexicographically sorts the peaks by their intensity.
const DataValue & getMetaValue(const std::string &name) const
Returns the value corresponding to a string, or DataValue::EMPTY if not found.
void setMetaValue(const std::string &name, const DataValue &value)
Sets the DataValue corresponding to a name.
UInt registerName(const std::string &name, const std::string &description="", const std::string &unit="")
static MetaInfoRegistry & registry()
Returns a reference to the MetaInfoRegistry.
void setMZ(CoordinateType coordinate)
Mutable access to the m/z coordinate (index 1)
Definition Peak2D.h:179
void setRT(CoordinateType coordinate)
Mutable access to the RT coordinate (index 0)
Definition Peak2D.h:191
IntensityType getIntensity() const
Definition Peak2D.h:143
void setIntensity(IntensityType intensity)
Sets data point intensity (height)
Definition Peak2D.h:149
Compute the area, background and shape metrics of a peak.
Definition PeakIntegrator.h:87
Int points_across_half_height
Definition PeakIntegrator.h:224
double apex_pos
Definition PeakIntegrator.h:111
ConvexHull2D::PointArrayType hull_points
Definition PeakIntegrator.h:115
double width_at_5
Definition PeakIntegrator.h:146
Int points_across_baseline
Definition PeakIntegrator.h:220
double width_at_50
Definition PeakIntegrator.h:154
double end_position_at_50
Definition PeakIntegrator.h:178
double baseline_delta_2_height
Definition PeakIntegrator.h:216
double height
Definition PeakIntegrator.h:107
double end_position_at_10
Definition PeakIntegrator.h:174
double width_at_10
Definition PeakIntegrator.h:150
double total_width
Definition PeakIntegrator.h:182
double end_position_at_5
Definition PeakIntegrator.h:170
double start_position_at_50
Definition PeakIntegrator.h:166
double tailing_factor
Definition PeakIntegrator.h:196
double slope_of_baseline
Definition PeakIntegrator.h:211
double start_position_at_10
Definition PeakIntegrator.h:162
double asymmetry_factor
Definition PeakIntegrator.h:206
double start_position_at_5
Definition PeakIntegrator.h:158
double area
Definition PeakIntegrator.h:103
Definition PeakIntegrator.h:99
Definition PeakIntegrator.h:124
Definition PeakIntegrator.h:142
The PeakPickerChromatogram finds peaks a single chromatogram.
Definition PeakPickerChromatogram.h:51
Size ensureUniqueId()
Assigns a valid unique id, but only if the present one is invalid. Returns 1 if the unique id was cha...
functor to compute the mean and stddev of sequence using the std::foreach algorithm
Definition StatsHelpers.h:147
double mean() const
Definition StatsHelpers.h:184
OpenMS looks in the< code > OPENMS_THERMO_MANAGED_DIR</code > environment variable first
Definition common-cmake-parameters.doxygen:199
int Int
Signed integer type.
Definition Types.h:72
unsigned int UInt
Unsigned integer type.
Definition Types.h:64
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition Types.h:97
#define OPENMS_PRECONDITION(condition, message)
Precondition macro.
Definition openms/include/OpenMS/CONCEPT/Macros.h:91
UInt rightWidth()
Definition MRMTransitionGroupPicker.h:191
UInt widthAt10()
Definition MRMTransitionGroupPicker.h:251
UInt potentialOutlier()
Definition MRMTransitionGroupPicker.h:185
UInt startPositionAt50()
Definition MRMTransitionGroupPicker.h:215
UInt widthAt5()
Definition MRMTransitionGroupPicker.h:245
UInt peakApexInt()
Definition MRMTransitionGroupPicker.h:149
UInt asymmetryFactor()
Definition MRMTransitionGroupPicker.h:95
UInt widthAt50()
Definition MRMTransitionGroupPicker.h:257
UInt areaBackgroundLevel()
Definition MRMTransitionGroupPicker.h:89
UInt totalXIC()
Definition MRMTransitionGroupPicker.h:239
UInt endPositionAt10()
Definition MRMTransitionGroupPicker.h:113
UInt peakApexPosition()
Definition MRMTransitionGroupPicker.h:155
UInt nativeID()
Definition MRMTransitionGroupPicker.h:137
UInt totalMI()
Definition MRMTransitionGroupPicker.h:227
UInt startPositionAt10()
Definition MRMTransitionGroupPicker.h:209
UInt endPositionAt5()
Definition MRMTransitionGroupPicker.h:107
UInt pointsAcrossBaseline()
Definition MRMTransitionGroupPicker.h:173
UInt initialPeakQuality()
Definition MRMTransitionGroupPicker.h:125
UInt totalWidth()
Definition MRMTransitionGroupPicker.h:233
UInt tailingFactor()
Definition MRMTransitionGroupPicker.h:221
UInt peakApicesSum()
Definition MRMTransitionGroupPicker.h:161
UInt pointsAcrossHalfHeight()
Definition MRMTransitionGroupPicker.h:179
UInt noiseBackgroundLevel()
Definition MRMTransitionGroupPicker.h:143
UInt endPositionAt50()
Definition MRMTransitionGroupPicker.h:119
UInt startPositionAt5()
Definition MRMTransitionGroupPicker.h:203
UInt slopeOfBaseline()
Definition MRMTransitionGroupPicker.h:197
UInt leftWidth()
Definition MRMTransitionGroupPicker.h:131
UInt peptideRef()
Definition MRMTransitionGroupPicker.h:167
UInt baselineDelta2Height()
Definition MRMTransitionGroupPicker.h:101
Main OpenMS namespace.
Definition openswathalgo/include/OpenMS/OPENSWATHALGO/DATAACCESS/ISpectrumAccess.h:19
PickerPoolShared & g_picker_pool_shared()
Definition MRMTransitionGroupPicker.h:81
OPENSWATHALGO_DLLAPI XCorrArrayType normalizedCrossCorrelation(std::vector< double > &data1, std::vector< double > &data2, const int maxdelay, const int lag)
OPENSWATHALGO_DLLAPI unsigned int computeAndAppendRank(const std::vector< double > &v, std::vector< unsigned int > &ranks)
OPENSWATHALGO_DLLAPI double rankedMutualInformation(std::vector< unsigned int > &ranked_data1, std::vector< unsigned int > &ranked_data2, const unsigned int max_rank1, const unsigned int max_rank2)
OPENSWATHALGO_DLLAPI XCorrArrayType::const_iterator xcorrArrayGetMaxPeak(const XCorrArrayType &array)
Find best peak in an cross-correlation (highest apex)
Definition MRMTransitionGroupPicker.h:40
std::vector< double > right_edges
Definition MRMTransitionGroupPicker.h:47
std::vector< double > transition_total_xics
Definition MRMTransitionGroupPicker.h:54
std::vector< double > mean_coel
Definition MRMTransitionGroupPicker.h:50
std::vector< double > mean_shapes
Definition MRMTransitionGroupPicker.h:49
std::vector< double > right_borders
Definition MRMTransitionGroupPicker.h:52
std::vector< double > left_borders
Definition MRMTransitionGroupPicker.h:51
std::vector< const MSChromatogram * > picked_input_chromatograms
Definition MRMTransitionGroupPicker.h:43
std::vector< MRMFeature > features
Definition MRMTransitionGroupPicker.h:45
std::vector< const MSChromatogram * > transition_chromatograms
Definition MRMTransitionGroupPicker.h:44
std::vector< MSChromatogram > picked_chroms
Definition MRMTransitionGroupPicker.h:41
std::vector< double > left_edges
Definition MRMTransitionGroupPicker.h:46
std::vector< MSChromatogram > smoothed_chroms
Definition MRMTransitionGroupPicker.h:42
std::vector< int > largest_peak_indices
Definition MRMTransitionGroupPicker.h:53
std::vector< std::vector< double > > all_ints
Definition MRMTransitionGroupPicker.h:48
void reset()
Definition MRMTransitionGroupPicker.h:56
Definition Scoring.h:46