1
// --------------------------------------------------------------------------
2
// OpenMS -- Open-Source Mass Spectrometry
3
// --------------------------------------------------------------------------
4
// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
5
// ETH Zurich, and Freie Universitaet Berlin 2002-2013.
7
// This software is released under a three-clause BSD license:
8
// * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
// * Redistributions in binary form must reproduce the above copyright
11
// notice, this list of conditions and the following disclaimer in the
12
// documentation and/or other materials provided with the distribution.
13
// * Neither the name of any author or any participating institution
14
// may be used to endorse or promote products derived from this software
15
// without specific prior written permission.
16
// For a full list of authors, refer to the file AUTHORS.
17
// --------------------------------------------------------------------------
18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
22
// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
// --------------------------------------------------------------------------
31
// $Maintainer: Hannes Roest $
32
// $Authors: Hannes Roest $
33
// --------------------------------------------------------------------------
35
#ifndef OPENMS_TRANSFORMATIONS_FEATUREFINDER_EMGSCORING_H
36
#define OPENMS_TRANSFORMATIONS_FEATUREFINDER_EMGSCORING_H
39
#include <boost/math/special_functions/fpclassify.hpp> // for isnan
40
#include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/EmgFitter1D.h>
41
#include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/EmgModel.h>
42
#include <OpenMS/FILTERING/SMOOTHING/GaussFilter.h>
44
#include <OpenMS/KERNEL/MRMFeature.h>
45
#include <OpenMS/KERNEL/MRMTransitionGroup.h>
47
#include <OpenMS/KERNEL/StandardTypes.h>
54
@brief Scoring of an elution peak using an exponentially modified gaussian distribution model.
56
This class uses the original ideas from FeatureFinderAlgorithmMRM to
57
construct an interface that allows scoring of chromatographic peaks.
69
void setFitterParam(Param param)
71
fitter_emg1D_.setParameters(param);
76
return fitter_emg1D_.getDefaults();
79
/// calculate the elution profile fit score
80
template<typename SpectrumType, class TransitionT>
81
double calcElutionFitScore(MRMFeature & mrmfeature, MRMTransitionGroup<SpectrumType, TransitionT> & transition_group)
84
std::vector<double> fit_scores;
86
bool smooth_data = false;
87
for (Size k = 0; k < transition_group.size(); k++)
89
// get the id, then find the corresponding transition and features within this peakgroup
90
String native_id = transition_group.getChromatograms()[k].getNativeID();
91
Feature f = mrmfeature.getFeature(native_id);
92
OPENMS_PRECONDITION(f.getConvexHulls().size() == 1, "Convex hulls need to have exactly one hull point structure");
94
// TODO what if score is -1 ?? e.g. if it is undefined
95
double fscore = elutionModelFit(f.getConvexHulls()[0].getHullPoints(), smooth_data);
96
fit_scores.push_back(fscore);
100
avg_score /= transition_group.size();
104
// Fxn from FeatureFinderAlgorithmMRM
105
// TODO: check whether we can leave out some of the steps here, e.g. gaussian smoothing
106
double elutionModelFit(ConvexHull2D::PointArrayType current_section, bool smooth_data)
108
// We need at least 2 datapoints in order to create a fit
109
if (current_section.size() < 2)
114
// local PeakType is a small hack since here we *need* data of type
115
// Peak1D, otherwise our fitter will not accept it.
116
typedef Peak1D LocalPeakType;
119
// -- cut line 301 of FeatureFinderAlgorithmMRM
120
std::vector<LocalPeakType> data_to_fit;
121
prepareFit_(current_section, data_to_fit, smooth_data);
122
InterpolationModel * model_rt = 0;
123
DoubleReal quality = fitRT_(data_to_fit, model_rt);
124
// cut line 354 of FeatureFinderAlgorithmMRM
132
template<class LocalPeakType>
133
double fitRT_(std::vector<LocalPeakType> & rt_input_data, InterpolationModel * & model)
139
param.setValue( "tolerance_stdev_bounding_box", tolerance_stdev_box_);
140
param.setValue( "statistics:mean", rt_stat_.mean() );
141
param.setValue( "statistics:variance", rt_stat_.variance() );
142
param.setValue( "interpolation_step", interpolation_step_rt_ );
143
param.setValue( "max_iteration", max_iteration_);
144
param.setValue( "deltaAbsError", deltaAbsError_);
145
param.setValue( "deltaRelError", deltaRelError_);
148
// Set parameter for fitter
149
//fitter_emg1D.setParameters(param);
150
// Construct model for rt
151
quality = fitter_emg1D_.fit1d(rt_input_data, model);
154
if (boost::math::isnan(quality)) quality = -1.0;
158
// Fxn from FeatureFinderAlgorithmMRM
159
// TODO: check whether we can leave out some of the steps here, e.g. gaussian smoothing
160
template<class LocalPeakType>
161
void prepareFit_(const ConvexHull2D::PointArrayType & current_section, std::vector<LocalPeakType> & data_to_fit, bool smooth_data)
163
// typedef Peak1D LocalPeakType;
164
PeakSpectrum filter_spec;
165
// first smooth the data to prevent outliers from destroying the fit
166
for (ConvexHull2D::PointArrayType::const_iterator it = current_section.begin(); it != current_section.end(); it++)
170
p.setIntensity(it->getY());
171
filter_spec.push_back(p);
174
// add two peaks at the beginning and at the end for better fit
175
// therefore calculate average distance first
176
std::vector<DoubleReal> distances;
177
for (Size j = 1; j < filter_spec.size(); ++j)
179
distances.push_back(filter_spec[j].getMZ() - filter_spec[j - 1].getMZ());
181
DoubleReal dist_average = std::accumulate(distances.begin(), distances.end(), 0.0) / (DoubleReal) distances.size();
185
new_peak.setIntensity(0);
186
new_peak.setMZ(filter_spec.back().getMZ() + dist_average);
187
filter_spec.push_back(new_peak);
188
new_peak.setMZ(filter_spec.back().getMZ() + dist_average);
189
filter_spec.push_back(new_peak);
190
new_peak.setMZ(filter_spec.back().getMZ() + dist_average);
191
filter_spec.push_back(new_peak);
194
new_peak.setMZ(filter_spec.front().getMZ() - dist_average);
195
filter_spec.insert(filter_spec.begin(), new_peak);
196
new_peak.setMZ(filter_spec.front().getMZ() - dist_average);
197
filter_spec.insert(filter_spec.begin(), new_peak);
198
new_peak.setMZ(filter_spec.front().getMZ() - dist_average);
199
filter_spec.insert(filter_spec.begin(), new_peak);
201
// To get an estimate of the peak quality, we probably should not smooth
202
// and/or transform the data.
206
Param filter_param(filter.getParameters());
207
filter.setParameters(filter_param);
208
filter_param.setValue("gaussian_width", 4 * dist_average);
209
filter.setParameters(filter_param);
210
filter.filter(filter_spec);
213
// transform the data for fitting and fit RT profile
214
for (Size j = 0; j != filter_spec.size(); ++j)
217
p.setPosition(filter_spec[j].getMZ());
218
p.setIntensity(filter_spec[j].getIntensity());
219
data_to_fit.push_back(p);
223
EmgFitter1D fitter_emg1D_;
227
#endif /* EMGSCORING_H_ */