CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch13/src/CommonTools/Clustering1D/interface/FsmwClusterizer1D.h

Go to the documentation of this file.
00001 #ifndef _FsmwClusterizer1D_H_
00002 #define _FsmwClusterizer1D_H_
00003 
00004 #include "CommonTools/Clustering1D/interface/Clusterizer1D.h"
00005 #include "CommonTools/Clustering1D/interface/Clusterizer1DCommons.h"
00006 #include "CommonTools/Clustering1D/interface/TrivialWeightEstimator.h"
00007 #include "CommonTools/Clustering1D/interface/Clustering1DException.h"
00008 
00009 #include <vector>
00010 #include <cmath>
00011 #include <algorithm>
00012 
00016 template <class T>
00017 class FsmwClusterizer1D : public Clusterizer1D<T>
00018 {
00019 public:
00022     FsmwClusterizer1D ( double fraction = .05, double n_sigma_in = 3.,
00023                       const WeightEstimator<T> & est = TrivialWeightEstimator<T>() );
00024     FsmwClusterizer1D ( const FsmwClusterizer1D & );
00025     ~FsmwClusterizer1D();
00026 
00027     std::pair < std::vector < Cluster1D<T> >, std::vector < const T * > >
00028     operator() ( const std::vector< Cluster1D<T> > & ) const;
00029 
00030     virtual FsmwClusterizer1D * clone() const;
00031 
00032 private:
00033     WeightEstimator<T> * theEstimator;
00034     double theFraction;
00035     double theNSigmaIn;
00036 };
00037 
00038 /*
00039  *                              --- implementation ---
00040  *
00041  */
00042 
00043 namespace FsmwClusterizer1DNameSpace
00044 {
00045 /*
00046  *  Function that computes the 'fraction-of sample mode with weights'.
00047  *  The modefinder, that is.
00048  *  Warning, values have to be sorted in this method!!
00049  */
00050 template <class T>
00051 std::pair < typename std::vector< Cluster1D<T> >::const_iterator,
00052 typename std::vector< Cluster1D<T> >::const_iterator >
00053 fsmw ( const std::vector< Cluster1D<T> > & values, double fraction )
00054 {
00055     typedef Cluster1D<T> Cluster1D;
00056     typename std::vector< Cluster1D >::const_iterator begin = values.begin();
00057     typename std::vector< Cluster1D >::const_iterator end = values.end()-1;
00058 
00059     while (1)
00060     {
00061 #ifdef FsmwClusterizer1DDebug
00062         cout << "Begin at " << begin->position().value() << endl;
00063 #endif
00064 
00065         const int size = (int) (end-begin);
00066 #ifdef FsmwClusterizer1DDebug
00067 
00068         cout << "Size " << size << endl;
00069 #endif
00070 
00071         int stepsize = (int) floor ( ( 1+ size ) * fraction );
00072         if ( stepsize == 0 )
00073             stepsize=1;
00074 #ifdef FsmwClusterizer1DDebug
00075 
00076         cout << "Old end at " << end->position().value() << endl;
00077 #endif
00078 
00079         end=begin+stepsize;
00080         typename std::vector< Cluster1D >::const_iterator new_begin = begin;
00081         typename std::vector< Cluster1D >::const_iterator new_end = end;
00082 
00083 #ifdef FsmwClusterizer1DDebug
00084 
00085         cout << "New end at " << end->position().value() << endl;
00086         cout << "stepsize " << stepsize << endl;
00087 #endif
00088 
00089         // Old version: used the weights of just the end points
00090         // double totalweight = begin->weight() + end->weight();
00091 
00092         // new version: sums up the weights of all points involved
00093         // _including_ the "end" point
00094         double totalweight = end->weight();
00095         for ( typename std::vector< Cluster1D >::const_iterator w=begin; w!=end ; ++w )
00096         {
00097             totalweight+=w->weight();
00098         };
00099 
00100         double div=fabs ( end->position().value() - begin->position().value() ) /
00101                    totalweight;
00102 #ifdef FsmwClusterizer1DDebug
00103 
00104         cout << "Div at " << begin->position().value() << ":" << (end)->position().value()
00105         << " = " << div << endl;
00106 #endif
00107 
00108         for ( typename std::vector< Cluster1D >::const_iterator i = (begin + 1);
00109                 i!=(begin + size - stepsize + 1); ++i )
00110         {
00111             // FIXME wrong
00112             // double tmpweight = i->weight() + (i+stepsize)->weight();
00113             //
00114             // new version: sums up the weights of all points in the interval
00115             // _including_ the end point (i+stepsize)
00116             double tmpweight = 0.;
00117             for ( typename std::vector< Cluster1D >::const_iterator wt=i; wt!=(i+stepsize+1); ++wt )
00118             {
00119                 tmpweight+=wt->weight();
00120             };
00121 
00122             double tmpdiv = fabs( i->position().value() - (i+stepsize)->position().value() )
00123                             / tmpweight;
00124 #ifdef FsmwClusterizer1DDebug
00125 
00126             cout << "Div at " << i->position().value() << ":" << (i+stepsize)->position().value()
00127             << " = " << tmpdiv << endl;
00128 #endif
00129 
00130             if ( tmpdiv < div)
00131             {
00132                 new_begin= i;
00133                 new_end = i+stepsize;
00134                 div= tmpdiv;
00135             };
00136         };
00137 #ifdef FsmwClusterizer1DDebug
00138 
00139         cout << "---- new interval: " << new_begin->position().value()
00140         << ":" << new_end->position().value() << endl;
00141 #endif
00142 
00143         begin = new_begin;
00144         end = new_end;
00145         if ( size < 4 )
00146             break;
00147     };
00148 
00149     std::pair < typename std::vector< Cluster1D >::const_iterator,
00150     typename std::vector< Cluster1D >::const_iterator > ret ( begin, end );
00151     return ret;
00152 }
00153 }
00154 
00155 template <class T>
00156 FsmwClusterizer1D<T>::FsmwClusterizer1D( const FsmwClusterizer1D<T> & o ) 
00157     : theEstimator( o.theEstimator->clone() ), theFraction ( o.theFraction ),
00158     theNSigmaIn ( o.theNSigmaIn )
00159 {}
00160 
00161 
00162 template <class T>
00163 FsmwClusterizer1D<T>::FsmwClusterizer1D( double fraction, double nsig, const WeightEstimator<T> & est ) 
00164     : theEstimator ( est.clone() ), theFraction ( fraction ), theNSigmaIn ( nsig )
00165 {}
00166 
00167 
00168 template <class T>
00169 FsmwClusterizer1D<T>::~FsmwClusterizer1D()
00170 {
00171     delete theEstimator;
00172 }
00173 
00174 template <class T>
00175 FsmwClusterizer1D<T> * FsmwClusterizer1D<T>::clone() const
00176 {
00177     return new FsmwClusterizer1D<T>( *this );
00178 }
00179 
00180 template <class T>
00181 std::pair < std::vector< Cluster1D<T> >, std::vector< const T * > >
00182 FsmwClusterizer1D<T>::operator() ( const std::vector < Cluster1D<T> > & ov ) const
00183 {
00184     using namespace Clusterizer1DCommons;
00185     using namespace FsmwClusterizer1DNameSpace;
00186     typedef Cluster1D<T> Cluster1D;
00187     std::vector < const T * > unusedtracks;
00188 
00189     switch ( ov.size() )
00190     {
00191     case 0:
00192         throw Clustering1DException("[FsmwClusterizer1D] no values given" );
00193     case 1:
00194         std::pair < std::vector < Cluster1D >, std::vector < const T * > > ret ( ov, unusedtracks );
00195         return ret;
00196     };
00197 
00198     std::vector < Cluster1D > v = ov;
00199     sort ( v.begin(), v.end(), ComparePairs<T>() );
00200     std::vector < Cluster1D > sols;
00201 
00202     std::pair < typename std::vector< Cluster1D >::const_iterator,
00203     typename std::vector< Cluster1D >::const_iterator > estors
00204     = fsmw ( v, theFraction );
00205 
00206     double weight = estors.first->weight() + estors.second->weight();
00207     double est = ( estors.first->weight() * estors.first->position().value() +
00208                    estors.second->weight() * estors.second->position().value() ) /
00209                  weight;
00210     double err=0.;
00211     double sigma = sqrt ( square ( estors.first->position().value() - est ) +
00212                           square ( estors.second->position().value() - est ));
00213     /*
00214     std::cout << "[FsmwClusterizer1D] first=" << estors.first->position().value()
00215               << " second=" << estors.second->position().value()
00216               << " est=" << est << std::endl;
00217     double sigma = sqrt ( square ( estors.first->position().error() ) +
00218                           square ( estors.second->position().error() ) );
00219     double sigma = estors.first->position().error();
00220                           */
00221     std::vector < const T * > trks;
00222     int inliers=0;
00223 
00224     for ( typename std::vector< Cluster1D >::iterator i=v.begin();
00225             i!=v.end() ; ++i )
00226     {
00227         /*
00228         std::cout << "[FsmwClusterizer1D] see if they're in: delta="
00229                   << 10000 * fabs ( i->position().value() - est )
00230                   << " sigma=" << 10000 * sigma << std::endl;
00231          */
00232         if ( fabs ( i->position().value() - est ) < theNSigmaIn * sigma )
00233         {
00234             // all within theNSigmaIn sigma are 'in'
00235             add ( i->tracks(), trks );
00236             err+= square ( i->position().value() - est );
00237             inliers++;
00238         } else {
00239             add ( i->tracks(), unusedtracks );
00240         };
00241     };
00242     err /= ( inliers - 1 ); // the algo definitely produces 2 or more inliers
00243     err = sqrt ( err );
00244 
00245 
00246     err=sqrt(err);
00247     sols.push_back ( Cluster1D ( Measurement1D ( est, err ), trks, weight ) );
00248 
00249     std::pair < std::vector < Cluster1D >, std::vector < const T * > > ret ( sols, unusedtracks );
00250     return ret;
00251 }
00252 
00253 #endif