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

IsotopeWaveletTransform.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: Rene Hussong$
00032 // $Authors: $
00033 // --------------------------------------------------------------------------
00034 
00035 #ifndef OPENMS_TRANSFORMATIONS_FEATUREFINDER_ISOTOPEWAVELETTRANSFORM_H
00036 #define OPENMS_TRANSFORMATIONS_FEATUREFINDER_ISOTOPEWAVELETTRANSFORM_H
00037 
00038 #include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/IsotopeWaveletConstants.h>
00039 #include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/IsotopeWavelet.h>
00040 #include <OpenMS/KERNEL/FeatureMap.h>
00041 #include <OpenMS/KERNEL/MSExperiment.h>
00042 #include <OpenMS/KERNEL/MSSpectrum.h>
00043 #include <OpenMS/CONCEPT/Exception.h>
00044 #include <OpenMS/MATH/STATISTICS/LinearRegression.h>
00045 #include <OpenMS/DATASTRUCTURES/ConstRefVector.h>
00046 #include <cmath>
00047 #include <math.h>
00048 #include <boost/math/special_functions/bessel.hpp>
00049 #include <vector>
00050 #include <map>
00051 #include <sstream>
00052 #include <fstream>
00053 #include <iomanip>
00054 
00055 #ifdef OPENMS_HAS_CUDA
00056 #include <cuda.h>
00057 #include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/IsotopeWaveletCudaKernel.h>
00058 #endif
00059 
00060 // we are not yet sure if we really want to drag in cutil.h and the CUDA_SAFE_CALL definitions...
00061 #ifndef CUDA_SAFE_CALL
00062 #define CUDA_SAFE_CALL(call) call;
00063 #endif
00064 
00065 namespace OpenMS
00066 {
00067 
00069   class cudaHelp
00070   {
00071 public:
00072     float getMZ()
00073     { return mz; }
00074     float getIntensity()
00075     { return intens; }
00076 
00077     float mz;
00078     float intens;
00079     float score;
00080   };
00081 
00082 
00086   template <typename PeakType>
00087   class IsotopeWaveletTransform
00088   {
00089 public:
00090 
00091 
00093     struct BoxElement
00094     {
00095       DoubleReal mz; //<The monoisotopic position
00096       UInt c; //<Note, this is not the charge (it is charge-1!!!)
00097       DoubleReal score; //<The associated score
00098       DoubleReal intens; //<The transformed intensity at the monoisotopic mass
00099       DoubleReal ref_intens;
00100       DoubleReal RT; //<The elution time (not the scan index)
00101       UInt RT_index; //<The elution time (map) index
00102       UInt MZ_begin; //<Index
00103       UInt MZ_end; //<Index
00104     };
00105 
00106     typedef std::multimap<UInt, BoxElement> Box; 
00107 
00108 
00112     class TransSpectrum
00113     {
00114       friend class IsotopeWaveletTransform;
00115 
00116 public:
00117 
00119       TransSpectrum() :
00120         reference_(NULL), trans_intens_(NULL)
00121       {
00122       }
00123 
00125       TransSpectrum(const MSSpectrum<PeakType>* reference) :
00126         reference_(reference)
00127       {
00128         trans_intens_ = new std::vector<float>(reference_->size(), 0.0);
00129       }
00130 
00132       virtual ~TransSpectrum()
00133       {
00134         delete (trans_intens_);
00135       }
00136 
00137       virtual void destroy()
00138       {
00139         delete (trans_intens_);
00140         trans_intens_ = NULL;
00141         delete (reference_);
00142         reference_ = NULL;
00143       }
00144 
00146       inline DoubleReal getRT() const
00147       {
00148         return reference_->getRT();
00149       }
00150 
00152       inline DoubleReal getMZ(const UInt i) const
00153       {
00154         return (*reference_)[i].getMZ();
00155       }
00156 
00158       inline DoubleReal getRefIntensity(const UInt i) const
00159       {
00160         return (*reference_)[i].getIntensity();
00161       }
00162 
00164       inline DoubleReal getTransIntensity(const UInt i) const
00165       {
00166         return (*trans_intens_)[i];
00167       }
00168 
00170       inline void setTransIntensity(const UInt i, const DoubleReal intens)
00171       {
00172         (*trans_intens_)[i] = intens;
00173       }
00174 
00176       inline Size size() const
00177       {
00178         return trans_intens_->size();
00179       }
00180 
00182       inline const MSSpectrum<PeakType>* getRefSpectrum()
00183       {
00184         return reference_;
00185       }
00186 
00188       inline const MSSpectrum<PeakType>* getRefSpectrum() const
00189       {
00190         return reference_;
00191       }
00192 
00195       inline typename MSSpectrum<PeakType>::const_iterator MZBegin(const DoubleReal mz) const
00196       {
00197         return reference_->MZBegin(mz);
00198       }
00199 
00202       inline typename MSSpectrum<PeakType>::const_iterator MZEnd(const DoubleReal mz) const
00203       {
00204         return reference_->MZEnd(mz);
00205       }
00206 
00209       inline typename MSSpectrum<PeakType>::const_iterator end() const
00210       {
00211         return reference_->end();
00212       }
00213 
00216       inline typename MSSpectrum<PeakType>::const_iterator begin() const
00217       {
00218         return reference_->begin();
00219       }
00220 
00221 protected:
00222 
00223       const MSSpectrum<PeakType>* reference_; //<The reference spectrum
00224       std::vector<float>* trans_intens_; //<The intensities of the transform
00225 
00226     };
00227 
00228 
00229 
00235     IsotopeWaveletTransform(const DoubleReal min_mz, const DoubleReal max_mz, const UInt max_charge, const Size max_scan_size = 0, const bool use_cuda = false, const bool hr_data = false, const String intenstype = "ref");
00236 
00238     virtual ~IsotopeWaveletTransform();
00239 
00240 
00245     virtual void getTransform(MSSpectrum<PeakType>& c_trans, const MSSpectrum<PeakType>& c_ref, const UInt c);
00246 
00251     virtual void getTransformHighRes(MSSpectrum<PeakType>& c_trans, const MSSpectrum<PeakType>& c_ref, const UInt c);
00252 
00272     virtual void identifyCharge(const MSSpectrum<PeakType>& candidates, const MSSpectrum<PeakType>& ref, const UInt scan_index, const UInt c,
00273                                 const DoubleReal ampl_cutoff, const bool check_PPMs);
00274 
00275     virtual void initializeScan(const MSSpectrum<PeakType>& c_ref, const UInt c = 0);
00276 
00277 #ifdef OPENMS_HAS_CUDA
00278 
00280     virtual int initializeScanCuda(const MSSpectrum<PeakType>& scan, const UInt c = 0);
00281 
00283     virtual void finalizeScanCuda();
00284 
00288     virtual void getTransformCuda(TransSpectrum& c_trans, const UInt c);
00289 
00305     virtual void identifyChargeCuda(const TransSpectrum& candidates, const UInt scan_index, const UInt c,
00306                                     const DoubleReal ampl_cutoff, const bool check_PPMs);
00307 
00310     virtual int sortCuda(MSSpectrum<PeakType>& sorted);
00311 #endif
00312 
00313 
00320     void updateBoxStates(const MSExperiment<PeakType>& map, const Size scan_index, const UInt RT_interleave,
00321                          const UInt RT_votes_cutoff, const Int front_bound = -1, const Int end_bound = -1);
00322 
00323 
00324     void mergeFeatures(IsotopeWaveletTransform<PeakType>* later_iwt, const UInt RT_interleave, const UInt RT_votes_cutoff);
00325 
00326 
00331     FeatureMap<Feature> mapSeeds2Features(const MSExperiment<PeakType>& map, const UInt RT_votes_cutoff);
00332 
00334     virtual std::multimap<DoubleReal, Box> getClosedBoxes()
00335     { return closed_boxes_;  }
00336 
00337 
00342     inline DoubleReal getLinearInterpolation(const typename MSSpectrum<PeakType>::const_iterator& left_iter, const DoubleReal mz_pos, const typename MSSpectrum<PeakType>::const_iterator& right_iter)
00343     {
00344       return left_iter->getIntensity() + (right_iter->getIntensity() - left_iter->getIntensity()) / (right_iter->getMZ() - left_iter->getMZ()) * (mz_pos - left_iter->getMZ());
00345     }
00346 
00353     inline DoubleReal getLinearInterpolation(const DoubleReal mz_a, const DoubleReal intens_a, const DoubleReal mz_pos, const DoubleReal mz_b, const DoubleReal intens_b)
00354     {
00355       return intens_a + (intens_b - intens_a) / (mz_b - mz_a) * (mz_pos - mz_a);
00356     }
00357 
00358     inline DoubleReal getSigma() const
00359     {
00360       return sigma_;
00361     }
00362 
00363     inline void setSigma(const DoubleReal sigma)
00364     {
00365       sigma_ = sigma;
00366     }
00367 
00368     virtual void computeMinSpacing(const MSSpectrum<PeakType>& c_ref);
00369 
00370     inline DoubleReal getMinSpacing() const
00371     {
00372       return min_spacing_;
00373     }
00374 
00375     inline Size getMaxScanSize() const
00376     {
00377       return max_scan_size_;
00378     }
00379 
00380 protected:
00381 
00382 
00385     IsotopeWaveletTransform();
00386 
00387 
00388     inline void sampleTheCMarrWavelet_(const MSSpectrum<PeakType>& scan, const Int wavelet_length, const Int mz_index, const UInt charge);
00389 
00390 
00397     virtual DoubleReal scoreThis_(const TransSpectrum& candidate, const UInt peak_cutoff,
00398                                   const DoubleReal seed_mz, const UInt c, const DoubleReal ampl_cutoff);
00399 
00406     virtual DoubleReal scoreThis_(const MSSpectrum<PeakType>& candidate, const UInt peak_cutoff,
00407                                   const DoubleReal seed_mz, const UInt c, const DoubleReal ampl_cutoff);
00408 
00409 
00417     virtual bool checkPositionForPlausibility_(const TransSpectrum& candidate, const MSSpectrum<PeakType>& ref, const DoubleReal seed_mz,
00418                                                const UInt c, const UInt scan_index, const bool check_PPMs, const DoubleReal transintens, const DoubleReal prev_score);
00419 
00427     virtual bool checkPositionForPlausibility_(const MSSpectrum<PeakType>& candidate, const MSSpectrum<PeakType>& ref, const DoubleReal seed_mz,
00428                                                const UInt c, const UInt scan_index, const bool check_PPMs, const DoubleReal transintens, const DoubleReal prev_score);
00429 
00430     virtual std::pair<DoubleReal, DoubleReal> checkPPMTheoModel_(const MSSpectrum<PeakType>& ref, const DoubleReal c_mz, const UInt c);
00431 
00432 
00434     inline DoubleReal getAvIntens_(const TransSpectrum& scan);
00436     inline DoubleReal getAvIntens_(const MSSpectrum<PeakType>& scan);
00437 
00439     inline DoubleReal getSdIntens_(const TransSpectrum& scan, const DoubleReal mean);
00441     inline DoubleReal getSdIntens_(const MSSpectrum<PeakType>& scan, const DoubleReal mean);
00442 
00453     virtual void push2Box_(const DoubleReal mz, const UInt scan, UInt c, const DoubleReal score,
00454                            const DoubleReal intens, const DoubleReal rt, const UInt MZ_begin, const UInt MZ_end, const DoubleReal ref_intens);
00455 
00471     virtual void push2TmpBox_(const DoubleReal mz, const UInt scan, UInt charge, const DoubleReal score,
00472                               const DoubleReal intens, const DoubleReal rt, const UInt MZ_begin, const UInt MZ_end);
00473 
00479     inline DoubleReal getAvMZSpacing_(const MSSpectrum<PeakType>& scan);
00480 
00481 
00486     void clusterSeeds_(const TransSpectrum& candidates, const MSSpectrum<PeakType>& ref,
00487                        const UInt scan_index, const UInt c, const bool check_PPMs);
00488 
00493     virtual void clusterSeeds_(const MSSpectrum<PeakType>& candidates, const MSSpectrum<PeakType>& ref,
00494                                const UInt scan_index, const UInt c, const bool check_PPMs);
00495 
00496 
00501     void extendBox_(const MSExperiment<PeakType>& map, const Box box);
00502 
00505     inline DoubleReal peptideMassRule_(const DoubleReal c_mass) const
00506     {
00507       DoubleReal correction_fac = c_mass / Constants::PEPTIDE_MASS_RULE_BOUND;
00508       DoubleReal old_frac_mass = c_mass - (Int)(c_mass);
00509       DoubleReal new_mass = ((Int)(c_mass)) * (1. + Constants::PEPTIDE_MASS_RULE_FACTOR) - (Int)(correction_fac);
00510       DoubleReal new_frac_mass = new_mass - (Int)(new_mass);
00511 
00512       if (new_frac_mass - old_frac_mass > 0.5)
00513       {
00514         new_mass -= 1.;
00515       }
00516 
00517       if (new_frac_mass - old_frac_mass < -0.5)
00518       {
00519         new_mass += 1.;
00520       }
00521 
00522       return new_mass;
00523     }
00524 
00528     inline DoubleReal getPPMs_(const DoubleReal mass_a, const DoubleReal mass_b) const
00529     {
00530       return fabs(mass_a - mass_b) / (0.5 * (mass_a + mass_b)) * 1e6;
00531     }
00532 
00533     //internally used data structures for the sweep line algorithm
00534     std::multimap<DoubleReal, Box> open_boxes_, closed_boxes_, end_boxes_, front_boxes_; //DoubleReal = average m/z position
00535     std::vector<std::multimap<DoubleReal, Box> >* tmp_boxes_; //for each charge we need a separate container
00536 
00537     DoubleReal av_MZ_spacing_, sigma_;
00538     std::vector<DoubleReal> c_mzs_, c_spacings_, psi_, prod_, xs_;
00539     std::vector<DoubleReal> interpol_xs_, interpol_ys_;
00540 
00541     Size max_scan_size_;
00542     UInt max_num_peaks_per_pattern_, max_charge_, data_length_;
00543     bool hr_data_;
00544     String intenstype_;
00545     Int from_max_to_left_, from_max_to_right_;
00546     std::vector<int> indices_;
00547 
00548     MSSpectrum<PeakType> c_sorted_candidate_;
00549     DoubleReal min_spacing_, max_mz_cutoff_;
00550     std::vector<float> scores_, zeros_;
00551 
00552 #ifdef OPENMS_HAS_CUDA
00553     float* h_data_;
00554     int* h_pos_;
00555     UInt largest_array_size_, overall_size_, block_size_, to_load_, to_compute_;
00556     Int num_elements_;
00557     void* cuda_device_intens_;
00558     void* cuda_device_pos_;
00559     void* cuda_device_trans_intens_;
00560     void* cuda_device_fwd2_;
00561     void* cuda_device_posindices_sorted_;
00562     void* cuda_device_trans_intens_sorted_;
00563     void* cuda_device_scores_;
00564     std::vector<float> cuda_positions_, cuda_intensities_;
00565     dim3 dimGrid_, dimBlock_;
00566 #endif
00567   };
00568 
00569 
00570   bool myCudaComparator(const cudaHelp& a, const cudaHelp& b);
00571 
00572   template <typename PeakType>
00573   bool intensityComparator(const PeakType& a, const PeakType& b)
00574   {
00575     return a.getIntensity() > b.getIntensity();
00576   }
00577 
00578   template <typename PeakType>
00579   bool intensityAscendingComparator(const PeakType& a, const PeakType& b)
00580   {
00581     return a.getIntensity() < b.getIntensity();
00582   }
00583 
00584   template <typename PeakType>
00585   bool intensityPointerComparator(PeakType* a, PeakType* b)
00586   {
00587     return a->getIntensity() > b->getIntensity();
00588   }
00589 
00590   template <typename PeakType>
00591   bool positionComparator(const PeakType& a, const PeakType& b)
00592   {
00593     return a.getMZ() < b.getMZ();
00594   }
00595 
00596   template <typename PeakType>
00597   IsotopeWaveletTransform<PeakType>::IsotopeWaveletTransform()
00598   {
00599     tmp_boxes_ = new std::vector<std::multimap<DoubleReal, Box> >(1);
00600     av_MZ_spacing_ = 1;
00601     max_scan_size_ = 0;
00602     max_mz_cutoff_ = 3;
00603     max_num_peaks_per_pattern_ = 3;
00604     hr_data_ = false;
00605     intenstype_ = "ref";
00606 #ifdef OPENMS_HAS_CUDA
00607     largest_array_size_ = 0;
00608     num_elements_ = 0;
00609     h_data_ = NULL;
00610     h_pos_ = NULL;
00611 #endif
00612   }
00613 
00614   template <typename PeakType>
00615   IsotopeWaveletTransform<PeakType>::IsotopeWaveletTransform(const DoubleReal min_mz, const DoubleReal max_mz, const UInt max_charge, const Size max_scan_size, const bool use_cuda, const bool hr_data, String intenstype)
00616   {
00617     max_charge_ = max_charge;
00618     max_scan_size_ = max_scan_size;
00619     hr_data_ = hr_data;
00620     intenstype_ = intenstype;
00621     tmp_boxes_ = new std::vector<std::multimap<DoubleReal, Box> >(max_charge);
00622     if (max_scan_size <= 0) //only important for the CPU
00623     {
00624       IsotopeWavelet::init(max_mz, max_charge);
00625     }
00626 
00627     av_MZ_spacing_ = 1;
00628     max_mz_cutoff_ =  IsotopeWavelet::getMzPeakCutOffAtMonoPos(max_mz, max_charge);
00629     max_num_peaks_per_pattern_ =  IsotopeWavelet::getNumPeakCutOff(max_mz, max_charge);
00630 
00631 #ifdef OPENMS_HAS_CUDA
00632     if (use_cuda) //only important for the GPU
00633     {
00634       if (hr_data_)
00635       {
00636         max_scan_size_ = max_scan_size * (4 * (max_mz_cutoff_ - 1) - 1);
00637       }
00638       largest_array_size_ =  pow(2, ceil(log(max_scan_size_ +  Constants::CUDA_EXTENDED_BLOCK_SIZE_MAX) / log(2.0)));
00639 
00640       cuda_positions_.reserve(largest_array_size_);
00641       cuda_intensities_.reserve(largest_array_size_);
00642       indices_.resize(largest_array_size_);
00643       for (UInt q = 0; q < largest_array_size_; ++q)
00644       {
00645         indices_[q] = q;
00646       }
00647 
00648       h_data_ = (float*) malloc(largest_array_size_ * sizeof(float));
00649       h_pos_ = (int*) malloc(largest_array_size_ * sizeof(int));
00650     }
00651     else
00652     {
00653       h_data_ = NULL;
00654       h_pos_ = NULL;
00655       Int size_estimate((Int)ceil(max_scan_size_ / (max_mz - min_mz)));
00656       Int to_reserve((Int)ceil(size_estimate * max_num_peaks_per_pattern_ * Constants::IW_NEUTRON_MASS));
00657       psi_.reserve(to_reserve); //The wavelet
00658       prod_.reserve(to_reserve);
00659       xs_.reserve(to_reserve);
00660       interpol_xs_.resize(Constants::DEFAULT_NUM_OF_INTERPOLATION_POINTS);
00661       interpol_ys_.resize(Constants::DEFAULT_NUM_OF_INTERPOLATION_POINTS);
00662     }
00663 #else
00664     if (!use_cuda)
00665     {
00666       Int size_estimate((Int)ceil(max_scan_size_ / (max_mz - min_mz)));
00667       Int to_reserve((Int)ceil(size_estimate * max_num_peaks_per_pattern_ * Constants::IW_NEUTRON_MASS));
00668       psi_.reserve(to_reserve); //The wavelet
00669       prod_.reserve(to_reserve);
00670       xs_.reserve(to_reserve);
00671       interpol_xs_.resize(Constants::DEFAULT_NUM_OF_INTERPOLATION_POINTS);
00672       interpol_ys_.resize(Constants::DEFAULT_NUM_OF_INTERPOLATION_POINTS);
00673     }
00674 #endif
00675   }
00676 
00677   template <typename PeakType>
00678   IsotopeWaveletTransform<PeakType>::~IsotopeWaveletTransform()
00679   {
00680 #ifdef OPENMS_HAS_CUDA
00681     if (h_data_ != NULL)
00682       free(h_data_);
00683     if (h_pos_ != NULL)
00684       free(h_pos_);
00685     h_data_ = NULL;
00686     h_pos_ = NULL;
00687 #endif
00688 
00689     delete (tmp_boxes_);
00690   }
00691 
00692   template <typename PeakType>
00693   void IsotopeWaveletTransform<PeakType>::getTransform(MSSpectrum<PeakType>& c_trans, const MSSpectrum<PeakType>& c_ref, const UInt c)
00694   {
00695     Int spec_size((Int)c_ref.size());
00696     //in the very unlikely case that size_t will not fit to int anymore this will be a problem of course
00697     //for the sake of simplicity (we need here a signed int) we do not cast at every following comparison individually
00698     UInt charge = c + 1;
00699     DoubleReal value, T_boundary_left, T_boundary_right, old, c_diff, current, old_pos, my_local_MZ, my_local_lambda, origin, c_mz;
00700 
00701     for (Int my_local_pos = 0; my_local_pos < spec_size; ++my_local_pos)
00702     {
00703       value = 0; T_boundary_left = 0, T_boundary_right = IsotopeWavelet::getMzPeakCutOffAtMonoPos(c_ref[my_local_pos].getMZ(), charge) / (DoubleReal)charge;
00704       old = 0; old_pos = (my_local_pos - from_max_to_left_ - 1 >= 0) ? c_ref[my_local_pos - from_max_to_left_ - 1].getMZ() : c_ref[0].getMZ() - min_spacing_;
00705       my_local_MZ = c_ref[my_local_pos].getMZ(); my_local_lambda = IsotopeWavelet::getLambdaL(my_local_MZ * charge);
00706       c_diff = 0;
00707       origin = -my_local_MZ + Constants::IW_QUARTER_NEUTRON_MASS / (DoubleReal)charge;
00708 
00709       for (Int current_conv_pos =  std::max(0, my_local_pos - from_max_to_left_); c_diff < T_boundary_right; ++current_conv_pos)
00710       {
00711         if (current_conv_pos >= spec_size)
00712         {
00713           value += 0.5 * old * min_spacing_;
00714           break;
00715         }
00716 
00717         c_mz = c_ref[current_conv_pos].getMZ();
00718         c_diff = c_mz + origin;
00719 
00720         //Attention! The +1. has nothing to do with the charge, it is caused by the wavelet's formula (tz1).
00721         current = c_diff > T_boundary_left && c_diff <= T_boundary_right ? IsotopeWavelet::getValueByLambda(my_local_lambda, c_diff * charge + 1.) * c_ref[current_conv_pos].getIntensity() : 0;
00722 
00723         value += 0.5 * (current + old) * (c_mz - old_pos);
00724 
00725         old = current;
00726         old_pos = c_mz;
00727       }
00728 
00729 
00730 
00731       c_trans[my_local_pos].setIntensity(value);
00732     }
00733   }
00734 
00735   template <typename PeakType>
00736   void IsotopeWaveletTransform<PeakType>::getTransformHighRes(MSSpectrum<PeakType>& c_trans, const MSSpectrum<PeakType>& c_ref, const UInt c)
00737   {
00738     Int spec_size((Int)c_ref.size());
00739     //in the very unlikely case that size_t will not fit to int anymore this will be a problem of course
00740     //for the sake of simplicity (we need here a signed int) we do not cast at every following comparison individually
00741     UInt charge = c + 1;
00742     DoubleReal value, T_boundary_left, T_boundary_right, c_diff, current, my_local_MZ, my_local_lambda, origin, c_mz;
00743 
00744     for (Int my_local_pos = 0; my_local_pos < spec_size; ++my_local_pos)
00745     {
00746       value = 0; T_boundary_left = 0, T_boundary_right = IsotopeWavelet::getMzPeakCutOffAtMonoPos(c_ref[my_local_pos].getMZ(), charge) / (DoubleReal)charge;
00747 
00748 
00749       my_local_MZ = c_ref[my_local_pos].getMZ(); my_local_lambda = IsotopeWavelet::getLambdaL(my_local_MZ * charge);
00750       c_diff = 0;
00751       origin = -my_local_MZ + Constants::IW_QUARTER_NEUTRON_MASS / (DoubleReal)charge;
00752 
00753       for (Int current_conv_pos =  std::max(0, my_local_pos - from_max_to_left_); c_diff < T_boundary_right; ++current_conv_pos)
00754       {
00755         if (current_conv_pos >= spec_size)
00756         {
00757           break;
00758         }
00759 
00760         c_mz = c_ref[current_conv_pos].getMZ();
00761         c_diff = c_mz + origin;
00762 
00763         //Attention! The +1. has nothing to do with the charge, it is caused by the wavelet's formula (tz1).
00764         current = c_diff > T_boundary_left && c_diff <= T_boundary_right ? IsotopeWavelet::getValueByLambda(my_local_lambda, c_diff * charge + 1.) * c_ref[current_conv_pos].getIntensity() : 0;
00765 
00766         value += current;
00767       }
00768 
00769       c_trans[my_local_pos].setIntensity(value);
00770     }
00771   }
00772 
00773   template <typename PeakType>
00774   void IsotopeWaveletTransform<PeakType>::initializeScan(const MSSpectrum<PeakType>& c_ref, const UInt c)
00775   {
00776     data_length_ = (UInt) c_ref.size();
00777     computeMinSpacing(c_ref);
00778     Int wavelet_length = 0, quarter_length = 0;
00779 
00780     if (hr_data_) //We have to check this separately, because the simply estimation for LowRes data is destroyed by large gaps
00781     {
00782       UInt c_mz_cutoff;
00783       typename MSSpectrum<PeakType>::const_iterator start_iter, end_iter;
00784       for (UInt i = 0; i < data_length_; ++i)
00785       {
00786         c_mz_cutoff =  IsotopeWavelet::getMzPeakCutOffAtMonoPos(c_ref[i].getMZ(), c + 1);
00787         start_iter = c_ref.MZEnd(c_ref[i].getMZ());
00788         end_iter = c_ref.MZBegin(c_ref[i].getMZ() + c_mz_cutoff);
00789         wavelet_length = std::max((SignedSize) wavelet_length, distance(start_iter, end_iter) + 1);
00790         end_iter = c_ref.MZEnd(c_ref[i].getMZ() - Constants::IW_QUARTER_NEUTRON_MASS / DoubleReal(c + 1.));
00791         quarter_length = std::max((SignedSize) quarter_length, distance(end_iter, start_iter) + 1);
00792       }
00793     }
00794     else
00795     {
00796       //CHANGED
00797       max_mz_cutoff_ =  IsotopeWavelet::getMzPeakCutOffAtMonoPos(c_ref[data_length_ - 1].getMZ(), max_charge_);
00798       wavelet_length = (UInt) ceil(max_mz_cutoff_ / min_spacing_);
00799     }
00800     //... done
00801 
00802 
00803     if (wavelet_length > (Int) c_ref.size())
00804     {
00805       std::cout << "Warning: the extremal length of the wavelet is larger (" << wavelet_length << ") than the number of data points (" << c_ref.size() << "). This might (!) severely affect the transform." << std::endl;
00806       std::cout << "Minimal spacing: " << min_spacing_ << std::endl;
00807       std::cout << "Warning/Error generated at scan with RT " << c_ref.getRT() << "." << std::endl;
00808     }
00809 
00810     Int max_index = (UInt) (Constants::IW_QUARTER_NEUTRON_MASS / min_spacing_);
00811     from_max_to_left_ = max_index;
00812     from_max_to_right_ = wavelet_length - 1 - from_max_to_left_;
00813   }
00814 
00815   template <typename PeakType>
00816   void IsotopeWaveletTransform<PeakType>::computeMinSpacing(const MSSpectrum<PeakType>& c_ref)
00817   {
00818     min_spacing_ = INT_MAX;
00819     for (UInt c_conv_pos = 1; c_conv_pos < c_ref.size(); ++c_conv_pos)
00820     {
00821       min_spacing_ = std::min(min_spacing_, c_ref[c_conv_pos].getMZ() - c_ref[c_conv_pos - 1].getMZ());
00822     }
00823   }
00824 
00825 #ifdef OPENMS_HAS_CUDA
00826   template <typename PeakType>
00827   void IsotopeWaveletTransform<PeakType>::finalizeScanCuda()
00828   {
00829     (cudaFree(cuda_device_pos_));
00830     (cudaFree(cuda_device_intens_));
00831     (cudaFree(cuda_device_trans_intens_));
00832     (cudaFree(cuda_device_fwd2_));
00833     (cudaFree(cuda_device_trans_intens_sorted_));
00834     (cudaFree(cuda_device_posindices_sorted_));
00835     (cudaFree(cuda_device_scores_));
00836   }
00837 
00838   template <typename PeakType>
00839   int IsotopeWaveletTransform<PeakType>::initializeScanCuda(const MSSpectrum<PeakType>& scan, const UInt c)
00840   {
00841     data_length_ = scan.size();
00842 
00843     std::vector<float> pre_positions(data_length_), pre_intensities(data_length_);
00844     float c_spacing;
00845     min_spacing_ = INT_MAX;
00846     pre_positions[0] = scan[0].getMZ();
00847     pre_intensities[0] = scan[0].getIntensity();
00848 
00849     for (UInt i = 1; i < data_length_; ++i)
00850     {
00851       pre_positions[i] = scan[i].getMZ();
00852       c_spacing = pre_positions[i] - pre_positions[i - 1];
00853       if (c_spacing < min_spacing_)
00854       {
00855         min_spacing_ = c_spacing;
00856       }
00857       pre_intensities[i] = scan[i].getIntensity();
00858     }
00859     if (min_spacing_ == INT_MAX) //spectrum consists of a single data point
00860     {
00861       std::cout << "Scan consits of a single point. Unable to compute transform." << std::endl;
00862       return Constants::CUDA_INIT_FAIL;
00863     }
00864 
00865     //Estimating the wave_length ...
00866     UInt wavelet_length = 0, quarter_length = 0;
00867     if (hr_data_) //We have to check this separately, because the simply estimation for LowRes data is destroyed by large gaps
00868     {
00869       UInt c_mz_cutoff;
00870       typename MSSpectrum<PeakType>::const_iterator start_iter, end_iter;
00871       for (UInt i = 0; i < data_length_; ++i)
00872       {
00873         c_mz_cutoff =  IsotopeWavelet::getMzPeakCutOffAtMonoPos(scan[i].getMZ(), c + 1);
00874         start_iter = scan.MZEnd(scan[i].getMZ());
00875         end_iter = scan.MZBegin(scan[i].getMZ() + c_mz_cutoff);
00876         wavelet_length = std::max((long int) wavelet_length, distance(start_iter, end_iter) + 1);
00877         end_iter = scan.MZEnd(scan[i].getMZ() - Constants::IW_QUARTER_NEUTRON_MASS / DoubleReal(c + 1.));
00878         quarter_length = std::max((long int) quarter_length, distance(end_iter, start_iter) + 1);
00879       }
00880     }
00881     else
00882     {
00883       //CHANGED
00884       max_mz_cutoff_ =  IsotopeWavelet::getMzPeakCutOffAtMonoPos(scan[data_length_ - 1].getMZ(), max_charge_);
00885       wavelet_length = (UInt) ceil(max_mz_cutoff_ / min_spacing_);
00886     }
00887     //... done
00888 
00889     if (wavelet_length > data_length_ || wavelet_length == 1) //==1, because of 'ceil'
00890     {
00891       std::cout << "Warning: the extremal length of the wavelet is larger (" << wavelet_length << ") than the number of data points (" << data_length_ << "). This might (!) severely affect the transform." << std::endl;
00892       std::cout << "Minimal spacing: " << min_spacing_ << std::endl;
00893       std::cout << "Warning/Error generated at scan with RT " << scan.getRT() << "." << std::endl;
00894     }
00895 
00896     UInt max_index;
00897     if (hr_data_)
00898     {
00899       max_index = quarter_length;
00900     }
00901     else
00902     {
00903       max_index = (UInt) (Constants::IW_QUARTER_NEUTRON_MASS / min_spacing_);
00904     }
00905     from_max_to_left_ = max_index;
00906     from_max_to_right_ = wavelet_length - 1 - from_max_to_left_;
00907 
00908     Int problem_size = Constants::CUDA_BLOCK_SIZE_MAX;
00909     to_load_ = problem_size + from_max_to_left_ + from_max_to_right_;
00910 
00911     UInt missing_points = problem_size - (data_length_ % problem_size);
00912     overall_size_ = wavelet_length - 1 + data_length_ + missing_points;
00913 
00914     num_elements_ = overall_size_;
00915     Int dev_num_elements = 1, tmp = overall_size_ >> 1;
00916 
00917     //Get power of 2 elements (necessary for the sorting algorithm)
00918     while (tmp)
00919     {
00920       dev_num_elements <<= 1;
00921       tmp >>= 1;
00922     }
00923 
00924     if (num_elements_ > dev_num_elements)
00925     {
00926       dev_num_elements <<= 1;
00927     }
00928 
00929     if (dev_num_elements < Constants::CUDA_MIN_SORT_SIZE)
00930     {
00931       dev_num_elements = Constants::CUDA_MIN_SORT_SIZE;
00932     }
00933 
00934     overall_size_ = dev_num_elements;
00935 
00936     cuda_intensities_.resize(overall_size_, 0); cuda_positions_.resize(overall_size_, 0);
00937     //Pad the values to the left; the positions should not matter if the values are zero
00938     float first_pos = pre_positions[0];
00939     for (Int i = 0; i < from_max_to_left_; ++i)
00940     {
00941       cuda_positions_[i] = first_pos - (from_max_to_left_ - i) * min_spacing_;
00942     }
00943 
00944     for (UInt i = 0; i < data_length_; ++i)
00945     {
00946       cuda_positions_[from_max_to_left_ + i] = pre_positions[i];
00947       cuda_intensities_[from_max_to_left_ + i] = pre_intensities[i];
00948     }
00949 
00950     float last_pos = pre_positions[pre_positions.size() - 1];
00951     for (UInt i = 0; i < missing_points + from_max_to_right_ + dev_num_elements - num_elements_; ++i)
00952     {
00953       cuda_positions_[from_max_to_left_ + data_length_ + i] = last_pos + (i + 1) * min_spacing_;
00954     }
00955 
00956 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
00957     std::stringstream name; name << "cuda_input_" << scan.getRT() << ".out\0";
00958     std::fstream outfile(name.str().c_str(), std::ios::out);
00959     for (size_t i = 0; i < overall_size_; ++i)
00960       outfile << cuda_positions_[i] << " " << cuda_intensities_[i] << std::endl;
00961     outfile.close();
00962 #endif
00963 
00964 
00965     dimBlock_ = dim3(Constants::CUDA_BLOCK_SIZE_MAX);
00966     to_compute_ = problem_size;
00967     dimGrid_ = dim3((data_length_ + missing_points) / problem_size);
00968 
00969     (cudaMalloc(&cuda_device_posindices_sorted_, overall_size_ * sizeof(int)));
00970     (cudaMalloc(&cuda_device_pos_, overall_size_ * sizeof(float)));
00971     (cudaMemcpy(cuda_device_pos_, &(cuda_positions_[0]), overall_size_ * sizeof(float), cudaMemcpyHostToDevice));
00972     (cudaMalloc(&cuda_device_intens_, overall_size_ * sizeof(float)));
00973     (cudaMemcpy(cuda_device_intens_, &(cuda_intensities_[0]), overall_size_ * sizeof(float), cudaMemcpyHostToDevice));
00974     (cudaMalloc(&cuda_device_trans_intens_, overall_size_ * sizeof(float)));
00975     (cudaMalloc(&cuda_device_fwd2_, overall_size_ * sizeof(float)));
00976     (cudaMalloc(&cuda_device_trans_intens_sorted_, overall_size_ * sizeof(float)));
00977 
00978     c_sorted_candidate_.resize(overall_size_);
00979     scores_.resize(data_length_);
00980     zeros_.resize(overall_size_);
00981     memset(&zeros_[0], 0., overall_size_ * sizeof(float));
00982 
00983     (cudaMalloc(&cuda_device_scores_, overall_size_ * sizeof(float)));
00984 
00985     return Constants::CUDA_INIT_SUCCESS;
00986   }
00987 
00988   template <typename PeakType>
00989   void IsotopeWaveletTransform<PeakType>::getTransformCuda(TransSpectrum& c_trans, const UInt c)
00990   {
00991 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
00992     std::cout << "res in vector" << std::endl;
00993     std::vector<float> res(overall_size_, 0);
00994 #endif
00995     (cudaMemcpy(cuda_device_trans_intens_, &zeros_[0], overall_size_ * sizeof(float), cudaMemcpyHostToDevice));
00996 
00997     (cudaMemcpy(cuda_device_fwd2_, &zeros_[0], overall_size_ * sizeof(float), cudaMemcpyHostToDevice));
00998     getExternalCudaTransforms(dimGrid_, dimBlock_, (float*)cuda_device_pos_, (float*)cuda_device_intens_, from_max_to_left_, from_max_to_right_, (float*)cuda_device_trans_intens_,
00999                               c + 1, to_load_, to_compute_, data_length_, (float*)cuda_device_fwd2_, hr_data_);
01000 
01001     (cudaMemcpy(cuda_device_trans_intens_sorted_, cuda_device_fwd2_, overall_size_ * sizeof(float), cudaMemcpyDeviceToDevice));
01002 
01003     (cudaMemcpy(&((*c_trans.trans_intens_)[0]), (float*)cuda_device_trans_intens_ + from_max_to_left_, data_length_ * sizeof(float), cudaMemcpyDeviceToHost));
01004 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01005     (cudaMemcpy(&(res[0]), (float*)cuda_device_trans_intens_ + from_max_to_left_, data_length_ * sizeof(float), cudaMemcpyDeviceToHost));
01006     for (UInt i = 0; i < data_length_; ++i)
01007     {
01008       c_trans.setTransIntensity(i, res[i]);
01009     }
01010 #endif
01011   }
01012 
01013   template <typename PeakType>
01014   int IsotopeWaveletTransform<PeakType>::sortCuda(MSSpectrum<PeakType>& sorted)
01015   {
01016     (cudaMemcpy(cuda_device_posindices_sorted_, &indices_[0], overall_size_ * sizeof(int), cudaMemcpyHostToDevice));
01017     Int gpu_index = sortOnDevice((float*)cuda_device_trans_intens_sorted_, (int*) cuda_device_posindices_sorted_, overall_size_, 0);
01018 
01019     if (gpu_index < 0) //i.e., there is no positive intensity value at all
01020     {
01021       return gpu_index;
01022     }
01023 
01024     (cudaMemcpy(h_data_, (float*)cuda_device_trans_intens_sorted_ + gpu_index, sizeof(float) * (overall_size_ - gpu_index), cudaMemcpyDeviceToHost));
01025     (cudaMemcpy(h_pos_, (int*)cuda_device_posindices_sorted_ + gpu_index, sizeof(int) * (overall_size_ - gpu_index), cudaMemcpyDeviceToHost));
01026 
01027     for (UInt i = 0; i < (overall_size_ - gpu_index); ++i)
01028     {
01029       sorted[i].setIntensity(h_data_[i]);
01030       sorted[i].setMZ(cuda_positions_[h_pos_[i]]);
01031     }
01032 
01033     return gpu_index;
01034   }
01035 
01036   template <typename PeakType>
01037   void IsotopeWaveletTransform<PeakType>::identifyChargeCuda(const TransSpectrum& candidates,
01038                                                              const UInt scan_index, const UInt c, const DoubleReal ampl_cutoff, const bool check_PPMs)
01039   {
01040     const MSSpectrum<PeakType>& ref(*candidates.getRefSpectrum());
01041     UInt index, MZ_start, MZ_end;
01042     typename MSSpectrum<PeakType>::iterator iter, bound_iter;
01043     typename MSSpectrum<PeakType>::const_iterator iter_start, iter_end, iter_p, iter2, seed_iter;
01044     DoubleReal mz_cutoff, seed_mz, c_av_intens = 0, c_score = 0, c_sd_intens = 0, threshold = 0, help_mz;
01045 
01046     Int gpu_index = sortCuda(c_sorted_candidate_), c_index;
01047     if (gpu_index < 0) //the transform produced non-exploitable data
01048     {
01049       return;
01050     }
01051 
01052     std::vector<UInt> processed(data_length_, 0);
01053     if (ampl_cutoff < 0)
01054     {
01055       threshold = 0;
01056     }
01057     else
01058     {
01059       c_av_intens = getAvIntens_(candidates);
01060       c_sd_intens = getSdIntens_(candidates, c_av_intens);
01061       threshold = ampl_cutoff * c_sd_intens + c_av_intens;
01062     }
01063 
01064     Int num_of_scores = overall_size_ - gpu_index;
01065 
01066     (cudaMemcpy(cuda_device_scores_, &zeros_[0], num_of_scores * sizeof(float), cudaMemcpyHostToDevice));
01067 
01068     scoreOnDevice((int*)cuda_device_posindices_sorted_, (float*)cuda_device_trans_intens_, (float*)cuda_device_pos_, (float*)cuda_device_scores_,
01069                   c, num_of_scores, overall_size_, max_num_peaks_per_pattern_, threshold);
01070 
01071     (cudaMemcpy(&scores_[0], cuda_device_scores_, num_of_scores * sizeof(float), cudaMemcpyDeviceToHost));
01072 
01073     std::vector<float>::iterator score_iter;
01074 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01075     std::stringstream stream;
01076     stream << "sorted_gpu_" << candidates.getRT() << "_" << c + 1 << ".trans\0";
01077     std::ofstream ofile(stream.str().c_str());
01078     for (c_index = overall_size_ - gpu_index - 1, score_iter = scores_.begin() + num_of_scores - 1; c_index >= 0; --c_index, --score_iter)
01079     {
01080       ofile << c_sorted_candidate_[c_index].getMZ() << "\t" << c_sorted_candidate_[c_index].getIntensity() << "\t" << *score_iter << std::endl;
01081     }
01082     ofile.close();
01083 #endif
01084 
01085     for (c_index = overall_size_ - gpu_index - 1, score_iter = scores_.begin() + num_of_scores - 1; c_index >= 0; --c_index, --score_iter)
01086     {
01087       seed_mz = c_sorted_candidate_[c_index].getMZ();
01088 
01089       //We can replace the following two lines ...
01090       //seed_iter = ref.MZBegin(seed_mz);
01091       //index = distance(ref.begin(), seed_iter);
01092       //... with:
01093       index = h_pos_[c_index] - from_max_to_left_;
01094       seed_iter = ref.begin() + index;
01095 
01096       if (seed_iter == ref.end() || processed[distance(ref.begin(), seed_iter)] || index <= 0)
01097       {
01098         continue;
01099       }
01100 
01101       mz_cutoff = IsotopeWavelet::getMzPeakCutOffAtMonoPos(seed_mz, c + 1);
01102       //Mark the region as processed
01103       //Do not move this further down, since we have to mark this as processed in any case,
01104       //even when score <=0; otherwise we would look around the maximum's position unless
01105       //any significant point is found
01106       iter_start = ref.MZBegin(ref.begin(), seed_mz - Constants::IW_QUARTER_NEUTRON_MASS / (c + 1.), seed_iter);
01107       iter_end = ref.MZEnd(seed_iter, seed_mz + mz_cutoff / (c + 1.), ref.end());
01108 
01109       if (iter_end == ref.end())
01110       {
01111         --iter_end;
01112       }
01113 
01114       MZ_start = distance(ref.begin(), iter_start);
01115       MZ_end = distance(ref.begin(), iter_end);
01116 
01117       memset(&(processed[MZ_start]), 1, sizeof(UInt) * (MZ_end - MZ_start + 1));
01118 
01119       c_score = *score_iter;
01120 
01121       if (c_score <= 0 && c_score != -1000)
01122       {
01123         continue;
01124       }
01125 
01126       //Push the seed into its corresponding box (or create a new one, if necessary)
01127       //Do ***NOT*** move this further down!
01128 
01129       push2TmpBox_(seed_mz, scan_index, c, c_score, c_sorted_candidate_[c_index].getIntensity(), ref.getRT(), MZ_start, MZ_end);
01130 
01131       //Push neighboring peaks to compute finally a derivative over the isotope pattern envelope
01132       help_mz = seed_mz - Constants::IW_NEUTRON_MASS / (c + 1.);
01133       iter2 = candidates.MZBegin(help_mz);
01134 
01135       if (iter2 == candidates.end() || iter2 == candidates.begin())
01136       {
01137         continue;
01138       }
01139 
01140       if (fabs(iter2->getMZ() - seed_mz) > 0.5 * Constants::IW_NEUTRON_MASS / (c + 1.))
01141       {
01142         //In the other case, we are too close to the peak, leading to incorrect derivatives.
01143         if (iter2 != candidates.end())
01144         {
01145           UInt dist = distance(candidates.begin(), iter2);
01146           push2TmpBox_(iter2->getMZ(), scan_index, c, 0,
01147                        getLinearInterpolation((iter2 - 1)->getMZ(), candidates.getTransIntensity(dist - 1), help_mz, iter2->getMZ(), candidates.getTransIntensity(dist)),
01148                        candidates.getRT(), MZ_start, MZ_end);
01149         }
01150       }
01151 
01152       help_mz = seed_mz + Constants::IW_NEUTRON_MASS / (c + 1.);
01153       iter2 = candidates.MZBegin(help_mz);
01154 
01155       if (iter2 == candidates.end() || iter2 == candidates.begin())
01156       {
01157         continue;
01158       }
01159 
01160       if (fabs(iter2->getMZ() - seed_mz) > 0.5 * Constants::IW_NEUTRON_MASS / (c + 1.))
01161       {
01162         //In the other case, we are too close to the peak, leading to incorrect derivatives.
01163         if (iter2 != candidates.end())
01164         {
01165           UInt dist = distance(candidates.begin(), iter2);
01166           push2TmpBox_(iter2->getMZ(), scan_index, c, 0,
01167                        getLinearInterpolation((iter2 - 1)->getMZ(), candidates.getTransIntensity(dist - 1), help_mz, iter2->getMZ(), candidates.getTransIntensity(dist)),
01168                        candidates.getRT(), MZ_start, MZ_end);
01169         }
01170       }
01171     }
01172 
01173     clusterSeeds_(candidates, ref, scan_index, c, check_PPMs);
01174   }
01175 
01176 #endif
01177 
01178 
01179   template <typename PeakType>
01180   void IsotopeWaveletTransform<PeakType>::identifyCharge(const MSSpectrum<PeakType>& candidates,
01181                                                          const MSSpectrum<PeakType>& ref, const UInt scan_index, const UInt c, const DoubleReal ampl_cutoff, const bool check_PPMs)
01182   {
01183     Size scan_size(candidates.size());
01184     typename ConstRefVector<MSSpectrum<PeakType> >::iterator iter;
01185     typename MSSpectrum<PeakType>::const_iterator iter_start, iter_end, iter_p, seed_iter, iter2;
01186     DoubleReal mz_cutoff, seed_mz, c_av_intens = 0, c_score = 0, c_sd_intens = 0, threshold = 0, help_mz, share, share_pos, bwd, fwd;
01187     UInt MZ_start, MZ_end;
01188 
01189     MSSpectrum<PeakType> diffed(candidates);
01190     diffed[0].setIntensity(0); diffed[scan_size - 1].setIntensity(0);
01191 
01192 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01193     std::stringstream stream;
01194     stream << "diffed_" << ref.getRT() << "_" << c + 1 << ".trans\0";
01195     std::ofstream ofile(stream.str().c_str());
01196 #endif
01197 
01198     if (!hr_data_) //LowRes data
01199     {
01200       for (UInt i = 0; i < scan_size - 2; ++i)
01201       {
01202         share = candidates[i + 1].getIntensity(), share_pos = candidates[i + 1].getMZ();
01203         bwd = (share - candidates[i].getIntensity()) / (share_pos - candidates[i].getMZ());
01204         fwd = (candidates[i + 2].getIntensity() - share) / (candidates[i + 2].getMZ() - share_pos);
01205 
01206         if (!(bwd >= 0 && fwd <= 0) || share > ref[i + 1].getIntensity())
01207         {
01208           diffed[i + 1].setIntensity(0);
01209         }
01210 
01211 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01212         ofile << diffed[i + 1].getMZ() << "\t" <<  diffed[i + 1].getIntensity() << std::endl;
01213 #endif
01214       }
01215     }
01216     else //HighRes data
01217     {
01218       for (UInt i = 0; i < scan_size - 2; ++i)
01219       {
01220         share = candidates[i + 1].getIntensity(), share_pos = candidates[i + 1].getMZ();
01221         bwd = (share - candidates[i].getIntensity()) / (share_pos - candidates[i].getMZ());
01222         fwd = (candidates[i + 2].getIntensity() - share) / (candidates[i + 2].getMZ() - share_pos);
01223 
01224         if (!(bwd >= 0 && fwd <= 0))
01225         {
01226           diffed[i + 1].setIntensity(0);
01227         }
01228 
01229 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01230         ofile << diffed[i + 1].getMZ() << "\t" <<  diffed[i + 1].getIntensity() << std::endl;
01231 #endif
01232       }
01233     }
01234 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01235     ofile.close();
01236 #endif
01237 
01238     ConstRefVector<MSSpectrum<PeakType> > c_sorted_candidate_(diffed.begin(), diffed.end());
01239 
01240     //Sort the transform in descending order according to the intensities present in the transform
01241     c_sorted_candidate_.sortByIntensity();
01242 
01243 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01244     std::stringstream stream2;
01245     stream2 << "sorted_cpu_" << candidates.getRT() << "_" << c + 1 << ".trans\0";
01246     std::ofstream ofile2(stream2.str().c_str());
01247     for (iter = c_sorted_candidate_.end() - 1; iter != c_sorted_candidate_.begin(); --iter)
01248     {
01249       ofile2 << iter->getMZ() << "\t" << iter->getIntensity() << std::endl;
01250     }
01251     ofile2.close();
01252 #endif
01253 
01254     std::vector<UInt> processed(scan_size, 0);
01255 
01256     if (ampl_cutoff < 0)
01257     {
01258       threshold = 0;
01259     }
01260     else
01261     {
01262       c_av_intens = getAvIntens_(candidates);
01263       c_sd_intens = getSdIntens_(candidates, c_av_intens);
01264       threshold = ampl_cutoff * c_sd_intens + c_av_intens;
01265     }
01266 
01267     for (iter = c_sorted_candidate_.end() - 1; iter != c_sorted_candidate_.begin(); --iter)
01268     {
01269       if (iter->getIntensity() <= 0)
01270       {
01271         break;
01272       }
01273 
01274       seed_mz = iter->getMZ();
01275       seed_iter = ref.MZBegin(seed_mz);
01276 
01277       if (seed_iter == ref.end() || processed[distance(ref.begin(), seed_iter)])
01278       {
01279         continue;
01280       }
01281 
01282       mz_cutoff = IsotopeWavelet::getMzPeakCutOffAtMonoPos(seed_mz, c + 1);
01283       //Mark the region as processed
01284       //Do not move this further down, since we have to mark this as processed in any case,
01285       //even when score <=0; otherwise we would look around the maximum's position unless
01286       //any significant point is found
01287       iter_start = ref.MZBegin(ref.begin(), seed_mz - Constants::IW_QUARTER_NEUTRON_MASS / (c + 1.), seed_iter);
01288       iter_end = ref.MZEnd(seed_iter, seed_mz + mz_cutoff / (c + 1.), ref.end());
01289       if (iter_end == ref.end())
01290       {
01291         --iter_end;
01292       }
01293 
01294       MZ_start = distance(ref.begin(), iter_start);
01295       MZ_end = distance(ref.begin(), iter_end);
01296 
01297       memset(&(processed[MZ_start]), 1, sizeof(UInt) * (MZ_end - MZ_start + 1));
01298 
01299       c_score = scoreThis_(candidates, IsotopeWavelet::getNumPeakCutOff(seed_mz * (c + 1.)), seed_mz, c, threshold);
01300 
01301 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01302       if (trunc(seed_mz) == 874)
01303         std::cout << seed_mz << "\t" << c_score << std::endl;
01304 #endif
01305 
01306       if (c_score <= 0 && c_score != -1000)
01307       {
01308         continue;
01309       }
01310 
01311       //Push the seed into its corresponding box (or create a new one, if necessary)
01312       //Do ***NOT*** move this further down!
01313       push2TmpBox_(seed_mz, scan_index, c, c_score, iter->getIntensity(), ref.getRT(), MZ_start, MZ_end);
01314 
01315       help_mz = seed_mz - Constants::IW_NEUTRON_MASS / (c + 1.);
01316       iter2 = candidates.MZBegin(help_mz);
01317       if (iter2 == candidates.end() || iter2 == candidates.begin())
01318       {
01319         continue;
01320       }
01321 
01322       if (fabs(iter2->getMZ() - seed_mz) > 0.5 * Constants::IW_NEUTRON_MASS / (c + 1.))
01323       {
01324         //In the other case, we are too close to the peak, leading to incorrect derivatives.
01325         if (iter2 != candidates.end())
01326         {
01327           push2TmpBox_(iter2->getMZ(), scan_index, c, 0, getLinearInterpolation(iter2 - 1, help_mz, iter2), ref.getRT(), MZ_start, MZ_end);
01328         }
01329       }
01330 
01331       help_mz = seed_mz + Constants::IW_NEUTRON_MASS / (c + 1.);
01332       iter2 = candidates.MZBegin(help_mz);
01333       if (iter2 == candidates.end() || iter2 == candidates.begin())
01334       {
01335         continue;
01336       }
01337 
01338       if (fabs(iter2->getMZ() - seed_mz) > 0.5 * Constants::IW_NEUTRON_MASS / (c + 1.))
01339       {
01340         //In the other case, we are too close to the peak, leading to incorrect derivatives.
01341         if (iter2 != candidates.end())
01342         {
01343           push2TmpBox_(iter2->getMZ(), scan_index, c, 0, getLinearInterpolation(iter2 - 1, help_mz, iter2), ref.getRT(), MZ_start, MZ_end);
01344         }
01345       }
01346     }
01347 
01348     clusterSeeds_(candidates, ref, scan_index, c, check_PPMs);
01349   }
01350 
01351 #if defined(OPENMS_HAS_TBB) && defined(OPENMS_HAS_CUDA)
01352   template <typename PeakType>
01353   void IsotopeWaveletTransform<PeakType>::mergeFeatures(IsotopeWaveletTransform<PeakType>* later_iwt, const UInt RT_interleave, const UInt RT_votes_cutoff)
01354   {
01355     typename std::multimap<DoubleReal, Box>::iterator front_iter, end_iter, best_match, help_iter;
01356 
01357     //First of all do the trivial part of the merge
01358     for (end_iter = later_iwt->closed_boxes_.begin(); end_iter != later_iwt->closed_boxes_.end(); ++end_iter)
01359     {
01360       closed_boxes_.insert(*end_iter);
01361     }
01362 
01363     typename std::multimap<DoubleReal, Box>& end_container(this->end_boxes_);
01364     typename std::multimap<DoubleReal, Box>& front_container(later_iwt->front_boxes_);
01365 
01366 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01367     std::cout << "FontBox: " << front_container.size() << std::endl;
01368     for (front_iter = front_container.begin(); front_iter != front_container.end(); ++front_iter)
01369       std::cout << front_iter->first << "\t" << front_iter->second.size() << std::endl;
01370 
01371     std::cout << "EndBox: " << end_container.size() << std::endl;
01372     for (front_iter = end_container.begin(); front_iter != end_container.end(); ++front_iter)
01373       std::cout << front_iter->first << "\t" << front_iter->second.size() << std::endl;
01374 #endif
01375 
01376     typename std::multimap<UInt, BoxElement>::iterator biter;
01377 
01378     DoubleReal best_dist, c_dist; UInt c;
01379     //Now, try to find matching boxes for the rest
01380     for (front_iter = front_container.begin(); front_iter != front_container.end(); )
01381     {
01382       best_match = end_container.end(); best_dist = INT_MAX;
01383       //This is everything else than efficient, but both containers should be very small in size
01384       for (end_iter = end_container.begin(); end_iter != end_container.end(); ++end_iter)
01385       {
01386         c = 0;
01387         for (biter = front_iter->second.begin(); biter != front_iter->second.end(); ++biter)
01388         {
01389           c = std::max(c, biter->second.c);
01390         }
01391 
01392 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01393         std::cout << "Trying to match: " << end_iter->first << " to front " <<  front_iter->first << std::endl;
01394 #endif
01395 
01396         c_dist = fabs(end_iter->first - front_iter->first);
01397         if (c_dist < Constants::IW_HALF_NEUTRON_MASS / (c + 1.) && c_dist < best_dist)
01398         {
01399 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01400           std::cout << "best match " << front_iter->second.begin()->first << "\t" << (--(end_iter->second.end()))->first << std::endl;
01401 #endif
01402           if ((front_iter->second.begin()->first - (--(end_iter->second.end()))->first) <= RT_interleave + 1)
01403           {
01404             //otherwise, there are too many blank scans in between
01405             best_match = end_iter;
01406             best_dist = c_dist;
01407           }
01408         }
01409       }
01410       if (best_match == end_container.end()) //No matching pair found
01411       {
01412         if (front_iter->second.size() >= RT_votes_cutoff)
01413         {
01414           closed_boxes_.insert(*front_iter);
01415           //extendBox_ (map, front_iter->second);
01416         }
01417         ++front_iter;
01418       }
01419       else //That's the funny part
01420       {
01421 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01422         std::cout << "Merging the boxes: " << front_iter->first  << "\t" << best_match->first << std::endl;
01423 #endif
01424 
01425         front_iter->second.insert(best_match->second.begin(), best_match->second.end());
01426         Box replacement(front_iter->second);
01427 
01428         //We cannot divide both m/z by 2, since we already inserted some m/zs whose weight would be lowered.
01429         DoubleReal c_mz = front_iter->first * (front_iter->second.size() - best_match->second.size()) + best_match->first * best_match->second.size();
01430         c_mz /= ((DoubleReal) (front_iter->second.size()));
01431 
01432         help_iter = front_iter;
01433         ++help_iter;
01434         std::pair<DoubleReal, std::multimap<UInt, BoxElement> > help3(c_mz, replacement);
01435         closed_boxes_.insert(help3);
01436         //extendBox_ (map, help3.second);
01437         front_container.erase(front_iter);
01438         end_container.erase(best_match);
01439         front_iter = help_iter;
01440       }
01441     }
01442 
01443     //Merge the rest in end_container
01444     for (end_iter = end_container.begin(); end_iter != end_container.end(); ++end_iter)
01445     {
01446       if (end_iter->second.size() >= RT_votes_cutoff)
01447       {
01448         closed_boxes_.insert(*end_iter);
01449         //extendBox_ (map, end_iter->second);
01450       }
01451     }
01452   }
01453 
01454 #endif
01455 
01456 
01457   template <typename PeakType>
01458   DoubleReal IsotopeWaveletTransform<PeakType>::scoreThis_(const MSSpectrum<PeakType>& candidate,
01459                                                            const UInt peak_cutoff, const DoubleReal seed_mz, const UInt c, const DoubleReal ampl_cutoff)
01460   {
01461     DoubleReal c_score = 0, c_val;
01462     typename MSSpectrum<PeakType>::const_iterator c_left_iter2, c_right_iter2;
01463     Int signal_size((Int)candidate.size());
01464     //in the very unlikely case that size_t will not fit to int anymore this will be a problem of course
01465     //for the sake of simplicity (we need here a signed int) we do not cast at every following comparison individually
01466 
01467     //p_h_ind indicates if we are looking for a whole or a peak
01468     Int p_h_ind = 1, end = 4 * (peak_cutoff - 1) - 1; //4 times and not 2 times, since we move by 0.5 m/z entities
01469 
01470     std::vector<DoubleReal> positions(end);
01471     for (Int i = 0; i < end; ++i)
01472     {
01473       positions[i] =  seed_mz - ((peak_cutoff - 1) * Constants::IW_NEUTRON_MASS - (i + 1) * Constants::IW_HALF_NEUTRON_MASS) / ((DoubleReal)c + 1);
01474     }
01475 
01476     DoubleReal l_score = 0, mid_val = 0;
01477     Int start_index = distance(candidate.begin(), candidate.MZBegin(positions[0])) - 1;
01478     for (Int v = 1; v <= end; ++v, ++p_h_ind)
01479     {
01480       do
01481       {
01482         if (start_index < signal_size - 1)
01483           ++start_index;
01484         else
01485           break;
01486       }
01487       while (candidate[start_index].getMZ() < positions[v - 1]);
01488 
01489       if (start_index <= 0 || start_index >= signal_size - 1) //unable to interpolate
01490       {
01491         continue;
01492       }
01493 
01494       c_left_iter2 = candidate.begin() + start_index - 1;
01495       c_right_iter2 = c_left_iter2 + 1;
01496 
01497       c_val = c_left_iter2->getIntensity() + (c_right_iter2->getIntensity() - c_left_iter2->getIntensity()) / (c_right_iter2->getMZ() - c_left_iter2->getMZ()) * (positions[v - 1] - c_left_iter2->getMZ());
01498 
01499       if (v == (int)(ceil(end / 2.)))
01500       {
01501         l_score = c_score;
01502         mid_val = c_val;
01503       }
01504 
01505       if (p_h_ind % 2 == 1) //I.e. a whole
01506       {
01507         c_score -= c_val;
01508 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01509         if (trunc(seed_mz) == 874)
01510           std::cout << -c_val << std::endl;
01511 #endif
01512       }
01513       else
01514       {
01515         c_score += c_val;
01516 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01517         if (trunc(seed_mz) == 874)
01518           std::cout << c_val << std::endl;
01519 #endif
01520       }
01521 
01522 
01523       start_index = distance(candidate.begin(), c_left_iter2);
01524     }
01525 
01526 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01527     std::ofstream ofile_score("scores.dat", ios::app);
01528     std::ofstream ofile_check_score("check_scores.dat", ios::app);
01529     ofile_score.close();
01530     ofile_check_score.close();
01531 #endif
01532 
01533 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01534     if (trunc(seed_mz) == 874)
01535       std::cout << "final_score: " <<  seed_mz << "\t" << c_score << "\t l_score: " << l_score << "\t" << c_score - l_score - mid_val << "\t" <<  c_score - mid_val << "\t" << ampl_cutoff << std::endl;
01536 #endif
01537 
01538     if (c_score - mid_val <= 0)
01539     {
01540       return 0;
01541     }
01542 
01543     if (c_score - mid_val <= ampl_cutoff)
01544     {
01545       return -1000;
01546     }
01547 
01548     if (l_score <= 0 || c_score - l_score - mid_val <= 0)
01549     {
01550       return 0;
01551     }
01552 
01553     return c_score;
01554   }
01555 
01556   template <typename PeakType>
01557   DoubleReal IsotopeWaveletTransform<PeakType>::scoreThis_(const TransSpectrum& candidate,
01558                                                            const UInt peak_cutoff, const DoubleReal seed_mz, const UInt c, const DoubleReal ampl_cutoff)
01559   {
01560     DoubleReal c_score = 0, c_val;
01561     typename MSSpectrum<PeakType>::const_iterator c_left_iter2, c_right_iter2;
01562     Int signal_size((Int)candidate.size());
01563 
01564     //p_h_ind indicates if we are looking for a whole or a peak
01565     Int p_h_ind = 1, end = 4 * (peak_cutoff - 1) - 1; //4 times and not 2 times, since we move by 0.5 m/z entities
01566 
01567     std::vector<DoubleReal> positions(end);
01568     for (Int i = 0; i < end; ++i)
01569     {
01570       positions[i] =  seed_mz - ((peak_cutoff - 1) * Constants::IW_NEUTRON_MASS - (i + 1) * Constants::IW_HALF_NEUTRON_MASS) / ((DoubleReal)c + 1);
01571     }
01572 
01573     DoubleReal l_score = 0, mid_val = 0;
01574     Int start_index = distance(candidate.begin(), candidate.MZBegin(positions[0])) - 1;
01575     for (Int v = 1; v <= end; ++v, ++p_h_ind)
01576     {
01577       do
01578       {
01579         if (start_index < signal_size - 1)
01580           ++start_index;
01581         else
01582           break;
01583       }
01584       while (candidate.getMZ(start_index) < positions[v - 1]);
01585 
01586       if (start_index <= 0 || start_index >= signal_size - 1) //unable to interpolate
01587       {
01588         continue;
01589       }
01590 
01591       c_left_iter2 = candidate.begin() + start_index - 1;
01592       c_right_iter2 = c_left_iter2 + 1;
01593 
01594       c_val = candidate.getTransIntensity(start_index - 1) + (candidate.getTransIntensity(start_index) - candidate.getTransIntensity(start_index - 1)) / (c_right_iter2->getMZ() - c_left_iter2->getMZ()) * (positions[v - 1] - c_left_iter2->getMZ());
01595       if (v == (int)(ceil(end / 2.)))
01596       {
01597         l_score = c_score;
01598         mid_val = c_val;
01599       }
01600 
01601       if (p_h_ind % 2 == 1) //I.e. a whole
01602       {
01603         c_score -= c_val;
01604       }
01605       else
01606       {
01607         c_score += c_val;
01608       }
01609 
01610       start_index = distance(candidate.begin(), c_left_iter2);
01611     }
01612 
01613 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01614     std::ofstream ofile_score("scores.dat", ios::app);
01615     std::ofstream ofile_check_score("check_scores.dat", ios::app);
01616     ofile_score << c_check_point << "\t" << c_score << std::endl;
01617     ofile_score.close();
01618     ofile_check_score.close();
01619 #endif
01620 
01621     if (l_score <= 0 || c_score - l_score - mid_val <= 0 || c_score - mid_val <= ampl_cutoff)
01622     {
01623       return 0;
01624     }
01625 
01626     return c_score;
01627   }
01628 
01629   template <typename PeakType>
01630   void IsotopeWaveletTransform<PeakType>::clusterSeeds_(const MSSpectrum<PeakType>& candidate,
01631                                                         const MSSpectrum<PeakType>& ref, const UInt scan_index, const UInt c, const bool check_PPMs)
01632   {
01633     typename std::multimap<DoubleReal, Box>::iterator iter;
01634     typename Box::iterator box_iter;
01635     std::vector<BoxElement> final_box;
01636     DoubleReal c_mz, av_score = 0, av_mz = 0, av_intens = 0, av_abs_intens = 0, count = 0;
01637     DoubleReal virtual_av_mz = 0, virtual_av_intens = 0, virtual_av_abs_intens = 0, virtual_count = 0;
01638 
01639     typename std::pair<DoubleReal, DoubleReal> c_extend;
01640     for (iter = tmp_boxes_->at(c).begin(); iter != tmp_boxes_->at(c).end(); ++iter)
01641     {
01642 
01643       Box& c_box = iter->second;
01644       av_score = 0, av_mz = 0, av_intens = 0, av_abs_intens = 0, count = 0;
01645       virtual_av_mz = 0, virtual_av_intens = 0, virtual_av_abs_intens = 0, virtual_count = 0;
01646 
01647       //Now, let's get the RT boundaries for the box
01648       for (box_iter = c_box.begin(); box_iter != c_box.end(); ++box_iter)
01649       {
01650         if (box_iter->second.score == 0) //virtual helping point
01651         {
01652           if (count != 0)
01653             continue; //it is in any way not pure virtual
01654 
01655           c_mz = box_iter->second.mz;
01656           virtual_av_intens += box_iter->second.intens;
01657           virtual_av_abs_intens += fabs(box_iter->second.intens);
01658           virtual_av_mz += c_mz * fabs(box_iter->second.intens);
01659           ++virtual_count;
01660         }
01661         else
01662         {
01663           c_mz = box_iter->second.mz;
01664           av_score += box_iter->second.score;
01665           av_intens += box_iter->second.intens;
01666           av_abs_intens += fabs(box_iter->second.intens);
01667           av_mz += c_mz * fabs(box_iter->second.intens);
01668           ++count;
01669         }
01670       }
01671 
01672       if (count == 0) //pure virtual helping box
01673       {
01674         av_intens = virtual_av_intens / virtual_count;
01675         av_score = 0;
01676         av_mz = virtual_av_mz / virtual_av_abs_intens;
01677       }
01678       else
01679       {
01680         av_intens /= count;
01681         av_score /= count;
01682         av_mz /= av_abs_intens;
01683       }
01684 
01685       BoxElement c_box_element;
01686       c_box_element.mz = av_mz;
01687       c_box_element.c = c;
01688       c_box_element.score = av_score;
01689       c_box_element.intens = av_intens;
01690 
01691       c_box_element.RT = c_box.begin()->second.RT;
01692       final_box.push_back(c_box_element);
01693     }
01694 
01695     Size num_o_feature = final_box.size();
01696     if (num_o_feature == 0)
01697     {
01698       tmp_boxes_->at(c).clear();
01699       return;
01700     }
01701 
01702     //Computing the derivatives
01703     std::vector<DoubleReal> bwd_diffs(num_o_feature, 0);
01704 
01705     bwd_diffs[0] = 0;
01706     for (Size i = 1; i < num_o_feature; ++i)
01707     {
01708       bwd_diffs[i] = (final_box[i].intens - final_box[i - 1].intens) / (final_box[i].mz - final_box[i - 1].mz);
01709     }
01710 
01711 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
01712     std::ofstream ofile_bwd("bwd_cpu.dat");
01713     for (Size i = 0; i < num_o_feature; ++i)
01714     {
01715       ofile_bwd << final_box[i].mz << "\t" << bwd_diffs[i] << std::endl;
01716     }
01717     ofile_bwd.close();
01718 #endif
01719 
01720 
01721     for (Size i = 0; i < num_o_feature - 1; ++i)
01722     {
01723       while (i < num_o_feature - 2)
01724       {
01725         if (final_box[i].score > 0 || final_box[i].score == -1000) //this has been an helping point
01726           break;
01727         ++i;
01728       }
01729 
01730       if (bwd_diffs[i] > 0 && bwd_diffs[i + 1] < 0)
01731       {
01732         checkPositionForPlausibility_(candidate, ref, final_box[i].mz, final_box[i].c, scan_index, check_PPMs, final_box[i].intens, final_box[i].score);
01733         continue;
01734       }
01735     }
01736 
01737     tmp_boxes_->at(c).clear();
01738   }
01739 
01740   template <typename PeakType>
01741   DoubleReal IsotopeWaveletTransform<PeakType>::getAvIntens_(const MSSpectrum<PeakType>& scan)
01742   {
01743     DoubleReal av_intens = 0;
01744     for (UInt i = 0; i < scan.size(); ++i)
01745     {
01746       if (scan[i].getIntensity() >= 0)
01747       {
01748         av_intens += scan[i].getIntensity();
01749       }
01750     }
01751     return av_intens / (double)scan.size();
01752   }
01753 
01754   template <typename PeakType>
01755   DoubleReal IsotopeWaveletTransform<PeakType>::getSdIntens_(const MSSpectrum<PeakType>& scan, const DoubleReal mean)
01756   {
01757     DoubleReal res = 0, intens;
01758     for (UInt i = 0; i < scan.size(); ++i)
01759     {
01760       if (scan[i].getIntensity() >= 0)
01761       {
01762         intens = scan[i].getIntensity();
01763         res += (intens - mean) * (intens - mean);
01764       }
01765     }
01766     return sqrt(res / (double)(scan.size() - 1));
01767   }
01768 
01769   template <typename PeakType>
01770   DoubleReal IsotopeWaveletTransform<PeakType>::getAvMZSpacing_(const MSSpectrum<PeakType>& scan) //, Int start_index, Int end_index)
01771   {
01772     std::vector<DoubleReal> diffs(scan.size() - 1, 0);
01773     for (UInt i = 0; i < scan.size() - 1; ++i)
01774     {
01775       diffs[i] = scan[i + 1].getMZ() - scan[i].getMZ();
01776     }
01777 
01778     sort(diffs.begin(), diffs.end());
01779     DoubleReal av_MZ_spacing = 0;
01780     for (UInt i = 0; i < diffs.size() / 2; ++i)
01781     {
01782       av_MZ_spacing += diffs[i];
01783     }
01784 
01785     return av_MZ_spacing / (diffs.size() / 2);
01786   }
01787 
01788   template <typename PeakType>
01789   DoubleReal IsotopeWaveletTransform<PeakType>::getAvIntens_(const TransSpectrum& scan)
01790   {
01791     DoubleReal av_intens = 0;
01792     for (UInt i = 0; i < scan.size(); ++i)
01793     {
01794       if (scan.getTransIntensity(i) >= 0)
01795       {
01796         av_intens += scan.getTransIntensity(i);
01797       }
01798     }
01799     return av_intens / (double)scan.size();
01800   }
01801 
01802   template <typename PeakType>
01803   DoubleReal IsotopeWaveletTransform<PeakType>::getSdIntens_(const TransSpectrum& scan, const DoubleReal mean)
01804   {
01805     DoubleReal res = 0, intens;
01806     for (UInt i = 0; i < scan.size(); ++i)
01807     {
01808       if (scan.getTransIntensity(i) >= 0)
01809       {
01810         intens = scan.getTransIntensity(i);
01811         res += (intens - mean) * (intens - mean);
01812       }
01813     }
01814     return sqrt(res / (double)(scan.size() - 1));
01815   }
01816 
01817   template <typename PeakType>
01818   void IsotopeWaveletTransform<PeakType>::push2Box_(const DoubleReal mz, const UInt scan, UInt c,
01819                                                     const DoubleReal score, const DoubleReal intens, const DoubleReal rt, const UInt MZ_begin, const UInt MZ_end, DoubleReal ref_intens)
01820   {
01821     const DoubleReal dist_constraint(Constants::IW_HALF_NEUTRON_MASS / (DoubleReal)max_charge_);
01822 
01823     typename std::multimap<DoubleReal, Box>::iterator upper_iter(open_boxes_.upper_bound(mz));
01824     typename std::multimap<DoubleReal, Box>::iterator lower_iter(open_boxes_.lower_bound(mz));
01825 
01826     if (lower_iter != open_boxes_.end())
01827     {
01828       //Ugly, but necessary due to the implementation of STL lower_bound
01829       if (mz != lower_iter->first && lower_iter != open_boxes_.begin())
01830       {
01831         --lower_iter;
01832       }
01833     }
01834 
01835     typename std::multimap<DoubleReal, Box>::iterator insert_iter;
01836     bool create_new_box = true;
01837     if (lower_iter == open_boxes_.end()) //I.e. there is no open Box for that mz position
01838     {
01839       //There is another special case to be considered here:
01840       //Assume that the current box contains only a single element that is (slightly) smaller than the new mz value,
01841       //then the lower bound for the new mz value is box.end and this would usually force a new entry
01842       if (!open_boxes_.empty())
01843       {
01844         if (fabs((--lower_iter)->first - mz) < dist_constraint) //matching box
01845         {
01846           create_new_box = false;
01847           insert_iter = lower_iter;
01848         }
01849       }
01850       else
01851       {
01852         create_new_box = true;
01853       }
01854     }
01855     else
01856     {
01857       if (upper_iter == open_boxes_.end() && fabs(lower_iter->first - mz) < dist_constraint) //Found matching Box
01858       {
01859         insert_iter = lower_iter;
01860         create_new_box = false;
01861       }
01862       else
01863       {
01864         create_new_box = true;
01865       }
01866     }
01867 
01868 
01869     if (upper_iter != open_boxes_.end() && lower_iter != open_boxes_.end())
01870     {
01871       //Here is the question if you should figure out the smallest charge .... and then
01872 
01873       //Figure out which entry is closer to m/z
01874       DoubleReal dist_lower = fabs(lower_iter->first - mz);
01875       DoubleReal dist_upper = fabs(upper_iter->first - mz);
01876       dist_lower = (dist_lower < dist_constraint) ? dist_lower : INT_MAX;
01877       dist_upper = (dist_upper < dist_constraint) ? dist_upper : INT_MAX;
01878 
01879       if (dist_lower >= dist_constraint && dist_upper >= dist_constraint) // they are both too far away
01880       {
01881         create_new_box = true;
01882       }
01883       else
01884       {
01885         insert_iter = (dist_lower < dist_upper) ? lower_iter : upper_iter;
01886         create_new_box = false;
01887       }
01888     }
01889 
01890     BoxElement element;
01891     element.c = c; element.mz = mz; element.score = score; element.RT = rt; element.intens = intens; element.ref_intens = ref_intens;
01892     element.RT_index = scan; element.MZ_begin = MZ_begin; element.MZ_end = MZ_end;
01893 
01894 
01895     if (create_new_box == false)
01896     {
01897       std::pair<UInt, BoxElement> help2(scan, element);
01898       insert_iter->second.insert(help2);
01899 
01900       //Unfortunately, we need to change the m/z key to the average of all keys inserted in that box.
01901       Box replacement(insert_iter->second);
01902 
01903       //We cannot divide both m/z by 2, since we already inserted some m/zs whose weight would be lowered.
01904       //Also note that we already inserted the new entry, leading to size-1.
01905       DoubleReal c_mz = insert_iter->first * (insert_iter->second.size() - 1) + mz;
01906       c_mz /= ((DoubleReal) insert_iter->second.size());
01907 
01908       //Now let's remove the old and insert the new one
01909       open_boxes_.erase(insert_iter);
01910       std::pair<DoubleReal, std::multimap<UInt, BoxElement> > help3(c_mz, replacement);
01911       open_boxes_.insert(help3);
01912     }
01913     else
01914     {
01915       std::pair<UInt, BoxElement> help2(scan, element);
01916       std::multimap<UInt, BoxElement> help3;
01917       help3.insert(help2);
01918       std::pair<DoubleReal, std::multimap<UInt, BoxElement> > help4(mz, help3);
01919       open_boxes_.insert(help4);
01920     }
01921   }
01922 
01923   template <typename PeakType>
01924   void IsotopeWaveletTransform<PeakType>::push2TmpBox_(const DoubleReal mz, const UInt scan, UInt c,
01925                                                        const DoubleReal score, const DoubleReal intens, const DoubleReal rt, const UInt MZ_begin, const UInt MZ_end)
01926   {
01927     const DoubleReal dist_constraint(Constants::IW_HALF_NEUTRON_MASS / (DoubleReal)max_charge_);
01928 
01929     std::multimap<DoubleReal, Box>& tmp_box(tmp_boxes_->at(c));
01930     typename std::multimap<DoubleReal, Box>::iterator upper_iter(tmp_box.upper_bound(mz));
01931     typename std::multimap<DoubleReal, Box>::iterator lower_iter(tmp_box.lower_bound(mz));
01932 
01933     if (lower_iter != tmp_box.end())
01934     {
01935       //Ugly, but necessary due to the implementation of STL lower_bound
01936       if (mz != lower_iter->first && lower_iter != tmp_box.begin())
01937       {
01938         --lower_iter;
01939       }
01940     }
01941 
01942     typename std::multimap<DoubleReal, Box>::iterator insert_iter;
01943     bool create_new_box = true;
01944     if (lower_iter == tmp_box.end()) //I.e. there is no tmp Box for that mz position
01945     {
01946       //There is another special case to be considered here:
01947       //Assume that the current box contains only a single element that is (slightly) smaller than the new mz value,
01948       //then the lower bound for the new mz value is box.end and this would usually force a new entry
01949       if (!tmp_box.empty())
01950       {
01951         if (fabs((--lower_iter)->first - mz) < dist_constraint) //matching box
01952         {
01953           create_new_box = false;
01954           insert_iter = lower_iter;
01955         }
01956       }
01957       else
01958       {
01959         create_new_box = true;
01960       }
01961     }
01962     else
01963     {
01964       if (upper_iter == tmp_box.end() && fabs(lower_iter->first - mz) < dist_constraint) //Found matching Box
01965       {
01966         insert_iter = lower_iter;
01967         create_new_box = false;
01968       }
01969       else
01970       {
01971         create_new_box = true;
01972       }
01973     }
01974 
01975 
01976     if (upper_iter != tmp_box.end() && lower_iter != tmp_box.end())
01977     {
01978       //Figure out which entry is closer to m/z
01979       DoubleReal dist_lower = fabs(lower_iter->first - mz);
01980       DoubleReal dist_upper = fabs(upper_iter->first - mz);
01981       dist_lower = (dist_lower < dist_constraint) ? dist_lower : INT_MAX;
01982       dist_upper = (dist_upper < dist_constraint) ? dist_upper : INT_MAX;
01983 
01984       if (dist_lower >= dist_constraint && dist_upper >= dist_constraint) // they are both too far away
01985       {
01986         create_new_box = true;
01987       }
01988       else
01989       {
01990         insert_iter = (dist_lower < dist_upper) ? lower_iter : upper_iter;
01991         create_new_box = false;
01992       }
01993     }
01994 
01995     BoxElement element;
01996     element.c = c; element.mz = mz; element.score = score; element.RT = rt; element.intens = intens; element.ref_intens = -1000;
01997     element.RT_index = scan; element.MZ_begin = MZ_begin; element.MZ_end = MZ_end;
01998 
01999     if (create_new_box == false)
02000     {
02001       std::pair<UInt, BoxElement> help2(scan, element);
02002       insert_iter->second.insert(help2);
02003 
02004       //Unfortunately, we need to change the m/z key to the average of all keys inserted in that box.
02005       Box replacement(insert_iter->second);
02006 
02007       //We cannot divide both m/z by 2, since we already inserted some m/zs whose weight would be lowered.
02008       //Also note that we already inserted the new entry, leading to size-1.
02009       DoubleReal c_mz = insert_iter->first * (insert_iter->second.size() - 1) + mz;
02010       c_mz /= ((DoubleReal) insert_iter->second.size());
02011 
02012       //Now let's remove the old and insert the new one
02013       tmp_box.erase(insert_iter);
02014       std::pair<DoubleReal, std::multimap<UInt, BoxElement> > help3(c_mz, replacement);
02015       tmp_box.insert(help3);
02016     }
02017     else
02018     {
02019       std::pair<UInt, BoxElement> help2(scan, element);
02020       std::multimap<UInt, BoxElement> help3;
02021       help3.insert(help2);
02022 
02023       std::pair<DoubleReal, std::multimap<UInt, BoxElement> > help4(mz, help3);
02024       tmp_box.insert(help4);
02025     }
02026   }
02027 
02028   template <typename PeakType>
02029   void IsotopeWaveletTransform<PeakType>::updateBoxStates(const MSExperiment<PeakType>& map, const Size scan_index, const UInt RT_interleave,
02030                                                           const UInt RT_votes_cutoff, const Int front_bound, const Int end_bound)
02031   {
02032     typename std::multimap<DoubleReal, Box>::iterator iter, iter2;
02033 
02034     if ((Int)scan_index == end_bound && end_bound != (Int)map.size() - 1)
02035     {
02036       for (iter = open_boxes_.begin(); iter != open_boxes_.end(); ++iter)
02037       {
02038 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02039         std::cout << "LOW THREAD insert in end_box " << iter->first << std::endl;
02040         typename Box::iterator dings;
02041         for (dings = iter->second.begin(); dings != iter->second.end(); ++dings)
02042           std::cout << map[dings->first].getRT() << "\t" << dings->second.c + 1 <<  std::endl;
02043 #endif
02044         end_boxes_.insert(*iter);
02045       }
02046       open_boxes_.clear();
02047       return;
02048     }
02049 
02050     for (iter = open_boxes_.begin(); iter != open_boxes_.end(); )
02051     {
02052 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02053       if (front_bound > 0)
02054       {
02055         std::cout << "HIGH THREAD open box. " << iter->first << "\t current scan index " << scan_index << "\t" << ((iter->second.begin()))->first << "\t of last scan " << map.size() - 1 << "\t" << front_bound << std::endl;
02056       }
02057 #endif
02058 
02059       //For each Box we need to figure out, if and when the last RT value has been inserted
02060       UInt lastScan = (--(iter->second.end()))->first;
02061       if (scan_index - lastScan > RT_interleave + 1 || scan_index == map.size() - 1) //I.e. close the box!
02062       {
02063         if (iter->second.begin()->first - front_bound <= RT_interleave + 1 && front_bound > 0)
02064         {
02065           iter2 = iter;
02066           ++iter2;
02067 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02068           std::cout << "HIGH THREAD insert in front_box " << iter->first << std::endl;
02069 #endif
02070           front_boxes_.insert(*iter);
02071           open_boxes_.erase(iter);
02072           iter = iter2;
02073           continue;
02074         }
02075 
02076         iter2 = iter;
02077         ++iter2;
02078         //Please do **NOT** simplify the upcoming lines.
02079         //The 'obvious' overhead is necessary since the object represented by iter might be erased
02080         //by push2Box which might be called by extendBox_.
02081         if (iter->second.size() >= RT_votes_cutoff)
02082         {
02083           //extendBox_ (map, iter->second);
02084           iter = iter2;
02085           closed_boxes_.insert(*(--iter));
02086         }
02087         open_boxes_.erase(iter);
02088         iter = iter2;
02089       }
02090       else
02091       {
02092         ++iter;
02093       }
02094     }
02095   }
02096 
02097   template <typename PeakType>
02098   void IsotopeWaveletTransform<PeakType>::extendBox_(const MSExperiment<PeakType>& map, const Box box)
02099   {
02100 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02101     std::cout << "**** CHECKING FOR BOX EXTENSIONS ****" << std::endl;
02102 #endif
02103 
02104     //Determining the elution profile
02105     typename Box::const_iterator iter;
02106     std::vector<DoubleReal> elution_profile(box.size());
02107     UInt index = 0;
02108     for (iter = box.begin(); iter != box.end(); ++iter, ++index)
02109     {
02110       for (Size i = iter->second.MZ_begin; i != iter->second.MZ_end; ++i)
02111       {
02112         elution_profile[index] += map[iter->second.RT_index][i].getIntensity();
02113       }
02114       elution_profile[index] /= iter->second.MZ_end - iter->second.MZ_begin + 1.;
02115     }
02116 
02117     DoubleReal max = 0;
02118     Int max_index = INT_MIN;
02119     for (Size i = 0; i < elution_profile.size(); ++i)
02120     {
02121       if (elution_profile[i] > max)
02122       {
02123         max_index = i;
02124         max = elution_profile[i];
02125       }
02126     }
02127 
02128     Int max_extension = (Int)(elution_profile.size()) - 2 * max_index;
02129 
02130     DoubleReal av_elution = 0;
02131     for (Size i = 0; i < elution_profile.size(); ++i)
02132     {
02133       av_elution += elution_profile[i];
02134     }
02135     av_elution /= (DoubleReal)elution_profile.size();
02136 
02137     DoubleReal sd_elution = 0;
02138     for (Size i = 0; i < elution_profile.size(); ++i)
02139     {
02140       sd_elution += (av_elution - elution_profile[i]) * (av_elution - elution_profile[i]);
02141     }
02142     sd_elution /= (DoubleReal)(elution_profile.size() - 1);
02143     sd_elution = sqrt(sd_elution);
02144 
02145     //Determine average m/z monoisotopic pos
02146     DoubleReal av_mz = 0;
02147     for (iter = box.begin(); iter != box.end(); ++iter, ++index)
02148     {
02149       av_mz += iter->second.mz;
02150 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02151       std::cout << iter->second.RT << "\t" << iter->second.mz << "\t" << iter->second.c + 1 << std::endl;
02152 #endif
02153     }
02154     av_mz /= (DoubleReal)box.size();
02155 
02156 
02157     //Boundary check
02158     if ((Int)(box.begin()->second.RT_index) - 1 < 0)
02159     {
02160       return;
02161     }
02162 
02163     UInt pre_index =  box.begin()->second.RT_index - 1;
02164     typename MSSpectrum<PeakType>::const_iterator c_iter =  map[pre_index].MZBegin(av_mz);
02165     DoubleReal pre_elution = 0;
02166 
02167     DoubleReal mz_start = map[pre_index + 1][box.begin()->second.MZ_begin].getMZ();
02168     DoubleReal mz_end = map[pre_index + 1][box.begin()->second.MZ_end].getMZ();
02169 
02170     typename MSSpectrum<PeakType>::const_iterator mz_start_iter = map[pre_index].MZBegin(mz_start), mz_end_iter = map[pre_index].MZBegin(mz_end);
02171     for (typename MSSpectrum<PeakType>::const_iterator mz_iter = mz_start_iter; mz_iter != mz_end_iter; ++mz_iter)
02172     {
02173       pre_elution += mz_iter->getIntensity();
02174     }
02175 
02176 
02177     //Do we need to extend at all?
02178     if (pre_elution <= av_elution - 2 * sd_elution)
02179     {
02180       return;
02181     }
02182 
02183     Int c_index = max_extension;
02184     Int first_index = box.begin()->second.RT_index;
02185     for (Int i = 1; i < max_extension; ++i)
02186     {
02187       c_index = first_index - i;
02188       if (c_index < 0)
02189       {
02190         break;
02191       }
02192 
02193       //CHECK Majority vote for charge???????????????
02194 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02195       std::cout << box.begin()->second.RT << "\t" << av_mz << "\t" << box.begin()->second.c + 1 << "\t" << " extending the box " << std::endl;
02196 #endif
02197 
02198       push2Box_(av_mz, c_index, box.begin()->second.c, box.begin()->second.score, c_iter->getIntensity(),
02199                 map[c_index].getRT(), box.begin()->second.MZ_begin, box.begin()->second.MZ_end);
02200     }
02201   }
02202 
02203   template <typename PeakType>
02204   void IsotopeWaveletTransform<PeakType>::clusterSeeds_(const TransSpectrum& candidates,
02205                                                         const MSSpectrum<PeakType>& ref, const UInt scan_index, const UInt c, const bool check_PPMs)
02206   {
02207     typename std::multimap<DoubleReal, Box>::iterator iter;
02208     typename Box::iterator box_iter;
02209     std::vector<BoxElement> final_box;
02210     DoubleReal c_mz, av_score = 0, av_mz = 0, av_intens = 0, av_abs_intens = 0, count = 0;
02211     DoubleReal virtual_av_mz = 0, virtual_av_intens = 0, virtual_av_abs_intens = 0, virtual_count = 0;
02212 
02213     typename std::pair<DoubleReal, DoubleReal> c_extend;
02214     for (iter = tmp_boxes_->at(c).begin(); iter != tmp_boxes_->at(c).end(); ++iter)
02215     {
02216       Box& c_box = iter->second;
02217       av_score = 0, av_mz = 0, av_intens = 0, av_abs_intens = 0, count = 0;
02218       virtual_av_mz = 0, virtual_av_intens = 0, virtual_av_abs_intens = 0, virtual_count = 0;
02219 
02220       for (box_iter = c_box.begin(); box_iter != c_box.end(); ++box_iter)
02221       {
02222         if (box_iter->second.score == 0) //virtual helping point
02223         {
02224           if (count != 0)
02225             continue; //it is in any way not pure virtual
02226 
02227           c_mz = box_iter->second.mz;
02228           virtual_av_intens += box_iter->second.intens;
02229           virtual_av_abs_intens += fabs(box_iter->second.intens);
02230           virtual_av_mz += c_mz * fabs(box_iter->second.intens);
02231           ++virtual_count;
02232         }
02233         else
02234         {
02235           c_mz = box_iter->second.mz;
02236           av_score += box_iter->second.score;
02237           av_intens += box_iter->second.intens;
02238           av_abs_intens += fabs(box_iter->second.intens);
02239           av_mz += c_mz * fabs(box_iter->second.intens);
02240           ++count;
02241         }
02242       }
02243 
02244       if (count == 0) //pure virtual helping box
02245       {
02246         av_intens = virtual_av_intens / virtual_count;
02247         av_score = 0;
02248         av_mz = virtual_av_mz / virtual_av_abs_intens;
02249       }
02250       else
02251       {
02252         av_intens /= count;
02253         av_score /= count;
02254         av_mz /= av_abs_intens;
02255       }
02256 
02257       BoxElement c_box_element;
02258       c_box_element.mz = av_mz;
02259       c_box_element.c = c;
02260       c_box_element.score = av_score;
02261       c_box_element.intens = av_intens;
02262 
02263       c_box_element.RT = c_box.begin()->second.RT;
02264 
02265       final_box.push_back(c_box_element);
02266     }
02267 
02268     UInt num_o_feature = final_box.size();
02269     if (num_o_feature == 0)
02270     {
02271       tmp_boxes_->at(c).clear();
02272       return;
02273     }
02274 
02275     //Computing the derivatives
02276     std::vector<DoubleReal> bwd_diffs(num_o_feature, 0);
02277 
02278     bwd_diffs[0] = 0;
02279     for (UInt i = 1; i < num_o_feature; ++i)
02280     {
02281       bwd_diffs[i] = (final_box[i].intens - final_box[i - 1].intens) / (final_box[i].mz - final_box[i - 1].mz);
02282     }
02283 
02284 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02285     std::ofstream ofile_bwd("bwd_gpu.dat");
02286     for (UInt i = 0; i < num_o_feature; ++i)
02287     {
02288       ofile_bwd << final_box[i].mz << "\t" << bwd_diffs[i] << std::endl;
02289     }
02290     ofile_bwd.close();
02291 #endif
02292 
02293     for (UInt i = 0; i < num_o_feature - 1; ++i)
02294     {
02295       while (i < num_o_feature - 2)
02296       {
02297         if (final_box[i].score > 0 || final_box[i].score == -1000) //this has been an helping point
02298           break;
02299         ++i;
02300       }
02301 
02302       if (bwd_diffs[i] > 0 && bwd_diffs[i + 1] < 0)
02303       {
02304         checkPositionForPlausibility_(candidates, ref, final_box[i].mz, final_box[i].c, scan_index, check_PPMs, final_box[i].intens, final_box[i].score);
02305         continue;
02306       }
02307     }
02308 
02309     tmp_boxes_->at(c).clear();
02310   }
02311 
02312   template <typename PeakType>
02313   FeatureMap<Feature> IsotopeWaveletTransform<PeakType>::mapSeeds2Features(const MSExperiment<PeakType>& map, const UInt RT_votes_cutoff)
02314   {
02315     FeatureMap<Feature> feature_map;
02316     typename std::multimap<DoubleReal, Box>::iterator iter;
02317     typename Box::iterator box_iter;
02318     UInt best_charge_index; DoubleReal best_charge_score, c_mz, c_RT; UInt c_charge;
02319     DoubleReal av_intens = 0, av_ref_intens = 0, av_score = 0, av_mz = 0, av_RT = 0, mz_cutoff, sum_of_ref_intenses_g;
02320     bool restart = false;
02321 
02322     typename std::pair<DoubleReal, DoubleReal> c_extend;
02323     for (iter = closed_boxes_.begin(); iter != closed_boxes_.end(); ++iter)
02324     {
02325       sum_of_ref_intenses_g = 0;
02326       Box& c_box = iter->second;
02327       std::vector<DoubleReal> charge_votes(max_charge_, 0), charge_binary_votes(max_charge_, 0);
02328       restart = false;
02329 
02330       //Let's first determine the charge
02331       //Therefor, we can use two types of votes: qualitative ones (charge_binary_votes) or quantitative ones (charge_votes)
02332       for (box_iter = c_box.begin(); box_iter != c_box.end(); ++box_iter)
02333       {
02334 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02335         if (trunc(box_iter->second.mz) == 874)
02336           std::cout << box_iter->second.c << "\t" <<  box_iter->second.intens  << "\t" << box_iter->second.score << std::endl;
02337 #endif
02338 
02339         if (box_iter->second.score == -1000)
02340         {
02341           restart = true;
02342           break;
02343         }
02344 
02345         charge_votes[box_iter->second.c] += box_iter->second.intens; //score; Do not use score, can get problematic for charge state 2 vs 4
02346         ++charge_binary_votes[box_iter->second.c];
02347       }
02348 
02349       if (restart)
02350       {
02351         continue;
02352       }
02353 
02354       //... determining the best fitting charge
02355       best_charge_index = 0; best_charge_score = 0;
02356       for (UInt i = 0; i < max_charge_; ++i)
02357       {
02358         if (charge_votes[i] > best_charge_score)
02359         {
02360           best_charge_index = i;
02361           best_charge_score = charge_votes[i];
02362         }
02363       }
02364 
02365       //Pattern found in too few RT scan
02366       if (charge_binary_votes[best_charge_index] < RT_votes_cutoff && RT_votes_cutoff <= map.size())
02367       {
02368         continue;
02369       }
02370 
02371       c_charge = best_charge_index + 1; //that's the finally predicted charge state for the pattern
02372 
02373       av_intens = 0, av_ref_intens = 0, av_score = 0, av_mz = 0, av_RT = 0;
02374       //Now, let's get the RT boundaries for the box
02375       std::vector<DPosition<2> > point_set;
02376       DoubleReal sum_of_ref_intenses_l;
02377       for (box_iter = c_box.begin(); box_iter != c_box.end(); ++box_iter)
02378       {
02379         sum_of_ref_intenses_l = 0;
02380         c_mz = box_iter->second.mz;
02381         c_RT = box_iter->second.RT;
02382 
02383         mz_cutoff = IsotopeWavelet::getMzPeakCutOffAtMonoPos(c_mz, c_charge);
02384 
02385         point_set.push_back(DPosition<2>(c_RT, c_mz - Constants::IW_QUARTER_NEUTRON_MASS / (DoubleReal)c_charge));
02386         //-1 since we are already at the first peak and +0.75, since this includes the last peak of the wavelet as a whole
02387         point_set.push_back(DPosition<2>(c_RT, c_mz + mz_cutoff / (DoubleReal)c_charge));
02388 
02389 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02390         std::cout << "Intenstype: " << intenstype_ << std::endl;
02391 #endif
02392         if (intenstype_ == "ref")
02393         {
02394           //Find monoisotopic max
02395           const MSSpectrum<PeakType>& c_spec(map[box_iter->second.RT_index]);
02396           //'Correct' possible shift
02397           for (unsigned int i = 0; i < mz_cutoff; ++i)
02398           {
02399             typename MSSpectrum<PeakType>::const_iterator h_iter = c_spec.MZBegin(c_mz + i * Constants::IW_NEUTRON_MASS / c_charge + Constants::IW_QUARTER_NEUTRON_MASS / (DoubleReal)c_charge), hc_iter = c_spec.MZBegin(c_mz + i * Constants::IW_NEUTRON_MASS / c_charge);
02400 
02401             hc_iter = c_spec.MZBegin(c_mz + i * Constants::IW_NEUTRON_MASS / c_charge);
02402 
02403             while (h_iter != c_spec.begin())
02404             {
02405 
02406 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02407               if (trunc(c_mz) == 874)
02408               {
02409                 std::cout << "cmz: " << c_mz + i * Constants::IW_NEUTRON_MASS / c_charge << "\t" << hc_iter->getMZ() << "\t" << hc_iter->getIntensity() << "\t" << h_iter->getMZ() << "\t" << h_iter->getIntensity() << std::endl;
02410               }
02411 #endif
02412 
02413               --h_iter;
02414               if (h_iter->getIntensity() > hc_iter->getIntensity() || (h_iter->getIntensity() == hc_iter->getIntensity() && hc_iter->getIntensity() == 0))
02415               {
02416                 hc_iter = h_iter;
02417               }
02418 
02419               if (c_mz + i * Constants::IW_NEUTRON_MASS / c_charge - h_iter->getMZ() > Constants::IW_QUARTER_NEUTRON_MASS / (DoubleReal)c_charge)
02420               {
02421                 break;
02422               }
02423             }
02424 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02425             if (trunc(c_mz) == 874)
02426             {
02427               std::cout << "c_mz: " << c_mz + i * Constants::IW_NEUTRON_MASS / c_charge << "\t" << hc_iter->getMZ() << "\t" << hc_iter->getIntensity() << "\t" << i * Constants::IW_NEUTRON_MASS / c_charge << "\t";
02428             }
02429 #endif
02430             sum_of_ref_intenses_l += hc_iter->getIntensity();
02431 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02432             if (trunc(c_mz) == 874)
02433             {
02434               std::cout << sum_of_ref_intenses_l <<  "********" << std::endl;
02435             }
02436 #endif
02437           }
02438         }
02439 
02440         if (best_charge_index == box_iter->second.c)
02441         {
02442           av_score += box_iter->second.score;
02443           av_intens += box_iter->second.intens;
02444           av_ref_intens += box_iter->second.ref_intens;
02445           sum_of_ref_intenses_g += sum_of_ref_intenses_l;
02446           av_mz += c_mz * box_iter->second.intens;
02447         }
02448         av_RT += c_RT;
02449       }
02450 
02451       av_mz /= av_intens;
02452       av_ref_intens /= (DoubleReal)charge_binary_votes[best_charge_index];
02453       av_score /= (DoubleReal)charge_binary_votes[best_charge_index];
02454       av_RT /= (DoubleReal)c_box.size();
02455 
02456 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02457       if (trunc(av_mz) == 874)
02458         std::cout << av_mz << "\t" << best_charge_index << "\t" << best_charge_score << std::endl;
02459 #endif
02460 
02461       Feature c_feature;
02462       ConvexHull2D c_conv_hull;
02463       c_conv_hull.addPoints(point_set);
02464       c_feature.setCharge(c_charge);
02465       c_feature.setConvexHulls(std::vector<ConvexHull2D>(1, c_conv_hull));
02466 
02467       //This makes the intensity value independent of the m/z (the lambda) value (Skellam distribution)
02468       if (intenstype_ == "corrected")
02469       {
02470         DoubleReal lambda = IsotopeWavelet::getLambdaL(av_mz * c_charge);
02471         av_intens /= exp(-2 * lambda) * boost::math::cyl_bessel_i(0, 2 * lambda);
02472       }
02473       if (intenstype_ == "ref")
02474       {
02475 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02476         if (trunc(c_mz) == 874)
02477         {
02478           std::cout << sum_of_ref_intenses_g <<  "####" << std::endl;
02479         }
02480 #endif
02481 
02482         av_intens = sum_of_ref_intenses_g;
02483       }
02484 
02485       c_feature.setMZ(av_mz);
02486       c_feature.setIntensity(av_intens);
02487       c_feature.setRT(av_RT);
02488       c_feature.setOverallQuality(av_score);
02489       feature_map.push_back(c_feature);
02490     }
02491 
02492     return feature_map;
02493   }
02494 
02495   template <typename PeakType>
02496   bool IsotopeWaveletTransform<PeakType>::checkPositionForPlausibility_(const MSSpectrum<PeakType>& candidate,
02497                                                                         const MSSpectrum<PeakType>& ref, const DoubleReal seed_mz, const UInt c, const UInt scan_index, const bool check_PPMs, const DoubleReal transintens, const DoubleReal prev_score)
02498   {
02499     typename MSSpectrum<PeakType>::const_iterator iter, ref_iter;
02500     UInt peak_cutoff;
02501     peak_cutoff = IsotopeWavelet::getNumPeakCutOff(seed_mz, c + 1);
02502 
02503     iter = candidate.MZBegin(seed_mz);
02504     //we can ignore those cases
02505     if (iter == candidate.begin() || iter == candidate.end())
02506     {
02507       return false;
02508     }
02509 
02510     std::pair<DoubleReal, DoubleReal> reals;
02511     ref_iter =  ref.MZBegin(seed_mz);
02512     //Correct the position
02513     DoubleReal real_mz, real_intens;
02514     if (check_PPMs)
02515     {
02516       reals = checkPPMTheoModel_(ref, iter->getMZ(), c);
02517       real_mz = reals.first, real_intens = reals.second;
02518       //if (real_mz <= 0 || real_intens <= 0)
02519       //{
02520       typename MSSpectrum<PeakType>::const_iterator h_iter = ref_iter, hc_iter = ref_iter;
02521       while (h_iter != ref.begin())
02522       {
02523         --h_iter;
02524         if (h_iter->getIntensity() > hc_iter->getIntensity() || (h_iter->getIntensity() == hc_iter->getIntensity() && hc_iter->getIntensity() == 0))
02525         {
02526           hc_iter = h_iter;
02527         }
02528         else
02529         {
02530           break;
02531         }
02532 
02533         if (seed_mz - h_iter->getMZ() > Constants::IW_QUARTER_NEUTRON_MASS / (c + 1.))
02534         {
02535           return false;
02536         }
02537       }
02538       reals = checkPPMTheoModel_(ref, h_iter->getMZ(), c);
02539       real_mz = reals.first, real_intens = reals.second;
02540       if (real_mz <= 0 || real_intens <= 0)
02541       {
02542         return false;
02543       }
02544       real_mz = h_iter->getMZ();
02545       real_intens = h_iter->getIntensity();
02546       //}
02547     }
02548     else
02549     {
02550       reals = std::pair<DoubleReal, DoubleReal>(seed_mz, ref_iter->getIntensity());
02551       real_mz = reals.first, real_intens = reals.second;
02552 
02553       if (real_mz <= 0 || real_intens <= 0)
02554       {
02555         typename MSSpectrum<PeakType>::const_iterator h_iter = ref_iter, hc_iter = ref_iter;
02556         while (h_iter != ref.begin())
02557         {
02558           --h_iter;
02559           if (h_iter->getIntensity() > hc_iter->getIntensity() || (h_iter->getIntensity() == hc_iter->getIntensity() && hc_iter->getIntensity() == 0))
02560           {
02561             hc_iter = h_iter;
02562           }
02563           else
02564           {
02565             break;
02566           }
02567 
02568           if (seed_mz - h_iter->getMZ() > Constants::IW_QUARTER_NEUTRON_MASS / (c + 1.))
02569           {
02570             return false;
02571           }
02572         }
02573         real_mz = h_iter->getMZ(), real_intens = h_iter->getIntensity();
02574         if (real_mz <= 0 || real_intens <= 0)
02575         {
02576           return false;
02577         }
02578         real_mz = h_iter->getMZ();
02579         real_intens = h_iter->getIntensity();
02580       }
02581     }
02582 
02583     DoubleReal c_score = scoreThis_(candidate, peak_cutoff, real_mz, c, 0);
02584 
02585     if (c_score <= 0)
02586     {
02587       return false;
02588     }
02589 
02590     DoubleReal mz_cutoff = IsotopeWavelet::getMzPeakCutOffAtMonoPos(real_mz, c + 1);
02591     typename MSSpectrum<PeakType>::const_iterator real_l_MZ_iter = ref.MZBegin(real_mz - Constants::IW_QUARTER_NEUTRON_MASS / (c + 1.));
02592     typename MSSpectrum<PeakType>::const_iterator real_r_MZ_iter = ref.MZBegin(real_l_MZ_iter, real_mz + mz_cutoff / (c + 1.), ref.end());
02593     if (real_r_MZ_iter == ref.end())
02594     {
02595       --real_r_MZ_iter;
02596     }
02597 
02598 
02599     UInt real_mz_begin = distance(ref.begin(), real_l_MZ_iter);
02600     UInt real_mz_end = distance(ref.begin(), real_r_MZ_iter);
02601 
02602     if (prev_score == -1000)
02603     {
02604       push2Box_(real_mz, scan_index, c, prev_score, transintens, ref.getRT(), real_mz_begin, real_mz_end, real_intens);
02605     }
02606     else
02607     {
02608       push2Box_(real_mz, scan_index, c, c_score, transintens, ref.getRT(), real_mz_begin, real_mz_end, real_intens);
02609     }
02610     return true;
02611   }
02612 
02613   template <typename PeakType>
02614   bool IsotopeWaveletTransform<PeakType>::checkPositionForPlausibility_(const TransSpectrum& candidate,
02615                                                                         const MSSpectrum<PeakType>& ref, const DoubleReal seed_mz, const UInt c, const UInt scan_index, const bool check_PPMs, const DoubleReal transintens, const DoubleReal prev_score)
02616   {
02617     typename MSSpectrum<PeakType>::const_iterator iter, ref_iter;
02618     UInt peak_cutoff;
02619     peak_cutoff = IsotopeWavelet::getNumPeakCutOff(seed_mz, c + 1);
02620 
02621     iter = candidate.MZBegin(seed_mz);
02622     //we can ignore those cases
02623     if (iter == candidate.begin() || iter == candidate.end())
02624     {
02625       return false;
02626     }
02627 
02628     std::pair<DoubleReal, DoubleReal> reals;
02629     ref_iter =  ref.MZBegin(seed_mz);
02630     //Correct the position
02631     DoubleReal real_mz, real_intens;
02632     if (check_PPMs)
02633     {
02634       reals = checkPPMTheoModel_(ref, iter->getMZ(), c);
02635       real_mz = reals.first, real_intens = reals.second;
02636       //if (real_mz <= 0 || real_intens <= 0)
02637       //{
02638       typename MSSpectrum<PeakType>::const_iterator h_iter = ref_iter, hc_iter = ref_iter;
02639       while (h_iter != ref.begin())
02640       {
02641         --h_iter;
02642         if (h_iter->getIntensity() > hc_iter->getIntensity() || (h_iter->getIntensity() == hc_iter->getIntensity() && hc_iter->getIntensity() == 0))
02643         {
02644           hc_iter = h_iter;
02645         }
02646         else
02647         {
02648           break;
02649         }
02650 
02651         if (seed_mz - h_iter->getMZ() > Constants::IW_QUARTER_NEUTRON_MASS / (c + 1.))
02652         {
02653           return false;
02654         }
02655       }
02656       ++h_iter;
02657       reals = checkPPMTheoModel_(ref, h_iter->getMZ(), c);
02658       real_mz = reals.first, real_intens = reals.second;
02659 
02660 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02661       std::cout << "Plausibility check old_mz: " << iter->getMZ() << "\t" << real_mz << std::endl;
02662 #endif
02663 
02664       if (real_mz <= 0 || real_intens <= 0)
02665       {
02666         return false;
02667       }
02668       real_mz = h_iter->getMZ();
02669       real_intens = h_iter->getIntensity();
02670       //}
02671     }
02672     else
02673     {
02674       reals = std::pair<DoubleReal, DoubleReal>(seed_mz, ref_iter->getIntensity());
02675       real_mz = reals.first, real_intens = reals.second;
02676 
02677       if (real_mz <= 0 || real_intens <= 0)
02678       {
02679         typename MSSpectrum<PeakType>::const_iterator h_iter = ref_iter, hc_iter = ref_iter;
02680         while (h_iter != ref.begin())
02681         {
02682           --h_iter;
02683           if (h_iter->getIntensity() > hc_iter->getIntensity() || (h_iter->getIntensity() == hc_iter->getIntensity() && hc_iter->getIntensity() == 0))
02684           {
02685             hc_iter = h_iter;
02686           }
02687           else
02688           {
02689             break;
02690           }
02691 
02692           if (seed_mz - h_iter->getMZ() > Constants::IW_QUARTER_NEUTRON_MASS / (c + 1.))
02693           {
02694             return false;
02695           }
02696         }
02697         real_mz = h_iter->getMZ(), real_intens = h_iter->getIntensity();
02698         if (real_mz <= 0 || real_intens <= 0)
02699         {
02700           return false;
02701         }
02702         real_mz = h_iter->getMZ();
02703         real_intens = h_iter->getIntensity();
02704       }
02705     }
02706 
02707     DoubleReal c_score = scoreThis_(candidate, peak_cutoff, real_mz, c, 0);
02708 
02709     if (c_score <= 0)
02710     {
02711       return false;
02712     }
02713 
02714     DoubleReal mz_cutoff = IsotopeWavelet::getMzPeakCutOffAtMonoPos(real_mz, c + 1);
02715     typename MSSpectrum<PeakType>::const_iterator real_l_MZ_iter = ref.MZBegin(real_mz - Constants::IW_QUARTER_NEUTRON_MASS / (c + 1.));
02716     typename MSSpectrum<PeakType>::const_iterator real_r_MZ_iter = ref.MZBegin(real_l_MZ_iter, real_mz + mz_cutoff / (c + 1.), ref.end());
02717     if (real_r_MZ_iter == ref.end())
02718     {
02719       --real_r_MZ_iter;
02720     }
02721 
02722 
02723     UInt real_mz_begin = distance(ref.begin(), real_l_MZ_iter);
02724     UInt real_mz_end = distance(ref.begin(), real_r_MZ_iter);
02725 
02726     if (prev_score == -1000)
02727     {
02728       push2Box_(real_mz, scan_index, c, prev_score, transintens, ref.getRT(), real_mz_begin, real_mz_end, real_intens);
02729     }
02730     else
02731     {
02732       push2Box_(real_mz, scan_index, c, c_score, transintens, ref.getRT(), real_mz_begin, real_mz_end, real_intens);
02733     }
02734 
02735     return true;
02736   }
02737 
02738   template <typename PeakType>
02739   std::pair<DoubleReal, DoubleReal> IsotopeWaveletTransform<PeakType>::checkPPMTheoModel_(const MSSpectrum<PeakType>& ref, const DoubleReal c_mz, const UInt c)
02740   {
02741     DoubleReal mass = c_mz * (c + 1) - Constants::IW_PROTON_MASS * (c);
02742     DoubleReal ppms = getPPMs_(peptideMassRule_(mass), mass);
02743     if (ppms >= Constants::PEPTIDE_MASS_RULE_THEO_PPM_BOUND)
02744     {
02745 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02746       std::cout << ::std::setprecision(8) << std::fixed << c_mz << "\t =(" << "ISO_WAVE" << ")> " << "REJECT \t" << ppms << " (rule: " << peptideMassRule_(mass) << " got: " << mass << ")" << std::endl;
02747 #endif
02748       return std::pair<DoubleReal, DoubleReal>(-1, -1);
02749     }
02750 
02751 #ifdef OPENMS_DEBUG_ISOTOPE_WAVELET
02752     std::cout << ::std::setprecision(8) << std::fixed << c_mz << "\t =(" << "ISO_WAVE" << ")> " << "ACCEPT \t" << ppms << " (rule: " << peptideMassRule_(mass) << " got: " << mass << ")" << std::endl;
02753 #endif
02754     return std::pair<DoubleReal, DoubleReal>(c_mz, ref.MZBegin(c_mz)->getIntensity());
02755   }
02756 
02757 } //namespace
02758 
02759 #endif

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