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