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 (against all earlier features, so decide for all
460 // of them before moving the kept ones into the transition group)
461 std::vector<char> keep(features.size(), 0);
462 for (Size i = 0; i < features.size(); i++)
463 {
464 const MRMFeature& mrm_feature = features[i];
465 bool skip = false;
466 for (Size j = 0; j < i; j++)
467 {
468 if ((double)mrm_feature.getMetaValue(MRMTransitionGroupPickerMeta::leftWidth()) >= (double)features[j].getMetaValue(MRMTransitionGroupPickerMeta::leftWidth()) &&
469 (double)mrm_feature.getMetaValue(MRMTransitionGroupPickerMeta::rightWidth()) <= (double)features[j].getMetaValue(MRMTransitionGroupPickerMeta::rightWidth()))
470 { skip = true; }
471 }
472 keep[i] = mrm_feature.getIntensity() > 0 && !skip;
473 }
474 for (Size i = 0; i < features.size(); i++)
475 {
476 if (keep[i])
477 {
478 transition_group.addFeature(std::move(features[i]));
479 }
480 }
481
482 }
483
500 template <typename SpectrumT, typename TransitionT>
502 std::vector<SpectrumT>& picked_chroms,
503 const std::vector<SpectrumT>& smoothed_chroms,
504 const int chr_idx,
505 const int peak_idx)
506 {
507 std::vector<double> transition_total_xics;
508 transition_total_xics.reserve(transition_group.getTransitions().size());
509 std::vector<const SpectrumT*> transition_chromatograms;
510 transition_chromatograms.reserve(transition_group.getTransitions().size());
511 double detecting_total_xic = 0.0;
512 for (const TransitionT& transition : transition_group.getTransitions())
513 {
514 const SpectrumT& chromatogram = selectChromHelper_(transition_group, transition.getNativeID());
515 transition_chromatograms.push_back(&chromatogram);
516 const double transition_total_xic = std::accumulate(chromatogram.begin(), chromatogram.end(), 0.0,
517 [](double total, const auto& peak)
518 {
519 return total + peak.getIntensity();
520 });
521 transition_total_xics.push_back(transition_total_xic);
522 if (transition.isDetectingTransition())
523 {
524 detecting_total_xic += transition_total_xic;
525 }
526 }
527
528 std::vector<const SpectrumT*> picked_input_chromatograms;
529 picked_input_chromatograms.reserve(picked_chroms.size());
530 for (const SpectrumT& picked_chrom : picked_chroms)
531 {
532 picked_input_chromatograms.push_back(&selectChromHelper_(transition_group, picked_chrom.getNativeID()));
533 }
534
535 return createMRMFeature(transition_group, picked_chroms, smoothed_chroms,
536 transition_total_xics, detecting_total_xic,
537 transition_chromatograms, picked_input_chromatograms,
538 chr_idx, peak_idx);
539 }
540
561 template <typename SpectrumT, typename TransitionT>
563 std::vector<SpectrumT>& picked_chroms,
564 const std::vector<SpectrumT>& smoothed_chroms,
565 const std::vector<double>& transition_total_xics,
566 double detecting_total_xic,
567 const std::vector<const SpectrumT*>& transition_chromatograms,
568 const std::vector<const SpectrumT*>& picked_input_chromatograms,
569 const int chr_idx,
570 const int peak_idx)
571 {
572 OPENMS_PRECONDITION(transition_group.isInternallyConsistent(), "Consistent state required")
573 OPENMS_PRECONDITION(transition_group.chromatogramIdsMatch(), "Chromatogram native IDs need to match keys in transition group")
574
575 MRMFeature mrmFeature;
576 mrmFeature.setIntensity(0.0);
577 double best_left = picked_chroms[chr_idx].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][peak_idx];
578 double best_right = picked_chroms[chr_idx].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][peak_idx];
579 double peak_apex = picked_chroms[chr_idx][peak_idx].getRT();
580 OPENMS_LOG_DEBUG << "**** Creating MRMFeature for peak " << peak_idx << " in chrom. " << chr_idx << " with " <<
581 picked_chroms[chr_idx][peak_idx] << " and borders " << best_left << " " <<
582 best_right << " (" << best_right - best_left << ")" << std::endl;
583
584 if (use_consensus_ && recalculate_peaks_)
585 {
586 // This may change best_left / best_right
587 recalculatePeakBorders_(picked_chroms, best_left, best_right, recalculate_peaks_max_z_);
588 if (peak_apex < best_left || peak_apex > best_right)
589 {
590 // apex fell out of range, lets correct it
591 peak_apex = (best_left + best_right) / 2.0;
592 }
593 }
594
595 // Use a small thread-local pool for these per-feature vectors to avoid
596 // frequent allocations when called repeatedly.
597 struct CreateFeaturePool
598 {
599 std::vector<double> left_edges;
600 std::vector<double> right_edges;
601 void reset() { left_edges.clear(); right_edges.clear(); }
602 };
603 thread_local CreateFeaturePool create_feat_pool;
604 create_feat_pool.reset();
605 auto &left_edges = create_feat_pool.left_edges;
606 auto &right_edges = create_feat_pool.right_edges;
607 double min_left = best_left;
608 double max_right = best_right;
609 if (use_consensus_)
610 {
611 // Remove other, overlapping, picked peaks (in this and other
612 // chromatograms) and then ensure that at least one peak is set to zero
613 // (the currently best peak).
614 remove_overlapping_features(picked_chroms, best_left, best_right);
615 }
616 else
617 {
618 pickApex(picked_chroms, best_left, best_right, peak_apex,
619 min_left, max_right, left_edges, right_edges);
620
621 } // end !use_consensus_
622 picked_chroms[chr_idx][peak_idx].setIntensity(0.0); // ensure that we set at least one peak to zero
623
624 // Check for minimal peak width -> return empty feature (Intensity zero)
625 if (use_consensus_)
626 {
627 if (min_peak_width_ > 0.0 && std::fabs(best_right - best_left) < min_peak_width_)
628 {
629 return mrmFeature;
630 }
631
632 if (compute_peak_quality_)
633 {
634 std::string outlier = "none";
635 double qual = computeQuality_(transition_group, picked_chroms, picked_input_chromatograms,
636 chr_idx, best_left, best_right, outlier);
637 if (qual < min_qual_)
638 {
639 return mrmFeature;
640 }
641 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::potentialOutlier(), outlier);
642 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::initialPeakQuality(), qual);
643 mrmFeature.setOverallQuality(qual);
644 }
645 }
646
647 // Prepare linear resampling of all the chromatograms, here creating the
648 // empty master_peak_container with the same RT (m/z) values as the
649 // reference chromatogram. We use the overall minimal left boundary and
650 // maximal right boundary to prepare the container.
651 SpectrumT master_peak_container;
652 const SpectrumT& ref_chromatogram = *picked_input_chromatograms[chr_idx];
653 prepareMasterContainer_(ref_chromatogram, master_peak_container, min_left, max_right);
654
655 // Iterate over initial transitions / chromatograms (note that we may
656 // have a different number of picked chromatograms than total transitions
657 // as not all are detecting transitions).
658 double total_intensity = 0; double total_peak_apices = 0; double total_xic = 0; double total_mi = 0;
659 pickFragmentChromatograms(transition_group, picked_chroms, mrmFeature, smoothed_chroms,
660 best_left, best_right, use_consensus_,
661 total_intensity, total_xic, total_mi, total_peak_apices,
662 master_peak_container, left_edges, right_edges,
663 transition_total_xics, detecting_total_xic,
664 transition_chromatograms,
665 chr_idx, peak_idx);
666
667 // Also pick the precursor chromatogram(s); note total_xic is not
668 // extracted here, only for fragment traces
669 pickPrecursorChromatograms(transition_group,
670 picked_chroms, mrmFeature, smoothed_chroms,
671 best_left, best_right, use_consensus_,
672 total_intensity, master_peak_container, left_edges, right_edges,
673 chr_idx, peak_idx);
674
675 mrmFeature.setRT(peak_apex);
676 mrmFeature.setIntensity(total_intensity);
677 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::peptideRef(), transition_group.getTransitionGroupID());
678 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::leftWidth(), best_left);
679 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::rightWidth(), best_right);
680 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::totalXIC(), total_xic);
681 if (compute_total_mi_)
682 {
683 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::totalMI(), total_mi);
684 }
685 mrmFeature.setMetaValue(MRMTransitionGroupPickerMeta::peakApicesSum(), total_peak_apices);
686
687 mrmFeature.ensureUniqueId();
688 return mrmFeature;
689 }
690
703 template <typename SpectrumT>
704 void pickApex(std::vector<SpectrumT>& picked_chroms,
705 const double best_left, const double best_right, const double peak_apex,
706 double &min_left, double &max_right,
707 std::vector< double > & left_edges, std::vector< double > & right_edges)
708 {
709 for (Size k = 0; k < picked_chroms.size(); k++)
710 {
711 double peak_apex_dist_min = std::numeric_limits<double>::max();
712 int min_dist = -1;
713 for (Size i = 0; i < picked_chroms[k].size(); i++)
714 {
715 PeakIntegrator::PeakArea pa_tmp = pi_.integratePeak( // get the peak apex
716 picked_chroms[k],
717 picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][i],
718 picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][i]);
719 if (pa_tmp.apex_pos > 1e-11 && std::fabs(pa_tmp.apex_pos - peak_apex) < peak_apex_dist_min)
720 { // update best candidate
721 peak_apex_dist_min = std::fabs(pa_tmp.apex_pos - peak_apex);
722 min_dist = (int)i;
723 }
724 }
725
726 // Select master peak boundaries, or in the case we found at least one peak, the local peak boundaries
727 double l = best_left;
728 double r = best_right;
729 if (min_dist >= 0)
730 {
731 l = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][min_dist];
732 r = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][min_dist];
733 picked_chroms[k][min_dist].setIntensity(0.0); // only remove one peak per transition
734 }
735
736 left_edges.push_back(l);
737 right_edges.push_back(r);
738 // ensure we remember the overall maxima / minima
739 if (l < min_left) {min_left = l;}
740 if (r > max_right) {max_right = r;}
741 }
742 }
743
744 template <typename SpectrumT, typename TransitionT>
746 const std::vector<SpectrumT>& picked_chroms,
747 MRMFeature& mrmFeature,
748 const std::vector<SpectrumT>& smoothed_chroms,
749 const double best_left, const double best_right,
750 const bool use_consensus_,
751 double & total_intensity,
752 double & total_xic,
753 double & total_mi,
754 double & total_peak_apices,
755 const SpectrumT & master_peak_container,
756 const std::vector< double > & left_edges,
757 const std::vector< double > & right_edges,
758 const std::vector<double>& transition_total_xics,
759 double detecting_total_xic,
760 const std::vector<const SpectrumT*>& transition_chromatograms,
761 const int chr_idx,
762 const int peak_idx)
763 {
764 total_xic += detecting_total_xic;
765 for (Size k = 0; k < transition_group.getTransitions().size(); k++)
766 {
767
768 double local_left = best_left;
769 double local_right = best_right;
770 if (!use_consensus_)
771 {
772 // We cannot have any non-detecting transitions (otherwise we have
773 // too few left / right edges) as we skipped those when doing peak
774 // picking and smoothing.
775 if (!transition_group.getTransitions()[k].isDetectingTransition())
776 {
777 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
778 "When using non-consensus peak picker, all transitions need to be detecting transitions.");
779 }
780 local_left = left_edges[k];
781 local_right = right_edges[k];
782 }
783
784 const SpectrumT& chromatogram = *transition_chromatograms[k];
785
786 // Compute total intensity on transition-level
787 const double transition_total_xic = transition_total_xics[k];
788
789 // Compute total mutual information on transition-level.
790 double transition_total_mi = 0;
791 if (compute_total_mi_)
792 {
793 // reuse thread-local temporaries to avoid repeated allocations
794 thread_local std::vector<unsigned int> chrom_vect_id_ranked;
795 thread_local std::vector<unsigned int> chrom_vect_det_ranked;
796 thread_local std::vector<double> chrom_vect_id;
797 thread_local std::vector<double> chrom_vect_det;
798 chrom_vect_id.clear(); chrom_vect_det.clear(); chrom_vect_id_ranked.clear(); chrom_vect_det_ranked.clear();
799 for (typename SpectrumT::const_iterator it = chromatogram.begin(); it != chromatogram.end(); it++)
800 {
801 chrom_vect_id.push_back(it->getIntensity());
802 }
803 unsigned int max_rank_det = OpenSwath::Scoring::computeAndAppendRank(chrom_vect_id, chrom_vect_det_ranked);
804 // compute baseline mutual information
805 int transition_total_mi_norm = 0;
806 for (Size m = 0; m < transition_group.getTransitions().size(); m++)
807 {
808 if (transition_group.getTransitions()[m].isDetectingTransition())
809 {
810 const SpectrumT& chromatogram_det = *transition_chromatograms[m];
811 chrom_vect_det.clear();
812 for (typename SpectrumT::const_iterator it = chromatogram_det.begin(); it != chromatogram_det.end(); it++)
813 {
814 chrom_vect_det.push_back(it->getIntensity());
815 }
816 unsigned int max_rank_id = OpenSwath::Scoring::computeAndAppendRank(chrom_vect_det, chrom_vect_id_ranked);
817 transition_total_mi += OpenSwath::Scoring::rankedMutualInformation(chrom_vect_id_ranked, chrom_vect_det_ranked, max_rank_id, max_rank_det);
818 transition_total_mi_norm++;
819 }
820 }
821 if (transition_total_mi_norm > 0) { transition_total_mi /= transition_total_mi_norm; }
822
823 if (transition_group.getTransitions()[k].isDetectingTransition())
824 {
825 // sum up all transition-level total MI and divide by the number of detection transitions to have peak group level total MI
826 total_mi += transition_total_mi / transition_total_mi_norm;
827 }
828 }
829
830 SpectrumT used_chromatogram;
831 // resample the current chromatogram
832 if (peak_integration_ == "original")
833 {
834 used_chromatogram = resampleChromatogram_(chromatogram, master_peak_container, local_left, local_right);
835 }
836 else if (peak_integration_ == "smoothed")
837 {
838 if (smoothed_chroms.size() <= k)
839 {
840 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
841 "Tried to calculate peak area and height without any smoothed chromatograms");
842 }
843 used_chromatogram = resampleChromatogram_(smoothed_chroms[k], master_peak_container, local_left, local_right);
844 }
845 else
846 {
847 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
848 std::string("Peak integration chromatogram ") + peak_integration_ + " is not a valid method for MRMTransitionGroupPicker");
849 }
850
851 Feature f;
852 double quality = 0;
853 f.setQuality(0, quality);
854 f.setOverallQuality(quality);
855
856 PeakIntegrator::PeakArea pa = pi_.integratePeak(used_chromatogram, local_left, local_right);
857 double peak_integral = pa.area;
858 double peak_apex_int = pa.height;
859 f.setMetaValue(MRMTransitionGroupPickerMeta::peakApexPosition(), pa.apex_pos);
860
861 // In non-consensus mode, override hull_points with the full resampled
862 // chromatogram so all transitions produce equal-sized intensity vectors
863 // for cross-correlation scoring. Area/height/apex are already correct
864 // from the per-transition integration above.
865 if (!use_consensus_)
866 {
867 pa.hull_points.clear();
868 for (const auto& p : used_chromatogram)
869 {
870 pa.hull_points.push_back(DPosition<2>(p.getPos(), p.getIntensity()));
871 }
872 }
873
874 if (background_subtraction_ != "none")
875 {
876 double background{0};
877 double avg_noise_level{0};
878 if (background_subtraction_ == "original")
879 {
880 const double intensity_left = chromatogram.PosBegin(local_left)->getIntensity();
881 const double intensity_right = (chromatogram.PosEnd(local_right) - 1)->getIntensity();
882 const UInt n_points = std::distance(chromatogram.PosBegin(local_left), chromatogram.PosEnd(local_right));
883 avg_noise_level = (intensity_right + intensity_left) / 2;
884 background = avg_noise_level * n_points;
885 }
886 else if (background_subtraction_ == "exact")
887 {
888 PeakIntegrator::PeakBackground pb = pi_.estimateBackground(used_chromatogram, local_left, local_right, pa.apex_pos);
889 background = pb.area;
890 avg_noise_level = pb.height;
891 }
892 peak_integral -= background;
893 peak_apex_int -= avg_noise_level;
894 if (peak_integral < 0) {peak_integral = 0;}
895 if (peak_apex_int < 0) {peak_apex_int = 0;}
896
897 f.setMetaValue(MRMTransitionGroupPickerMeta::areaBackgroundLevel(), background);
898 f.setMetaValue(MRMTransitionGroupPickerMeta::noiseBackgroundLevel(), avg_noise_level);
899 } // end background
900
901 f.setRT(picked_chroms[chr_idx][peak_idx].getPos());
902 f.setIntensity(peak_integral);
903 ConvexHull2D hull;
904 hull.setHullPoints(pa.hull_points);
905 f.getConvexHulls().push_back(hull);
906
907 f.setMZ(chromatogram.getProduct().getMZ());
908 mrmFeature.setMZ(chromatogram.getPrecursor().getMZ());
909
910 if (chromatogram.metaValueExists("product_mz")) // legacy code (ensures that old tests still work)
911 {
912 f.setMetaValue("MZ", chromatogram.getMetaValue("product_mz"));
913 f.setMZ(chromatogram.getMetaValue("product_mz"));
914 }
915
916 f.setMetaValue(MRMTransitionGroupPickerMeta::nativeID(), chromatogram.getNativeID());
917 f.setMetaValue(MRMTransitionGroupPickerMeta::peakApexInt(), peak_apex_int);
918 f.setMetaValue(MRMTransitionGroupPickerMeta::totalXIC(), transition_total_xic);
919 if (compute_total_mi_)
920 {
921 f.setMetaValue(MRMTransitionGroupPickerMeta::totalMI(), transition_total_mi);
922 }
923
924 if (transition_group.getTransitions()[k].isQuantifyingTransition())
925 {
926 total_intensity += peak_integral;
927 total_peak_apices += peak_apex_int;
928 }
929
930 // for backwards compatibility with TOPP tests
931 // Calculate peak shape metrics that will be used for later QC
932 PeakIntegrator::PeakShapeMetrics psm = pi_.calculatePeakShapeMetrics(used_chromatogram, local_left, local_right, peak_apex_int, pa.apex_pos);
933 f.setMetaValue(MRMTransitionGroupPickerMeta::widthAt50(), psm.width_at_50);
934 if (compute_peak_shape_metrics_)
935 {
936 f.setMetaValue(MRMTransitionGroupPickerMeta::widthAt5(), psm.width_at_5);
937 f.setMetaValue(MRMTransitionGroupPickerMeta::widthAt10(), psm.width_at_10);
938 f.setMetaValue(MRMTransitionGroupPickerMeta::startPositionAt5(), psm.start_position_at_5);
939 f.setMetaValue(MRMTransitionGroupPickerMeta::startPositionAt10(), psm.start_position_at_10);
940 f.setMetaValue(MRMTransitionGroupPickerMeta::startPositionAt50(), psm.start_position_at_50);
941 f.setMetaValue(MRMTransitionGroupPickerMeta::endPositionAt5(), psm.end_position_at_5);
942 f.setMetaValue(MRMTransitionGroupPickerMeta::endPositionAt10(), psm.end_position_at_10);
943 f.setMetaValue(MRMTransitionGroupPickerMeta::endPositionAt50(), psm.end_position_at_50);
944 f.setMetaValue(MRMTransitionGroupPickerMeta::totalWidth(), psm.total_width);
945 f.setMetaValue(MRMTransitionGroupPickerMeta::tailingFactor(), psm.tailing_factor);
946 f.setMetaValue(MRMTransitionGroupPickerMeta::asymmetryFactor(), psm.asymmetry_factor);
947 f.setMetaValue(MRMTransitionGroupPickerMeta::slopeOfBaseline(), psm.slope_of_baseline);
948 f.setMetaValue(MRMTransitionGroupPickerMeta::baselineDelta2Height(), psm.baseline_delta_2_height);
949 f.setMetaValue(MRMTransitionGroupPickerMeta::pointsAcrossBaseline(), psm.points_across_baseline);
950 f.setMetaValue(MRMTransitionGroupPickerMeta::pointsAcrossHalfHeight(), psm.points_across_half_height);
951 }
952
953 mrmFeature.addFeature(std::move(f), chromatogram.getNativeID()); //map index and feature
954 }
955 }
956
957 template <typename SpectrumT, typename TransitionT>
959 const std::vector<SpectrumT>& picked_chroms,
960 MRMFeature& mrmFeature,
961 const std::vector<SpectrumT>& smoothed_chroms,
962 const double best_left, const double best_right,
963 const bool use_consensus_,
964 double & total_intensity,
965 const SpectrumT & master_peak_container,
966 const std::vector< double > & left_edges,
967 const std::vector< double > & right_edges,
968 const int chr_idx,
969 const int peak_idx)
970 {
971 for (Size k = 0; k < transition_group.getPrecursorChromatograms().size(); k++)
972 {
973 const SpectrumT& chromatogram = transition_group.getPrecursorChromatograms()[k];
974
975 // Identify precursor index
976 // note: this is only valid if all transitions are detecting transitions
977 Size prec_idx = transition_group.getChromatograms().size() + k;
978
979 double local_left = best_left;
980 double local_right = best_right;
981 if (!use_consensus_ && right_edges.size() > prec_idx && left_edges.size() > prec_idx)
982 {
983 local_left = left_edges[prec_idx];
984 local_right = right_edges[prec_idx];
985 }
986
987 SpectrumT used_chromatogram;
988 // resample the current chromatogram
989 if (peak_integration_ == "original")
990 {
991 used_chromatogram = resampleChromatogram_(chromatogram, master_peak_container, local_left, local_right);
992 // const SpectrumT& used_chromatogram = chromatogram; // instead of resampling
993 }
994 else if (peak_integration_ == "smoothed" && smoothed_chroms.size() <= prec_idx)
995 {
996 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
997 "Tried to calculate peak area and height without any smoothed chromatograms for precursors");
998 }
999 else if (peak_integration_ == "smoothed")
1000 {
1001 used_chromatogram = resampleChromatogram_(smoothed_chroms[prec_idx], master_peak_container, local_left, local_right);
1002 }
1003 else
1004 {
1005 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
1006 std::string("Peak integration chromatogram ") + peak_integration_ + " is not a valid method for MRMTransitionGroupPicker");
1007 }
1008
1009 Feature f;
1010 double quality = 0;
1011 f.setQuality(0, quality);
1012 f.setOverallQuality(quality);
1013
1014 PeakIntegrator::PeakArea pa = pi_.integratePeak(used_chromatogram, local_left, local_right);
1015 double peak_integral = pa.area;
1016 double peak_apex_int = pa.height;
1017
1018 // In non-consensus mode, override hull_points with the full resampled
1019 // chromatogram so all precursors produce equal-sized intensity vectors
1020 // for cross-correlation scoring (see pickFragmentChromatograms).
1021 if (!use_consensus_)
1022 {
1023 pa.hull_points.clear();
1024 for (const auto& p : used_chromatogram)
1025 {
1026 pa.hull_points.push_back(DPosition<2>(p.getPos(), p.getIntensity()));
1027 }
1028 }
1029
1030 if (background_subtraction_ != "none")
1031 {
1032 double background{0};
1033 double avg_noise_level{0};
1034 if ((peak_integration_ == "smoothed") && smoothed_chroms.size() <= prec_idx)
1035 {
1036 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
1037 "Tried to calculate background estimation without any smoothed chromatograms");
1038 }
1039 else if (background_subtraction_ == "original")
1040 {
1041 const double intensity_left = chromatogram.PosBegin(local_left)->getIntensity();
1042 const double intensity_right = (chromatogram.PosEnd(local_right) - 1)->getIntensity();
1043 const UInt n_points = std::distance(chromatogram.PosBegin(local_left), chromatogram.PosEnd(local_right));
1044 avg_noise_level = (intensity_right + intensity_left) / 2;
1045 background = avg_noise_level * n_points;
1046 }
1047 else if (background_subtraction_ == "exact")
1048 {
1049 PeakIntegrator::PeakBackground pb = pi_.estimateBackground(used_chromatogram, local_left, local_right, pa.apex_pos);
1050 background = pb.area;
1051 avg_noise_level = pb.height;
1052 }
1053 peak_integral -= background;
1054 peak_apex_int -= avg_noise_level;
1055 if (peak_integral < 0) {peak_integral = 0;}
1056 if (peak_apex_int < 0) {peak_apex_int = 0;}
1057
1058 f.setMetaValue(MRMTransitionGroupPickerMeta::areaBackgroundLevel(), background);
1059 f.setMetaValue(MRMTransitionGroupPickerMeta::noiseBackgroundLevel(), avg_noise_level);
1060 }
1061
1062 f.setMZ(chromatogram.getPrecursor().getMZ());
1063 if (k == 0) {mrmFeature.setMZ(chromatogram.getPrecursor().getMZ());} // only use m/z if first (monoisotopic) isotope
1064
1065 if (chromatogram.metaValueExists("precursor_mz")) // legacy code (ensures that old tests still work)
1066 {
1067 f.setMZ(chromatogram.getMetaValue("precursor_mz"));
1068 if (k == 0) {mrmFeature.setMZ(chromatogram.getMetaValue("precursor_mz"));} // only use m/z if first (monoisotopic) isotope
1069 }
1070
1071 f.setRT(picked_chroms[chr_idx][peak_idx].getPos());
1072 f.setIntensity(peak_integral);
1073 ConvexHull2D hull;
1074 hull.setHullPoints(pa.hull_points);
1075 f.getConvexHulls().push_back(hull);
1076 f.setMetaValue(MRMTransitionGroupPickerMeta::nativeID(), chromatogram.getNativeID());
1077 f.setMetaValue(MRMTransitionGroupPickerMeta::peakApexInt(), peak_apex_int);
1078
1079 if (use_precursors_ && transition_group.getTransitions().empty())
1080 {
1081 total_intensity += peak_integral;
1082 }
1083
1084 mrmFeature.addPrecursorFeature(std::move(f), chromatogram.getNativeID());
1085 }
1086 }
1087
1088 // maybe private, but we have tests
1089
1101 template <typename SpectrumT>
1102 void remove_overlapping_features(std::vector<SpectrumT>& picked_chroms, double best_left, double best_right)
1103 {
1104 // delete all seeds that lie within the current seed
1105 Size count_inside = 0;
1106 for (Size k = 0; k < picked_chroms.size(); k++)
1107 {
1108 for (Size i = 0; i < picked_chroms[k].size(); i++)
1109 {
1110 if (picked_chroms[k][i].getPos() >= best_left && picked_chroms[k][i].getPos() <= best_right)
1111 {
1112 picked_chroms[k][i].setIntensity(0.0);
1113 count_inside++;
1114 }
1115 }
1116 }
1117
1118 Size count_overlap = 0;
1119 // delete all seeds that overlap within the current seed
1120 for (Size k = 0; k < picked_chroms.size(); k++)
1121 {
1122 for (Size i = 0; i < picked_chroms[k].size(); i++)
1123 {
1124 if (picked_chroms[k][i].getIntensity() <= 1e-11) {continue; }
1125
1126 double left = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][i];
1127 double right = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][i];
1128 if ((left > best_left && left < best_right)
1129 || (right > best_left && right < best_right))
1130 {
1131 picked_chroms[k][i].setIntensity(0.0);
1132 count_overlap++;
1133 }
1134 }
1135 }
1136 OPENMS_LOG_DEBUG << " ** Removed " << count_inside << " peaks enclosed in and " <<
1137 count_overlap << " peaks overlapping with added feature." << std::endl;
1138 }
1139
1141 void findLargestPeak(const std::vector<MSChromatogram >& picked_chroms, int& chr_idx, int& peak_idx);
1142
1143 template <typename SpectrumT>
1144 void findLargestPeakCached_(const std::vector<SpectrumT>& picked_chroms,
1145 std::vector<int>& largest_peak_indices,
1146 int& chr_idx,
1147 int& peak_idx) const
1148 {
1149 OPENMS_PRECONDITION(largest_peak_indices.size() == picked_chroms.size(),
1150 "Cached largest peak indices must match picked chromatogram count.");
1151 double largest = 0.0;
1152 for (Size k = 0; k < picked_chroms.size(); k++)
1153 {
1154 int candidate_idx = largest_peak_indices[k];
1155 while (candidate_idx >= 0 && picked_chroms[k][candidate_idx].getIntensity() <= 0.0)
1156 {
1157 --candidate_idx;
1158 }
1159 largest_peak_indices[k] = candidate_idx;
1160 if (candidate_idx < 0)
1161 {
1162 continue;
1163 }
1164 const double intensity = picked_chroms[k][candidate_idx].getIntensity();
1165 if (intensity > largest)
1166 {
1167 largest = intensity;
1168 chr_idx = static_cast<int>(k);
1169 peak_idx = candidate_idx;
1170 }
1171 }
1172 }
1173
1182 void findWidestPeakIndices(const std::vector<MSChromatogram>& picked_chroms, Int& chrom_idx, Int& point_idx) const;
1183
1184protected:
1185
1187 void updateMembers_() override;
1188
1191
1195 template <typename SpectrumT, typename TransitionT>
1196 const SpectrumT& selectChromHelper_(const MRMTransitionGroup<SpectrumT, TransitionT>& transition_group, const std::string& native_id)
1197 {
1198 if (transition_group.hasChromatogram(native_id))
1199 {
1200 return transition_group.getChromatogram(native_id);
1201 }
1202 else if (transition_group.hasPrecursorChromatogram(native_id))
1203 {
1204 return transition_group.getPrecursorChromatogram(native_id);
1205 }
1206 else
1207 {
1208 throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Did not find chromatogram for id '" + native_id + "'.");
1209 }
1210 }
1211
1228 template <typename SpectrumT, typename TransitionT>
1230 const std::vector<SpectrumT>& picked_chroms,
1231 const std::vector<const SpectrumT*>& picked_input_chromatograms,
1232 const int chr_idx,
1233 const double best_left,
1234 const double best_right,
1235 std::string& outlier)
1236 {
1237 // Resample all chromatograms around the current estimated peak and
1238 // collect the raw intensities. For resampling, use a bit more on either
1239 // side to correctly identify shoulders etc.
1240 double resample_boundary = resample_boundary_; // sample 15 seconds more on each side
1241 SpectrumT master_peak_container;
1242 const SpectrumT& ref_chromatogram = *picked_input_chromatograms[chr_idx];
1243 prepareMasterContainer_(ref_chromatogram, master_peak_container, best_left - resample_boundary, best_right + resample_boundary);
1244 // Reuse the shared per-thread pool's containers for quality computation
1245 auto &pool = g_picker_pool_shared();
1246 auto &all_ints = pool.all_ints;
1247 all_ints.clear();
1248 for (Size k = 0; k < picked_chroms.size(); k++)
1249 {
1250 const SpectrumT& chromatogram = *picked_input_chromatograms[k];
1251 const SpectrumT used_chromatogram = resampleChromatogram_(chromatogram,
1252 master_peak_container, best_left - resample_boundary, best_right + resample_boundary);
1253
1254 std::vector<double> int_here;
1255 for (const auto& peak : used_chromatogram) int_here.push_back(peak.getIntensity());
1256 // Remove chromatograms without a single peak
1257 double tic = std::accumulate(int_here.begin(), int_here.end(), 0.0);
1258 if (tic > 1e-11) all_ints.push_back(int_here);
1259 }
1260
1261 // Compute the cross-correlation for the collected intensities
1262 auto &mean_shapes = pool.mean_shapes;
1263 auto &mean_coel = pool.mean_coel;
1264 mean_shapes.clear();
1265 mean_coel.clear();
1266 for (Size k = 0; k < all_ints.size(); k++)
1267 {
1268 std::vector<double> shapes;
1269 std::vector<double> coel;
1270 for (Size i = 0; i < all_ints.size(); i++)
1271 {
1272 if (i == k) {continue;}
1274 = OpenSwath::Scoring::normalizedCrossCorrelation(all_ints[k], all_ints[i], OpenMS::checkedCast<int>(all_ints[i].size()), 1);
1275
1276 // the first value is the x-axis (retention time) and should be an int -> it show the lag between the two
1277 double res_coelution = std::abs(OpenSwath::Scoring::xcorrArrayGetMaxPeak(res)->first);
1278 double res_shape = std::abs(OpenSwath::Scoring::xcorrArrayGetMaxPeak(res)->second);
1279
1280 shapes.push_back(res_shape);
1281 coel.push_back(res_coelution);
1282 }
1283
1284 // We have computed the cross-correlation of chromatogram k against
1285 // all others. Use the mean of these computations as the value for k.
1287 msc = std::for_each(shapes.begin(), shapes.end(), msc);
1288 double shapes_mean = msc.mean();
1289 msc = std::for_each(coel.begin(), coel.end(), msc);
1290 double coel_mean = msc.mean();
1291
1292 // mean shape scores below 0.5-0.6 should be a real sign of trouble ... !
1293 // mean coel scores above 3.5 should be a real sign of trouble ... !
1294 mean_shapes.push_back(shapes_mean);
1295 mean_coel.push_back(coel_mean);
1296 }
1297
1298 // find the chromatogram with the minimal shape score and the maximal
1299 // coelution score -> if it is the same chromatogram, the chance is
1300 // pretty good that it is different from the others...
1301 int min_index_shape = std::distance(mean_shapes.begin(), std::min_element(mean_shapes.begin(), mean_shapes.end()));
1302 int max_index_coel = std::distance(mean_coel.begin(), std::max_element(mean_coel.begin(), mean_coel.end()));
1303
1304 // Look at the picked peaks that are within the current left/right borders
1305 int missing_peaks = 0;
1306 int multiple_peaks = 0;
1307
1308 // collect all seeds that lie within the current seed
1309 auto &left_borders = pool.left_borders;
1310 auto &right_borders = pool.right_borders;
1311 left_borders.clear();
1312 right_borders.clear();
1313 for (Size k = 0; k < picked_chroms.size(); k++)
1314 {
1315 double l_tmp;
1316 double r_tmp;
1317 double max_int = -1;
1318
1319 int pfound = 0;
1320 l_tmp = -1;
1321 r_tmp = -1;
1322 for (Size i = 0; i < picked_chroms[k].size(); i++)
1323 {
1324 if (picked_chroms[k][i].getPos() >= best_left && picked_chroms[k][i].getPos() <= best_right)
1325 {
1326 pfound++;
1327 if (picked_chroms[k][i].getIntensity() > max_int)
1328 {
1329 max_int = picked_chroms[k][i].getIntensity() > max_int;
1330 l_tmp = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][i];
1331 r_tmp = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][i];
1332 }
1333 }
1334 }
1335
1336 if (l_tmp > 1e-11) left_borders.push_back(l_tmp);
1337 if (r_tmp > 1e-11) right_borders.push_back(r_tmp);
1338
1339 if (pfound == 0) missing_peaks++;
1340 if (pfound > 1) multiple_peaks++;
1341 }
1342
1343 // Check how many chromatograms had exactly one peak picked between our
1344 // current left/right borders -> this would be a sign of consistency.
1345 OPENMS_LOG_DEBUG << " Overall found missing : " << missing_peaks << " and multiple : " << multiple_peaks << std::endl;
1346
1348
1349 // Is there one transitions that is very different from the rest (e.g.
1350 // the same element has a bad shape and a bad coelution score) -> potential outlier
1351 if (min_index_shape == max_index_coel)
1352 {
1353 OPENMS_LOG_DEBUG << " Element " << min_index_shape << " is a candidate for removal ... " << std::endl;
1354 outlier =std::string(picked_chroms[min_index_shape].getNativeID());
1355 }
1356 else
1357 {
1358 outlier = "none";
1359 }
1360
1361 // For the final score (larger is better), consider these scores:
1362 // - missing_peaks (the more peaks are missing, the worse)
1363 // - multiple_peaks
1364 // - mean of the shapes (1 is very good, 0 is bad)
1365 // - mean of the co-elution scores (0 is good, 1 is ok, above 1 is pretty bad)
1366 double shape_score = std::accumulate(mean_shapes.begin(), mean_shapes.end(), 0.0) / mean_shapes.size();
1367 double coel_score = std::accumulate(mean_coel.begin(), mean_coel.end(), 0.0) / mean_coel.size();
1368 coel_score = (coel_score - 1.0) / 2.0;
1369
1370 double score = shape_score - coel_score - 1.0 * missing_peaks / picked_chroms.size();
1371
1372 OPENMS_LOG_DEBUG << " Computed score " << score << " (from " << shape_score <<
1373 " - " << coel_score << " - " << 1.0 * missing_peaks / picked_chroms.size() << ")" << std::endl;
1374
1375 return score;
1376 }
1377
1387 template <typename SpectrumT>
1388 void recalculatePeakBorders_(const std::vector<SpectrumT>& picked_chroms, double& best_left, double& best_right, double max_z)
1389 {
1390 // 1. Collect all seeds that lie within the current seed
1391 // - Per chromatogram only the most intense one counts, otherwise very
1392 // - low intense peaks can contribute disproportionally to the voting
1393 // - procedure.
1394 // TODO Especially with DDA MS1 "transitions" from FFID, you often have exactly the same
1395 // borders and the logs get confusing and you get -Nan CVs. You also might save time if you use a set here.
1396 std::vector<double> left_borders;
1397 std::vector<double> right_borders;
1398 for (Size k = 0; k < picked_chroms.size(); k++)
1399 {
1400 double max_int = -1;
1401 double left = -1;
1402 double right = -1;
1403 for (Size i = 0; i < picked_chroms[k].size(); i++)
1404 {
1405 if (picked_chroms[k][i].getPos() >= best_left && picked_chroms[k][i].getPos() <= best_right)
1406 {
1407 if (picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_ABUNDANCE][i] > max_int)
1408 {
1409 max_int = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_ABUNDANCE][i];
1410 left = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_LEFTBORDER][i];
1411 right = picked_chroms[k].getFloatDataArrays()[PeakPickerChromatogram::IDX_RIGHTBORDER][i];
1412 }
1413 }
1414 }
1415 if (max_int > -1 )
1416 {
1417 left_borders.push_back(left);
1418 right_borders.push_back(right);
1419 OPENMS_LOG_DEBUG << " * peak " << k << " left boundary " << left_borders.back() << " with inty " << max_int << std::endl;
1420 OPENMS_LOG_DEBUG << " * peak " << k << " right boundary " << right_borders.back() << " with inty " << max_int << std::endl;
1421 }
1422 }
1423
1424 // Return for empty peak list
1425 if (right_borders.empty())
1426 {
1427 return;
1428 }
1429
1430 // FEATURE IDEA: instead of Z-score use modified Z-score for small data sets
1431 // http://d-scholarship.pitt.edu/7948/1/Seo.pdf
1432 // http://www.itl.nist.gov/div898/handbook/eda/section3/eda35h.htm
1433 // 1. calculate median
1434 // 2. MAD = calculate difference to median for each value -> take median of that
1435 // 3. Mi = 0.6745*(xi - median) / MAD
1436
1437 // 2. Calculate mean and standard deviation
1438 // If the coefficient of variation is too large for one border, we use a
1439 // "pseudo-median" instead of the border of the most intense peak.
1440 double mean, stdev;
1441
1442 // Right borders
1443 mean = std::accumulate(right_borders.begin(), right_borders.end(), 0.0) / (double) right_borders.size();
1444 stdev = std::sqrt(std::inner_product(right_borders.begin(), right_borders.end(), right_borders.begin(), 0.0)
1445 / right_borders.size() - mean * mean);
1446 std::sort(right_borders.begin(), right_borders.end());
1447
1448 OPENMS_LOG_DEBUG << " - Recalculating right peak boundaries " << mean << " mean / best "
1449 << best_right << " std " << stdev << " : " << std::fabs(best_right - mean) / stdev
1450 << " coefficient of variation" << std::endl;
1451
1452 // Compare right borders of best transition with the mean
1453 if (std::fabs(best_right - mean) / stdev > max_z)
1454 {
1455 best_right = right_borders[right_borders.size() / 2]; // pseudo median
1456 OPENMS_LOG_DEBUG << " - CV too large: correcting right boundary to " << best_right << std::endl;
1457 }
1458
1459 // Left borders
1460 mean = std::accumulate(left_borders.begin(), left_borders.end(), 0.0) / (double) left_borders.size();
1461 stdev = std::sqrt(std::inner_product(left_borders.begin(), left_borders.end(), left_borders.begin(), 0.0)
1462 / left_borders.size() - mean * mean);
1463 std::sort(left_borders.begin(), left_borders.end());
1464
1465 OPENMS_LOG_DEBUG << " - Recalculating left peak boundaries " << mean << " mean / best "
1466 << best_left << " std " << stdev << " : " << std::fabs(best_left - mean) / stdev
1467 << " coefficient of variation" << std::endl;
1468
1469 // Compare left borders of best transition with the mean
1470 if (std::fabs(best_left - mean) / stdev > max_z)
1471 {
1472 best_left = left_borders[left_borders.size() / 2]; // pseudo median
1473 OPENMS_LOG_DEBUG << " - CV too large: correcting left boundary to " << best_left << std::endl;
1474 }
1475
1476 }
1477
1479
1480
1495 template <typename PeakContainerT>
1496 void prepareMasterContainer_(const PeakContainerT& ref_chromatogram,
1497 PeakContainerT& master_peak_container,
1498 double left_boundary,
1499 double right_boundary)
1500 {
1501 OPENMS_PRECONDITION(master_peak_container.empty(), "Master peak container must be empty")
1502
1503 // get the start / end point of this chromatogram => then add one more
1504 // point beyond the two boundaries to make the resampling accurate also
1505 // at the edge.
1506 auto begin = ref_chromatogram.begin();
1507 while (begin != ref_chromatogram.end() && begin->getPos() < left_boundary) {begin++; }
1508 if (begin != ref_chromatogram.begin()) { begin--; }
1509
1510 auto end = begin;
1511 while (end != ref_chromatogram.end() && end->getPos() < right_boundary) {end++; }
1512 if (end != ref_chromatogram.end()) { end++; }
1513
1514 // resize the master container and set the m/z values to the ones of the master container
1515 master_peak_container.resize(distance(begin, end)); // initialize to zero
1516 auto it = master_peak_container.begin();
1517 for (auto chrom_it = begin; chrom_it != end; chrom_it++, it++)
1518 {
1519 it->setPos(chrom_it->getPos());
1520 }
1521 }
1522
1533 template <typename PeakContainerT>
1534 PeakContainerT resampleChromatogram_(const PeakContainerT& chromatogram,
1535 const PeakContainerT& master_peak_container,
1536 double left_boundary,
1537 double right_boundary)
1538 {
1539 // get the start / end point of this chromatogram => then add one more
1540 // point beyond the two boundaries to make the resampling accurate also
1541 // at the edge.
1542 auto begin = chromatogram.begin();
1543 while (begin != chromatogram.end() && begin->getPos() < left_boundary) {begin++;}
1544 if (begin != chromatogram.begin()) { begin--; }
1545
1546 auto end = begin;
1547 while (end != chromatogram.end() && end->getPos() < right_boundary) {end++;}
1548 if (end != chromatogram.end()) { end++; }
1549
1550 auto resampled_peak_container = master_peak_container; // copy the master container, which contains the RT values
1551 // raster() only uses the default parameters: construct the resampler (and its Param) once per thread
1552 static thread_local LinearResamplerAlign lresampler;
1553 lresampler.raster(begin, end, resampled_peak_container.begin(), resampled_peak_container.end());
1554
1555 return resampled_peak_container;
1556 }
1557
1559
1560 // Members
1570
1576
1583
1586 };
1587}
#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:1496
void findLargestPeakCached_(const std::vector< SpectrumT > &picked_chroms, std::vector< int > &largest_peak_indices, int &chr_idx, int &peak_idx) const
Definition MRMTransitionGroupPicker.h:1144
bool compute_total_mi_
Definition MRMTransitionGroupPicker.h:1568
std::string peak_integration_
Definition MRMTransitionGroupPicker.h:1561
bool compute_peak_quality_
Definition MRMTransitionGroupPicker.h:1566
bool use_precursors_
Definition MRMTransitionGroupPicker.h:1564
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:1534
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:704
std::string background_subtraction_
Definition MRMTransitionGroupPicker.h:1562
const SpectrumT & selectChromHelper_(const MRMTransitionGroup< SpectrumT, TransitionT > &transition_group, const std::string &native_id)
Select matching precursor or fragment ion chromatogram.
Definition MRMTransitionGroupPicker.h:1196
double min_peak_width_
Definition MRMTransitionGroupPicker.h:1573
void remove_overlapping_features(std::vector< SpectrumT > &picked_chroms, double best_left, double best_right)
Remove overlapping features.
Definition MRMTransitionGroupPicker.h:1102
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:1388
int stop_after_feature_
Definition MRMTransitionGroupPicker.h:1571
PeakPickerChromatogram picker_
Definition MRMTransitionGroupPicker.h:1584
double recalculate_peaks_max_z_
Definition MRMTransitionGroupPicker.h:1574
PeakIntegrator pi_
Definition MRMTransitionGroupPicker.h:1585
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:1569
double resample_boundary_
Definition MRMTransitionGroupPicker.h:1575
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:501
~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:745
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:562
void updateMembers_() override
Synchronize members with param class.
double stop_after_intensity_ratio_
Definition MRMTransitionGroupPicker.h:1572
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:1565
std::string boundary_selection_method_
Which method to use for selecting peaks' boundaries.
Definition MRMTransitionGroupPicker.h:1582
bool recalculate_peaks_
Definition MRMTransitionGroupPicker.h:1563
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:958
bool compute_peak_shape_metrics_
Definition MRMTransitionGroupPicker.h:1567
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:1229
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:253
const std::vector< TransitionType > & getTransitions() const
Definition MRMTransitionGroup.h:115
ChromatogramType & getPrecursorChromatogram(const std::string &key)
Definition MRMTransitionGroup.h:258
const TransitionType & getTransition(const std::string &key)
Definition MRMTransitionGroup.h:148
ChromatogramType & getChromatogram(const std::string &key)
Definition MRMTransitionGroup.h:204
bool isInternallyConsistent() const
Check whether internal state is consistent, e.g. same number of chromatograms and transitions are pre...
Definition MRMTransitionGroup.h:302
bool chromatogramIdsMatch() const
Ensure that chromatogram native ids match their keys in the map.
Definition MRMTransitionGroup.h:311
const std::string & getTransitionGroupID() const
Definition MRMTransitionGroup.h:103
void addFeature(const MRMFeature &feature)
Definition MRMTransitionGroup.h:286
std::vector< ChromatogramType > & getPrecursorChromatograms()
Definition MRMTransitionGroup.h:222
std::vector< ChromatogramType > & getChromatograms()
Definition MRMTransitionGroup.h:159
bool hasChromatogram(const std::string &key) const
Definition MRMTransitionGroup.h:199
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:179
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