1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
17 ///////////////////////////////////////////////////////////////////////////////
19 // TRD tender: reapply pid on the fly //
21 ///////////////////////////////////////////////////////////////////////////////
24 #include <TDirectory.h>
27 #include <TObjString.h>
32 #include <AliCDBEntry.h>
34 #include <AliCDBManager.h>
35 #include <AliOADBContainer.h>
36 #include <AliTRDCalDet.h>
37 #include "AliTRDonlineTrackMatching.h"
42 #include <AliGeomManager.h>
44 #include <AliVEvent.h>
45 #include <AliESDEvent.h>
46 #include <AliESDpid.h>
47 #include <AliESDtrack.h>
48 #include <AliESDInputHandler.h>
49 #include <AliAnalysisManager.h>
50 #include <AliTrackerBase.h>
51 #include <AliTRDPIDReference.h>
52 #include <AliTRDPIDResponse.h>
53 #include <AliTRDCalChamberStatus.h>
54 #include <AliTender.h>
56 #include "AliTRDTenderSupply.h"
58 ClassImp(AliTRDTenderSupply)
60 //_____________________________________________________
61 AliTRDTenderSupply::AliTRDTenderSupply() :
65 fTrdOnlineTrackMatcher(NULL),
66 fChamberGainOld(NULL),
67 fChamberGainNew(NULL),
68 fChamberVdriftOld(NULL),
69 fChamberVdriftNew(NULL),
70 fRunByRunCorrection(NULL),
72 fNormalizationFactor(1.),
76 fGainCorrection(kTRUE),
77 // fLoadReferences(kFALSE),
78 // fLoadReferencesFromCDB(kFALSE),
79 fLoadDeadChambers(kFALSE),
80 fHasReferences(kFALSE),
81 fHasNewCalibration(kTRUE),
83 fRedoTrdMatching(kTRUE),
84 fNameRunByRunCorrection(),
85 fNormalizationFactorArray(NULL)
90 memset(fBadChamberID, 0, sizeof(Int_t) * kNChambers);
91 memset(fSlicesForPID, 0, sizeof(UInt_t) * 2);
94 //_____________________________________________________
95 AliTRDTenderSupply::AliTRDTenderSupply(const char *name, const AliTender *tender) :
96 AliTenderSupply(name,tender),
99 fTrdOnlineTrackMatcher(NULL),
100 fChamberGainOld(NULL),
101 fChamberGainNew(NULL),
102 fChamberVdriftOld(NULL),
103 fChamberVdriftNew(NULL),
104 fRunByRunCorrection(NULL),
105 fPIDmethod(k1DLQpid),
106 fNormalizationFactor(1.),
110 fGainCorrection(kTRUE),
111 // fLoadReferences(kFALSE),
112 // fLoadReferencesFromCDB(kFALSE),
113 fLoadDeadChambers(kFALSE),
114 fHasReferences(kFALSE),
115 fHasNewCalibration(kTRUE),
117 fRedoTrdMatching(kTRUE),
118 fNameRunByRunCorrection(),
119 fNormalizationFactorArray(NULL)
124 memset(fSlicesForPID, 0, sizeof(UInt_t) * 2);
125 memset(fBadChamberID, 0, sizeof(Int_t) * kNChambers);
128 //_____________________________________________________
129 AliTRDTenderSupply::~AliTRDTenderSupply()
134 if(fNormalizationFactorArray) delete fNormalizationFactorArray;
135 delete fTrdOnlineTrackMatcher;
138 //_____________________________________________________
139 void AliTRDTenderSupply::Init()
142 // Initialise TRD tender
145 AliAnalysisManager *mgr=AliAnalysisManager::GetAnalysisManager();
147 // 1DLQ PID implemented in the AliESD object
148 fESDpid=fTender->GetESDhandler()->GetESDpid();
150 fESDpid=new AliESDpid;
151 fTender->GetESDhandler()->SetESDpid(fESDpid);
154 //if(fLoadReferences && !fLoadReferencesFromCDB) LoadReferences();
155 //fESDpid->GetTRDResponse().SetGainNormalisationFactor(fNormalizationFactor);
156 //fESDpid->SetTRDslicesForPID(fSlicesForPID[0], fSlicesForPID[1]);
158 if(fNameRunByRunCorrection.Length()) LoadRunByRunCorrection(fNameRunByRunCorrection.Data());
159 fTrdOnlineTrackMatcher=new AliTRDonlineTrackMatching();
160 // Set Normalisation Factors
161 if(mgr->GetMCtruthEventHandler()){
163 //fESDpid->GetTRDResponse().SetGainNormalisationFactor(1.);
164 SwitchOffGainCorrection();
168 //if(fPIDmethod == kNNpid) fPidRecal->SetGainScaleFactor(1.14);
169 //fESDpid->GetTRDResponse().SetGainNormalisationFactor(1.14);
170 SwitchOnGainCorrection();
174 //_____________________________________________________
175 void AliTRDTenderSupply::ProcessEvent()
178 // Reapply pid information
180 if (fTender->RunChanged()){
181 AliDebug(0, Form("AliTPCTenderSupply::ProcessEvent - Run Changed (%d)\n",fTender->GetRun()));
182 if (fGainCorrection) SetChamberGain();
183 //if(fLoadReferences && !fHasReferences) LoadReferences();
184 if(fLoadDeadChambers) LoadDeadChambersFromCDB();
186 if(AliGeomManager::GetGeometry()){
187 AliInfo("Geometry already loaded by other tenders");
189 if(fGeoFile) AliInfo(Form("Load geometry from file %s\n", fGeoFile));
190 else AliInfo("Load Geometry from OCDB\n");
191 AliGeomManager::LoadGeometry(fGeoFile);
196 fESD = fTender->GetEvent();
198 if(fNormalizationFactorArray) fNormalizationFactor = GetNormalizationFactor(fESD->GetRunNumber());
\r
199 Int_t ntracks=fESD->GetNumberOfTracks();
203 if (fRedoTrdMatching) {
204 if (!fTrdOnlineTrackMatcher->ProcessEvent(fESD)) {
205 AliError("TRD online track matching failed!");
212 // recalculate PID probabilities
214 Int_t detectors[kNPlanes];
215 for(Int_t itrack = 0; itrack < ntracks; itrack++){
216 for(Int_t idet = 0; idet < 5; idet++) detectors[idet] = -1;
217 AliESDtrack *track=fESD->GetTrack(itrack);
218 // Recalculate likelihoods
219 if(!(track->GetStatus() & AliESDtrack::kTRDout)) continue;
220 AliDebug(2, Form("TRD track found, gain correction: %s, Number of bad chambers: %d\n", fGainCorrection ? "Yes" : "No", fNBadChambers));
221 if(GetTRDchamberID(track, detectors)){
222 if(fGainCorrection && fHasNewCalibration) ApplyGainCorrection(track, detectors);
223 if(fNBadChambers) MaskChambers(track, detectors);
225 if(fRunByRunCorrection) ApplyRunByRunCorrection(track);
226 if(fNormalizationFactor != 1.){
227 //printf("Gain Factor: %f\n", fNormalizationFactor);
228 // Renormalize charge
229 Double_t qslice = -1;
230 for(Int_t ily = 0; ily < 6; ily++){
231 for(Int_t is = 0; is < track->GetNumberOfTRDslices(); is++){
232 qslice = track->GetTRDslice(ily, is);
233 //printf("Doing layer %d slice %d, value %f\n", ily, is, qslice);
235 qslice *= fNormalizationFactor;
236 //printf("qslice new: %f\n", qslice);
237 track->SetTRDslice(qslice, ily, is);
246 fESDpid->MakeTRDPID(fESD->GetTrack(itrack));
249 AliError("PID Method not implemented (yet)");
254 //_____________________________________________________
255 void AliTRDTenderSupply::LoadDeadChambersFromCDB(){
257 // Load Dead Chambers from the OCDB
259 AliDebug(1, "Loading Dead Chambers from the OCDB");
260 AliCDBEntry *en = fTender->GetCDBManager()->Get("TRD/Calib/ChamberStatus",fTender->GetRun());
262 AliError("Dead Chambers not in OCDB");
267 AliTRDCalChamberStatus* chamberStatus = 0;
269 chamberStatus = (AliTRDCalChamberStatus*)en->GetObject();
270 if(!chamberStatus) AliError("List with the dead chambers not found");
271 for(Int_t ichamber = 0; ichamber < 540; ichamber++) {
272 if(!chamberStatus->IsGood(ichamber)){
273 //printf("Chamber not installed %d\n",ichamber);
274 AddBadChamber(ichamber);
281 //_____________________________________________________
282 void AliTRDTenderSupply::LoadReferences(){
284 // Load Reference from the OCDB/OADB into the PID Response
286 if(fLoadReferencesFromCDB){
287 AliDebug(1, "Loading Reference Distributions from the OCDB");
288 AliCDBEntry *en = fTender->GetCDBManager()->Get("TRD/Calib/PIDLQ1D");
290 AliError("References for 1D Likelihood Method not in OCDB");
294 TObjArray *arr = dynamic_cast<TObjArray *>(en->GetObject());
295 if(!arr) AliError("List with the references not found");
297 // Get new references
300 AliTRDPIDReference *ref = NULL;
302 if(!TString(o->IsA()->GetName()).CompareTo("AliTRDPIDReference")){
303 ref = dynamic_cast<AliTRDPIDReference *>(o);
308 fESDpid->GetTRDResponse().Load(ref);
309 fHasReferences = kTRUE;
310 AliDebug(1, "Reference distributions loaded into the PID Response");
312 AliError("References not found");
315 // Backward compatibility mode
316 AliInfo("Loading Reference Distributions from ROOT file");
317 fESDpid->GetTRDResponse().Load("$TRAIN_ROOT/util/tender/LQ1dRef_v3.root");
318 fHasReferences = kTRUE;
323 //_____________________________________________________
324 void AliTRDTenderSupply::SetChamberGain(){
326 // Load Chamber Gain factors into the Tender supply
329 //find previous entry from the UserInfo
330 TTree *tree=((TChain*)fTender->GetInputData(0))->GetTree();
332 fHasNewCalibration = kFALSE;
333 AliError("Tree not found in ESDhandler");
337 TList *userInfo=(TList*)tree->GetUserInfo();
339 fHasNewCalibration = kFALSE;
340 AliError("No UserInfo found in tree");
344 TList *cdbList=(TList*)userInfo->FindObject("cdbList");
346 fHasNewCalibration = kFALSE;
347 AliError("No cdbList found in UserInfo");
348 if (AliLog::GetGlobalLogLevel()>=AliLog::kError) userInfo->Print();
351 fHasNewCalibration = kTRUE;
353 TIter nextCDB(cdbList);
355 while ( (os=(TObjString*)nextCDB()) ){
356 if(os->GetString().Contains("TRD/Calib/ChamberGainFactor")){
357 // Get Old gain calibration
358 AliCDBId *id=AliCDBId::MakeFromString(os->GetString());
360 AliCDBEntry *entry=fTender->GetCDBManager()->Get(id->GetPath(), id->GetFirstRun(), id->GetVersion());
362 AliError("No previous gain calibration entry found");
366 fChamberGainOld = dynamic_cast<AliTRDCalDet *>(entry->GetObject());
368 AliDebug(1, Form("Used old Gain entry: %s\n",entry->GetId().ToString().Data()));
369 } else if(os->GetString().Contains("TRD/Calib/ChamberVdrift")){
370 // Get Old drift velocity calibration
371 AliCDBId *id=AliCDBId::MakeFromString(os->GetString());
373 AliCDBEntry *entry=fTender->GetCDBManager()->Get(id->GetPath(), id->GetFirstRun(), id->GetVersion());
375 AliError("No previous drift velocity calibration entry found");
379 fChamberVdriftOld = dynamic_cast<AliTRDCalDet *>(entry->GetObject());
381 AliDebug(1, Form("Used old Drift velocity entry: %s\n",entry->GetId().ToString().Data()));
386 // Get Latest Gain Calib Object
387 AliCDBEntry *entryNew=fTender->GetCDBManager()->Get("TRD/Calib/ChamberGainFactor",fTender->GetRun());
389 AliDebug(1, Form("Used new Gain entry: %s\n",entryNew->GetId().ToString().Data()));
390 fChamberGainNew = dynamic_cast<AliTRDCalDet *>(entryNew->GetObject());
392 AliError("No new gain calibration entry found");
394 // Also get the latest Drift Velocity calibration object
395 entryNew=fTender->GetCDBManager()->Get("TRD/Calib/ChamberVdrift",fTender->GetRun());
397 AliDebug(1, Form("Used new Drift velocity entry: %s\n",entryNew->GetId().ToString().Data()));
398 fChamberVdriftNew = dynamic_cast<AliTRDCalDet *>(entryNew->GetObject());
400 AliError("No new drift velocity calibration entry found");
402 if(!fChamberGainNew || !fChamberVdriftNew){
403 AliError("No recent calibration found");
404 fHasNewCalibration = kFALSE;
408 //_____________________________________________________
409 void AliTRDTenderSupply::LoadRunByRunCorrection(const char *filename){
411 // Define run by run gain correction for the charge
414 TDirectory *bkp = gDirectory;
415 TFile *in = TFile::Open(filename);
417 fRunByRunCorrection = dynamic_cast<AliOADBContainer *>(in->Get("TRDchargeCorrection"));
419 if(fRunByRunCorrection )
420 AliDebug(2, Form("OADB Container has %d runs\n", fRunByRunCorrection->GetNumberOfEntries()));
421 /* Temporarily out due to a bug in AliOADBContainer
422 fRunByRunCorrection = new AliOADBContainer("TRDchargeCorrection");
423 Int_t status = fRunByRunCorrection->InitFromFile(filename, "TRDchargeCorrection");
424 if(!status) AliDebug(1, Form("Run-dependend gain correction factors loaded from OADB file %s", filename));
426 AliDebug(1, "Failed Loading Run-dependend gain correction factors");
427 delete fRunByRunCorrection;
428 fRunByRunCorrection = NULL;
433 //_____________________________________________________
434 Bool_t AliTRDTenderSupply::IsBadChamber(Int_t chamberID){
436 // Check if the chamber id is in the list of bad chambers
438 Bool_t isBad = kFALSE;
439 for(UInt_t icam = 0; icam < fNBadChambers; icam++)
440 if(fBadChamberID[icam] == chamberID){
442 //printf("cross checking: %i \n",chamberID);
448 //_____________________________________________________
449 void AliTRDTenderSupply::ApplyGainCorrection(AliESDtrack * track, const Int_t * const chamberID){
451 // Apply new gain factors to the track
453 if(!fChamberGainNew || !fChamberGainOld){
454 AliError("Cannot apply gain correction.");
458 if(!(track->GetStatus() & AliESDtrack::kTRDout)) return;
459 Bool_t applyCorrectionVdrift = kFALSE;
460 if(fChamberVdriftOld && fChamberVdriftNew) applyCorrectionVdrift = kTRUE;
462 for(Int_t iplane = 0; iplane < kNPlanes; iplane++){
463 if(chamberID[iplane] < 0) continue;
464 if(IsBadChamber(chamberID[iplane])) continue; // Don't apply gain correction for chambers which are in the list of bad chambers
466 // Take old and new gain factor and make ratio
467 Double_t facOld = fChamberGainOld->GetValue(chamberID[iplane]);
468 Double_t facNew = fChamberGainNew->GetValue(chamberID[iplane]);
469 Double_t correction = facNew/facOld;
470 if(applyCorrectionVdrift){
471 // apply also correction for drift velocity calibration
472 Double_t vDriftOld = fChamberVdriftOld->GetValue(chamberID[iplane]);
473 Double_t vDriftNew = fChamberVdriftNew->GetValue(chamberID[iplane]);
474 correction *= vDriftNew/vDriftOld;
476 AliDebug(2, Form("Applying correction factor %f\n", correction));
477 for(Int_t islice = 0; islice < track->GetNumberOfTRDslices(); islice++){
478 Double_t qslice = track->GetTRDslice(iplane, islice);
479 if(qslice <= 0.) continue;
480 track->SetTRDslice(qslice / correction, iplane, islice);
485 //_____________________________________________________
486 void AliTRDTenderSupply::ApplyRunByRunCorrection(AliESDtrack *const track) {
488 // Equalize charge distribution by applying run-by-run correction (multiplicative)
491 TVectorD *corrfactor = dynamic_cast<TVectorD *>(fRunByRunCorrection->GetObject(fTender->GetRun()));
493 // No correction available - simply return
\r
494 AliDebug(2, "Couldn't derive gain correction factor from OADB");
497 else AliDebug(2, Form("Gain factor from OADB %f", (*corrfactor)[0]));
499 for(Int_t ily = 0; ily < kNPlanes; ily++){
500 for(Int_t islice = 0; islice < track->GetNumberOfTRDslices(); islice++){
501 slice = track->GetTRDslice(ily, islice);
502 if(slice < 0.001) continue; // do not modify slices which are 0 or negative
503 slice *= (*corrfactor)[0];
504 track->SetTRDslice(slice, ily, islice);
509 //_____________________________________________________
510 void AliTRDTenderSupply::SetNormalizationFactor(Double_t norm, Int_t runMin, Int_t runMax) {
512 // Set the normalisation factor for a given run range
514 if(!fNormalizationFactorArray)
515 fNormalizationFactorArray = new TObjArray;
516 TVectorD *entry = new TVectorD(3);
517 TVectorD &myentry = *entry;
521 fNormalizationFactorArray->Add(entry);
524 //_____________________________________________________
525 Double_t AliTRDTenderSupply::GetNormalizationFactor(Int_t runnumber){
527 // Load the normalization factor
\r
530 if(fNormalizationFactorArray){
532 Int_t runMin, runMax;
533 TIter entries(fNormalizationFactorArray);
534 while((entry = dynamic_cast<TVectorD *>(entries()))){
535 TVectorD &myentry = *entry;
536 runMin = TMath::Nint(myentry(0));
537 runMax = TMath::Nint(myentry(1));
538 if(runnumber >= runMin && runnumber <= runMax) norm = myentry(2);
541 AliDebug(1, Form("Gain normalization factor: %f\n", norm));
545 //_____________________________________________________
546 void AliTRDTenderSupply::MaskChambers(AliESDtrack *const track, const Int_t * const chamberID){
548 // Mask out chambers which are in the list of bad chambers
549 // Set chamber signal to 0 and reduce the number of tracklets used for PID
551 AliDebug(2, "Masking bad chambers for TRD track");
552 Int_t nTrackletsPID = 0, nslice = 0, nTracklets = track->GetTRDntracklets();
553 Bool_t badChamber = kFALSE;
554 //Int_t nbad = 0 ; // Number of bad chambers which contain also a signal
555 //Int_t nsliceBad = 0; // Number of slices in tracklet in a bad chamber
556 for(Int_t iplane = 0; iplane < kNPlanes; iplane++){
558 nslice = 0; //nsliceBad = 0;
559 if(IsBadChamber(chamberID[iplane])) badChamber = kTRUE;
560 for(Int_t islice = 0; islice < track->GetNumberOfTRDslices(); islice++){
562 //if(track->GetTRDslice(iplane, islice)) nsliceBad++;
563 track->SetTRDslice(-1, iplane, islice);
564 } else if(track->GetTRDslice(iplane, islice) > 0.001) nslice++;
566 //if(nsliceBad) nbad++;
567 if(nslice > 0) nTrackletsPID++;
569 //if(nbad) track->SetTRDncls(track->GetTRDncls() - 20 * nbad); // subtract mean number of clusters per tracklet for bad tracklets
570 // Use nTrackletsPID to indicate the number of tracklets from good
571 // chambers so they are used for the PID
572 track->SetTRDntracklets(nTrackletsPID | (nTracklets << 3));
575 //_____________________________________________________
576 Bool_t AliTRDTenderSupply::GetTRDchamberID(AliESDtrack * const track, Int_t *detectors) {
578 // Calculate TRD chamber ID
580 Double_t p = track->GetOuterParam() ? track->GetOuterParam()->P() : track->P();
581 if(p < fPthreshold) return kFALSE; // Apply low momentum cutoff
583 Double_t xLayer[kNPlanes] = {300.2, 312.8, 325.4, 338., 350.6, 363.2};
584 Double_t etamin[kNStacks] = {0.536, 0.157, -0.145, -0.527,-0.851};
585 Double_t etamax[kNStacks] = {0.851, 0.527, 0.145, -0.157,-0.536};
586 //Double_t zboundary[kNPlanes] = {302., 317., 328., 343., 350., 350.};
587 for(Int_t ily = 0; ily < kNPlanes; ily++) detectors[ily] = -1;
589 const AliExternalTrackParam *trueparam = NULL;
590 if(track->GetOuterParam()) trueparam = track->GetOuterParam();
591 else if(track->GetTPCInnerParam()) trueparam = track->GetTPCInnerParam();
592 else if(track->GetInnerParam()) trueparam = track->GetInnerParam();
594 AliDebug(2, "No Track Params");
598 AliExternalTrackParam workparam(*trueparam); // Do calculation on working Copy
601 for(Int_t ily = 0; ily < kNPlanes; ily++){
602 //if(TMath::Abs(workparam.GetZ()) > zboundary[ily]) break;
603 //if(!AliTrackerBase::PropagateTrackToBxByBz(&workparam, xLayer[ily], 0.139, 100)){ // Assuming the pion mass
604 if(!workparam.PropagateTo(xLayer[ily], fESD->GetMagneticField())) {
605 AliDebug(2, "Propagation failed");
608 workparam.GetXYZ(pos);
609 Double_t trackAlpha = TMath::ATan2(pos[1], pos[0]);
610 if(trackAlpha < 0) trackAlpha = 2 * TMath::Pi() + trackAlpha;
611 Double_t secAlpha = 2 * TMath::Pi() / 18.;
613 Int_t sector = static_cast<Int_t>(trackAlpha/secAlpha);
616 // Compare to simple propagation without magnetic field
617 AliExternalTrackParam workparam1(*trueparam); // Do calculation on working Copy
619 //if(!workparam1.PropagateTo(xLayer[ily], fESD->GetMagneticField())) {
620 if(!AliTrackerBase::PropagateTrackToBxByBz(&workparam1, xLayer[ily], 0.139, 100)){ // Assuming the pion mass
621 AliDebug(2, "Propagation failed");
624 workparam1.GetXYZ(pos1);
625 Double_t trackAlpha1 = TMath::ATan2(pos1[1], pos1[0]);
626 if(trackAlpha1 < 0) trackAlpha1 = 2 * TMath::Pi() + trackAlpha1;
628 Int_t sector1 = static_cast<Int_t>(trackAlpha1/secAlpha);
629 AliDebug(2, Form("Alpha: Old %f, New %f, diff %f", trackAlpha, trackAlpha1, trackAlpha-trackAlpha1));
630 AliDebug(2, Form("Sector: Old %d, New %d", sector, sector1));
633 Double_t etaTrack = track->Eta();
635 for(Int_t istack = 0; istack < 5; istack++){
636 if(etaTrack >= etamin[istack] && etaTrack <= etamax[istack]){
642 AliDebug(2, "Dead Area");
646 detectors[ily] = sector * kNStacks * kNPlanes + stack * kNPlanes + ily;
649 return nDet ? kTRUE : kFALSE;