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
00012
00013 namespace {
00014
00015
00016
00017
00018
00019
00020
00021
00022
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)
00032 return arr[median] ;
00033
00034 if (high == low + 1) {
00035 if (arr[low] > arr[high])
00036 std::swap(arr[low], arr[high]) ;
00037 return arr[median] ;
00038 }
00039
00040
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
00047 std::swap(arr[middle], arr[low+1]) ;
00048
00049
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
00063 std::swap(arr[low], arr[hh]) ;
00064
00065
00066 if (hh <= median)
00067 low = ll;
00068 if (hh >= median)
00069 high = hh - 1;
00070 }
00071 return 0.f;
00072 }
00073
00074
00075 namespace wirth {
00076
00077 typedef float elem_type ;
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
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
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
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
00205
00206 ElemIterator begin(selector,subset,subset+subsetSize);
00207 ElemIterator end(selector,subset+subsetSize,subset+subsetSize);
00208
00209
00210 offset = pairMedian(begin,end);
00211
00212
00213
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;
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
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
00242
00243 }
00244
00245
00246