00001 #include "emcGainFEM.h"
00002 #include "emcDefines.h"
00003 #include "EmcIndexer.h"
00004 #include "emcTracedValue.h"
00005 #include "emcCalFEMFactory.h"
00006 #include <cmath>
00007 #include <iostream>
00008
00009 #include <string>
00010
00011 using std::endl;
00012 using std::cerr;
00013
00014 namespace
00015 {
00016 static std::string name = "emcGainFEM" ;
00017 static std::string title = "Gain calibration data" ;
00018 static std::string classname = "emcGainFEM" ;
00019
00020 emcCalFEM* creator(int absPosition,
00021 const PHTimeStamp& start,
00022 const PHTimeStamp& end,
00023 bool isDefault)
00024 {
00025 if ( isDefault )
00026 {
00027 return emcGainFEM::Default(absPosition,start,end);
00028 }
00029 else
00030 {
00031 return new emcGainFEM(absPosition,start,end);
00032 }
00033 }
00034
00035 static bool r = emcCalFEMFactory::registerCreator("Gains",
00036 creator);
00037 }
00038
00039
00040 emcGainFEM::emcGainFEM(int absPosition)
00041 : emcTracedFEM(absPosition)
00042 {
00043 NameIt(name,title,classname) ;
00044 }
00045
00046
00047
00048 emcGainFEM::emcGainFEM(int absPosition,
00049 const PHTimeStamp& tStart, const PHTimeStamp& tEnd)
00050 : emcTracedFEM(absPosition,tStart,tEnd)
00051 {
00052 NameIt(name,title,classname) ;
00053 }
00054
00055
00056 void
00057 emcGainFEM::AddNewItem(int channel, emcTracedValue* item)
00058 {
00059 if (item) {
00060 if ( EmcIndexer::isPbScFEM(AbsolutePosition()) ) {
00061 item->MakeConstant(false) ;
00062 }
00063 else {
00064 item->MakeConstant(true) ;
00065 }
00066 emcTracedFEM::AddNewItem(channel,item) ;
00067 }
00068 }
00069
00070
00071 bool
00072 emcGainFEM::AreDifferent(float v1, float v2, float epsilon) const
00073 {
00074 float diff = fabs((v1-v2)/v1) ;
00075 return ( diff > epsilon ) ;
00076 }
00077
00078
00079 float
00080 emcGainFEM::Compact(float epsilon)
00081 {
00082 size_t nitems = GetNumberOfItems();
00083 size_t nchannels = GetNumberOfChannels();
00084
00085 if ( EmcIndexer::isPbScFEM(AbsolutePosition()) )
00086 {
00087 for ( size_t i = 0 ; i < nchannels ; i++)
00088 {
00089 CompactOneChannelLines(i,epsilon) ;
00090 }
00091 }
00092 else
00093 {
00094 if ( EmcIndexer::isPbGlFEM(AbsolutePosition()) )
00095 {
00096 for ( size_t i = 0 ; i < nchannels ; i++)
00097 {
00098 CompactOneChannelConstants(i,epsilon) ;
00099 }
00100 }
00101 else
00102 {
00103 std::cerr << "<EMC-ERROR> emcGainFEM::Compact : "
00104 << " found a FEM which is not PBGL nor PBSC ?!"
00105 << std::endl;
00106 return 1.0;
00107 }
00108 }
00109
00110 float compression = GetNumberOfItems()/static_cast<float>(nitems);
00111 return compression;
00112 }
00113
00114
00115 bool
00116 emcGainFEM::CompactOneChannelLines(int ichannel, float epsilon)
00117 {
00118
00119
00120 size_t i ;
00121
00122 emcItemVector* pvec = fItems[ichannel] ;
00123
00124 if ( !pvec || pvec->size()<2 ) return false ;
00125
00126 emcItemVector& vec = *pvec ;
00127
00128 emcTracedValue* t1 ;
00129 emcTracedValue* t2 ;
00130
00131 for ( i = 0 ; i < vec.size()-1 ; i++) {
00132
00133 t1 = vec[i] ;
00134 t2 = vec[i+1] ;
00135
00136 if ( t2->GetConstant() != 0 ) {
00137
00138
00139 float xs1 = t1->GetX() ;
00140 float xs2 = t2->GetX() ;
00141
00142 float xe2 ;
00143 if ( i < vec.size()-2 ) {
00144 xe2 = vec[i+2]->GetX() ;
00145 }
00146 else {
00147 xe2 = GetXmax() ;
00148 }
00149
00150 float xc1 = 0.5*(xs1+xs2) ;
00151 float xc2 = 0.5*(xs2+xe2) ;
00152 float yc1 = t1->getValue(xc1) ;
00153 float yc2 = t2->getValue(xc2) ;
00154
00155 float slope = (yc2-yc1)/(xc2-xc1) ;
00156 float intercept = yc1 + (xs1-xc1)*slope ;
00157 float diff1 = fabs( 2.0 * (intercept-t1->GetConstant()) /
00158 (intercept+t1->GetConstant()) ) ;
00159
00160 if ( diff1 > epsilon ) continue ;
00161
00162 float ys2 = intercept + slope*(xs2-xs1) ;
00163 float diff2 = fabs( 2.0 * (ys2-t2->GetConstant()) /
00164 (ys2+t2->GetConstant()) ) ;
00165
00166 if (diff2 > epsilon) continue ;
00167
00168
00169 t1->Set(t1->GetX(),intercept,slope) ;
00170
00171 }
00172 delete t2 ;
00173 t2 = 0 ;
00174 fNItems-- ;
00175 size_t j ;
00176 for ( j = i+1 ; j < vec.size()-1 ; j++ ) {
00177 vec[j] = vec[j+1] ;
00178 }
00179 vec.pop_back() ;
00180 --i ;
00181 }
00182
00183 return true ;
00184 }
00185
00186
00187 bool
00188 emcGainFEM::CompactOneChannelConstants(int ichannel, float epsilon)
00189 {
00190
00191
00192 size_t i ;
00193
00194 emcItemVector* pvec = fItems[ichannel] ;
00195
00196 if ( !pvec || pvec->size()<2 ) return false ;
00197
00198 emcItemVector& vec = *pvec ;
00199
00200 emcTracedValue* t1 ;
00201 emcTracedValue* t2 ;
00202
00203 for ( i = 0 ; i < vec.size()-1 ; i++) {
00204
00205 t1 = vec[i] ;
00206 t2 = vec[i+1] ;
00207
00208 if ( !AreDifferent(t1->GetConstant(),t2->GetConstant(),epsilon) ) {
00209
00210
00211 float mean = 0.5*(t1->GetConstant()+t2->GetConstant()) ;
00212 t1->Set(t1->GetX(),mean,t1->GetSlope()) ;
00213 delete t2 ;
00214 t2 = 0 ;
00215 fNItems-- ;
00216 size_t j ;
00217 for ( j = i+1 ; j < vec.size()-1 ; j++ ) {
00218 vec[j] = vec[j+1] ;
00219 }
00220 vec.pop_back() ;
00221 --i ;
00222 }
00223 }
00224 return true ;
00225 }
00226
00227
00228
00229 emcGainFEM*
00230 emcGainFEM::Default(int absPosition,
00231 const PHTimeStamp& tStart, const PHTimeStamp& tEnd)
00232 {
00233 emcGainFEM* fem = new emcGainFEM(absPosition,tStart,tEnd) ;
00234
00235 fem->SetNumberOfChannels(144) ;
00236
00237 size_t i ;
00238 for ( i = 0 ; i < 144 ; i++ ) {
00239 fem->AddNewItem(i,new emcTracedValue(0,1,0)) ;
00240 }
00241
00242 return fem ;
00243
00244 }