emcGainFEM.C

Go to the documentation of this file.
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   // Here ichannel is supposed to be valid
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 ) { // protection against "zero-ed" lines.
00137 
00138       // xs is the start X of the line
00139       float xs1 = t1->GetX() ;
00140       float xs2 = t2->GetX() ;
00141       // xe is the end X of the 2nd line
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       // extand t1 line and delete t2 (i.e. t1 "absorbs" t2).
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   // Here ichannel is supposed to be valid.
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       // merge t1 and t2 
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 }