CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/RecoLocalTracker/SiStripZeroSuppression/src/IteratedMedianCMNSubtractor.cc

Go to the documentation of this file.
00001 #include "RecoLocalTracker/SiStripZeroSuppression/interface/IteratedMedianCMNSubtractor.h"
00002 
00003 #include "CondFormats/SiStripObjects/interface/SiStripNoises.h"
00004 #include "CalibFormats/SiStripObjects/interface/SiStripQuality.h"
00005 #include "CondFormats/DataRecord/interface/SiStripNoisesRcd.h"
00006 #include "CalibTracker/Records/interface/SiStripQualityRcd.h"
00007 #include <cmath>
00008 
00009 
00010 
00011 // this part should be moved to a "utility" package
00012 // unit tests need to be added
00013 namespace {
00014 
00015   // fastest median search to date 
00016   //  https://ndevilla.free.fr/median/median/index.html
00017   // code adapted from https://ndevilla.free.fr/median/median/src/quickselect.c
00018   /*
00019    *  This Quickselect routine is based on the algorithm described in
00020    *  "Numerical recipes in C", Second Edition,
00021    *  Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5
00022    *  This code by Nicolas Devillard - 1998. Public domain.
00023    */
00024   inline float quick_select(float arr[], int n) {
00025     int low, high ;
00026     int median;
00027     int middle, ll, hh;
00028     
00029     low = 0 ; high = n-1 ; median = (low + high) / 2;
00030     for (;;) {
00031       if (high <= low) /* One element only */
00032         return arr[median] ;
00033       
00034       if (high == low + 1) {  /* Two elements only */
00035         if (arr[low] > arr[high])
00036           std::swap(arr[low], arr[high]) ;
00037         return arr[median] ;
00038       }
00039       
00040       /* Find median of low, middle and high items; swap into position low */
00041       middle = (low + high) / 2;
00042       if (arr[middle] > arr[high])    std::swap(arr[middle], arr[high]) ;
00043       if (arr[low] > arr[high])       std::swap(arr[low], arr[high]) ;
00044       if (arr[middle] > arr[low])     std::swap(arr[middle], arr[low]) ;
00045       
00046       /* Swap low item (now in position middle) into position (low+1) */
00047       std::swap(arr[middle], arr[low+1]) ;
00048       
00049       /* Nibble from each end towards middle, swapping items when stuck */
00050       ll = low + 1;
00051       hh = high;
00052       for (;;) {
00053         do ll++; while (arr[low] > arr[ll]) ;
00054         do hh--; while (arr[hh]  > arr[low]) ;
00055         
00056         if (hh < ll)
00057           break;
00058         
00059         std::swap(arr[ll], arr[hh]) ;
00060       }
00061       
00062       /* Swap middle item (in position low) back into correct position */
00063       std::swap(arr[low], arr[hh]) ;
00064       
00065       /* Re-set active partition */
00066       if (hh <= median)
00067         low = ll;
00068       if (hh >= median)
00069         high = hh - 1;
00070     }
00071     return 0.f; // compiler
00072   }
00073   
00074 
00075   namespace wirth {
00076 
00077     typedef float elem_type ;
00078     
00079     
00080     /*---------------------------------------------------------------------------
00081       Function :   kth_smallest()
00082       In       :   array of elements, # of elements in the array, rank k
00083       Out      :   one element
00084       Job      :   find the kth smallest element in the array
00085       Notice   :   use the median() macro defined below to get the median. 
00086       
00087       Reference:
00088       
00089       Author: Wirth, Niklaus 
00090       Title: Algorithms + data structures = programs 
00091       Publisher: Englewood Cliffs: Prentice-Hall, 1976 
00092       Physical description: 366 p. 
00093       Series: Prentice-Hall Series in Automatic Computation 
00094       
00095       ---------------------------------------------------------------------------*/
00096     
00097     
00098     inline elem_type kth_smallest(elem_type a[], int n, int k) {
00099       int i,j,l,m ;
00100       elem_type x ;
00101       
00102       l=0 ; m=n-1 ;
00103       while (l<m) {
00104         x=a[k] ;
00105         i=l ;
00106         j=m ;
00107         do {
00108           while (a[i]<x) i++ ;
00109           while (x<a[j]) j-- ;
00110           if (i<=j) {
00111             std::swap(a[i],a[j]) ;
00112             i++ ; j-- ;
00113           }
00114         } while (i<=j) ;
00115         if (j<k) l=i ;
00116         if (k<i) m=j ;
00117       }
00118       return a[k] ;
00119     }
00120     
00121 
00122     inline elem_type median(elem_type a[], int n) { return kth_smallest(a,n,(((n)&1)?((n)/2):(((n)/2)-1))); }
00123   }
00124 }
00125 
00126 
00127 #include "boost/iterator/filter_iterator.hpp"
00128 
00129 namespace {
00130   struct SelectElem {
00131     std::pair<float,float>  const * begin;
00132     bool const * ok;
00133     SelectElem() : begin(0), ok(0){}
00134     SelectElem(std::pair<float,float> const * isample, bool const * iok):
00135       begin(isample), ok(iok){}
00136     bool operator()(std::pair<float,float> const & elem) const {
00137       return ok[&elem-begin];
00138     }
00139   };
00140   
00141   
00142   typedef boost::filter_iterator<SelectElem, std::pair<float,float> const *> ElemIterator;
00143   inline float pairMedian(ElemIterator b, ElemIterator e) {
00144     float sample[128]; int size=0;
00145     for (;b!=e; ++b) sample[size++] = (*b).first;
00146     //    return  wirth::median(sample,size);
00147     return  quick_select(sample,size);
00148   }
00149 }
00150 
00151 
00152 void IteratedMedianCMNSubtractor::init(const edm::EventSetup& es){
00153   uint32_t n_cache_id = es.get<SiStripNoisesRcd>().cacheIdentifier();
00154   uint32_t q_cache_id = es.get<SiStripQualityRcd>().cacheIdentifier();
00155   
00156   if(n_cache_id != noise_cache_id) {
00157     es.get<SiStripNoisesRcd>().get( noiseHandle );
00158     noise_cache_id = n_cache_id;
00159   }
00160   if(q_cache_id != quality_cache_id) {
00161     es.get<SiStripQualityRcd>().get( qualityHandle );
00162     quality_cache_id = q_cache_id;
00163   }
00164 }
00165 
00166 void IteratedMedianCMNSubtractor::subtract(const uint32_t& detId,std::vector<int16_t>& digis){ subtract_(detId,digis);}
00167 void IteratedMedianCMNSubtractor::subtract(const uint32_t& detId,std::vector<float>& digis){ subtract_(detId,digis);}
00168 
00169 template<typename T>
00170 inline
00171 void IteratedMedianCMNSubtractor::
00172 subtract_(const uint32_t& detId,std::vector<T>& digis){
00173 
00174 
00175   SiStripNoises::Range detNoiseRange = noiseHandle->getRange(detId);
00176   SiStripQuality::Range detQualityRange = qualityHandle->getRange(detId);
00177 
00178   typename std::vector<T>::iterator fs,ls;
00179   float offset = 0;  
00180   std::pair<float,float> subset[128];
00181   bool ok[128];
00182   int subsetSize=0;
00183   typedef std::pair<float,float> const * iterator;
00184   SelectElem selector(subset,ok);
00185   
00186   _vmedians.clear(); 
00187 
00188   for( uint16_t APV=0; APV< digis.size()/128; ++APV)
00189   {
00190     subsetSize=0;
00191     // fill subset vector with all good strips and their noises
00192     for (uint16_t istrip=APV*128; istrip<(APV+1)*128; ++istrip)
00193     {
00194       if ( !qualityHandle->IsStripBad(detQualityRange,istrip) )
00195       {
00196         std::pair<float,float> pin((float)digis[istrip], (float)noiseHandle->getNoiseFast(istrip,detNoiseRange));
00197         subset[subsetSize]= pin;
00198         ok[subsetSize++]=true;
00199       }
00200     }
00201 
00202     if (subsetSize == 0) continue;
00203 
00204     // std::cout << "subset size " << subsetSize << std::endl;
00205 
00206     ElemIterator begin(selector,subset,subset+subsetSize);
00207     ElemIterator end(selector,subset+subsetSize,subset+subsetSize);
00208 
00209     // caluate offset for all good strips (first iteration)
00210     offset = pairMedian(begin,end);
00211 
00212     // for second, third... iterations, remove strips over threshold
00213     // and recalculate offset on remaining strips
00214     int nokold=subsetSize;
00215     for ( int ii = 0; ii<iterations_-1; ++ii )
00216     {
00217       int nok=0;
00218       for (int j=0; j!=subsetSize;++j)
00219       {
00220         iterator si = subset+j;
00221         ok[j] =  si->first-offset < cut_to_avoid_signal_*si->second;
00222         ++nok;
00223       }
00224       if (nok==nokold) break;   // std::cout << "converged at " << ii << std::endl;
00225       if (nok == 0 ) break;
00226       offset = pairMedian(begin,end);
00227       nokold=nok;
00228     }        
00229 
00230     _vmedians.push_back(std::pair<short,float>(APV,offset));
00231 
00232     // remove offset
00233     fs = digis.begin()+APV*128;
00234     ls = digis.begin()+(APV+1)*128;
00235     while (fs < ls) {
00236       *fs = static_cast<T>(*fs-offset);
00237       fs++;
00238     }
00239 
00240   }
00241   // std::cout << "IMCMNS end " <<  _vmedians.size() << std::endl;
00242 
00243 }
00244 
00245 
00246