Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef OPENMS_TRANSFORMATIONS_RAW2PEAK_PEAKPICKERHIRES_H
00035 #define OPENMS_TRANSFORMATIONS_RAW2PEAK_PEAKPICKERHIRES_H
00036
00037 #include <OpenMS/KERNEL/MSExperiment.h>
00038 #include <OpenMS/DATASTRUCTURES/DefaultParamHandler.h>
00039 #include <OpenMS/CONCEPT/ProgressLogger.h>
00040
00041 #include <OpenMS/FILTERING/NOISEESTIMATION/SignalToNoiseEstimatorMedian.h>
00042
00043 #include <gsl/gsl_spline.h>
00044 #include <gsl/gsl_interp.h>
00045
00046 #include <map>
00047
00048
00049 #define DEBUG_PEAK_PICKING
00050 #undef DEBUG_PEAK_PICKING
00051
00052 namespace OpenMS
00053 {
00067 class OPENMS_DLLAPI PeakPickerHiRes :
00068 public DefaultParamHandler,
00069 public ProgressLogger
00070 {
00071 public:
00073 PeakPickerHiRes();
00074
00076 virtual ~PeakPickerHiRes();
00077
00081 template <typename PeakType>
00082 void pick(const MSSpectrum<PeakType> & input, MSSpectrum<PeakType> & output) const
00083 {
00084
00085 output.clear(true);
00086 output.SpectrumSettings::operator=(input);
00087 output.MetaInfoInterface::operator=(input);
00088 output.setRT(input.getRT());
00089 output.setMSLevel(input.getMSLevel());
00090 output.setName(input.getName());
00091 output.setType(SpectrumSettings::PEAKS);
00092
00093
00094 if (input.size() < 5) return;
00095
00096
00097 SignalToNoiseEstimatorMedian<MSSpectrum<PeakType> > snt;
00098
00099 if (signal_to_noise_ > 0.0)
00100 {
00101 snt.init(input);
00102 }
00103
00104
00105 for (Size i = 2; i < input.size() - 2; ++i)
00106 {
00107 double central_peak_mz = input[i].getMZ(), central_peak_int = input[i].getIntensity();
00108 double left_neighbor_mz = input[i - 1].getMZ(), left_neighbor_int = input[i - 1].getIntensity();
00109 double right_neighbor_mz = input[i + 1].getMZ(), right_neighbor_int = input[i + 1].getIntensity();
00110
00111
00112 double left_to_central = std::fabs(central_peak_mz - left_neighbor_mz);
00113 double central_to_right = std::fabs(right_neighbor_mz - central_peak_mz);
00114 double min_spacing = (left_to_central < central_to_right) ? left_to_central : central_to_right;
00115
00116 double act_snt = 0.0, act_snt_l1 = 0.0, act_snt_r1 = 0.0;
00117
00118 if (signal_to_noise_ > 0.0)
00119 {
00120 act_snt = snt.getSignalToNoise(input[i]);
00121 act_snt_l1 = snt.getSignalToNoise(input[i - 1]);
00122 act_snt_r1 = snt.getSignalToNoise(input[i + 1]);
00123 }
00124
00125
00126 if (act_snt >= signal_to_noise_
00127 && left_to_central < 1.5 * min_spacing
00128 && central_peak_int > left_neighbor_int
00129 && act_snt_l1 >= signal_to_noise_
00130 && central_to_right < 1.5 * min_spacing
00131 && central_peak_int > right_neighbor_int
00132 && act_snt_r1 >= signal_to_noise_)
00133 {
00134
00135
00136
00137
00138 double act_snt_l2 = 0.0, act_snt_r2 = 0.0;
00139
00140 if (signal_to_noise_ > 0.0)
00141 {
00142 act_snt_l2 = snt.getSignalToNoise(input[i - 2]);
00143 act_snt_r2 = snt.getSignalToNoise(input[i + 2]);
00144 }
00145
00146 if ((i > 1
00147 && std::fabs(left_neighbor_mz - input[i - 2].getMZ()) < 1.5 * min_spacing
00148 && left_neighbor_int < input[i - 2].getIntensity()
00149 && act_snt_l2 >= signal_to_noise_)
00150 &&
00151 ((i + 2) < input.size()
00152 && std::fabs(input[i + 2].getMZ() - right_neighbor_mz) < 1.5 * min_spacing
00153 && right_neighbor_int < input[i + 2].getIntensity()
00154 && act_snt_r2 >= signal_to_noise_)
00155 )
00156 {
00157 ++i;
00158 continue;
00159 }
00160
00161
00162 std::map<double, double> peak_raw_data;
00163
00164 peak_raw_data[central_peak_mz] = central_peak_int;
00165 peak_raw_data[left_neighbor_mz] = left_neighbor_int;
00166 peak_raw_data[right_neighbor_mz] = right_neighbor_int;
00167
00168
00169
00170
00171 Size k = 2;
00172
00173 Size missing_left(0);
00174 Size missing_right(0);
00175
00176 while ((i - k + 1) > 0
00177 && (missing_left < 2)
00178 && input[i - k].getIntensity() <= peak_raw_data.begin()->second)
00179 {
00180
00181 double act_snt_lk = 0.0;
00182
00183 if (signal_to_noise_ > 0.0)
00184 {
00185 act_snt_lk = snt.getSignalToNoise(input[i - k]);
00186 }
00187
00188
00189 if (act_snt_lk >= signal_to_noise_ && std::fabs(input[i - k].getMZ() - peak_raw_data.begin()->first) < 1.5 * min_spacing)
00190 {
00191 peak_raw_data[input[i - k].getMZ()] = input[i - k].getIntensity();
00192 }
00193 else
00194 {
00195 peak_raw_data[input[i - k].getMZ()] = input[i - k].getIntensity();
00196 ++missing_left;
00197 }
00198
00199 ++k;
00200
00201 }
00202
00203
00204 k = 2;
00205 while ((i + k) < input.size()
00206 && (missing_right < 2)
00207 && input[i + k].getIntensity() <= peak_raw_data.rbegin()->second)
00208 {
00209
00210 double act_snt_rk = 0.0;
00211
00212 if (signal_to_noise_ > 0.0)
00213 {
00214 act_snt_rk = snt.getSignalToNoise(input[i + k]);
00215 }
00216
00217 if (act_snt_rk >= signal_to_noise_ && std::fabs(input[i + k].getMZ() - peak_raw_data.rbegin()->first) < 1.5 * min_spacing)
00218 {
00219 peak_raw_data[input[i + k].getMZ()] = input[i + k].getIntensity();
00220 }
00221 else
00222 {
00223 peak_raw_data[input[i + k].getMZ()] = input[i + k].getIntensity();
00224 ++missing_right;
00225 }
00226
00227 ++k;
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 const Size num_raw_points = peak_raw_data.size();
00243
00244 std::vector<double> raw_mz_values;
00245 std::vector<double> raw_int_values;
00246
00247 for (std::map<double, double>::const_iterator map_it = peak_raw_data.begin(); map_it != peak_raw_data.end(); ++map_it)
00248 {
00249 raw_mz_values.push_back(map_it->first);
00250 raw_int_values.push_back(map_it->second);
00251 }
00252
00253
00254 gsl_interp_accel * spline_acc = gsl_interp_accel_alloc();
00255 gsl_interp_accel * first_deriv_acc = gsl_interp_accel_alloc();
00256 gsl_spline * peak_spline = gsl_spline_alloc(gsl_interp_cspline, num_raw_points);
00257 gsl_spline_init(peak_spline, &(*raw_mz_values.begin()), &(*raw_int_values.begin()), num_raw_points);
00258
00259
00260
00261
00262 double max_peak_mz = central_peak_mz, max_peak_int = central_peak_int;
00263 double threshold = 0.000001;
00264 double lefthand = left_neighbor_mz;
00265 double righthand = right_neighbor_mz;
00266
00267 bool lefthand_sign = 1;
00268 double eps = std::numeric_limits<double>::epsilon();
00269
00270
00271
00272 do
00273 {
00274 double mid = (lefthand + righthand) / 2;
00275
00276 double midpoint_deriv_val = gsl_spline_eval_deriv(peak_spline, mid, first_deriv_acc);
00277
00278
00279 if (!(std::fabs(midpoint_deriv_val) > eps))
00280 {
00281 break;
00282 }
00283
00284 bool midpoint_sign = (midpoint_deriv_val < 0.0) ? 0 : 1;
00285
00286 if (lefthand_sign ^ midpoint_sign)
00287 {
00288 righthand = mid;
00289 }
00290 else
00291 {
00292 lefthand = mid;
00293 }
00294
00295
00296
00297
00298
00299
00300
00301 }
00302 while (std::fabs(lefthand - righthand) > threshold);
00303
00304
00305 max_peak_mz = (lefthand + righthand) / 2;
00306 max_peak_int = gsl_spline_eval(peak_spline, max_peak_mz, spline_acc);
00307
00308
00309 PeakType peak;
00310 peak.setMZ(max_peak_mz);
00311 peak.setIntensity(max_peak_int);
00312 output.push_back(peak);
00313
00314
00315 gsl_spline_free(peak_spline);
00316 gsl_interp_accel_free(spline_acc);
00317 gsl_interp_accel_free(first_deriv_acc);
00318
00319
00320 i = i + k - 1;
00321 }
00322 }
00323
00324 return;
00325 }
00326
00330 template <typename PeakType>
00331 void pickExperiment(const MSExperiment<PeakType> & input, MSExperiment<PeakType> & output) const
00332 {
00333
00334 output.clear(true);
00335
00336
00337 static_cast<ExperimentalSettings &>(output) = input;
00338
00339
00340 output.resize(input.size());
00341
00342 bool ms1_only = param_.getValue("ms1_only").toBool();
00343 Size progress = 0;
00344
00345 startProgress(0, input.size(), "picking peaks");
00346 for (Size scan_idx = 0; scan_idx != input.size(); ++scan_idx)
00347 {
00348 if (ms1_only && (input[scan_idx].getMSLevel() != 1))
00349 {
00350 output[scan_idx] = input[scan_idx];
00351 }
00352 else
00353 {
00354 pick(input[scan_idx], output[scan_idx]);
00355 }
00356 setProgress(++progress);
00357 }
00358 endProgress();
00359
00360 return;
00361 }
00362
00363 protected:
00364
00365 double signal_to_noise_;
00366
00367
00368 void updateMembers_();
00369
00370 };
00371
00372 }
00373
00374 #endif