emcGainBaseLineCalculator.C

Go to the documentation of this file.
00001 #include "emcGainBaseLineCalculator.h"
00002 
00003 #include "emcCalFEM.h"
00004 #include "emcCalibrationDataHelper.h"
00005 #include "emcFEMList.h"
00006 #include "EmcIndexer.h"
00007 #include "PHTimeStamp.h"
00008 #include "TH1.h"
00009 #include "TH2.h"
00010 #include "TDirectoryHelper.h"
00011 #include <cassert>
00012 #include <cmath>
00013 #include <set>
00014 #include <vector>
00015 #include <string>
00016 #include <iostream>
00017 #include <iterator>
00018 #include <list>
00019 #include <algorithm>
00020 #include <sstream>
00021 
00022 using namespace std;
00023 
00024 int emcGainBaseLineCalculator::fRefRunNumber = -1;
00025 int emcGainBaseLineCalculator::fCurrentRunNumber = -1;
00026 emcCalibrationDataHelper* emcGainBaseLineCalculator::fCDH0 = 0;
00027 std::map<std::string, TH1*> emcGainBaseLineCalculator::fHistos;
00028 bool emcGainBaseLineCalculator::fHistogramming = false;
00029 
00030 
00031 namespace
00032 { 
00033   void 
00034   distributionShape(const std::vector<emcGainBaseLineCalculator::Tuple>& vx, 
00035                     double mean, 
00036                     unsigned int k,
00037                     float& variance,
00038                     float& skewness,
00039                     float& kurtosis)
00040   {
00041     double m2 = 0.0;
00042     double m3 = 0.0;
00043     double m4 = 0.0;
00044     
00045     unsigned int n = vx.size()-1;
00046 
00047     for ( size_t i = k; i <= n - k ; ++i )
00048       {
00049         double x = vx[i].value() - mean;
00050         m2 += x*x;
00051         m3 += x*x*x;
00052         m4 += x*x*x*x;
00053       }
00054     
00055     m2 /= n;
00056     m3 /= n;
00057     m4 /= n;
00058     double s = sqrt(m2);
00059     
00060     skewness = m3/(s*s*s);
00061     kurtosis = m4/(s*s*s*s);
00062     variance = m2;
00063 
00064   }
00065 
00066   int getIz(const emcGainBaseLineCalculator::Tuple& x)
00067   {
00068     int towerid = x.towerid();
00069     int is,iy,iz;
00070     EmcIndexer::decodeTowerId(towerid,is,iz,iy);
00071     return iz;
00072   }
00073 
00074   int getIy(const emcGainBaseLineCalculator::Tuple& x)
00075   {
00076     int towerid = x.towerid();
00077     int is,iy,iz;
00078     EmcIndexer::decodeTowerId(towerid,is,iz,iy);
00079     return iy;
00080   }
00081 
00082   class BLMethod
00083   {
00084   public:
00085     
00086     BLMethod() : fZeroSuppressed(false), fPercentage(0) {}
00087 
00088     void zeroSuppressed(bool yesorno) { fZeroSuppressed=yesorno; }
00089     bool isZeroSuppressed(void) const { return fZeroSuppressed; }
00090 
00091     float percentage() const { return fPercentage; }
00092     void percentage(float v) { fPercentage = v; }
00093 
00094     virtual 
00095     void compute(const std::vector<emcGainBaseLineCalculator::Tuple>& gt,
00096                  std::vector<emcGainBaseLineCalculator::Tuple>& gt0,
00097                  std::vector<int>& reject,
00098                  float& value,
00099                  float& error_on_value,
00100                  float& skewness,
00101                  float& kurtosis) = 0;
00102   private:
00103     bool fZeroSuppressed;
00104     float fPercentage;
00105   };
00106   
00107   float ratio(float a, float b, float epsilon)
00108   {
00109     if ( fabs(b) > epsilon )
00110       {
00111         return a / b;
00112       }
00113     else
00114       {
00115         return 0.0;
00116       }
00117   }
00118 
00119   void split(const std::string& s,
00120              const char sep,
00121              std::vector<std::string>& parts)
00122   {
00123     std::string str = s;
00124 
00125     std::vector<size_t> sep_pos;
00126 
00127     if ( str[0] != sep )
00128       {
00129         str.insert(str.begin(), sep);
00130       }
00131 
00132     if ( str[str.size() - 1] != sep )
00133       {
00134         str.push_back(sep);
00135       }
00136 
00137     for (size_t i = 0 ; i < str.size() ; i++)
00138       {
00139         if ( str[i] == sep )
00140           {
00141             sep_pos.push_back(i);
00142           }
00143       }
00144 
00145     parts.clear();
00146 
00147     if ( sep_pos.size() > 0 )
00148       {
00149         for (size_t i = 0 ; i < sep_pos.size() - 1 ; i++)
00150           {
00151             parts.push_back(str.substr(sep_pos[i] + 1,
00152                                        sep_pos[i + 1] - sep_pos[i] - 1));
00153           }
00154       }
00155   }
00156 
00157 
00158   std::string patch(const std::string& src)
00159   {
00160     std::string dest = src;
00161     for ( size_t i = 0; i < dest.size(); ++i )
00162       {
00163         if ( dest[i] == ':' )
00164           {
00165             dest[i] = '_';
00166           }
00167         if ( dest[i] == '-' )
00168           {
00169             dest.erase(i, 1);
00170           }
00171       }
00172     return dest;
00173   }
00174 
00175   std::string buildBasename(int run, int isector, const char* details)
00176   {
00177     std::ostringstream str;
00178 
00179     str << run << "/" << EmcIndexer::EmcSectorId(isector)
00180         << "_" << patch(details);
00181 
00182     return str.str();
00183   }
00184 
00185   std::ostream& operator<<(std::ostream& os, 
00186                            const emcGainBaseLineCalculator::Tuple& fp)
00187   {
00188     os << "[" << fp.index() << "," << fp.value() << "] ";
00189     return os;
00190   }
00191 
00192   int trim(const std::vector<emcGainBaseLineCalculator::Tuple>& x,
00193            const float& alpha,
00194            float& tmean, float& tvar,
00195            unsigned int& k,
00196            std::vector<emcGainBaseLineCalculator::Tuple>& sx,
00197            std::vector<int>& reject)
00198   {
00199     //
00200     // Calculates the trimmed (tmean) mean
00201     // of a sample (x) and estimates the variance (tvar)
00202     // of that mean.
00203     //
00204 
00205     // First check input parameters
00206 
00207     unsigned int n = x.size(); // number of observations
00208     if ( n < 2 )
00209       {
00210         return -1;
00211       }
00212 
00213     if ( alpha < 0 || alpha >= 0.5 )
00214       // proportion of observations
00215       // to be trimmed at each end of the sorted sample
00216       {
00217         return -2;
00218       }
00219 
00220     // Input parameters are good. Let's move on.
00221 
00222     // Insure we use a sample sorted into ascending order.
00223 
00224     sx = x;
00225     std::sort(sx.begin(), sx.end());
00226 
00227     // Number of observations trimmed at each end.
00228 
00229     k = static_cast<unsigned int>(floorf(alpha * n));
00230 
00231     float sum = 0.0;
00232 
00233     for ( size_t i = k; i < n - k ; ++i )
00234       {
00235         sum += sx[i].value();
00236       }
00237 
00238     tmean = sum / ( n - 2 * k );
00239 
00240     float t2 = 0.0;
00241 
00242     for ( size_t i = k; i < n - k; ++i )
00243       {
00244         t2 += (sx[i].value() - tmean) * (sx[i].value() - tmean);
00245       }
00246 
00247     tvar = (
00248             t2 +
00249             k * (sx[k].value() - tmean) * (sx[k].value() - tmean) +
00250             k * (sx[n - k - 1].value() - tmean) * (sx[n - k - 1].value() - tmean)
00251             ) / (n * n);
00252 
00253     // mark the rejected entries as such
00254     for ( size_t i = 0; i < k; ++i ) 
00255       {
00256         reject[sx[i].index()]=1;
00257       }
00258 
00259     for ( size_t i = n - k; i < n; ++i ) 
00260       {
00261         reject[sx[i].index()]=1;
00262       }
00263 
00264     return 0;
00265   }
00266 
00267   void zeroSuppress(const std::vector<emcGainBaseLineCalculator::Tuple>& in,
00268                     std::vector<emcGainBaseLineCalculator::Tuple>& out,
00269                     float epsilon,
00270                     std::vector<int>& reject)
00271   {
00272     out.clear();
00273     for ( size_t i = 0; i < in.size(); ++i )
00274       {
00275         if ( std::fabs(in[i].value()) < epsilon )
00276           {
00277             reject[in[i].index()] = 1;
00278           }
00279         else
00280           {
00281             out.push_back(in[i]);
00282           }
00283       }
00284   }
00285 
00286   class BLM_RatioOfAverages : public BLMethod
00287   {
00288   public:
00289     void compute(const std::vector<emcGainBaseLineCalculator::Tuple>& gt,
00290                  std::vector<emcGainBaseLineCalculator::Tuple>& gt0,
00291                  std::vector<int>& reject,
00292                  float& value,
00293                  float& error_on_value,
00294                  float& skewness,
00295                  float& kurtosis)
00296     {
00297       if ( gt0.empty() )
00298         {
00299           for ( size_t i = 0; i < gt.size(); ++i )
00300             {
00301               gt0.push_back(emcGainBaseLineCalculator::Tuple(gt[i].index(),gt[i].towerid(),1.0));
00302             }
00303         }
00304 
00305       value = 0;
00306       error_on_value = 0;
00307     
00308       float mgt, egt;
00309       float mgt0, egt0;
00310 
00311       std::vector<emcGainBaseLineCalculator::Tuple> cgt;
00312       std::vector<emcGainBaseLineCalculator::Tuple> cgt0;
00313 
00314       reject.resize(gt.size());
00315 
00316       for ( size_t i = 0; i < gt.size(); ++i )
00317         {
00318           assert(gt[i].index()==gt0[i].index());
00319           bool both_non_zero = ( gt[i].value() != 0 && gt0[i].value() != 0 );
00320 
00321           if ( !isZeroSuppressed() || 
00322                (isZeroSuppressed() && both_non_zero) 
00323                )
00324             {
00325               cgt.push_back(gt[i]);
00326               cgt0.push_back(gt0[i]);
00327               reject[gt[i].index()] = 0;
00328             }
00329           else
00330             {
00331               reject[gt[i].index()] = 1;
00332              }
00333         }
00334 
00335       std::vector<emcGainBaseLineCalculator::Tuple> sx;
00336       std::vector<emcGainBaseLineCalculator::Tuple> sx0;
00337       unsigned int k;
00338       unsigned int k0;
00339 
00340       int error = trim(cgt, percentage(), mgt, egt, k, sx, reject);      
00341       int error0 = trim(cgt0, percentage(), mgt0, egt0, k0, sx0, reject);
00342       assert(k==k0);
00343 
00344       if ( error || error0 )
00345         {
00346           std::cerr << __FILE__ << ":" << __LINE__ << " trim error."
00347                     << std::endl;
00348           return;
00349         }
00350 
00351       const float epsilon = 1E-3;
00352 
00353       value = ratio(mgt, mgt0, epsilon);
00354 
00355       egt = ratio(sqrt(egt), mgt, epsilon);
00356       egt0 = ratio(sqrt(egt), mgt0, epsilon);
00357 
00358       error_on_value = sqrt(egt * egt + egt0 * egt0);
00359 
00360       float variance;
00361 
00362       distributionShape(cgt,mgt,k,variance,skewness,kurtosis);
00363     }
00364   };
00365 
00366 
00375   class BLM_AverageOfRatios : public BLMethod
00376   {
00377   public:
00378     void compute(const std::vector<emcGainBaseLineCalculator::Tuple>& gt,
00379                  std::vector<emcGainBaseLineCalculator::Tuple>& gt0,
00380                  std::vector<int>& reject,
00381                  float& value,
00382                  float& error_on_value,
00383                  float& skewness,
00384                  float& kurtosis)
00385     {
00386       if ( gt0.empty() )
00387         {
00388           gt0 = gt;
00389         }
00390 
00391       value = 0;
00392       error_on_value = 0;
00393       skewness = 0;
00394       kurtosis = 0;
00395 
00396       reject.resize(gt.size());
00397 
00398       std::vector<emcGainBaseLineCalculator::Tuple> values;
00399       std::vector<emcGainBaseLineCalculator::Tuple> sgt;
00400       std::vector<emcGainBaseLineCalculator::Tuple> sgt0;
00401 
00402       const float epsilon = 1E-3;
00403 
00404       if ( isZeroSuppressed() )
00405         {
00406           // Zero suppress both g(t) and g(t0) if so required.
00407           zeroSuppress(gt,sgt,epsilon,reject);
00408           zeroSuppress(gt0,sgt0,epsilon,reject);
00409         }
00410 
00411       std::vector<emcGainBaseLineCalculator::Tuple> sx;
00412       std::vector<emcGainBaseLineCalculator::Tuple> sx0;
00413       unsigned int k;
00414       unsigned int k0;
00415       float dummy;
00416 
00417       // Trim the zero-suppressed g(t) and gt(0).
00418       // What is really important after the 2 trim calls is the content
00419       // of the reject[] array.
00420       int error = trim(sgt, percentage(), dummy, dummy, k, sx, reject);      
00421       int error0 = trim(sgt0, percentage(), dummy, dummy, k0, sx0, reject);
00422 
00423       if ( error || error0 )
00424         {
00425           std::cerr << __FILE__ << ":" << __LINE__ << " trim error."
00426                     << std::endl;
00427           return;
00428         }
00429 
00430       // Compute the ratios only for the gains which survived both
00431       // the zero suppression and the trimming.
00432       for ( size_t i = 0; i < gt.size(); ++i )
00433         {
00434           assert(gt[i].index()==gt0[i].index());
00435           assert(gt[i].towerid()==gt0[i].towerid());
00436 
00437           if ( reject[gt[i].index()] ) continue;
00438 
00439           float value = ratio(gt[i].value(), gt0[i].value(), epsilon);
00440 
00441           if ( !isZeroSuppressed() || 
00442                (isZeroSuppressed() && value != 0 ) )
00443             {
00444               values.push_back(emcGainBaseLineCalculator::Tuple(i,gt[i].towerid(),value));
00445             }
00446           else
00447             {
00448               reject[gt[i].index()]=1;
00449             }
00450         }
00451 
00452       if ( values.empty() )
00453         {
00454           std::cerr << __FILE__ << ":" << __LINE__ << " No values."
00455                     << std::endl;
00456           return;
00457         }
00458 
00459       // Finally we trim those ratios too to get the final answer.
00460       error = trim(values, percentage(), value, error_on_value, 
00461                    k, sx, reject);
00462 
00463       if ( error )
00464         {
00465           std::cerr << __FILE__ << ":" << __LINE__ << " trim error."
00466                     << std::endl;
00467           value = 0;
00468           error_on_value = 0;
00469           return;
00470         }
00471       
00472       float variance;
00473 
00474       distributionShape(values,value,k,variance,skewness,kurtosis);
00475 
00476       error_on_value = sqrt(error_on_value);
00477     }
00478   };
00479 
00480   class BLM_AverageOfAsymetries : public BLMethod
00481   {
00482   public:
00483     void compute(const std::vector<emcGainBaseLineCalculator::Tuple>& gt,
00484                  std::vector<emcGainBaseLineCalculator::Tuple>& gt0,
00485                  std::vector<int>& reject,
00486                  float& value,
00487                  float& error_on_value,
00488                  float& skewness,
00489                  float& kurtosis)
00490     {
00491       if ( gt0.empty() )
00492         {
00493           // that a non-sense request. Let the value be nonsense too.
00494           const float some_crazy_high_number = 1E9;
00495           for ( size_t i = 0; i < gt.size(); ++i )
00496             {
00497               emcGainBaseLineCalculator::Tuple t = 
00498                 emcGainBaseLineCalculator::Tuple(gt[i].index(),
00499                                                  gt[i].towerid(),
00500                                                  some_crazy_high_number);
00501               gt0.push_back(t);
00502             }
00503         }
00504 
00505       value = 0;
00506       error_on_value = 0;
00507       skewness = 0;
00508       kurtosis = 0;
00509 
00510       std::vector<emcGainBaseLineCalculator::Tuple> values;
00511 
00512       const float epsilon = 1E-3;
00513 
00514       reject.resize(gt.size());
00515    
00516       for ( size_t i = 0; i < gt.size(); ++i )
00517         {
00518           assert(gt[i].index()==gt0[i].index());
00519           assert(gt[i].towerid()==gt0[i].towerid());
00520           float value = ratio(gt[i].value()-gt0[i].value(), 
00521                               gt[i].value()+gt0[i].value(), epsilon);
00522           
00523           if ( !isZeroSuppressed() || 
00524                (isZeroSuppressed() && value != 0 ) )
00525             {
00526               reject[gt[i].index()] = 0;
00527               values.push_back(emcGainBaseLineCalculator::Tuple(i,gt[i].towerid(),value));
00528             }
00529           else
00530             {
00531               reject[gt[i].index()] = 1;
00532             }
00533         }
00534 
00535       if ( values.empty() )
00536         {
00537           return;
00538         }
00539 
00540       std::vector<emcGainBaseLineCalculator::Tuple> sx;
00541       unsigned int k;
00542 
00543       int error = trim(values, percentage(), value, error_on_value, 
00544                        k, sx, reject);
00545 
00546       float variance;
00547 
00548       distributionShape(values,value,k,variance,skewness,kurtosis);
00549 
00550       if ( error )
00551         {
00552           std::cerr << __FILE__ << ":" << __LINE__ << " trim error."
00553                     << std::endl;
00554           value = 0;
00555           error_on_value = 0;
00556           return;
00557         }
00558 
00559       error_on_value = sqrt(error_on_value);
00560       
00561     }
00562   };
00563 
00564   int decodeRunNumber(const std::string str)
00565   {
00566     bool ok = true;
00567 
00568     for ( size_t i = 0; i < str.size() && ok; ++i ) 
00569       {
00570         if (!isdigit(str[i])) ok=false;
00571       }
00572     if (!ok)
00573       {
00574         return -1;
00575       }
00576     else
00577       {
00578         return atoi(str.c_str());
00579       }
00580   }
00581 
00582   BLMethod* decodeDetails(const std::string& details,
00583                           std::set<int>& femsToDiscard,
00584                           float& percent,
00585                           int& xminxxmax,
00586                           bool& zerosuppressed,
00587                           int& runnumber)
00588   {
00589     femsToDiscard.clear();
00590     percent = 0;
00591     xminxxmax = -1;
00592     zerosuppressed = false;
00593     BLMethod* method = 0;
00594     bool methodSpecified = false;
00595     bool runnumberSpecified = false;
00596 
00597     std::vector<std::string> parts;
00598 
00599     split(details, ':', parts);
00600 
00601     std::list<int> residualParts; 
00602     // list to keep track of indices
00603     // of parts. By the time the decoding below is finished,
00604     // this list should be empty. If not, it means something 
00605     // in the decoding went wrong (most probably a syntax error
00606     // in the details string, e.g. method's name).
00607 
00608     for ( size_t i = 0; i < parts.size(); ++i )
00609       {
00610         residualParts.push_back(i);
00611       }
00612 
00613     if ( parts.size() > 0)
00614       {
00615         percent = atoi(parts[0].c_str());
00616         if ( percent<0 || percent >= 50 )
00617           {
00618             std::cerr << __FILE__ << ":" << __LINE__ 
00619                       << "percent=" << percent << "!!"
00620                       << std::endl;
00621             return 0;
00622           }
00623         percent /= 100;
00624         residualParts.remove(0);
00625       }
00626 
00627     for ( size_t i = 1; i < parts.size(); ++i )
00628       {
00629         if ( parts[i] == "xmin" )
00630           {
00631             xminxxmax = -1;
00632             residualParts.remove(i);
00633           }
00634         if ( parts[i] == "xmax" )
00635           {
00636             xminxxmax = + 1;
00637             residualParts.remove(i);
00638           }
00639         if ( parts[i] == "x" )
00640           {
00641             xminxxmax = 0;
00642             residualParts.remove(i);
00643           }
00644 
00645         if ( parts[i][0] == '-' )
00646           {
00647             femsToDiscard.insert(atoi(parts[i].c_str() + 1));
00648             residualParts.remove(i);
00649           }
00650 
00651         if ( parts[i] == "ZS" )
00652           {
00653             zerosuppressed = true;
00654             residualParts.remove(i);
00655           }
00656 
00657         if ( parts[i] == "RATIOOFAV" )
00658           {
00659             method = new BLM_RatioOfAverages();
00660             methodSpecified = true;
00661             residualParts.remove(i);
00662           }
00663 
00664         if ( parts[i] == "AVOFRATIO" )
00665           {
00666             method = new BLM_AverageOfRatios();
00667             methodSpecified = true;
00668             residualParts.remove(i);
00669           }
00670 
00671         if ( parts[i] == "AVOFASYM" )
00672           {
00673             method = new BLM_AverageOfAsymetries();
00674             methodSpecified = true;
00675             residualParts.remove(i);
00676           }
00677 
00678 //      if ( parts[i] == "GAUSRATIO" )
00679 //        {
00680 //          return BLM_GaussianFitOfRatios();
00681 //          methodSpecified = true;
00682 //        }
00683       }
00684 
00685     //    runnumber = atoi(parts[parts.size() - 1].c_str());
00686     runnumber = decodeRunNumber(parts[parts.size()-1]);
00687     if (runnumber>=0 )
00688       {
00689         residualParts.remove(parts.size()-1);
00690         runnumberSpecified=true;
00691       }
00692 
00693     if ( !runnumberSpecified )
00694       {
00695         // let it be 0 by default to be backward compatible.
00696         runnumber = 0;
00697       }
00698 
00699     if ( !residualParts.empty() )
00700       {
00701         std::cerr << __FILE__ << ":" << __LINE__ << " details' string="
00702                   << details << " is not valid. Here are the residues "
00703                   << "(separated by |) : "
00704                   << std::endl;
00705         while ( !residualParts.empty() )
00706           {
00707             int ix = residualParts.front();
00708             residualParts.pop_front();
00709             std::cerr << parts[ix] << " | " << std::endl;
00710           }
00711         return 0;
00712       }
00713 
00714     if (!(xminxxmax == -1 || xminxxmax == 0 || xminxxmax == 1))
00715       {
00716         std::cerr << __FILE__ << ":" << __LINE__ << " details' string="
00717                   << details << " is not valid. xminxxmax decoded to "
00718                   << xminxxmax
00719                   << std::endl;
00720         return 0;
00721       }
00722 
00723     if (!methodSpecified)
00724       {
00725         // for backward compatibility.
00726         // Note that this test is made only AFTER we check that 
00727         // the FULL details string is correct (e.g. we correctly
00728         // handle the case where the method name is mispelled)
00729         method = new BLM_RatioOfAverages();
00730       }
00731 
00732     method->zeroSuppressed(zerosuppressed);
00733     method->percentage(percent);
00734     return method;
00735   }
00736 
00737 }
00738 
00739 //_____________________________________________________________________________
00740 void
00741 emcGainBaseLineCalculator::histogramming(bool onoff)
00742 {
00743   fHistogramming = onoff;
00744 }
00745 
00746 //_____________________________________________________________________________
00747 TH1*
00748 emcGainBaseLineCalculator::getHisto(int isector, const char* details,
00749                                     const std::string& suffix)
00750 {
00751   std::string name = buildBasename(fCurrentRunNumber, isector, details);
00752 
00753   name += "_";
00754   name += suffix;
00755 
00756   std::map<std::string, TH1*>::const_iterator it = fHistos.find(name);
00757 
00758   if ( it != fHistos.end() )
00759     {
00760       return it->second;
00761     }
00762   else
00763     {
00764       //      std::cout << "Creating histogram " << name << std::endl;
00765       createHistos(isector, details);
00766       it = fHistos.find(name);
00767       if ( it == fHistos.end() )
00768         {
00769           std::cerr << "<E> emcGainBaseLineCalculator::getHisto : Creation "
00770                     << "failed for " << name << std::endl;
00771           return 0;
00772         }
00773       else
00774         {
00775           return it->second;
00776         }
00777     }
00778 }
00779 
00780 //_____________________________________________________________________________
00781 void
00782 emcGainBaseLineCalculator::createOneHistoPair(const std::string& basename,
00783                                               const std::string& suffix,
00784                                               int nx,
00785                                               double xmin, double xmax)
00786 {
00787   std::string key = basename;
00788   key += "_";
00789   key += suffix;
00790   std::string::size_type pos = key.find_first_of('/');
00791   std::string hname = key.substr(pos + 1);
00792 
00793   TH1* h = new TH1F(hname.c_str(), hname.c_str(), nx, xmin, xmax);
00794      
00795   h->SetDirectory(0);
00796   fHistos[key] = h;
00797 
00798   hname += "_yz";
00799   key += "_yz";
00800 
00801   h = new TH2F(hname.c_str(), hname.c_str(),
00802                72,-0.5,71.5,
00803                36,-0.5,35.5);
00804 
00805   h->SetDirectory(0);
00806   fHistos[key] = h;
00807 }
00808 
00809 //_____________________________________________________________________________
00810 void
00811 emcGainBaseLineCalculator::createHistos(int isector, const char* details)
00812 {
00813   std::string basename = buildBasename(fCurrentRunNumber, isector, details);
00814 
00815   createOneHistoPair(basename, "gt", 100, 0, 400);
00816   createOneHistoPair(basename, "ratio", 100, 0.5, 1.5);
00817   createOneHistoPair(basename, "asym", 100, -0.4, 0.4);
00818 }
00819 
00820 //_____________________________________________________________________________
00821 void
00822 emcGainBaseLineCalculator::deleteHistos()
00823 {
00824   std::map<std::string, TH1*>::iterator it;
00825   for ( it = fHistos.begin(); it != fHistos.end(); ++it )
00826     {
00827       delete it->second;
00828     }
00829   fHistos.clear();
00830 }
00831 
00832 //_____________________________________________________________________________
00833 void
00834 emcGainBaseLineCalculator::fillHistograms(int isector, const char* details,
00835                                           const std::vector<emcGainBaseLineCalculator::Tuple>& gt,
00836                                           const std::vector<emcGainBaseLineCalculator::Tuple>& gt0,
00837                                           const std::vector<int>& reject)
00838 {
00839   assert(gt.size() == gt0.size());
00840   assert(gt.size() == reject.size());
00841 
00842   TH1* hgt = getHisto(isector, details, "gt");
00843   TH2* hgt_yz = static_cast<TH2*>(getHisto(isector, details, "gt_yz"));
00844 
00845   for ( size_t i = 0; i < gt.size(); ++i )
00846     {
00847       if (!reject[i])
00848         {
00849           hgt->Fill(gt[i].value());
00850           hgt_yz->Fill(getIz(gt[i]),getIy(gt[i]),gt[i].value());
00851         }
00852     }
00853 
00854  //  TH1* hgt0 = getHisto(isector, details, "gt0");
00855 //   TH2* hgt0_yz = static_cast<TH2*>(getHisto(isector, details, "gt0_yz"));
00856 
00857 //   for ( size_t i = 0; i < gt0.size(); ++i )
00858 //     {
00859 //       if (!reject[i] )
00860 //         {
00861 //           hgt0->Fill(gt0[i].value());
00862 //        hgt0_yz->Fill(getIz(gt0[i]),getIy(gt0[i]),gt0[i].value());
00863 //         }
00864 //     }
00865 
00866   TH1* hratio = getHisto(isector, details, "ratio");
00867   TH2* hratio_yz = static_cast<TH2*>(getHisto(isector, details, "ratio_yz"));
00868 
00869   for ( size_t i = 0; i < gt0.size(); ++i )
00870     {
00871       if (!reject[i] )
00872         {
00873           float value = 0;
00874           if ( gt0[i].value() )
00875             {
00876               assert(gt[i].towerid()==gt0[i].towerid());
00877               value = gt[i].value() / gt0[i].value();
00878             }
00879           hratio->Fill(value);
00880           hratio_yz->Fill(getIz(gt[i]),getIy(gt[i]),value);
00881         }
00882     }
00883 
00884   TH1* hasym = getHisto(isector, details, "asym");
00885   TH2* hasym_yz = static_cast<TH2*>(getHisto(isector, details, "asym_yz"));
00886 
00887   for ( size_t i = 0; i < gt0.size(); ++i )
00888     {
00889       if (!reject[i] )
00890         {
00891           float value = 0;
00892           if ( gt[i].value() + gt0[i].value() )
00893             {
00894               assert(gt[i].towerid()==gt0[i].towerid());
00895               value = (gt[i].value()-gt0[i].value())/(gt[i].value()+gt0[i].value());
00896             }
00897           hasym->Fill(value);
00898           hasym_yz->Fill(getIz(gt[i]),getIy(gt[i]),value);
00899         }
00900     }
00901 }
00902 
00903 
00904 //_____________________________________________________________________________
00905 bool
00906 emcGainBaseLineCalculator::getBaseLine(emcCalibrationDataHelper* cdh,
00907                                        int isector,
00908                                        const char* details,
00909                                        float& value,
00910                                        float& error_on_value,
00911                                        float& skewness,
00912                                        float& kurtosis)
00913 {
00914   value = 0;
00915   error_on_value = 0;
00916   skewness = 0;
00917   kurtosis = 0;
00918 
00919   std::string sname = EmcIndexer::EmcSectorId(isector);
00920   std::set<int> femsToDiscard;
00921   float percent;
00922   int xminxxmax;
00923   bool zerosuppressed;
00924   int runnumber;
00925 
00926   fCurrentRunNumber = cdh->runNumber();
00927 
00928   emcFEMList* femlist = cdh->femlist();
00929 
00930   // Decode the details to be used for average gain computation
00931   std::auto_ptr<BLMethod> method(decodeDetails(details, femsToDiscard, percent,
00932                                                xminxxmax, zerosuppressed, 
00933                                                runnumber));
00934 
00935   if (!method.get())
00936     {
00937       std::cerr << __FILE__ << ":" << __LINE__ << " Unknown method of "
00938                 << " base line computation" << std::endl;
00939       return false;
00940     }
00941 
00942   std::vector<emcGainBaseLineCalculator::Tuple> gt; // gains at time t
00943   std::vector<emcGainBaseLineCalculator::Tuple> gt0; // gains at time0
00944 
00945   bool ok = get(sname, gt, *cdh, *femlist, femsToDiscard, xminxxmax);
00946   if (!ok) 
00947     {
00948       return false;
00949     }
00950 
00951   if ( runnumber > 0 )
00952     {
00953       if ( fRefRunNumber != runnumber )
00954         {
00955           delete fCDH0;
00956           fCDH0 = new emcCalibrationDataHelper(runnumber, false);
00957           fRefRunNumber = runnumber;
00958         }
00959       ok = get(sname, gt0, *fCDH0, *femlist, femsToDiscard, xminxxmax);
00960       if (!ok)
00961         {
00962           return false;
00963         }
00964     }
00965 
00966   std::vector<int> reject;
00967 
00968   // Now that we both have gains at time t and at reference time 0,
00969   // let's compute the averages and takes the ratio.
00970   // The whole point here is that you can either take ratio of average or
00971   // average of ratio...
00972 
00973   method->compute(gt,gt0,reject,value,error_on_value,skewness,kurtosis);
00974 
00975   if ( gt.size() != gt0.size() )
00976     {
00977       std::cerr << "emcGainBaseLineCalculator::getBaseLine : Houston, "
00978                 << "we have a serious problem here : gt.size()="
00979                 << gt.size() << " whereas gt0.size()="
00980                 << gt0.size() << " for isector=" << isector
00981                 << " and details=" << details
00982                 << std::endl;
00983       exit(1);
00984     }
00985 
00986   if (fHistogramming)
00987     {
00988       fillHistograms(isector, details, gt, gt0, reject);
00989     }
00990 
00991   return true;
00992 }
00993 
00994 //_____________________________________________________________________________
00995 bool
00996 emcGainBaseLineCalculator::get(const std::string& sname,
00997                                std::vector<emcGainBaseLineCalculator::Tuple>& values,
00998                                emcCalibrationDataHelper& cdh,
00999                                const emcFEMList& femlist,
01000                                const std::set<int>& femsToDiscard,
01001                                const int xminxxmax)
01002 {
01003   values.clear();
01004 
01005   // Only consider sectors for which we got configured.
01006   if ( femlist.hasSector(sname.c_str()) )
01007     {
01008       std::set<int> fems = femlist.fems(sname.c_str());
01009       std::set<int>::const_iterator it;
01010 
01011       time_t tics = cdh.timeStamp().getTics();
01012 
01013       for ( it = fems.begin(); it != fems.end(); ++it )
01014         {
01015           std::set<int>::const_iterator d = femsToDiscard.find((*it));
01016           if ( d != femsToDiscard.end() )
01017             {
01018               // FEM is one to discard. Skip it.
01019               continue;
01020             }
01021           const emcCalFEM* g = cdh.getCalibration((*it), "Gains");
01022           if (!g)
01023             {
01024               std::cerr << __FILE__ << ":" << __LINE__ << "g=0"
01025                         << std::endl;
01026               return false;
01027             }
01028 
01029 
01030           for ( size_t i = 0; i < g->GetNumberOfChannels(); ++i )
01031             {
01032               float value = 0.0;
01033               
01034               if ( xminxxmax == -1 )
01035                 {
01036                   value = g->getValue(i, g->GetXmin());
01037                 }
01038               else if ( xminxxmax == 0 )
01039                 {
01040                   value = g->getValue(i, tics);
01041                 }
01042               else if ( xminxxmax == 1)
01043                 {
01044                   value = g->getValue(i, g->GetXmax());
01045                 }
01046               
01047               int towerid = EmcIndexer::PXSM144iCH_iPX((*it),i);
01048               values.push_back(emcGainBaseLineCalculator::Tuple(values.size(),towerid,value));
01049             }
01050         }
01051       return true;
01052     }
01053   else
01054     {
01055       return false;
01056     }
01057 }
01058 
01059 //_____________________________________________________________________________
01060 void
01061 emcGainBaseLineCalculator::write(bool make_subdirectories)
01062 {
01063   std::map<std::string, TH1*>::const_iterator it;
01064 
01065   TDirectory* save = gDirectory;
01066 
01067   for ( it = fHistos.begin(); it != fHistos.end(); ++it )
01068     {
01069       TH1* h = it->second;
01070       std::string::size_type pos = it->first.find_first_of('/');
01071       if ( make_subdirectories )
01072         {
01073           TDirectory* dir =
01074             TDirectoryHelper::mkdir(save, it->first.substr(0, pos).c_str());
01075           dir->cd();
01076         }
01077       h->Write();
01078     }
01079 
01080   save->cd();
01081 }