emcTracedFEM.C

Go to the documentation of this file.
00001 #include "emcTracedFEM.h"
00002 #include "emcTracedValue.h"
00003 #include <iostream>
00004 #include <cassert>
00005 #include <ctime>
00006 #include <string>
00007 #include <cmath>
00008 
00009 using std::string;
00010 
00011 static string name = "emcTracedFEM" ;
00012 static string title = "Traced calibration data (base class)" ;
00013 static string classname = "emcTracedFEM" ;
00014 
00015 namespace {
00016 
00017   bool compare(Float_t x1, Float_t x2, float epsilon=1E-4) 
00018   {
00019     if ( x1 == 0 && x2 == 0 )
00020       {
00021         return true;
00022       }
00023 
00024     if ( std::abs((x1-x2)/x2) < epsilon ) 
00025       {
00026         return true;
00027       }
00028     else
00029       {
00030         return false;
00031       }
00032   }
00033 }
00034 
00035 //_____________________________________________________________________________
00036 emcTracedFEM::emcTracedFEM(int absPosition)
00037   : emcCalFEM(absPosition),
00038     fNItems(0),fCurrentItem(0),fCurrentPosition(0)
00039 
00040 {
00041   NameIt(name,title,classname) ;
00042 }
00043 
00044 //_____________________________________________________________________________
00045 emcTracedFEM::emcTracedFEM(int absPosition,
00046                            const PHTimeStamp& t1, 
00047                            const PHTimeStamp& t2)
00048   : emcCalFEM(absPosition,t1,t2),
00049     fNItems(0),fCurrentItem(0),fCurrentPosition(0)
00050 {  
00051   NameIt(name,title,classname) ;
00052 }
00053 
00054 //_____________________________________________________________________
00055 emcTracedFEM::emcTracedFEM(const emcTracedFEM& o)
00056   : emcCalFEM(o.AbsolutePosition())
00057 {
00058   o.Copy(*this) ;
00059 }
00060 
00061 //_____________________________________________________________________________
00062 emcTracedFEM&
00063 emcTracedFEM::operator=(const emcTracedFEM& o)
00064 {
00065   if ( this == &o ) return *this ;
00066   // de-allocate what we already have.
00067   Delete() ;
00068   o.Copy(*this) ;
00069   return *this ;
00070 }
00071 
00072 //_____________________________________________________________________
00073 void 
00074 emcTracedFEM::Copy(emcTracedFEM& o) const
00075 {
00076   emcCalFEM::Copy(o) ;
00077   o.fItems.resize(fItems.size(),0) ;
00078   size_t i ;
00079   int nitems = 0 ;
00080 
00081   for (i=0;i<fItems.size();i++) {
00082     o.fItems[i] = new emcItemVector ;
00083     size_t j ;
00084     for (j=0;j<fItems[i]->size();j++) {
00085       emcTracedValue* tv = (*fItems[i])[j] ;
00086       o.fItems[i]->push_back(new emcTracedValue(tv->GetX(),
00087                                                 tv->GetConstant(),
00088                                                 tv->GetSlope(),
00089                                                 tv->isConstant())) ;
00090       nitems++ ;
00091     }
00092   }
00093   o.fNItems = nitems ;
00094   assert(o.fNItems==fNItems) ;
00095   o.fCurrentItem = fCurrentItem ;
00096   o.fCurrentPosition = fCurrentPosition ;
00097 }
00098 
00099 //_____________________________________________________________________________
00100 
00101 emcTracedFEM::~emcTracedFEM()
00102 {
00103   Delete() ;
00104 }
00105 
00106 //_____________________________________________________________________________
00107 
00108 void emcTracedFEM::AddNewItem(int channel, emcTracedValue* item)
00109 {
00110   // Add a new item to one channel.
00111   //
00112   // It is assumed that item->GetX() is either greater than
00113   // any of the existing items for this channel or equal to
00114   // one of them (in which case item replaces the old one).
00115   // To put it another way, items are NOT time ordered by this method.
00116 
00117   assert (channel>=0 && channel<static_cast<int>(fItems.size())) ;
00118   assert(fItems[channel]!=0) ;
00119   emcItemVector& itemVector = *(fItems[channel]) ;
00120   emcTracedValue* currentitem ;
00121   size_t i ;
00122   bool inserted = false ;
00123 
00124   for ( i = 0 ; i < itemVector.size() && !inserted ; i++ ) {
00125     currentitem = itemVector[i] ;
00126     assert(currentitem!=0) ;
00127     if ( currentitem->GetX() == item->GetX() ) {
00128       // we replace currentitem by item, because both are starting
00129       // at the same time
00130       delete currentitem ;
00131       itemVector[i] = item ;
00132       inserted = true ;
00133     }
00134   }
00135   if (!inserted) {
00136     fNItems++ ; 
00137     itemVector.push_back(item) ;
00138   }
00139 }
00140 
00141 
00142 //_____________________________________________________________________________
00143 void emcTracedFEM::Delete(void)
00144 {
00145   // Delete internal storage memory space.
00146   size_t i,j ;
00147 
00148   for ( i = 0 ; i < fItems.size() ; i++ ) {
00149     assert(fItems[i]!=0) ;
00150     emcItemVector& itemVector = *(fItems[i]) ;
00151     for ( j = 0 ; j < itemVector.size() ; j++ ) {
00152       delete itemVector[j] ;      
00153       itemVector[j] = 0 ;
00154     }
00155     delete fItems[i] ;
00156     fItems[i] = 0 ;
00157   }
00158 
00159   fItems.clear() ;
00160   fNItems = 0 ;
00161 }
00162 
00163 //_____________________________________________________________________________
00164 void emcTracedFEM::FirstItem(int channel) const
00165 {
00166     // Position the internal iterator to the first item for channel
00167   assert (channel>=0 && channel<static_cast<int>(fItems.size()));
00168   fCurrentItem = channel ;
00169   fCurrentPosition = 0 ;
00170 }
00171 
00172 //_____________________________________________________________________________
00173 size_t
00174 emcTracedFEM::GetNumberOfItems(int ichannel) const
00175 {
00176   if ( ichannel < 0 || ichannel >= static_cast<int>(fItems.size()) ) return 0;
00177   emcItemVector* vec = fItems[ichannel] ;
00178   if ( vec ) return vec->size() ;
00179   return 0 ;
00180 }
00181 
00182 //_____________________________________________________________________________
00183 emcTracedValue* 
00184 emcTracedFEM::getTV(int ichannel, time_t absoluteX, size_t& thecase) const 
00185 {
00186   /* 
00187      For a given channel, recover the piece of line valid for absoluteX.
00188 
00189      (absolute)X have 2 different meanings :
00190      a) For PbSc : X=tics=a "time"
00191      b) For PbGl : X=run number
00192 
00193      The internal value used is not directly absoluteX, but 
00194      x = absoluteX - GetXmin(), i.e. a relative X.
00195 
00196      Depending on x, 4 cases are to be considered :
00197      1. x is < xmin of the first tracedvalue
00198      2. x falls within the validity range of one of the tracedvalues
00199      3. x is after the last tracedvalue valid x, but
00200         before GetXmax
00201      4. x is after GetXmax
00202    */
00203 
00204   int x = static_cast<int>(absoluteX - GetXmin()) ; 
00205   
00206   emcItemVector* vec = fItems[ichannel] ;
00207   assert(vec!=0) ;
00208   emcItemVector& fTracedValues = *vec ;
00209 
00210   if (fTracedValues.size()==0) { return 0 ; }
00211 
00212   if ( x <= fTracedValues[0]->GetX() ) {
00213     // x requested is before first valid x : we return
00214     // the first item
00215     thecase = 1 ; 
00216     return fTracedValues[0] ;
00217   }
00218 
00219   bool inside = false ;
00220   int i ;
00221   int n = static_cast<int>(fTracedValues.size()) ;
00222 
00223   for ( i = 0 ; i < n-1 && !inside ; i++ ) {
00224     assert(fTracedValues[i]!=0) ;
00225     assert(fTracedValues[i+1]!=0) ;
00226     if ( x >= fTracedValues[i]->GetX() && 
00227          x < fTracedValues[i+1]->GetX() ) inside = true ;
00228   } 
00229 
00230   if (inside) {
00231     thecase = 2 ; 
00232     // requested x falls within validity period of a tracedvalue
00233     // we return this tracedvalue
00234     assert(fTracedValues[i-1]!=0) ;    
00235     return fTracedValues[i-1] ;
00236   }
00237 
00238   int xrelmax = GetXmax()-GetXmin() ;
00239   assert(fTracedValues[n-1]!=0) ;
00240   if ( x>= fTracedValues[n-1]->GetX() && x<=xrelmax ) {
00241     thecase = 3 ;
00242     // Requested x is after last tracedvalue x, but still
00243     // in authorized extrapolation region
00244   }
00245   else {
00246     // Requested x is after xmax. 
00247     thecase = 4 ;
00248   }
00249   return fTracedValues[n-1] ;
00250 }
00251 
00252 //_____________________________________________________________________________
00253 float 
00254 emcTracedFEM::getValueFast(int ichannel, time_t absoluteX) const
00255 {
00256   /* 
00257      (absolute)X have 2 different meanings :
00258      a) For PbSc : X=tics=a "time"
00259      b) For PbGl : X=run number
00260 
00261      The internal value used is not directly absoluteX, but 
00262      x = absoluteX - GetXmin(), i.e. a relative X.
00263 
00264      Depending on x, 4 cases are to be considered :
00265      1. x is < xmin of the first tracedvalue
00266         -> we return the constant of the first tracedvalue
00267      2. x falls within the validity range of one of the tracedvalues
00268         -> we let this tracedvalue compute the correct value for this x
00269      3. x is after the last tracedvalue valid x, but
00270         before GetXmax
00271         -> we let the last tracedvalue extrapolate to x
00272      4. x is after GetXmax
00273         -> we return the last tracedvalue extrapolation up to Xmax
00274    */
00275 
00276   size_t thecase ;
00277 
00278   emcTracedValue* tv = getTV(ichannel, absoluteX, thecase) ;
00279 
00280   float rv = 0.0 ;
00281 
00282   if (!tv) thecase = 0 ;
00283 
00284   int x = static_cast<int>(absoluteX - GetXmin()) ; 
00285   int xrelmax = static_cast<int>(GetXmax()-GetXmin()) ;
00286 
00287   switch (thecase) {
00288 
00289   case 0 :
00290     rv = 1.0 ;
00291     break;
00292   case 1:
00293     rv = tv->GetConstant() ;
00294     break ;
00295   case 2:
00296   case 3: // same as 2
00297     rv = tv->getValue(x) ;
00298     break ;
00299   case 4:
00300     rv = tv->getValue(xrelmax) ;
00301     break ;
00302   default:
00303     assert(0==1) ;
00304     break;
00305   }
00306 
00307   return rv ;
00308 }
00309 
00310 //_____________________________________________________________________________
00311 bool
00312 emcTracedFEM::IsEqual(const emcCalFEM& obj) const 
00313 {
00314   const emcTracedFEM* tfem = dynamic_cast<const emcTracedFEM*>(&obj) ;
00315   if (!tfem) return false ;
00316 
00317   if ( size() != obj.size() ) return false ;
00318 
00319   emcTracedValue* me;
00320   emcTracedValue* other;
00321 
00322   for ( size_t ichannel = 0 ; ichannel < size() ; ichannel++) {
00323     FirstItem(ichannel) ;
00324     tfem->FirstItem(ichannel) ;
00325     while ( ( me = NextItem() ) ) {
00326       other = tfem->NextItem() ;
00327       // tricky equality between emcTracedValue, due
00328       // to strange semantics of emcTracedValue::operator== ?!?!
00329       if ( me->GetX() != other->GetX() ) 
00330         {
00331           return false ;
00332         }
00333       if ( !compare(me->GetConstant(),other->GetConstant())) 
00334         {
00335           return false ;
00336         }
00337       if ( !compare(me->GetSlope(),other->GetSlope())) 
00338         {
00339           return false ;
00340         }
00341       if ( me->isConstant() != other->isConstant()) 
00342         {
00343           return false ;
00344         }
00345     }
00346   }
00347 
00348   return true ;
00349 }
00350 
00351 //_____________________________________________________________________________
00352 emcTracedValue* 
00353 emcTracedFEM::LastItem(int channel) const
00354 {
00355   if ( channel >= static_cast<int>( fItems.size() ) ||
00356        channel < 0 ) {
00357     return 0 ;
00358   }
00359  
00360   emcTracedValue* tv = 0 ;      
00361   emcItemVector* vec = fItems[channel] ;
00362 
00363   if (vec) {
00364     int i = vec->size()-1 ;
00365     if (i>=0) {
00366       tv = (*vec)[i] ;
00367     }
00368   }
00369   return tv ;
00370 }
00371 
00372 //_____________________________________________________________________________
00373 emcTracedValue* emcTracedFEM::NextItem(void) const
00374 {
00375   // Iterate forward
00376   emcTracedValue* rv = 0 ;
00377 
00378   if (fCurrentItem<fItems.size()) {
00379     emcItemVector* vec = fItems[fCurrentItem] ;
00380     assert(vec!=0) ;
00381     if (fCurrentPosition<vec->size()) {
00382       rv = (*vec)[fCurrentPosition] ;
00383       fCurrentPosition++ ;
00384     }
00385   }
00386   return rv ;
00387 }
00388 
00389 //_____________________________________________________________________
00390 std::ostream&
00391 emcTracedFEM::Print(std::ostream& out, int level) const
00392 {
00393   emcCalFEM::Print(out,level) ;
00394 
00395   if (level) {
00396     out << "xmin=" << GetXmin() << " xmax=" << GetXmax() << std::endl ;
00397     for ( size_t i = 0 ; i < fItems.size() ; i++) {
00398       emcItemVector* vec = fItems[i] ;
00399       if (vec) {
00400         for (size_t j = 0; j < vec->size() ; j++) {
00401           out << i << " " << *((*vec)[j]) ;
00402         }
00403       }
00404     }
00405   }
00406   return out ;
00407 }
00408 
00409 //_____________________________________________________________________________
00410 void
00411 emcTracedFEM::RemoveLastItems(void)
00412 {
00413   // Remove the last item of each channel.
00414 
00415   for (size_t i = 0 ; i < fItems.size() ; ++i) {
00416     emcItemVector* vec = fItems[i] ;
00417     if (vec) {
00418       emcTracedValue* last = vec->back() ;
00419       delete last ;
00420       last = 0 ;
00421       vec->pop_back() ;
00422       --fNItems ;
00423     }
00424   }
00425 }
00426 
00427 //_____________________________________________________________________________
00428 void emcTracedFEM::Reset(void)
00429 {
00430   Delete() ;
00431   SetXmin(0) ;
00432   SetXmax(0) ;
00433 }
00434 
00435 //_____________________________________________________________________________
00436 void emcTracedFEM::SetNumberOfChannels(int number_of_channels)
00437 {
00438   assert (number_of_channels>=0) ;
00439 
00440   Delete() ;
00441   fItems.resize(number_of_channels) ;
00442 
00443   for( size_t i = 0 ; i < fItems.size() ; i++ ) {
00444     fItems[i] = new emcItemVector() ;
00445   }
00446 }
00447 
00448 //_____________________________________________________________________________
00449 void emcTracedFEM::writeDataToFile(FILE* fp) const
00450 {
00451   time_t tics = GetStartValTime().getTics(); 
00452   char timeString[25]; 
00453   timeString[24] = '\0'; 
00454   strncpy(timeString, ctime(&tics), 24);   
00455   fprintf(fp,"%s\n",timeString) ;
00456 
00457   size_t i,j ;
00458   int item = 0 ;
00459 
00460   for (i=0;i<fItems.size();i++) {
00461     assert(fItems[i]!=0) ;
00462     emcItemVector& itemVector = *(fItems[i]) ;
00463     for (j=0;j<itemVector.size();j++) {    
00464       fprintf(fp," %5d", item) ;
00465       itemVector[j]->writeData(fp) ;
00466       fprintf(fp,"\n") ;
00467     }
00468     item++ ;
00469   }
00470   fprintf(fp,"144 %ld 0 0\n",GetXmax());
00471   fprintf(fp,"145 %ld 0 0\n",GetXmin());
00472 }