Home  · Classes  · Annotated Classes  · Modules  · Members  · Namespaces  · Related Pages

InternalCalibration.h

Go to the documentation of this file.
00001 // --------------------------------------------------------------------------
00002 //                   OpenMS -- Open-Source Mass Spectrometry
00003 // --------------------------------------------------------------------------
00004 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
00005 // ETH Zurich, and Freie Universitaet Berlin 2002-2012.
00006 //
00007 // This software is released under a three-clause BSD license:
00008 //  * Redistributions of source code must retain the above copyright
00009 //    notice, this list of conditions and the following disclaimer.
00010 //  * Redistributions in binary form must reproduce the above copyright
00011 //    notice, this list of conditions and the following disclaimer in the
00012 //    documentation and/or other materials provided with the distribution.
00013 //  * Neither the name of any author or any participating institution
00014 //    may be used to endorse or promote products derived from this software
00015 //    without specific prior written permission.
00016 // For a full list of authors, refer to the file AUTHORS.
00017 // --------------------------------------------------------------------------
00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
00022 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00025 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00027 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 //
00030 // --------------------------------------------------------------------------
00031 // $Maintainer: Alexandra Zerck $
00032 // $Authors: $
00033 // --------------------------------------------------------------------------
00034 
00035 
00036 #ifndef OPENMS_FILTERING_CALIBRATION_INTERNALCALIBRATION_H
00037 #define OPENMS_FILTERING_CALIBRATION_INTERNALCALIBRATION_H
00038 #include <OpenMS/KERNEL/FeatureMap.h>
00039 #include <OpenMS/KERNEL/MSExperiment.h>
00040 #include <OpenMS/DATASTRUCTURES/DefaultParamHandler.h>
00041 #include <OpenMS/ANALYSIS/MAPMATCHING/TransformationDescription.h>
00042 #include <OpenMS/CONCEPT/ProgressLogger.h>
00043 #include <OpenMS/FORMAT/MzMLFile.h>
00044 #include <OpenMS/FORMAT/TransformationXMLFile.h>
00045 
00046 #include <gsl/gsl_fit.h>
00047 
00048 namespace OpenMS
00049 {
00050 
00062   class OPENMS_DLLAPI InternalCalibration :
00063     public DefaultParamHandler,
00064     public ProgressLogger
00065   {
00066 public:
00068     InternalCalibration();
00069 
00071     ~InternalCalibration(){}
00072 
00085     template <typename InputPeakType>
00086     void calibrateMapSpectrumwise(const MSExperiment<InputPeakType> & exp, MSExperiment<InputPeakType> & calibrated_exp, std::vector<DoubleReal> & ref_masses);
00087 
00100     template <typename InputPeakType>
00101     void calibrateMapGlobally(const MSExperiment<InputPeakType> & exp, MSExperiment<InputPeakType> & calibrated_exp, std::vector<DoubleReal> & ref_masses, String trafo_file_name = "");
00102 
00116     template <typename InputPeakType>
00117     void calibrateMapGlobally(const MSExperiment<InputPeakType> & exp, MSExperiment<InputPeakType> & calibrated_exp, std::vector<PeptideIdentification> & ref_ids, String trafo_file_name = "");
00118 
00127     void calibrateMapGlobally(const FeatureMap<> & feature_map, FeatureMap<> & calibrated_feature_map, String trafo_file_name = "");
00128 
00138     void calibrateMapGlobally(const FeatureMap<> & feature_map, FeatureMap<> & calibrated_feature_map, std::vector<PeptideIdentification> & ref_ids, String trafo_file_name = "");
00139 
00140 
00141 
00142     template <typename InputPeakType>
00143     void calibrateMapList(std::vector<MSExperiment<InputPeakType> > & exp_list, std::vector<MSExperiment<InputPeakType> > & calibrated_exp_list, std::vector<DoubleReal> & ref_masses, std::vector<DoubleReal> & detected_background_masses);
00144 
00145 
00146 protected:
00147 
00149     void makeLinearRegression_(std::vector<DoubleReal> & observed_masses, std::vector<DoubleReal> & theoretical_masses);
00150 
00152     void checkReferenceIds_(std::vector<PeptideIdentification> & pep_ids);
00153 
00155     void checkReferenceIds_(const FeatureMap<> & feature_map);
00156 
00158     void applyTransformation_(const FeatureMap<> & feature_map, FeatureMap<> & calibrated_feature_map);
00159 
00161     TransformationDescription trafo_;
00162   }; // class InternalCalibration
00163 
00164 
00165   template <typename InputPeakType>
00166   void InternalCalibration::calibrateMapSpectrumwise(const MSExperiment<InputPeakType> & exp, MSExperiment<InputPeakType> & calibrated_exp, std::vector<DoubleReal> & ref_masses)
00167   {
00168 #ifdef DEBUG_CALIBRATION
00169     std::cout.precision(writtenDigits<DoubleReal>());
00170 #endif
00171     if (exp.empty())
00172     {
00173       std::cout << "Input is empty." << std::endl;
00174       return;
00175     }
00176 
00177     if (exp[0].getType() != SpectrumSettings::PEAKS)
00178     {
00179       std::cout << "Attention: this function is assuming peak data." << std::endl;
00180     }
00181     calibrated_exp = exp;
00182 
00183     Size num_ref_peaks = ref_masses.size();
00184     bool use_ppm = (param_.getValue("mz_tolerance_unit") == "ppm") ? true : false;
00185     DoubleReal mz_tol = param_.getValue("mz_tolerance");
00186     startProgress(0, exp.size(), "calibrate spectra");
00187     // for each spectrum
00188     for (Size spec = 0; spec <  exp.size(); ++spec)
00189     {
00190       // calibrate only MS1 spectra
00191       if (exp[spec].getMSLevel() != 1)
00192       {
00193         continue;
00194       }
00195 
00196 
00197       std::vector<DoubleReal> corr_masses, rel_errors, found_ref_masses;
00198       UInt corr_peaks = 0;
00199       for (Size peak = 0; peak <  exp[spec].size(); ++peak)
00200       {
00201         for (Size ref_peak = 0; ref_peak < num_ref_peaks; ++ref_peak)
00202         {
00203           if (!use_ppm &&  fabs(exp[spec][peak].getMZ() - ref_masses[ref_peak]) <  mz_tol)
00204           {
00205             found_ref_masses.push_back(ref_masses[ref_peak]);
00206             corr_masses.push_back(exp[spec][peak].getMZ());
00207             ++corr_peaks;
00208             break;
00209           }
00210           else if (use_ppm &&  fabs(exp[spec][peak].getMZ() - ref_masses[ref_peak]) / ref_masses[ref_peak] * 1e6 <  mz_tol)
00211           {
00212             found_ref_masses.push_back(ref_masses[ref_peak]);
00213             corr_masses.push_back(exp[spec][peak].getMZ());
00214             ++corr_peaks;
00215             break;
00216           }
00217         }
00218       }
00219       if (corr_peaks < 2)
00220       {
00221         std::cout << "spec: " << spec
00222                   << " less than 2 reference masses were detected within a reasonable error range\n";
00223         std::cout << "This spectrum cannot be calibrated!\n";
00224         continue;
00225       }
00226 
00227       // determine rel error in ppm for the two reference masses
00228       for (Size ref_peak = 0; ref_peak < found_ref_masses.size(); ++ref_peak)
00229       {
00230         rel_errors.push_back((found_ref_masses[ref_peak] - corr_masses[ref_peak]) / corr_masses[ref_peak] * 1e6);
00231       }
00232 
00233       makeLinearRegression_(corr_masses, found_ref_masses);
00234 
00235       // now calibrate the whole spectrum
00236       for (unsigned int peak = 0; peak <  calibrated_exp[spec].size(); ++peak)
00237       {
00238 #ifdef DEBUG_CALIBRATION
00239         std::cout << calibrated_exp[spec][peak].getMZ() << "\t";
00240 #endif
00241         DoubleReal mz = calibrated_exp[spec][peak].getMZ();
00242         mz = trafo_.apply(mz);
00243         calibrated_exp[spec][peak].setMZ(mz);
00244 #ifdef DEBUG_CALIBRATION
00245         std::cout << calibrated_exp[spec][peak].getMZ() << std::endl;
00246 #endif
00247 
00248       }
00249       setProgress(spec);
00250     }  // for(Size spec=0;spec <  exp.size(); ++spec)
00251     endProgress();
00252   }
00253 
00254   template <typename InputPeakType>
00255   void InternalCalibration::calibrateMapGlobally(const MSExperiment<InputPeakType> & exp,
00256                                                  MSExperiment<InputPeakType> & calibrated_exp,
00257                                                  std::vector<PeptideIdentification> & ref_ids, String trafo_file_name)
00258   {
00259     bool use_ppm = param_.getValue("mz_tolerance_unit") == "ppm" ? true : false;
00260     DoubleReal mz_tolerance = param_.getValue("mz_tolerance");
00261     if (exp.empty())
00262     {
00263       std::cout << "Input is empty." << std::endl;
00264       return;
00265     }
00266 
00267     if (exp[0].getType() != SpectrumSettings::PEAKS)
00268     {
00269       std::cout << "Attention: this function is assuming peak data." << std::endl;
00270     }
00271     // check if the ids contain meta information about the peak positions
00272     checkReferenceIds_(ref_ids);
00273 
00274     std::vector<DoubleReal> theoretical_masses, observed_masses;
00275     for (Size p_id = 0; p_id < ref_ids.size(); ++p_id)
00276     {
00277       for (Size p_h = 0; p_h < ref_ids[p_id].getHits().size(); ++p_h)
00278       {
00279         Int charge = ref_ids[p_id].getHits()[p_h].getCharge();
00280         DoubleReal theo_mass = ref_ids[p_id].getHits()[p_h].getSequence().getMonoWeight(Residue::Full, charge) / (DoubleReal)charge;
00281         // first find corresponding ms1-spectrum
00282         typename MSExperiment<InputPeakType>::ConstIterator rt_iter = exp.RTBegin(ref_ids[p_id].getMetaValue("RT"));
00283         while (rt_iter != exp.begin() && rt_iter->getMSLevel() != 1)
00284         {
00285           --rt_iter;
00286         }
00287         // now find closest peak
00288         typename MSSpectrum<InputPeakType>::ConstIterator mz_iter = rt_iter->MZBegin(ref_ids[p_id].getMetaValue("MZ"));
00289         //std::cout << mz_iter->getMZ() <<" "<<(DoubleReal)ref_ids[p_id].getMetaValue("MZ")<<"\t";
00290         DoubleReal dist = (DoubleReal)ref_ids[p_id].getMetaValue("MZ") - mz_iter->getMZ();
00291         //std::cout << dist << "\t";
00292         if ((mz_iter + 1) != rt_iter->end()
00293            && fabs((mz_iter + 1)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")) < fabs(dist)
00294            && mz_iter != rt_iter->begin()
00295            && fabs((mz_iter - 1)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")) < fabs((mz_iter + 1)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")))                 // if mz_iter +1 has smaller dist than mz_iter and mz_iter-1
00296         {
00297           if ((use_ppm &&
00298                fabs((mz_iter + 1)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")) / (DoubleReal)ref_ids[p_id].getMetaValue("MZ") * 1e06 < mz_tolerance) ||
00299               (!use_ppm && fabs((mz_iter + 1)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")) < mz_tolerance))
00300           {
00301             //std::cout <<(mz_iter +1)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")<<"\t";
00302             observed_masses.push_back((mz_iter + 1)->getMZ());
00303             theoretical_masses.push_back(theo_mass);
00304             //std::cout << (mz_iter +1)->getMZ() << " ~ "<<theo_mass << " charge: "<<ref_ids[p_id].getHits()[p_h].getCharge()
00305             //<< "\tplus 1"<< std::endl;
00306           }
00307         }
00308         else if (mz_iter != rt_iter->begin()
00309                 && fabs((mz_iter - 1)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")) < fabs(dist))                        // if mz_iter-1 has smaller dist than mz_iter
00310         {
00311           if ((use_ppm &&
00312                fabs((mz_iter - 1)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")) / (DoubleReal)ref_ids[p_id].getMetaValue("MZ") * 1e06 < mz_tolerance) ||
00313               (!use_ppm && fabs((mz_iter - 1)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")) < mz_tolerance))
00314           {
00315             //std::cout <<(mz_iter -1)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")<<"\t";
00316             observed_masses.push_back((mz_iter - 1)->getMZ());
00317             theoretical_masses.push_back(theo_mass);
00318             //std::cout << (mz_iter -1)->getMZ() << " ~ "<<theo_mass << " charge: "<<ref_ids[p_id].getHits()[p_h].getCharge()
00319             //<< "\tminus 1"<< std::endl;
00320           }
00321         }
00322         else
00323         {
00324           if ((use_ppm &&
00325                fabs((mz_iter)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")) / (DoubleReal)ref_ids[p_id].getMetaValue("MZ") * 1e06 < mz_tolerance) ||
00326               (!use_ppm && fabs((mz_iter)->getMZ() - (DoubleReal)ref_ids[p_id].getMetaValue("MZ")) < mz_tolerance))
00327           {
00328 
00329             observed_masses.push_back(mz_iter->getMZ());
00330             theoretical_masses.push_back(theo_mass);
00331 //                                      std::cout <<"\t"<< mz_iter->getMZ() << " ~ "<<theo_mass<< " charge: "<<ref_ids[p_id].getHits()[p_h].getCharge()
00332 //                                                          << "\tat mz_iter"<< std::endl;
00333           }
00334         }
00335       }
00336     }
00337 
00338     makeLinearRegression_(observed_masses, theoretical_masses);
00339     static_cast<ExperimentalSettings &>(calibrated_exp) = exp;
00340     calibrated_exp.resize(exp.size());
00341 
00342     // for each spectrum
00343     for (Size spec = 0; spec <  exp.size(); ++spec)
00344     {
00345       // calibrate only MS1 spectra
00346       if (exp[spec].getMSLevel() != 1)
00347       {
00348         calibrated_exp[spec] = exp[spec];
00349         continue;
00350       }
00351       // copy the spectrum meta data
00352       calibrated_exp[spec] = exp[spec];
00353 
00354       for (unsigned int peak = 0; peak <  exp[spec].size(); ++peak)
00355       {
00356 #ifdef DEBUG_CALIBRATION
00357         std::cout << exp[spec][peak].getMZ() << "\t";
00358 #endif
00359         DoubleReal mz = exp[spec][peak].getMZ();
00360         mz = trafo_.apply(mz);
00361         calibrated_exp[spec][peak].setMZ(mz);
00362 #ifdef DEBUG_CALIBRATION
00363         std::cout << calibrated_exp[spec][peak].getMZ() << std::endl;
00364 #endif
00365 
00366       }
00367     }  // for(Size spec=0;spec <  exp.size(); ++spec)
00368     if (trafo_file_name != "")
00369     {
00370       TransformationXMLFile().store(trafo_file_name, trafo_);
00371     }
00372   }
00373 
00374   template <typename InputPeakType>
00375   void InternalCalibration::calibrateMapGlobally(const MSExperiment<InputPeakType> & exp, MSExperiment<InputPeakType> & calibrated_exp, std::vector<DoubleReal> & ref_masses, String trafo_file_name)
00376   {
00377     if (exp.empty())
00378     {
00379       std::cout << "Input is empty." << std::endl;
00380       return;
00381     }
00382 
00383     if (exp[0].getType() != SpectrumSettings::PEAKS)
00384     {
00385       std::cout << "Attention: this function is assuming peak data." << std::endl;
00386     }
00387 
00388 
00389     Size num_ref_peaks = ref_masses.size();
00390     bool use_ppm = (param_.getValue("mz_tolerance_unit") == "ppm") ? true : false;
00391     DoubleReal mz_tol = param_.getValue("mz_tolerance");
00392     startProgress(0, exp.size(), "calibrate spectra");
00393     std::vector<DoubleReal> corr_masses, rel_errors, found_ref_masses;
00394     UInt corr_peaks = 0;
00395     // for each spectrum
00396     for (Size spec = 0; spec <  exp.size(); ++spec)
00397     {
00398       // calibrate only MS1 spectra
00399       if (exp[spec].getMSLevel() != 1)
00400         continue;
00401       for (Size peak = 0; peak <  exp[spec].size(); ++peak)
00402       {
00403         for (Size ref_peak = 0; ref_peak < num_ref_peaks; ++ref_peak)
00404         {
00405           if (!use_ppm &&  fabs(exp[spec][peak].getMZ() - ref_masses[ref_peak]) <  mz_tol)
00406           {
00407             found_ref_masses.push_back(ref_masses[ref_peak]);
00408             corr_masses.push_back(exp[spec][peak].getMZ());
00409             ++corr_peaks;
00410             break;
00411           }
00412           else if (use_ppm &&  fabs(exp[spec][peak].getMZ() - ref_masses[ref_peak]) / ref_masses[ref_peak] * 1e6 <  mz_tol)
00413           {
00414             found_ref_masses.push_back(ref_masses[ref_peak]);
00415             corr_masses.push_back(exp[spec][peak].getMZ());
00416             ++corr_peaks;
00417             break;
00418           }
00419         }
00420       }
00421     }
00422     if (corr_peaks < 2)
00423     {
00424       std::cout << "Less than 2 reference masses were detected within a reasonable error range\n";
00425       std::cout << "This spectrum cannot be calibrated!\n";
00426       return;
00427     }
00428 
00429     // calculate the (linear) calibration function
00430     makeLinearRegression_(corr_masses, found_ref_masses);
00431     static_cast<ExperimentalSettings &>(calibrated_exp) = exp;
00432     calibrated_exp.resize(exp.size());
00433 
00434     // apply the calibration function to each peak
00435     for (Size spec = 0; spec <  exp.size(); ++spec)
00436     {
00437       // calibrate only MS1 spectra
00438       if (exp[spec].getMSLevel() != 1)
00439       {
00440         calibrated_exp[spec] = exp[spec];
00441         continue;
00442       }
00443 
00444       // copy the spectrum data
00445       calibrated_exp[spec] = exp[spec];
00446 
00447       for (unsigned int peak = 0; peak <  exp[spec].size(); ++peak)
00448       {
00449 #ifdef DEBUG_CALIBRATION
00450         std::cout << exp[spec][peak].getMZ() << "\t";
00451 #endif
00452         DoubleReal mz = exp[spec][peak].getMZ();
00453         mz = trafo_.apply(mz);
00454         calibrated_exp[spec][peak].setMZ(mz);
00455 
00456 #ifdef DEBUG_CALIBRATION
00457         std::cout << calibrated_exp[spec][peak].getMZ() << std::endl;
00458 #endif
00459 
00460       }
00461       setProgress(spec);
00462     }  // for(Size spec=0;spec <  exp.size(); ++spec)
00463     endProgress();
00464     if (trafo_file_name != "")
00465     {
00466       TransformationXMLFile().store(trafo_file_name, trafo_);
00467     }
00468   }
00469 
00470 } // namespace OpenMS
00471 
00472 #endif // OPENMS_FILTERING_CALIBRATION_INTERNALCALIBRATION_H

OpenMS / TOPP release 1.10.0 Documentation generated on Thu Mar 7 2013 09:42:40 using doxygen 1.7.1