00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012 #include "PulserTimeCalScheme.h"
00013 #include "MessageService/MsgService.h"
00014 #include "Plex/PlexHandle.h"
00015 #include "Plex/PlexSEIdAltL.h"
00016 #include "Plex/PlexStripEndId.h"
00017 #include "DatabaseInterface/DbiValidityRec.h"
00018 #include "Validity/VldRange.h"
00019 #include "Calibrator.h"
00020
00021 CVSID("$Id: PulserTimeCalScheme.cxx,v 1.23 2008/10/31 14:36:12 tagg Exp $");
00022 ClassImp(PulserTimeCalScheme)
00023
00024
00025 const RawChannelId kVaRcid(Detector::kFar,ElecType::kVA,0,0);
00026
00027 PulserTimeCalScheme::PulserTimeCalScheme()
00028 {
00029 Registry r;
00030
00031 r.Set("UseMuonCalibration",1);
00032 r.Set("UsePulserCalibration",0);
00033 r.Set("UseShieldCalibration",1);
00034 r.Set("UseJumps",1);
00035 r.Set("JumpTask",1);
00036 r.Set("DoWalkCorrection",1);
00037 r.Set("PulserLed1",2);
00038 r.Set("PulserLed2",3);
00039 r.Set("PulserLed3",4);
00040 r.Set("DefaultTimingCardSetting",260.);
00041
00042 r.Set("ReferenceDate",20040930);
00043 r.Set("ReferenceTime",0);
00044 r.Set("MuonTask","Dogwood");
00045 InitializeConfig(r);
00046 }
00047
00048
00049 void PulserTimeCalScheme::ConfigModified()
00050 {
00051 Int_t refDate = 0;
00052 Int_t refTime = 0;;
00053
00054 const char* taskname;
00055
00056 bool ok = true;
00057 ok = ok && GetConfig().Get("UseMuonCalibration",fUseMuonCalibration);
00058 ok = ok && GetConfig().Get("UseShieldCalibration",fUseShieldCalibration);
00059 ok = ok && GetConfig().Get("UsePulserCalibration",fUsePulserCalibration);
00060 ok = ok && GetConfig().Get("UseJumps",fUseJumps);
00061
00062 ok = ok && GetConfig().Get("DoWalkCorrection",fDoWalkCorrection);
00063 ok = ok && GetConfig().Get("DefaultTimingCardSetting",fDefaultTimingCardSetting);
00064
00065 ok = ok && GetConfig().Get("ReferenceDate",refDate);
00066 ok = ok && GetConfig().Get("ReferenceTime",refTime);
00067 for(int i=0;i<kMaxLeds; i++) {
00068 ok = ok && GetConfig().Get(Form("PulserLed%d",i+1),fPulserLed[i]);
00069 }
00070 ok = ok && GetConfig().Get("MuonTask",taskname);
00071
00072 if(!ok){
00073 MSG("Calib",Msg::kWarning) << "PulserTimeCalScheme couldn't configure properly!" << endl;
00074 GetConfig().PrettyPrint(std::cerr);
00075 }
00076
00077 if (0==strcasecmp(taskname,"Dogwood")){ fMuonTask = 2; }
00078 else if(0==strcasecmp(taskname,"Andys" )){ fMuonTask = 1; }
00079 else if(0==strcasecmp(taskname,"Brians" )){ fMuonTask = 0; }
00080 else{
00081
00082 MSG("Calib",Msg::kWarning) << "PulserTimeCalScheme doesn't recognise task " << taskname << endl;
00083 }
00084
00085 fReferenceTime = VldTimeStamp(refDate,refTime,0);
00086
00087
00088 Reset(GetContext(),true);
00089 }
00090
00091
00092 void PulserTimeCalScheme::PrintConfig( std::ostream& os ) const
00093 {
00094 char taskname[100];
00095 switch(fMuonTask) {
00096 case 0: sprintf(taskname,"Brians"); break;
00097 case 1: sprintf(taskname,"Andys"); break;
00098 case 2: sprintf(taskname,"Dogwood"); break;
00099 default: sprintf(taskname,"Task %d",fMuonTask); break;
00100 }
00101
00102 os << " UseMuonCalibration: " << ((fUseMuonCalibration)?("On"):("Off")) << endl;
00103 os << " MuonTask: " << taskname << endl;
00104 os << " UseShieldCalibration: " << ((fUseShieldCalibration)?("On"):("Off")) << endl;
00105 os << " UseJumps: " << ((fUseJumps)?("On"):("Off")) << endl;
00106
00107 os << " UsePulserCalibration: " << ((fUsePulserCalibration)?("On"):("Off")) << endl;
00108 os << " DoWalkCorrection: " << ((fDoWalkCorrection)?("On"):("Off")) << endl;
00109 os << " Reference date: " << fReferenceTime.AsString() << endl;
00110 os << " PulserLeds to use: ";
00111 for(int i=0;i<kMaxLeds;i++) {
00112 os << fPulserLed[i];
00113 if(i!=kMaxLeds-1) os << ",";
00114 }
00115 os << endl;
00116
00117 }
00118
00119
00120 void PulserTimeCalScheme::DoReset( const VldContext& context )
00121 {
00122 MSG("Calib",Msg::kVerbose) << "PulserTimeCalScheme::DoReset()" << endl;
00123
00124 if(fUseMuonCalibration) {
00125 fMuonResPtr.NewQuery(context,fMuonTask);
00126
00127 if(fMuonResPtr.GetNumRows()==0) {
00128 MAXMSG("Calib",Msg::kWarning,10)
00129 << "No rows in CALTIMECALIBRATION with validity context "
00130 << context.AsString() << " No muon timing calibration will be applied." << endl;
00131 IncrementErrors(kTimeCalibrator,kMissingTable);
00132 }
00133 }
00134
00135 if(fUseShieldCalibration && context.GetDetector()==Detector::kFar) {
00136 fShieldResPtr.NewQuery(context,99);
00137 if(fShieldResPtr.GetNumRows()==0) {
00138 MAXMSG("Calib",Msg::kWarning,10)
00139 << "No rows for FD shield timing calibration CALTIMECALIBRATION task "
00140 << 99 << " with validity context "
00141 << context.AsString() << endl;
00142 IncrementErrors(kTimeCalibrator,kMissingTable);
00143 }
00144 }
00145
00146 if(fUseJumps && fMuonTask>0) {
00147 fJumpResPtr.NewQuery(context,fMuonTask);
00148
00149 }
00150
00151 VldContext refContext(context.GetDetector(),
00152 context.GetSimFlag(),
00153 fReferenceTime);
00154
00155 if(fUsePulserCalibration) {
00156
00157
00158
00159 for(int iled=0;iled<kMaxLeds;iled++) {
00160 fDriftPtr[iled].NewQuery(context,fPulserLed[iled]);
00161 if(fDriftPtr[iled].GetNumRows()==0) {
00162 MAXMSG("Calib",Msg::kWarning,10)
00163 << "No rows in PULSERTIMEDRIFT task " << fPulserLed[iled] << " with validity context "
00164 << context.AsString() << endl;
00165 IncrementErrors(kTimeCalibrator,kMissingTable);
00166 }
00167
00168
00169 fDriftRefPtr[iled].NewQuery(refContext,fPulserLed[iled]);
00170 if(fDriftRefPtr[iled].GetNumRows()==0) {
00171 MAXMSG("Calib",Msg::kWarning,10)
00172 << "No rows in PULSERTIMEDRIFT task " << fPulserLed[iled] << " with reference context "
00173 << refContext.AsString() << endl;
00174 IncrementErrors(kTimeCalibrator,kMissingTable);
00175 }
00176
00177 }
00178
00179
00180
00181 fTimingCardResPtr.NewQuery(context,0);
00182 if(fTimingCardResPtr.GetNumRows()==0) {
00183 MAXMSG("Calib",Msg::kWarning,10)
00184 << "No rows in PULSERTIMINGCARDSETTING with validity context "
00185 << context.AsString() << endl;
00186 IncrementErrors(kTimeCalibrator,kMissingTable);
00187 }
00188
00189 fTimingCardReferencePtr.NewQuery(refContext,0);
00190 if(fTimingCardReferencePtr.GetNumRows()==0) {
00191 MAXMSG("Calib",Msg::kWarning,10)
00192 << "No rows in PULSERTIMINGCARDSETTING with reference context "
00193 << refContext.AsString() << endl;
00194 IncrementErrors(kTimeCalibrator,kMissingTable);
00195 }
00196
00197 }
00198 }
00199
00200
00201 DoubleErr PulserTimeCalScheme::GetCalibratedTime(DoubleErr rawtime,
00202 FloatErr rawcharge,
00203 const PlexStripEndId& seid) const
00204 {
00216
00217
00218 DoubleErr time = rawtime;
00219
00220 if(seid.IsVetoShield()) {
00221
00222
00223 if(fUseShieldCalibration) time = CalibrateShield(time,rawcharge,seid,true);
00224 } else {
00225
00226
00227
00228 if(GetContext().GetDetector()==Detector::kFar) {
00229 PlexHandle plex(GetContext());
00230 RawChannelId rcid = plex.GetRawChannelId(seid);
00231 if(fUseJumps) time = CalibrateByJumps(time,rcid,true);
00232 if(fUsePulserCalibration) time = CalibrateByPulser(time,rcid,true);
00233 }
00234 if(fUseMuonCalibration) time = CalibrateByMuon(time,seid,true);
00235 if(fDoWalkCorrection) time-= WalkCorrection(rawcharge,seid);
00236 }
00237
00238 return time;
00239 }
00240
00241
00242 DoubleErr PulserTimeCalScheme::DecalTime(DoubleErr caltime,
00243 FloatErr rawcharge,
00244 const PlexStripEndId& seid) const
00245 {
00259
00260
00261 DoubleErr time = caltime;
00262
00263 if(seid.IsVetoShield()) {
00264
00265
00266 if(fUseShieldCalibration) time = CalibrateShield(time,rawcharge,seid,false);
00267
00268 } else {
00269
00270
00271
00272 if(GetContext().GetDetector()==Detector::kFar) {
00273 PlexHandle plex(GetContext());
00274 RawChannelId rcid = plex.GetRawChannelId(seid);
00275 if(fUseJumps) time = CalibrateByJumps(time,rcid,false);
00276 if(fUsePulserCalibration) time = CalibrateByPulser(time,rcid,false);
00277 }
00278 if(fUseMuonCalibration) time = CalibrateByMuon(time,seid,false);
00279 if(fDoWalkCorrection) time+= WalkCorrection(rawcharge,seid);
00280 }
00281
00282 return time;
00283 }
00284
00285
00286
00287 DoubleErr PulserTimeCalScheme::CalibrateByJumps(DoubleErr rawtime,
00288 const RawChannelId& rcid,
00289 Bool_t calibrate) const
00290 {
00291
00292 UInt_t index = CalTimeJump::GetIndex(rcid);
00293
00294
00295
00296 const CalTimeJump* jump = fJumpResPtr.GetRowByIndex(index);
00297 if(jump) {
00298 if(calibrate)
00299 return rawtime - (double)jump->GetJump();
00300 else
00301 return rawtime + (double)jump->GetJump();
00302 }
00303
00304
00305
00306 return rawtime;
00307 }
00308
00309
00310 DoubleErr PulserTimeCalScheme::CalibrateByMuon(DoubleErr rawtime,
00311 const PlexStripEndId& seid,
00312 Bool_t calibrate) const
00313 {
00314
00315 const CalTimeCalibration* dpgc = fMuonResPtr.GetRowByIndex(seid.BuildPlnStripEndKey());
00316
00317 if(dpgc==0) {
00318 if(fMuonResPtr.GetNumRows()>0) {
00319 MAXMSG("Calib",Msg::kWarning,10)
00320 << "PulserTimeCalScheme: No database row for StripEnd " << seid.AsString() << "\n";
00321
00322 IncrementErrors(kTimeCalibrator,kMissingRow,seid);
00323 }
00324 return rawtime + DoubleErr(0,20.*Munits::ns);
00325 }
00326 if(calibrate)
00327 return (rawtime/(double)dpgc->GetScale()) - (double)dpgc->GetOffset();
00328
00329
00330
00331
00332 return (rawtime + (double)dpgc->GetOffset())*(double)dpgc->GetScale();
00333 }
00334
00335
00336
00337
00338 DoubleErr PulserTimeCalScheme::CalibrateByPulser(DoubleErr rawtime,
00339 const RawChannelId& rcid,
00340 Bool_t calibrate) const
00341 {
00342
00343 UInt_t index = PulserTimeDrift::GetIndex(rcid);
00344
00345 const PulserTimeDrift* drift = 0;
00346 const PulserTimeDrift* driftref = 0;
00347
00348
00349 Int_t whichled = 0;
00350 bool driftok = GetPulserCalibration(whichled,index,drift,driftref);
00351
00352
00353 while(!driftok){
00354 whichled++;
00355 if(whichled<kMaxLeds) {
00356 driftok = GetPulserCalibration(whichled,index,drift,driftref);
00357 MSG("Calib",Msg::kDebug) << "PulserTiming: " << rcid.AsString() << " Fell back to LED " << fPulserLed[whichled] << endl;
00358 } else {
00359 MAXMSG("Calib",Msg::kWarning,10)
00360 << "PulserTimeCalScheme: Failed to find calibration for channel "
00361 << rcid.AsString() << " index " << index << " in primary or fallback tables.\n";
00362 IncrementErrors(kTimeCalibrator,kMissingRow,rcid);
00363 return rawtime + DoubleErr(0,50.*Munits::ns);
00364 }
00365 }
00366
00367
00368
00369 const PulserTimingCardSetting* cardSetting =
00370 fTimingCardResPtr.GetRowByIndex(rcid.GetCrate());
00371 const PulserTimingCardSetting* refCardSetting =
00372 fTimingCardReferencePtr.GetRowByIndex(rcid.GetCrate());
00373
00374 Double_t tpmt_delay_ns = fDefaultTimingCardSetting;
00375 Double_t ref_delay_ns = fDefaultTimingCardSetting;
00376
00377
00378 if(cardSetting==0) {
00379 if(fTimingCardResPtr.GetNumRows()>0) {
00380 MAXMSG("Calib",Msg::kWarning,10) << "Incomplete PulserTimingCardSettings table!" << endl;
00381 }
00382 IncrementErrors(kTimeCalibrator,kMissingRow,rcid);
00383 } else {
00384 tpmt_delay_ns = cardSetting->GetDelayNanoSecs();
00385 }
00386
00387
00388
00389 if(refCardSetting==0) {
00390 if(fTimingCardReferencePtr.GetNumRows()>0) {
00391 MAXMSG("Calib",Msg::kWarning,10) << "Incomplete PulserTimingCardSettings table!" << endl;
00392 }
00393 IncrementErrors(kTimeCalibrator,kMissingRow,rcid);
00394 } else {
00395 ref_delay_ns = cardSetting->GetDelayNanoSecs();
00396 }
00397
00398
00399
00400
00401
00402 double crate_offset_t = (tpmt_delay_ns - ref_delay_ns)*Munits::ns;
00403
00404
00405
00406 double drift_tdcs = (drift->GetMean() - driftref->GetMean());
00407 double drift_err = (drift->GetRms() / sqrt(drift->GetEntries()));
00408 double convert = Calibrator::Instance().GetTDCConvert(kVaRcid);
00409 DoubleErr drift_t(drift_tdcs * convert,
00410 drift_err * convert);
00411
00412
00413
00414
00415 DoubleErr offset = drift_t - crate_offset_t;
00416
00417 if(calibrate)
00418 return rawtime - offset;
00419
00420
00421 return rawtime + offset;
00422 }
00423
00424 Bool_t
00425 PulserTimeCalScheme::GetPulserCalibration(Int_t iled, UInt_t index,
00426 const PulserTimeDrift* &drift,
00427 const PulserTimeDrift* &ref) const
00428 {
00429
00430
00431
00432 drift = fDriftPtr[iled].GetRowByIndex(index);
00433 ref = fDriftRefPtr[iled].GetRowByIndex(index);
00434
00435
00436 if(drift==0) return false;
00437 if(ref==0) return false;
00438
00439
00440
00441
00442
00443
00444
00445 if( drift->GetRms() >= sqrt(drift->GetEntries())*0.2 ) return false;
00446 if( ref->GetRms() >= sqrt( ref->GetEntries())*0.2 ) return false;
00447
00448
00449 return true;
00450 }
00451
00452
00453
00454
00455 DoubleErr PulserTimeCalScheme::WalkCorrection(FloatErr rawcharge,
00456 const PlexStripEndId&) const
00457 {
00463
00464
00465 if(GetContext().GetDetector()==Detector::kFar) {
00466
00467 const float kParData[4] = { 5.44066e+00,
00468 -5.94887e-01,
00469 -7.36609e-02,
00470 7.66637e-03 };
00471
00472 const float kParMC[4] = { 4.18608e+00,
00473 -3.75033e-01,
00474 -9.50218e-02,
00475 9.52560e-03 };
00476
00477 const float* par = kParData;
00478 if(GetContext().GetSimFlag()==SimFlag::kMC) par = kParMC;
00479
00480 if(rawcharge<=0) rawcharge = 1;
00481 double cx = log(rawcharge()/2.3);
00482 double walk = (
00483 par[0]
00484 + (par[1] * cx)
00485 + (par[2] * cx *cx)
00486 + (par[3] * cx * cx *cx)
00487 );
00488
00489 return walk / Munits::c_light;
00490
00491 }
00492
00493 return 0;
00494 }
00495
00496
00497 DoubleErr PulserTimeCalScheme::CalibrateShield(DoubleErr rawtime,
00498 FloatErr rawcharge,
00499 const PlexStripEndId& seid,
00500 Bool_t calibrate) const
00501 {
00502
00503 const CalTimeCalibration* dpgc = fShieldResPtr.GetRowByIndex(seid.BuildPlnStripEndKey());
00504
00505 if(dpgc==0) {
00506 if(fShieldResPtr.GetNumRows()>0) {
00507 MAXMSG("Calib",Msg::kWarning,10)
00508 << "PulserTimeCalScheme: No database row for shield StripEnd " << seid.AsString() << "\n";
00509 IncrementErrors(kTimeCalibrator,kMissingRow,seid);
00510 }
00511 return rawtime - DoubleErr(-30.0*Munits::ns,
00512 20.*Munits::ns);
00513 }
00514
00515
00516 if(rawcharge<1) rawcharge=1;
00517 Double_t logq = log(rawcharge);
00518
00519 Double_t walk = 0;
00520 if(fDoWalkCorrection) {
00521 const float kgainadjust=60./90.;
00522 walk = WalkCorrection(rawcharge*kgainadjust,seid);
00523 walk += dpgc->GetSlewC1()
00524 + dpgc->GetSlewC2()*logq
00525 + dpgc->GetSlewC3()*logq*logq
00526 + dpgc->GetSlewC4()*logq*logq*logq;
00527 }
00528
00529
00530 if(calibrate)
00531 return rawtime - walk + (double)dpgc->GetOffset();
00532
00533
00534 return rawtime + walk - (double)dpgc->GetScale();
00535
00536 }
00537