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

GaussFilter.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: Eva Lange $
00033 // --------------------------------------------------------------------------
00034 
00035 #ifndef OPENMS_FILTERING_SMOOTHING_GAUSSFILTER_H
00036 #define OPENMS_FILTERING_SMOOTHING_GAUSSFILTER_H
00037 
00038 #include <OpenMS/DATASTRUCTURES/DefaultParamHandler.h>
00039 #include <OpenMS/CONCEPT/ProgressLogger.h>
00040 #include <OpenMS/CONCEPT/Constants.h>
00041 #include <OpenMS/KERNEL/MSExperiment.h>
00042 
00043 #include <cmath>
00044 
00045 namespace OpenMS
00046 {
00070 //#define DEBUG_FILTERING
00071 
00072   class OPENMS_DLLAPI GaussFilter :
00073     public ProgressLogger,
00074     public DefaultParamHandler
00075   {
00076 public:
00078     GaussFilter();
00079 
00081     virtual ~GaussFilter();
00082 
00090     template <typename PeakType>
00091     void filter(MSSpectrum<PeakType> & spectrum)
00092     {
00093       // make sure the right data type is set
00094       spectrum.setType(SpectrumSettings::RAWDATA);
00095       //create container for output peaks
00096       std::vector<DoubleReal> output(spectrum.size());
00097 
00098       bool use_ppm_tolerance(param_.getValue("use_ppm_tolerance").toBool());
00099       DoubleReal ppm_tolerance((DoubleReal)param_.getValue("ppm_tolerance"));
00100 
00101       bool found_signal = false;
00102       for (Size p = 0; p < spectrum.size(); ++p)
00103       {
00104         // if ppm tolerance is used, calculate a reasonable width value for this m/z
00105         if (use_ppm_tolerance)
00106         {
00107           param_.setValue("gaussian_width", spectrum[p].getMZ() * ppm_tolerance * 10e-6);
00108           updateMembers_();
00109         }
00110 
00111         DoubleReal new_int = integrate_(spectrum.begin() + p, spectrum.begin(), spectrum.end());
00112         output[p] = std::max(new_int, 0.0);
00113         if (fabs(new_int) > 0) found_signal = true;
00114       }
00115 
00116       // If all intensities are zero in the scan and the scan has a reasonable size, throw an exception.
00117       // This is the case if the gaussian filter is smaller than the spacing of raw data
00118       if (!found_signal && spectrum.size() >= 3)
00119       {
00120         String error_message = "Found no signal. The gaussian width is probably smaller than the spacing in your profile data. Try to use a bigger width.";
00121         if (spectrum.getRT() > 0.0)
00122         {
00123           error_message += String(" The error occured in the spectrum with retention time ") + spectrum.getRT() + ".\n";
00124         }
00125         std::cerr << error_message;
00126       }
00127       else
00128       {
00129         // copy the new data into the spectrum
00130         for (Size p = 0; p < spectrum.size(); ++p)
00131         {
00132           spectrum[p].setIntensity(output[p]);
00133         }
00134       }
00135     }
00136 
00142     template <typename PeakType>
00143     void filterExperiment(MSExperiment<PeakType> & map)
00144     {
00145       startProgress(0, map.size(), "smoothing data");
00146       for (Size i = 0; i < map.size(); ++i)
00147       {
00148         filter(map[i]);
00149         setProgress(i);
00150       }
00151       endProgress();
00152     }
00153 
00154 protected:
00155 
00157     std::vector<DoubleReal> coeffs_;
00159     DoubleReal sigma_;
00161     DoubleReal spacing_;
00162 
00163     // Docu in base class
00164     virtual void updateMembers_();
00165 
00167     template <typename InputPeakIterator>
00168     DoubleReal integrate_(InputPeakIterator x, InputPeakIterator first, InputPeakIterator last)
00169     {
00170       DoubleReal v = 0.;
00171       // norm the gaussian kernel area to one
00172       DoubleReal norm = 0.;
00173       Size middle = coeffs_.size();
00174 
00175       DoubleReal start_pos = ((x->getMZ() - (middle * spacing_)) > first->getMZ()) ? (x->getMZ() - (middle * spacing_))
00176                              : first->getMZ();
00177       DoubleReal end_pos = ((x->getMZ() + (middle * spacing_)) < (last - 1)->getMZ()) ? (x->getMZ() + (middle * spacing_))
00178                            : (last - 1)->getMZ();
00179 
00180 
00181       InputPeakIterator help = x;
00182 #ifdef DEBUG_FILTERING
00183 
00184       std::cout << "integrate from middle to start_pos " << help->getMZ() << " until " << start_pos << std::endl;
00185 #endif
00186 
00187       //integrate from middle to start_pos
00188       while ((help != first) && ((help - 1)->getMZ() > start_pos))
00189       {
00190         // search for the corresponding datapoint of help in the gaussian (take the left most adjacent point)
00191         DoubleReal distance_in_gaussian = fabs(x->getMZ() - help->getMZ());
00192         Size left_position = (Size)floor(distance_in_gaussian / spacing_);
00193 
00194         // search for the true left adjacent data point (because of rounding errors)
00195         for (int j = 0; ((j < 3) &&  (distance(first, help - j) >= 0)); ++j)
00196         {
00197           if (((left_position - j) * spacing_ <= distance_in_gaussian) && ((left_position - j + 1) * spacing_ >= distance_in_gaussian))
00198           {
00199             left_position -= j;
00200             break;
00201           }
00202 
00203           if (((left_position + j) * spacing_ < distance_in_gaussian) && ((left_position + j + 1) * spacing_ < distance_in_gaussian))
00204           {
00205             left_position += j;
00206             break;
00207           }
00208         }
00209 
00210         // interpolate between the left and right data points in the gaussian to get the true value at position distance_in_gaussian
00211         Size right_position = left_position + 1;
00212         DoubleReal d = fabs((left_position * spacing_) - distance_in_gaussian) / spacing_;
00213         // check if the right data point in the gaussian exists
00214         DoubleReal coeffs_right = (right_position < middle) ? (1 - d) * coeffs_[left_position] + d * coeffs_[right_position]
00215                                   : coeffs_[left_position];
00216 #ifdef DEBUG_FILTERING
00217 
00218         std::cout << "distance_in_gaussian " << distance_in_gaussian << std::endl;
00219         std::cout << " right_position " << right_position << std::endl;
00220         std::cout << " left_position " << left_position << std::endl;
00221         std::cout << "coeffs_ at left_position "  <<  coeffs_[left_position] << std::endl;
00222         std::cout << "coeffs_ at right_position "  <<  coeffs_[right_position] << std::endl;
00223         std::cout << "interpolated value left " << coeffs_right << std::endl;
00224 #endif
00225 
00226 
00227         // search for the corresponding datapoint for (help-1) in the gaussian (take the left most adjacent point)
00228         distance_in_gaussian = fabs(x->getMZ() - (help - 1)->getMZ());
00229         left_position = (Size)floor(distance_in_gaussian / spacing_);
00230 
00231         // search for the true left adjacent data point (because of rounding errors)
00232         for (UInt j = 0; ((j < 3) && (distance(first, help - j) >= 0)); ++j)
00233         {
00234           if (((left_position - j) * spacing_ <= distance_in_gaussian) && ((left_position - j + 1) * spacing_ >= distance_in_gaussian))
00235           {
00236             left_position -= j;
00237             break;
00238           }
00239 
00240           if (((left_position + j) * spacing_ < distance_in_gaussian) && ((left_position + j + 1) * spacing_ < distance_in_gaussian))
00241           {
00242             left_position += j;
00243             break;
00244           }
00245         }
00246 
00247         // start the interpolation for the true value in the gaussian
00248         right_position = left_position + 1;
00249         d = fabs((left_position * spacing_) - distance_in_gaussian) / spacing_;
00250         DoubleReal coeffs_left = (right_position < middle) ? (1 - d) * coeffs_[left_position] + d * coeffs_[right_position]
00251                                  : coeffs_[left_position];
00252 #ifdef DEBUG_FILTERING
00253 
00254         std::cout << " help-1 " << (help - 1)->getMZ() << " distance_in_gaussian " << distance_in_gaussian << std::endl;
00255         std::cout << " right_position " << right_position << std::endl;
00256         std::cout << " left_position " << left_position << std::endl;
00257         std::cout << "coeffs_ at left_position " <<  coeffs_[left_position] << std::endl;
00258         std::cout << "coeffs_ at right_position " <<   coeffs_[right_position] << std::endl;
00259         std::cout << "interpolated value right " << coeffs_left << std::endl;
00260 
00261         std::cout << " intensity " << fabs((help - 1)->getMZ() - help->getMZ()) / 2. << " * " << (help - 1)->getIntensity() << " * " << coeffs_left << " + " << (help)->getIntensity() << "* " << coeffs_right
00262                   << std::endl;
00263 #endif
00264 
00265 
00266         norm += fabs((help - 1)->getMZ() - help->getMZ()) / 2. * (coeffs_left + coeffs_right);
00267 
00268         v += fabs((help - 1)->getMZ() - help->getMZ()) / 2. * ((help - 1)->getIntensity() * coeffs_left + help->getIntensity() * coeffs_right);
00269         --help;
00270       }
00271 
00272 
00273       //integrate from middle to end_pos
00274       help = x;
00275 #ifdef DEBUG_FILTERING
00276 
00277       std::cout << "integrate from middle to endpos " << (help)->getMZ() << " until " << end_pos << std::endl;
00278 #endif
00279 
00280       while ((help != (last - 1)) && ((help + 1)->getMZ() < end_pos))
00281       {
00282         // search for the corresponding datapoint for help in the gaussian (take the left most adjacent point)
00283         DoubleReal distance_in_gaussian = fabs(x->getMZ() - help->getMZ());
00284         int left_position = (UInt)floor(distance_in_gaussian / spacing_);
00285 
00286         // search for the true left adjacent data point (because of rounding errors)
00287         for (int j = 0; ((j < 3) && (distance(help + j, last - 1) >= 0)); ++j)
00288         {
00289           if (((left_position - j) * spacing_ <= distance_in_gaussian) && ((left_position - j + 1) * spacing_ >= distance_in_gaussian))
00290           {
00291             left_position -= j;
00292             break;
00293           }
00294 
00295           if (((left_position + j) * spacing_ < distance_in_gaussian) && ((left_position + j + 1) * spacing_ < distance_in_gaussian))
00296           {
00297             left_position += j;
00298             break;
00299           }
00300         }
00301         // start the interpolation for the true value in the gaussian
00302         Size right_position = left_position + 1;
00303         DoubleReal d = fabs((left_position * spacing_) - distance_in_gaussian) / spacing_;
00304         DoubleReal coeffs_left = (right_position < middle) ? (1 - d) * coeffs_[left_position] + d * coeffs_[right_position]
00305                                  : coeffs_[left_position];
00306 
00307 #ifdef DEBUG_FILTERING
00308 
00309         std::cout << " help " << (help)->getMZ() << " distance_in_gaussian " << distance_in_gaussian << std::endl;
00310         std::cout << " left_position " << left_position << std::endl;
00311         std::cout << "coeffs_ at right_position " <<  coeffs_[left_position] << std::endl;
00312         std::cout << "coeffs_ at left_position " <<  coeffs_[right_position] << std::endl;
00313         std::cout << "interpolated value left " << coeffs_left << std::endl;
00314 #endif
00315 
00316         // search for the corresponding datapoint for (help+1) in the gaussian (take the left most adjacent point)
00317         distance_in_gaussian = fabs(x->getMZ() - (help + 1)->getMZ());
00318         left_position = (UInt)floor(distance_in_gaussian / spacing_);
00319 
00320         // search for the true left adjacent data point (because of rounding errors)
00321         for (int j = 0; ((j < 3) && (distance(help + j, last - 1) >= 0)); ++j)
00322         {
00323           if (((left_position - j) * spacing_ <= distance_in_gaussian) && ((left_position - j + 1) * spacing_ >= distance_in_gaussian))
00324           {
00325             left_position -= j;
00326             break;
00327           }
00328 
00329           if (((left_position + j) * spacing_ < distance_in_gaussian) && ((left_position + j + 1) * spacing_ < distance_in_gaussian))
00330           {
00331             left_position += j;
00332             break;
00333           }
00334         }
00335 
00336         // start the interpolation for the true value in the gaussian
00337         right_position = left_position + 1;
00338         d = fabs((left_position * spacing_) - distance_in_gaussian) / spacing_;
00339         DoubleReal coeffs_right = (right_position < middle) ? (1 - d) * coeffs_[left_position] + d * coeffs_[right_position]
00340                                   : coeffs_[left_position];
00341 #ifdef DEBUG_FILTERING
00342 
00343         std::cout << " (help + 1) " << (help + 1)->getMZ() << " distance_in_gaussian " << distance_in_gaussian << std::endl;
00344         std::cout << " left_position " << left_position << std::endl;
00345         std::cout << "coeffs_ at right_position " <<   coeffs_[left_position] << std::endl;
00346         std::cout << "coeffs_ at left_position " <<  coeffs_[right_position] << std::endl;
00347         std::cout << "interpolated value right " << coeffs_right << std::endl;
00348 
00349         std::cout << " intensity " <<  fabs(help->getMZ() - (help + 1)->getMZ()) / 2.
00350                   << " * " << help->getIntensity() << " * " << coeffs_left << " + " << (help + 1)->getIntensity()
00351                   << "* " << coeffs_right
00352                   << std::endl;
00353 #endif
00354         norm += fabs(help->getMZ() - (help + 1)->getMZ()) / 2. * (coeffs_left + coeffs_right);
00355 
00356         v += fabs(help->getMZ() - (help + 1)->getMZ()) / 2. * (help->getIntensity() * coeffs_left + (help + 1)->getIntensity() * coeffs_right);
00357         ++help;
00358       }
00359 
00360       if (v > 0)
00361       {
00362         return v / norm;
00363       }
00364       else
00365       {
00366         return 0;
00367       }
00368     }
00369 
00370   };
00371 
00372 } // namespace OpenMS
00373 #endif

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