Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Calibrator.cxx

Go to the documentation of this file.
00001 
00002 // $Id: Calibrator.cxx,v 1.7 2009/10/19 17:15:21 jpaley Exp $
00003 //
00004 // Singleton class that handles calibrations for a particular 
00005 // validity context (eg: detector+timestamp).
00006 //
00008 
00009 #include "Calibrator/Calibrator.h"
00010 #include "CMap/CMap.h"
00011 #include "JobControl/Exception.h"
00012 #include "Geometry/geo.h"
00013 #include "Database/Table.h"
00014 #include "TMath.h"
00015 #include "TSystem.h"
00016 #include "TFile.h"
00017 #include <iostream>
00018 
00019 using namespace std;
00020 using namespace calib;
00021 
00022 Calibrator* Calibrator::fInstance = 0;
00023 
00024 //------------------------------------------------------------
00025 
00026 Calibrator::Calibrator() : 
00027   fCurrTimeStamp(0),
00028   fCurrDetector(rawdata::kNear),
00029   fCurrGeo(0),
00030   fPEACperMIP(0), fPEACperMIPErr(0),
00031   fLoadedFineTimeDistros(0)
00032 {
00033   fADCtoPE.clear();
00034   fMIPtoGeV.clear();
00035   fMIPtoGeVErr.clear();
00036   fFTDistNDX.clear();
00037   fFTDistNDY.clear();
00038   fFTDistFDX.clear();
00039   fFTDistFDY.clear();
00040 }
00041 
00042 
00043 //------------------------------------------------------------
00044 
00045 void Calibrator::SetContext(TTimeStamp timestamp,
00046                             rawdata::det_id_ detector,
00047                             const geo::Geometry &geometry) {
00048   fCurrTimeStamp = timestamp;
00049   fCurrDetector = detector;
00050   fCurrGeo = &geometry;
00051   LoadFineTimeDistros();
00052   /*
00053   LoadADCtoPE();
00054   LoadPEtoSigCor();
00055   LoadSCtoPEAC();
00056   LoadPEACtoMIP();
00057   LoadMIPtoGeV();
00058   */
00059 }
00060 
00061 //------------------------------------------------------------
00062 
00063 Calibrator& Calibrator::Instance(TTimeStamp timestamp,
00064                                  rawdata::det_id_ detector,
00065                                  const geo::Geometry &geometry) {
00066   if (!fInstance)
00067     fInstance = new Calibrator;
00068   fInstance->SetContext(timestamp, detector, geometry);
00069   return *fInstance;
00070 }
00071 
00072 //------------------------------------------------------------
00073 //   Load ADC to PE database constants
00074 //------------------------------------------------------------
00075 
00076 bool Calibrator::LoadADCtoPE()
00077 {
00078   fADCtoPE.clear();
00079   
00080   std::string dbFile = "ADCtoPE.xml";
00081 
00082   db::Table* table = new db::Table(dbFile);
00083   
00084   if (!table) return false;
00085 
00086   if (table->Connect()) {
00087     table->Init(fCurrTimeStamp.GetSec());
00088     
00089     if (table->empty()) return false;
00090 
00091     table->Disconnect();
00092   }
00093 
00094   // now fill STL map...
00095   std::string str1 = "Channel";
00096   std::string str2 = "PEperADC";
00097   int chan;
00098   float val;
00099   for (unsigned int i=0; i<table->size(); ++i) {    
00100     (*table)[i].Get(str1,chan);
00101     (*table)[i].Get(str2,val);
00102     fADCtoPE[chan] = val;
00103   }
00104   
00105   delete table;
00106 
00107   return true;
00108 }
00109 
00110 //------------------------------------------------------------
00111 //   Load PE to SigCor database constants
00112 //------------------------------------------------------------
00113 
00114 bool Calibrator::LoadPEtoSigCor()
00115 {
00116   fPEtoSigCor.clear();
00117   
00118   std::string dbFile = "PEtoSigCor.xml";
00119 
00120   db::Table* table = new db::Table(dbFile);
00121 
00122   if (!table) return false;
00123 
00124   if (table->Connect()) {
00125     table->Init(fCurrTimeStamp.GetSec());
00126     
00127     if (table->empty()) return false;
00128 
00129     table->Disconnect();
00130   }
00131 
00132   // now fill STL map...
00133   std::string str1 = "Channel";
00134   std::string str2 = "SCperPE";
00135   int chan;
00136   float val;
00137   for (unsigned int i=0; i<table->size(); ++i) {    
00138     (*table)[i].Get(str1,chan);
00139     (*table)[i].Get(str2,val);
00140     fPEtoSigCor[chan] = val;
00141   }
00142   
00143   delete table;
00144   
00145   return true;
00146 }
00147 
00148 //------------------------------------------------------------
00149 //   Load SigCor to PEAC database constants
00150 //------------------------------------------------------------
00151 
00152 bool Calibrator::LoadSCtoPEAC()
00153 {
00154   fSCtoPEAC.clear();
00155   
00156   std::string dbFile = "SigCortoPEAC.xml";
00157 
00158   db::Table* table = new db::Table(dbFile);
00159 
00160   if (!table) return false;
00161 
00162   if (table->Connect()) {
00163     table->Init(fCurrTimeStamp.GetSec());
00164     
00165     if (table->empty()) return false;
00166 
00167     table->Disconnect();
00168   }
00169 
00170   // now fill STL map...
00171   std::string str1 = "Channel";
00172   std::string str2 = "A1";
00173   std::string str3 = "A2";
00174   std::string str4 = "L1";
00175   std::string str5 = "L2";
00176   int chan;
00177   for (unsigned int i=0; i<table->size(); ++i) {    
00178     attlen a;
00179     (*table)[i].Get(str1,chan);
00180     (*table)[i].Get(str2,a.a1);
00181     (*table)[i].Get(str2+"Err",a.a1sig);
00182     (*table)[i].Get(str3,a.a2);
00183     (*table)[i].Get(str3+"Err",a.a2sig);
00184     (*table)[i].Get(str4,a.l1);
00185     (*table)[i].Get(str4+"Err",a.l1sig);
00186     (*table)[i].Get(str5,a.l2);
00187     (*table)[i].Get(str5+"Err",a.l2sig);
00188 
00189     fSCtoPEAC[chan] = a;
00190   }
00191   
00192   delete table;
00193   
00194   return true;
00195 }
00196 
00197 //------------------------------------------------------------
00198 //   Load PEAC to MIP database constant
00199 //------------------------------------------------------------
00200 
00201 bool Calibrator::LoadPEACtoMIP()
00202 {
00203   fPEACperMIP = 1.;
00204   
00205   std::string dbFile = "PEACtoMIP.xml";
00206 
00207   db::Table* table = new db::Table(dbFile);
00208 
00209   if (!table) return false;
00210 
00211   if (table->Connect()) {
00212     table->Init(fCurrTimeStamp.GetSec());
00213     
00214     if (table->empty()) return false;
00215 
00216     table->Disconnect();
00217   }
00218 
00219   std::string str1 = "PEACperMIP";
00220   (*table)[0].Get(str1,fPEACperMIP);
00221 
00222   delete table;
00223   
00224   return true;
00225 }
00226 
00227 //------------------------------------------------------------
00228 //   Load MIP to GeV database constant
00229 //------------------------------------------------------------
00230 
00231 bool Calibrator::LoadMIPtoGeV()
00232 {
00233   fMIPtoGeV.clear();
00234   
00235   std::string dbFile = "MIPtoGeV.xml";
00236 
00237   db::Table* table = new db::Table(dbFile);
00238 
00239   if (!table) return false;
00240 
00241   if (table->Connect()) {
00242     table->Init(fCurrTimeStamp.GetSec());
00243     
00244     if (table->empty()) return false;
00245 
00246     table->Disconnect();
00247   }
00248 
00249   float val;
00250   char buf[20];
00251   std::string str1;
00252   for (int i=0; i<5; ++i) {    
00253     sprintf(buf,"par%d",i);
00254     str1 = buf;
00255     (*table)[0].Get(str1,val);
00256     fMIPtoGeV.push_back(val);
00257   }
00258 
00259   delete table;
00260   
00261   if (fMIPtoGeV.empty()) return false;
00262 
00263   return true;
00264 }
00265 
00266 //------------------------------------------------------------
00267 //   Load Fine-time Distributions from dB
00268 //------------------------------------------------------------
00269 
00270 bool Calibrator::LoadFineTimeDistros() 
00271 {
00272   fFTDistNDX.clear();
00273   fFTDistNDY.clear();
00274   fFTDistFDX.clear();
00275   fFTDistFDY.clear();
00276 
00277   // get values for ND first
00278   std::string dbFile = "FTDistroND.xml";
00279 
00280   db::Table* table = new db::Table(dbFile);
00281 
00282   if (!table) return false;
00283 
00284   if (table->Connect()) {
00285     table->Init(fCurrTimeStamp.GetSec());
00286     
00287     if (table->empty()) return false;
00288 
00289     table->Disconnect();
00290   }
00291 
00292   float x,y;
00293   std::string strx = "x";
00294   std::string stry = "y";
00295   for (unsigned int i=0; i<table->size(); ++i) {
00296     (*table)[i].Get(strx,x);
00297     (*table)[i].Get(stry,y);
00298     fFTDistNDX.push_back(x);
00299     fFTDistNDY.push_back(y);
00300   }
00301 
00302   delete table;
00303   
00304   // now get values for FD 
00305   dbFile = "FTDistroFD.xml";
00306 
00307   table = new db::Table(dbFile);
00308 
00309   if (!table) return false;
00310 
00311   if (table->Connect()) {
00312     table->Init(fCurrTimeStamp.GetSec());
00313     
00314     if (table->empty()) return false;
00315 
00316     table->Disconnect();
00317   }
00318 
00319   for (unsigned int i=0; i<table->size(); ++i) {
00320     (*table)[i].Get(strx,x);
00321     (*table)[i].Get(stry,y);
00322     fFTDistFDX.push_back(x);
00323     fFTDistFDY.push_back(y);
00324   }
00325 
00326   delete table;
00327 
00328   fLoadedFineTimeDistros = 1;
00329 
00330   return true;
00331 }
00332 
00333 //------------------------------------------------------------
00334 //   RawDigit-to-CellHit methods
00335 //------------------------------------------------------------
00336 
00337 void Calibrator::MakeCellHit(const RawDigit *rawdigit, CellHit *cellhit) {
00338 
00339   // copy inherited data members
00340   (*((RawDigit*)cellhit)) = (*rawdigit);
00341 
00342   cmap::CMap& cmap = cmap::CMap::Instance(fCurrTimeStamp,fCurrDetector);
00343 
00344   // new info
00345   cellhit->SetStatus(0); // for now, it always works!
00346   cellhit->SetCell  (cmap.GetCell(rawdigit));
00347   cellhit->SetPlane (cmap.GetPlane(rawdigit));
00348   cellhit->SetView  (fCurrGeo->Plane(cellhit->Plane()).View());
00349   cellhit->SetTNS   (GetTNS(rawdigit));
00350   cellhit->SetPE    (GetPE(rawdigit));
00351   cellhit->SetPECorr(cellhit->PE()*GetPECorrFactor(rawdigit));
00352 }
00353 
00354 //-----
00355 float Calibrator::GetPE(const RawDigit *rawdigit) {
00356   // Look up gain from DB.  For now, must hard code the
00357   // number.  (This should not be put in any XML file.
00358   // That'll just confuse the issue.)
00359   float gain = 1.43;
00360   return rawdigit->ADC(0)/gain;
00361 }
00362 
00363 //-----
00364 float Calibrator::GetPECorrFactor(const RawDigit* /*rawdigit*/) {
00365   // Look up channel-to-channel correction factors in DB.
00366   // For now, must hard code the factor.
00367   return 1.0;
00368 }
00369 
00370 //-----
00371 float Calibrator::GetTNS(const RawDigit *rawdigit) {
00372   // You'd think this would be a simple function... Not anymore!
00373   // The new readout scheme allows for super time resolution, and
00374   // this is the code that gets it.
00375 
00376   Double_t t = 0;
00377 
00378   // First, see if we're using the new-style readout.  This
00379   // condition should be unnecessary in the future.
00380 
00381   if (rawdigit->NADC()<=1) {
00382 
00383     // Old style readout.  Return old style answer:
00384     t = rawdigit->TDC(0)*62.5;
00385 
00386   }
00387   else {
00388 
00389     // New style readout.  Use ADC info to determine fine timing.
00390     // See doc-???? for details.
00391 
00392     // ADC readings before and after peak, scaled to peak,
00393     // yield "x" and "y":
00394     Double_t peakadc = rawdigit->ADC(0);
00395     Double_t x = (rawdigit->ADC(1))/peakadc;
00396     Double_t y = (rawdigit->ADC(2))/peakadc;
00397     
00398     // These constants belong in the the DB.  For now, hard code them.
00399     // Tuned up by RBP, 2009-10-07
00400     Double_t Xa = 0.0;
00401     Double_t Ya = 1.0;
00402     Double_t Xb = 0.0;
00403     Double_t Yb = (fCurrDetector==rawdata::kNear?0.90:0.885);
00404     Double_t Xc = 1.0;
00405     Double_t Yc = 0.800;
00406 
00407     // These could be evaluated offline and stuck in the DB.
00408     // For now, I'll evaluate them explicitly here so the math
00409     // isn't lost:
00410     Double_t L1 = sqrt((Yb-Ya)*(Yb-Ya)+(Xb-Xa)*(Xb-Xa));
00411     Double_t L2 = sqrt((Yc-Yb)*(Yc-Yb)+(Xc-Xb)*(Xc-Xb));
00412 
00413     // distance to first line segment:
00414     Double_t U1 = ((x-Xa)*(Xb-Xa)+(y-Ya)*(Yb-Ya))/L1/L1;
00415     if (U1<0) U1=0;
00416     if (U1>0.99999) U1=0.99999;
00417     Double_t PX1 = Xa + U1*(Xb-Xa);
00418     Double_t PY1 = Ya + U1*(Yb-Ya);
00419     Double_t D1 = sqrt((PX1-x)*(PX1-x)+(PY1-y)*(PY1-y));
00420 
00421     // distance to second line segment:
00422     Double_t U2 = ((x-Xb)*(Xc-Xb)+(y-Yb)*(Yc-Yb))/L2/L2;
00423     if (U2<0) U2=0;
00424     if (U2>0.99999) U2=0.99999;
00425     Double_t PX2 = Xb + U2*(Xc-Xb);
00426     Double_t PY2 = Yb + U2*(Yc-Yb);
00427     Double_t D2 = sqrt((PX2-x)*(PX2-x)+(PY2-y)*(PY2-y));
00428 
00429     // get the better of the two
00430     Double_t U;
00431     if (D1<D2) U = U1*L1/(L1+L2);
00432     else       U = (L1+U2*L2)/(L1+L2);
00433 
00434     // map best U value to a fine time:
00435     vector<float>& ftx = fFTDistNDX;
00436     vector<float>& fty = fFTDistNDY;
00437     if (fCurrDetector == rawdata::kFar) {
00438       ftx = fFTDistFDX;
00439       fty = fFTDistFDY;
00440     }
00441 
00442     unsigned int bin=1;
00443     if (U < ftx[0])
00444       bin = 0;
00445     else
00446       for (; bin<ftx.size()-1; ++bin) {
00447         if (U >= ftx[bin-1] && U < ftx[bin]) break;
00448       }
00449     if (bin == ftx.size()) {
00450       // should never get in here
00451       std::cout << "In GetTNS(): bin=" << bin << " u=" << U << std::endl;
00452       bin=ftx.size()-1;
00453     }
00454     Double_t timefrac = 0.5*( fty[bin] + fty[bin-1]);
00455 
00456     // Gap between digitizations
00457     Double_t gap = (fCurrDetector==rawdata::kNear?125.0:500.0);
00458 
00459     t = rawdigit->TDC(0)*62.5 - timefrac*gap;
00460   }
00461 
00462   return t;
00463 }
00464 
00465 
00466 //------------------------------------------------------------
00467 //   CellHit-to-RecoHit methods
00468 //------------------------------------------------------------
00469 
00470 void Calibrator::MakeRecoHit(const CellHit *cellhit, RecoHit *recohit, float w) {
00471 
00472   // copy inherited data members
00473   (*((CellHit*)recohit)) = (*cellhit);
00474 
00475   // new info:
00476   recohit->SetW(w);
00477 
00478   // Need position info to continue...
00479   Double_t xyzd[4];
00480   GetXYZD(cellhit,w,xyzd);
00481 
00482   recohit->SetX    (xyzd[0]);
00483   recohit->SetY    (xyzd[1]);
00484   recohit->SetZ    (xyzd[2]);
00485 
00486   recohit->SetT    (GetT    (cellhit,xyzd[3]));
00487   recohit->SetPEAtt(GetPEAtt(cellhit,xyzd[3]));
00488 
00489   recohit->SetMIP  (recohit->PEAtt() * GetMIPScale(cellhit));
00490   recohit->SetGeV  (recohit->MIP()   * GetGeVScale(cellhit));
00491 }
00492 
00493 //-----
00494 float Calibrator::GetT(const CellHit *cellhit, float dist_to_readout) {
00495   // This needs to be calibrated and put in a DB table
00496   Double_t speedOfFiberTransport = 15.3; // cm/ns, "first principles" calib.
00497                                          // Differs from c/n due to zigzag
00498                                          // paths down fiber.  But, this
00499                                          // value may be way off (10%? 30%?).
00500   return (cellhit->TNS()-dist_to_readout/speedOfFiberTransport);
00501 }
00502 
00503 //-----
00504 float Calibrator::GetPEAtt(const CellHit *cellhit, float dist_to_readout) {
00505 
00506   // These constants belong in the DB.  Don't put them in an XML file
00507   // in the meantime, as this will just confuse the issue...
00508   Double_t F0 = 5.744; // P. Shanahan tuning from old CalHit.xml
00509   Double_t L0 = 315.3; // .
00510   Double_t F1 = 1.546; // .
00511   Double_t L1 = 3329.; // .
00512 
00513   Double_t attenuation = F0*TMath::Exp(-dist_to_readout/L0) +
00514                          F1*TMath::Exp(-dist_to_readout/L1);
00515 
00516   return cellhit->PECorr() / attenuation;
00517 }
00518 
00519 //-----
00520 float Calibrator::GetMIPScale(const CellHit* /* cellhit */ ) {
00521   // This needs to be calibrated and put in the DB, obviously!
00522   return 0.033;
00523 }
00524 
00525 //-----
00526 float Calibrator::GetGeVScale(const CellHit* /* cellhit */ ) {
00527   // This needs to be calibrated and put in the DB, obviously!
00528   // Super-rough number based on 1 MIP = ~2 MeV/cm.
00529   return 0.013;
00530 }
00531 
00532 //-----
00533 void Calibrator::GetXYZD(const CellHit *cellhit, float w, double *xyzd) {
00534   // Return (via 'xyzd' argument) position of deposition in world
00535   // coordinates and the distance to the readout, assuming deposition
00536   // has cell-local-z position = w.
00537 
00538   UInt_t plane = cellhit->Plane();
00539   UInt_t cell  = cellhit->Cell();
00540   if (plane>=fCurrGeo->NPlanes()) {
00541     throw geo::Exception(__FILE__,__LINE__,geo::Exception::BAD_PLANE_NUMBER);
00542   }
00543   const geo::PlaneGeo& p = fCurrGeo->Plane(plane);
00544   if (cell>=p.Ncells()) {
00545     throw geo::Exception(__FILE__,__LINE__,geo::Exception::BAD_CELL_NUMBER);
00546   }
00547   const geo::CellGeo& c = p.Cell(cell);
00548 
00549   // Should be replaced with alignment tables or whatnot.  Okay for now.
00550 
00551   // w is not localZ, which makes this a lot messier than just
00552   // c.GetCenter(xyzd,w) and c.DistToReadOut(w)
00553   c.GetCenter(xyzd);
00554   if (cellhit->View()==geo::kX)
00555     xyzd[1] = w;
00556   else
00557     xyzd[0] = w;
00558   Double_t localxyz[3];
00559   c.WorldToLocal(xyzd,localxyz);
00560   xyzd[3] = c.DistToReadOut(localxyz[2]);
00561 }
00562 

Generated on Mon Nov 23 04:45:24 2009 for NOvA Offline by  doxygen 1.3.9.1