From: abercuci Date: Fri, 30 Oct 2009 08:12:25 +0000 (+0000) Subject: copy TRD performance train to PWG1 X-Git-Url: http://git.uio.no/git/?p=u%2Fmrichter%2FAliRoot.git;a=commitdiff_plain;h=1ee39b3a7eaefd7a1b25741a34738772c5607262 copy TRD performance train to PWG1 --- diff --git a/PWG1/TRD/AliTRDalignmentTask.cxx b/PWG1/TRD/AliTRDalignmentTask.cxx new file mode 100644 index 00000000000..37681fa80b3 --- /dev/null +++ b/PWG1/TRD/AliTRDalignmentTask.cxx @@ -0,0 +1,143 @@ +/************************************************************************** +* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* * +* Author: The ALICE Off-line Project. * +* Contributors are mentioned in the code where appropriate. * +* * +* Permission to use, copy, modify and distribute this software and its * +* documentation strictly for non-commercialf purposes is hereby granted * +* without fee, provided that the above copyright notice appears in all * +* copies and that both the copyright notice and this permission notice * +* appear in the supporting documentation. The authors make no claims * +* about the suitability of this software for any purpose. It is * +* provided "as is" without express or implied warranty. * +**************************************************************************/ + +/////////////////////////////////////////////// +// TRD alignment task +// +// Some documentation +// +// Authors : +// +//////////////////////////////////////////////// + +#include "TTreeStream.h" +#include "TROOT.h" +#include "TH1.h" +#include "TH2.h" + +#include "AliTrackPointArray.h" +#include "AliLog.h" + +#include "AliTRDgeometry.h" +#include "AliTRDcluster.h" +#include "AliTRDseedV1.h" +#include "AliTRDtrackV1.h" + +#include "AliTRDalignmentTask.h" + +ClassImp(AliTRDalignmentTask) + +//________________________________________________________ +AliTRDalignmentTask::AliTRDalignmentTask() + :AliTRDrecoTask("Alignment", "TRD alignment") + ,fTree(0x0) + ,fArray(0x0) +{ + InitFunctorList(); + DefineOutput(1, TTree::Class()); + +} + +//________________________________________________________ +AliTRDalignmentTask::~AliTRDalignmentTask() +{ + if (fArray) delete fArray; +} + + +//________________________________________________________ +void AliTRDalignmentTask::CreateOutputObjects() +{ + // spatial resolution + OpenFile(1, "RECREATE"); + + fTree = new TTree("spTree", "Tree with track space point arrays"); + fTree->Branch("SP","AliTrackPointArray", &fArray); +} + + +//________________________________________________________ +void AliTRDalignmentTask::Exec(Option_t *opt) +{ +// Documentation to come + + AliTRDrecoTask::Exec(opt); + PostData(1, fTree); +} + + +//________________________________________________________ +TH1* AliTRDalignmentTask::PlotTrackPoints(const AliTRDtrackV1 *track) +{ +// Documentation to come + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + + if (fArray) delete fArray; + fArray = new AliTrackPointArray(fkTrack->GetNumberOfTracklets()); + + // Filling the track points array + Float_t x, y, z; + AliTrackPoint p; Int_t ip = 0; + AliTRDseedV1 *tracklet = 0x0; + for(Int_t il=0; ilGetTracklet(il))) continue; + if(!tracklet->IsOK()) continue; + tracklet->Fit(kTRUE); + + x = tracklet->GetX0(); + y = tracklet->GetYfit(0)-tracklet->GetYfit(1)*(tracklet->GetX0()-x); + z = tracklet->GetZfit(0); + p.SetXYZ(x,y,z); + fArray->AddPoint(ip++, &p); + } + fTree->Fill(); + +/* if(fDebugLevel>=1){ + Float_t yt = fRim.GetYat(x[il]); + (*fDebugStream) << "TrkltResiduals" + << "layer=" << il + << "x=" <GetNPoints() && iGetPoint(pa,i); + //printf("comparing %7.3f with %7.3f\n",p->GetY(),pa.GetY()); + if (p->GetResidual(pa,0)<1e-8) return kTRUE; + //printf("different\n"); + } + return kFALSE; +} diff --git a/PWG1/TRD/AliTRDalignmentTask.h b/PWG1/TRD/AliTRDalignmentTask.h new file mode 100644 index 00000000000..568894a66cd --- /dev/null +++ b/PWG1/TRD/AliTRDalignmentTask.h @@ -0,0 +1,45 @@ +#ifndef ALITRDALIGNMENTTASK_H +#define ALITRDALIGNMENTTASK_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + + +//////////////////////////////////////////////////////////////////////////// +// // +// TRD Alignment QA // +// // +//////////////////////////////////////////////////////////////////////////// + +#ifndef ALITRDRECOTASK_H +#include "AliTRDrecoTask.h" +#endif + +class TH1; +class TTree; +class AliTrackPoint; +class AliTrackPointArray; +class AliTRDtrackV1; +class AliTRDalignmentTask : public AliTRDrecoTask +{ +public: + + AliTRDalignmentTask(); + virtual ~AliTRDalignmentTask(); + + void CreateOutputObjects(); + void Exec(Option_t *opt); + TH1* PlotTrackPoints(const AliTRDtrackV1 *track=0x0); + Bool_t PostProcess() { return kTRUE;} + +private: + Bool_t IsIdenticalWithOneOf(AliTrackPoint * const p, AliTrackPointArray *parray, int nmax); + AliTRDalignmentTask(const AliTRDalignmentTask&); + AliTRDalignmentTask& operator=(const AliTRDalignmentTask&); + +private: + TTree *fTree; //! pointer to the output TTree + AliTrackPointArray *fArray; // pointer to the track points + + ClassDef(AliTRDalignmentTask, 1) // tracking resolution task +}; +#endif diff --git a/PWG1/TRD/AliTRDcalibration.cxx b/PWG1/TRD/AliTRDcalibration.cxx new file mode 100644 index 00000000000..82a79075111 --- /dev/null +++ b/PWG1/TRD/AliTRDcalibration.cxx @@ -0,0 +1,1373 @@ + +/************************************************************************** +* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* * +* Author: The ALICE Off-line Project. * +* Contributors are mentioned in the code where appropriate. * +* * +* Permission to use, copy, modify and distribute this software and its * +* documentation strictly for non-commercial purposes is hereby granted * +* without fee, provided that the above copyright notice appears in all * +* copies and that both the copyright notice and this permission notice * +* appear in the supporting documentation. The authors make no claims * +* about the suitability of this software for any purpose. It is * +* provided "as is" without express or implied warranty. * +**************************************************************************/ + +///////////////////////////////////////////////////////////////////////////////// +// +// AliTRDcalibration +// +// Task to run the calibration offline. +// Author: +// R. Bailhache (rbailhache@ikf.uni-frankfurt.de, R.Bailhache@gsi.de) +// +////////////////////////////////////////////////////////////////////////////////// + + +#include "Riostream.h" +#include "TChain.h" +#include "TTree.h" +#include "TProfile2D.h" +#include "TH2I.h" +#include "TH1F.h" +#include "TList.h" +#include "TMath.h" +#include "TCanvas.h" +#include "TObject.h" +#include "TFile.h" +#include "TObjArray.h" +#include "TGraph.h" +#include "TStyle.h" +#include "TLegend.h" +#include "TGraphErrors.h" + +#include "AliTRDrecoTask.h" +#include "AliAnalysisManager.h" + +#include "AliESDInputHandler.h" +#include "AliTRDtrackV1.h" +#include "AliTRDseedV1.h" +#include "AliTRDcluster.h" +#include "info/AliTRDtrackInfo.h" +#include "AliTRDcalibDB.h" + +#include "AliTRDCalibraFillHisto.h" +#include "AliTRDCalibraFit.h" +#include "AliTRDCalibraVdriftLinearFit.h" +#include "AliTRDCalibraMode.h" +#include "AliTRDCalibraVector.h" +#include "./Cal/AliTRDCalPad.h" +#include "./Cal/AliTRDCalDet.h" +#include "AliCDBMetaData.h" +#include "AliCDBManager.h" +#include "AliCDBStorage.h" + +#include "AliLog.h" + +#include "AliTRDcalibration.h" + + +ClassImp(AliTRDcalibration) + +//________________________________________________________________________ +AliTRDcalibration::AliTRDcalibration() + :AliTRDrecoTask("Calibration", "Calibration on tracks") + ,fTrackInfo(0) + ,ftrdTrack(0) + ,fcl(0) + ,fTRDCalibraFillHisto(0) + ,fNbTRDTrack(0) + ,fNbTRDTrackOffline(0) + ,fNbTRDTrackStandalone(0) + ,fNbTRDTracklet(0) + ,fNbTRDTrackletOffline(0) + ,fNbTRDTrackletStandalone(0) + ,fNbTimeBin(0x0) + ,fNbTimeBinOffline(0x0) + ,fNbTimeBinStandalone(0x0) + ,fNbClusters(0) + ,fNbClustersOffline(0) + ,fNbClustersStandalone(0) + ,fPHSum(0) + ,fCHSum(0) + ,fDetSum(0) + ,fDetSumVector(0) + ,fHisto2d(kTRUE) + ,fVector2d(kFALSE) + ,fVdriftLinear(kTRUE) + ,flow(0) + ,fhigh(30) + ,fNbTimeBins(30) + ,ffillZero(kFALSE) + ,fnormalizeNbOfCluster(kFALSE) + ,fmaxCluster(0) + ,fOfflineTracks(kFALSE) + ,fStandaloneTracks(kFALSE) + ,fCompressPerDetector(kFALSE) + ,fRunNumber(0) + ,fkNameDirectory("local://.") + ,fGraph(0x0) + ,fPostProcess(kFALSE) +{ + // Constructor + + fNRefFigures = 17; + + for(Int_t k = 0; k < 3; k++) + { + fNz[k]=0; + fNrphi[k]=0; + } + +} +//________________________________________________________________________ +AliTRDcalibration::~AliTRDcalibration() +{ + // Default destructor + + if(fNbTRDTrack) delete fNbTRDTrack; + if(fNbTRDTrackOffline) delete fNbTRDTrackOffline; + if(fNbTRDTrackStandalone) delete fNbTRDTrackStandalone; + if(fNbTRDTracklet) delete fNbTRDTracklet; + if(fNbTRDTrackletOffline) delete fNbTRDTrackletOffline; + if(fNbTRDTrackletStandalone) delete fNbTRDTrackletStandalone; + if(fNbTimeBin) delete fNbTimeBin; + if(fNbTimeBinOffline) delete fNbTimeBinOffline; + if(fNbTimeBinStandalone) delete fNbTimeBinStandalone; + if(fNbClusters) delete fNbClusters; + if(fNbClustersOffline) delete fNbClustersOffline; + if(fNbClustersStandalone) delete fNbClustersStandalone; + if(fPHSum) delete fPHSum; + if(fCHSum) delete fCHSum; + if(fDetSum) delete fDetSum; + if(fDetSumVector) delete fDetSumVector; + if(fkNameDirectory) delete fkNameDirectory; + if(fGraph){fGraph->Delete(); delete fGraph;} + +} +//________________________________________________________________________ +void AliTRDcalibration::CreateOutputObjects() +{ + // Create output objects + + OpenFile(0, "RECREATE"); + + // Number of time bins + AliTRDcalibDB *cal = AliTRDcalibDB::Instance(); + fNbTimeBins = cal->GetNumberOfTimeBins(); + + // instance calibration: what to calibrate + fTRDCalibraFillHisto = AliTRDCalibraFillHisto::Instance(); + fTRDCalibraFillHisto->SetHisto2d(fHisto2d); // choose to use histograms + fTRDCalibraFillHisto->SetVector2d(fVector2d); // choose to use vectors + fTRDCalibraFillHisto->SetCH2dOn(); // choose to calibrate the gain + fTRDCalibraFillHisto->SetPH2dOn(); // choose to calibrate the drift velocity + fTRDCalibraFillHisto->SetPRF2dOn(); // choose to look at the PRF + fTRDCalibraFillHisto->SetLinearFitterOn(fVdriftLinear); // Other possibility vdrift VDRIFT + fTRDCalibraFillHisto->SetLinearFitterDebugOn(fVdriftLinear); // Other possibility vdrift + + // segmentation (should be per default the max and add at the end) + for(Int_t k = 0; k < 3; k++){ + if(((fNz[k] != 10) && (fNrphi[k] != 10)) && ((fNz[k] != 100) && (fNrphi[k] != 100))) { + fTRDCalibraFillHisto->SetNz(k,fNz[k]); // Mode calibration + fTRDCalibraFillHisto->SetNrphi(k,fNrphi[k]); // Mode calibration + } + else { + if((fNz[k] == 100) && (fNrphi[k] == 100)) { + if(fVector2d) AliInfo("The mode all together is not supported by the vector method"); + fTRDCalibraFillHisto->SetAllTogether(k); + } + if((fNz[k] == 10) && (fNrphi[k] == 10)) { + if(fVector2d) AliInfo("The mode per supermodule is not supported by the vector method"); + fTRDCalibraFillHisto->SetPerSuperModule(k); + } + } + } + + // Debug level + fTRDCalibraFillHisto->SetDebugLevel(DebugLevel()); //debug stuff + + // Init the stuff + fTRDCalibraFillHisto->Init2Dhistos(); // initialise the histos + + // cuts + fTRDCalibraFillHisto->SetNumberClusters(flow); // At least flow clusters + fTRDCalibraFillHisto->SetNumberClustersf(fhigh); // The more fhigh clusters + fTRDCalibraFillHisto->SetFillWithZero(ffillZero); // Fill zeros + fTRDCalibraFillHisto->SetNormalizeNbOfCluster(fnormalizeNbOfCluster); // For iterations + + // Add them to the container + fContainer = new TObjArray(); + if(fHisto2d) { + fContainer->Add(fTRDCalibraFillHisto->GetCH2d()); //TH2I + fContainer->Add(fTRDCalibraFillHisto->GetPH2d()); //TProfile2D + fContainer->Add(fTRDCalibraFillHisto->GetPRF2d()); //TProfile2D + } + if(fVdriftLinear) fContainer->Add(fTRDCalibraFillHisto->GetVdriftLinearFit()); // Other drift velocity + if(fVector2d) fContainer->Add(fTRDCalibraFillHisto->GetCalibraVector()); //calibra vector + + if(DebugLevel()) { + + // Init the debug histos + fNbTRDTrack = new TH1F("TRDTrack","TRDTrack",500,0,500); + fNbTRDTrack->Sumw2(); + fNbTRDTrackOffline = new TH1F("TRDTrackOffline","TRDTrackOffline",500,0,500); + fNbTRDTrackOffline->Sumw2(); + fNbTRDTrackStandalone = new TH1F("TRDTrackStandalone","TRDTrackStandalone",500,0,500); + fNbTRDTrackStandalone->Sumw2(); + // + fNbTRDTracklet = new TH1F("TRDTracklet","TRDTracklet",540,0.,540.); + fNbTRDTracklet->Sumw2(); + fNbTRDTrackletOffline = new TH1F("TRDTrackletOffline","TRDTrackletOffline",540,0.,540.); + fNbTRDTrackletOffline->Sumw2(); + fNbTRDTrackletStandalone = new TH1F("TRDTrackletStandalone","TRDTrackletStandalone",540,0.,540.); + fNbTRDTrackletStandalone->Sumw2(); + // + fNbTimeBin = new TH1F("TimeBin","TimeBin",35,0,35); + fNbTimeBin->Sumw2(); + fNbTimeBinOffline = new TH1F("TimeBinOffline","TimeBinOffline",35,0,35); + fNbTimeBinOffline->Sumw2(); + fNbTimeBinStandalone = new TH1F("TimeBinStandalone","TimeBinStandalone",35,0,35); + fNbTimeBinStandalone->Sumw2(); + // + fNbClusters = new TH1F("NbClusters","",35,0,35); + fNbClusters->Sumw2(); + fNbClustersOffline = new TH1F("NbClustersOffline","",35,0,35); + fNbClustersOffline->Sumw2(); + fNbClustersStandalone = new TH1F("NbClustersStandalone","",35,0,35); + fNbClustersStandalone->Sumw2(); + // + fPHSum = new TProfile2D("PH2dSum","Nz0Nrphi0" + ,fNbTimeBins,-0.05,(Double_t)(fNbTimeBins/10.0)-0.05 + ,540,0,540); + fPHSum->SetYTitle("Det/pad groups"); + fPHSum->SetXTitle("time [#mus]"); + fPHSum->SetZTitle(" [a.u.]"); + fPHSum->SetStats(0); + // + fCHSum = new TH2I("CH2dSum","Nz0Nrphi0",100,0,300,540,0,540); + fCHSum->SetYTitle("Det/pad groups"); + fCHSum->SetXTitle("charge deposit [a.u]"); + fCHSum->SetZTitle("counts"); + fCHSum->SetStats(0); + fCHSum->Sumw2(); + + // Add them + fContainer->Add(fNbTRDTrack); + fContainer->Add(fNbTRDTrackOffline); + fContainer->Add(fNbTRDTrackStandalone); + fContainer->Add(fNbTRDTracklet); + fContainer->Add(fNbTRDTrackletOffline); + fContainer->Add(fNbTRDTrackletStandalone); + fContainer->Add(fNbTimeBin); + fContainer->Add(fNbTimeBinOffline); + fContainer->Add(fNbTimeBinStandalone); + fContainer->Add(fNbClusters); + fContainer->Add(fNbClustersOffline); + fContainer->Add(fNbClustersStandalone); + fContainer->Add(fPHSum); + fContainer->Add(fCHSum); + + } + +} + +//________________________________________________________________________ +void AliTRDcalibration::Exec(Option_t *) +{ + // + // Execute function where the reference data are filled + // + + if(!fTracks) return; + + // In total + Int_t nbTrdTracks = 0; + // standalone + Int_t nbTrdTracksStandalone = 0; + // offline + Int_t nbTrdTracksOffline = 0; + + + // + // Loop on track in the event + // + //printf("Total of %d\n",fTracks->GetEntriesFast()); + for(Int_t itrk=0; itrk < fTracks->GetEntriesFast(); itrk++){ + + //printf("itrk %d\n",itrk); + + fTrackInfo = (AliTRDtrackInfo*)fTracks->UncheckedAt(itrk); + ftrdTrack = fTrackInfo->GetTrack(); + if(!ftrdTrack) continue; + + nbTrdTracks++; + + fTRDCalibraFillHisto->UpdateHistogramsV1(ftrdTrack); + + if(DebugLevel()) { + + Bool_t standalonetracklet = kFALSE; + const AliTRDseedV1 *tracklet = 0x0; + // + // Loop on tracklet in the event + // + for(Int_t itr = 0; itr < 6; itr++){ + //printf("itr %d\n",itr); + if(!(tracklet = ftrdTrack->GetTracklet(itr))) continue; + if(!tracklet->IsOK()) continue; + // standalone + if(tracklet->IsStandAlone()) standalonetracklet = kTRUE; + Int_t nbclusters = 0; + // For PH + Double_t phtb[AliTRDseedV1::kNtb]; + memset(phtb, 0, AliTRDseedV1::kNtb*sizeof(Double_t)); + // For CH + Double_t sum = 0.0; + // normalisation + Float_t normalisation = 6.67; + Int_t detector = 0; + Int_t crossrow = 0; + for(int ic=0; icGetClusters(icc))) crossrow = 1; + } + if(!(fcl = tracklet->GetClusters(ic))) continue; + nbclusters++; + Int_t time = fcl->GetPadTime(); + Float_t ch = tracklet->GetdQdl(ic); + Float_t qcl = TMath::Abs(fcl->GetQ()); + detector = fcl->GetDetector(); + if((time>-1) && (timeFill(time); + if(tracklet->IsStandAlone()) fNbTimeBinStandalone->Fill(time); + else fNbTimeBinOffline->Fill(time); + } + + fNbTRDTracklet->Fill(detector); + if(tracklet->IsStandAlone()) fNbTRDTrackletStandalone->Fill(detector); + else fNbTRDTrackletOffline->Fill(detector); + + fNbClusters->Fill(nbclusters); + if(tracklet->IsStandAlone()) fNbClustersStandalone->Fill(nbclusters); + else fNbClustersOffline->Fill(nbclusters); + + if((nbclusters > flow) && (nbclusters < fhigh)){ + fCHSum->Fill(sum/20.0,0.0); + for(int ic=0; icFill((Double_t)(ic/10.0),0.0,(Double_t)phtb[ic]); + else { + if(phtb[ic] > 0.0) fPHSum->Fill((Double_t)(ic/10.0),0.0,(Double_t)phtb[ic]); + } + } + } + } + + if(standalonetracklet) nbTrdTracksStandalone++; + else nbTrdTracksOffline++; + + } + + } + + if(DebugLevel()) { + + //Fill Histos + fNbTRDTrack->Fill(nbTrdTracks); + fNbTRDTrackStandalone->Fill(nbTrdTracksStandalone); + fNbTRDTrackOffline->Fill(nbTrdTracksOffline); + + } + + //printf("Nbof tracks %d\n",nbTrdTracks); + + TFile *file = TFile::Open("test.root","RECREATE"); + fContainer->Write(); + file->Close(); + + // Post output data + PostData(0, fContainer); + + //printf("post container\n"); + +} +//________________________________________________________________________ +void AliTRDcalibration::Terminate(Option_t *) +{ + // Draw result to the screen + // Called once at the end of the query + + //printf("terminate\n"); + + if(fTRDCalibraFillHisto) fTRDCalibraFillHisto->DestroyDebugStreamer(); + +} +//________________________________________________________ +Bool_t AliTRDcalibration::GetRefFigure(Int_t ifig) +{ + // + // Draw filled histos + // + + gStyle->SetPalette(1); + gStyle->SetOptStat(1111); + gStyle->SetPadBorderMode(0); + gStyle->SetCanvasColor(10); + gStyle->SetPadLeftMargin(0.13); + gStyle->SetPadRightMargin(0.13); + + if(!fContainer) return kFALSE; + + switch(ifig){ + case kNbTrack:{ + TCanvas *c0 = new TCanvas("c0","c0",10,10,510,510); + TLegend *legNbTrack = new TLegend(.7, .7, .98, .98); + legNbTrack->SetBorderSize(1); + TH1F *h = 0x0; + TH1F *ho = 0x0; + TH1F *hs = 0x0; + if(!(h = (TH1F *)fContainer->FindObject("TRDTrack"))) break; + if(!(ho = (TH1F *)fContainer->FindObject("TRDTrackOffline"))) break; + if(!(hs = (TH1F *)fContainer->FindObject("TRDTrackStandalone"))) break; + c0->cd(); + //gPad->SetLogy(); + gPad->SetGridy(); + gPad->SetGridx(); + h->Draw(); + ho->Draw("same"); + hs->Draw("same"); + legNbTrack->AddEntry(h, "all", "p"); + legNbTrack->AddEntry(ho, "offline", "p"); + legNbTrack->AddEntry(hs, "standalone", "p"); + legNbTrack->Draw("same"); + return kTRUE; + } + case kNbTracklet:{ + TLegend *legNbTracklet = new TLegend(.7, .7, .98, .98); + legNbTracklet->SetBorderSize(1); + TH1F *h = 0x0; + TH1F *ho = 0x0; + TH1F *hs = 0x0; + if(!(h = (TH1F *)fContainer->FindObject("TRDTracklet"))) break; + if(!(ho = (TH1F *)fContainer->FindObject("TRDTrackletOffline"))) break; + if(!(hs = (TH1F *)fContainer->FindObject("TRDTrackletStandalone"))) break; + h->Draw(); + ho->Draw("same"); + hs->Draw("same"); + legNbTracklet->AddEntry(h, "all", "p"); + legNbTracklet->AddEntry(ho, "offline", "p"); + legNbTracklet->AddEntry(hs, "standalone", "p"); + legNbTracklet->Draw("same"); + gPad->SetLogy(); + gPad->SetGridy(); + gPad->SetGridx(); + return kTRUE; + } + case kNbTimeBin:{ + TLegend *legNbTimeBin = new TLegend(.7, .7, .98, .98); + legNbTimeBin->SetBorderSize(1); + TH1F *h = 0x0; + TH1F *ho = 0x0; + TH1F *hs = 0x0; + if(!(h = (TH1F *)fContainer->FindObject("TimeBin"))) break; + if(!(ho = (TH1F *)fContainer->FindObject("TimeBinOffline"))) break; + if(!(hs = (TH1F *)fContainer->FindObject("TimeBinStandalone"))) break; + h->Draw(); + ho->Draw("same"); + hs->Draw("same"); + legNbTimeBin->AddEntry(h, "all", "p"); + legNbTimeBin->AddEntry(ho, "offline", "p"); + legNbTimeBin->AddEntry(hs, "standalone", "p"); + legNbTimeBin->Draw("same"); + //gPad->SetLogy(); + gPad->SetGridy(); + gPad->SetGridx(); + return kTRUE; + } + case kNbClusters:{ + TLegend *legNbClusters = new TLegend(.7, .7, .98, .98); + legNbClusters->SetBorderSize(1); + TH1F *h = 0x0; + TH1F *ho = 0x0; + TH1F *hs = 0x0; + if(!(h = (TH1F *)fContainer->FindObject("NbClusters"))) break; + if(!(ho = (TH1F *)fContainer->FindObject("NbClustersOffline"))) break; + if(!(hs = (TH1F *)fContainer->FindObject("NbClustersStandalone"))) break; + h->Draw(); + ho->Draw("same"); + hs->Draw("same"); + legNbClusters->AddEntry(h, "all", "p"); + legNbClusters->AddEntry(ho, "offline", "p"); + legNbClusters->AddEntry(hs, "standalone", "p"); + legNbClusters->Draw("same"); + gPad->SetLogy(); + gPad->SetGridy(); + gPad->SetGridx(); + return kTRUE; + } + case kPHSum:{ + TProfile2D *h = 0x0; + if(!(h = (TProfile2D *)fContainer->FindObject("PH2dSum"))) break; + TH1D *projh = h->ProjectionX("projh",1,1,"e"); + projh->Draw(); + gPad->SetGridy(); + gPad->SetGridx(); + return kTRUE; + } + case kCHSum:{ + TH2I *h = 0x0; + if(!(h = (TH2I *)fContainer->FindObject("CH2dSum"))) break; + TH1D *projh = h->ProjectionX("projhh",1,1,"e"); + projh->Draw(); + gPad->SetGridy(); + gPad->SetGridx(); + return kTRUE; + } + case kPH2D:{ + if(!fHisto2d) { + AliInfo("Histo was not filled!"); + break; + } + TProfile2D *h = 0x0; + if(!(h = (TProfile2D *)fContainer->FindObject("PH2d"))) break; + h->Draw("lego"); + return kTRUE; + } + case kCH2D:{ + if(!fHisto2d) { + AliInfo("Histo was not filled!"); + break; + } + TH2I *h = 0x0; + if(!(h = (TH2I *)fContainer->FindObject("CH2d"))) break; + h->Draw("lego"); + return kTRUE; + } + case kPRF2D:{ + if(!fHisto2d) { + AliInfo("Histo was not filled!"); + break; + } + TProfile2D *h = 0x0; + if(!(h = (TProfile2D *)fContainer->FindObject("PRF2d"))) break; + h->Draw("lego"); + return kTRUE; + } + case kPH2DVector:{ + if(!fVector2d) { + AliInfo("vector was not filled!"); + break; + } + AliTRDCalibraVector *v = 0x0; + TGraphErrors *vdet = 0x0; + if(!(v = (AliTRDCalibraVector *)fContainer->FindObject("AliTRDCalibraVector"))) break; + Int_t detectormax = -1; + Int_t groupmax = -1; + if(!v->FindTheMaxEntries(1,detectormax,groupmax)) break; + if(!(vdet = v->ConvertVectorPHTGraphErrors((Int_t)detectormax,groupmax,"plotPH2dVector"))) break; + Int_t nbeentries = 0; + TH1F *ko = v->CorrectTheError(vdet,nbeentries); + ko->Draw(); + AliInfo(Form("There are %d entries in the detector %d and group %d",nbeentries,detectormax,groupmax)); + return kTRUE; + } +case kCH2DVector:{ + if(!fVector2d) { + AliInfo("vector was not filled!"); + break; + } + AliTRDCalibraVector *v = 0x0; + TH1F *vdet = 0x0; + if(!(v = (AliTRDCalibraVector *)fContainer->FindObject("AliTRDCalibraVector"))) break; + Int_t detectormax = -1; + Int_t groupmax = -1; + if(!v->FindTheMaxEntries(0,detectormax,groupmax)) break; + if(!(vdet = v->ConvertVectorCHHisto((Int_t)detectormax,groupmax,"plotCH2dVector"))) break; + vdet->Draw(); + AliInfo(Form("The detectormax and groupmax are %d and %d",detectormax,groupmax)); + return kTRUE; + } + case kPRF2DVector:{ + if(!fVector2d) { + AliInfo("vector was not filled!"); + break; + } + AliTRDCalibraVector *v = 0x0; + TGraphErrors *vdet = 0x0; + if(!(v = (AliTRDCalibraVector *)fContainer->FindObject("AliTRDCalibraVector"))) break; + Int_t detectormax = -1; + Int_t groupmax = -1; + Int_t nbeentries = 0; + if(!v->FindTheMaxEntries(2,detectormax,groupmax)) break; + if(!(vdet = v->ConvertVectorPRFTGraphErrors((Int_t)detectormax,groupmax,"plotPRF2dVector"))) break; + TH1F *ko = v->CorrectTheError(vdet,nbeentries); + ko->Draw(); + AliInfo(Form("The detectormax and groupmax are %d and %d",detectormax,groupmax)); + return kTRUE; + } + case kLinearFitter:{ + if(!fVdriftLinear) { + AliInfo("vdrift linear was not filled!"); + break; + } + AliTRDCalibraVdriftLinearFit *h = 0x0; + TH2S *hdetector = 0x0; + if(!(h = (AliTRDCalibraVdriftLinearFit *)fContainer->FindObject("AliTRDCalibraVdriftLinearFit"))) break; + Double_t entries[540]; + for(Int_t k = 0; k < 540; k++){ + entries[k] = 0.0; + hdetector = 0x0; + if(!(hdetector = (TH2S *)h->GetLinearFitterHisto(k,kFALSE))) continue; + entries[k] = hdetector->GetEntries(); + } + Double_t max = -10.0; + Double_t detectormax = -1; + for(Int_t k = 0; k < 540; k++){ + if(entries[k] > max) { + max = entries[k]; + detectormax = k; + } + } + hdetector = 0x0; + if((TMath::Abs(max) <= 0.001) || (detectormax <0.0) || (detectormax >=540.0)) break; + if(!(hdetector = (TH2S *)h->GetLinearFitterHisto((Int_t)detectormax,kFALSE))) break; + AliInfo(Form("The detector with the maximum of entries is %d",detectormax)); + hdetector->Draw(); + return kTRUE; + } + case kGainFactor:{ + if(!fPostProcess){ + if(!PostProcess()) break; + } + TGraph *fgain = (TGraph *) fGraph->At(0); + if(!fgain) break; + fgain->Draw("ALP"); + return kTRUE; + } + case kVdriftT0Factor:{ + if(!fPostProcess){ + if(!PostProcess()) break; + } + TCanvas *c = new TCanvas("c","c",10,10,510,510); + c->Divide(2,1); + TGraph *fvd = (TGraph *) fGraph->At(1); + if(fvd){ + c->cd(1); + fvd->Draw("ALP"); + } + TGraph *ft0 = (TGraph *) fGraph->At(2); + if(ft0){ + c->cd(2); + ft0->Draw("ALP"); + } + return kTRUE; + } + case kVdriftLorentzAngleFactor:{ + if(!fVdriftLinear) { + AliInfo("vdrift linear was not filled!"); + break; + } + if(!fPostProcess){ + if(!PostProcess()) break; + } + TCanvas *c = new TCanvas("c","c",10,10,510,510); + c->Divide(2,1); + TGraph *fvdl = (TGraph *) fGraph->At(3); + if(fvdl){ + c->cd(1); + fvdl->Draw("ALP"); + } + TGraph *flal = (TGraph *) fGraph->At(4); + if(flal){ + c->cd(2); + flal->Draw("ALP"); + } + return kTRUE; + } + case kPRFFactor:{ + if(!fPostProcess){ + if(!PostProcess()) break; + } + TGraph *fprf = (TGraph *) fGraph->At(5); + if(!fprf) break; + fprf->Draw("ALP"); + return kTRUE; + } + } + + return kFALSE; + +} +//________________________________________________________________________ +Bool_t AliTRDcalibration::PostProcess() +{ + // + // Fit the filled histos + // + + if(!fGraph){ + fGraph = new TObjArray(6); + fGraph->SetOwner(); + } + else { + delete fGraph; + PostProcess(); + } + + Bool_t storage[3] = {kFALSE,kFALSE,kFALSE}; + + // storage element + AliCDBManager *man = AliCDBManager::Instance(); + man->SetDefaultStorage("local://$ALICE_ROOT"); + AliCDBStorage* storLoc = man->GetStorage(fkNameDirectory); + if (!storLoc) + return kFALSE; + man->SetRun(fRunNumber); + + // MetaData + AliCDBMetaData mdDet; + mdDet.SetObjectClassName("AliTRDCalDet"); + AliCDBMetaData mdPad; + mdPad.SetObjectClassName("AliTRDCalPad"); + + // Objects for fitting + AliTRDCalibraFit *calibra = AliTRDCalibraFit::Instance(); + calibra->SetDebugLevel(2); // 0 rien, 1 fitvoir, 2 debug files, 3 one detector + + // Take the stuff + if (!fContainer) { + Printf("ERROR: list not available"); + return kFALSE; + } + + if(fHisto2d && fVector2d) AliInfo("We will only look at histos. Set fHisto2d off if you don't want"); + AliTRDCalibraVector *calibraVector = 0x0; + if(fVector2d) calibraVector = (AliTRDCalibraVector *) fContainer->FindObject("CalibraVector"); + // + // GAIN TH2I + // + Bool_t pass = kFALSE; + AliTRDCalibraVector *vvect = 0x0; + if(fHisto2d) { + TH2I *histogain = (TH2I *) fContainer->FindObject("CH2d"); + if(histogain) { + histogain->SetDirectory(0); + calibra->SetMinEntries(20); + if(fCompressPerDetector){ + if(AddStatsPerDetector(histogain)) pass = calibra->AnalyseCH(fCHSum); + } + else pass = calibra->AnalyseCH(histogain); + } + } + else { + if(fVector2d && calibraVector) { + calibra->SetMinEntries(20); + if(fCompressPerDetector){ + if(!(vvect = calibraVector->AddStatsPerDetectorCH())) return kFALSE; + pass = calibra->AnalyseCH(vvect); + } + else pass = calibra->AnalyseCH(calibraVector); + } + } + + if(pass) + { + Int_t nbtg = 6*4*18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb0(0)) + + 6* 18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb2(0)); + Int_t nbfit = calibra->GetNumberFit(); //Number of fits + Int_t nbE = calibra->GetNumberEnt(); //Number of detector mit entries + // enough statistics + if ((nbtg > 0) && + (nbfit >= 0.001*nbE)) + { + // create the cal objects + calibra->PutMeanValueOtherVectorFit(1,kTRUE); + TObjArray object = calibra->GetVectorFit(); + AliTRDCalDet *objgaindet = calibra->CreateDetObjectGain(&object); + TObject *objgainpad = calibra->CreatePadObjectGain(); + // store + AliCDBId id1("TRD/Calib/ChamberGainFactor",fRunNumber, AliCDBRunRange::Infinity()); + storLoc->Put((TObject *)objgaindet, id1, &mdDet); + AliCDBId id2("TRD/Calib/LocalGainFactor",fRunNumber, AliCDBRunRange::Infinity()); + storLoc->Put((TObject *)objgainpad, id2, &mdPad); + storage[0] = kTRUE; + // Make graph + TGraph *graph = 0x0; + if(FillGraphIndex(&object,graph)){ + fGraph->AddAt(graph,0); + } + }//if(enough statistics?) + calibra->ResetVectorFit(); + } + else return kFALSE; + + // + // VDRIFT average pulse height + // + pass = kFALSE; + if(fHisto2d) { + TProfile2D *histodriftvelocity = (TProfile2D *) fContainer->FindObject("PH2d"); + if(histodriftvelocity) { + histodriftvelocity->SetDirectory(0); + calibra->SetMinEntries(20*20); + if(fCompressPerDetector){ + if(AddStatsPerDetector(histodriftvelocity,1)) { + pass = calibra->AnalysePH(fDetSumVector); + } + } + else pass = calibra->AnalysePH(histodriftvelocity); + } + } + else { + if(fVector2d && calibraVector) { + calibra->SetMinEntries(20*20); + if(fCompressPerDetector){ + if(!(vvect = calibraVector->AddStatsPerDetectorPH())) return kFALSE; + pass = calibra->AnalysePH(vvect); + } + else pass = calibra->AnalysePH(calibraVector); + } + } + + if(pass) { + Int_t nbtg = 6*4*18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb0(1)) + + 6* 18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb2(1)); + Int_t nbfit = calibra->GetNumberFit(); + Int_t nbE = calibra->GetNumberEnt(); + // enough statistics + if ((nbtg > 0) && + (nbfit >= 0.001*nbE)) + { + // create the cal objects + calibra->PutMeanValueOtherVectorFit(1,kTRUE); + calibra->PutMeanValueOtherVectorFit2(1,kTRUE); + TObjArray object = calibra->GetVectorFit(); + AliTRDCalDet *objdriftvelocitydet = calibra->CreateDetObjectVdrift(&object,kTRUE); + TObject *objdriftvelocitypad = calibra->CreatePadObjectVdrift(); + TObjArray objectt = calibra->GetVectorFit2(); + AliTRDCalDet *objtime0det = calibra->CreateDetObjectT0(&object,kTRUE); + TObject *objtime0pad = calibra->CreatePadObjectT0(); + // store + AliCDBId id1("TRD/Calib/ChamberVdrift",fRunNumber, AliCDBRunRange::Infinity()); + storLoc->Put((TObject *)objdriftvelocitydet, id1, &mdDet); + AliCDBId id2("TRD/Calib/LocalVdrift",fRunNumber, AliCDBRunRange::Infinity()); + storLoc->Put((TObject *)objdriftvelocitypad, id2, &mdPad); + // + AliCDBId idd1("TRD/Calib/ChamberT0",fRunNumber, AliCDBRunRange::Infinity()); + storLoc->Put((TObject *)objtime0det, idd1, &mdDet); + AliCDBId idd2("TRD/Calib/LocalT0",fRunNumber, AliCDBRunRange::Infinity()); + storLoc->Put((TObject *)objtime0pad, idd2, &mdPad); + // Make graph + TGraph *graph = 0x0; + if(FillGraphIndex(&object,graph)){ + fGraph->AddAt(graph,1); + } + TGraph *graphh = 0x0; + if(FillGraphIndex(&objectt,graphh)){ + fGraph->AddAt(graphh,2); + } + }//if(enough statistics) + calibra->ResetVectorFit(); + } + else return kFALSE; + + // + // PRF + // + pass = kFALSE; + if(fHisto2d) { + TProfile2D *histoprf = (TProfile2D *) fContainer->FindObject("PRF2d"); + if (histoprf) { + histoprf->SetDirectory(0); + calibra->SetMinEntries(600); + if(fCompressPerDetector){ + if(AddStatsPerDetector(histoprf,2)) pass = calibra->AnalysePRFMarianFit(fDetSumVector); + } + else pass = calibra->AnalysePRFMarianFit(histoprf); + } + } + else { + if(fVector2d && calibraVector) { + calibra->SetMinEntries(600); + if(fCompressPerDetector){ + if(!(vvect =calibraVector->AddStatsPerDetectorPRF())) return kFALSE; + pass = calibra->AnalysePRFMarianFit(vvect); + } + else pass = calibra->AnalysePRFMarianFit(calibraVector); + } + } + + if(pass){ + Int_t nbtg = 6*4*18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb0(2)) + + 6* 18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb2(2)); + Int_t nbfit = calibra->GetNumberFit(); + Int_t nbE = calibra->GetNumberEnt(); + // enough statistics + if ((nbtg > 0) && + (nbfit >= 0.001*nbE)) { + TObjArray object = calibra->GetVectorFit(); + TObject *objPRFpad = calibra->CreatePadObjectPRF(&object); + // store + AliCDBId id2("TRD/Calib/PRFWidth",fRunNumber, AliCDBRunRange::Infinity()); + storLoc->Put((TObject *)objPRFpad, id2, &mdPad); + // Make graph + TGraph *graph = 0x0; + if(FillGraphIndex(&object,graph)){ + fGraph->AddAt(graph,5); + } + } + calibra->ResetVectorFit(); + } + else return kFALSE; + + // + // VDRIFT linear fit + // + AliTRDCalibraVdriftLinearFit *vlinearfit = (AliTRDCalibraVdriftLinearFit *) fContainer->FindObject("LinearVdriftFit"); + if (vlinearfit) { + calibra->SetMinEntries(20*20); + if(calibra->AnalyseLinearFitters(vlinearfit)) { + + Int_t nbtg = 6*4*18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb0(2)) + + 6* 18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb2(2)); + Int_t nbfit = calibra->GetNumberFit(); + Int_t nbE = calibra->GetNumberEnt(); + // enough statistics + if ((nbtg > 0) && + (nbfit >= 0.001*nbE)) + { + // create the cal objects + calibra->PutMeanValueOtherVectorFit(1,kTRUE); + calibra->PutMeanValueOtherVectorFit2(1,kTRUE); + TObjArray object = calibra->GetVectorFit(); + AliTRDCalDet *objdriftvelocitydet = calibra->CreateDetObjectVdrift(&object,kTRUE); + TObject *objdriftvelocitypad = calibra->CreatePadObjectVdrift(); + TObjArray objectt = calibra->GetVectorFit2(); + AliTRDCalDet *objtime0det = calibra->CreateDetObjectT0(&object,kTRUE); + TObject *objtime0pad = calibra->CreatePadObjectT0(); + // store dummy + AliCDBId id1("TRD/Calib/ChamberVdriftLinear",fRunNumber, AliCDBRunRange::Infinity()); + storLoc->Put((TObject *)objdriftvelocitydet, id1, &mdDet); + AliCDBId id2("TRD/Calib/LocalVdriftLinear",fRunNumber, AliCDBRunRange::Infinity()); + storLoc->Put((TObject *)objdriftvelocitypad, id2, &mdPad); + // + AliCDBId idd1("TRD/Calib/ChamberLorentzAngle",fRunNumber, AliCDBRunRange::Infinity()); + storLoc->Put((TObject *)objtime0det, idd1, &mdDet); + AliCDBId idd2("TRD/Calib/LocalLorentzAngle",fRunNumber, AliCDBRunRange::Infinity()); + storLoc->Put((TObject *)objtime0pad, idd2, &mdPad); + // Make graph + TGraph *graph = 0x0; + if(FillGraphIndex(&object,graph)){ + fGraph->AddAt(graph,3); + } + TGraph *graphh = 0x0; + if(FillGraphIndex(&objectt,graphh)){ + fGraph->AddAt(graphh,4); + } + }//if(enough statistics) + }// if fit + calibra->ResetVectorFit(); + } + else return kFALSE; + + fPostProcess = kTRUE; + + return kTRUE; + +} + +//________________________________________________________________________ +Bool_t AliTRDcalibration::FillGraphIndex(const TObjArray *vectora,TGraph *graph) const +{ + // + // Fill one value (the first one) per detector + // + + Int_t loop = (Int_t) vectora->GetEntriesFast(); + if(loop != 540) { + AliInfo("The Vector Fit is not complete!"); + return kFALSE; + } + + Double_t x[540]; + Double_t y[540]; + for (Int_t k = 0; k < loop; k++) { + if(!vectora->At(k)){ + x[k] = -1.0; + y[k] = -1.0; + continue; + } + x[k] = ((AliTRDCalibraFit::AliTRDFitInfo *) vectora->At(k))->GetDetector(); + y[k] = ((Float_t *)((AliTRDCalibraFit::AliTRDFitInfo *) vectora->At(k))->GetCoef())[0]; + } + + if(!graph) graph = new TGraph(540,&x[0],&y[0]); + else{ + graph->~TGraph(); + new(graph) TGraph(540,&x[0],&y[0]); + } + + return kTRUE; + +} +//________________________________________________________________________ +Bool_t AliTRDcalibration::AddStatsPerDetector(const TH2I *ch) +{ + // + // Add statistic per detector + // + + AliTRDCalibraMode calibMode = AliTRDCalibraMode(); + const char *name = ch->GetTitle(); + if(!SetNzFromTObject(name,0,&calibMode)) return 0x0; + if(!SetNrphiFromTObject(name,0,&calibMode)) return 0x0; + if(((calibMode.GetNz(0) == 100) && (calibMode.GetNrphi(0) == 100)) || ((calibMode.GetNz(0) == 10) && (calibMode.GetNrphi(0) == 10))) return kFALSE; + + Int_t nybins = ch->GetNbinsY();// groups number + Int_t nxbins = ch->GetNbinsX();// number of bins X + TAxis *xaxis = ch->GetXaxis(); + Double_t lowedge = xaxis->GetBinLowEdge(1); + Double_t upedge = xaxis->GetBinUpEdge(nxbins); + + // number per chamber 2 + calibMode.ModePadCalibration(2,0); + calibMode.ModePadFragmentation(0,2,0,0); + calibMode.SetDetChamb2(0); + Int_t perChamber2 = (Int_t) calibMode.GetDetChamb2(0); + + // number per other chamber + calibMode.ModePadCalibration(0,0); + calibMode.ModePadFragmentation(0,0,0,0); + calibMode.SetDetChamb0(0); + Int_t perChamber0 = (Int_t) calibMode.GetDetChamb0(0); + + if(nybins != (6*18*perChamber2+6*4*18*perChamber0)) return kFALSE; + + // Create Histo + TString nname((const char *)ch->GetName()); + nname += "PerDetector"; + TString title("Nz"); + title += 0; + title += "Nrphi"; + title += 0; + if(!fCHSum) fCHSum = new TH2I((const char *)nname,(const char *)title + ,nxbins,lowedge,upedge,540,0,540); + else{ + fCHSum->~TH2I(); + new(fCHSum) TH2I((const Char_t *) nname,(const char *)title + ,nxbins,lowedge,upedge,540,0,540); + } + fCHSum->SetYTitle("Detector number"); + fCHSum->SetXTitle("charge deposit [a.u]"); + fCHSum->SetZTitle("counts"); + fCHSum->SetStats(0); + fCHSum->Sumw2(); + + Int_t counter = 0; + + for(Int_t det = 0; det < 540; det++){ + + Int_t numberofgroup = 0; + if(AliTRDgeometry::GetStack(det) == 2) numberofgroup = perChamber2; + else numberofgroup = perChamber0; + TH1I *projch = (TH1I *) ch->ProjectionX("projch",counter+1,counter+numberofgroup,(Option_t *)"e"); + projch->SetDirectory(0); + + for(Int_t nx = 0; nx <= nxbins; nx++) { + fCHSum->SetBinContent(nx,det+1,projch->GetBinContent(nx)); + fCHSum->SetBinError(nx,det+1,projch->GetBinError(nx)); + } + + counter += numberofgroup; + + delete projch; + + } + + return kTRUE; + +} +//_____________________________________________________________________________________________________________________ +Bool_t AliTRDcalibration::AddStatsPerDetector(const TProfile2D *ph,Int_t i) +{ + // + // Add statistic per detector + // + + AliTRDCalibraMode calibMode = AliTRDCalibraMode(); + const char *name = ph->GetTitle(); + //printf("name %s\n",name); + if(!SetNzFromTObject(name,0,&calibMode)) return kFALSE; + if(!SetNrphiFromTObject(name,0,&calibMode)) return kFALSE; + if(((calibMode.GetNz(0) == 100) && (calibMode.GetNrphi(0) == 100)) || ((calibMode.GetNz(0) == 10) && (calibMode.GetNrphi(0) == 10))) return kFALSE; + //printf("Found mode Mz %d, Nrphi %d\n",calibMode.GetNz(0),calibMode.GetNrphi(0)); + + + Int_t nybins = ph->GetNbinsY();// groups number + Int_t nxbins = ph->GetNbinsX();// number of bins X + TAxis *xaxis = ph->GetXaxis(); + Double_t lowedge = xaxis->GetBinLowEdge(1); + Double_t upedge = xaxis->GetBinUpEdge(nxbins); + + // number per chamber 2 + calibMode.ModePadCalibration(2,0); + calibMode.ModePadFragmentation(0,2,0,0); + calibMode.SetDetChamb2(0); + Int_t perChamber2 = (Int_t) calibMode.GetDetChamb2(0); + + // number per other chamber + calibMode.ModePadCalibration(0,0); + calibMode.ModePadFragmentation(0,0,0,0); + calibMode.SetDetChamb0(0); + Int_t perChamber0 = (Int_t) calibMode.GetDetChamb0(0); + + if(nybins != (6*18*perChamber2+6*4*18*perChamber0)) return kFALSE; + + // Create calvector + TString nbname((const char *)ph->GetName()); + nbname += "PerDetectorVector"; + if(!fDetSumVector) fDetSumVector = new AliTRDCalibraVector(); + else{ + fDetSumVector->~AliTRDCalibraVector(); + new(fDetSumVector) AliTRDCalibraVector(); + } + if(i==1){ + fDetSumVector->SetTimeMax(nxbins); + } + if(i==2){ + fDetSumVector->SetNumberBinPRF(nxbins); + fDetSumVector->SetPRFRange(TMath::Abs(lowedge)); + } + fDetSumVector->SetDetCha0(i,1); + fDetSumVector->SetDetCha2(i,1); + fDetSumVector->SetNzNrphi(i,0,0); + if(i==2) { + Int_t nbg = GetNumberOfGroupsPRF((const char *)name); + fDetSumVector->SetNbGroupPRF(nbg); + } + + // Create Histo + TString nname((const char *)ph->GetName()); + nname += "PerDetector"; + TString title("Nz"); + title += 0; + title += "Nrphi"; + title += 0; + if(!fDetSum) fDetSum = new TH2D((const char *)nname,(const Char_t *) title + ,nxbins,lowedge,upedge,540,0,540); + else{ + fDetSum->~TH2D(); + new(fDetSum) TH2D((const Char_t *) nname,(const Char_t *) title + ,nxbins,lowedge,upedge,540,0,540); + } + fDetSum->SetYTitle("Detector number"); + fDetSum->SetXTitle(xaxis->GetTitle()); + fDetSum->SetStats(0); + + Int_t counter = 0; + + for(Int_t det = 0; det < 540; det++){ + + Int_t numberofgroup = 0; + if(AliTRDgeometry::GetStack(det) == 2) numberofgroup = perChamber2; + else numberofgroup = perChamber0; + + for(Int_t nx = 1; nx <= nxbins; nx++) { + + Double_t entries = 0.0; + Double_t sumw2 = 0.0; + Double_t sumw = 0.0; + + for(Int_t k = counter+1; k <= (counter+numberofgroup); k++){ + Int_t binnumber = ph->GetBin(nx,k); + entries += ph->GetBinEntries(binnumber); + sumw2 += (ph->GetBinError(binnumber)*ph->GetBinError(binnumber)+ph->GetBinContent(binnumber)*ph->GetBinContent(binnumber))*ph->GetBinEntries(binnumber); + sumw += ph->GetBinContent(binnumber)*ph->GetBinEntries(binnumber); + } + + Double_t mean = 0.0; + if(entries > 0.0) mean = sumw/entries; + Double_t squaremean = 0.0; + if(entries > 0.0) squaremean = sumw2/entries; + Double_t errorf = squaremean - mean*mean; + Double_t error = 0.0; + if(entries > 0.0) error = TMath::Sqrt(TMath::Abs(errorf)/entries); + + fDetSum->SetBinContent(nx,det+1,mean); + fDetSum->SetBinError(nx,det+1,error); + + if(i==1) fDetSumVector->FillVectorPH(det,0,nx-1,(Int_t)entries,(Float_t)mean,(Float_t)squaremean); + if(i==2) fDetSumVector->FillVectorPRF(det,0,nx-1,(Int_t)entries,(Float_t)mean,(Float_t)squaremean); + + } + + counter += numberofgroup; + + } + + return kTRUE; + + +} +//_____________________________________________________________________________ +Bool_t AliTRDcalibration::SetNrphiFromTObject(const char *name, Int_t i, AliTRDCalibraMode *calibMode) const +{ + // + // Set the granularity from object + // + + const Char_t *patternrphi0 = "Nrphi0"; + const Char_t *patternrphi1 = "Nrphi1"; + const Char_t *patternrphi2 = "Nrphi2"; + const Char_t *patternrphi3 = "Nrphi3"; + const Char_t *patternrphi4 = "Nrphi4"; + const Char_t *patternrphi5 = "Nrphi5"; + const Char_t *patternrphi6 = "Nrphi6"; + + + const Char_t *patternrphi10 = "Nrphi10"; + const Char_t *patternrphi100 = "Nrphi100"; + const Char_t *patternz10 = "Nz10"; + const Char_t *patternz100 = "Nz100"; + + // Nrphi mode + if ((strstr(name,patternrphi100)) && (strstr(name,patternz100))) { + calibMode->SetAllTogether(i); + return kTRUE; + } + if ((strstr(name,patternrphi10)) && (strstr(name,patternz10))) { + calibMode->SetPerSuperModule(i); + return kTRUE; + } + + if (strstr(name,patternrphi0)) { + calibMode->SetNrphi(i ,0); + return kTRUE; + } + if (strstr(name,patternrphi1)) { + calibMode->SetNrphi(i, 1); + return kTRUE; + } + if (strstr(name,patternrphi2)) { + calibMode->SetNrphi(i, 2); + return kTRUE; + } + if (strstr(name,patternrphi3)) { + calibMode->SetNrphi(i, 3); + return kTRUE; + } + if (strstr(name,patternrphi4)) { + calibMode->SetNrphi(i, 4); + return kTRUE; + } + if (strstr(name,patternrphi5)) { + calibMode->SetNrphi(i, 5); + return kTRUE; + } + if (strstr(name,patternrphi6)) { + calibMode->SetNrphi(i, 6); + return kTRUE; + } + + calibMode->SetNrphi(i ,0); + return kFALSE; + +} +//_____________________________________________________________________________ +Bool_t AliTRDcalibration::SetNzFromTObject(const char *name, Int_t i, AliTRDCalibraMode *calibMode) const +{ + // + // Set fNz[i] of the AliTRDCalibraFit::Instance() + // corresponding to the given TObject + // + + // Some patterns + const Char_t *patternz0 = "Nz0"; + const Char_t *patternz1 = "Nz1"; + const Char_t *patternz2 = "Nz2"; + const Char_t *patternz3 = "Nz3"; + const Char_t *patternz4 = "Nz4"; + + const Char_t *patternrphi10 = "Nrphi10"; + const Char_t *patternrphi100 = "Nrphi100"; + const Char_t *patternz10 = "Nz10"; + const Char_t *patternz100 = "Nz100"; + + if ((strstr(name,patternrphi100)) && (strstr(name,patternz100))) { + calibMode->SetAllTogether(i); + return kTRUE; + } + if ((strstr(name,patternrphi10)) && (strstr(name,patternz10))) { + calibMode->SetPerSuperModule(i); + return kTRUE; + } + if (strstr(name,patternz0)) { + calibMode->SetNz(i, 0); + return kTRUE; + } + if (strstr(name,patternz1)) { + calibMode->SetNz(i ,1); + return kTRUE; + } + if (strstr(name,patternz2)) { + calibMode->SetNz(i ,2); + return kTRUE; + } + if (strstr(name,patternz3)) { + calibMode->SetNz(i ,3); + return kTRUE; + } + if (strstr(name,patternz4)) { + calibMode->SetNz(i ,4); + return kTRUE; + } + + calibMode->SetNz(i ,0); + return kFALSE; +} +//____________________________________________________________________________________________________ +Int_t AliTRDcalibration::GetNumberOfGroupsPRF(const char* nametitle) const +{ + // + // Get numberofgroupsprf + // + + // Some patterns + const Char_t *pattern0 = "Ngp0"; + const Char_t *pattern1 = "Ngp1"; + const Char_t *pattern2 = "Ngp2"; + const Char_t *pattern3 = "Ngp3"; + const Char_t *pattern4 = "Ngp4"; + const Char_t *pattern5 = "Ngp5"; + const Char_t *pattern6 = "Ngp6"; + + // Nrphi mode + if (strstr(nametitle,pattern0)) { + return 0; + } + if (strstr(nametitle,pattern1)) { + return 1; + } + if (strstr(nametitle,pattern2)) { + return 2; + } + if (strstr(nametitle,pattern3)) { + return 3; + } + if (strstr(nametitle,pattern4)) { + return 4; + } + if (strstr(nametitle,pattern5)) { + return 5; + } + if (strstr(nametitle,pattern6)){ + return 6; + } + else return -1; + + +} diff --git a/PWG1/TRD/AliTRDcalibration.h b/PWG1/TRD/AliTRDcalibration.h new file mode 100644 index 00000000000..0c24a2ce92b --- /dev/null +++ b/PWG1/TRD/AliTRDcalibration.h @@ -0,0 +1,151 @@ +#ifndef ALITRDCALIBRATION_H +#define ALITRDCALIBRATION_H + +// macro for extremely simple analysis + +/////////////////////////////////////////////////////////////////////////////// +// // +// TRD calibration class // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include "AliTRDrecoTask.h" + +class TList; +class TObject; +class TH1F; +class TProfile2D; +class TGraph; +class TH2I; +class TH2D; +class TTree; +class TObjArray; +class AliTRDtrackV1; +class AliTRDCalibraFillHisto; +class AliTRDCalibraVector; +class AliTRDCalibraMode; +class AliTRDcluster; +class AliTRDtrackInfo; + +class AliTRDcalibration : public AliTRDrecoTask +{ + +public: + + // Plots registered for this task + enum{ + kNbTrack = 0 // Nb tracks per event + ,kNbTracklet = 1 // Nb of traklets per detector + ,kNbTimeBin = 2 // Nb of clusters per timebin + ,kNbClusters = 3 // Nb of clusters per tracklet + ,kPHSum = 4 // All integrated PH + ,kCHSum = 5 // All integrated CH + ,kPH2D = 6 // PH2D + ,kCH2D = 7 // CH2D + ,kPRF2D = 8 // PRF2D + ,kPH2DVector = 9 // PH2D + ,kCH2DVector = 10 // CH2D + ,kPRF2DVector = 11 // PRF2D + ,kLinearFitter = 12 // For the one with the most stats + ,kGainFactor = 13 // Gain factor + ,kVdriftT0Factor = 14 // VdriftT0 average pulse height + ,kVdriftLorentzAngleFactor = 15 // VdriftLorentzAngle + ,kPRFFactor = 16 //PRF Factor + }; + + + AliTRDcalibration(); + virtual ~AliTRDcalibration(); + + virtual void CreateOutputObjects(); + virtual void Exec(Option_t *option); + virtual void Terminate(Option_t *); + virtual Bool_t GetRefFigure(Int_t ifig); + virtual Bool_t PostProcess(); + + Bool_t FillGraphIndex(const TObjArray *vectora, TGraph *graph) const; + Bool_t AddStatsPerDetector(const TH2I *ch); + Bool_t AddStatsPerDetector(const TProfile2D *ph, Int_t i); + + Bool_t SetNrphiFromTObject(const char *name, Int_t i, AliTRDCalibraMode *calibMode) const; + Bool_t SetNzFromTObject(const char *name, Int_t i, AliTRDCalibraMode *calibMode) const; + + Int_t GetNumberOfGroupsPRF(const char* nametitle) const; + TH2I *GetSumCH() const { return fCHSum; }; + TH2D *GetSumDet() const { return fDetSum;}; + AliTRDCalibraVector *GetSumDetVector() const { return fDetSumVector;}; + + + + void SetHisto2d(Bool_t histo2d) {fHisto2d=histo2d;}; + void SetVector2d(Bool_t vector2d) {fVector2d=vector2d;}; + void SetVdriftLinear(Bool_t vdriftLinear) {fVdriftLinear = vdriftLinear;}; + void SetLow(Int_t low) {flow=low;}; + void SetHigh(Int_t high) {fhigh=high;}; + void SetNz(Short_t nz, Int_t i) {fNz[i]=nz;}; + void SetNrphi(Short_t nrphi, Int_t i) {fNrphi[i]=nrphi;}; + void SetFillZero(Bool_t fillZero) {ffillZero = fillZero;}; + void SetNormalizeNbOfCluster(Bool_t normalizeNbOfCluster) {fnormalizeNbOfCluster = normalizeNbOfCluster;}; + void SetMaxCluster(Float_t maxcluster) {fmaxCluster = maxcluster; }; + void SetOfflineTracks() {fOfflineTracks=kTRUE; fStandaloneTracks=kFALSE; }; + void SetStandaloneTracks() {fStandaloneTracks=kTRUE; fOfflineTracks=kFALSE; }; + void SetCompressPerDetector(Bool_t compressPerDetector=kTRUE) {fCompressPerDetector=compressPerDetector; }; + void SetRunNumber(Int_t runNumber) {fRunNumber=runNumber; }; + void SetNameDirectoryOutput(const char *nameDirectory) {fkNameDirectory=nameDirectory; }; + +private: + AliTRDtrackInfo *fTrackInfo; //track info + + AliTRDtrackV1 *ftrdTrack; //trdtrack + AliTRDcluster *fcl; //cluster + + AliTRDCalibraFillHisto *fTRDCalibraFillHisto; //! calibration analyse object + TH1F *fNbTRDTrack; //! nb ESD tracks used + TH1F *fNbTRDTrackOffline; //! nb ESD tracks offline used + TH1F *fNbTRDTrackStandalone; //! nb ESD tracks standalone used + TH1F *fNbTRDTracklet; //! nb tracklets used + TH1F *fNbTRDTrackletOffline; //! nb tracklets offline used + TH1F *fNbTRDTrackletStandalone; //! nb tracklets standalone used + TH1F *fNbTimeBin; //! nb Time Bin + TH1F *fNbTimeBinOffline; //! nb Time Bin offline + TH1F *fNbTimeBinStandalone; //! nb Time Bin standalone + TH1F *fNbClusters; //! nb Clusters + TH1F *fNbClustersOffline; //! nb Clusters offline + TH1F *fNbClustersStandalone; //! nb Clusters standalone + + + TProfile2D *fPHSum; //! sum PH + TH2I *fCHSum; //! sum CH + TH2D *fDetSum; //! sum Det + AliTRDCalibraVector *fDetSumVector; //! sum Det Vect + + Bool_t fHisto2d; //! histo + Bool_t fVector2d; //! vector + Bool_t fVdriftLinear; //! vdrift Linear + + Int_t flow; //! lower limit nb of clusters + Int_t fhigh; //! higher limit nb of clusters + Int_t fNbTimeBins; //! number of timebins + Bool_t ffillZero; //! fill zero + Short_t fNz[3]; //! Nz mode + Short_t fNrphi[3]; //! Nrphi mode + Bool_t fnormalizeNbOfCluster; //! normalize with number of clusters + Float_t fmaxCluster; //! maxcluster (noise at the end) + Bool_t fOfflineTracks; //! Offline refited tracks + Bool_t fStandaloneTracks; //! Take only standalone tracks + + Bool_t fCompressPerDetector; //! Compress per detector + + Int_t fRunNumber; //! Run number + const char *fkNameDirectory; //! Name output directory fit parameters + + TObjArray *fGraph; //! array of graphs filled in PostProcess + Bool_t fPostProcess; //Post process + + AliTRDcalibration(const AliTRDcalibration&); + AliTRDcalibration& operator=(const AliTRDcalibration&); + + ClassDef(AliTRDcalibration, 1) // calibration task +}; +#endif + diff --git a/PWG1/TRD/AliTRDcheckDET.cxx b/PWG1/TRD/AliTRDcheckDET.cxx new file mode 100644 index 00000000000..3b34d5dd960 --- /dev/null +++ b/PWG1/TRD/AliTRDcheckDET.cxx @@ -0,0 +1,1210 @@ +//////////////////////////////////////////////////////////////////////////// +// // +// // +// Basic checks for tracking and detector performance // +// +// For the moment (15.10.2009) the following checks are implemented // +// - Number of clusters/track +// - Number of clusters/tracklet +// - Number of tracklets/track from different sources (Barrel, StandAlone) +// - Number of findable tracklets +// - Number of tracks per event and TRD sector +// - +// - Chi2 distribution for tracks +// - Charge distribution per cluster and tracklet +// - Number of events and tracks per trigger source +// - Trigger purity +// - Track and Tracklet propagation status +// +// Authors: // +// Anton Andronic // +// Alexandru Bercuci // +// Markus Fasel // +// // +//////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "AliLog.h" +#include "AliTRDcluster.h" +#include "AliESDHeader.h" +#include "AliESDRun.h" +#include "AliESDtrack.h" +#include "AliTRDgeometry.h" +#include "AliTRDpadPlane.h" +#include "AliTRDSimParam.h" +#include "AliTRDseedV1.h" +#include "AliTRDtrackV1.h" +#include "AliTRDtrackerV1.h" +#include "AliTRDReconstructor.h" +#include "AliTrackReference.h" +#include "AliTrackPointArray.h" +#include "AliTracker.h" +#include "TTreeStream.h" + +#include "info/AliTRDtrackInfo.h" +#include "info/AliTRDeventInfo.h" +#include "AliTRDcheckDET.h" + +#include +#include + +ClassImp(AliTRDcheckDET) + +//_______________________________________________________ +AliTRDcheckDET::AliTRDcheckDET(): + AliTRDrecoTask("checkDET", "Basic TRD data checker") + ,fEventInfo(0x0) + ,fTriggerNames(0x0) + ,fReconstructor(0x0) + ,fGeo(0x0) +{ + // + // Default constructor + // + DefineInput(1,AliTRDeventInfo::Class()); + fReconstructor = new AliTRDReconstructor; + fReconstructor->SetRecoParam(AliTRDrecoParam::GetLowFluxParam()); + fGeo = new AliTRDgeometry; + InitFunctorList(); +} + +//_______________________________________________________ +AliTRDcheckDET::~AliTRDcheckDET(){ + // + // Destructor + // + if(fTriggerNames) delete fTriggerNames; + delete fReconstructor; + delete fGeo; +} + +//_______________________________________________________ +void AliTRDcheckDET::ConnectInputData(Option_t *opt){ + // + // Connect the Input data with the task + // + AliTRDrecoTask::ConnectInputData(opt); + fEventInfo = dynamic_cast(GetInputData(1)); +} + +//_______________________________________________________ +void AliTRDcheckDET::CreateOutputObjects(){ + // + // Create Output Objects + // + OpenFile(0,"RECREATE"); + fContainer = Histos(); + if(!fTriggerNames) fTriggerNames = new TMap(); +} + +//_______________________________________________________ +void AliTRDcheckDET::Exec(Option_t *opt){ + // + // Execution function + // Filling TRD quality histos + // + if(!HasMCdata() && fEventInfo->GetEventHeader()->GetEventType() != 7) return; // For real data we select only physical events + AliTRDrecoTask::Exec(opt); + Int_t nTracks = 0; // Count the number of tracks per event + Int_t triggermask = fEventInfo->GetEventHeader()->GetTriggerMask(); + TString triggername = fEventInfo->GetRunInfo()->GetFiredTriggerClasses(triggermask); + AliDebug(6, Form("Trigger cluster: %d, Trigger class: %s\n", triggermask, triggername.Data())); + dynamic_cast(fContainer->UncheckedAt(kNeventsTrigger))->Fill(triggermask); + for(Int_t iti = 0; iti < fTracks->GetEntriesFast(); iti++){ + if(!fTracks->UncheckedAt(iti)) continue; + AliTRDtrackInfo *fTrackInfo = dynamic_cast(fTracks->UncheckedAt(iti)); + if(!fTrackInfo->GetTrack()) continue; + nTracks++; + } + if(nTracks){ + dynamic_cast(fContainer->UncheckedAt(kNeventsTriggerTracks))->Fill(triggermask); + dynamic_cast(fContainer->UncheckedAt(kNtracksEvent))->Fill(nTracks); + } + if(triggermask <= 20 && !fTriggerNames->FindObject(Form("%d", triggermask))){ + fTriggerNames->Add(new TObjString(Form("%d", triggermask)), new TObjString(triggername)); + // also set the label for both histograms + TH1 *histo = dynamic_cast(fContainer->UncheckedAt(kNeventsTriggerTracks)); + histo->GetXaxis()->SetBinLabel(histo->FindBin(triggermask), triggername); + histo = dynamic_cast(fContainer->UncheckedAt(kNeventsTrigger)); + histo->GetXaxis()->SetBinLabel(histo->FindBin(triggermask), triggername); + } + PostData(0, fContainer); +} + + +//_______________________________________________________ +Bool_t AliTRDcheckDET::PostProcess(){ + // + // Do Postprocessing (for the moment set the number of Reference histograms) + // + + TH1 * h = 0x0; + + // Calculate of the trigger clusters purity + h = dynamic_cast(fContainer->FindObject("hEventsTrigger")); + TH1F *h1 = dynamic_cast(fContainer->FindObject("hEventsTriggerTracks")); + h1->Divide(h); + Float_t purities[20], val = 0; + TString triggernames[20]; + Int_t nTriggerClasses = 0; + for(Int_t ibin = 1; ibin <= h->GetNbinsX(); ibin++){ + if((val = h1->GetBinContent(ibin))){ + purities[nTriggerClasses] = val; + triggernames[nTriggerClasses] = h1->GetXaxis()->GetBinLabel(ibin); + nTriggerClasses++; + } + } + h = dynamic_cast(fContainer->UncheckedAt(kTriggerPurity)); + TAxis *ax = h->GetXaxis(); + for(Int_t itrg = 0; itrg < nTriggerClasses; itrg++){ + h->Fill(itrg, purities[itrg]); + ax->SetBinLabel(itrg+1, triggernames[itrg].Data()); + } + ax->SetRangeUser(-0.5, nTriggerClasses+.5); + h->GetYaxis()->SetRangeUser(0,1); + + // track status + h=dynamic_cast(fContainer->At(kTrackStatus)); + Float_t ok = h->GetBinContent(1); + Int_t nerr = h->GetNbinsX(); + for(Int_t ierr=nerr; ierr--;){ + h->SetBinContent(ierr+1, 1.e2*h->GetBinContent(ierr+1)/ok); + } + h->SetBinContent(1, 0.); + + // tracklet status + TObjArray *arr = dynamic_cast(fContainer->UncheckedAt(kTrackletStatus)); + for(Int_t ily = AliTRDgeometry::kNlayer; ily--;){ + h=dynamic_cast(arr->At(ily)); + Float_t okB = h->GetBinContent(1); + Int_t nerrB = h->GetNbinsX(); + for(Int_t ierr=nerrB; ierr--;){ + h->SetBinContent(ierr+1, 1.e2*h->GetBinContent(ierr+1)/okB); + } + h->SetBinContent(1, 0.); + } + + fNRefFigures = 18; + + return kTRUE; +} + +//_______________________________________________________ +Bool_t AliTRDcheckDET::GetRefFigure(Int_t ifig){ + // + // Setting Reference Figures + // + gPad->SetLogy(0); + gPad->SetLogx(0); + TH1 *h = 0x0; TObjArray *arr=0x0; + TLegend *leg = 0x0; + Bool_t kFIRST(1); + switch(ifig){ + case kNclustersTrack: + (h=(TH1F*)fContainer->FindObject("hNcls"))->Draw("pl"); + PutTrendValue("NClustersTrack", h->GetMean()); + PutTrendValue("NClustersTrackRMS", h->GetRMS()); + return kTRUE; + case kNclustersTracklet: + (h =(TH1F*)fContainer->FindObject("hNclTls"))->Draw("pc"); + PutTrendValue("NClustersTracklet", h->GetMean()); + PutTrendValue("NClustersTrackletRMS", h->GetRMS()); + return kTRUE; + case kNtrackletsTrack: + h=MakePlotNTracklets(); + PutTrendValue("NTrackletsTrack", h->GetMean()); + PutTrendValue("NTrackletsTrackRMS", h->GetRMS()); + return kTRUE; + case kNtrackletsCross: + h = (TH1F*)fContainer->FindObject("hNtlsCross"); + if(!MakeBarPlot(h, kRed)) break; + PutTrendValue("NTrackletsCross", h->GetMean()); + PutTrendValue("NTrackletsCrossRMS", h->GetRMS()); + return kTRUE; + case kNtrackletsFindable: + h = (TH1F*)fContainer->FindObject("hNtlsFindable"); + if(!MakeBarPlot(h, kGreen)) break; + PutTrendValue("NTrackletsFindable", h->GetMean()); + PutTrendValue("NTrackletsFindableRMS", h->GetRMS()); + return kTRUE; + case kNtracksEvent: + (h = (TH1F*)fContainer->FindObject("hNtrks"))->Draw("pl"); + PutTrendValue("NTracksEvent", h->GetMean()); + PutTrendValue("NTracksEventRMS", h->GetRMS()); + return kTRUE; + case kNtracksSector: + h = (TH1F*)fContainer->FindObject("hNtrksSector"); + if(!MakeBarPlot(h, kGreen)) break; + PutTrendValue("NTracksSector", h->Integral()/h->GetNbinsX()); + return kTRUE; + case kTrackStatus: + if(!(h=(TH1F *)fContainer->FindObject("hTrackStatus"))) break; + h->GetXaxis()->SetRangeUser(0.5, -1); + h->GetYaxis()->CenterTitle(); + h->Draw("c"); + PutTrendValue("TrackStatus", h->Integral()); + gPad->SetLogy(0); + return kTRUE; + case kTrackletStatus: + if(!(arr = dynamic_cast(fContainer->At(kTrackletStatus)))) break; + leg = new TLegend(.68, .7, .98, .98); + leg->SetBorderSize(1);leg->SetFillColor(0); + leg->SetHeader("TRD layer"); + for(Int_t ily=0; ily(arr->At(ily)))) continue; + if(kFIRST){ + h->Draw("c"); + h->GetXaxis()->SetRangeUser(0.5, -1); + h->GetYaxis()->CenterTitle(); + kFIRST = kFALSE; + } else h->Draw("samec"); + leg->AddEntry(h, Form("%d", ily), "l"); + PutTrendValue(Form("TrackletStatus%d", ily), h->Integral()); + } + leg->Draw(); + gPad->SetLogy(0); + return kTRUE; + case kChi2: + MakePlotChi2(); + return kTRUE; + case kPH: + MakePlotPulseHeight(); + gPad->SetLogy(0); + return kTRUE; + case kChargeCluster: + (h = (TH1F*)fContainer->FindObject("hQcl"))->Draw("c"); + gPad->SetLogy(1); + PutTrendValue("ChargeCluster", h->GetMaximumBin()); + PutTrendValue("ChargeClusterRMS", h->GetRMS()); + return kTRUE; + case kChargeTracklet: + (h=(TH1F*)fContainer->FindObject("hQtrklt"))->Draw("c"); + PutTrendValue("ChargeTracklet", h->GetMaximumBin()); + PutTrendValue("ChargeTrackletRMS", h->GetRMS()); + return kTRUE; + case kNeventsTrigger: + ((TH1F*)fContainer->FindObject("hEventsTrigger"))->Draw(""); + return kTRUE; + case kNeventsTriggerTracks: + ((TH1F*)fContainer->FindObject("hEventsTriggerTracks"))->Draw(""); + return kTRUE; + case kTriggerPurity: + if(!MakeBarPlot((TH1F*)fContainer->FindObject("hTriggerPurity"), kGreen)) break; + break; + default: + break; + } + AliInfo(Form("Reference plot [%d] missing result", ifig)); + return kFALSE; +} + +//_______________________________________________________ +TObjArray *AliTRDcheckDET::Histos(){ + // + // Create QA histograms + // + if(fContainer) return fContainer; + + fContainer = new TObjArray(20); + //fContainer->SetOwner(kTRUE); + + // Register Histograms + TH1 * h = NULL; + TAxis *ax = NULL; + if(!(h = (TH1F *)gROOT->FindObject("hNcls"))){ + h = new TH1F("hNcls", "N_{clusters} / track", 181, -0.5, 180.5); + h->GetXaxis()->SetTitle("N_{clusters}"); + h->GetYaxis()->SetTitle("Entries"); + } else h->Reset(); + fContainer->AddAt(h, kNclustersTrack); + + if(!(h = (TH1F *)gROOT->FindObject("hNclTls"))){ + h = new TH1F("hNclTls","N_{clusters} / tracklet", 51, -0.5, 50.5); + h->GetXaxis()->SetTitle("N_{clusters}"); + h->GetYaxis()->SetTitle("Entries"); + } else h->Reset(); + fContainer->AddAt(h, kNclustersTracklet); + + if(!(h = (TH1F *)gROOT->FindObject("hNtls"))){ + h = new TH1F("hNtls", "N_{tracklets} / track", AliTRDgeometry::kNlayer, 0.5, 6.5); + h->GetXaxis()->SetTitle("N^{tracklet}"); + h->GetYaxis()->SetTitle("freq. [%]"); + } else h->Reset(); + fContainer->AddAt(h, kNtrackletsTrack); + + if(!(h = (TH1F *)gROOT->FindObject("htlsSTA"))){ + h = new TH1F("hNtlsSTA", "N_{tracklets} / track (Stand Alone)", AliTRDgeometry::kNlayer, 0.5, 6.5); + h->GetXaxis()->SetTitle("N^{tracklet}"); + h->GetYaxis()->SetTitle("freq. [%]"); + } + fContainer->AddAt(h, kNtrackletsSTA); + + if(!(h = (TH1F *)gROOT->FindObject("htlsBAR"))){ + h = new TH1F("hNtlsBAR", "N_{tracklets} / track (Barrel)", AliTRDgeometry::kNlayer, 0.5, 6.5); + h->GetXaxis()->SetTitle("N^{tracklet}"); + h->GetYaxis()->SetTitle("freq. [%]"); + } + fContainer->AddAt(h, kNtrackletsBAR); + + // + if(!(h = (TH1F *)gROOT->FindObject("hNtlsCross"))){ + h = new TH1F("hNtlsCross", "N_{tracklets}^{cross} / track", 7, -0.5, 6.5); + h->GetXaxis()->SetTitle("n_{row cross}"); + h->GetYaxis()->SetTitle("freq. [%]"); + } else h->Reset(); + fContainer->AddAt(h, kNtrackletsCross); + + if(!(h = (TH1F *)gROOT->FindObject("hNtlsFindable"))){ + h = new TH1F("hNtlsFindable", "Found/Findable Tracklets" , 101, -0.005, 1.005); + h->GetXaxis()->SetTitle("r [a.u]"); + h->GetYaxis()->SetTitle("Entries"); + } else h->Reset(); + fContainer->AddAt(h, kNtrackletsFindable); + + if(!(h = (TH1F *)gROOT->FindObject("hNtrks"))){ + h = new TH1F("hNtrks", "N_{tracks} / event", 100, 0, 100); + h->GetXaxis()->SetTitle("N_{tracks}"); + h->GetYaxis()->SetTitle("Entries"); + } else h->Reset(); + fContainer->AddAt(h, kNtracksEvent); + + if(!(h = (TH1F *)gROOT->FindObject("hNtrksSector"))){ + h = new TH1F("hNtrksSector", "N_{tracks} / sector", AliTRDgeometry::kNsector, -0.5, 17.5); + h->GetXaxis()->SetTitle("sector"); + h->GetYaxis()->SetTitle("freq. [%]"); + } else h->Reset(); + fContainer->AddAt(h, kNtracksSector); + + if(!(h = (TH1F*)gROOT->FindObject("hTrackStatus"))){ + const Int_t nerr = 7; + h = new TH1F("hTrackStatus", "Track Status", nerr, -0.5, nerr-0.5); + const Char_t *label[nerr] = {"OK", "PROL", "PROP", "AJST", "SNP", "TINI", "UPDT"}; + ax = h->GetXaxis(); + for(Int_t ierr=nerr; ierr--;) ax->SetBinLabel(ierr+1, label[ierr]); + h->SetYTitle("Relative Error to Good [%]"); + } + fContainer->AddAt(h, kTrackStatus); + + TObjArray *arr = new TObjArray(AliTRDgeometry::kNlayer); + arr->SetOwner(kTRUE); arr->SetName("TrackletStatus"); + fContainer->AddAt(arr, kTrackletStatus); + for(Int_t ily=AliTRDgeometry::kNlayer; ily--;){ + if(!(h = (TH1F *)gROOT->FindObject(Form("hTrackletStatus%d", ily)))){ + const Int_t nerr = 8; + h = new TH1F(Form("hTrackletStatus%d", ily), "Tracklet status", nerr, -0.5, nerr-0.5); + h->SetLineColor(ily+1); + const Char_t *label[nerr] = {"OK", "Geom", "Bound", "NoCl", "NoAttach", "NoClTr", "NoFit", "Chi2"}; + ax = h->GetXaxis(); + for(Int_t ierr=nerr; ierr--;) ax->SetBinLabel(ierr+1, label[ierr]); + h->SetYTitle("Relative Error to Good [%]"); + } else h->Reset(); + arr->AddAt(h, ily); + } + + // histos + arr = new TObjArray(2); + arr->SetOwner(kTRUE); arr->SetName(""); + fContainer->AddAt(arr, kPH); + if(!(h = (TH1F *)gROOT->FindObject("hPHt"))){ + h = new TProfile("hPHt", "", 31, -0.5, 30.5); + h->GetXaxis()->SetTitle("Time / 100ns"); + h->GetYaxis()->SetTitle(" [a.u]"); + } else h->Reset(); + arr->AddAt(h, 0); + if(!(h = (TH1F *)gROOT->FindObject("hPHx"))) + h = new TProfile("hPHx", "", 31, -0.08, 4.88); + else h->Reset(); + arr->AddAt(h, 1); + + // Chi2 histos + if(!(h = (TH2S*)gROOT->FindObject("hChi2"))){ + h = new TH2S("hChi2", "#chi^{2} per track", AliTRDgeometry::kNlayer, .5, AliTRDgeometry::kNlayer+.5, 100, 0, 50); + h->SetXTitle("ndf"); + h->SetYTitle("#chi^{2}/ndf"); + h->SetZTitle("entries"); + } else h->Reset(); + fContainer->AddAt(h, kChi2); + + if(!(h = (TH1F *)gROOT->FindObject("hQcl"))){ + h = new TH1F("hQcl", "Q_{cluster}", 200, 0, 1200); + h->GetXaxis()->SetTitle("Q_{cluster} [a.u.]"); + h->GetYaxis()->SetTitle("Entries"); + }else h->Reset(); + fContainer->AddAt(h, kChargeCluster); + + if(!(h = (TH1F *)gROOT->FindObject("hQtrklt"))){ + h = new TH1F("hQtrklt", "Q_{tracklet}", 6000, 0, 6000); + h->GetXaxis()->SetTitle("Q_{tracklet} [a.u.]"); + h->GetYaxis()->SetTitle("Entries"); + }else h->Reset(); + fContainer->AddAt(h, kChargeTracklet); + + + if(!(h = (TH1F *)gROOT->FindObject("hEventsTrigger"))) + h = new TH1F("hEventsTrigger", "Trigger Class", 100, 0, 100); + else h->Reset(); + fContainer->AddAt(h, kNeventsTrigger); + + if(!(h = (TH1F *)gROOT->FindObject("hEventsTriggerTracks"))) + h = new TH1F("hEventsTriggerTracks", "Trigger Class (Tracks)", 100, 0, 100); + else h->Reset(); + fContainer->AddAt(h, kNeventsTriggerTracks); + + if(!(h = (TH1F *)gROOT->FindObject("hTriggerPurity"))){ + h = new TH1F("hTriggerPurity", "Trigger Purity", 10, -0.5, 9.5); + h->GetXaxis()->SetTitle("Trigger Cluster"); + h->GetYaxis()->SetTitle("freq."); + } else h->Reset(); + fContainer->AddAt(h, kTriggerPurity); + + return fContainer; +} + +/* +* Plotting Functions +*/ + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotTrackStatus(const AliTRDtrackV1 *track) +{ +// +// Plot the track propagation status. The following errors are defined (see AliTRDtrackV1::ETRDtrackError) +// PROL - track prolongation failure +// PROP - track propagation failure +// AJST - crossing sectors failure +// SNP - too large bending +// TINI - tracklet initialization failure +// UPDT - track position/covariance update failure +// +// Performance plot looks as below: +//Begin_Html +// +//End_Html +// + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TH1 *h = 0x0; + if(!(h = dynamic_cast(fContainer->At(kTrackStatus)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + h->Fill(fkTrack->GetStatusTRD()); + return h; +} + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotTrackletStatus(const AliTRDtrackV1 *track) +{ +// +// Plot the tracklet propagation status. The following errors are defined for tracklet (see AliTRDtrackV1::ETRDlayerError) +// Geom - +// Bound - tracklet too close to chamber walls +// NoCl - no clusters in the track roads +// NoAttach - fail to attach clusters +// NoClTr - fail to use clusters for fit +// NoFit - tracklet fit failled +// Chi2 - chi2 tracklet-track over threshold +// +// Performance plot looks as below: +//Begin_Html +// +//End_Html +// + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TObjArray *arr =0x0; + if(!(arr = dynamic_cast(fContainer->At(kTrackletStatus)))){ + AliWarning("Histograms not defined."); + return 0x0; + } + + TH1 *h = 0x0; + for(Int_t ily=AliTRDgeometry::kNlayer; ily--;){ + if(!(h = dynamic_cast(arr->At(ily)))){ + AliWarning(Form("Missing histo for layer %d.", ily)); + continue; + } + h->Fill(fkTrack->GetStatusTRD(ily)); + } + return h; +} + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotNClustersTracklet(const AliTRDtrackV1 *track){ + // + // Plot the mean number of clusters per tracklet + // + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TH1 *h = 0x0; + if(!(h = dynamic_cast(fContainer->At(kNclustersTracklet)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + AliTRDseedV1 *tracklet = 0x0; + for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){ + if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK()) continue; + h->Fill(tracklet->GetN2()); + } + return h; +} + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotNClustersTrack(const AliTRDtrackV1 *track){ + // + // Plot the number of clusters in one track + // + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TH1 *h = 0x0; + if(!(h = dynamic_cast(fContainer->At(kNclustersTrack)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + Int_t nclusters = 0; + AliTRDseedV1 *tracklet = 0x0; + for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){ + if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK()) continue; + nclusters += tracklet->GetN(); + if(DebugLevel() > 2){ + Int_t crossing = Int_t(tracklet->IsRowCross()); + Int_t detector = tracklet->GetDetector(); + Float_t theta = TMath::ATan(tracklet->GetZref(1)); + Float_t phi = TMath::ATan(tracklet->GetYref(1)); + Float_t momentum = 0.; + Int_t pdg = 0; + Int_t kinkIndex = fkESD ? fkESD->GetKinkIndex() : 0; + UShort_t nclsTPC = fkESD ? fkESD->GetTPCncls() : 0; + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } + (*DebugStream()) << "NClustersTrack" + << "Detector=" << detector + << "crossing=" << crossing + << "momentum=" << momentum + << "pdg=" << pdg + << "theta=" << theta + << "phi=" << phi + << "kinkIndex=" << kinkIndex + << "TPCncls=" << nclsTPC + << "nclusters=" << nclusters + << "\n"; + } + } + h->Fill(nclusters); + return h; +} + + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotNTrackletsTrack(const AliTRDtrackV1 *track){ + // + // Plot the number of tracklets + // + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TH1 *h = 0x0, *hMethod = 0x0; + if(!(h = dynamic_cast(fContainer->At(kNtrackletsTrack)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + Int_t nTracklets = fkTrack->GetNumberOfTracklets(); + h->Fill(nTracklets); + if(!fkESD) return h; + Int_t status = fkESD->GetStatus(); +/* printf("in/out/refit/pid: TRD[%d|%d|%d|%d]\n", status &AliESDtrack::kTRDin ? 1 : 0, status &AliESDtrack::kTRDout ? 1 : 0, status &AliESDtrack::kTRDrefit ? 1 : 0, status &AliESDtrack::kTRDpid ? 1 : 0);*/ + if((status & AliESDtrack::kTRDin) != 0){ + // Full BarrelTrack + if(!(hMethod = dynamic_cast(fContainer->At(kNtrackletsBAR)))) + AliWarning("Method: Barrel. Histogram not processed!"); + } else { + // Stand alone Track + if(!(hMethod = dynamic_cast(fContainer->At(kNtrackletsSTA)))) + AliWarning("Method: StandAlone. Histogram not processed!"); + } + hMethod->Fill(nTracklets); + + if(DebugLevel() > 3){ + if(nTracklets == 1){ + // If we have one Tracklet, check in which layer this happens + Int_t layer = -1; + AliTRDseedV1 *tracklet = 0x0; + for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){ + if((tracklet = fkTrack->GetTracklet(il)) && tracklet->IsOK()){layer = il; break;} + } + (*DebugStream()) << "NTrackletsTrack" + << "Layer=" << layer + << "\n"; + } + } + return h; +} + + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotNTrackletsRowCross(const AliTRDtrackV1 *track){ + // + // Plot the number of tracklets + // + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TH1 *h = 0x0; + if(!(h = dynamic_cast(fContainer->At(kNtrackletsCross)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + Int_t ncross = 0; + AliTRDseedV1 *tracklet = 0x0; + for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){ + if(!(tracklet = fkTrack->GetTracklet(il)) || !tracklet->IsOK()) continue; + + if(tracklet->IsRowCross()) ncross++; + } + h->Fill(ncross); + return h; +} + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotFindableTracklets(const AliTRDtrackV1 *track){ + // + // Plots the ratio of number of tracklets vs. + // number of findable tracklets + // + // Findable tracklets are defined as track prolongation + // to layer i does not hit the dead area +- epsilon + // + // In order to check whether tracklet hist active area in Layer i, + // the track is refitted and the fitted position + an uncertainty + // range is compared to the chamber border (also with a different + // uncertainty) + // + // For the track fit two cases are distinguished: + // If the track is a stand alone track (defined by the status bit + // encoding, then the track is fitted with the tilted Rieman model + // Otherwise the track is fitted with the Kalman fitter in two steps: + // Since the track parameters are give at the outer point, we first + // fit in direction inwards. Afterwards we fit again in direction outwards + // to extrapolate the track to layers which are not reached by the track + // For the Kalman model, the radial track points have to be shifted by + // a distance epsilon in the direction that we want to fit + // + const Float_t epsilon = 0.01; // dead area tolerance + const Float_t epsilonR = 1; // shift in radial direction of the anode wire position (Kalman filter only) + const Float_t deltaY = 0.7; // Tolerance in the track position in y-direction + const Float_t deltaZ = 7.0; // Tolerance in the track position in z-direction (Padlength) + Double_t xAnode[AliTRDgeometry::kNlayer] = {300.2, 312.8, 325.4, 338.0, 350.6, 363.2}; // Take the default X0 + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TH1 *h = 0x0; + if(!(h = dynamic_cast(fContainer->At(kNtrackletsFindable)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + Int_t nFound = 0, nFindable = 0; + Int_t stack = -1; + Double_t ymin = 0., ymax = 0., zmin = 0., zmax = 0.; + Double_t y = 0., z = 0.; + AliTRDseedV1 *tracklet = 0x0; + AliTRDpadPlane *pp; + for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){ + if((tracklet = fkTrack->GetTracklet(il)) && tracklet->IsOK()){ + tracklet->SetReconstructor(fReconstructor); + nFound++; + } + } + // 2 Different cases: + // 1st stand alone: here we cannot propagate, but be can do a Tilted Rieman Fit + // 2nd barrel track: here we propagate the track to the layers + AliTrackPoint points[6]; + Float_t xyz[3]; + memset(xyz, 0, sizeof(Float_t) * 3); + if(((fkESD->GetStatus() & AliESDtrack::kTRDout) > 0) && !((fkESD->GetStatus() & AliESDtrack::kTRDin) > 0)){ + // stand alone track + for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){ + xyz[0] = xAnode[il]; + points[il].SetXYZ(xyz); + } + AliTRDtrackerV1::FitRiemanTilt(const_cast(fkTrack), 0x0, kTRUE, 6, points); + } else { + // barrel track + // + // 2 Steps: + // -> Kalman inwards + // -> Kalman outwards + AliTRDtrackV1 copyTrack(*fkTrack); // Do Kalman on a (non-constant) copy of the track + AliTrackPoint pointsInward[6], pointsOutward[6]; + for(Int_t il = AliTRDgeometry::kNlayer; il--;){ + // In order to avoid complications in the Kalman filter if the track points have the same radial + // position like the tracklets, we have to shift the radial postion of the anode wire by epsilon + // in the direction we want to go + // The track points have to be in reverse order for the Kalman Filter inwards + xyz[0] = xAnode[AliTRDgeometry::kNlayer - il - 1] - epsilonR; + pointsInward[il].SetXYZ(xyz); + xyz[0] = xAnode[il] + epsilonR; + pointsOutward[il].SetXYZ(xyz); + } + /*for(Int_t ipt = 0; ipt < AliTRDgeometry::kNlayer; ipt++) + printf("%d. X = %f\n", ipt, points[ipt].GetX());*/ + // Kalman inwards + AliTRDtrackerV1::FitKalman(©Track, 0x0, kFALSE, 6, pointsInward); + memcpy(points, pointsInward, sizeof(AliTrackPoint) * 6); // Preliminary store the inward results in the Array points + // Kalman outwards + AliTRDtrackerV1::FitKalman(©Track, 0x0, kTRUE, 6, pointsInward); + memcpy(points, pointsOutward, sizeof(AliTrackPoint) * AliTRDgeometry::kNlayer); + } + for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){ + y = points[il].GetY(); + z = points[il].GetZ(); + if((stack = fGeo->GetStack(z, il)) < 0) continue; // Not findable + pp = fGeo->GetPadPlane(il, stack); + ymin = pp->GetCol0() + epsilon; + ymax = pp->GetColEnd() - epsilon; + zmin = pp->GetRowEnd() + epsilon; + zmax = pp->GetRow0() - epsilon; + // ignore y-crossing (material) + if((z + deltaZ > zmin && z - deltaZ < zmax) && (y + deltaY > ymin && y - deltaY < ymax)) nFindable++; + if(DebugLevel() > 3){ + Double_t posTracklet[2] = {tracklet ? tracklet->GetYfit(0) : 0, tracklet ? tracklet->GetZfit(0) : 0}; + Int_t hasTracklet = tracklet ? 1 : 0; + (*DebugStream()) << "FindableTracklets" + << "layer=" << il + << "ytracklet=" << posTracklet[0] + << "ytrack=" << y + << "ztracklet=" << posTracklet[1] + << "ztrack=" << z + << "tracklet=" << hasTracklet + << "\n"; + } + } + + h->Fill(nFindable > 0 ? TMath::Min(nFound/static_cast(nFindable), 1.) : 1); + AliDebug(2, Form("Findable[Found]: %d[%d|%f]", nFindable, nFound, nFound/static_cast(nFindable > 0 ? nFindable : 1))); + return h; +} + + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotChi2(const AliTRDtrackV1 *track){ + // + // Plot the chi2 of the track + // + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TH1 *h = 0x0; + if(!(h = dynamic_cast(fContainer->At(kChi2)))) { + AliWarning("No Histogram defined."); + return 0x0; + } + Int_t n = fkTrack->GetNumberOfTracklets(); + if(!n) return 0x0; + + h->Fill(n, fkTrack->GetChi2()/n); + return h; +} + + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotPHt(const AliTRDtrackV1 *track){ + // + // Plot the average pulse height + // + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TProfile *h = 0x0; + if(!(h = dynamic_cast(((TObjArray*)(fContainer->At(kPH)))->At(0)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + AliTRDseedV1 *tracklet = 0x0; + AliTRDcluster *c = 0x0; + for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){ + if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK())continue; + Int_t crossing = Int_t(tracklet->IsRowCross()); + Int_t detector = tracklet->GetDetector(); + tracklet->ResetClusterIter(); + while((c = tracklet->NextCluster())){ + if(!c->IsInChamber()) continue; + Int_t localtime = c->GetLocalTimeBin(); + Double_t absoluteCharge = TMath::Abs(c->GetQ()); + h->Fill(localtime, absoluteCharge); + if(DebugLevel() > 3){ + Double_t distance[2]; + GetDistanceToTracklet(distance, tracklet, c); + Float_t theta = TMath::ATan(tracklet->GetZref(1)); + Float_t phi = TMath::ATan(tracklet->GetYref(1)); + Float_t momentum = 0.; + Int_t pdg = 0; + Int_t kinkIndex = fkESD ? fkESD->GetKinkIndex() : 0; + UShort_t TPCncls = fkESD ? fkESD->GetTPCncls() : 0; + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } + (*DebugStream()) << "PHt" + << "Detector=" << detector + << "crossing=" << crossing + << "Timebin=" << localtime + << "Charge=" << absoluteCharge + << "momentum=" << momentum + << "pdg=" << pdg + << "theta=" << theta + << "phi=" << phi + << "kinkIndex=" << kinkIndex + << "TPCncls=" << TPCncls + << "dy=" << distance[0] + << "dz=" << distance[1] + << "c.=" << c + << "\n"; + } + } + } + return h; +} + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotPHx(const AliTRDtrackV1 *track){ + // + // Plots the average pulse height vs the distance from the anode wire + // (plus const anode wire offset) + // + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TProfile *h = 0x0; + if(!(h = dynamic_cast(((TObjArray*)(fContainer->At(kPH)))->At(1)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + Float_t offset = .5*AliTRDgeometry::CamHght(); + AliTRDseedV1 *tracklet = 0x0; + AliTRDcluster *c = 0x0; + Double_t distance = 0; + Double_t x, y; + for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){ + if(!(tracklet = fkTrack->GetTracklet(itl)) || !(tracklet->IsOK())) continue; + tracklet->ResetClusterIter(); + while((c = tracklet->NextCluster())){ + if(!c->IsInChamber()) continue; + x = c->GetX()-AliTRDcluster::GetXcorr(c->GetLocalTimeBin()); + y = c->GetY()-AliTRDcluster::GetYcorr(AliTRDgeometry::GetLayer(c->GetDetector()), c->GetCenter()); + + distance = tracklet->GetX0() - (c->GetX() + 0.3) + offset; + h->Fill(distance, TMath::Abs(c->GetQ())); + } + } + return h; +} + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotChargeCluster(const AliTRDtrackV1 *track){ + // + // Plot the cluster charge + // + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TH1 *h = 0x0; + if(!(h = dynamic_cast(fContainer->At(kChargeCluster)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + AliTRDseedV1 *tracklet = 0x0; + AliTRDcluster *c = 0x0; + for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){ + if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK())continue; + for(Int_t itime = 0; itime < AliTRDtrackerV1::GetNTimeBins(); itime++){ + if(!(c = tracklet->GetClusters(itime))) continue; + h->Fill(c->GetQ()); + } + } + return h; +} + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotChargeTracklet(const AliTRDtrackV1 *track){ + // + // Plot the charge deposit per chamber + // + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TH1 *h = 0x0; + if(!(h = dynamic_cast(fContainer->At(kChargeTracklet)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + AliTRDseedV1 *tracklet = 0x0; + AliTRDcluster *c = 0x0; + Double_t qTot = 0; + Int_t nTracklets =fkTrack->GetNumberOfTracklets(); + for(Int_t itl = 0x0; itl < AliTRDgeometry::kNlayer; itl++){ + if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK()) continue; + qTot = 0.; + for(Int_t ic = AliTRDseedV1::kNclusters; ic--;){ + if(!(c = tracklet->GetClusters(ic))) continue; + qTot += TMath::Abs(c->GetQ()); + } + h->Fill(qTot); + if(DebugLevel() > 3){ + Int_t crossing = (Int_t)tracklet->IsRowCross(); + Int_t detector = tracklet->GetDetector(); + Float_t theta = TMath::ATan(tracklet->GetZfit(1)); + Float_t phi = TMath::ATan(tracklet->GetYfit(1)); + Float_t momentum = 0.; + Int_t pdg = 0; + Int_t kinkIndex = fkESD ? fkESD->GetKinkIndex() : 0; + UShort_t nclsTPC = fkESD ? fkESD->GetTPCncls() : 0; + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } + (*DebugStream()) << "ChargeTracklet" + << "Detector=" << detector + << "crossing=" << crossing + << "momentum=" << momentum + << "nTracklets="<< nTracklets + << "pdg=" << pdg + << "theta=" << theta + << "phi=" << phi + << "kinkIndex=" << kinkIndex + << "TPCncls=" << nclsTPC + << "QT=" << qTot + << "\n"; + } + } + return h; +} + +//_______________________________________________________ +TH1 *AliTRDcheckDET::PlotNTracksSector(const AliTRDtrackV1 *track){ + // + // Plot the number of tracks per Sector + // + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TH1 *h = 0x0; + if(!(h = dynamic_cast(fContainer->At(kNtracksSector)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + // TODO we should compare with + // sector = Int_t(track->GetAlpha() / AliTRDgeometry::GetAlpha()); + + AliTRDseedV1 *tracklet = 0x0; + Int_t sector = -1; + for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){ + if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK()) continue; + sector = static_cast(tracklet->GetDetector()/AliTRDgeometry::kNdets); + break; + } + h->Fill(sector); + return h; +} + + +//________________________________________________________ +void AliTRDcheckDET::SetRecoParam(AliTRDrecoParam *r) +{ + + fReconstructor->SetRecoParam(r); +} + +//________________________________________________________ +void AliTRDcheckDET::GetDistanceToTracklet(Double_t *dist, AliTRDseedV1 * const tracklet, AliTRDcluster * const c) +{ + Float_t x = c->GetX(); + dist[0] = c->GetY() - tracklet->GetYat(x); + dist[1] = c->GetZ() - tracklet->GetZat(x); +} + + +//_______________________________________________________ +TH1* AliTRDcheckDET::MakePlotChi2() +{ +// Plot chi2/track normalized to number of degree of freedom +// (tracklets) and compare with the theoretical distribution. +// +// Alex Bercuci + + TH2S *h2 = (TH2S*)fContainer->At(kChi2); + TF1 f("fChi2", "[0]*pow(x, [1]-1)*exp(-0.5*x)", 0., 50.); + TLegend *leg = new TLegend(.7,.7,.95,.95); + leg->SetBorderSize(1); leg->SetHeader("Tracklets per Track"); + TH1D *h1 = 0x0; + Bool_t kFIRST = kTRUE; + for(Int_t il=1; il<=h2->GetNbinsX(); il++){ + h1 = h2->ProjectionY(Form("pyChi2%d", il), il, il); + if(h1->Integral()<50) continue; + h1->Scale(1./h1->Integral()); + h1->SetMarkerStyle(7);h1->SetMarkerColor(il); + h1->SetLineColor(il);h1->SetLineStyle(2); + f.SetParameter(1, .5*il);f.SetLineColor(il); + h1->Fit(&f, "QW+", kFIRST ? "pc": "pcsame"); + leg->AddEntry(h1, Form("%d", il), "l"); + if(kFIRST){ + h1->GetXaxis()->SetRangeUser(0., 25.); + } + kFIRST = kFALSE; + } + leg->Draw(); + gPad->SetLogy(); + return h1; +} + + +//________________________________________________________ +TH1* AliTRDcheckDET::MakePlotNTracklets(){ + // + // Make nice bar plot of the number of tracklets in each method + // + TH1F *hBAR = (TH1F *)fContainer->FindObject("hNtlsBAR"); + TH1F *hSTA = (TH1F *)fContainer->FindObject("hNtlsSTA"); + TH1F *hCON = (TH1F *)fContainer->FindObject("hNtls"); + TLegend *leg = new TLegend(0.13, 0.75, 0.39, 0.89); + leg->SetBorderSize(1); + leg->SetFillColor(0); + + Float_t scale = hCON->Integral(); + hCON->Scale(100./scale); + hCON->SetFillColor(kRed);hCON->SetLineColor(kRed); + hCON->SetBarWidth(0.2); + hCON->SetBarOffset(0.6); + hCON->SetStats(kFALSE); + hCON->GetYaxis()->SetRangeUser(0.,40.); + hCON->GetYaxis()->SetTitleOffset(1.2); + hCON->Draw("bar1"); leg->AddEntry(hCON, "Total", "f"); + hCON->SetMaximum(55.); + + hBAR->Scale(100./scale); + hBAR->SetFillColor(kGreen);hBAR->SetLineColor(kGreen); + hBAR->SetBarWidth(0.2); + hBAR->SetBarOffset(0.2); + hBAR->SetTitle(""); + hBAR->SetStats(kFALSE); + hBAR->GetYaxis()->SetRangeUser(0.,40.); + hBAR->GetYaxis()->SetTitleOffset(1.2); + hBAR->Draw("bar1same"); leg->AddEntry(hBAR, "Barrel", "f"); + + hSTA->Scale(100./scale); + hSTA->SetFillColor(kBlue);hSTA->SetLineColor(kBlue); + hSTA->SetBarWidth(0.2); + hSTA->SetBarOffset(0.4); + hSTA->SetTitle(""); + hSTA->SetStats(kFALSE); + hSTA->GetYaxis()->SetRangeUser(0.,40.); + hSTA->GetYaxis()->SetTitleOffset(1.2); + hSTA->Draw("bar1same"); leg->AddEntry(hSTA, "Stand Alone", "f"); + leg->Draw(); + gPad->Update(); + return hCON; +} + +//________________________________________________________ +TH1* AliTRDcheckDET::MakePlotPulseHeight(){ + // + // Create Plot of the Pluse Height Spectrum + // + TH1 *h, *h1, *h2; + TObjArray *arr = (TObjArray*)fContainer->FindObject(""); + h = (TH1F*)arr->At(0); + h->SetMarkerStyle(24); + h->SetMarkerColor(kBlack); + h->SetLineColor(kBlack); + h->Draw("e1"); +// copy the second histogram in a new one with the same x-dimension as the phs with respect to time + h1 = (TH1F *)arr->At(1); + h2 = new TH1F("hphs1","Average PH", 31, -0.5, 30.5); + for(Int_t ibin = h1->GetXaxis()->GetFirst(); ibin < h1->GetNbinsX(); ibin++) + h2->SetBinContent(ibin, h1->GetBinContent(ibin)); + h2->SetMarkerStyle(22); + h2->SetMarkerColor(kBlue); + h2->SetLineColor(kBlue); + h2->Draw("e1same"); + gPad->Update(); +// create axis according to the histogram dimensions of the original second histogram + TGaxis *axis = new TGaxis(gPad->GetUxmin(), + gPad->GetUymax(), + gPad->GetUxmax(), + gPad->GetUymax(), + -0.08, 4.88, 510,"-L"); + axis->SetLineColor(kBlue); + axis->SetLabelColor(kBlue); + axis->SetTextColor(kBlue); + axis->SetTitle("x_{0}-x_{c} [cm]"); + axis->Draw(); + return h1; +} + +//________________________________________________________ +Bool_t AliTRDcheckDET::MakeBarPlot(TH1 *histo, Int_t color){ + // + // Draw nice bar plots + // + if(!histo->GetEntries()) return kFALSE; + histo->Scale(100./histo->Integral()); + histo->SetFillColor(color); + histo->SetBarOffset(.2); + histo->SetBarWidth(.6); + histo->Draw("bar1"); + return kTRUE; +} diff --git a/PWG1/TRD/AliTRDcheckDET.h b/PWG1/TRD/AliTRDcheckDET.h new file mode 100644 index 00000000000..04fef04dd43 --- /dev/null +++ b/PWG1/TRD/AliTRDcheckDET.h @@ -0,0 +1,97 @@ +#ifndef ALITRDCHECKDET_H +#define ALITRDCHECKDET_H + +#ifndef ALITRDRECOTASK_H +#include "AliTRDrecoTask.h" +#endif +//////////////////////////////////////////////////////////////////////////// +// Basic checks for tracking and detector performance // +// // +// Authors: // +// Anton Andronic // +// Alexandru Bercuci // +// Markus Fasel // +//////////////////////////////////////////////////////////////////////////// + + +class TObjArray; +class TH1; +class TMap; +class AliESDHeader; +class AliTRDcluster; +class AliTRDseedV1; +class AliTRDgeometry; +class AliTRDReconstructor; +class AliTRDrecoParam; +class AliTRDeventInfo; +class AliTRDcheckDET : public AliTRDrecoTask{ +public: + // The Histogram number + enum HistType_t { + kNclustersTrack = 0, + kNclustersTracklet = 1, + kNtrackletsTrack = 2, + kNtrackletsSTA = 3, + kNtrackletsBAR = 4, + kNtrackletsCross = 5, + kNtrackletsFindable = 6, + kNtracksEvent = 7, + kNtracksSector = 8, + kPH = 9, + kChi2 = 10, + kChargeCluster = 11, + kChargeTracklet = 12, + kNeventsTrigger = 13, + kNeventsTriggerTracks=14, + kTriggerPurity = 15, + kTrackStatus = 16, + kTrackletStatus = 17 + }; + + AliTRDcheckDET(); + virtual ~AliTRDcheckDET(); + + virtual void ConnectInputData(const Option_t *); + virtual void CreateOutputObjects(); + virtual void Exec(Option_t *opt); + + virtual TObjArray *Histos(); + + // Plotting Functions: + TH1 *PlotTrackStatus(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotTrackletStatus(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotNClustersTracklet(const AliTRDtrackV1 *t = 0x0); + TH1 *PlotNClustersTrack(const AliTRDtrackV1 *t = 0x0); + TH1 *PlotNTrackletsTrack(const AliTRDtrackV1 *t = 0x0); + TH1 *PlotNTrackletsRowCross(const AliTRDtrackV1 *t = 0x0); + TH1 *PlotFindableTracklets(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotNTracksSector(const AliTRDtrackV1 *t = 0x0); + TH1 *PlotPHt(const AliTRDtrackV1 *t = 0x0); + TH1 *PlotPHx(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotChi2(const AliTRDtrackV1 *t = 0x0); + TH1 *PlotChargeCluster(const AliTRDtrackV1 *t = 0x0); + TH1 *PlotChargeTracklet(const AliTRDtrackV1 *t = 0x0); + + virtual Bool_t PostProcess(); + virtual Bool_t GetRefFigure(Int_t ifig); + + void SetRecoParam(AliTRDrecoParam *r); + +private: + AliTRDcheckDET(const AliTRDcheckDET &); + AliTRDcheckDET& operator=(const AliTRDcheckDET &); + void GetDistanceToTracklet(Double_t *dist, AliTRDseedV1 * const tracklet, AliTRDcluster * const c); + TH1* MakePlotChi2(); + TH1* MakePlotNTracklets(); + TH1* MakePlotPulseHeight(); + Bool_t MakeBarPlot(TH1 *histo, Int_t Color); + + AliTRDeventInfo *fEventInfo; //! ESD Header + TMap *fTriggerNames; //! Containing trigger class names + AliTRDReconstructor *fReconstructor; // TRD Reconstructor + AliTRDgeometry *fGeo; // TRD Geometry object + + ClassDef(AliTRDcheckDET, 1) +}; +#endif + diff --git a/PWG1/TRD/AliTRDcheckESD.cxx b/PWG1/TRD/AliTRDcheckESD.cxx new file mode 100644 index 00000000000..0a07060aa6c --- /dev/null +++ b/PWG1/TRD/AliTRDcheckESD.cxx @@ -0,0 +1,486 @@ +/************************************************************************** +* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* * +* Author: The ALICE Off-line Project. * +* Contributors are mentioned in the code where appropriate. * +* * +* Permission to use, copy, modify and distribute this software and its * +* documentation strictly for non-commercial purposes is hereby granted * +* without fee, provided that the above copyright notice appears in all * +* copies and that both the copyright notice and this permission notice * +* appear in the supporting documentation. The authors make no claims * +* about the suitability of this software for any purpose. It is * +* provided "as is" without express or implied warranty. * +**************************************************************************/ + +///////////////////////////////////////////////////// +// +// Check basic detector results at ESD level +// - Geometrical efficiency +// - Tracking efficiency +// - PID efficiency +// - Refit efficiency +// +// Author +// Alex Bercuci +// +////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AliLog.h" +#include "AliAnalysisManager.h" +#include "AliESDEvent.h" +#include "AliESDkink.h" +#include "AliMCEvent.h" +#include "AliESDInputHandler.h" +#include "AliMCEventHandler.h" + +#include "AliESDtrack.h" +#include "AliMCParticle.h" +#include "AliPID.h" +#include "AliStack.h" +#include "AliTrackReference.h" + +#include "AliTRDcheckESD.h" + +ClassImp(AliTRDcheckESD) + +const Float_t AliTRDcheckESD::fgkxTPC = 290.; +const Float_t AliTRDcheckESD::fgkxTOF = 365.; +FILE* AliTRDcheckESD::fgFile = 0x0; + +//____________________________________________________________________ +AliTRDcheckESD::AliTRDcheckESD(): + AliAnalysisTask("checkESD", "ESD checker for TRD info") + ,fStatus(0) + ,fESD(0x0) + ,fMC(0x0) + ,fHistos(0x0) + ,fResults(0x0) +{ + // + // Default constructor + // + SetMC(kTRUE); + DefineInput(0, TChain::Class()); + DefineOutput(0, TObjArray::Class()); +} + +//____________________________________________________________________ +AliTRDcheckESD::~AliTRDcheckESD() +{ +// Destructor + if(fHistos){ + //fHistos->Delete(); + delete fHistos; + } + if(fResults){ + fResults->Delete(); + delete fResults; + } +} + +//____________________________________________________________________ +void AliTRDcheckESD::ConnectInputData(Option_t *) +{ + // + // Link the Input Data + // + TTree *tree = dynamic_cast(GetInputData(0)); + if(tree) tree->SetBranchStatus("Tracks", 1); + + AliESDInputHandler *esdH = dynamic_cast(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()); + fESD = esdH ? esdH->GetEvent() : 0x0; + + if(!HasMC()) return; + AliMCEventHandler *mcH = dynamic_cast(AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler()); + fMC = mcH ? mcH->MCEvent() : 0x0; +} + +//____________________________________________________________________ +void AliTRDcheckESD::CreateOutputObjects() +{ + // + // Create Output Containers (TObjectArray containing 1D histograms) + // + OpenFile(0, "RECREATE"); + Histos(); +} + +//____________________________________________________________________ +TGraph* AliTRDcheckESD::GetGraph(Int_t id, Option_t *opt) +{ +// Retrieve graph with "id" +// Possible options are : +// "b" - build graph if none found +// "c" - clear existing graph + + Bool_t kBUILD = strstr(opt, "b"), // build graph if none found + kCLEAR = strstr(opt, "c"); // clear existing graph + + const Char_t *name[] = { + "Geo", "Trk", "Pid", "Ref", "Max06", "Mean09" + }; + const Char_t *title[] = { + "TRD geometrical efficiency (TRDin/TPCout)" + ,"TRD tracking efficiency (TRDout/TRDin)" + ,"TRD PID efficiency (TRDpid/TRDin)" + ,"TRD refit efficiency (TRDrefit/TRDin)" + ,"TRD Eloss (Max/90% quantile)" + ,"TRD Eloss (Mean/60% quantile)" + }; + const Int_t ngr = sizeof(name)/sizeof(Char_t*); + if(ngr != kNgraphs){ + AliWarning("No of graphs defined different from definition"); + return 0x0; + } + + if(!fResults){ + fResults = new TObjArray(kNgraphs); + fResults->SetOwner(); + fResults->SetName("results"); + } + + TGraph *g = 0x0; + if((g = dynamic_cast(fResults->At(id)))){ + if(kCLEAR){ + for(Int_t ip=g->GetN(); ip--;) g->RemovePoint(ip); + } else { + PutTrendValue(name[id], g->GetMean(2)); + PutTrendValue(Form("%sRMS", name[id]), g->GetRMS(2)); + } + } else { + if(kBUILD){ + switch(id){ + case 0: + g = new TGraphErrors(); + break; + case 1: + g = new TGraphErrors(); + break; + case 2: + g = new TGraphErrors(); + break; + case 3: + g = new TGraphErrors(); + break; + case 4: + g = new TGraphAsymmErrors(6); + g->SetMarkerStyle(22);g->SetMarkerColor(kRed); + g->SetLineColor(kBlack);g->SetLineWidth(2); + break; + case 5: + g = new TGraphAsymmErrors(6); + g->SetMarkerStyle(21); + g->SetLineColor(kRed);g->SetLineWidth(2); + break; + default: + AliWarning(Form("Graph index[%d] missing/not defined.", id)); + return 0x0; + } + g->SetNameTitle(name[id], title[id]); + fResults->AddAt(g, id); + } + } + return g; +} + +//____________________________________________________________________ +void AliTRDcheckESD::Exec(Option_t *){ + // + // Run the Analysis + // + if(!fESD){ + AliError("ESD event missing."); + return; + } + + // Get MC information if available + AliStack * fStack = 0x0; + if(HasMC()){ + if(!fMC){ + AliWarning("MC event missing"); + SetMC(kFALSE); + } else { + if(!(fStack = fMC->Stack())){ + AliWarning("MC stack missing"); + SetMC(kFALSE); + } + } + } + Bool_t bTRDin(0), bTRDout(0), bTRDpid(0); + + AliESDtrack *esdTrack = 0x0; + for(Int_t itrk = 0; itrk < fESD->GetNumberOfTracks(); itrk++){ + bTRDin=0;bTRDout=0;bTRDpid=0; + esdTrack = fESD->GetTrack(itrk); + +// if(esdTrack->GetNcls(1)) nTPC++; +// if(esdTrack->GetNcls(2)) nTRD++; + + // track status + ULong_t status = esdTrack->GetStatus(); + //PrintStatus(status); + + // define TPC out tracks + if(!Bool_t(status & AliESDtrack::kTPCout)) continue; + if(esdTrack->GetKinkIndex(0) > 0) continue; + + // TRD PID + Double_t p[AliPID::kSPECIES]; esdTrack->GetTRDpid(p); + // pid quality + //esdTrack->GetTRDntrackletsPID(); + + // look at external track param + const AliExternalTrackParam *op = esdTrack->GetOuterParam(); + const AliExternalTrackParam *ip = esdTrack->GetInnerParam(); + Double_t xyz[3]; + if(op){ + op->GetXYZ(xyz); + op->Global2LocalPosition(xyz, op->GetAlpha()); + //printf("op @ X[%7.3f]\n", xyz[0]); + } + + // read MC info + if(!HasMC()) continue; + + Int_t fLabel = esdTrack->GetLabel(); + if(TMath::Abs(fLabel) > fStack->GetNtrack()) continue; + + // read MC particle + AliMCParticle *mcParticle = 0x0; + if(!(mcParticle = (AliMCParticle*) fMC->GetTrack(TMath::Abs(fLabel)))){ + AliWarning(Form("MC particle missing. Label[ %d].", fLabel)); + continue; + } + + AliTrackReference *ref = 0x0; + Int_t nRefs = mcParticle->GetNumberOfTrackReferences(); + if(!nRefs){ + AliWarning(Form("Track refs missing. Label[%d].", fLabel)); + continue; + } + Int_t iref = 0; + while(irefGetTrackReference(iref); + if(ref->LocalX() > fgkxTPC) break; + ref=0x0; iref++; + } + + // read TParticle + //TParticle *tParticle = mcParticle->Particle(); + //Int_t fPdg = tParticle->GetPdgCode(); + // reject secondaries + //if(!tParticle->IsPrimary()) continue; + + if(ref){ + if(ref->LocalX() > fgkxTOF){ // track skipping TRD fiducial volume + ref = mcParticle->GetTrackReference(TMath::Max(iref-1, 0)); + } else { + bTRDin=1; + if(esdTrack->GetNcls(2)) bTRDout=1; + if(esdTrack->GetTRDntrackletsPID()>=4) bTRDpid=1; + } + } else { // track stopped in TPC + ref = mcParticle->GetTrackReference(TMath::Max(iref-1, 0)); + } + // get the MC pt !! + Float_t pt = ref->Pt(); + + TH2 *h = (TH2I*)fHistos->At(kTRDstat); + if(status & AliESDtrack::kTPCout) h->Fill(pt, kTPCout); + if(/*status & AliESDtrack::k*/bTRDin) h->Fill(pt, kTRDin); + if(/*status & AliESDtrack::k*/bTRDout){ + ((TH1*)fHistos->At(kNCl))->Fill(esdTrack->GetNcls(2)); + h->Fill(pt, kTRDout); + } + if(/*status & AliESDtrack::k*/bTRDpid) h->Fill(pt, kTRDpid); + if(status & AliESDtrack::kTRDrefit) h->Fill(pt, kTRDref); + + if(ip){ + h = (TH2I*)fHistos->At(kTRDmom); + Float_t p(0.); + for(Int_t ily=6; ily--;){ + if((p=esdTrack->GetTRDmomentum(ily))<0.) continue; + h->Fill(ip->GetP()-p, ily); + } + } + } + PostData(0, fHistos); +} + +//____________________________________________________________________ +TObjArray* AliTRDcheckESD::Histos() +{ +// Retrieve histograms array if already build or build it + + if(fHistos) return fHistos; + + fHistos = new TObjArray(kNhistos); + //fHistos->SetOwner(kTRUE); + + TH1 *h = 0x0; + + // clusters per tracklet + if(!(h = (TH1I*)gROOT->FindObject("hNCl"))){ + h = new TH1I("hNCl", "Clusters per TRD track", 100, 0., 200.); + h->GetXaxis()->SetTitle("N_{cl}^{TRD}"); + h->GetYaxis()->SetTitle("entries"); + } else h->Reset(); + fHistos->AddAt(h, kNCl); + + // status bits histogram + if(!(h = (TH2I*)gROOT->FindObject("hTRDstat"))){ + h = new TH2I("hTRDstat", "TRD status bits", 100, 0., 20., kNbits, .5, kNbits+.5); + h->GetXaxis()->SetTitle("p_{T} [GeV/c]"); + h->GetYaxis()->SetTitle("status bits"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + fHistos->AddAt(h, kTRDstat); + + // energy loss + if(!(h = (TH2I*)gROOT->FindObject("hTRDmom"))){ + h = new TH2I("hTRDmom", "TRD energy loss", 100, -1., 2., 6, -0.5, 5.5); + h->GetXaxis()->SetTitle("p_{inner} - p_{ly} [GeV/c]"); + h->GetYaxis()->SetTitle("layer"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + fHistos->AddAt(h, kTRDmom); + + return fHistos; +} + +//____________________________________________________________________ +Bool_t AliTRDcheckESD::Load(const Char_t *filename, const Char_t *name) +{ +// Load data from performance file + + if(!TFile::Open(filename)){ + AliWarning(Form("Couldn't open file %s.", filename)); + return kFALSE; + } + TObjArray *o = 0x0; + if(!(o = (TObjArray*)gFile->Get(name ? name : GetName()))){ + AliWarning("Missing histogram container."); + return kFALSE; + } + fHistos = (TObjArray*)o->Clone(GetName()); + gFile->Close(); + return kTRUE; +} + +//_______________________________________________________ +Bool_t AliTRDcheckESD::PutTrendValue(const Char_t *name, Double_t val) +{ +// Dump trending value to default file + + if(!fgFile){ + fgFile = fopen("TRD.Performance.txt", "at"); + } + fprintf(fgFile, "%s_%s %f\n", GetName(), name, val); + return kTRUE; +} + +//____________________________________________________________________ +void AliTRDcheckESD::Terminate(Option_t *) +{ +// Steer post-processing + + + // geometrical efficiency + TH2I *h2 = (TH2I*)fHistos->At(kTRDstat); + TH1 *h1[2] = {0x0, 0x0}; + h1[0] = h2->ProjectionX("checkESDx0", kTPCout, kTPCout); + h1[1] = h2->ProjectionX("checkESDx1", kTRDin, kTRDin); + Process(h1, (TGraphErrors*)GetGraph(0)); + delete h1[0];delete h1[1]; + + // tracking efficiency + h1[0] = h2->ProjectionX("checkESDx0", kTRDin, kTRDin); + h1[1] = h2->ProjectionX("checkESDx1", kTRDout, kTRDout); + Process(h1, (TGraphErrors*)GetGraph(1)); + delete h1[1]; + + // PID efficiency + h1[1] = h2->ProjectionX("checkESDx1", kTRDpid, kTRDpid); + Process(h1, (TGraphErrors*)GetGraph(2)); + delete h1[1]; + + // Refit efficiency + h1[1] = h2->ProjectionX("checkESDx1", kTRDref, kTRDref); + Process(h1, (TGraphErrors*)GetGraph(3)); + delete h1[1]; + if(!(h2 = dynamic_cast(fHistos->At(kTRDmom)))) return; + + TGraphAsymmErrors *g06 = (TGraphAsymmErrors*)GetGraph(4), *g09 = (TGraphAsymmErrors*)GetGraph(5); + TAxis *ax=h2->GetXaxis(); + const Int_t nq(4); + const Double_t xq[nq] = {0.05, 0.2, 0.8, 0.95}; + Double_t yq[nq]; + for(Int_t ily=6; ily--;){ + h1[0] = h2->ProjectionX("checkESDp0", ily+1, ily+1); + h1[0]->GetQuantiles(nq,yq,xq); + g06->SetPoint(ily, Float_t(ily), ax->GetBinCenter(h1[0]->GetMaximumBin())); + g06->SetPointError(ily, 0., 0., TMath::Abs(yq[0]), yq[3]); + g09->SetPoint(ily, Float_t(ily), h1[0]->GetMean()); + g09->SetPointError(ily, 0., 0., TMath::Abs(yq[1]), yq[2]); + + //printf(" max[%f] mean[%f] q[%f %f %f %f]\n", ax->GetBinCenter(h1[0]->GetMaximumBin()), h1[0]->GetMean(), yq[0], yq[1], yq[2], yq[3]); + delete h1[0]; + } +} + +//____________________________________________________________________ +void AliTRDcheckESD::Process(TH1 **h1, TGraphErrors *g) +{ +// Generic function to process one reference plot + + Int_t n1 = 0, n2 = 0, ip=0; + Double_t eff = 0.; + + TAxis *ax = h1[0]->GetXaxis(); + for(Int_t ib=1; ib<=ax->GetNbins(); ib++){ + if(!(n1 = (Int_t)h1[0]->GetBinContent(ib))) continue; + n2 = (Int_t)h1[1]->GetBinContent(ib); + eff = n2/Float_t(n1); + + ip=g->GetN(); + g->SetPoint(ip, ax->GetBinCenter(ib), eff); + g->SetPointError(ip, 0., n2 ? eff*TMath::Sqrt(1./n1+1./n2) : 0.); + } +} + +//____________________________________________________________________ +void AliTRDcheckESD::PrintStatus(ULong_t status) +{ +// Dump track status to stdout + + printf("ITS[i(%d) o(%d) r(%d)] TPC[i(%d) o(%d) r(%d) p(%d)] TRD[i(%d) o(%d) r(%d) p(%d) s(%d)] HMPID[o(%d) p(%d)]\n" + ,Bool_t(status & AliESDtrack::kITSin) + ,Bool_t(status & AliESDtrack::kITSout) + ,Bool_t(status & AliESDtrack::kITSrefit) + ,Bool_t(status & AliESDtrack::kTPCin) + ,Bool_t(status & AliESDtrack::kTPCout) + ,Bool_t(status & AliESDtrack::kTPCrefit) + ,Bool_t(status & AliESDtrack::kTPCpid) + ,Bool_t(status & AliESDtrack::kTRDin) + ,Bool_t(status & AliESDtrack::kTRDout) + ,Bool_t(status & AliESDtrack::kTRDrefit) + ,Bool_t(status & AliESDtrack::kTRDpid) + ,Bool_t(status & AliESDtrack::kTRDStop) + ,Bool_t(status & AliESDtrack::kHMPIDout) + ,Bool_t(status & AliESDtrack::kHMPIDpid) + ); +} + diff --git a/PWG1/TRD/AliTRDcheckESD.h b/PWG1/TRD/AliTRDcheckESD.h new file mode 100644 index 00000000000..6dd999bdab0 --- /dev/null +++ b/PWG1/TRD/AliTRDcheckESD.h @@ -0,0 +1,79 @@ +#ifndef ALITRDCHECKESD_H +#define ALITRDCHECKESD_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/* $Id: AliTRDcheckESD.h 27496 2008-07-22 08:35:45Z cblume $ */ + +///////////////////////////////////////////////////// +// +// Check basic detector results at ESD level +// +// Author +// Alex Bercuci +// +////////////////////////////////////////////////////// + +#ifndef ALIANALYSISTASK_H +#include "AliAnalysisTask.h" +#endif + +class AliESDEvent; +class AliMCEvent; +class TH1; +class TObjArray; +class TGraph; +class TGraphErrors; +class AliTRDcheckESD : public AliAnalysisTask { +public: + enum ETRDcheckESDstatus { + kMC = BIT(0) + }; + enum ETRDcheckESDhistos { + kNCl = 0 // number of clusters per track + ,kTRDstat // TRD tracks status + ,kTRDmom // TRD track momentum + ,kNhistos = 3 // number of histograms + ,kNgraphs = 6 // number of graphs + }; + enum ETRDcheckESDbits { + kTPCout = 1 // track left TPC + ,kTRDin // track reach TRD fiducial volume + ,kTRDout // track reconstructed in TRD + ,kTRDpid // PID calculated in TRD + ,kTRDref // track refitted in TRD + ,kNbits = 5 // number of check bits + }; + AliTRDcheckESD(); + virtual ~AliTRDcheckESD(); + + void ConnectInputData(Option_t *); + void CreateOutputObjects(); + TGraph* GetGraph(Int_t id, Option_t *opt="bc"); + void Exec(Option_t *); + + Bool_t HasMC() const { return TESTBIT(fStatus, kMC);} + TObjArray* Histos(); + Bool_t Load(const Char_t *fn, const Char_t *name=0x0); + void SetMC(Bool_t mc = kTRUE) { mc ? SETBIT(fStatus, kMC) : CLRBIT(fStatus, kMC);} + Bool_t PutTrendValue(const Char_t *name, Double_t val); + void Terminate(Option_t *); + +private: + static const Float_t fgkxTPC; // end radial position of TPC + static const Float_t fgkxTOF; // start radial position of TOF + + AliTRDcheckESD(const AliTRDcheckESD&); + AliTRDcheckESD& operator=(const AliTRDcheckESD&); + void Process(TH1 **h, TGraphErrors *g); + void PrintStatus(ULong_t s); + + Int_t fStatus; // bit mask for controlling the task + AliESDEvent *fESD; // ESD event + AliMCEvent *fMC; // MC event + TObjArray *fHistos; // QA histos + TObjArray *fResults; // QA graphs + static FILE *fgFile; //! trend file streamer + ClassDef(AliTRDcheckESD, 3) // user oriented TRD analysis based on ESD-MC data +}; +#endif diff --git a/PWG1/TRD/AliTRDcheckPID.cxx b/PWG1/TRD/AliTRDcheckPID.cxx new file mode 100644 index 00000000000..389954e3c6d --- /dev/null +++ b/PWG1/TRD/AliTRDcheckPID.cxx @@ -0,0 +1,1075 @@ +////////////////////////////////////////////////////// +// +// PID performance checker of the TRD +// +// Performs checks of ESD information for TRD-PID and recalculate PID based on OCDB information +// Also provides performance plots on detector based on the PID information - for the moment only +// MC source is used but V0 is also possible. Here is a list of detector performance checks +// - Integrated dE/dx per chamber +// - as function of time bin and local radial position +// - number of clusters/tracklet +// - number of tracklets/track +// +// Author : Alex Wilk +// Alex Bercuci +// Markus Fasel +// +/////////////////////////////////////////////////////// + +#include "TAxis.h" +#include "TROOT.h" +#include "TPDGCode.h" +#include "TCanvas.h" +#include "TF1.h" +#include "TH1F.h" +#include "TH1D.h" +#include "TH2F.h" +#include "TProfile.h" +#include "TProfile2D.h" +#include "TGraph.h" +#include "TGraphErrors.h" +#include "TLegend.h" + +#include +#include +#include + +#include "AliESDEvent.h" +#include "AliESDInputHandler.h" +#include "AliTrackReference.h" + +#include "AliAnalysisTask.h" + +#include "AliTRDtrackerV1.h" +#include "AliTRDtrackV1.h" +#include "AliTRDcluster.h" +#include "AliTRDReconstructor.h" +#include "AliCDBManager.h" +#include "AliTRDpidUtil.h" + +#include "AliTRDcheckPID.h" +#include "info/AliTRDtrackInfo.h" + +ClassImp(AliTRDcheckPID) + +//________________________________________________________________________ +AliTRDcheckPID::AliTRDcheckPID() + :AliTRDrecoTask("checkPID", "TRD PID checker") + ,fReconstructor(0x0) + ,fUtil(0x0) + ,fGraph(0x0) + ,fEfficiency(0x0) + ,fMomentumAxis(0x0) + ,fMinNTracklets(AliTRDgeometry::kNlayer) + ,fMaxNTracklets(AliTRDgeometry::kNlayer) + { + // + // Default constructor + // + + fReconstructor = new AliTRDReconstructor(); + fReconstructor->SetRecoParam(AliTRDrecoParam::GetLowFluxParam()); + + // Initialize momentum axis with default values + Double_t defaultMomenta[AliTRDCalPID::kNMom+1]; + for(Int_t imom = 0; imom < AliTRDCalPID::kNMom+1; imom++) + defaultMomenta[imom] = AliTRDCalPID::GetMomentumBinning(imom); + SetMomentumBinning(AliTRDCalPID::kNMom, defaultMomenta); + + fUtil = new AliTRDpidUtil(); + InitFunctorList(); +} + + +//________________________________________________________________________ +AliTRDcheckPID::~AliTRDcheckPID() +{ + if(fGraph){fGraph->Delete(); delete fGraph;} + if(fReconstructor) delete fReconstructor; + if(fUtil) delete fUtil; +} + + +//________________________________________________________________________ +void AliTRDcheckPID::CreateOutputObjects() +{ + // Create histograms + // Called once + + OpenFile(0, "RECREATE"); + fContainer = Histos(); +} + + +//_______________________________________________________ +TObjArray * AliTRDcheckPID::Histos(){ + + // + // Create QA histograms + // + if(fContainer) return fContainer; + + Int_t xBins = AliPID::kSPECIES*fMomentumAxis->GetNbins(); + fContainer = new TObjArray(); fContainer->Expand(kNPlots); + + const Float_t epsilon = 1./(2*(AliTRDpidUtil::kBins-1)); // get nice histos with bin center at 0 and 1 + + // histos of the electron probability of all 5 particle species and 11 momenta for the 2-dim LQ method + fEfficiency = new TObjArray(3); + fEfficiency->SetOwner(); fEfficiency->SetName("Efficiency"); + fContainer->AddAt(fEfficiency, kEfficiency); + + TH1 *h = 0x0; + if(!(h = (TH2F*)gROOT->FindObject("PID_LQ"))){ + h = new TH2F("PID_LQ", "", xBins, -0.5, xBins - 0.5, + AliTRDpidUtil::kBins, 0.-epsilon, 1.+epsilon); + } else h->Reset(); + fEfficiency->AddAt(h, AliTRDpidUtil::kLQ); + + // histos of the electron probability of all 5 particle species and 11 momenta for the neural network method + if(!(h = (TH2F*)gROOT->FindObject("PID_NN"))){ + h = new TH2F("PID_NN", "", + xBins, -0.5, xBins - 0.5, + AliTRDpidUtil::kBins, 0.-epsilon, 1.+epsilon); + } else h->Reset(); + fEfficiency->AddAt(h, AliTRDpidUtil::kNN); + + // histos of the electron probability of all 5 particle species and 11 momenta for the ESD output + if(!(h = (TH2F*)gROOT->FindObject("PID_ESD"))){ + h = new TH2F("PID_ESD", "", + xBins, -0.5, xBins - 0.5, + AliTRDpidUtil::kBins, 0.-epsilon, 1.+epsilon); + } else h->Reset(); + fEfficiency->AddAt(h, AliTRDpidUtil::kESD); + + // histos of the dE/dx distribution for all 5 particle species and 11 momenta + if(!(h = (TH2F*)gROOT->FindObject("dEdx"))){ + h = new TH2F("dEdx", "", + xBins, -0.5, xBins - 0.5, + 200, 0, 10000); + } else h->Reset(); + fContainer->AddAt(h, kdEdx); + + // histos of the dE/dx slices for all 5 particle species and 11 momenta + if(!(h = (TH2F*)gROOT->FindObject("dEdxSlice"))){ + h = new TH2F("dEdxSlice", "", + xBins*AliTRDpidUtil::kLQslices, -0.5, xBins*AliTRDpidUtil::kLQslices - 0.5, + 200, 0, 5000); + } else h->Reset(); + fContainer->AddAt(h, kdEdxSlice); + + // histos of the pulse height distribution for all 5 particle species and 11 momenta + TObjArray *fPH = new TObjArray(2); + fPH->SetOwner(); fPH->SetName("PH"); + fContainer->AddAt(fPH, kPH); + if(!(h = (TProfile2D*)gROOT->FindObject("PHT"))){ + h = new TProfile2D("PHT", "", + xBins, -0.5, xBins - 0.5, + AliTRDtrackerV1::GetNTimeBins(), -0.5, AliTRDtrackerV1::GetNTimeBins() - 0.5); + } else h->Reset(); + fPH->AddAt(h, 0); + if(!(h = (TProfile2D*)gROOT->FindObject("PHX"))){ + h = new TProfile2D("PHX", "", + xBins, -0.5, xBins - 0.5, + AliTRDtrackerV1::GetNTimeBins(), 0., .5*AliTRDgeometry::CamHght()+AliTRDgeometry::CdrHght()); + } else h->Reset(); + fPH->AddAt(h, 1); + + // histos of the number of clusters distribution for all 5 particle species and 11 momenta + if(!(h = (TH2F*)gROOT->FindObject("NClus"))){ + h = new TH2F("NClus", "", + xBins, -0.5, xBins - 0.5, + 50, -0.5, 49.5); + } else h->Reset(); + fContainer->AddAt(h, kNClus); + + + // momentum distributions - absolute and in momentum bins + if(!(h = (TH1F*)gROOT->FindObject("hMom"))){ + h = new TH1F("hMom", "momentum distribution", fMomentumAxis->GetNbins(), fMomentumAxis->GetXmin(), fMomentumAxis->GetXmax()); + } else h->Reset(); + fContainer->AddAt(h, kMomentum); + + if(!(h = (TH1F*)gROOT->FindObject("hMomBin"))){ + h = new TH1F("hMomBin", "momentum distribution in momentum bins", fMomentumAxis->GetNbins(), fMomentumAxis->GetXmin(), fMomentumAxis->GetXmax()); + } else h->Reset(); + fContainer->AddAt(h, kMomentumBin); + + // Number of tracklets per track + if(!(h = (TH2F*)gROOT->FindObject("nTracklets"))){ + h = new TH2F("nTracklets", "", + xBins, -0.5, xBins - 0.5, + AliTRDgeometry::kNlayer, 0.5, AliTRDgeometry::kNlayer+.5); + } else h->Reset(); + fContainer->AddAt(h, kNTracklets); + + return fContainer; +} + + +//________________________________________________________________________ +Bool_t AliTRDcheckPID::CheckTrackQuality(const AliTRDtrackV1* track) const +{ + // + // Check if the track is ok for PID + // + + Int_t ntracklets = track->GetNumberOfTracklets(); + if(ntracklets >= fMinNTracklets && ntracklets <= fMaxNTracklets) return 1; +// if(!fESD) +// return 0; + + return 0; +} + +//________________________________________________________________________ +Int_t AliTRDcheckPID::CalcPDG(AliTRDtrackV1* track) +{ +// Documentation to come + + track -> SetReconstructor(fReconstructor); + (const_cast(fReconstructor->GetRecoParam()))->SetPIDNeuralNetwork(); + track -> CookPID(); + + if(track -> GetPID(AliPID::kElectron) > track -> GetPID(AliPID::kMuon) + track -> GetPID(AliPID::kPion) + track -> GetPID(AliPID::kKaon) + track -> GetPID(AliPID::kProton)){ + return kElectron; + } + else if(track -> GetPID(kProton) > track -> GetPID(AliPID::kPion) && track -> GetPID(AliPID::kProton) > track -> GetPID(AliPID::kKaon) && track -> GetPID(AliPID::kProton) > track -> GetPID(AliPID::kMuon)){ + return kProton; + } + else if(track -> GetPID(AliPID::kKaon) > track -> GetPID(AliPID::kMuon) && track -> GetPID(AliPID::kKaon) > track -> GetPID(AliPID::kPion)){ + return kKPlus; + } + else if(track -> GetPID(AliPID::kMuon) > track -> GetPID(AliPID::kPion)){ + return kMuonPlus; + } + else{ + return kPiPlus; + } +} + + +//_______________________________________________________ +TH1 *AliTRDcheckPID::PlotLQ(const AliTRDtrackV1 *track) +{ + // + // Plot the probabilities for electrons using 2-dim LQ + // + + if(!fkESD){ + AliWarning("No ESD info available."); + return 0x0; + } + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + + ULong_t status; + status = fkESD -> GetStatus(); + if(!(status&AliESDtrack::kTRDin)) return 0x0; + + if(!CheckTrackQuality(fkTrack)) return 0x0; + + if(!(fEfficiency = dynamic_cast(fContainer->At(kEfficiency)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + TH2F *hPIDLQ = 0x0; + if(!(hPIDLQ = dynamic_cast(fEfficiency->At(AliTRDpidUtil::kLQ)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + AliTRDtrackV1 cTrack(*fkTrack); + cTrack.SetReconstructor(fReconstructor); + + Int_t pdg = 0; + Float_t momentum = 0.; + + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } else{ + //AliWarning("No MC info available!"); + momentum = cTrack.GetMomentum(0); + pdg = CalcPDG(&cTrack); + } + if(!IsInRange(momentum)) return 0x0; + + (const_cast(fReconstructor->GetRecoParam()))->SetPIDNeuralNetwork(kFALSE); + cTrack.CookPID(); + if(cTrack.GetNumberOfTrackletsPID() < fMinNTracklets) return 0x0; + + Int_t species = AliTRDpidUtil::Pdg2Pid(pdg); + hPIDLQ -> Fill(FindBin(species, momentum), cTrack.GetPID(AliPID::kElectron)); + return hPIDLQ; +} + + +//_______________________________________________________ +TH1 *AliTRDcheckPID::PlotNN(const AliTRDtrackV1 *track) +{ + // + // Plot the probabilities for electrons using 2-dim LQ + // + + if(!fkESD){ + AliWarning("No ESD info available."); + return 0x0; + } + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + + ULong_t status; + status = fkESD -> GetStatus(); + if(!(status&AliESDtrack::kTRDin)) return 0x0; + + if(!CheckTrackQuality(fkTrack)) return 0x0; + + if(!(fEfficiency = dynamic_cast(fContainer->At(kEfficiency)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + TH2F *hPIDNN; + if(!(hPIDNN = dynamic_cast(fEfficiency->At(AliTRDpidUtil::kNN)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + AliTRDtrackV1 cTrack(*fkTrack); + cTrack.SetReconstructor(fReconstructor); + + Int_t pdg = 0; + Float_t momentum = 0.; + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } else { + //AliWarning("No MC info available!"); + momentum = cTrack.GetMomentum(0); + pdg = CalcPDG(&cTrack); + } + if(!IsInRange(momentum)) return 0x0; + + (const_cast(fReconstructor->GetRecoParam()))->SetPIDNeuralNetwork(); + cTrack.CookPID(); + if(cTrack.GetNumberOfTrackletsPID() < fMinNTracklets) return 0x0; + + Int_t species = AliTRDpidUtil::Pdg2Pid(pdg); + hPIDNN -> Fill(FindBin(species, momentum), cTrack.GetPID(AliPID::kElectron)); + return hPIDNN; +} + + +//_______________________________________________________ +TH1 *AliTRDcheckPID::PlotESD(const AliTRDtrackV1 *track) +{ + // + // Plot the probabilities for electrons using 2-dim LQ + // + + if(!fkESD){ + AliWarning("No ESD info available."); + return 0x0; + } + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + + ULong_t status; + status = fkESD -> GetStatus(); + if(!(status&AliESDtrack::kTRDin)) return 0x0; + + if(!CheckTrackQuality(fkTrack)) return 0x0; + if(fkTrack->GetNumberOfTrackletsPID() < fMinNTracklets) return 0x0; + + if(!(fEfficiency = dynamic_cast(fContainer->At(kEfficiency)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + TH2F *hPIDESD = 0x0; + if(!(hPIDESD = dynamic_cast(fEfficiency->At(AliTRDpidUtil::kESD)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + + Int_t pdg = 0; + Float_t momentum = 0.; + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } else { + //AliWarning("No MC info available!"); + AliTRDtrackV1 cTrack(*fkTrack); + cTrack.SetReconstructor(fReconstructor); + momentum = cTrack.GetMomentum(0); + pdg = CalcPDG(&cTrack); + } + if(!IsInRange(momentum)) return 0x0; + +// Double32_t pidESD[AliPID::kSPECIES]; + const Double32_t *pidESD = fkESD->GetResponseIter(); + Int_t species = AliTRDpidUtil::Pdg2Pid(pdg); + hPIDESD -> Fill(FindBin(species, momentum), pidESD[0]); + return hPIDESD; +} + + +//_______________________________________________________ +TH1 *AliTRDcheckPID::PlotdEdx(const AliTRDtrackV1 *track) +{ + // + // Plot the probabilities for electrons using 2-dim LQ + // + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + + if(!CheckTrackQuality(fkTrack)) return 0x0; + + TH2F *hdEdx; + if(!(hdEdx = dynamic_cast(fContainer->At(kdEdx)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + AliTRDtrackV1 cTrack(*fkTrack); + cTrack.SetReconstructor(fReconstructor); + Int_t pdg = 0; + Float_t momentum = 0.; + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } else { + //AliWarning("No MC info available!"); + momentum = cTrack.GetMomentum(0); + pdg = CalcPDG(&cTrack); + } + Int_t species = AliTRDpidUtil::Pdg2Pid(pdg); + if(!IsInRange(momentum)) return 0x0; + + (const_cast(fReconstructor->GetRecoParam()))->SetPIDNeuralNetwork(kFALSE); + Float_t sumdEdx = 0; + Int_t iBin = FindBin(species, momentum); + AliTRDseedV1 *tracklet = 0x0; + for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){ + sumdEdx = 0; + tracklet = cTrack.GetTracklet(iChamb); + if(!tracklet) continue; + tracklet -> CookdEdx(AliTRDpidUtil::kLQslices); + for(Int_t i = 3; i--;) sumdEdx += tracklet->GetdEdx()[i]; + hdEdx -> Fill(iBin, sumdEdx); + } + return hdEdx; +} + + +//_______________________________________________________ +TH1 *AliTRDcheckPID::PlotdEdxSlice(const AliTRDtrackV1 *track) +{ + // + // Plot the probabilities for electrons using 2-dim LQ + // + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + + if(!CheckTrackQuality(fkTrack)) return 0x0; + + TH2F *hdEdxSlice; + if(!(hdEdxSlice = dynamic_cast(fContainer->At(kdEdxSlice)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + AliTRDtrackV1 cTrack(*fkTrack); + cTrack.SetReconstructor(fReconstructor); + Int_t pdg = 0; + Float_t momentum = 0.; + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } else { + //AliWarning("No MC info available!"); + momentum = cTrack.GetMomentum(0); + pdg = CalcPDG(&cTrack); + } + if(!IsInRange(momentum)) return 0x0; + + (const_cast(fReconstructor->GetRecoParam()))->SetPIDNeuralNetwork(kFALSE); + Int_t iMomBin = fMomentumAxis->FindBin(momentum); + Int_t species = AliTRDpidUtil::Pdg2Pid(pdg); + Float_t *fdEdx; + AliTRDseedV1 *tracklet = 0x0; + for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){ + tracklet = cTrack.GetTracklet(iChamb); + if(!tracklet) continue; + tracklet -> CookdEdx(AliTRDpidUtil::kLQslices); + fdEdx = const_cast(tracklet->GetdEdx()); + for(Int_t iSlice = 0; iSlice < AliTRDpidUtil::kLQslices; iSlice++){ + hdEdxSlice -> Fill(species * fMomentumAxis->GetNbins() * AliTRDpidUtil::kLQslices + (iMomBin-1) * AliTRDpidUtil::kLQslices + iSlice, fdEdx[iSlice]); + } + } + + return hdEdxSlice; +} + + +//_______________________________________________________ +TH1 *AliTRDcheckPID::PlotPH(const AliTRDtrackV1 *track) +{ + // + // Plot the probabilities for electrons using 2-dim LQ + // + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + + if(!CheckTrackQuality(fkTrack)) return 0x0; + + TObjArray *arr = 0x0; + TProfile2D *hPHX, *hPHT; + if(!(arr = dynamic_cast(fContainer->At(kPH)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + hPHT = (TProfile2D*)arr->At(0); + hPHX = (TProfile2D*)arr->At(1); + + Int_t pdg = 0; + Float_t momentum = 0.; + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } else { + //AliWarning("No MC info available!"); + AliTRDtrackV1 cTrack(*fkTrack); + cTrack.SetReconstructor(fReconstructor); + momentum = cTrack.GetMomentum(0); + pdg = CalcPDG(&cTrack); + } + if(!IsInRange(momentum)) return 0x0;; + + AliTRDseedV1 *tracklet = 0x0; + AliTRDcluster *cluster = 0x0; + Int_t species = AliTRDpidUtil::Pdg2Pid(pdg); + Int_t iBin = FindBin(species, momentum); + for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){ + tracklet = fkTrack->GetTracklet(iChamb); + if(!tracklet) continue; + Float_t x0 = tracklet->GetX0(); + for(Int_t ic = 0; ic < AliTRDtrackerV1::GetNTimeBins(); ic++){ + if(!(cluster = tracklet->GetClusters(ic))) continue; + hPHT -> Fill(iBin, cluster->GetLocalTimeBin(), TMath::Abs(cluster->GetQ())); + hPHX -> Fill(iBin, x0 - cluster->GetX(), tracklet->GetdQdl(ic)); + } + } + return hPHT; +} + + +//_______________________________________________________ +TH1 *AliTRDcheckPID::PlotNClus(const AliTRDtrackV1 *track) +{ + // + // Plot the probabilities for electrons using 2-dim LQ + // + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + + if(!CheckTrackQuality(fkTrack)) return 0x0; + + TH2F *hNClus; + if(!(hNClus = dynamic_cast(fContainer->At(kNClus)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + + Int_t pdg = 0; + Float_t momentum = 0.; + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } else { + //AliWarning("No MC info available!"); + AliTRDtrackV1 cTrack(*fkTrack); + cTrack.SetReconstructor(fReconstructor); + momentum = cTrack.GetMomentum(0); + pdg = CalcPDG(&cTrack); + } + if(!IsInRange(momentum)) return 0x0; + + Int_t species = AliTRDpidUtil::AliTRDpidUtil::Pdg2Pid(pdg); + Int_t iBin = FindBin(species, momentum); + AliTRDseedV1 *tracklet = 0x0; + for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){ + tracklet = fkTrack->GetTracklet(iChamb); + if(!tracklet) continue; + hNClus -> Fill(iBin, tracklet->GetN()); + } + + return hNClus; +} + +//_______________________________________________________ +TH1 *AliTRDcheckPID::PlotNTracklets(const AliTRDtrackV1 *track) +{ + // + // Plot the probabilities for electrons using 2-dim LQ + // + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + + TH2F *hTracklets; + if(!(hTracklets = dynamic_cast(fContainer->At(kNTracklets)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + AliTRDtrackV1 cTrack(*fkTrack); + cTrack.SetReconstructor(fReconstructor); + Int_t pdg = 0; + Float_t momentum = 0.; + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } else { + //AliWarning("No MC info available!"); + momentum = cTrack.GetMomentum(0); + pdg = CalcPDG(&cTrack); + } + Int_t species = AliTRDpidUtil::Pdg2Pid(pdg); + if(!IsInRange(momentum)) return 0x0; + + Int_t iBin = FindBin(species, momentum); + hTracklets -> Fill(iBin, cTrack.GetNumberOfTracklets()); + return hTracklets; +} + +//_______________________________________________________ +TH1 *AliTRDcheckPID::PlotMom(const AliTRDtrackV1 *track) +{ + // + // Plot the probabilities for electrons using 2-dim LQ + // + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + + if(!CheckTrackQuality(fkTrack)) return 0x0; + + TH1F *hMom; + if(!(hMom = dynamic_cast(fContainer->At(kMomentum)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + + Int_t pdg = 0; + Float_t momentum = 0.; + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } else { + //AliWarning("No MC info available!"); + AliTRDtrackV1 cTrack(*fkTrack); + cTrack.SetReconstructor(fReconstructor); + momentum = cTrack.GetMomentum(0); + pdg = CalcPDG(&cTrack); + } + if(IsInRange(momentum)) hMom -> Fill(momentum); + return hMom; +} + + +//_______________________________________________________ +TH1 *AliTRDcheckPID::PlotMomBin(const AliTRDtrackV1 *track) +{ + // + // Plot the probabilities for electrons using 2-dim LQ + // + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + + if(!CheckTrackQuality(fkTrack)) return 0x0; + + TH1F *hMomBin; + if(!(hMomBin = dynamic_cast(fContainer->At(kMomentumBin)))){ + AliWarning("No Histogram defined."); + return 0x0; + } + + + Int_t pdg = 0; + Float_t momentum = 0.; + + if(fkMC){ + if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P(); + pdg = fkMC->GetPDG(); + } else { + //AliWarning("No MC info available!"); + AliTRDtrackV1 cTrack(*fkTrack); + cTrack.SetReconstructor(fReconstructor); + momentum = cTrack.GetMomentum(0); + } + if(IsInRange(momentum)) hMomBin -> Fill(fMomentumAxis->FindBin(momentum)); + return hMomBin; +} + + +//________________________________________________________ +Bool_t AliTRDcheckPID::GetRefFigure(Int_t ifig) +{ +// Steering function to retrieve performance plots + + Bool_t kFIRST = kTRUE; + TGraphErrors *g = 0x0; + TAxis *ax = 0x0; + TObjArray *arr = 0x0; + TH1 *h1 = 0x0, *h=0x0; + TH2 *h2 = 0x0; + TList *content = 0x0; + switch(ifig){ + case kEfficiency:{ + gPad->Divide(2, 1, 1.e-5, 1.e-5); + TList *l=gPad->GetListOfPrimitives(); + TVirtualPad *pad = ((TVirtualPad*)l->At(0));pad->cd(); + pad->SetMargin(0.1, 0.01, 0.1, 0.01); + + TLegend *legEff = new TLegend(.65, .75, .98, .98); + legEff->SetBorderSize(1); + legEff->SetFillColor(0); + h=new TH1S("hEff", "", 1, .5, 11.); + h->SetLineColor(1);h->SetLineWidth(1); + ax = h->GetXaxis(); + ax->SetTitle("p [GeV/c]"); + ax->SetRangeUser(.5, 11.); + ax->SetMoreLogLabels(); + ax = h->GetYaxis(); + ax->SetTitle("#epsilon_{#pi} [%]"); + ax->CenterTitle(); + ax->SetRangeUser(1.e-2, 10.); + h->Draw(); + content = (TList *)fGraph->FindObject("Efficiencies"); + if(!(g = (TGraphErrors*)content->At(AliTRDpidUtil::kLQ))) break; + if(!g->GetN()) break; + legEff->SetHeader("PID Source"); + g->Draw("pc"); legEff->AddEntry(g, "LQ 2D", "pl"); + if(! (g = (TGraphErrors*)content->At(AliTRDpidUtil::kNN))) break; + g->Draw("pc"); legEff->AddEntry(g, "NN", "pl"); + if(! (g = (TGraphErrors*)content->At(AliTRDpidUtil::kESD))) break; + g->Draw("p"); legEff->AddEntry(g, "ESD", "pl"); + legEff->Draw(); + gPad->SetLogy(); + gPad->SetLogx(); + gPad->SetGridy(); + gPad->SetGridx(); + + pad = ((TVirtualPad*)l->At(1));pad->cd(); + pad->SetMargin(0.1, 0.01, 0.1, 0.01); + h=new TH1S("hThr", "", 1, .5, 11.); + h->SetLineColor(1);h->SetLineWidth(1); + ax = h->GetXaxis(); + ax->SetTitle("p [GeV/c]"); + ax->SetMoreLogLabels(); + ax = h->GetYaxis(); + ax->SetTitle("Threshold [%]"); + ax->SetRangeUser(5.e-2, 1.); + h->Draw(); + content = (TList *)fGraph->FindObject("Thresholds"); + if(!(g = (TGraphErrors*)content->At(AliTRDpidUtil::kLQ))) break; + if(!g->GetN()) break; + g->Draw("pc"); + if(!(g = (TGraphErrors*)content->At(AliTRDpidUtil::kNN))) break; + g->Draw("pc"); + if(!(g = (TGraphErrors*)content->At(AliTRDpidUtil::kESD))) break; + g->Draw("p"); + gPad->SetLogx(); + gPad->SetGridy(); + gPad->SetGridx(); + return kTRUE; + } + case kdEdx:{ + // save 2.0 GeV projection as reference + TLegend *legdEdx = new TLegend(.7, .7, .98, .98); + legdEdx->SetBorderSize(1); + kFIRST = kTRUE; + if(!(h2 = (TH2F*)(fContainer->At(kdEdx)))) break; + legdEdx->SetHeader("Particle Species"); + gPad->SetMargin(0.1, 0.01, 0.1, 0.01); + for(Int_t is = AliPID::kSPECIES-1; is>=0; is--){ + Int_t bin = FindBin(is, 2.); + h1 = h2->ProjectionY(Form("px%d", is), bin, bin); + if(!h1->GetEntries()) continue; + h1->Scale(1./h1->Integral()); + h1->SetLineColor(AliTRDCalPID::GetPartColor(is)); + if(kFIRST){ + h1->GetXaxis()->SetTitle("dE/dx (a.u.)"); + h1->GetYaxis()->SetTitle(""); + } + h = (TH1F*)h1->DrawClone(kFIRST ? "c" : "samec"); + legdEdx->AddEntry(h, Form("%s", AliTRDCalPID::GetPartName(is)), "l"); + kFIRST = kFALSE; + } + if(kFIRST) break; + legdEdx->Draw(); + gPad->SetLogy(); + gPad->SetLogx(0); + gPad->SetGridy(); + gPad->SetGridx(); + return kTRUE; + } + case kdEdxSlice: + break; + case kPH:{ + gPad->Divide(2, 1, 1.e-5, 1.e-5); + TList *l=gPad->GetListOfPrimitives(); + + // save 2.0 GeV projection as reference + TLegend *legPH = new TLegend(.4, .7, .68, .98); + legPH->SetBorderSize(1);legPH->SetFillColor(0); + legPH->SetHeader("Particle Species"); + if(!(arr = (TObjArray*)(fContainer->At(kPH)))) break; + if(!(h2 = (TProfile2D*)(arr->At(0)))) break; + + TVirtualPad *pad = ((TVirtualPad*)l->At(0));pad->cd(); + pad->SetMargin(0.1, 0.01, 0.1, 0.01); + kFIRST = kTRUE; + for(Int_t is=0; isProjectionY(Form("pyt%d", is), bin, bin); + if(!h1->GetEntries()) continue; + h1->SetMarkerStyle(24); + h1->SetMarkerColor(AliTRDCalPID::GetPartColor(is)); + h1->SetLineColor(AliTRDCalPID::GetPartColor(is)); + if(kFIRST){ + h1->GetXaxis()->SetTitle("t_{drift} [100*ns]"); + h1->GetYaxis()->SetTitle(" [a.u.]"); + } + h = (TH1F*)h1->DrawClone(kFIRST ? "c" : "samec"); + legPH->AddEntry(h, Form("%s", AliTRDCalPID::GetPartName(is)), "pl"); + kFIRST = kFALSE; + } + + pad = ((TVirtualPad*)l->At(1));pad->cd(); + pad->SetMargin(0.1, 0.01, 0.1, 0.01); + if(!(h2 = (TProfile2D*)(arr->At(1)))) break; + kFIRST = kTRUE; + for(Int_t is=0; isProjectionY(Form("pyx%d", is), bin, bin); + if(!h1->GetEntries()) continue; + h1->SetMarkerStyle(24); + h1->SetMarkerColor(AliTRDCalPID::GetPartColor(is)); + h1->SetLineColor(AliTRDCalPID::GetPartColor(is)); + if(kFIRST){ + h1->GetXaxis()->SetTitle("x_{drift} [cm]"); + h1->GetYaxis()->SetTitle(" [a.u./cm]"); + } + h = (TH1F*)h1->DrawClone(kFIRST ? "c" : "samec"); + kFIRST = kFALSE; + } + + if(kFIRST) break; + legPH->Draw(); + gPad->SetLogy(0); + gPad->SetLogx(0); + gPad->SetGridy(); + gPad->SetGridx(); + return kTRUE; + } + case kNClus:{ + // save 2.0 GeV projection as reference + TLegend *legNClus = new TLegend(.13, .7, .4, .98); + legNClus->SetBorderSize(1); + legNClus->SetFillColor(0); + + kFIRST = kTRUE; + if(!(h2 = (TH2F*)(fContainer->At(kNClus)))) break; + legNClus->SetHeader("Particle Species"); + for(Int_t is=0; isProjectionY(Form("pyNClus%d", is), bin, bin); + if(!h1->GetEntries()) continue; + h1->Scale(100./h1->Integral()); + //h1->SetMarkerStyle(24); + //h1->SetMarkerColor(AliTRDCalPID::GetPartColor(is)); + h1->SetLineColor(AliTRDCalPID::GetPartColor(is)); + if(kFIRST){ + h1->GetXaxis()->SetTitle("N^{cl}/tracklet"); + h1->GetYaxis()->SetTitle("Prob. [%]"); + h = (TH1F*)h1->DrawClone("c"); + h->SetMaximum(55.); + h->GetXaxis()->SetRangeUser(0., 35.); + kFIRST = kFALSE; + } else h = (TH1F*)h1->DrawClone("samec"); + + legNClus->AddEntry(h, Form("%s", AliTRDCalPID::GetPartName(is)), "l"); + } + if(kFIRST) break; + legNClus->Draw(); + gPad->SetLogy(0); + gPad->SetLogx(0); + gPad->SetGridy(); + gPad->SetGridx(); + return kTRUE; + } + case kMomentum: + case kMomentumBin: + break; + case kNTracklets:{ + TLegend *legNClus = new TLegend(.4, .7, .68, .98); + legNClus->SetBorderSize(1); + kFIRST = kTRUE; + if(!(h2 = (TH2F*)(fContainer->At(kNTracklets)))) break; + legNClus->SetHeader("Particle Species"); + for(Int_t is=0; isProjectionY(Form("pyNTracklets%d", is), bin, bin); + if(!h1->GetEntries()) continue; + h1->Scale(100./h1->Integral()); + //h1->SetMarkerStyle(24); + //h1->SetMarkerColor(AliTRDCalPID::GetPartColor(is)); + h1->SetLineColor(AliTRDCalPID::GetPartColor(is)); + if(kFIRST){ + h1->GetXaxis()->SetTitle("N^{trklt}/track"); + h1->GetXaxis()->SetRangeUser(1.,6.); + h1->GetYaxis()->SetTitle("Prob. [%]"); + } + h = (TH1F*)h1->DrawClone(kFIRST ? "c" : "samec"); + legNClus->AddEntry(h, Form("%s", AliTRDCalPID::GetPartName(is)), "l"); + kFIRST = kFALSE; + } + if(kFIRST) break; + legNClus->Draw(); + gPad->SetLogy(0); + gPad->SetLogx(0); + gPad->SetGridy(); + gPad->SetGridx(); + return kTRUE; + } + } + AliInfo(Form("Reference plot [%d] missing result", ifig)); + return kFALSE; +} + +//________________________________________________________________________ +Bool_t AliTRDcheckPID::PostProcess() +{ + // Draw result to the screen + // Called once at the end of the query + + if (!fContainer) { + Printf("ERROR: list not available"); + return kFALSE; + } + if(!(fEfficiency = dynamic_cast(fContainer->At(kEfficiency)))){ + AliError("Efficiency container missing."); + return 0x0; + } + if(!fGraph){ + fGraph = new TObjArray(6); + fGraph->SetOwner(); + EvaluatePionEfficiency(fEfficiency, fGraph, 0.9); + } + fNRefFigures = 9; + return kTRUE; +} + +//________________________________________________________________________ +void AliTRDcheckPID::EvaluatePionEfficiency(TObjArray * const histoContainer, TObjArray *results, Float_t electronEfficiency){ +// Process PID information for pion efficiency + + fUtil->SetElectronEfficiency(electronEfficiency); + + Color_t colors[3] = {kBlue, kGreen+2, kRed}; + Int_t markerStyle[3] = {7, 7, 24}; + TString methodName[3] = {"LQ", "NN", "ESD"}; + // efficiency graphs + TGraphErrors *g, *gPtrEff[3], *gPtrThres[3]; + TObjArray *eff = new TObjArray(3); eff->SetOwner(); eff->SetName("Efficiencies"); + results->AddAt(eff, 0); + for(Int_t iMethod = 0; iMethod < 3; iMethod++){ + eff->AddAt(g = gPtrEff[iMethod] = new TGraphErrors(), iMethod); + g->SetName(Form("efficiency_%s", methodName[iMethod].Data())); + g->SetLineColor(colors[iMethod]); + g->SetMarkerColor(colors[iMethod]); + g->SetMarkerStyle(markerStyle[iMethod]); + } + + // Threshold graphs + TObjArray *thres = new TObjArray(3); thres->SetOwner(); thres->SetName("Thresholds"); + results->AddAt(thres, 1); + for(Int_t iMethod = 0; iMethod < 3; iMethod++){ + thres->AddAt(g = gPtrThres[iMethod] = new TGraphErrors(), iMethod); + g->SetName(Form("threshold_%s", methodName[iMethod].Data())); + g->SetLineColor(colors[iMethod]); + g->SetMarkerColor(colors[iMethod]); + g->SetMarkerStyle(markerStyle[iMethod]); + } + + Float_t mom = 0.; + TH1D *histo1=0x0, *histo2=0x0; + + TH2F *hPtr[3]; + hPtr[0] = (TH2F*)histoContainer->At(AliTRDpidUtil::kLQ); + hPtr[1] = (TH2F*)histoContainer->At(AliTRDpidUtil::kNN); + hPtr[2] = (TH2F*)histoContainer->At(AliTRDpidUtil::kESD); + + for(Int_t iMom = 0; iMom < fMomentumAxis->GetNbins(); iMom++){ + mom = fMomentumAxis->GetBinCenter(iMom+1); + + Int_t binEl = fMomentumAxis->GetNbins() * AliPID::kElectron + iMom + 1, + binPi = fMomentumAxis->GetNbins() * AliPID::kPion + iMom + 1; + for(Int_t iMethod = 0; iMethod < 3; iMethod++){ + // Calculate the Pion Efficiency at 90% electron efficiency for each Method + histo1 = hPtr[iMethod] -> ProjectionY(Form("%s_ele", methodName[iMethod].Data()), binEl, binEl); + histo2 = hPtr[iMethod] -> ProjectionY(Form("%s_pio", methodName[iMethod].Data()), binPi, binPi); + + if(!fUtil->CalculatePionEffi(histo1, histo2)) continue; + + gPtrEff[iMethod]->SetPoint(iMom, mom, 1.e2*fUtil->GetPionEfficiency()); + gPtrEff[iMethod]->SetPointError(iMom, 0., 1.e2*fUtil->GetError()); + gPtrThres[iMethod]->SetPoint(iMom, mom, fUtil->GetThreshold()); + gPtrThres[iMethod]->SetPointError(iMom, 0., 0.); + + AliDebug(2, Form("Pion Efficiency for %s is : %f +/- %f", methodName[iMethod].Data(), fUtil->GetPionEfficiency(), fUtil->GetError())); + } + } +} diff --git a/PWG1/TRD/AliTRDcheckPID.h b/PWG1/TRD/AliTRDcheckPID.h new file mode 100644 index 00000000000..d1f9eb373f6 --- /dev/null +++ b/PWG1/TRD/AliTRDcheckPID.h @@ -0,0 +1,110 @@ +#ifndef ALITRDCHECKPID_H +#define ALITRDCHECKPID_H + +////////////////////////////////////////////////////// +// +// PID performance checker of the TRD +// +// Author : Alex Wilk +// Alex Bercuci +// Markus Fasel +// +/////////////////////////////////////////////////////// + +#ifndef ROOT_TAxis +#include "TAxis.h" +#endif + +#ifndef ALITRDRECOTASK_H +#include "AliTRDrecoTask.h" +#endif + +class AliTRDReconstructor; +class AliTRDpidUtil; +class AliTRDcheckPID : public AliTRDrecoTask +{ +public: + // Plots registered for this task + enum{ + kEfficiency = 0 // pi Efficiency plot + ,kdEdx = 1 // dE/dx spectra + ,kdEdxSlice = 2 // dE/dx spectra + ,kPH = 3 // pulse height spectra + ,kNClus = 4 // number of clusters per track + ,kMomentum = 5 // momentum distribution + ,kMomentumBin = 6 // momentum distribution + ,kNTracklets = 7 // Number of tracklets per track + ,kNPlots = 8 // Number of plots for this tasks + }; + AliTRDcheckPID(); + virtual ~AliTRDcheckPID(); + + virtual void CreateOutputObjects(); + virtual Bool_t GetRefFigure(Int_t ifig); + virtual Bool_t PostProcess(); + + TH1 *PlotLQ(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotNN(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotESD(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotdEdx(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotdEdxSlice(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotPH(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotNClus(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotNTracklets(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotMom(const AliTRDtrackV1 *track = 0x0); + TH1 *PlotMomBin(const AliTRDtrackV1 *track = 0x0); + + void SetRequireMinNTracklets(Int_t mintracklets) { fMinNTracklets = mintracklets; } + void SetRequireMaxNTracklets(Int_t maxtracklets) { fMaxNTracklets = maxtracklets; } + + TObjArray *GetGraphs() const { return fGraph; }; + //TObjArray *GetHistos() { return fContainer; }; + virtual TObjArray *Histos(); + void EvaluatePionEfficiency(TObjArray * const histoContainer, TObjArray *results, Float_t electronEfficiency); + inline void SetMomentumBinning(Int_t nBins, Double_t *bins); + inline Int_t FindBin(Int_t species, Double_t momentum); + inline Bool_t IsInRange(Double_t momentum); + +private: + AliTRDcheckPID(const AliTRDcheckPID&); // not implemented + AliTRDcheckPID& operator=(const AliTRDcheckPID&); // not implemented + + Int_t CalcPDG(AliTRDtrackV1* track = 0x0); + Bool_t CheckTrackQuality(const AliTRDtrackV1* track = 0x0) const; + + AliTRDReconstructor *fReconstructor; //! reconstructor needed for recalculation the PID + AliTRDpidUtil *fUtil; //! utility class for PID calculations + TObjArray *fGraph; //! array of graphs filled in PostProcess + TObjArray *fEfficiency; //! array of histograms with efficiency + TAxis *fMomentumAxis; //! helper mementum binning + Int_t fMinNTracklets; // minimum number of required Tracklets (for systematic studies) + Int_t fMaxNTracklets; // maximum number of required Tracklets (for systematic studies) + ClassDef(AliTRDcheckPID, 1); // TRD PID checker +}; + +//________________________________________________________________________ +inline void AliTRDcheckPID::SetMomentumBinning(Int_t nBins, Double_t *bins){ + // + // Set the Momentum Bins + // + if(fMomentumAxis) delete fMomentumAxis; + fMomentumAxis = new TAxis(nBins, bins); +} + +//________________________________________________________________________ +inline Int_t AliTRDcheckPID::FindBin(Int_t species, Double_t momentum){ + // + // Find the Bin in the 2D Histogram + // + return species * fMomentumAxis->GetNbins() + (fMomentumAxis->FindBin(momentum) -1); +} + +//________________________________________________________________________ +inline Bool_t AliTRDcheckPID::IsInRange(Double_t momentum){ + // + // Check Whether momentum is in the defined Range + // + return (momentum >= fMomentumAxis->GetXmin() && momentum <= fMomentumAxis->GetXmax()); +} + +#endif diff --git a/PWG1/TRD/AliTRDclusterResolution.cxx b/PWG1/TRD/AliTRDclusterResolution.cxx new file mode 100644 index 00000000000..fc8d264396f --- /dev/null +++ b/PWG1/TRD/AliTRDclusterResolution.cxx @@ -0,0 +1,1225 @@ +/************************************************************************** +* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* * +* Author: The ALICE Off-line Project. * +* Contributors are mentioned in the code where appropriate. * +* * +* Permission to use, copy, modify and distribute this software and its * +* documentation strictly for non-commercialf purposes is hereby granted * +* without fee, provided that the above copyright notice appears in all * +* copies and that both the copyright notice and this permission notice * +* appear in the supporting documentation. The authors make no claims * +* about the suitability of this software for any purpose. It is * +* provided "as is" without express or implied warranty. * +**************************************************************************/ + +/* $Id: AliTRDclusterResolution.cxx */ + +/////////////////////////////////////////////////////////////////////////////// +// // +// TRD cluster error parameterization // +// // +// This class is designed to produce the reference plots for a detailed study// +// and parameterization of TRD cluster errors. The following effects are taken// +// into account : // +// - dependence with the total charge of the cluster // +// - dependence with the distance from the center pad. This is monitored +// for each layer individually since the pad size varies with layer +// - dependence with the drift length - here the influence of anisochronity +// and diffusion are searched +// - dependence with the distance to the anode wire - anisochronity effects +// - dependence with track angle (for y resolution) +// The correlation between effects is taken into account. +// +// Since magnetic field plays a very important role in the TRD measurement +// the ExB correction is forced by the setter function SetExB(Int_t). The +// argument is the detector index, if none is specified all will be +// considered. +// +// Two cases are of big importance. +// - comparison with MC +// - comparison with Kalman fit. In this case the covariance matrix of the +// Kalman fit are needed. +// +// The functionalities implemented in this class are based on the storage +// class AliTRDclusterInfo. +// +// The Method +// ---------- +// +// The method to disentangle s_y and s_x is based on the relation (see also fig.) +// BEGIN_LATEX +// #sigma^{2} = #sigma^{2}_{y} + tg^{2}(#alpha_{L})*#sigma^{2}_{x_{d}} + tg^{2}(#phi-#alpha_{L})*(#sigma^{2}_{x_{d}}+#sigma^{2}_{x_{c}}) +// END_LATEX +// with +// BEGIN_LATEX +// #sigma^{2}_{x_{c}} #approx 0 +// END_LATEX +// we suppose the chamber is well calibrated for t_{0} and aligned in +// radial direction. +// +// Clusters can be radially shifted due to three causes: +// - globally shifted - due to residual misalignment/miscalibration(t0) +// - locally shifted - due to different local drift velocity from the mean +// - randomly shifted - due to neighboring (radial direction) clusters +// charge induced by asymmetry of the TRF. +// +// We estimate this effects by the relations: +// BEGIN_LATEX +// #mu_{y} = tg(#alpha_{L})*#Delta x_{d}(...) + tg(#phi-#alpha_{L})*(#Delta x_{c}(...) + #Delta x_{d}(...)) +// END_LATEX +// where +// BEGIN_LATEX +// #Delta x_{d}(...) = ( + #delta v_{d}(x_{d}, d)) * (t + t^{*}(Q)) +// END_LATEX +// and we specified explicitely the variation of drift velocity parallel +// with the track (x_{d}) and perpendicular to it due to anisochronity (d). +// +// For estimating the contribution from asymmetry of TRF the following +// parameterization is being used +// BEGIN_LATEX +// t^{*}(Q) = #delta_{0} * #frac{Q_{t+1} - Q_{t-1}}{Q_{t-1} + Q_{t} + Q_{t+1}} +// END_LATEX +// +// +// Clusters can also be r-phi shifted due to: +// - wrong PRF or wrong cuts at digits level +//The following correction is applied : +// BEGIN_LATEX +// <#Delta y> = a + b * sin(c*y_{pw}) +// END_LATEX + +// The Models +// +// Parameterization against total charge +// +// Obtained for B=0T at phi=0. All other effects integrated out. +// BEGIN_LATEX +// #sigma^{2}_{y}(Q) = #sigma^{2}_{y}(...) + b(#frac{1}{Q} - #frac{1}{Q_{0}}) +// END_LATEX +// For B diff 0T the error of the average ExB correction error has to be subtracted !! +// +// Parameterization Sx +// +// The parameterization of the error in the x direction can be written as +// BEGIN_LATEX +// #sigma_{x} = #sigma_{x}^{||} + #sigma_{x}^{#perp} +// END_LATEX +// +// where the parallel component is given mainly by the TRF width while +// the perpendicular component by the anisochronity. The model employed for +// the parallel is gaus(0)+expo(3) with the following parameters +// 1 C 5.49018e-01 1.23854e+00 3.84540e-04 -8.21084e-06 +// 2 M 7.82999e-01 6.22531e-01 2.71272e-04 -6.88485e-05 +// 3 S 2.74451e-01 1.13815e+00 2.90667e-04 1.13493e-05 +// 4 E1 2.53596e-01 1.08646e+00 9.95591e-05 -2.11625e-05 +// 5 E2 -2.40078e-02 4.26520e-01 4.67153e-05 -2.35392e-04 +// +// and perpendicular to the track is pol2 with the parameters +// +// Par_0 = 0.190676 +/- 0.41785 +// Par_1 = -3.9269 +/- 7.49862 +// Par_2 = 14.7851 +/- 27.8012 +// +// Parameterization Sy +// +// The parameterization of the error in the y direction along track uses +// BEGIN_LATEX +// #sigma_{y}^{||} = #sigma_{y}^{0} -a*exp(1/(x-b)) +// END_LATEX +// +// with following values for the parameters: +// 1 sy0 2.60967e-01 2.99652e-03 7.82902e-06 -1.89636e-04 +// 2 a -7.68941e+00 1.87883e+00 3.84539e-04 9.38268e-07 +// 3 b -3.41160e-01 7.72850e-02 1.63231e-05 2.51602e-05 +// +//========================================================================== +// Example how to retrive reference plots from the task +// void steerClErrParam(Int_t fig=0) +// { +// gSystem->Load("libANALYSIS.so"); +// gSystem->Load("libTRDqaRec.so"); +// +// // initialize DB manager +// AliCDBManager *cdb = AliCDBManager::Instance(); +// cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB"); +// cdb->SetRun(0); +// // initialize magnetic field. +// AliMagFCheb *field=new AliMagFCheb("Maps","Maps", 2, 1., 10., AliMagFCheb::k5kG); +// AliTracker::SetFieldMap(field, kTRUE); +// +// AliTRDclusterResolution *res = new AliTRDclusterResolution(); +// res->SetMCdata(); +// res->Load("TRD.TaskClErrParam.root"); +// res->SetExB(); +// res->SetVisual(); +// //res->SetSaveAs(); +// res->SetProcessCharge(kFALSE); +// res->SetProcessCenterPad(kFALSE); +// //res->SetProcessMean(kFALSE); +// res->SetProcessSigma(kFALSE); +// if(!res->PostProcess()) return; +// new TCanvas; +// res->GetRefFigure(fig); +// } +// +// Authors: // +// Alexandru Bercuci // +//////////////////////////////////////////////////////////////////////////// + +#include "AliTRDclusterResolution.h" +#include "info/AliTRDclusterInfo.h" +#include "AliTRDgeometry.h" +#include "AliTRDcluster.h" +#include "AliTRDcalibDB.h" +#include "AliTRDCommonParam.h" +#include "Cal/AliTRDCalROC.h" +#include "Cal/AliTRDCalDet.h" + +#include "AliLog.h" +#include "AliTracker.h" +#include "AliCDBManager.h" + +#include "TROOT.h" +#include "TObjArray.h" +#include "TAxis.h" +#include "TF1.h" +#include "TLegend.h" +#include "TGraphErrors.h" +#include "TLine.h" +#include "TH2I.h" +#include "TH3S.h" +#include "TTree.h" +#include "TMath.h" +#include "TLinearFitter.h" + +#include "TCanvas.h" +#include "TSystem.h" + +ClassImp(AliTRDclusterResolution) + +const Float_t AliTRDclusterResolution::fgkTimeBinLength = 1./ AliTRDCommonParam::Instance()->GetSamplingFrequency(); +//_______________________________________________________ +AliTRDclusterResolution::AliTRDclusterResolution(const char *name, const char *title) + : AliTRDrecoTask(name, title) + ,fCanvas(0x0) + ,fInfo(0x0) + ,fResults(0x0) + ,fAt(0x0) + ,fStatus(0) + ,fDet(-1) + ,fExB(0.) + ,fVdrift(0.) + ,fLy(0) + ,fX(0.) + ,fY(0.) + ,fZ(0.) +{ +// Constructor + + memset(fR, 0, 4*sizeof(Float_t)); + memset(fP, 0, 4*sizeof(Float_t)); + // time drift axis + fAt = new TAxis(kNTB, 0., kNTB*fgkTimeBinLength); + + // By default register all analysis + // The user can switch them off in his steering macro + SetProcess(kQRes); + SetProcess(kCenter); + SetProcess(kMean); + SetProcess(kSigm); +} + +//_______________________________________________________ +AliTRDclusterResolution::~AliTRDclusterResolution() +{ +// Destructor + + if(fCanvas) delete fCanvas; + if(fAt) delete fAt; + if(fResults){ + fResults->Delete(); + delete fResults; + } +} + +//_______________________________________________________ +void AliTRDclusterResolution::ConnectInputData(Option_t *) +{ + fInfo = dynamic_cast(GetInputData(0)); +} + +//_______________________________________________________ +void AliTRDclusterResolution::CreateOutputObjects() +{ + OpenFile(0, "RECREATE"); + fContainer = Histos(); +} + +//_______________________________________________________ +Bool_t AliTRDclusterResolution::GetRefFigure(Int_t ifig) +{ +// Steering function to retrieve performance plots + + if(!fResults) return kFALSE; + TLegend *leg = 0x0; + TList *l = 0x0; + TObjArray *arr = 0x0; + TTree *t = 0x0; + TH2 *h2 = 0x0;TH1 *h1 = 0x0; + TGraphErrors *gm(0x0), *gs(0x0), *gp(0x0); + switch(ifig){ + case kQRes: + if(!(arr = (TObjArray*)fResults->At(kQRes))) break; + if(!(gm = (TGraphErrors*)arr->At(0))) break; + if(!(gs = (TGraphErrors*)arr->At(1))) break; + if(!(gp = (TGraphErrors*)arr->At(2))) break; + gs->Draw("apl"); + gs->GetHistogram()->GetYaxis()->SetRangeUser(-50., 700.); + gs->GetHistogram()->SetXTitle("Q [a.u.]"); + gs->GetHistogram()->SetYTitle("#sigma_{y} / #mu_{y} [#mum] / freq"); + gm->Draw("pl"); + gp->Draw("pl"); + return kTRUE; + case kCenter: + if(!(arr = (TObjArray*)fResults->At(kCenter))) break; + gPad->Divide(2, 1); l = gPad->GetListOfPrimitives(); + ((TVirtualPad*)l->At(0))->cd(); + ((TTree*)arr->At(0))->Draw("y:x>>h(23, 0.1, 2.4, 51, -.51, .51)", + "m[0]*(ly==0&&abs(m[0])<1.e-1)", "colz"); + ((TVirtualPad*)l->At(1))->cd(); + leg= new TLegend(.7, .7, .9, .95); + leg->SetBorderSize(0); leg->SetFillColor(0); leg->SetFillStyle(0); + leg->SetHeader("TRD Plane"); + for(Int_t il = 1; il<=AliTRDgeometry::kNlayer; il++){ + if(!(gm = (TGraphErrors*)arr->At(il))) return kFALSE; + gm->Draw(il>1?"pc":"apc"); leg->AddEntry(gm, Form("%d", il-1), "pl"); + if(il>1) continue; + gm->GetHistogram()->SetXTitle("t_{drift} [#mus]"); + gm->GetHistogram()->SetYTitle("#sigma_{y}(x|cen=0) [#mum]"); + gm->GetHistogram()->GetYaxis()->SetRangeUser(150., 500.); + } + leg->Draw(); + return kTRUE; + case kSigm: + if(!(t = (TTree*)fResults->At(kSigm))) break; + t->Draw("z:t>>h2x(23, 0.1, 2.4, 25, 0., 2.5)","sx*(1)", "lego2fb"); + h2 = (TH2F*)gROOT->FindObject("h2x"); + printf(" const Double_t sx[24][25]={\n"); + for(Int_t ix=1; ix<=h2->GetNbinsX(); ix++){ + printf(" {"); + for(Int_t iy=1; iyGetNbinsY(); iy++){ + printf("%6.4f ", h2->GetBinContent(ix, iy)); + } + printf("%6.4f},\n", h2->GetBinContent(ix, h2->GetNbinsY())); + } + printf(" };\n"); + gPad->Divide(2, 1, 1.e-5, 1.e-5); l = gPad->GetListOfPrimitives(); + ((TVirtualPad*)l->At(0))->cd(); + h1 = h2->ProjectionX("hsx_pxx"); h1->Scale(1.e4/kND); h1->SetMarkerStyle(24); + h1->SetYTitle("<#sigma_{x}> [#mum]"); + h1->SetXTitle("t_{drift} [#mus]"); + h1->GetXaxis()->SetRange(2, kNTB-1); h1->Draw("pc"); + + t->Draw("z:t>>h2y(23, 0.1, 2.4, 25, 0., 2.5)","sy*(1)", "lego2fb"); + h2 = (TH2F*)gROOT->FindObject("h2y"); + printf(" const Double_t sy[24][25]={\n"); + for(Int_t ix=1; ix<=h2->GetNbinsX(); ix++){ + printf(" {"); + for(Int_t iy=1; iyGetNbinsY(); iy++){ + printf("%6.4f ", h2->GetBinContent(ix, iy)); + } + printf("%6.4f},\n", h2->GetBinContent(ix, h2->GetNbinsY())); + } + printf(" };\n"); + ((TVirtualPad*)l->At(1))->cd(); + h1 = h2->ProjectionX("hsy_pxx"); h1->Scale(1.e4/kND); h1->SetMarkerStyle(24); + h1->SetYTitle("<#sigma_{y}> [#mum]"); + h1->SetXTitle("t_{drift} [#mus]"); + h1->GetXaxis()->SetRange(2, kNTB-1); h1->Draw("pc"); + return kTRUE; + case kMean: + if(!(t = (TTree*)fResults->At(kMean))) break; + t->Draw("z:t>>h2x(23, 0.1, 2.4, 25, 0., 2.5)","dx*(1)", "goff"); + h2 = (TH2F*)gROOT->FindObject("h2x"); + printf(" const Double_t dx[24][25]={\n"); + for(Int_t ix=1; ix<=h2->GetNbinsX(); ix++){ + printf(" {"); + for(Int_t iy=1; iyGetNbinsY(); iy++){ + printf("%6.4f ", h2->GetBinContent(ix, iy)); + } + printf("%6.4f},\n", h2->GetBinContent(ix, h2->GetNbinsY())); + } + printf(" };\n"); + gPad->Divide(2, 1, 1.e-5, 1.e-5); l = gPad->GetListOfPrimitives(); + ((TVirtualPad*)l->At(0))->cd(); + h1 = h2->ProjectionX("hdx_pxx"); h1->Scale(1.e4/kND); h1->SetMarkerStyle(24); + h1->SetYTitle(" [#mum]"); + h1->SetXTitle("t_{drift} [#mus]"); + h1->GetXaxis()->SetRange(2, kNTB-1); h1->Draw("pc"); + + t->Draw("z:t>>h2y(23, 0.1, 2.4, 25, 0., 2.5)","dy*(1)", "goff"); + h2 = (TH2F*)gROOT->FindObject("h2y"); + printf(" const Double_t dy[24][25]={\n"); + for(Int_t ix=1; ix<=h2->GetNbinsX(); ix++){ + printf(" {"); + for(Int_t iy=1; iyGetNbinsY(); iy++){ + printf("%6.4f ", h2->GetBinContent(ix, iy)); + } + printf("%6.4f},\n", h2->GetBinContent(ix, h2->GetNbinsY())); + } + printf(" };\n"); + ((TVirtualPad*)l->At(1))->cd(); + h1 = h2->ProjectionX("hdy_pxx"); h1->Scale(1.e4/kND); h1->SetMarkerStyle(24); + h1->SetYTitle(" [#mum]"); + h1->SetXTitle("t_{drift} [#mus]"); + h1->GetXaxis()->SetRange(2, kNTB-1); h1->Draw("pc"); + + return kTRUE; + default: + break; + } + AliWarning("No container/data found."); + return kFALSE; +} + +//_______________________________________________________ +TObjArray* AliTRDclusterResolution::Histos() +{ +// Retrieve histograms array if already build or build it + + if(fContainer) return fContainer; + fContainer = new TObjArray(kNtasks); + //fContainer->SetOwner(kTRUE); + + TH3S *h3 = 0x0; + TObjArray *arr = 0x0; + + fContainer->AddAt(arr = new TObjArray(2*AliTRDgeometry::kNlayer), kCenter); + arr->SetName("Center"); + for(Int_t il=0; ilFindObject(Form("hCenResLy%d", il)))){ + h3 = new TH3S( + Form("hCenResLy%d", il), + Form(" ly [%d]", il), + kNTB, fAt->GetBinLowEdge(1), fAt->GetBinUpEdge(kNTB), // x + 51, -.51, .51, // y + 60, -.3, .3); // dy + h3->SetXTitle("x [#mus]"); + h3->SetYTitle("y [pw]"); + h3->SetZTitle("#Delta y[cm]"); + } h3->Reset(); + arr->AddAt(h3, il); + // add Pull plot for each layer + if(!(h3=(TH3S*)gROOT->FindObject(Form("hCenPullLy%d", il)))){ + h3 = new TH3S( + Form("hCenPullLy%d", il), + Form(" ly [%d]", il), + kNTB, fAt->GetBinLowEdge(1), fAt->GetBinUpEdge(kNTB), // x + 51, -.51, .51, // y + 60, -4., 4.); // dy + h3->SetXTitle("x [#mus]"); + h3->SetYTitle("y [pw]"); + h3->SetZTitle("#Delta y/#sigma_{y}"); + } h3->Reset(); + arr->AddAt(h3, AliTRDgeometry::kNlayer+il); + } + + if(!(h3 = (TH3S*)gROOT->FindObject("Charge"))){ + h3 = new TH3S("Charge", "dy=f(q)", 50, 2.2, 7.5, 60, -.3, .3, 60, -4., 4.); + h3->SetXTitle("log(q) [a.u.]"); + h3->SetYTitle("#Delta y[cm]"); + h3->SetZTitle("#Delta y/#sigma_{y}"); + } + fContainer->AddAt(h3, kQRes); + + fContainer->AddAt(arr = new TObjArray(kNTB), kSigm); + arr->SetName("Resolution"); + for(Int_t ix=0; ixFindObject(Form("hr_x%02d", ix)))){ + h3 = new TH3S( + Form("hr_x%02d", ix), + Form(" t_{drift}(%3.1f-%3.1f)[#mus]", fAt->GetBinLowEdge(ix+1), fAt->GetBinUpEdge(ix+1)), + kND, 0., 2.5, // z + 35, -.35, .35, // tgp + 60, -.3, .3); // dy + h3->SetXTitle("z [mm]"); + h3->SetYTitle("tg#phi"); + h3->SetZTitle("#Delta y[cm]"); + } + arr->AddAt(h3, ix); + } + + fContainer->AddAt(arr = new TObjArray(kNTB), kMean); + arr->SetName("Systematics"); + for(Int_t ix=0; ixFindObject(Form("hs_x%02d", ix)))){ + h3 = new TH3S( + Form("hs_x%02d", ix), + Form(" t_{drift}(%3.1f-%3.1f)[#mus]", fAt->GetBinLowEdge(ix+1), fAt->GetBinUpEdge(ix+1)), + kND, 0., 2.5, // z + 35, -.35, .35, // tgp-h tgt + 60, -.3, .3); // dy + h3->SetXTitle("z [mm]"); + h3->SetYTitle("tg(#phi) - h*tg(#theta)"); + h3->SetZTitle("#Delta y[cm]"); + } + arr->AddAt(h3, ix); + } + + return fContainer; +} + +//_______________________________________________________ +void AliTRDclusterResolution::Exec(Option_t *) +{ +// Fill container histograms + + if(!HasExB()) AliWarning("ExB was not set. Call SetExB() before running the task."); + + Int_t det, t; + Float_t x, y, z, q, dy, dydx, dzdx, cov[3], covcl[3]; + TH3S *h3 = 0x0; + + // define limits around ExB for which x contribution is negligible + const Float_t kDtgPhi = 3.5e-2; //(+- 2 deg) + + TObjArray *arr0 = (TObjArray*)fContainer->At(kCenter); + TObjArray *arr1 = (TObjArray*)fContainer->At(kSigm); + TObjArray *arr2 = (TObjArray*)fContainer->At(kMean); + + const AliTRDclusterInfo *cli = 0x0; + TIterator *iter=fInfo->MakeIterator(); + while((cli=dynamic_cast((*iter)()))){ + cli->GetCluster(det, x, y, z, q, t, covcl); + if(fDet>=0 && fDet!=det) continue; + + dy = cli->GetResolution(); + cli->GetGlobalPosition(y, z, dydx, dzdx, &cov[0]); + + // resolution as a function of cluster charge + // only for phi equal exB + if(TMath::Abs(dydx-fExB) < kDtgPhi){ + h3 = (TH3S*)fContainer->At(kQRes); + h3->Fill(TMath::Log(q), dy, dy/TMath::Sqrt(covcl[0])); + + printf("q=%f Log(q)=%f dy=%f pull=%f\n",q, TMath::Log(q), dy, dy/TMath::Sqrt(covcl[0])); + } + + // do not use problematic clusters in resolution analysis + // TODO define limits as calibration aware (gain) !! + if(q<20. || q>250.) continue; + + x = (t+.5)*fgkTimeBinLength; // conservative approach !! + + // resolution as a function of y displacement from pad center + // only for phi equal exB + if(TMath::Abs(dydx-fExB) < kDtgPhi/* && + TMath::Abs(x-0.675)<0.225*/){ + Int_t ly(AliTRDgeometry::GetLayer(det)); + h3 = (TH3S*)arr0->At(ly); + h3->Fill(x, cli->GetYDisplacement(), dy); + h3 = (TH3S*)arr0->At(AliTRDgeometry::kNlayer+ly); + h3->Fill(x, cli->GetYDisplacement(), dy/TMath::Sqrt(covcl[0])); + } + + Int_t ix = fAt->FindBin(x); + if(ix==0 || ix == fAt->GetNbins()+1){ + AliWarning(Form("Drift time %3.1f outside allowed range", x)); + continue; + } + + // fill histo for resolution (sigma) + ((TH3S*)arr1->At(ix-1))->Fill(10.*cli->GetAnisochronity(), dydx, dy); + + // fill histo for systematic (mean) + ((TH3S*)arr2->At(ix-1))->Fill(10.*cli->GetAnisochronity(), dydx-cli->GetTilt()*dzdx, dy); + } + PostData(0, fContainer); +} + + +//_______________________________________________________ +Bool_t AliTRDclusterResolution::PostProcess() +{ + if(!fContainer) return kFALSE; + if(!HasExB()) AliWarning("ExB was not set. Call SetExB() before running the post processing."); + + TObjArray *arr = 0x0; + TTree *t=0x0; + if(!fResults){ + TGraphErrors *g = 0x0; + fResults = new TObjArray(kNtasks); + fResults->SetOwner(); + fResults->AddAt(arr = new TObjArray(3), kQRes); + arr->SetOwner(); + arr->AddAt(g = new TGraphErrors(), 0); + g->SetLineColor(kBlue); g->SetMarkerColor(kBlue); + g->SetMarkerStyle(7); + arr->AddAt(g = new TGraphErrors(), 1); + g->SetLineColor(kRed); g->SetMarkerColor(kRed); + g->SetMarkerStyle(23); + arr->AddAt(g = new TGraphErrors(), 2); + g->SetLineColor(kGreen); g->SetMarkerColor(kGreen); + g->SetMarkerStyle(7); + + // pad center dependence + fResults->AddAt(arr = new TObjArray(AliTRDgeometry::kNlayer+1), kCenter); + arr->SetOwner(); + arr->AddAt( + t = new TTree("cent", "dy=f(y,x,ly)"), 0); + t->Branch("ly", &fLy, "ly/B"); + t->Branch("x", &fX, "x/F"); + t->Branch("y", &fY, "y/F"); + t->Branch("m", &fR[0], "m[2]/F"); + t->Branch("s", &fR[2], "s[2]/F"); + t->Branch("pm", &fP[0], "pm[2]/F"); + t->Branch("ps", &fP[2], "ps[2]/F"); + for(Int_t il=1; il<=AliTRDgeometry::kNlayer; il++){ + arr->AddAt(g = new TGraphErrors(), il); + g->SetLineColor(il); g->SetLineStyle(il); + g->SetMarkerColor(il);g->SetMarkerStyle(4); + } + + + fResults->AddAt(t = new TTree("sigm", "dy=f(dw,x,dydx)"), kSigm); + t->Branch("t", &fX, "t/F"); + t->Branch("z", &fZ, "z/F"); + t->Branch("sx", &fR[0], "sx[2]/F"); + t->Branch("sy", &fR[2], "sy[2]/F"); + + + fResults->AddAt(t = new TTree("mean", "dy=f(dw,x,dydx - h dzdx)"), kMean); + t->Branch("t", &fX, "t/F"); + t->Branch("z", &fZ, "z/F"); + t->Branch("dx", &fR[0], "dx[2]/F"); + t->Branch("dy", &fR[2], "dy[2]/F"); + } else { + TObject *o = 0x0; + TIterator *iter=fResults->MakeIterator(); + while((o=((*iter)()))) o->Clear(); // maybe it is wrong but we should never reach this point + } + + // precalculated value of tg^2(alpha_L) + Double_t exb2 = fExB*fExB; + // square of the mean value of sigma drift length. + // has to come from previous calibration + //Double_t sxd2 = 1.;// [mm^2] + + printf("ExB[%e] ExB2[%e]\n", fExB, exb2); + + // process resolution dependency on charge + if(HasProcess(kQRes)) ProcessCharge(); + + // process resolution dependency on y displacement + if(HasProcess(kCenter)) ProcessCenterPad(); + + // process resolution dependency on drift legth and drift cell width + if(HasProcess(kSigm)) ProcessSigma(); + + // process systematic shift on drift legth and drift cell width + if(HasProcess(kMean)) ProcessMean(); + + return kTRUE; +} + +//_______________________________________________________ +Bool_t AliTRDclusterResolution::SetExB(Int_t det, Int_t col, Int_t row) +{ + // check OCDB + AliCDBManager *cdb = AliCDBManager::Instance(); + if(cdb->GetRun() < 0){ + AliError("OCDB manager not properly initialized"); + return kFALSE; + } + + // check magnetic field + if(TMath::Abs(AliTracker::GetBz()) < 1.e-10){ + AliWarning("B=0. Magnetic field may not be initialized. Continue if you know what you are doing !"); + } + + // set reference detector if any + if(det>=0 && detGetVdriftROC(det); + const AliTRDCalDet *fCalVdriftDet = fCalibration->GetVdriftDet(); + + fVdrift = fCalVdriftDet->GetValue(det) * fCalVdriftROC->GetValue(col, row); + fExB = AliTRDCommonParam::Instance()->GetOmegaTau(fVdrift); + SetBit(kExB); + return kTRUE; +} + +//_______________________________________________________ +void AliTRDclusterResolution::SetVisual() +{ + if(fCanvas) return; + fCanvas = new TCanvas("clResCanvas", "Cluster Resolution Visualization", 10, 10, 600, 600); +} + +//_______________________________________________________ +void AliTRDclusterResolution::ProcessCharge() +{ +// Resolution as a function of cluster charge. +// +// As described in the function ProcessCenterPad() the error parameterization for clusters for phi = a_L can be +// written as: +// BEGIN_LATEX +// #sigma_{y}^{2} = #sigma_{y}^{2}|_{B=0} + tg^{2}(#alpha_{L})*#sigma_{x}^{2} +// END_LATEX +// with the contribution in case of B=0 given by: +// BEGIN_LATEX +// #sigma_{y}|_{B=0} = #sigma_{diff}*Gauss(0, s_{ly}) + #delta_{#sigma}(q) +// END_LATEX +// which further can be simplified to: +// BEGIN_LATEX +// <#sigma_{y}|_{B=0}>(q) = <#sigma_{y}> + #delta_{#sigma}(q) +// <#sigma_{y}> = #int{f(q)#sigma_{y}dq} +// END_LATEX +// The results for s_y and f(q) are displayed below: +//Begin_Html +// +//End_Html +// The function has to extended to accomodate gain calibration scalling and errors. +// +// Author +// Alexandru Bercuci + + TH2I *h2 = 0x0; + if(!(h2 = (TH2I*)fContainer->At(kQRes))) { + AliWarning("Missing dy=f(Q) histo"); + return; + } + TF1 f("f", "gaus", -.5, .5); + TAxis *ax = 0x0; + TH1D *h1 = 0x0; + + // compute mean error on x + Double_t s2x = 0.; + for(Int_t ix=5; ixAt(kQRes); + TGraphErrors *gqm = (TGraphErrors*)arr->At(0); + TGraphErrors *gqs = (TGraphErrors*)arr->At(1); + TGraphErrors *gqp = (TGraphErrors*)arr->At(2); + Double_t q, n = 0., entries; + ax = h2->GetXaxis(); + for(Int_t ix=1; ix<=ax->GetNbins(); ix++){ + q = TMath::Exp(ax->GetBinCenter(ix)); + if(q<20. || q>250.) continue; // ?! + + h1 = h2->ProjectionY("py", ix, ix); + entries = h1->GetEntries(); + if(entries < 50) continue; + Adjust(&f, h1); + h1->Fit(&f, "Q"); + + // Fill sy^2 = f(q) + Int_t ip = gqm->GetN(); + gqm->SetPoint(ip, q, 1.e4*f.GetParameter(1)); + gqm->SetPointError(ip, 0., 1.e4*f.GetParError(1)); + + // correct sigma for ExB effect + gqs->SetPoint(ip, q, 1.e4*(f.GetParameter(2)*f.GetParameter(2)-exb2*s2x)); + gqs->SetPointError(ip, 0., 1.e4*f.GetParError(2)*f.GetParameter(2)); + + // save probability + n += entries; + gqp->SetPoint(ip, q, entries); + gqp->SetPointError(ip, 0., 0./*TMath::Sqrt(entries)*/); + } + + // normalize probability and get mean sy + Double_t sm = 0., sy; + for(Int_t ip=gqp->GetN(); ip--;){ + gqp->GetPoint(ip, q, entries); + entries/=n; + gqp->SetPoint(ip, q, 1.e3*entries); + gqs->GetPoint(ip, q, sy); + sm += entries*sy; + } + + // error parametrization s(q) = + b(1/q-1/q0) + TF1 fq("fq", "[0] + [1]/x", 20., 250.); + gqs->Fit(&fq/*, "W"*/); + printf("sm=%f [0]=%f [1]=%f\n", 1.e-4*sm, fq.GetParameter(0), fq.GetParameter(1)); + printf(" const Float_t sq0inv = %f; // [1/q0]\n", (sm-fq.GetParameter(0))/fq.GetParameter(1)); + printf(" const Float_t sqb = %f; // [cm]\n", 1.e-4*fq.GetParameter(1)); +} + +//_______________________________________________________ +void AliTRDclusterResolution::ProcessCenterPad() +{ +// Resolution as a function of y displacement from pad center and drift length. +// +// Since the error parameterization of cluster r-phi position can be written as (see AliTRDcluster::SetSigmaY2()): +// BEGIN_LATEX +// #sigma_{y}^{2} = (#sigma_{diff}*Gauss(0, s_{ly}) + #delta_{#sigma}(q))^{2} + tg^{2}(#alpha_{L})*#sigma_{x}^{2} + tg^{2}(#phi-#alpha_{L})*#sigma_{x}^{2}+[tg(#phi-#alpha_{L})*tg(#alpha_{L})*x]^{2}/12 +// END_LATEX +// one can see that for phi = a_L one gets the following expression: +// BEGIN_LATEX +// #sigma_{y}^{2} = #sigma_{y}^{2}|_{B=0} + tg^{2}(#alpha_{L})*#sigma_{x}^{2} +// END_LATEX +// where we have explicitely marked the remaining term in case of absence of magnetic field. Thus one can use the +// previous equation to estimate s_y for B=0 and than by comparing in magnetic field conditions one can get the s_x. +// This is a simplified method to determine the error parameterization for s_x and s_y as compared to the one +// implemented in ProcessSigma(). For more details on cluster error parameterization please see also +// AliTRDcluster::SetSigmaY2() +// +// The representation of dy=f(y_cen, x_drift| layer) can be also used to estimate the systematic shift in the r-phi +// coordinate resulting from imperfection in the cluster shape parameterization. From the expresion of the shift derived +// in ProcessMean() with phi=exb one gets: +// BEGIN_LATEX +// <#Delta y>= <#delta x> * (tg(#alpha_{L})-h*dz/dx) + <#delta y - #delta x * tg(#alpha_{L})> +// <#Delta y>(y_{cen})= -h*<#delta x>(x_{drift}, q_{cl}) * dz/dx + #delta y(y_{cen}, ...) +// END_LATEX +// where all dependences are made explicit. This last expression can be used in two ways: +// - by average on the dz/dx we can determine directly dy (the method implemented here) +// - by plotting as a function of dzdx one can determine both dx and dy components in an independent method. +//Begin_Html +// +//End_Html +// Author +// Alexandru Bercuci + + TObjArray *arr = (TObjArray*)fContainer->At(kCenter); + if(!arr) { + AliWarning("Missing dy=f(y | x, ly) container"); + return; + } + Double_t exb2 = fExB*fExB; + Float_t s[AliTRDgeometry::kNlayer]; + TF1 f("f", "gaus", -.5, .5); + TF1 fp("fp", "gaus", -3.5, 3.5); + + TH1D *h1 = 0x0; TH2F *h2 = 0x0; TH3S *h3r=0x0, *h3p=0x0; + TObjArray *arrRes = (TObjArray*)fResults->At(kCenter); + TTree *t = (TTree*)arrRes->At(0); + TGraphErrors *gs = 0x0; + TAxis *ax = 0x0; + + printf(" const Float_t lSy[6][24] = {\n {"); + const Int_t nl = AliTRDgeometry::kNlayer; + for(Int_t il=0; ilAt(il))) continue; + if(!(h3p = (TH3S*)arr->At(nl+il))) continue; + gs = (TGraphErrors*)arrRes->At(il+1); + fLy = il; +// printf("Ly[%d]\n", il); + for(Int_t ix=1; ix<=h3r->GetXaxis()->GetNbins(); ix++){ + ax = h3r->GetXaxis(); ax->SetRange(ix, ix); + ax = h3p->GetXaxis(); ax->SetRange(ix, ix); + fX = ax->GetBinCenter(ix); +// printf(" x[%2d]=%4.2f\n", ix, fX); + for(Int_t iy=1; iy<=h3r->GetYaxis()->GetNbins(); iy++){ + ax = h3r->GetYaxis(); ax->SetRange(iy, iy); + ax = h3p->GetYaxis(); ax->SetRange(iy, iy); + fY = ax->GetBinCenter(iy); +// printf(" y[%2d]=%5.2f\n", iy, fY); + // finish navigation in the HnSparse + + h1 = (TH1D*)h3r->Project3D("z"); + Int_t entries = (Int_t)h1->Integral(); + if(entries < 50) continue; + //Adjust(&f, h1); + h1->Fit(&f, "QN"); + + // Fill sy,my=f(y_w,x,ly) + fR[0] = f.GetParameter(1); fR[1] = f.GetParError(1); + fR[2] = f.GetParameter(2); fR[3] = f.GetParError(2); + + h1 = (TH1D*)h3p->Project3D("z"); + h1->Fit(&fp, "QN"); + fP[0] = fp.GetParameter(1); fP[1] = fp.GetParError(1); + fP[2] = fp.GetParameter(2); fP[3] = fp.GetParError(2); + + //printf("ly[%d] x[%3.1f] y[%+5.2f] m[%5.3f] s[%5.3f] \n", fLy, fX, fY, fR[0], fR[2]); + t->Fill(); + + + } + } + t->Draw("y:x>>h(24, 0., 2.4, 51, -.51, .51)", + Form("s[0]*(ly==%d&&abs(m[0])<1.e-1)", fLy), + "goff"); + h2=(TH2F*)gROOT->FindObject("h"); + f.FixParameter(1, 0.); + Int_t n = h2->GetXaxis()->GetNbins(), nn(0); s[il]=0.; + printf(" {"); + for(Int_t ix=1; ix<=n; ix++){ + ax = h2->GetXaxis(); + fX = ax->GetBinCenter(ix); + h1 = h2->ProjectionY("hCenPy", ix, ix); + //if((Int_t)h1->Integral() < 1.e-10) continue; + + // Apply lorentz angle correction + // retrieve error on the drift length + Double_t s2x = AliTRDcluster::GetSX(ix-1); s2x *= s2x; + Int_t nnn = 0; + for(Int_t iy=1; iy<=h1->GetNbinsX(); iy++){ + Double_t s2 = h1->GetBinContent(iy); s2*= s2; + // sigma square corrected for Lorentz angle + // s2 = s2_y(y_w,x)+exb2*s2_x + Double_t sy = TMath::Sqrt(TMath::Max(s2 - exb2*s2x, Double_t(0.))); + if(sy<1.e-20) continue; + h1->SetBinContent(iy, sy); nnn++; + printf("s[%6.2f] sx[%6.2f] sy[%6.2f]\n", + 1.e4*TMath::Sqrt(s2), 1.e4*TMath::Abs(fExB*AliTRDcluster::GetSX(ix-1)), + 1.e4*h1->GetBinContent(iy)); + } + // do fit only if enough data + Double_t sPRF = 0.; + if(nnn>5){ + h1->Fit(&f, "QN"); + sPRF = f.GetParameter(2); + nn++; + } + s[il]+=sPRF; + printf("%6.4f,%s", sPRF, ix%6?" ":"\n "); + Int_t jx = gs->GetN(); + gs->SetPoint(jx, fX, 1.e4*sPRF); + gs->SetPointError(jx, 0., 0./*f.GetParError(0)*/); + } + printf("\b},\n"); + s[il]/=nn; + + f.ReleaseParameter(2); + + + if(!fCanvas) continue; + h2->Draw("lego2fb"); + fCanvas->Modified(); fCanvas->Update(); + if(IsSaveAs()) fCanvas->SaveAs(Form("Figures/ProcessCenter_ly[%d].gif", fLy)); + else gSystem->Sleep(100); + } + printf(" };\n"); + printf(" const Float_t lPRF[] = {" + "%5.3f, %5.3f, %5.3f, %5.3f, %5.3f, %5.3f};\n", + s[0], s[1], s[2], s[3], s[4], s[5]); +} + +//_______________________________________________________ +void AliTRDclusterResolution::ProcessSigma() +{ +// As the r-phi coordinate is the only one which is measured by the TRD detector we have to rely on it to +// estimate both the radial (x) and r-phi (y) errors. This method is based on the following assumptions. +// The measured error in the y direction is the sum of the intrinsic contribution of the r-phi measurement +// with the contribution of the radial measurement - because x is not a parameter of Alice track model (Kalman). +// BEGIN_LATEX +// #sigma^{2}|_{y} = #sigma^{2}_{y*} + #sigma^{2}_{x*} +// END_LATEX +// In the general case +// BEGIN_LATEX +// #sigma^{2}_{y*} = #sigma^{2}_{y} + tg^{2}(#alpha_{L})#sigma^{2}_{x_{drift}} +// #sigma^{2}_{x*} = tg^{2}(#phi - #alpha_{L})*(#sigma^{2}_{x_{drift}} + #sigma^{2}_{x_{0}} + tg^{2}(#alpha_{L})*x^{2}/12) +// END_LATEX +// where we have explicitely show the lorentz angle correction on y and the projection of radial component on the y +// direction through the track angle in the bending plane (phi). Also we have shown that the radial component in the +// last equation has twp terms, the drift and the misalignment (x_0). For ideal geometry or known misalignment one +// can solve the equation +// BEGIN_LATEX +// #sigma^{2}|_{y} = tg^{2}(#phi - #alpha_{L})*(#sigma^{2}_{x} + tg^{2}(#alpha_{L})*x^{2}/12)+ [#sigma^{2}_{y} + tg^{2}(#alpha_{L})#sigma^{2}_{x}] +// END_LATEX +// by fitting a straight line: +// BEGIN_LATEX +// #sigma^{2}|_{y} = a(x_{cl}, z_{cl}) * tg^{2}(#phi - #alpha_{L}) + b(x_{cl}, z_{cl}) +// END_LATEX +// the error parameterization will be given by: +// BEGIN_LATEX +// #sigma_{x} (x_{cl}, z_{cl}) = #sqrt{a(x_{cl}, z_{cl}) - tg^{2}(#alpha_{L})*x^{2}/12} +// #sigma_{y} (x_{cl}, z_{cl}) = #sqrt{b(x_{cl}, z_{cl}) - #sigma^{2}_{x} (x_{cl}, z_{cl}) * tg^{2}(#alpha_{L})} +// END_LATEX +// Below there is an example of such dependency. +//Begin_Html +// +//End_Html +// +// The error parameterization obtained by this method are implemented in the functions AliTRDcluster::GetSX() and +// AliTRDcluster::GetSYdrift(). For an independent method to determine s_y as a function of drift length check the +// function ProcessCenterPad(). One has to keep in mind that while this method return the mean s_y over the distance +// to pad center distribution the other method returns the *STANDARD* value at center=0 (maximum). To recover the +// standard value one has to solve the obvious equation: +// BEGIN_LATEX +// #sigma_{y}^{STANDARD} = #frac{<#sigma_{y}>}{#int{s exp(s^{2}/#sigma) ds}} +// END_LATEX +// with "" being the value calculated here and "sigma" the width of the s_y distribution calculated in +// ProcessCenterPad(). +// +// Author +// Alexandru Bercuci + + TObjArray *arr = (TObjArray*)fContainer->At(kSigm); + if(!arr){ + AliWarning("Missing dy=f(x_d, d_w) container"); + return; + } + + // init visualization + TGraphErrors *ggs = 0x0; + TGraph *line = 0x0; + if(fCanvas){ + ggs = new TGraphErrors(); + line = new TGraph(); + line->SetLineColor(kRed);line->SetLineWidth(2); + } + + // init logistic support + TF1 f("f", "gaus", -.5, .5); + TLinearFitter gs(1,"pol1"); + TH1 *hFrame=0x0; + TH1D *h1 = 0x0; TH3S *h3=0x0; + TAxis *ax = 0x0; + Double_t exb2 = fExB*fExB, x; + AliTRDcluster c; + TTree *t = (TTree*)fResults->At(kSigm); + for(Int_t ix=0; ixAt(ix))) continue; + c.SetPadTime(ix); + x = c.GetXloc(0., 1.5); + fX= fAt->GetBinCenter(ix+1); + for(Int_t iz=1; iz<=h3->GetXaxis()->GetNbins(); iz++){ + ax = h3->GetXaxis(); + ax->SetRange(iz, iz); + fZ = ax->GetBinCenter(iz); + + // reset visualization + if(fCanvas){ + new(ggs) TGraphErrors(); + ggs->SetMarkerStyle(7); + } + gs.ClearPoints(); + + for(Int_t ip=1; ip<=h3->GetYaxis()->GetNbins(); ip++){ + ax = h3->GetYaxis(); + ax->SetRange(ip, ip); + Double_t tgl = ax->GetBinCenter(ip); + // finish navigation in the HnSparse + + //if(TMath::Abs(dydx)>0.18) continue; + Double_t tgg = (tgl-fExB)/(1.+tgl*fExB); + Double_t tgg2 = tgg*tgg; + + h1 = (TH1D*)h3->Project3D("z"); + Int_t entries = (Int_t)h1->Integral(); + if(entries < 50) continue; + //Adjust(&f, h1); + h1->Fit(&f, "QN"); + + Double_t s2 = f.GetParameter(2)*f.GetParameter(2); + Double_t s2e = 2.*f.GetParameter(2)*f.GetParError(2); + // Fill sy^2 = f(tg^2(phi-a_L)) + gs.AddPoint(&tgg2, s2, s2e); + + if(!ggs) continue; + Int_t jp = ggs->GetN(); + ggs->SetPoint(jp, tgg2, s2); + ggs->SetPointError(jp, 0., s2e); + } + // TODO here a more robust fit method has to be provided + // for which lower boundaries on the parameters have to + // be imposed. Unfortunately the Minuit fit does not work + // for the TGraph in the case of B not 0. + if(gs.Eval()) continue; + + fR[0] = gs.GetParameter(1) - x*x*exb2/12.; + printf("s2x+x2=%f ang=%f s2x=%f\n", gs.GetParameter(1), x*x*exb2/12., fR[0]); + fR[0] = TMath::Max(fR[0], Float_t(4.e-4)); + + // s^2_y = s0^2_y + tg^2(a_L) * s^2_x + // s0^2_y = f(D_L)*x + s_PRF^2 + fR[2]= gs.GetParameter(0)-exb2*fR[0]; + printf("s2y+s2x=%f s2y=%f\n", fR[0], fR[2]); + fR[2] = TMath::Max(fR[2], Float_t(2.5e-5)); + fR[0] = TMath::Sqrt(fR[0]); + fR[1] = .5*gs.GetParError(1)/fR[0]; + fR[2] = TMath::Sqrt(fR[2]); + fR[3] = gs.GetParError(0)+exb2*exb2*gs.GetParError(1); + t->Fill(); + printf(" xd=%4.2f[cm] sx=%6.1f[um] sy=%5.1f[um]\n", x, 1.e4*fR[0], 1.e4*fR[2]); + + if(!fCanvas) continue; + fCanvas->cd(); fCanvas->SetLogx(); //fCanvas->SetLogy(); + if(!hFrame){ + fCanvas->SetMargin(0.15, 0.01, 0.1, 0.01); + hFrame=new TH1I("hFrame", "", 100, 0., .3); + hFrame->SetMinimum(0.);hFrame->SetMaximum(.005); + hFrame->SetXTitle("tg^{2}(#phi-#alpha_{L})"); + hFrame->SetYTitle("#sigma^{2}y[cm^{2}]"); + hFrame->GetYaxis()->SetTitleOffset(2.); + hFrame->SetLineColor(1);hFrame->SetLineWidth(1); + hFrame->Draw(); + } else hFrame->Reset(); + Double_t xx = 0., dxx=.2/50; + for(Int_t ip=0;ip<50;ip++){ + line->SetPoint(ip, xx, gs.GetParameter(0)+xx*gs.GetParameter(1)); + xx+=dxx; + } + ggs->Draw("pl"); line->Draw("l"); + fCanvas->Modified(); fCanvas->Update(); + if(IsSaveAs()) fCanvas->SaveAs(Form("Figures/ProcessSigma_z[%5.3f]_x[%5.3f].gif", fZ, fX)); + else gSystem->Sleep(100); + } + } + return; +} + +//_______________________________________________________ +void AliTRDclusterResolution::ProcessMean() +{ +// By this method the cluster shift in r-phi and radial directions can be estimated by comparing with the MC. +// The resolution of the cluster corrected for pad tilt with respect to MC in the r-phi (measuring) plane can be +// expressed by: +// BEGIN_LATEX +// #Delta y=w - y_{MC}(x_{cl}) +// w = y_{cl}^{'} + h*(z_{MC}(x_{cl})-z_{cl}) +// y_{MC}(x_{cl}) = y_{0} - dy/dx*x_{cl} +// z_{MC}(x_{cl}) = z_{0} - dz/dx*x_{cl} +// y_{cl}^{'} = y_{cl}-x_{cl}*tg(#alpha_{L}) +// END_LATEX +// where x_cl is the drift length attached to a cluster, y_cl is the r-phi coordinate of the cluster measured by +// charge sharing on adjacent pads and y_0 and z_0 are MC reference points (as example the track references at +// entrance/exit of a chamber). If we suppose that both r-phi (y) and radial (x) coordinate of the clusters are +// affected by errors we can write +// BEGIN_LATEX +// x_{cl} = x_{cl}^{*} + #delta x +// y_{cl} = y_{cl}^{*} + #delta y +// END_LATEX +// where the starred components are the corrected values. Thus by definition the following quantity +// BEGIN_LATEX +// #Delta y^{*}= w^{*} - y_{MC}(x_{cl}^{*}) +// END_LATEX +// has 0 average over all dependency. Using this decomposition we can write: +// BEGIN_LATEX +// <#Delta y>=<#Delta y^{*}> + <#delta x * (dy/dx-h*dz/dx) + #delta y - #delta x * tg(#alpha_{L})> +// END_LATEX +// which can be transformed to the following linear dependence: +// BEGIN_LATEX +// <#Delta y>= <#delta x> * (dy/dx-h*dz/dx) + <#delta y - #delta x * tg(#alpha_{L})> +// END_LATEX +// if expressed as function of dy/dx-h*dz/dx. Furtheremore this expression can be plotted for various clusters +// i.e. we can explicitely introduce the diffusion (x_cl) and drift cell - anisochronity (z_cl) dependences. From +// plotting this dependence and linear fitting it with: +// BEGIN_LATEX +// <#Delta y>= a(x_{cl}, z_{cl}) * (dy/dx-h*dz/dx) + b(x_{cl}, z_{cl}) +// END_LATEX +// the systematic shifts will be given by: +// BEGIN_LATEX +// #delta x (x_{cl}, z_{cl}) = a(x_{cl}, z_{cl}) +// #delta y (x_{cl}, z_{cl}) = b(x_{cl}, z_{cl}) + a(x_{cl}, z_{cl}) * tg(#alpha_{L}) +// END_LATEX +// Below there is an example of such dependency. +//Begin_Html +// +//End_Html +// +// The occurance of the radial shift is due to the following conditions +// - the approximation of a constant drift velocity over the drift length (larger drift velocities close to +// cathode wire plane) +// - the superposition of charge tails in the amplification region (first clusters appear to be located at the +// anode wire) +// - the superposition of charge tails in the drift region (shift towards anode wire) +// - diffusion effects which convolute with the TRF thus enlarging it +// - approximate knowledge of the TRF (approximate measuring in test beam conditions) +// +// The occurance of the r-phi shift is due to the following conditions +// - approximate model for cluster shape (LUT) +// - rounding-up problems +// +// The numerical results for ideal simulations for the radial and r-phi shifts are displayed below and used +// for the cluster reconstruction (see the functions AliTRDcluster::GetXcorr() and AliTRDcluster::GetYcorr()). +//Begin_Html +// +// +//End_Html +// More details can be found in the presentation given during the TRD +// software meeting at the end of 2008 and beginning of year 2009, published on indico.cern.ch. +// +// Author +// Alexandru Bercuci + + + + TObjArray *arr = (TObjArray*)fContainer->At(kMean); + if(!arr){ + AliWarning("Missing dy=f(x_d, d_w) container"); + return; + } + + // init logistic support + TF1 f("f", "gaus", -.5, .5); + TF1 line("l", "[0]+[1]*x", -.15, .15); + TGraphErrors *gm = new TGraphErrors(); + TH1 *hFrame=0x0; + TH1D *h1 = 0x0; TH3S *h3 =0x0; + TAxis *ax = 0x0; + Double_t x; + + AliTRDcluster c; + TTree *t = (TTree*)fResults->At(kMean); + for(Int_t ix=0; ixAt(ix))) continue; + c.SetPadTime(ix); + x = c.GetXloc(0., 1.5); + fX= fAt->GetBinCenter(ix+1); + for(Int_t iz=1; iz<=h3->GetXaxis()->GetNbins(); iz++){ + ax = h3->GetXaxis(); + ax->SetRange(iz, iz); + fZ = ax->GetBinCenter(iz); + + // reset fitter + new(gm) TGraphErrors(); + gm->SetMarkerStyle(7); + + for(Int_t ip=1; ip<=h3->GetYaxis()->GetNbins(); ip++){ + ax = h3->GetYaxis(); + ax->SetRange(ip, ip); + Double_t tgl = ax->GetBinCenter(ip); + // finish navigation in the HnSparse + + h1 = (TH1D*)h3->Project3D("z"); + Int_t entries = (Int_t)h1->Integral(); + if(entries < 50) continue; + //Adjust(&f, h1); + h1->Fit(&f, "QN"); + + // Fill = f(dydx - h*dzdx) + Int_t jp = gm->GetN(); + gm->SetPoint(jp, tgl, f.GetParameter(1)); + gm->SetPointError(jp, 0., f.GetParError(1)); + } + if(gm->GetN()<4) continue; + + gm->Fit(&line, "QN"); + fR[0] = line.GetParameter(1); // dx + fR[1] = line.GetParError(1); + fR[2] = line.GetParameter(0) + fExB*fR[0]; // xs = dy - tg(a_L)*dx + t->Fill(); + printf(" xd=%4.2f[cm] dx=%6.2f[um] dy=%6.2f[um]\n", x, 1.e4*fR[0], 1.e4*fR[2]); + + if(!fCanvas) continue; + fCanvas->cd(); + if(!hFrame){ + fCanvas->SetMargin(0.1, 0.02, 0.1, 0.01); + hFrame=new TH1I("hFrame", "", 100, -.3, .3); + hFrame->SetMinimum(-.1);hFrame->SetMaximum(.1); + hFrame->SetXTitle("tg#phi-htg#theta"); + hFrame->SetYTitle("#Delta y[cm]"); + hFrame->GetYaxis()->SetTitleOffset(1.5); + hFrame->SetLineColor(1);hFrame->SetLineWidth(1); + hFrame->Draw(); + } else hFrame->Reset(); + gm->Draw("pl"); line.Draw("same"); + fCanvas->Modified(); fCanvas->Update(); + if(IsSaveAs()) fCanvas->SaveAs(Form("Figures/ProcessMean_Z[%5.3f]_X[%5.3f].gif", fZ, fX)); + else gSystem->Sleep(100); + } + } +} diff --git a/PWG1/TRD/AliTRDclusterResolution.h b/PWG1/TRD/AliTRDclusterResolution.h new file mode 100644 index 00000000000..7bdc89102e7 --- /dev/null +++ b/PWG1/TRD/AliTRDclusterResolution.h @@ -0,0 +1,122 @@ +#ifndef ALITRDCLUSTERRESOLUTION_H +#define ALITRDCLUSTERRESOLUTION_H + +/////////////////////////////////////////////////////////////////////////////// +// // +// TRD cluster error parameterization +// Authors: // +// Alexandru Bercuci // +//////////////////////////////////////////////////////////////////////////// + +#ifndef ALITRDRECOTASK_H +#include "AliTRDrecoTask.h" +#endif + +class TCanvas; +class TObjArray; +class TAxis; +class AliTRDclusterResolution : public AliTRDrecoTask +{ +public: + enum EAxisBinning { // bins in z and x direction + kNTB = 24 + ,kND = 25 + ,kN = kND*kNTB + }; + enum EResultContainer { // results container type + kCenter = 0 // cluster2center pad calibration + ,kQRes = 1 // resolution on charge dependence + ,kSigm = 2 // sigma cluster as func of x and z + ,kMean = 3 // shift cluster as func of x and z + ,kNtasks = 4 // total number os sub tasks + }; + enum ECheckBits { // force setting the ExB + kSaveAs = BIT(22) + ,kExB = BIT(23) + }; + AliTRDclusterResolution(const char *name="ClErrParam", const char *title="Cluster error monitor"); + virtual ~AliTRDclusterResolution(); + + void ConnectInputData(Option_t *); + void CreateOutputObjects(); + void Exec(Option_t *); + Int_t GetDetector() const { return fDet; } + inline Float_t GetExB() const; + inline Float_t GetVdrift() const; + Bool_t GetRefFigure(Int_t ifig); + Bool_t HasProcess(EResultContainer bit) const {return TESTBIT(fStatus, bit);} + Bool_t HasExB() const { return TestBit(kExB);} + + TObjArray* Histos(); + TObjArray* Results() const {return fResults;}; + + Bool_t IsVisual() const {return Bool_t(fCanvas);} + Bool_t IsSaveAs() const {return TestBit(kSaveAs);} + + Bool_t PostProcess(); + Bool_t SetExB(Int_t det=-1, Int_t c = 70, Int_t r = 7); + void SetVisual(); + void SetProcess(EResultContainer bit, Bool_t v = kTRUE) {v ? SETBIT(fStatus, bit) : CLRBIT(fStatus, bit);} + void SetSaveAs(Bool_t v = kTRUE) {SetBit(kSaveAs, v);} + inline void ResetProcess(); + +protected: + void ProcessCharge(); + void ProcessCenterPad(); + void ProcessSigma(); + void ProcessMean(); + +private: + AliTRDclusterResolution(const AliTRDclusterResolution&); + AliTRDclusterResolution& operator=(const AliTRDclusterResolution&); + + TCanvas *fCanvas; //! visualization canvas + TObjArray *fInfo; //! list of cluster info + TObjArray *fResults;// list of result graphs/histos + TAxis *fAt; //! binning in the x(radial) direction (time) + UChar_t fStatus; // steer parameter of the task + Short_t fDet; // detector (-1 for all) + Float_t fExB; // tg of the Lorentz angle + Float_t fVdrift; // mean drift velocity + static const Float_t fgkTimeBinLength;// time bin length (invers of sampling frequency) + + // working named variables + UChar_t fLy; //! TRD plane + Float_t fX; //! local drift length + Float_t fY; //! local rphi offset + Float_t fZ; //! local anode wire offset + Float_t fR[4]; //! mean/sgm resolution + Float_t fP[4]; //! mean/sgm pulls + + ClassDef(AliTRDclusterResolution, 3) // cluster resolution +}; + +//___________________________________________________ +inline Float_t AliTRDclusterResolution::GetExB() const +{ + if(!HasExB()){ + printf("WARNING :: ExB was not set. Use B=0.\n"); + } + return fExB; +} + +//___________________________________________________ +inline Float_t AliTRDclusterResolution::GetVdrift() const +{ + if(!HasExB()){ + printf("WARNING :: ExB was not set. Use B=0.\n"); + } + return fVdrift; +} + +//___________________________________________________ +inline void AliTRDclusterResolution::ResetProcess() +{ + CLRBIT(fStatus, kQRes); + CLRBIT(fStatus, kCenter); + CLRBIT(fStatus, kSigm); + CLRBIT(fStatus, kMean); +} + +#endif + diff --git a/PWG1/TRD/AliTRDefficiency.cxx b/PWG1/TRD/AliTRDefficiency.cxx new file mode 100644 index 00000000000..1d4440eb7a7 --- /dev/null +++ b/PWG1/TRD/AliTRDefficiency.cxx @@ -0,0 +1,295 @@ +/************************************************************************** + * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * * + * Author: The ALICE Off-line Project. * + * Contributors are mentioned in the code where appropriate. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/* $Id: AliTRDefficiency.cxx 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// Reconstruction QA // +// // +// Authors: // +// Markus Fasel // +// // +//////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "TTreeStream.h" + +#include "AliPID.h" +#include "AliESDtrack.h" +#include "AliTrackReference.h" +#include "AliExternalTrackParam.h" +#include "AliTracker.h" +#include "AliAnalysisManager.h" + +#include "Cal/AliTRDCalPID.h" +#include "AliTRDefficiency.h" +#include "info/AliTRDtrackInfo.h" + +ClassImp(AliTRDefficiency) + +//____________________________________________________________________ +AliTRDefficiency::AliTRDefficiency() + :AliTRDrecoTask("efficiency", "TRD barrel tracking efficiency checker") + ,fMissed(0x0) +{ + // + // Default constructor + // +} + +//____________________________________________________________________ +AliTRDefficiency::~AliTRDefficiency() +{ + // Destructor + if(fMissed){ + fMissed->Delete(); + delete fMissed; + } +} + +//____________________________________________________________________ +void AliTRDefficiency::CreateOutputObjects() +{ + // + // Create output objects + // + + OpenFile(0, "RECREATE"); + const Int_t nbins = AliTRDCalPID::kNMom; + Float_t xbins[nbins+1] = {.5, .7, .9, 1.3, 1.7, 2.4, 3.5, 4.5, 5.5, 7., 9., 11.}; + + TH1 *h = 0x0; + fContainer = new TObjArray(); + for(Int_t is=0; isAdd(h = new TProfile(Form("h%s", AliTRDCalPID::GetPartSymb(is)), "", nbins, xbins)); + h->SetLineColor(AliTRDCalPID::GetPartColor(is)); + h->SetMarkerColor(AliTRDCalPID::GetPartColor(is)); + h->SetMarkerStyle(7); + } + fContainer->Add(h = new TProfile("h", "", nbins, xbins)); + h->SetMarkerStyle(7); +} + +//____________________________________________________________________ +void AliTRDefficiency::Exec(Option_t *) +{ + // + // Do it + // + + Int_t labelsacc[10000]; + memset(labelsacc, 0, sizeof(Int_t) * 10000); + + if(!fMissed){ + fMissed = new TClonesArray("AliTRDtrackInfo", 10); + fMissed->SetOwner(); + } + + Float_t mom; + Int_t selection[10000], nselect = 0; + ULong_t status; Int_t pidx; + Int_t nTRD = 0, nTPC = 0, nMiss = 0; + AliTRDtrackInfo *track = 0x0; + AliTrackReference *ref = 0x0; + AliExternalTrackParam *esd = 0x0; + for(Int_t itrk=0; itrkGetEntriesFast(); itrk++){ + track = (AliTRDtrackInfo*)fTracks->UncheckedAt(itrk); + + if(!track->HasESDtrack()) continue; + status = track->GetStatus(); + + // missing TPC propagation - interesting for SA + if(!(status&AliESDtrack::kTPCout)) continue; + + // missing MC info. + if(HasMCdata() && track->GetNTrackRefs() <= 1) continue; + + nTPC++; + selection[nselect++]=itrk; + ref = track->GetTrackRef(0); + esd = track->GetESDinfo()->GetOuterParam(); + mom = ref ? ref->P(): esd->P(); + pidx = AliTRDCalPID::GetPartIndex(track->GetPDG()); + pidx = TMath::Max(pidx, 0); + + //Int_t n = track->GetNumberOfClusters(); + // where are this tracklets ??? + //if(ncls0 > ncls1) printf("%3d ESD[%3d] TRD[%3d|%3d]\n", itrk, ncls0, ncls1, n); + if(track->GetNumberOfClustersRefit()){ + ((TProfile*)fContainer->At(pidx))->Fill(mom, 1.); + labelsacc[nTRD] = track->GetLabel(); + nTRD++; + continue; + } + + + + Float_t xmed, xleng; + Int_t iref = 1; Bool_t found = kFALSE; + while((ref = track->GetTrackRef(iref))){ + xmed = .5*(ref->LocalX() + track->GetTrackRef(iref-1)->LocalX()); + xleng= (ref->LocalX() - track->GetTrackRef(iref-1)->LocalX()); + if(TMath::Abs(xmed - 298.5) < .5 && + TMath::Abs(xleng - 3.7) < .1){ + found = kTRUE; + break; + } + iref++; + } + if(!found){ + nTPC--; + // track missing first layer. Maybe interesting for SA. + continue; + } + nselect--; + new ((*fMissed)[nMiss]) AliTRDtrackInfo(*track); + nMiss++; + } + AliDebug(2, Form("%3d Tracks: ESD[%3d] TPC[%3d] TRD[%3d | %5.2f%%] Off[%d]", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), fTracks->GetEntriesFast(), nTPC, nTRD, nTPC ? 1.E2*nTRD/float(nTPC) : 0., fMissed->GetEntriesFast())); + + + // Find double tracks + Float_t threshold = 10.; + AliTrackReference *refMiss = 0x0; + AliExternalTrackParam *op = 0x0; + AliTRDtrackInfo *tt = 0x0; + for(Int_t imiss=0; imissUncheckedAt(imiss); + op = tt->GetESDinfo()->GetOuterParam(); + Double_t alpha = op->GetAlpha(), cosa = TMath::Cos(alpha), sina = TMath::Sin(alpha); + + Double_t xyz[3], x0, y0, z0, x, y, z, dx, dy, dz, d; + + Bool_t bFOUND = kFALSE; + for(Int_t iselect=0; iselectUncheckedAt(selection[iselect]); + + // check first MC ... if available + d = 0; + for(Int_t iref=0; irefGetNTrackRefs(); iref++){ + if(!(ref = track->GetTrackRef(iref))) continue; + if((refMiss = tt->GetTrackRef(iref))){ + dy = ref->LocalY() - refMiss->LocalY(); + dz = ref->Z() - refMiss->Z(); + } else { + // compare missOP with refTrackRef in LTC + x0 = ref->LocalX(); + op->GetYAt(x0, AliTracker::GetBz(), y0); + op->GetZAt(x0, AliTracker::GetBz(), z0); + dy = y0 - ref->LocalY(); + dz = z0 - ref->Z(); + } + d += (dy*dy + dz*dz); + } + //printf("\td[%d] = %f N[%d]\n", selection[iselect], d, track->GetNTrackRefs()); + if((track->GetNTrackRefs())){ + d /= track->GetNTrackRefs(); + if(d < threshold){ + //printf("\t\tFound %2d in ref[%3d] : d[%f]\n", imiss, selection[iselect], d/track->GetNTrackRefs()); + bFOUND = kTRUE; break; + } + } + + // process outer param ... always available + // compare missOP with OP in GTC + esd = track->GetESDinfo()->GetOuterParam(); + esd->GetXYZ(xyz); + x0 = esd->GetX(); + op->GetYAt(x0, AliTracker::GetBz(), y0); + op->GetZAt(x0, AliTracker::GetBz(), z0); + x = x0*cosa - y0*sina; + y = x0*sina + y0*cosa; + z = z0; + dx=xyz[0]-x; + dy=xyz[1]-y; + dz=xyz[2]-z; + d = dx*dx+dy*dy+dz*dz; + //printf("\td[%d] = %f op\n", selection[iselect], d); + if(d < threshold){ + //printf("\t\tFound %2d in op[%3d] : d[%f] dx[%5.2f] dy[%5.2f] dz[%5.2f]\n", imiss, selection[iselect], d, dx, dy, dz); + bFOUND = kTRUE; break; + } + } + if(bFOUND) nTPC--; + else{ + ref = tt->GetTrackRef(0); + mom = ref ? ref->P(): op->P(); + pidx = AliTRDCalPID::GetPartIndex(tt->GetPDG()); + pidx = TMath::Max(pidx, 0); + ((TProfile*)fContainer->At(pidx))->Fill(mom, 0.); + AliDebug(2, Form(" NOT bFOUND Id[%d] Mom[%f]\n", tt->GetTrackId(), mom)); + } + } + + AliDebug(2, Form("%3d Tracks: ESD[%3d] TPC[%3d] TRD[%3d | %5.2f%%] Off[%d]", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), fTracks->GetEntriesFast(), nTPC, nTRD, nTPC ? 1.E2*nTRD/float(nTPC) : 0., fMissed->GetEntriesFast())); + + //fMissed->Delete(); + // check for double countings + Int_t indices[10000]; memset(indices, 0, sizeof(Int_t) * 10000); + TMath::Sort(nTRD, labelsacc, indices); + if(DebugLevel() > 2){ + for(Int_t itk = 0; itk < nTRD - 1; itk++) + if(labelsacc[indices[itk]] ==labelsacc[indices[itk + 1]]) printf("Double counted MC track: %d\n", labelsacc[indices[itk]]); + } + PostData(0, fContainer); +} + + +//____________________________________________________________________ +Bool_t AliTRDefficiency::GetRefFigure(Int_t ifig) +{ +// Steer reference figures + + Bool_t bFIRST = kTRUE; + TProfile *h = 0x0; + switch(ifig){ + case 0: + h = (TProfile*)fContainer->At(AliPID::kSPECIES); + for(Int_t is=0; isAdd((TProfile*)fContainer->At(is)); + } + h->SetMarkerColor(kBlack); + h->SetLineColor(kBlack); + h->GetXaxis()->SetTitle("p [GeV/c]"); + h->Draw("e1"); + break; + case 1: + bFIRST = kTRUE; + for(Int_t is=0; isAt(is))) continue; + if(bFIRST){ + h->Draw("e1"); + h->GetXaxis()->SetTitle("p [GeV/c]"); + } else h->Draw("same e1"); + bFIRST = kFALSE; + } + break; + } + return kTRUE; +} + + +//____________________________________________________________________ +Bool_t AliTRDefficiency::PostProcess() +{ + fNRefFigures = HasMCdata() ? 2 : 1; + return kTRUE; +} diff --git a/PWG1/TRD/AliTRDefficiency.h b/PWG1/TRD/AliTRDefficiency.h new file mode 100644 index 00000000000..ea2739959e7 --- /dev/null +++ b/PWG1/TRD/AliTRDefficiency.h @@ -0,0 +1,43 @@ +#ifndef ALITRDEFFICIENCY_H +#define ALITRDEFFICIENCY_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/* $Id: AliTRDefficiency.h 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// Reconstruction QA // +// // +//////////////////////////////////////////////////////////////////////////// + +#ifndef ALITRDRECOTASK_H +#include "AliTRDrecoTask.h" +#endif + +class TObjArray; +class TList; +class TClonesArray; +class TTreeSRedirector; +class AliTRDefficiency : public AliTRDrecoTask +{ +public: + AliTRDefficiency(); + virtual ~AliTRDefficiency(); + void CreateOutputObjects(); + void Exec(Option_t *); + Bool_t GetRefFigure(Int_t ifig); + Bool_t PostProcess(); + +private: + AliTRDefficiency(const AliTRDefficiency&); + AliTRDefficiency& operator=(const AliTRDefficiency&); + +private: + TClonesArray *fMissed; // Missed ? + + ClassDef(AliTRDefficiency, 1) // TRD tracking efficiency +}; + +#endif + diff --git a/PWG1/TRD/AliTRDefficiencyMC.cxx b/PWG1/TRD/AliTRDefficiencyMC.cxx new file mode 100644 index 00000000000..12977579499 --- /dev/null +++ b/PWG1/TRD/AliTRDefficiencyMC.cxx @@ -0,0 +1,493 @@ +/************************************************************************** +* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* * +* Author: The ALICE Off-line Project. * +* Contributors are mentioned in the code where appropriate. * +* * +* Permission to use, copy, modify and distribute this software and its * +* documentation strictly for non-commercial purposes is hereby granted * +* without fee, provided that the above copyright notice appears in all * +* copies and that both the copyright notice and this permission notice * +* appear in the supporting documentation. The authors make no claims * +* about the suitability of this software for any purpose. It is * +* provided "as is" without express or implied warranty. * +**************************************************************************/ + +/* $Id: AliTRDefficiencyMC.cxx 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// Reconstruction QA // +// // +// Authors: // +// Markus Fasel // +// // +//////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "TTreeStream.h" + +#include "AliMagF.h" +#include "AliPID.h" +#include "AliMathBase.h" +#include "AliTrackReference.h" +#include "AliAnalysisManager.h" + +#include "AliTRDcluster.h" +#include "AliTRDseedV1.h" +#include "AliTRDtrackV1.h" +#include "Cal/AliTRDCalPID.h" +#include "info/AliTRDtrackInfo.h" +#include "AliTRDinfoGen.h" +#include "AliTRDefficiencyMC.h" + +ClassImp(AliTRDefficiencyMC) + +//_____________________________________________________________________________ +AliTRDefficiencyMC::AliTRDefficiencyMC() + :AliTRDrecoTask("EfficiencyMC", "Combined Tracking Efficiency") +{ + // + // Default constructor + // +} + + +//_____________________________________________________________________________ +void AliTRDefficiencyMC::CreateOutputObjects(){ + // + // Create output objects + // + + OpenFile(0, "RECREATE"); + fContainer = Histos(); + +} + +//_____________________________________________________________________________ +void AliTRDefficiencyMC::Exec(Option_t *){ + // + // Execute the task: + // + // Loop over TrackInfos + // 1st: check if there is a trackTRD + // 2nd: put conditions on the track: + // - check if we did not register it before + // - check if we have Track References for the track + // 3rd: Register track: + // - accepted if both conditions are fulfilled + // - contamination if at least one condition is not fulfilled + // 4th: check Monte-Carlo Track wheter findable or not if there is no TRD track in this track info + // 5th: register MC track as rejected if findable and not jet registered + // Match the registers accepted and rejected and clean register rejected + // Fill the histograms + // + const Int_t kArraySize = 10000; // Store indices of track references in an array + Int_t indexAccepted[kArraySize], indexRejected[kArraySize], indexContamination[kArraySize]; + memset(indexAccepted, 0, sizeof(Int_t) * kArraySize); + memset(indexRejected, 0, sizeof(Int_t) * kArraySize); + memset(indexContamination, 0, sizeof(Int_t) * kArraySize); + Int_t naccepted = 0, nrejected = 0, ncontamination = 0; + Bool_t isContamination = kFALSE; + + Int_t nTrackInfos = fTracks->GetEntriesFast(); + AliTRDtrackV1 *trackTRD = 0x0; + AliTRDtrackInfo *trkInf = 0x0; + for(Int_t itinf = 0; itinf < nTrackInfos; itinf++){ + trkInf = dynamic_cast(fTracks->UncheckedAt(itinf)); + if(!trkInf) continue; + if(trkInf->GetTrack() || trkInf->GetNumberOfClustersRefit()){ + isContamination = IsRegistered(trkInf,indexAccepted,naccepted); + if(!trkInf->GetNTrackRefs()){ + // We reject the track since the Monte Carlo Information is missing + AliDebug(1, Form("Error: Track Reference missing for Track %d", trkInf->GetLabel())); + isContamination = kTRUE; + // Debugging + if(trackTRD && DebugLevel() > 5) FillStreamTrackWOMC(trkInf); + } + if(isContamination){ + // reject kink (we count these only once) + if(trkInf->GetKinkIndex()) continue; + // Register track as contamination + indexContamination[ncontamination++]=itinf; + continue; + } + // Accept track + AliDebug(4, "Accept track"); + // Register track as accepted + indexAccepted[naccepted++] = itinf; + }else{ + if(IsFindable(trkInf)){ + // register track as rejected if not already registered there + // Attention: + // These track infos are not!!! registered as contamination + if(!IsRegistered(trkInf, indexRejected, nrejected)) indexRejected[nrejected++] = itinf; + } + } + } + // we have to check if the rejected tracks are registered as found + // a possible source for this: + // first the track is not found by the barrel tracking but it is later found + // by the stand alone tracking, then two track info objects with the same + // label would be created + // Attention: + // these tracks are not! registered as contamination + Int_t tmprejected[kArraySize]; Int_t nrej = nrejected; + memcpy(tmprejected, indexRejected, sizeof(Int_t) * nrejected); + nrejected = 0; + for(Int_t irej = 0; irej < nrej; irej++){ + trkInf = dynamic_cast(fTracks->At(tmprejected[irej])); + if(!IsRegistered(trkInf,indexAccepted,naccepted)) indexRejected[nrejected++] = tmprejected[irej]; + } + // Fill Histograms + FillHistograms(naccepted, &indexAccepted[0], kAccepted); + FillHistograms(nrejected, &indexRejected[0], kRejected); + FillHistograms(ncontamination, &indexContamination[0], kContamination); + Int_t nall = naccepted + nrejected; + //if(DebugLevel()>=1) + AliInfo(Form("%3d Tracks: MC[%3d] TRD[%3d | %5.2f%%] \n", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), nall, naccepted, nall ? 1.E2*Float_t(naccepted)/Float_t(nall) : 0.)); + AliInfo(Form("%3d Tracks: ALL[%3d] Contamination[%3d | %5.2f%%] \n", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), nall + ncontamination, ncontamination, nall ? 1.E2*Float_t(ncontamination)/Float_t(nall + ncontamination) : 0.)); + + PostData(0, fContainer); +} + + +//_____________________________________________________________________________ +Bool_t AliTRDefficiencyMC::PostProcess() +{ + // + // Post Process + // + // Change the histogram style + // For species histograms apply the colors connected with the given particle species + // + TH1 *histo = dynamic_cast(fContainer->At(kEfficiencyHistogram)); + histo->SetMarkerStyle(22); + histo->SetMarkerColor(kBlue); + histo->GetXaxis()->SetTitle("p [GeV/c]"); + histo->GetXaxis()->SetMoreLogLabels(); + histo->GetYaxis()->SetTitle("Efficiency [%]"); + histo->GetYaxis()->SetRangeUser(0.99, 1.005); + + histo = dynamic_cast(fContainer->At(kContaminationHistogram)); + histo->SetMarkerStyle(22); + histo->SetMarkerColor(kBlue); + histo->GetXaxis()->SetTitle("p [GeV/c]"); + histo->GetXaxis()->SetMoreLogLabels(); + histo->GetYaxis()->SetTitle("Contamination [%]"); + + // Species Efficiency Histograms + for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++){ + histo = dynamic_cast(fContainer->At(kEfficiencySpeciesHistogram + ispec)); + histo->SetMarkerStyle(22); + histo->SetLineColor(AliTRDCalPID::GetPartColor(ispec)); + histo->SetMarkerColor(AliTRDCalPID::GetPartColor(ispec)); + histo->GetXaxis()->SetTitle("p [GeV/c]"); + histo->GetXaxis()->SetMoreLogLabels(); + histo->GetYaxis()->SetTitle("Efficiency [%]"); + histo->GetYaxis()->SetRangeUser(0.99, 1.005); + } + + // Species Contamination Histograms + for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++){ + histo = dynamic_cast(fContainer->At(kContaminationSpeciesHistogram + ispec)); + histo->SetMarkerStyle(22); + histo->SetLineColor(AliTRDCalPID::GetPartColor(ispec)); + histo->SetMarkerColor(AliTRDCalPID::GetPartColor(ispec)); + histo->GetXaxis()->SetTitle("p [GeV/c]"); + histo->GetXaxis()->SetMoreLogLabels(); + histo->GetYaxis()->SetTitle("Contamination [%]"); + } + + fNRefFigures = 6; + return kTRUE; +} + +//_____________________________________________________________________________ +Bool_t AliTRDefficiencyMC::GetRefFigure(Int_t ifig){ + // + // Plot the histograms + // + if(ifig >= fNRefFigures) return kFALSE; + if(ifig < 2){ + (dynamic_cast(fContainer->At(ifig)))->Draw("e1"); + return kTRUE; + } + switch(ifig){ + case 2: + (dynamic_cast(fContainer->At(kEfficiencySpeciesHistogram)))->Draw("e1"); + for(Int_t ispec = 1; ispec < AliPID::kSPECIES; ispec++) + (dynamic_cast(fContainer->At(kEfficiencySpeciesHistogram + ispec)))->Draw("e1same"); + break; + case 3: + (dynamic_cast(fContainer->At(kContaminationSpeciesHistogram)))->Draw("e1"); + for(Int_t ispec = 1; ispec < AliPID::kSPECIES; ispec++) + (dynamic_cast(fContainer->At(kContaminationSpeciesHistogram + ispec)))->Draw("e1same"); + break; + case 4: + (dynamic_cast(fContainer->At(kEfficiencyNoPID)))->Draw("e1"); + break; + case 5: + (dynamic_cast(fContainer->At(kContaminationNoPID)))->Draw("e1"); + break; + } + return kTRUE; +} + +//_____________________________________________________________________________ +TObjArray *AliTRDefficiencyMC::Histos(){ + // + // Create the histograms + // + const Int_t nbins = 11; + + if(fContainer) return fContainer; + Float_t xbins[nbins+1] = {.5, .7, .9, 1.3, 1.7, 2.4, 3.5, 4.5, 5.5, 7., 9., 11.}; + + TString species[AliPID::kSPECIES] = {"Pions", "Muons", "Electrons", "Kaons", "Protons"}; + TString species_short[AliPID::kSPECIES] = {"Pi", "Mu", "El", "Ka", "Pr"}; + + fContainer = new TObjArray(); + fContainer->AddAt(new TProfile("trEffComb", "Combined Tracking Efficiency", nbins, xbins), kEfficiencyHistogram); + fContainer->AddAt(new TProfile("trContComb", "Combined Tracking Contamination", nbins, xbins), kContaminationHistogram); + for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++) + fContainer->AddAt(new TProfile(Form("trEffComb%s", species_short[ispec].Data()), Form("Combined Tracking Efficiency %s", species[ispec].Data()), nbins, xbins), kEfficiencySpeciesHistogram + ispec); + for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++) + fContainer->AddAt(new TProfile(Form("trContComb%s", species_short[ispec].Data()), Form("Combined Tracking Contamination %s", species[ispec].Data()), nbins, xbins), kContaminationSpeciesHistogram + ispec); + fContainer->AddAt(new TProfile("trEffCombNoPID", "Combined Tracking Efficiency", nbins, xbins), kEfficiencyNoPID); + fContainer->AddAt(new TProfile("trContCombNoPID", "Combined Tracking Contamination", nbins, xbins), kContaminationNoPID); + return fContainer; +} + +//_____________________________________________________________________________ +Bool_t AliTRDefficiencyMC::IsFindable(AliTRDtrackInfo * const trkInf){ + // + // Apply Cuts on the Monte Carlo track references + // return whether track is findable or not + // + const Float_t kAlpha = 0.349065850; + + AliDebug(10, "Analysing Track References\n"); + // Check if track is findable + Double_t mom = 0.; + Float_t xmin = 10000.0, xmax = 0.0; + Float_t ymin = 0.0, ymax = 0.0; + Float_t zmin = 0.0, zmax = 0.0; + Float_t lastx = 0.0, x = 0.0; + Int_t nLayers = 0; + Int_t sector[20]; + AliTrackReference *trackRef = 0x0; + for(Int_t itr = 0; itr < trkInf->GetNTrackRefs(); itr++){ + trackRef = trkInf->GetTrackRef(itr); + AliDebug(10, Form("%d. x[%f], y[%f], z[%f]\n", itr, trackRef->LocalX(), trackRef->LocalY(), trackRef->Z())); + x = trackRef->LocalX(); + + // Be Sure that we are inside TRD + if(x < AliTRDinfoGen::GetTPCx() || x > AliTRDinfoGen::GetTOFx()) continue; + sector[itr] = Int_t(trackRef->Alpha()/kAlpha); + if(x < xmin){ + xmin = trackRef->LocalX(); + ymin = trackRef->LocalY(); + zmin = trackRef->Z(); + mom = trackRef->P(); + } else if(x > xmax){ + xmax = trackRef->LocalX(); + ymax = trackRef->LocalY(); + zmax = trackRef->Z(); + } + if(itr > 0){ + Float_t dist = TMath::Abs(x - lastx); + AliDebug(10, Form("x = %f, lastx = %f, dist = %f\n", x, lastx, dist)); + if(TMath::Abs(dist - 3.7) < 0.1) nLayers++; // ref(i+1) has to be larger than ref(i) + } + lastx = x; + } + + // Apply cuts + Bool_t findable = kTRUE; + if(trkInf->GetNTrackRefs() > 2 && xmax > xmin){ + if(mom < 0.55) findable = kFALSE; // momentum cut at 0.6 + Double_t yangle = (ymax -ymin)/(xmax - xmin); + Double_t zangle = (zmax -zmin)/(xmax - xmin); + AliDebug(10, Form("\ntrack: y-Angle = %f, z-Angle = %f\nnLayers = %d", yangle, zangle, nLayers)); + if(TMath::ATan(TMath::Abs(yangle)) > 45.) findable = kFALSE; + if(TMath::ATan(TMath::Abs(zangle)) > 45.) findable = kFALSE; + if(nLayers < 4) findable = kFALSE; + if(!trkInf->IsPrimary()) findable = kFALSE; + Bool_t samesec = kTRUE; + for(Int_t iref = 1; iref < trkInf->GetNTrackRefs(); iref++) + if(sector[iref] != sector[0]) samesec = kFALSE; + if(!samesec) findable = kFALSE; // Discard all tracks which are passing more than one sector + if(DebugLevel()){ + Double_t trackAngle = TMath::ATan(yangle); + Bool_t primary = trkInf->IsPrimary(); + (*DebugStream()) << "NotFoundTrack" + << "Momentum=" << mom + << "trackAngle="<< trackAngle + << "NLayers=" << nLayers + << "Primary=" << primary + << "\n"; + } + } + else + findable = kFALSE; + return findable; +} + +//_____________________________________________________________________________ +void AliTRDefficiencyMC::FillHistograms(Int_t nTracks, Int_t *indices, FillingMode_t mode){ + // + // Fill Histograms in three different modes: + // 1st tracks which are found and accepted + // 2nd tracks which are not found and not already counted + // 3rd contaminating tracks: either double counts (kinks!) or tracks with no MC hit inside TRD + // + const Int_t pid[AliPID::kSPECIES] = {211,13,11,321,2212}; + Double_t trkmom = 0.; // the track momentum + Int_t trkpid = -1; // particle species + AliTRDtrackInfo *trkInf = 0x0; + for(Int_t itk = 0; itk < nTracks; itk++){ + trkInf = dynamic_cast(fTracks->At(indices[itk])); + AliDebug(3, Form("Accepted MC track: %d\n", trkInf->GetLabel())); + if(trkInf->GetNTrackRefs()){ + // use Monte-Carlo Information for Momentum and PID + trkmom = trkInf->GetTrackRef(0)->P(); + trkpid = trkInf->GetPDG(); + }else{ + // Use TPC Momentum + trkmom = trkInf->GetTrack()->P(); + } + switch(mode){ + case kAccepted: + (dynamic_cast(fContainer->At(kEfficiencyHistogram)))->Fill(trkmom, 1); + (dynamic_cast(fContainer->At(kContaminationHistogram)))->Fill(trkmom, 0); + break; + case kRejected: + (dynamic_cast(fContainer->At(kEfficiencyHistogram)))->Fill(trkmom, 0); + (dynamic_cast(fContainer->At(kContaminationHistogram)))->Fill(trkmom, 0); + break; + case kContamination: + (dynamic_cast(fContainer->At(kContaminationHistogram)))->Fill(trkmom, 1); + break; + } + // Fill species histogram + Int_t partSpec = -1; + for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++){ + if(trkpid == pid[ispec]) partSpec = ispec; + } + if(partSpec >= 0){ + switch(mode){ + case kAccepted: + (dynamic_cast(fContainer->At(kEfficiencySpeciesHistogram + partSpec)))->Fill(trkmom, 1); + (dynamic_cast(fContainer->At(kContaminationSpeciesHistogram + partSpec)))->Fill(trkmom, 0); + break; + case kRejected: + (dynamic_cast(fContainer->At(kEfficiencySpeciesHistogram + partSpec)))->Fill(trkmom, 0); (dynamic_cast(fContainer->At(kContaminationSpeciesHistogram + partSpec)))->Fill(trkmom, 0); + break; + case kContamination: + (dynamic_cast(fContainer->At(kContaminationSpeciesHistogram + partSpec)))->Fill(trkmom, 1); + break; + } + } else { + // The particle Type is not registered + (dynamic_cast(fContainer->At(kEfficiencyNoPID)))->Fill(trkmom, 1); + (dynamic_cast(fContainer->At(kContaminationNoPID)))->Fill(trkmom, 1); + } + } +} + +//_____________________________________________________________________________ +void AliTRDefficiencyMC::FillStreamTrackWOMC(AliTRDtrackInfo * const trkInf){ + // fill debug stream + // we want to know: + // 1. The event number + // 2. The track label + // 3. The TRD track label + // 4. The frequency of the TRD Label + // 5. Momentum from TPC (NO STAND ALONE TRACK) + // 6. TPC Phi angle + // 7. the TRD track + // 8. Monte Carlo PID + // 9. We check the Labels of the TRD track according to them we search the maching Monte-Carlo track. + // From the matching Monte-Carlo track we store trackRefs, phi and momentum + // 10. We may also want to keep the kink index + Double_t mom = trkInf->GetESDinfo()->GetOuterParam()->P(); + Int_t event = (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(); + Int_t label = trkInf->GetLabel(); + Int_t kinkIndex = trkInf->GetKinkIndex(); + Int_t pdg = trkInf->GetPDG(); + Double_t phiTPC = trkInf->GetESDinfo()->GetOuterParam()->Phi(); + Int_t labelsTRD[180]; // Container for the cluster labels + Int_t sortlabels[360]; // Cluster Labels sorted according their occurancy + AliTRDseedV1 *tracklet = 0x0; + AliTRDcluster *c = 0x0; + Int_t nclusters = 0x0; + AliTRDtrackV1 *trackTRD = trkInf->GetTrack(); + for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){ + tracklet = trackTRD->GetTracklet(il); + if(!tracklet) continue; + tracklet->ResetClusterIter(); + c = 0x0; + while((c = tracklet->NextCluster())) labelsTRD[nclusters++] = c->GetLabel(0); + } + // Determine Label and Frequency + AliMathBase::Freq(nclusters, const_cast(&labelsTRD[0]), &sortlabels[0], kTRUE); + Int_t labelTRD = sortlabels[0]; + Int_t freqTRD = sortlabels[1]; + // find the track info object matching to the TRD track + AliTRDtrackInfo *realtrack = 0; + TObjArrayIter rtiter(fTracks); + while((realtrack = (AliTRDtrackInfo *)rtiter())){ + if(realtrack->GetLabel() != labelTRD) continue; + break; + } + TClonesArray trackRefs("AliTrackReference"); + Int_t realPdg = -1; + Double_t realP = 0.; + Double_t realPhi = 0.; + if(realtrack){ + // pack the track references into the trackRefsContainer + for(Int_t iref = 0; iref < realtrack->GetNTrackRefs(); iref++){ + new(trackRefs[iref])AliTrackReference(*(realtrack->GetTrackRef(iref))); + } + realPdg = realtrack->GetPDG(); + if(realtrack->GetNTrackRefs()){ + realP = realtrack->GetTrackRef(0)->P(); + realPhi = realtrack->GetTrackRef(0)->Phi(); + } + } + (*DebugStream()) << "TrackingEffMCfake" + << "Event=" << event + << "Label=" << label + << "labelTRD=" << labelTRD + << "FreqTRDlabel=" << freqTRD + << "TPCp=" << mom + << "phiTPC=" << phiTPC + << "trackTRD=" << trackTRD + << "PDG=" << pdg + << "TrackRefs=" << &trackRefs + << "RealPDG=" << realPdg + << "RealP=" << realP + << "RealPhi" << realPhi + << "KinkIndex=" << kinkIndex + << "\n"; +} + +//_____________________________________________________________________________ +Bool_t AliTRDefficiencyMC::IsRegistered(AliTRDtrackInfo * const trkInf, Int_t *indices, Int_t nTracks){ + // + // Checks if track is registered in a given mode + // + Bool_t isRegistered = kFALSE; + for(Int_t il = 0; il < nTracks; il++){ + if((dynamic_cast(fTracks->At(indices[il])))->GetLabel() == trkInf->GetLabel()){ + isRegistered = kTRUE; + break; + } + } + return isRegistered; +} + diff --git a/PWG1/TRD/AliTRDefficiencyMC.h b/PWG1/TRD/AliTRDefficiencyMC.h new file mode 100644 index 00000000000..b0890ac3205 --- /dev/null +++ b/PWG1/TRD/AliTRDefficiencyMC.h @@ -0,0 +1,56 @@ +#ifndef ALITRDEFFICIENCYMC_H +#define ALITRDEFFICIENCYMC_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* See cxx source for full Copyright notice */ + +/* $Id: AliTRDefficiencyMC.h 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// Reconstruction QA // +// // +//////////////////////////////////////////////////////////////////////////// + +#ifndef ALITRDRECOTASK_H +#include "AliTRDrecoTask.h" +#endif + +class AliTRDefficiencyMC : public AliTRDrecoTask{ +public: + AliTRDefficiencyMC(); + virtual ~AliTRDefficiencyMC(){;} + + void CreateOutputObjects(); + void Exec(Option_t *); + + Bool_t PostProcess(); + TObjArray* Histos(); + Bool_t GetRefFigure(Int_t ifig); + +private: + enum{ + kEfficiencyHistogram = 0, + kContaminationHistogram = 1, + kEfficiencySpeciesHistogram = 2, + kContaminationSpeciesHistogram = 7, + kEfficiencyNoPID = 12, + kContaminationNoPID = 13 + }; + typedef enum{ + kAccepted = 0, + kRejected = 1, + kContamination = 2 + } FillingMode_t; + AliTRDefficiencyMC(const AliTRDefficiencyMC &); + AliTRDefficiencyMC& operator=(const AliTRDefficiencyMC &); + + void FillHistograms(Int_t ntracks, Int_t *indices, FillingMode_t mode); + void FillStreamTrackWOMC(AliTRDtrackInfo * const trkInf); + + Bool_t IsFindable(AliTRDtrackInfo * const trkInf); + Bool_t IsRegistered(AliTRDtrackInfo * const trkInf, Int_t *indices, Int_t nTracks); + + ClassDef(AliTRDefficiencyMC, 1); // Combined tracking efficiency +}; + +#endif diff --git a/PWG1/TRD/AliTRDinfoGen.cxx b/PWG1/TRD/AliTRDinfoGen.cxx new file mode 100644 index 00000000000..4dc3f59846f --- /dev/null +++ b/PWG1/TRD/AliTRDinfoGen.cxx @@ -0,0 +1,377 @@ +/************************************************************************** +* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* * +* Author: The ALICE Off-line Project. * +* Contributors are mentioned in the code where appropriate. * +* * +* Permission to use, copy, modify and distribute this software and its * +* documentation strictly for non-commercial purposes is hereby granted * +* without fee, provided that the above copyright notice appears in all * +* copies and that both the copyright notice and this permission notice * +* appear in the supporting documentation. The authors make no claims * +* about the suitability of this software for any purpose. It is * +* provided "as is" without express or implied warranty. * +**************************************************************************/ + +/* $Id: AliTRDinfoGen.cxx 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// +// Tender wagon for TRD performance/calibration train +// +// In this wagon the information from +// - ESD +// - Friends [if available] +// - MC [if available] +// are grouped into AliTRDtrackInfo objects and fed to worker tasks +// +// Authors: +// Markus Fasel +// Alexandru Bercuci +// +//////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AliLog.h" +#include "AliAnalysisManager.h" +#include "AliESDEvent.h" +#include "AliMCEvent.h" +#include "AliESDInputHandler.h" +#include "AliMCEventHandler.h" + +#include "AliESDfriend.h" +#include "AliESDfriendTrack.h" +#include "AliESDHeader.h" +#include "AliESDtrack.h" +#include "AliMCParticle.h" +#include "AliPID.h" +#include "AliStack.h" +#include "AliTRDtrackV1.h" +#include "AliTrackReference.h" +#include "AliTRDgeometry.h" +#include "AliTRDcluster.h" +#include "AliTRDseedV1.h" +#include "TTreeStream.h" + +#include +#include +#include +#include + +#include "AliTRDinfoGen.h" +#include "info/AliTRDtrackInfo.h" +#include "info/AliTRDeventInfo.h" +#include "info/AliTRDv0Info.h" + +ClassImp(AliTRDinfoGen) + +const Float_t AliTRDinfoGen::fgkTPC = 290.; +const Float_t AliTRDinfoGen::fgkTOF = 365.; + +//____________________________________________________________________ +AliTRDinfoGen::AliTRDinfoGen(): + AliTRDrecoTask("infoGen", "MC-REC TRD-track list generator") + ,fESDev(0x0) + ,fMCev(0x0) + ,fESDfriend(0x0) + ,fTrackInfo(0x0) + ,fEventInfo(0x0) + ,fV0container(0x0) + ,fV0Info(0x0) +{ + // + // Default constructor + // + + DefineInput(0, TChain::Class()); + DefineOutput(0, TObjArray::Class()); + DefineOutput(1, AliTRDeventInfo::Class()); + DefineOutput(2, TObjArray::Class()); +} + +//____________________________________________________________________ +AliTRDinfoGen::~AliTRDinfoGen() +{ +// Destructor + if(fTrackInfo) delete fTrackInfo; fTrackInfo = 0x0; + if(fEventInfo) delete fEventInfo; fEventInfo = 0x0; + if(fV0Info) delete fV0Info; fV0Info = 0x0; + if(fContainer){ + fContainer->Delete(); delete fContainer; + fContainer = 0x0; + } + if(fV0container){ + fV0container->Delete(); delete fV0container; + fV0container = 0x0; + } +} + +//____________________________________________________________________ +void AliTRDinfoGen::ConnectInputData(Option_t *) +{ + // + // Link the Input Data + // + TTree *tree = dynamic_cast(GetInputData(0)); + if(!tree){ + printf("ERROR - ESD event not found"); + } else { + tree->SetBranchStatus("Tracks", 1); + tree->SetBranchStatus("ESDfriend*",1); + } + + AliESDInputHandler *esdH = dynamic_cast(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()); + if(!esdH){ + printf("ERROR - ESD input handler not found"); + } else { + fESDev = esdH->GetEvent(); + if(!fESDev){ + printf("ERROR - ESD event not found"); + } else { + esdH->SetActiveBranches("ESDfriend*"); + fESDfriend = (AliESDfriend *)fESDev->FindListObject("AliESDfriend"); + } + } + if(HasMCdata()){ + AliMCEventHandler *mcH = dynamic_cast(AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler()); + if(!mcH){ + AliError("MC input handler not found"); + } else { + fMCev = mcH->MCEvent(); + } + } +} + +//____________________________________________________________________ +void AliTRDinfoGen::CreateOutputObjects() +{ + // + // Create Output Containers (TObjectArray containing 1D histograms) + // + fTrackInfo = new AliTRDtrackInfo(); + fEventInfo = new AliTRDeventInfo(); + fV0Info = new AliTRDv0Info(); + fContainer = new TObjArray(1000); + fContainer->SetOwner(kTRUE); + fV0container = new TObjArray(50); + fV0container->SetOwner(kTRUE); + +} + +//____________________________________________________________________ +void AliTRDinfoGen::Exec(Option_t *){ + // + // Run the Analysis + // + if(!fESDev){ + AliError("Failed retrieving ESD event"); + return; + } + if(!fESDfriend){ + AliError("Failed retrieving ESD friend event"); + return; + } + if(HasMCdata() && !fMCev){ + AliError("Failed retrieving MC event"); + return; + } + fContainer->Delete(); + fV0container->Delete(); + fEventInfo->Delete(""); + fESDev->SetESDfriend(fESDfriend); + new(fEventInfo)AliTRDeventInfo(fESDev->GetHeader(), const_cast(fESDev->GetESDRun())); + + Bool_t *trackMap = 0x0; + AliStack * mStack = 0x0; + Int_t nTracksMC = HasMCdata() ? fMCev->GetNumberOfTracks() : 0, nTracksESD = fESDev->GetNumberOfTracks(); + if(HasMCdata()){ + mStack = fMCev->Stack(); + if(!mStack){ + AliError("Failed retrieving MC Stack"); + return; + } + trackMap = new Bool_t[nTracksMC]; + memset(trackMap, 0, sizeof(Bool_t) * nTracksMC); + } + + Int_t nTRD = 0, nTPC = 0, nclsTrklt; + AliDebug(2, Form("Entry[%3d] Tracks: ESD[%d] MC[%d]\n", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), nTracksESD, nTracksMC)); + AliESDtrack *esdTrack = 0x0; + AliESDfriendTrack *esdFriendTrack = 0x0; + TObject *calObject = 0x0; + AliTRDtrackV1 *track = 0x0; + AliTRDseedV1 *tracklet = 0x0; + AliTRDcluster *cl = 0x0; + for(Int_t itrk = 0; itrk < nTracksESD; itrk++){ + esdTrack = fESDev->GetTrack(itrk); + AliDebug(3, Form("\n%3d ITS[%d] TPC[%d] TRD[%d]\n", itrk, esdTrack->GetNcls(0), esdTrack->GetNcls(1), esdTrack->GetNcls(2))); + if(esdTrack->GetNcls(1)) nTPC++; + if(esdTrack->GetNcls(2)) nTRD++; + + // look at external track param + const AliExternalTrackParam *op = esdTrack->GetOuterParam(); + Double_t xyz[3]; + if(op){ + op->GetXYZ(xyz); + op->Global2LocalPosition(xyz, op->GetAlpha()); + AliDebug(3, Form("op @ X[%7.3f]\n", xyz[0])); + } + + // read MC info + Int_t fPdg = -1; + Int_t label = -1; UInt_t alab=UINT_MAX; + if(HasMCdata()){ + label = esdTrack->GetLabel(); + alab = TMath::Abs(label); + // register the track + if(alab < UInt_t(nTracksMC)){ + trackMap[alab] = kTRUE; + } else { + AliError(Form("MC label[%d] outside scope for Ev[%d] Trk[%d].", label, (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), itrk)); + continue; + } + AliMCParticle *mcParticle = 0x0; + if(!(mcParticle = (AliMCParticle*) fMCev->GetTrack(alab))){ + AliError(Form("MC particle label[%d] missing for Ev[%d] Trk[%d].", label, (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), itrk)); + continue; + } + fPdg = mcParticle->Particle()->GetPdgCode(); + Int_t nRefs = mcParticle->GetNumberOfTrackReferences(); + Int_t iref = 0; AliTrackReference *ref = 0x0; + while(irefGetTrackReference(iref); + if(ref->LocalX() > fgkTPC) break; + iref++; + } + + new(fTrackInfo) AliTRDtrackInfo(); + fTrackInfo->SetPDG(fPdg); + fTrackInfo->SetPrimary(mcParticle->Particle()->IsPrimary()); + Int_t jref = iref;//, kref = 0; + while(jrefGetTrackReference(jref); + if(ref->LocalX() > fgkTOF) break; + AliDebug(4, Form(" trackRef[%2d (%2d)] @ %7.3f OK", jref-iref, jref, ref->LocalX())); + fTrackInfo->AddTrackRef(ref); + jref++; + } + AliDebug(3, Form("NtrackRefs[%d(%d)]", fTrackInfo->GetNTrackRefs(), nRefs)); + } else { + new (fTrackInfo) AliTRDtrackInfo(); + fTrackInfo->SetPDG(fPdg); + } + + // copy some relevant info to TRD track info + fTrackInfo->SetStatus(esdTrack->GetStatus()); + fTrackInfo->SetTrackId(esdTrack->GetID()); + Double_t p[AliPID::kSPECIES]; esdTrack->GetTRDpid(p); + fTrackInfo->SetESDpid(p); + fTrackInfo->SetESDpidQuality(esdTrack->GetTRDntrackletsPID()); + fTrackInfo->SetLabel(label); + fTrackInfo->SetNumberOfClustersRefit(esdTrack->GetNcls(2)); + // some other Informations which we may wish to store in order to find problematic cases + fTrackInfo->SetKinkIndex(esdTrack->GetKinkIndex(0)); + fTrackInfo->SetTPCncls(static_cast(esdTrack->GetNcls(1))); + nclsTrklt = 0; + + + // read REC info + esdFriendTrack = fESDfriend->GetTrack(itrk); + if(esdFriendTrack){ + Int_t icalib = 0; + while((calObject = esdFriendTrack->GetCalibObject(icalib++))){ + if(strcmp(calObject->IsA()->GetName(),"AliTRDtrackV1") != 0) continue; // Look for the TRDtrack + if(!(track = dynamic_cast(calObject))) break; + nTRD++; + AliDebug(4, Form("TRD track OK")); + // Set the clusters to unused + for(Int_t ipl = 0; ipl < AliTRDgeometry::kNlayer; ipl++){ + if(!(tracklet = track->GetTracklet(ipl))) continue; + tracklet->ResetClusterIter(); + while((cl = tracklet->NextCluster())) cl->Use(0); + } + fTrackInfo->SetTrack(track); + break; + } + AliDebug(3, Form("Ntracklets[%d]\n", fTrackInfo->GetNTracklets())); + } else AliDebug(3, "No ESD friends"); + if(op) fTrackInfo->SetOuterParam(op); + + if(DebugLevel() >= 1){ + AliTRDtrackInfo info(*fTrackInfo); + (*DebugStream()) << "trackInfo" + << "TrackInfo.=" << &info + << "\n"; + info.Delete(""); + } + + fContainer->Add(new AliTRDtrackInfo(*fTrackInfo)); + fTrackInfo->Delete(""); + } + AliDebug(3, Form("%3d Tracks: TPC[%d] TRD[%d]\n", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), nTPC, nTRD)); + +// AliESDv0 *v0 = 0x0; +// for(Int_t iv0=0; iv0GetNumberOfV0s(); iv0++){ +// if(!(v0 = fESD->GetV0(iv0))) continue; +// fV0container->Add(new AliTRDv0Info(v0)); +// } + + // Insert also MC tracks which are passing TRD where the track is not reconstructed + if(HasMCdata()){ + AliDebug(10, "Output of the MC track map:"); + for(Int_t itk = 0; itk < nTracksMC; itk++) AliDebug(10, Form("trackMap[%d] = %s", itk, trackMap[itk] == kTRUE ? "TRUE" : "kFALSE")); + + for(Int_t itk = 0; itk < nTracksMC; itk++){ + if(trackMap[itk]) continue; + AliMCParticle *mcParticle = (AliMCParticle*) fMCev->GetTrack(TMath::Abs(itk)); + Int_t fPdg = mcParticle->Particle()->GetPdgCode(); + Int_t nRefs = mcParticle->GetNumberOfTrackReferences(); + Int_t iref = 0; AliTrackReference *ref = 0x0; + Int_t nRefsTRD = 0; + new(fTrackInfo) AliTRDtrackInfo(); + fTrackInfo->SetPDG(fPdg); + while(irefGetTrackReference(iref); + if(ref->LocalX() > 250. && ref->LocalX() < 370.){ + AliDebug(4, Form(" trackRef[%2d] @ %7.3f IN", iref, ref->LocalX())); + fTrackInfo->AddTrackRef(ref); + nRefsTRD++; + } + else AliDebug(4, Form(" trackRef[%2d] @ %7.3f OUT", iref, ref->LocalX())); + iref++; + } + if(!nRefsTRD){ + // In this stage we at least require 1 hit inside TRD. What will be done with this tracks is a task for the + // analysis job + fTrackInfo->Delete(""); + continue; + } + fTrackInfo->SetPrimary(mcParticle->Particle()->IsPrimary()); + fTrackInfo->SetLabel(itk); + if(DebugLevel() >= 1){ + AliTRDtrackInfo info(*fTrackInfo); + (*DebugStream()) << "trackInfo" + << "TrackInfo.=" << &info + << "\n"; + info.Delete(""); + } + AliDebug(3, Form("Registering rejected MC track with label %d", itk)); + fContainer->Add(new AliTRDtrackInfo(*fTrackInfo)); + fTrackInfo->Delete(""); + } + delete[] trackMap; + } + PostData(0, fContainer); + PostData(1, fEventInfo); + PostData(2, fV0container); +} + diff --git a/PWG1/TRD/AliTRDinfoGen.h b/PWG1/TRD/AliTRDinfoGen.h new file mode 100644 index 00000000000..61dafcc0539 --- /dev/null +++ b/PWG1/TRD/AliTRDinfoGen.h @@ -0,0 +1,55 @@ +#ifndef ALITRDINFOGEN_H +#define ALITRDINFOGEN_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/* $Id: AliTRDinfoGen.h 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// Reconstruction QA // +// // +//////////////////////////////////////////////////////////////////////////// + +#ifndef ALITRDRECOTASK_H +#include "AliTRDrecoTask.h" +#endif + +class AliESDEvent; +class AliMCEvent; +class AliESDfriend; +class AliTRDtrackInfo; +class AliTRDeventInfo; +class AliTRDv0Info; +class TObjArray; +class TTreeSRedirector; +class AliTRDinfoGen : public AliTRDrecoTask{ +public: + + AliTRDinfoGen(); + virtual ~AliTRDinfoGen(); + + void ConnectInputData(Option_t *); + void CreateOutputObjects(); + void Exec(Option_t *); + static Float_t GetTPCx() { return fgkTPC;} + static Float_t GetTOFx() { return fgkTOF;} + +private: + static const Float_t fgkTPC; // end TPC radial position + static const Float_t fgkTOF; // begin TOF radial position + + AliTRDinfoGen(const AliTRDinfoGen&); + AliTRDinfoGen& operator=(const AliTRDinfoGen&); + + AliESDEvent *fESDev; //! ESD event + AliMCEvent *fMCev; //! MC event + AliESDfriend *fESDfriend; //! ESD friends + AliTRDtrackInfo *fTrackInfo; //! Track info + AliTRDeventInfo *fEventInfo; //! Event info + TObjArray *fV0container; //! V0 container + AliTRDv0Info *fV0Info; //! V0 info + + ClassDef(AliTRDinfoGen, 2) // entry to TRD analysis train +}; +#endif diff --git a/PWG1/TRD/AliTRDmultiplicity.cxx b/PWG1/TRD/AliTRDmultiplicity.cxx new file mode 100644 index 00000000000..619c89dea66 --- /dev/null +++ b/PWG1/TRD/AliTRDmultiplicity.cxx @@ -0,0 +1,288 @@ +/************************************************************************** + * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * * + * Author: The ALICE Off-line Project. * + * Contributors are mentioned in the code where appropriate. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + + +//////////////////////////////////////////////////////////////////////////// +// // +// TRD multiplicity // +// // +// Task to select true single tracks +// +// Program flow: +// Part A - task AliTRDmultiplicity (within the framework qaRec): +// For TRD standalone or TRD&TOF tracks I make a FitRiemanTilt +// The resulting parameterization is dumped into a DebugStreamer written to a file +// +// Part B – $ALICE_ROOT/TRD/qaRec/macros/TrackletsinTRD.C[h] (analysis macro): +// The clusters are read in +// The above produced file is read in +// I make a fit through the parameterization of the FitRiemanTilt -> in order to get a straight line (representing the track) +// the distance of each cluster with respect to the straight line is calculated +// If there is no cluster at a distance of 0.6 to 2 with respect to the track, the track is defined as a good track, i.e. clean single track +// // +// Authors: Yvonne C. Pachmayer // +// // +//////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +#include "AliESDtrack.h" +#include "AliExternalTrackParam.h" +#include "AliTRDseedV1.h" +#include "AliTRDtrackV1.h" +#include "AliTRDtrackerV1.h" +#include "AliTrackPointArray.h" + +#include "AliTRDmultiplicity.h" +#include "AliTRDgeometry.h" +#include "info/AliTRDtrackInfo.h" + +ClassImp(AliTRDmultiplicity) + +//____________________________________________________________________ +AliTRDmultiplicity::AliTRDmultiplicity() + :AliTRDrecoTask("Multiplicity", "Barrel Tracking Multiplicity") + ,fEventCounter(0) +{ + // + // Default constructor + // +} + +//____________________________________________________________________ +AliTRDmultiplicity::~AliTRDmultiplicity() +{ +} + +//____________________________________________________________________ +void AliTRDmultiplicity::CreateOutputObjects() +{ + // + // Create output objects + // + + OpenFile(0, "RECREATE"); + + TH1 *h = 0x0; + fContainer = new TObjArray(); + for(Int_t is=0; isAdd(h = new TH1F(Form("h_sector_%i", is), " ", 100,-10,10)); + } +} + +//____________________________________________________________________ +void AliTRDmultiplicity::Exec(Option_t *) +{ + // + // Do it + // + + + + ULong_t status; + AliTRDtrackInfo *track = 0x0; + AliExternalTrackParam *esd = 0x0; + AliTRDtrackV1 *trackTRD = 0x0; + Double_t x_anode[AliTRDgeometry::kNlayer] = {300.2, 312.8, 325.4, 338.0, 350.6, 363.2}; // Take the default X0 + Int_t standAlone=1; + fEventCounter++; + + + for(Int_t itrk=0; itrkGetEntriesFast(); itrk++){ + track = (AliTRDtrackInfo*)fTracks->UncheckedAt(itrk); + if(!track->HasESDtrack()) continue; + status = track->GetStatus(); + + AliTrackPoint points[6]; + Float_t xyz[3]; + memset(xyz, 0, sizeof(Float_t) * 3); + Float_t trackletX[6]; + Float_t trackletY[6]; + Float_t trackletZ[6]; + for(Int_t a=0;a<6;a++) + { + xyz[0] = x_anode[a]; + points[a].SetXYZ(xyz); + trackletX[a]=-1000; + trackletY[a]=-1000; + trackletZ[a]=-1000; + } + Int_t detTracklet=600; + + + + // TRD standalone + if(((status&AliESDtrack::kTRDout)>0) && !((status&AliESDtrack::kTRDin)>0)) + { + trackTRD = track->GetTrack(); + + if(trackTRD) + { + AliTRDseedV1 *tracklet = 0x0; + Int_t counterTracklet=0; + for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++) + { + tracklet = trackTRD->GetTracklet(itl); + if(tracklet) + { + if(tracklet->IsOK()) + { + counterTracklet++; + detTracklet=tracklet->GetDetector(); + //printf("%i %f %f \n",itl,tracklet->GetYfit(0),tracklet->GetZfit(0)); + trackletX[itl]=tracklet->GetX0(); + trackletY[itl]=tracklet->GetYfit(0); + trackletZ[itl]=tracklet->GetZfit(0); + } + } + } + // this cut is needed otherwise the order of tracklets in the fit function is not correct + if(counterTracklet==AliTRDgeometry::kNlayer) AliTRDtrackerV1::FitRiemanTilt(const_cast(trackTRD), 0x0, kTRUE, counterTracklet, points); + else continue; + + if(DebugLevel()>=1){ + for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){ + //printf("---------------------------------------- %i %i %f %f %f \n",counterTracklet,il,points[il].GetX(),points[il].GetY(),points[il].GetZ()); + Double_t pointX=points[il].GetX(); + Double_t pointY=points[il].GetY(); + Double_t pointZ=points[il].GetZ(); + + + (*DebugStream()) << "TrackletsinTRD" + << "standalone=" << standAlone + << "eventcounter=" << fEventCounter + << "layer=" << il + << "dettracklet=" << detTracklet + << "xtracklet=" << trackletX[il] + << "xtrack=" << pointX + << "ytracklet=" << trackletY[il] + << "ytrack=" << pointY + << "ztracklet=" << trackletZ[il] + << "ztrack=" << pointZ + << "num_tracklets=" << counterTracklet + << "\n"; + + } + } + } + } // end TRD standalone + + + + // TPC cluster selection for cosmic data + if((track->GetTPCncls())<40) continue; + // missing TPC propagation + if(!(status&AliESDtrack::kTPCout)) continue; + standAlone=0; + + esd = track->GetESDinfo()->GetOuterParam(); + // calculate sector - does not matter if track ends in TPC or TRD - sector number independent + Double_t alpha; + alpha=-100; + Int_t fSector=100; + if(esd){ + alpha=esd->GetAlpha(); + fSector = (Int_t)((alpha+ TMath::Pi())/(20*TMath::Pi()/180)); + if((fSector>-1) && (fSector<18)) + { + } + else + { + continue; + } + } + + + + // only these sectors have a TRD detector at the moment + if(fSector==0||fSector==8||fSector==9||fSector==17) + { + trackTRD = track->GetTrack(); + if(!trackTRD) continue; + AliTRDseedV1 *tracklet = 0x0; + Int_t counterTracklet=0; + + + for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){ + tracklet = trackTRD->GetTracklet(itl); + if(!tracklet || !tracklet->IsOK()) continue; + counterTracklet++; + detTracklet=tracklet->GetDetector(); + trackletX[itl]=tracklet->GetX0(); + trackletY[itl]=tracklet->GetYfit(0); + trackletZ[itl]=tracklet->GetZfit(0); + + /* + AliTRDcluster *c = 0x0; + for(Int_t itime = 0; itime < AliTRDseedV1::kNtb; itime++){ + c = tracklet->GetClusters(itime); + if(!c) continue; +// Float_t cluster_x = c->GetX(); +// Bool_t isprop; +// isprop=kFALSE; +// isprop=AliTracker::PropagateTrackTo(esd,(Double_t)cluster_x,0.105,5,kFALSE); +// if(isprop) +// { +// Int_t detector = c->GetDetector(); +// ((TH1F*)fContainer->At(fSector))->Fill((c->GetY())-(esd->GetY())); +// if(c->GetY()-esd->GetY()>); +// printf("diff: %f\n",c->GetY()-(esd->GetY())); +// } + } + */ + + } // loop over tracklets ends + + if(counterTracklet==AliTRDgeometry::kNlayer) + { + AliTRDtrackerV1::FitRiemanTilt(const_cast(trackTRD), 0x0, kTRUE, counterTracklet, points); + } + else continue; + + + + if(DebugLevel()>=1){ + for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){ + //printf("---------------------------------------- %i %i %f %f %f \n",counterTracklet,il,points[il].GetX(),points[il].GetY(),points[il].GetZ()); + Double_t pointX=points[il].GetX(); + Double_t pointY=points[il].GetY(); + Double_t pointZ=points[il].GetZ(); + + (*DebugStream()) << "TrackletsinTRD" + << "standalone=" << standAlone + << "eventcounter=" << fEventCounter + << "layer=" << il + << "dettracklet=" << detTracklet + << "xtracklet=" << trackletX[il] + << "xtrack=" << pointX + << "ytracklet=" << trackletY[il] + << "ytrack=" << pointY + << "ztracklet=" << trackletZ[il] + << "ztrack=" << pointZ + << "num_tracklets=" << counterTracklet + << "\n"; + } + } + + } + } + + + PostData(0, fContainer); +} + + diff --git a/PWG1/TRD/AliTRDmultiplicity.h b/PWG1/TRD/AliTRDmultiplicity.h new file mode 100644 index 00000000000..f544424b087 --- /dev/null +++ b/PWG1/TRD/AliTRDmultiplicity.h @@ -0,0 +1,37 @@ +#ifndef ALITRDMULTIPLICITY_H +#define ALITRDMULTIPLICITY_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + + +//////////////////////////////////////////////////////////////////////////// +// // +// TRD multiplicity // +// // +//////////////////////////////////////////////////////////////////////////// + +#ifndef ALITRDRECOTASK_H +#include "AliTRDrecoTask.h" +#endif + +class AliTRDmultiplicity : public AliTRDrecoTask +{ +public: + AliTRDmultiplicity(); + virtual ~AliTRDmultiplicity(); + void CreateOutputObjects(); + void Exec(Option_t *); + +private: + AliTRDmultiplicity(const AliTRDmultiplicity&); + AliTRDmultiplicity& operator=(const AliTRDmultiplicity&); + +private: + Int_t fEventCounter; // Event counter + + + ClassDef(AliTRDmultiplicity, 1) // TRD tracking multiplicity +}; + +#endif + diff --git a/PWG1/TRD/AliTRDpidRefMaker.cxx b/PWG1/TRD/AliTRDpidRefMaker.cxx new file mode 100644 index 00000000000..be8d4e6907c --- /dev/null +++ b/PWG1/TRD/AliTRDpidRefMaker.cxx @@ -0,0 +1,364 @@ +#include "TPDGCode.h" +#include "TFile.h" +#include "TTree.h" +#include "TEventList.h" +#include "TObjArray.h" +#include "TH2.h" + +#include "AliLog.h" +#include "AliESDtrack.h" +#include "AliTrackReference.h" + +#include "AliTRDReconstructor.h" +#include "AliTRDtrackV1.h" +#include "AliTRDseedV1.h" +#include "AliTRDpidRefMaker.h" +#include "info/AliTRDv0Info.h" + + +// Defines and implements basic functionality for building reference data for TRD PID. +// +// Here is the list of functionality provided by this class +// 1. +// 2. +// +// Authors: +// Alex Bercuci +// Alex Wilk +// Markus Fasel +// Markus Heide +// + +ClassImp(AliTRDpidRefMaker) +ClassImp(AliTRDpidRefMaker::AliTRDpidRefData) +ClassImp(AliTRDpidRefMaker::AliTRDpidRefDataArray) + +//________________________________________________________________________ +AliTRDpidRefMaker::AliTRDpidRefDataArray::AliTRDpidRefDataArray() : + fNtracklets(0) + ,fData(0x0) +{ + // Constructor of data array + fData = new AliTRDpidRefData[AliTRDgeometry::kNlayer]; +} + +//________________________________________________________________________ +AliTRDpidRefMaker::AliTRDpidRefDataArray::~AliTRDpidRefDataArray() +{ + // Destructor + delete [] fData; +} + +//________________________________________________________________________ +void AliTRDpidRefMaker::AliTRDpidRefDataArray::PushBack(Int_t ly, Int_t p, Float_t *dedx) +{ +// Add PID data to the end of the array + fData[fNtracklets].fPLbin= (ly<<4) | (p&0xf); + memcpy(fData[fNtracklets].fdEdx, dedx, 8*sizeof(Float_t)); + fNtracklets++; +} + +//________________________________________________________________________ +void AliTRDpidRefMaker::AliTRDpidRefDataArray::Reset() +{ +// Reset content + + if(!fNtracklets) return; + while(fNtracklets--){ + fData[fNtracklets].fPLbin = 0xff; + memset(fData[fNtracklets].fdEdx, 0, 8*sizeof(Float_t)); + } + fNtracklets=0; +} + +//________________________________________________________________________ +AliTRDpidRefMaker::AliTRDpidRefMaker(const char *name, const char *title) + :AliTRDrecoTask(name, title) + ,fReconstructor(0x0) + ,fV0s(0x0) + ,fData(0x0) + ,fPIDdataArray(0x0) + ,fRefPID(kMC) + ,fRefP(kMC) + ,fPIDbin(0xff) + ,fFreq(1.) + ,fP(-1.) + ,fPthreshold(0.5) +{ + // + // Default constructor + // + + fReconstructor = new AliTRDReconstructor(); + fReconstructor->SetRecoParam(AliTRDrecoParam::GetLowFluxParam()); + memset(fdEdx, 0, 10*sizeof(Float_t)); + memset(fPID, 0, AliPID::kSPECIES*sizeof(Float_t)); + + DefineInput(1, TObjArray::Class()); + DefineOutput(1, TTree::Class()); +} + + +//________________________________________________________________________ +AliTRDpidRefMaker::~AliTRDpidRefMaker() +{ + if(fPIDdataArray) delete fPIDdataArray; + if(fReconstructor) delete fReconstructor; +} + +//________________________________________________________________________ +Bool_t AliTRDpidRefMaker::CheckQuality(AliTRDseedV1* /*trklt*/) +{ +// Place holder for checking tracklet quality for PID. + return kTRUE; +} + + +//________________________________________________________________________ +Float_t* AliTRDpidRefMaker::CookdEdx(AliTRDseedV1 *trklt) +{ + trklt->CookdEdx(AliTRDpidUtil::kNNslices); + memcpy(fdEdx, trklt->GetdEdx(), AliTRDpidUtil::kNNslices*sizeof(Float_t)); + return fdEdx; +} + + +//________________________________________________________________________ +void AliTRDpidRefMaker::ConnectInputData(Option_t *opt) +{ + AliTRDrecoTask::ConnectInputData(opt); + fV0s = dynamic_cast(GetInputData(1)); +} + +//________________________________________________________________________ +void AliTRDpidRefMaker::CreateOutputObjects() +{ + // Create histograms + // Called once + + OpenFile(0, "RECREATE"); + fContainer = new TObjArray(); + fContainer->SetName(Form("Moni%s", GetName())); + + TH2 *h2 = new TH2I("hPDG","Particle abundance", AliPID::kSPECIES, -0.5, 4.5, AliTRDCalPID::kNMom, -0.5, AliTRDCalPID::kNMom-0.5); + TAxis *ax = h2->GetXaxis(); + ax->SetNdivisions(505); + ax->SetTitle("Particle species"); + for(Int_t is=AliPID::kSPECIES; is--;) ax->SetBinLabel(is+1, AliPID::ParticleShortName(is)); + h2->GetYaxis()->SetTitle("P bins"); + h2->GetYaxis()->SetNdivisions(511); + + fContainer->AddAt(h2, 0); + + fData = new TTree(GetName(), Form("Reference data for %s", GetName())); + fData->Branch("s", &fPIDbin, "s/b"); + fData->Branch("data", &fPIDdataArray); +} + +//________________________________________________________________________ +void AliTRDpidRefMaker::Exec(Option_t *) +{ + // Main loop + // Called for each event + + AliTRDtrackInfo *track = 0x0; + AliTRDtrackV1 *trackTRD = 0x0; + AliTrackReference *ref = 0x0; + const AliTRDtrackInfo::AliESDinfo *infoESD = 0x0; + for(Int_t itrk=0; itrkGetEntriesFast(); itrk++){ + track = (AliTRDtrackInfo*)fTracks->UncheckedAt(itrk); + if(!track->HasESDtrack()) continue; + trackTRD = track->GetTrack(); + infoESD = track->GetESDinfo(); + Double32_t *infoPID = infoESD->GetSliceIter(); + Int_t n = infoESD->GetNSlices() - AliTRDgeometry::kNlayer; + Double32_t *p = &infoPID[n]; + + + ULong_t status = track->GetStatus(); + if(!(status&AliESDtrack::kTPCout)) continue; + + // fill the pid information + SetRefPID(fRefPID, track, fPID); + + // prepare PID data array + if(!fPIDdataArray){ + fPIDdataArray = new AliTRDpidRefDataArray(); + } else fPIDdataArray->Reset(); + + // fill PID information + for(Int_t ily = 0; ily < AliTRDgeometry::kNlayer; ily++){ + + // fill P & dE/dx information + if(HasFriends()){ // from TRD track + if(!trackTRD) continue; + AliTRDseedV1 *trackletTRD(0x0); + trackTRD -> SetReconstructor(fReconstructor); + if(!(trackletTRD = trackTRD -> GetTracklet(ily))) continue; + if(!CheckQuality(trackletTRD)) continue; + if(!CookdEdx(trackletTRD)) continue; + + // fill momentum information + fP = 0.; + switch(fRefP){ + case kMC: + if(!(ref = track->GetTrackRef(trackletTRD))) continue; + fP = ref->P(); + break; + case kRec: + fP = trackletTRD->GetMomentum(); + break; + default: continue; + } + } else { // from ESD track + // fill momentum information + switch(fRefP){ + case kMC: + if(!(ref = track->GetTrackRef(ily))) continue; + fP = ref->P(); + break; + case kRec: + fP = p[ily]; + break; + default: continue; + } + Double32_t *it = &infoPID[ily*AliTRDCalPID::kNSlicesNN]; + for(Int_t is=AliTRDCalPID::kNSlicesNN; is--; it++) fdEdx[is] = (*it); + } + + // momentum threshold + if(fP < fPthreshold) continue; + + // store information + fPIDdataArray->PushBack(ily, AliTRDpidUtil::GetMomentumBin(fP), fdEdx); + } + + Fill(); + } + + PostData(0, fContainer); + PostData(1, fData); +} + + +//________________________________________________________________________ +void AliTRDpidRefMaker::Fill() +{ +// Fill data tree + + if(!fPIDdataArray->fNtracklets) return; + fPIDbin = TMath::LocMax(AliPID::kSPECIES, fPID); // get particle type +// Fill data tree + fData->Fill(); + + + // fill monitor + for(Int_t ily=fPIDdataArray->fNtracklets; ily--;){ + Int_t pBin = fPIDdataArray->fData[ily].fPLbin & 0xf; + ((TH2*)fContainer->At(0))->Fill(fPIDbin, pBin); + } +} + +//________________________________________________________________________ +void AliTRDpidRefMaker::LinkPIDdata() +{ +// Link data tree to data members + fData->SetBranchAddress("s", &fPIDbin); + fData->SetBranchAddress("data", &fPIDdataArray); +} + +//________________________________________________________________________ +void AliTRDpidRefMaker::SetRefPID(ETRDpidRefMakerSource select, void *source, Float_t *pid) +{ +// Fill the reference PID values "pid" from "source" object +// according to the option "select". Possible options are +// - kV0 - v0 based PID +// - kMC - MC truth [default] +// - kRec - outside detectors + + + memset(fPID, 0, AliPID::kSPECIES*sizeof(Float_t)); + switch(select){ + case kV0: + { + AliTRDtrackInfo *track = static_cast(source); + if(!track){ + AliError("No trackInfo found"); + return; + } + + //Get V0 PID decisions from the AliTRDv0Info for all particle species (implemented so far : electrons from conversions, pions from K0s and protons from Lambdas) : + AliTRDv0Info v0; + for(Int_t is=AliPID::kSPECIES; is--;) fPID[is] = v0.GetV0PID(is, track); + } + break; + case kMC: + if(!HasMCdata()){ + AliError("Could not retrive reference PID from MC"); + return; + } + { + AliTRDtrackInfo *track = static_cast(source); + switch(track->GetPDG()){ + case kElectron: + case kPositron: + fPID[AliPID::kElectron] = 1.; + break; + case kMuonPlus: + case kMuonMinus: + fPID[AliPID::kMuon] = 1.; + break; + case kPiPlus: + case kPiMinus: + fPID[AliPID::kPion] = 1.; + break; + case kKPlus: + case kKMinus: + fPID[AliPID::kKaon] = 1.; + break; + case kProton: + case kProtonBar: + fPID[AliPID::kProton] = 1.; + break; + } + } + break; + case kRec: + { + AliTRDtrackInfo *track = static_cast(source); + AliTRDtrackV1 *trackTRD = track->GetTrack(); + trackTRD -> SetReconstructor(fReconstructor); + //fReconstructor -> SetOption("nn"); + trackTRD -> CookPID(); + for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){ + pid[iPart] = trackTRD -> GetPID(iPart); + AliDebug(4, Form("PDG is (in V0info) %d %f", iPart, pid[iPart])); + } + } + break; + default: + AliWarning("PID reference source not implemented"); + return; + } + AliDebug(4, Form("Ref PID [%] : %s[%5.2f] %s[%5.2f] %s[%5.2f] %s[%5.2f] %s[%5.2f]" + ,AliPID::ParticleShortName(0), 1.e2*fPID[0] + ,AliPID::ParticleShortName(1), 1.e2*fPID[1] + ,AliPID::ParticleShortName(2), 1.e2*fPID[2] + ,AliPID::ParticleShortName(3), 1.e2*fPID[3] + ,AliPID::ParticleShortName(4), 1.e2*fPID[4] + )); +} + +//________________________________________________________________________ +void AliTRDpidRefMaker::SetAbundance(Float_t train) +{ +// Split data sample between trainning and testing + + if(train<0. || train >1.){ + AliWarning("The input data should be in the interval [0, 1]"); + return; + } + + fFreq = train; +} + diff --git a/PWG1/TRD/AliTRDpidRefMaker.h b/PWG1/TRD/AliTRDpidRefMaker.h new file mode 100644 index 00000000000..dfd8bb666c1 --- /dev/null +++ b/PWG1/TRD/AliTRDpidRefMaker.h @@ -0,0 +1,121 @@ +#ifndef ALITRDPIDREFMAKER_H +#define ALITRDPIDREFMAKER_H + +//////////////////////////////////////////////////////////// +// +// Base class for the Task to build TRD-PID reference data +// For the actual implementation please check the classes +// - AliTRDpidRefMakerNN (Neural Networks) +// - AliTRDpidRefMakerLQ (Multidimensional Likelihood) +// +// Authors: Alex Bercuci +// Alex Wilk +// +///////////////////////////////////////////////////////////// + +#ifndef ALITRDRECOTASK_H +#include "AliTRDrecoTask.h" +#endif +#ifndef ALIPID_H +#include "AliPID.h" +#endif +#ifndef ALITRDCALPID_H +#include "../Cal/AliTRDCalPID.h" +#endif +#ifndef ALITRDGEOMETRY_H +#include "../AliTRDgeometry.h" +#endif + +class TTree; +class TObjArray; +class AliTRDReconstructor; +class AliTRDseedV1; +class AliTRDpidRefMaker : public AliTRDrecoTask +{ +public: + enum ETRDpidRefMakerPBins { + k006 = 0 + ,k008 = 1 + ,k010 = 2 + ,k015 = 3 + ,k020 = 4 + ,k030 = 5 + ,k040 = 6 + ,k050 = 7 + ,k060 = 8 + ,k080 = 9 + ,k100 = 10 + ,kAll = 11 + }; + enum ETRDpidRefMakerSource { + kV0 = 0 // use V0 as reference + ,kMC = 1 // use MC as reference + ,kRec= 2 // use Reconstructed PID as reference + }; + + struct AliTRDpidRefData { + AliTRDpidRefData() : fPLbin(0xff) { + memset(fdEdx, 0, 8*sizeof(Float_t)); + } + virtual ~AliTRDpidRefData(){} + UChar_t fPLbin; // momentum / layer bin + Float_t fdEdx[8]; // dEdx array + ClassDef(AliTRDpidRefData, 1) // PID data representation + }; + struct AliTRDpidRefDataArray { + AliTRDpidRefDataArray(); + virtual ~AliTRDpidRefDataArray(); + void PushBack(Int_t ly, Int_t p, Float_t *dedx); + void Reset(); + + Int_t fNtracklets; // number of tracklets + AliTRDpidRefData *fData; //[fNtracklets] PID data array + private: + AliTRDpidRefDataArray(const AliTRDpidRefMaker::AliTRDpidRefDataArray& ref); + AliTRDpidRefDataArray& operator=(const AliTRDpidRefMaker::AliTRDpidRefDataArray& ref); + ClassDef(AliTRDpidRefDataArray, 1) // track PID data representation + }; + + AliTRDpidRefMaker(const char *name="PIDrefMaker", const char *title="PID Reference Maker"); + + virtual ~AliTRDpidRefMaker(); + + void ConnectInputData(Option_t *opt); + void CreateOutputObjects(); + void Exec(Option_t *option); + Float_t GetPthreshold() const { return fPthreshold;} + + void SetAbundance(Float_t train); + void SetPthreshold(Float_t t) { fPthreshold = t;} + void SetRefPID(ETRDpidRefMakerSource select, void *source, Float_t *pid); + void SetSource(ETRDpidRefMakerSource pid, ETRDpidRefMakerSource momentum) {fRefPID = pid; fRefP = momentum;} + + +protected: + virtual Bool_t CheckQuality(AliTRDseedV1* trklt); + virtual Float_t* CookdEdx(AliTRDseedV1* trklt); + virtual void LinkPIDdata(); + virtual void Fill(); + + AliTRDReconstructor *fReconstructor; //! reconstructor needed for recalculation the PID + TObjArray *fV0s; //! v0 array + TTree *fData; //! dEdx-P data + AliTRDpidRefDataArray *fPIDdataArray; //! pid data array + ETRDpidRefMakerSource fRefPID; // reference PID source + ETRDpidRefMakerSource fRefP; // reference momentum source + UChar_t fPIDbin; //! species bin + Float_t fFreq; //! training sample relative abundance + Float_t fP; //! momentum + Float_t fdEdx[8]; //! dEdx array + Float_t fPID[AliPID::kSPECIES]; //! pid from v0s + +private: + AliTRDpidRefMaker(const AliTRDpidRefMaker&); // not implemented + AliTRDpidRefMaker& operator=(const AliTRDpidRefMaker&); // not implemented + + Float_t fPthreshold; // momentum threshold [GeV/c] + + ClassDef(AliTRDpidRefMaker, 3); // TRD PID reference maker base class +}; + +#endif diff --git a/PWG1/TRD/AliTRDpidRefMakerLQ.cxx b/PWG1/TRD/AliTRDpidRefMakerLQ.cxx new file mode 100644 index 00000000000..fc0b63d41a3 --- /dev/null +++ b/PWG1/TRD/AliTRDpidRefMakerLQ.cxx @@ -0,0 +1,272 @@ +/************************************************************************** +* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* * +* Author: The ALICE Off-line Project. * +* Contributors are mentioned in the code where appropriate. * +* * +* Permission to use, copy, modify and distribute this software and its * +* documentation strictly for non-commercial purposes is hereby granted * +* without fee, provided that the above copyright notice appears in all * +* copies and that both the copyright notice and this permission notice * +* appear in the supporting documentation. The authors make no claims * +* about the suitability of this software for any purpose. It is * +* provided "as is" without express or implied warranty. * +**************************************************************************/ + +/* $Id: AliTRDpidRefMakerLQ.cxx 34163 2009-08-07 11:28:51Z cblume $ */ + +/////////////////////////////////////////////////////////////////////////////// +// +// +// TRD calibration class for building reference data for PID +// - 2D reference histograms (responsible A.Bercuci) +// - 3D reference histograms (not yet implemented) (responsible A.Bercuci) +// - Neural Network (responsible A.Wilk) +// +// Origin +// Alex Bercuci (A.Bercuci@gsi.de) +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +//#include +//#include + +#include "AliLog.h" +#include "../../STAT/TKDPDF.h" +#include "AliTRDpidRefMakerLQ.h" +#include "../Cal/AliTRDCalPID.h" +#include "../Cal/AliTRDCalPIDLQ.h" +#include "AliTRDseedV1.h" +#include "AliTRDcalibDB.h" +#include "AliTRDgeometry.h" + +ClassImp(AliTRDpidRefMakerLQ) + +//__________________________________________________________________ +AliTRDpidRefMakerLQ::AliTRDpidRefMakerLQ() + :AliTRDpidRefMaker("PIDrefMakerLQ", "PID(LQ) Reference Maker") +{ + // + // AliTRDpidRefMakerLQ default constructor + // +} + +//__________________________________________________________________ +AliTRDpidRefMakerLQ::~AliTRDpidRefMakerLQ() +{ + // + // AliTRDCalPIDQRef destructor + // +} + +//________________________________________________________________________ +void AliTRDpidRefMakerLQ::CreateOutputObjects() +{ + // Create histograms + // Called once + + AliTRDpidRefMaker::CreateOutputObjects(); + + // save dE/dx references + TH2 *h2 = 0x0; + for(Int_t ip=AliTRDCalPID::kNMom; ip--;){ + TObjArray *arr = new TObjArray(AliPID::kSPECIES); + arr->SetName(Form("Pbin%02d", ip)); + for(Int_t is=AliPID::kSPECIES; is--;) { + h2 = new TH2D(Form("h%s%d", AliPID::ParticleShortName(is), ip), Form("%s ref. dEdx @ Pbin[%d]", AliPID::ParticleName(is), ip), 50, 5., 10., 50, 5., 10.); + h2->GetXaxis()->SetTitle("log(dE/dx_{am}) [au]"); + h2->GetYaxis()->SetTitle("log(dE/dx_{dr}) [au]"); + h2->GetZaxis()->SetTitle("#"); + arr->AddAt(h2, is); + } + fContainer->AddAt(arr, 1+ip); + } +} + +/* +//________________________________________________________________________ +Float_t* AliTRDpidRefMakerLQ::CookdEdx(AliTRDseedV1 *trklt) +{ +// Fill dEdx array for multidim LQ PID + + trklt->CookdEdx(AliTRDpidUtil::kLQslices); + const Float_t *dedx = trklt->GetdEdx(); + if(dedx[0]+dedx[1] <= 0.) return 0x0; + if(dedx[2] <= 0.) return 0x0; + + fdEdx[0] = TMath::Log(dedx[0]+dedx[1]); + fdEdx[1] = TMath::Log(dedx[2]); + return fdEdx; +}*/ + +//__________________________________________________________________ +TObject* AliTRDpidRefMakerLQ::GetOCDBEntry(Option_t *opt) +{ +// Steer loading of OCDB LQ PID + + TDirectoryFile *d = 0x0; + if(!TFile::Open(Form("TRD.Calib%s.root", GetName()))) return 0x0; + if(!(d=(TDirectoryFile*)gFile->Get(Form("PDF_%s", opt)))) return 0x0; + AliTRDCalPIDLQ *cal = new AliTRDCalPIDLQ("pidLQ", "LQ TRD PID object"); + cal->LoadPDF(d); + return cal; +} + +//__________________________________________________________________ +Bool_t AliTRDpidRefMakerLQ::GetRefFigure(Int_t ifig) +{ +// Steering reference picture + + if(ifig<0 || ifig>AliTRDCalPID::kNMom-1){ + AliError("Ref fig requested outside definition."); + return kFALSE; + } + if(!gPad){ + AliWarning("Please provide a canvas to draw results."); + return kFALSE; + } + + TObjArray *arr = (TObjArray*)fContainer->At(ifig); + gPad->Divide(3, 2, 1.e-5, 1.e-5); + TList *l=gPad->GetListOfPrimitives(); + for(Int_t is=0; isAt(is))->cd(); + ((TH2*)arr->At(is))->Draw("cont4z"); + } + + return kTRUE; +} + +//________________________________________________________________________ +Bool_t AliTRDpidRefMakerLQ::PostProcess() +{ +// Analyse merged dedx = f(p) distributions. +// - select momentum - species bins +// - rotate to principal components +// - locally interpolate with TKDPDF +// - save interpolation to monitoring histograms +// - write pdf to file for loading to OCDB +// + + + TFile *fCalib = TFile::Open(Form("TRD.Calib%s.root", GetName()), "update"); + fData = dynamic_cast(gFile->Get(GetName())); + if (!fData) { + AliError("Calibration data not available"); + return kFALSE; + } + TObjArray *o = 0x0; + if(!(o = (TObjArray*)gFile->Get(Form("Moni%s", GetName())))){ + AliWarning("Missing monitoring container."); + return kFALSE; + } + fContainer = (TObjArray*)o->Clone("monitor"); + + TDatime d; + TDirectoryFile *pdfs = new TDirectoryFile(Form("PDF_%d", d.GetDate()), "PDFs for LQ TRD-PID", "", gFile); + pdfs->Write(); + AliDebug(2, Form("Data[%d]", fData->GetEntries())); + pdfs->cd(); + + //TCanvas *cc = new TCanvas("cc", "", 500, 500); + LinkPIDdata(); + Float_t *data[] = {0x0, 0x0}; + // allocate storage + data[0] = new Float_t[kMaxStat];data[1] = new Float_t[kMaxStat]; + for(Int_t ip=AliTRDCalPID::kNMom; ip--; ){ + for(Int_t is=AliPID::kSPECIES; is--;) { + Int_t n(0); // index of data + for(Int_t itrk=0; (itrk < fData->GetEntries()) && (nGetEntry(itrk))) continue; + if(fPIDbin!=is) continue; + for(Int_t ily=fPIDdataArray->fNtracklets; ily--;){ + if((fPIDdataArray->fData[ily].fPLbin & 0xf)!= ip) continue; + + Float_t dedx[] = {0., 0.}; + for(Int_t islice=AliTRDCalPID::kNSlicesNN; islice--;){ + Int_t jslice = islice>kNN2LQtransition; + dedx[jslice]+=fPIDdataArray->fData[ily].fdEdx[islice]; + } + + // check data integrity + if(dedx[0]<1.e-30) continue; + if(dedx[1]<1.e-30) continue; + + // store data + data[0][n] = TMath::Log(dedx[0]); + data[1][n] = TMath::Log(dedx[1]); + n++; if(n==kMaxStat) break; + } + } + + // estimate bucket statistics + Int_t nb(kMinBuckets), // number of buckets + ns(Int_t(Float_t(n)/nb)); //statistics/bucket + +// if(Float_t(n)/nb < 220.) ns = 200; // 7% stat error +// else if(Float_t(n)/nb < 420.) ns = 400; // 5% stat error + + AliDebug(2, Form("pBin[%d] sBin[%d] n[%d] ns[%d] nb[%d]", ip, is, n, ns, nb)); + if(nsModified(); cc->Update(); cc->SaveAs(Form("pdf_%s%02d.gif", AliPID::ParticleShortName(is), ip)); +// cc->SaveAs(Form("%s_%s%02d.gif", GetName(), AliPID::ParticleShortName(is), ip)); + + // save a discretization of the PDF for result monitoring + TH2 *h2s = (TH2D*)((TObjArray*)fContainer->At(ip))->At(is); + TAxis *ax = h2s->GetXaxis(), *ay = h2s->GetYaxis(); + h2s->Clear(); + for(int ix=1; ix<=ax->GetNbins(); ix++){ + rxy[0] = ax->GetBinCenter(ix); + for(int iy=1; iy<=ay->GetNbins(); iy++){ + rxy[1] = ay->GetBinCenter(iy); + + Double_t rr,ee; + pdf.Eval(rxy, rr, ee, kFALSE); + if(rr<0. || ee/rr>.15) continue; // 15% relative error + //printf("x[%2d] x[%2d] r[%f] e[%f]\n", ix, iy, rr, ee); + h2s->SetBinContent(ix, iy, rr); + } + } + + // write results to output array + //pdf.GetStatus(); + pdf.Write(Form("%s[%d]", AliPID::ParticleShortName(is), ip)); + } + } + delete [] data[0]; delete [] data[1]; + pdfs->Write(); + fCalib->Close(); delete fCalib; + + return kTRUE; // testing protection +} + + diff --git a/PWG1/TRD/AliTRDpidRefMakerLQ.h b/PWG1/TRD/AliTRDpidRefMakerLQ.h new file mode 100644 index 00000000000..a791a2c891d --- /dev/null +++ b/PWG1/TRD/AliTRDpidRefMakerLQ.h @@ -0,0 +1,53 @@ +#ifndef ALITRDPIDREFMAKERLQ_H +#define ALITRDPIDREFMAKERLQ_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/* $Id: AliTRDpidRefMakerLQ.h 34125 2009-08-06 09:35:40Z cblume $ */ + +/////////////////////////////////////////////////////////////////////////////// +// // +// TRD calibration class for building reference data for PID // +// // +/////////////////////////////////////////////////////////////////////////////// + +#ifndef ALIPID_H +#include "AliPID.h" +#endif + +#ifndef ALITRDPIDREFMAKER_H +#include "AliTRDpidRefMaker.h" +#endif + +#ifndef ALITRDPIDUTIL_H +#include "AliTRDpidUtil.h" +#endif + +class TObjArray; +class AliTRDpidRefMakerLQ : public AliTRDpidRefMaker { +public: + enum ETRDpidRefMakerLQsteer{ + kMaxStat = 180000 // maximum statistics/PID bin + ,kMinStat = 50 // minimum statistics/bucket 14% + ,kMinBuckets = 450 // minimum number of buckets [lambda(6)*alpha(1.5)*regions(50)] + ,kNN2LQtransition = 4 // index of NN slices where first LQ slice ends + }; + AliTRDpidRefMakerLQ(); + ~AliTRDpidRefMakerLQ(); + + void CreateOutputObjects(); + TObject* GetOCDBEntry(Option_t *opt); + Bool_t GetRefFigure(Int_t ifig); + Bool_t PostProcess(); + +private: + AliTRDpidRefMakerLQ(const AliTRDpidRefMakerLQ &ref); + AliTRDpidRefMakerLQ& operator=(const AliTRDpidRefMakerLQ &ref); + +private: + ClassDef(AliTRDpidRefMakerLQ, 5) // Reference builder for Multidim-LQ TRD-PID + +}; + +#endif + diff --git a/PWG1/TRD/AliTRDpidRefMakerNN.cxx b/PWG1/TRD/AliTRDpidRefMakerNN.cxx new file mode 100644 index 00000000000..e6e78700678 --- /dev/null +++ b/PWG1/TRD/AliTRDpidRefMakerNN.cxx @@ -0,0 +1,536 @@ +/************************************************************************* +* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* * +* Author: The ALICE Off-line Project. * +* Contributors are mentioned in the code where appropriate. * +* * +* Permission to use, copy, modify and distribute this software and its * +* documentation strictly for non-commercialf purposes is hereby granted * +* without fee, provided that the above copyright notice appears in all * +* copies and that both the copyright notice and this permission notice * +* appear in the supporting documentation. The authors make no claims * +* about the suitability of this software for any purpose. It is * +* provided "as is" without express or implied warranty. * +**************************************************************************/ + +/* $Id: AliTRDpidRefMakerNN.cxx 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// Builds the reference tree for the training of neural networks // +// // +//////////////////////////////////////////////////////////////////////////// + +#include "TSystem.h" +#include "TDatime.h" +#include "TPDGCode.h" +#include "TH1F.h" +#include "TH2F.h" +#include "TFile.h" +#include "TGraphErrors.h" +#include "TTree.h" +#include "TEventList.h" +#include "TMultiLayerPerceptron.h" + +#include "AliPID.h" +#include "AliESDtrack.h" +#include "AliTrackReference.h" + +#include "AliTRDtrackV1.h" +#include "AliTRDReconstructor.h" +#include "AliTRDpidUtil.h" +#include "AliTRDpidRefMakerNN.h" +#include "AliTRDpidUtil.h" + +#include "../Cal/AliTRDCalPID.h" +#include "../Cal/AliTRDCalPIDNN.h" +#include "info/AliTRDtrackInfo.h" +#include "info/AliTRDv0Info.h" + +ClassImp(AliTRDpidRefMakerNN) + +//________________________________________________________________________ +AliTRDpidRefMakerNN::AliTRDpidRefMakerNN() + :AliTRDpidRefMaker("PidRefMakerNN", "PID(NN) Reference Maker") +// :AliTRDrecoTask("PidRefMakerNN", "PID(NN) Reference Maker") + ,fTrainMomBin(kAll) + ,fEpochs(1000) + ,fMinTrain(100) + ,fDate(0) + ,fDoTraining(0) + ,fContinueTraining(0) + ,fTrainPath(0x0) + ,fScale(0) +{ + // + // Default constructor + // + + memset(fTrain, 0, AliTRDCalPID::kNMom*AliTRDgeometry::kNlayer*sizeof(TEventList*)); + memset(fTest, 0, AliTRDCalPID::kNMom*AliTRDgeometry::kNlayer*sizeof(TEventList*)); + memset(fNet, 0, AliTRDgeometry::kNlayer*sizeof(TMultiLayerPerceptron*)); + + SetAbundance(.67); + SetScaledEdx(Float_t(AliTRDCalPIDNN::kMLPscale)); + TDatime datime; + fDate = datime.GetDate(); + + DefineInput(1, TObjArray::Class()); + DefineOutput(1, TTree::Class()); +} + + +//________________________________________________________________________ +AliTRDpidRefMakerNN::~AliTRDpidRefMakerNN() +{ +} + + +//________________________________________________________________________ +void AliTRDpidRefMakerNN::CreateOutputObjects() +{ + // Create histograms + // Called once + + AliTRDpidRefMaker::CreateOutputObjects(); + TGraphErrors *gEffisTrain = new TGraphErrors(kMoniTrain); + gEffisTrain -> SetLineColor(4); + gEffisTrain -> SetMarkerColor(4); + gEffisTrain -> SetMarkerStyle(29); + gEffisTrain -> SetMarkerSize(1); + + TGraphErrors *gEffisTest = new TGraphErrors(kMoniTrain); + gEffisTest -> SetLineColor(2); + gEffisTest -> SetMarkerColor(2); + gEffisTest -> SetMarkerStyle(29); + gEffisTest -> SetMarkerSize(1); + + fContainer -> AddAt(gEffisTrain,kGraphTrain); + fContainer -> AddAt(gEffisTest,kGraphTest); +} + + + +//________________________________________________________________________ +Bool_t AliTRDpidRefMakerNN::PostProcess() +{ + // Draw result to the screen + // Called once at the end of the query + + // build the training andthe test list for the neural networks + MakeTrainingLists(); + if(!fDoTraining) return kTRUE; + + // train the neural networks and build the refrence histos for 2-dim LQ + gSystem->Exec(Form("mkdir ./Networks_%d/",fDate)); + AliDebug(2, Form("TrainMomBin [%d] [%d]", fTrainMomBin, kAll)); + + // train single network for a single momentum (recommended) + if(!(fTrainMomBin == kAll)){ + if(fTrain[fTrainMomBin][0] -> GetN() < fMinTrain){ + AliDebug(2, Form("Warning in AliTRDpidRefMakerNN::PostProcess : Not enough events for training available! Please check Data sample!")); + return kFALSE; + } + MakeRefs(fTrainMomBin); +// TrainNetworks(fTrainMomBin); + MonitorTraining(fTrainMomBin); + } + // train all momenta + else{ + for(Int_t iMomBin = 0; iMomBin < AliTRDCalPID::kNMom; iMomBin++){ + if(fTrain[iMomBin][0] -> GetN() < fMinTrain){ + AliDebug(2, Form("Warning in AliTRDpidRefMakerNN::PostProcess : Not enough events for training available for momentum bin [%d]! Please check Data sample!", iMomBin)); + continue; + } + MakeRefs(fTrainMomBin); +// TrainNetworks(iMomBin); + MonitorTraining(iMomBin); + } + } + + return kTRUE; // testing protection +} + + +//________________________________________________________________________ +void AliTRDpidRefMakerNN::MakeTrainingLists() +{ + // + // build the training lists for the neural networks + // + + if (!fData) { + LoadFile("TRD.CalibPidRefMakerNN.root"); + } + + if (!fData) { + Printf("ERROR tree for training list not available"); + return; + } + + AliDebug(2, " Making training lists! \n"); + + Int_t nPart[AliPID::kSPECIES][AliTRDCalPID::kNMom]; + memset(nPart, 0, AliPID::kSPECIES*AliTRDCalPID::kNMom*sizeof(Int_t)); + + // set needed branches + LinkPIDdata(); + + // start first loop to check total number of each particle type + for(Int_t iEv=0; iEv < fData -> GetEntries(); iEv++){ + fData -> GetEntry(iEv); + + // use only events with goes through 6 layers TRD + if(fPIDdataArray->fNtracklets != AliTRDgeometry::kNlayer) continue; + + for(Int_t ily=AliTRDgeometry::kNlayer; ily--;) nPart[fPIDbin][fPIDdataArray->fData[ily].fPLbin & 0xf]++; + } + + AliDebug(2, "Particle multiplicities:"); + for(Int_t iMomBin = 0; iMomBin nPart[iPart][iMomBin]) + iTrain[iMomBin] = nPart[iPart][iMomBin]; + } + iTrain[iMomBin] = Int_t(iTrain[iMomBin] * .66); + iTest[iMomBin] = Int_t( iTrain[iMomBin] * .5); + AliDebug(2, Form("Momentum[%d] Train[%d] Test[%d]", iMomBin, iTrain[iMomBin], iTest[iMomBin])); + } + + + // reset couters + memset(nPart, 0, AliPID::kSPECIES*AliTRDCalPID::kNMom*sizeof(Int_t)); + + // start second loop to set the event lists + for(Int_t iEv = 0; iEv < fData -> GetEntries(); iEv++){ + fData -> GetEntry(iEv); + + // use only events with goes through 6 layers TRD + if(fPIDdataArray->fNtracklets != AliTRDgeometry::kNlayer) continue; + + for(Int_t ily=AliTRDgeometry::kNlayer; ily--;){ + Int_t iMomBin = fPIDdataArray->fData[ily].fPLbin & 0xf; + + // set event list + if(nPart[fPIDbin][iMomBin] < iTrain[iMomBin]){ + fTrain[iMomBin][ily] -> Enter(iEv + ily); + nPart[fPIDbin][iMomBin]++; + } else if(nPart[fPIDbin][iMomBin] < iTest[iMomBin]+iTrain[iMomBin]){ + fTest[iMomBin][ily] -> Enter(iEv + ily); + nPart[fPIDbin][iMomBin]++; + } else continue; + } + } + + AliDebug(2, "Particle multiplicities in both lists:"); + for(Int_t iMomBin = 0; iMomBin Exec(Form("rm -r ./Networks_%d/MomBin_%d",fDate, mombin)); + gSystem->Exec(Form("mkdir ./Networks_%d/MomBin_%d",fDate, mombin)); + + // variable to check if network can load weights from previous training + Bool_t bFirstLoop[AliTRDgeometry::kNlayer]; + memset(bFirstLoop, kTRUE, AliTRDgeometry::kNlayer*sizeof(Bool_t)); + + // train networks over several loops and save them after each loop + for(Int_t iLoop = 0; iLoop < kMoniTrain; iLoop++){ + // loop over chambers + for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){ + // set the event lists + fData -> SetEventList(fTrain[mombin][iChamb]); + fData -> SetEventList(fTest[mombin][iChamb]); + + AliDebug(2, Form("Trainingloop[%d] Chamber[%d]", iLoop, iChamb)); + + // check if network is already implemented + if(bFirstLoop[iChamb] == kTRUE){ + fNet[iChamb] = new TMultiLayerPerceptron("fdEdx[0],fdEdx[1],fdEdx[2],fdEdx[3],fdEdx[4],fdEdx[5],fdEdx[6],fdEdx[7]:15:7:fPID[0],fPID[1],fPID[2],fPID[3],fPID[4]!",fData,fTrain[mombin][iChamb],fTest[mombin][iChamb]); + fNet[iChamb] -> SetLearningMethod(TMultiLayerPerceptron::kStochastic); // set learning method + fNet[iChamb] -> TMultiLayerPerceptron::SetEta(0.001); // set learning speed + if(!fContinueTraining){ + if(DebugLevel()>=2) fNet[iChamb] -> Train(nEpochs,"text update=10, graph"); + else fNet[iChamb] -> Train(nEpochs,""); + } + else{ + fNet[iChamb] -> LoadWeights(Form("./Networks_%d/MomBin_%d/Net%d_%d",fTrainPath, mombin, iChamb, kMoniTrain - 1)); + if(DebugLevel()>=2) fNet[iChamb] -> Train(nEpochs,"text update=10, graph+"); + else fNet[iChamb] -> Train(nEpochs,"+"); + } + bFirstLoop[iChamb] = kFALSE; + } + else{ + if(DebugLevel()>=2) fNet[iChamb] -> Train(nEpochs,"text update=10, graph+"); + else fNet[iChamb] -> Train(nEpochs,"+"); + } + + // save weights for monitoring of the training + fNet[iChamb] -> DumpWeights(Form("./Networks_%d/MomBin_%d/Net%d_%d",fDate, mombin, iChamb, iLoop)); + } // end chamber loop + } // end training loop +} + + + +//________________________________________________________________________ +void AliTRDpidRefMakerNN::MonitorTraining(Int_t mombin) +{ + // + // train the neural networks + // + + if (!fData) LoadFile(Form("TRD.Calib%s.root", GetName())); + if (!fData) { + AliError("Tree for training list not available"); + return; + } + + // init networks and set event list + for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){ + fNet[iChamb] = new TMultiLayerPerceptron("fdEdx[0],fdEdx[1],fdEdx[2],fdEdx[3],fdEdx[4],fdEdx[5],fdEdx[6],fdEdx[7]:15:7:fPID[0],fPID[1],fPID[2],fPID[3],fPID[4]!",fData,fTrain[mombin][iChamb],fTest[mombin][iChamb]); + fData -> SetEventList(fTrain[mombin][iChamb]); + fData -> SetEventList(fTest[mombin][iChamb]); + } + + // implement variables for likelihoods + Float_t like[AliPID::kSPECIES][AliTRDgeometry::kNlayer]; + memset(like, 0, AliPID::kSPECIES*AliTRDgeometry::kNlayer*sizeof(Float_t)); + Float_t likeAll[AliPID::kSPECIES], totProb; + + Double_t pionEffiTrain[kMoniTrain], pionEffiErrTrain[kMoniTrain]; + Double_t pionEffiTest[kMoniTrain], pionEffiErrTest[kMoniTrain]; + memset(pionEffiTrain, 0, kMoniTrain*sizeof(Double_t)); + memset(pionEffiErrTrain, 0, kMoniTrain*sizeof(Double_t)); + memset(pionEffiTest, 0, kMoniTrain*sizeof(Double_t)); + memset(pionEffiErrTest, 0, kMoniTrain*sizeof(Double_t)); + + // init histos + const Float_t epsilon = 1/(2*(AliTRDpidUtil::kBins-1)); // get nice histos with bin center at 0 and 1 + TH1F *hElecs, *hPions; + hElecs = new TH1F("hElecs","Likelihood for electrons", AliTRDpidUtil::kBins, 0.-epsilon, 1.+epsilon); + hPions = new TH1F("hPions","Likelihood for pions", AliTRDpidUtil::kBins, 0.-epsilon, 1.+epsilon); + + TGraphErrors *gEffisTrain=0x0, *gEffisTest=0x0; + gEffisTrain = (TGraphErrors*)fContainer->At(kGraphTrain); + gEffisTest = (TGraphErrors*)fContainer->At(kGraphTest); + + AliTRDpidUtil *util = new AliTRDpidUtil(); + + // monitor training progress + for(Int_t iLoop = 0; iLoop < kMoniTrain; iLoop++){ + + // load weights + for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){ + fNet[iChamb] -> LoadWeights(Form("./Networks_%d/MomBin_%d/Net%d_%d",fDate, mombin, iChamb, iLoop)); + } + + // event loop training list + for(Int_t iEvent = 0; iEvent < fTrain[mombin][0] -> GetN(); iEvent++ ){ + + // reset particle probabilities + for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){ + likeAll[iPart] = 1./AliPID::kSPECIES; + } + totProb = 0.; + + fData -> GetEntry(fTrain[mombin][0] -> GetEntry(iEvent)); + // use event only if it is electron or pion + if(!((fPID[AliPID::kElectron] == 1.0) || (fPID[AliPID::kPion] == 1.0))) continue; + + // get the probabilities for each particle type in each chamber + for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){ + for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){ + like[iPart][iChamb] = fNet[iChamb] -> Result(fTrain[mombin][iChamb] -> GetEntry(iEvent), iPart); + likeAll[iPart] *= like[iPart][iChamb]; + } + } + + // get total probability and normalize it + for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){ + totProb += likeAll[iPart]; + } + for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){ + likeAll[iPart] /= totProb; + } + + // fill likelihood distributions + if(fPID[AliPID::kElectron] == 1) + hElecs -> Fill(likeAll[AliPID::kElectron]); + if(fPID[AliPID::kPion] == 1) + hPions -> Fill(likeAll[AliPID::kElectron]); + } // end event loop + + + // calculate the pion efficiency and fill the graph + util -> CalculatePionEffi(hElecs, hPions); + pionEffiTrain[iLoop] = util -> GetPionEfficiency(); + pionEffiErrTrain[iLoop] = util -> GetError(); + + gEffisTrain -> SetPoint(iLoop, iLoop+1, pionEffiTrain[iLoop]); + gEffisTrain -> SetPointError(iLoop, 0, pionEffiErrTrain[iLoop]); + hElecs -> Reset(); + hPions -> Reset(); + AliDebug(2, Form("TrainingLoop[%d] PionEfficiency[%f +/- %f]", iLoop, pionEffiTrain[iLoop], pionEffiErrTrain[iLoop])); + // end training loop + + + + // event loop test list + for(Int_t iEvent = 0; iEvent < fTest[mombin][0] -> GetN(); iEvent++ ){ + + // reset particle probabilities + for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){ + likeAll[iPart] = 1./AliTRDgeometry::kNlayer; + } + totProb = 0.; + + fData -> GetEntry(fTest[mombin][0] -> GetEntry(iEvent)); + // use event only if it is electron or pion + if(!((fPID[AliPID::kElectron] == 1.0) || (fPID[AliPID::kPion] == 1.0))) continue; + + // get the probabilities for each particle type in each chamber + for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){ + for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){ + like[iPart][iChamb] = fNet[iChamb] -> Result(fTest[mombin][iChamb] -> GetEntry(iEvent), iPart); + likeAll[iPart] *= like[iPart][iChamb]; + } + } + + // get total probability and normalize it + for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){ + totProb += likeAll[iPart]; + } + for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){ + likeAll[iPart] /= totProb; + } + + // fill likelihood distributions + if(fPID[AliPID::kElectron] == 1) + hElecs -> Fill(likeAll[AliPID::kElectron]); + if(fPID[AliPID::kPion] == 1) + hPions -> Fill(likeAll[AliPID::kElectron]); + } // end event loop + + // calculate the pion efficiency and fill the graph + util -> CalculatePionEffi(hElecs, hPions); + pionEffiTest[iLoop] = util -> GetPionEfficiency(); + pionEffiErrTest[iLoop] = util -> GetError(); + + gEffisTest -> SetPoint(iLoop, iLoop+1, pionEffiTest[iLoop]); + gEffisTest -> SetPointError(iLoop, 0, pionEffiErrTest[iLoop]); + hElecs -> Reset(); + hPions -> Reset(); + AliDebug(2, Form("TestLoop[%d] PionEfficiency[%f +/- %f] \n", iLoop, pionEffiTest[iLoop], pionEffiErrTest[iLoop])); + + } // end training loop + + util -> Delete(); + + gEffisTest -> Draw("PAL"); + gEffisTrain -> Draw("PL"); + +} + + +//________________________________________________________________________ +void AliTRDpidRefMakerNN::LoadFile(const Char_t *InFileNN) +{ + // + // Loads the files and sets the event list + // for neural network training and + // building of the 2-dim reference histograms. + // Useable for training outside of the makeResults.C macro + // + + TFile *fInFileNN; + fInFileNN = new TFile(InFileNN, "READ"); + fData = (TTree*)fInFileNN -> Get("NN"); + + for(Int_t iMom = 0; iMom < AliTRDCalPID::kNMom; iMom++){ + for(Int_t ily = 0; ily < AliTRDgeometry::kNlayer; ily++){ + fTrain[iMom][ily] = new TEventList(Form("fTrainMom%d_%d", iMom, ily), Form("Training list for momentum intervall %d and plane %d", iMom, ily)); + fTest[iMom][ily] = new TEventList(Form("fTestMom%d_%d", iMom, ily), Form("Test list for momentum intervall %d and plane %d", iMom, ily)); + } + } +} + + +// //________________________________________________________________________ +// void AliTRDpidRefMakerNN::LoadContainer(const Char_t *InFileCont) +// { + +// // +// // Loads the container if no container is there. +// // Useable for training outside of the makeResults.C macro +// // + +// TFile *fInFileCont; +// fInFileCont = new TFile(InFileCont, "READ"); +// fContainer = (TObjArray*)fInFileCont -> Get("PidRefMaker"); + +// } + + +// //________________________________________________________________________ +// void AliTRDpidRefMakerNN::CreateGraphs() +// { +// // Create histograms +// // Called once + +// OpenFile(0, "RECREATE"); +// fContainer = new TObjArray(); +// fContainer->AddAt(new TH1F("hPDG","hPDG",AliPID::kSPECIES,-0.5,5.5),0); + +// TGraphErrors *gEffisTrain = new TGraphErrors(kMoniTrain); +// gEffisTrain -> SetLineColor(4); +// gEffisTrain -> SetMarkerColor(4); +// gEffisTrain -> SetMarkerStyle(29); +// gEffisTrain -> SetMarkerSize(2); + +// TGraphErrors *gEffisTest = new TGraphErrors(kMoniTrain); +// gEffisTest -> SetLineColor(2); +// gEffisTest -> SetMarkerColor(2); +// gEffisTest -> SetMarkerSize(2); + +// fContainer -> AddAt(gEffisTrain,kGraphTrain); +// fContainer -> AddAt(gEffisTest,kGraphTest); +// } + diff --git a/PWG1/TRD/AliTRDpidRefMakerNN.h b/PWG1/TRD/AliTRDpidRefMakerNN.h new file mode 100644 index 00000000000..78b59600f9e --- /dev/null +++ b/PWG1/TRD/AliTRDpidRefMakerNN.h @@ -0,0 +1,111 @@ +#ifndef ALITRDPIDREFMAKERNN_H +#define ALITRDPIDREFMAKERNN_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/* $Id: AliTRDpidRefMakerNN.h 27496 2008-07-22 08:35:45Z cblume $ */ + +////////////////////////////////////////////////////// +// +// Task to build PID reference tree for the training +// of neural networs for the TRD PID +// +// Authors: Alex Wilk +// Markus Heide +// +/////////////////////////////////////////////////////// + +/* #ifndef ALITRDRECOTASK_H */ +/* #include "AliTRDrecoTask.h" */ +/* #endif */ + +/* #ifndef ALIPID_H */ +/* #include "AliPID.h" */ +/* #endif */ + +/* #ifndef ALITRDCALPID_H */ +/* #include "../Cal/AliTRDCalPID.h" */ +/* #endif */ + +/* #ifndef ALITRDGEOMETRY_H */ +/* #include "../AliTRDgeometry.h" */ +/* #endif */ + +#ifndef ALITRDPIDREFMAKER_H +#include "AliTRDpidRefMaker.h" +#endif + +/* class TTree; */ +/* class TObjArray; */ +/* class TEventList; */ +/* class TMultiLayerPerceptron; */ +/* class AliPID; */ +/* class AliTRDtrackV1; */ +/* class AliTRDReconstructor; */ + +/* class AliTRDpidRefMakerNN : public AliTRDrecoTask */ + +class TEventList; +class TMultiLayerPerceptron; +class AliTRDpidRefMakerNN : public AliTRDpidRefMaker +{ + +public: + enum ETRDpidRefMakerNNgraph { + kGraphTrain = 0 + ,kGraphTest = 1 + }; + + enum ETRDpidRefMakerNNmoni { + kMoniTrain = 50 + }; + + AliTRDpidRefMakerNN(); + + virtual ~AliTRDpidRefMakerNN(); + + void CreateOutputObjects(); + Int_t GetEpochs() const {return fEpochs;}; + Int_t GetMinTrain() const {return fMinTrain;}; + Int_t GetTrainMomBin() const {return fTrainMomBin;}; + + Bool_t PostProcess(); + + void SetEpochs(Int_t epochs) {fEpochs = epochs;}; + void SetMinTrain(Int_t mintrain) {fMinTrain = mintrain;}; + void SetTrainMomBin(Int_t trainmombin) {fTrainMomBin = trainmombin;}; + void SetDate(Int_t date) {fDate = date;}; + void SetDoTraining(Bool_t train) {fDoTraining = train;}; + void SetContinueTraining(Bool_t continTrain) {fContinueTraining = continTrain;}; + void SetTrainPath(Int_t path) {fTrainPath = path;}; + void LoadFile(const Char_t *InFileNN); + void SetScaledEdx(Float_t s) {fScale = s;}; + + void MakeTrainingLists(); // build the training and the test list + void MonitorTraining(Int_t mombin); // monitor training process + +protected: + void MakeRefs(Int_t mombin); // train the neural networks for a given momentum bin + +private: + AliTRDpidRefMakerNN(const AliTRDpidRefMakerNN&); // not implemented + AliTRDpidRefMakerNN& operator=(const AliTRDpidRefMakerNN&); // not implemented + + TEventList *fTrain[AliTRDCalPID::kNMom][AliTRDgeometry::kNlayer]; // Training list for each momentum + TEventList *fTest[AliTRDCalPID::kNMom][AliTRDgeometry::kNlayer]; // Test list for each momentum + TMultiLayerPerceptron *fNet[AliTRDgeometry::kNlayer]; // artificial neural network + + Int_t fTrainMomBin; // momentum bin for the training + Int_t fEpochs; // Number of epochs for the training of the NNs + Int_t fMinTrain; // minimum of events needed for training + Int_t fDate; // date stamp for training of the NNs + Bool_t fDoTraining; // checks if training will be done + Bool_t fContinueTraining; // checks if training from an older run should be continued + Int_t fTrainPath; // sets the path for continuing the training + + Float_t fScale; + + ClassDef(AliTRDpidRefMakerNN, 2); // TRD reference maker for NN +}; + +#endif diff --git a/PWG1/TRD/AliTRDrecoTask.cxx b/PWG1/TRD/AliTRDrecoTask.cxx new file mode 100644 index 00000000000..4937f5fbe0c --- /dev/null +++ b/PWG1/TRD/AliTRDrecoTask.cxx @@ -0,0 +1,270 @@ +/////////////////////////////////////////////////////// +// +// Basic class for Performance/Calibration TRD tasks +// +// It performs generic tasks like : +// - data file manegment +// - reference container management +// - debug container management +// - interaction with AliAnalysisManager +// - Plot functor loop +// +// Author: Alexandru Bercuci , 10/09/2008 +// +///////////////////////////////////////////////////////// + +#include "TClass.h" +#include "TMethod.h" +#include "TMethodCall.h" +#include "TMethodArg.h" +#include "TFile.h" +#include "TList.h" +#include "TMap.h" +#include "TH1.h" +#include "TF1.h" +#include "TObjArray.h" +#include "TDirectory.h" +#include "TTreeStream.h" + +#include "AliLog.h" +#include "AliAnalysisTask.h" + +#include "AliTRDrecoTask.h" + +ClassImp(AliTRDrecoTask) + +TList* AliTRDrecoTask::fgTrendPoint(0x0); +TTreeSRedirector* AliTRDrecoTask::fgDebugStream(0x0); +//_______________________________________________________ +AliTRDrecoTask::AliTRDrecoTask(const char *name, const char *title) + : AliAnalysisTask(name, title) + ,fNRefFigures(0) + ,fContainer(0x0) + ,fTracks(0x0) + ,fkTrack(0x0) + ,fkMC(0x0) + ,fkESD(0x0) + ,fDebugLevel(0) + ,fPlotFuncList(0x0) +{ + DefineInput(0, TObjArray::Class()); + DefineOutput(0, TObjArray::Class()); +} + +//_______________________________________________________ +AliTRDrecoTask::~AliTRDrecoTask() +{ + + // Generic task destructor + + AliDebug(1, Form(" Ending %s (%s)\n", GetName(), GetTitle())); + if(fgDebugStream){ + delete fgDebugStream; + fgDebugStream = 0x0; + } + + if(fPlotFuncList){ + fPlotFuncList->Delete(); + delete fPlotFuncList; + fPlotFuncList = 0x0; + } + + if(fContainer){ + if(fContainer->IsOwner()) fContainer->Delete(); + delete fContainer; + fContainer = 0x0; + } + + if(fgTrendPoint){ + TFile::Open("TRD.PerformanceTrend.root", "UPDATE"); + fgTrendPoint->Write(); + delete fgTrendPoint; + fgTrendPoint=0x0; + gFile->Close(); + } +} + +//_______________________________________________________ +void AliTRDrecoTask::ConnectInputData(Option_t *) +{ + // + // Connect input data + // + + fTracks = dynamic_cast(GetInputData(0)); +} + +//_______________________________________________________ +void AliTRDrecoTask::Exec(Option_t *) +{ +// Loop over Plot functors published by particular tasks + + if(!fPlotFuncList){ + AliWarning("No functor list defined for the reference plots"); + return; + } + if(!fTracks) return; + if(!fTracks->GetEntriesFast()) return; + + AliTRDtrackInfo *trackInfo = 0x0; + TIter plotIter(fPlotFuncList); + TObjArrayIter trackIter(fTracks); + while((trackInfo = dynamic_cast(trackIter()))){ + fkTrack = trackInfo->GetTrack(); + fkMC = trackInfo->GetMCinfo(); + fkESD = trackInfo->GetESDinfo(); + + TMethodCall *plot = 0x0; + plotIter.Reset(); + while((plot=dynamic_cast(plotIter()))){ + plot->Execute(this); + } + } + PostData(0, fContainer); +} + +//_______________________________________________________ +Bool_t AliTRDrecoTask::GetRefFigure(Int_t /*ifig*/) +{ + AliWarning("Retrieving reference figures not implemented."); + return kFALSE; +} + +//_______________________________________________________ +Bool_t AliTRDrecoTask::PutTrendValue(const Char_t *name, Double_t val) +{ +// Generic publisher for trend values + + if(!fgTrendPoint){ + fgTrendPoint = new TList(); + fgTrendPoint->SetOwner(); + } + fgTrendPoint->AddLast(new TNamed(Form("%s_%s", GetName(), name), Form("%f", val))); + return kTRUE; +} + +//_______________________________________________________ +void AliTRDrecoTask::InitFunctorList() +{ +// Initialize list of functors + + TClass *c = this->IsA(); + + TMethod *m = 0x0; + TIter methIter(c->GetListOfMethods()); + while((m=dynamic_cast(methIter()))){ + TString name(m->GetName()); + if(!name.BeginsWith("Plot")) continue; + if(!fPlotFuncList) fPlotFuncList = new TList(); + fPlotFuncList->AddLast(new TMethodCall(c, (const char*)name, "")); + } +} + +//_______________________________________________________ +Bool_t AliTRDrecoTask::Load(const Char_t *filename) +{ +// Generic container loader + + if(!TFile::Open(filename)){ + AliWarning(Form("Couldn't open file %s.", filename)); + return kFALSE; + } + TObjArray *o = 0x0; + if(!(o = (TObjArray*)gFile->Get(GetName()))){ + AliWarning("Missing histogram container."); + return kFALSE; + } + fContainer = (TObjArray*)o->Clone(GetName()); + gFile->Close(); + return kTRUE; +} + +//________________________________________________________ +Bool_t AliTRDrecoTask::Save(TObjArray * const results){ + // + // Store the output graphs in a ROOT file + // Input TObject array will not be written as Key to the file, + // only content itself + // + + TDirectory *cwd = gDirectory; + if(!TFile::Open(Form("TRD.Result%s.root", GetName()), "RECREATE")) return kFALSE; + + TIterator *iter = results->MakeIterator(); + TObject *inObject = 0x0, *outObject = 0x0; + while((inObject = iter->Next())){ + outObject = inObject->Clone(); + outObject->Write(0x0, TObject::kSingleKey); + } + delete iter; + gFile->Close(); delete gFile; + cwd->cd(); + return kTRUE; +} + +//_______________________________________________________ +Bool_t AliTRDrecoTask::PostProcess() +{ +// To be implemented by particular tasks + + AliWarning("Post processing of reference histograms not implemented."); + return kFALSE; +} + +//_______________________________________________________ +void AliTRDrecoTask::SetDebugLevel(Int_t level) +{ +// Generic debug handler + + fDebugLevel = level; + if(fDebugLevel>=1){ + TDirectory *savedir = gDirectory; + fgDebugStream = new TTreeSRedirector("TRD.DebugPerformance.root"); + savedir->cd(); + } +} + +//____________________________________________________________________ +void AliTRDrecoTask::Terminate(Option_t *) +{ + // + // Terminate + // + + if(fgDebugStream){ + delete fgDebugStream; + fgDebugStream = 0x0; + fDebugLevel = 0; + } + if(HasPostProcess()) PostProcess(); +} + +//________________________________________________________ +void AliTRDrecoTask::Adjust(TF1 *f, TH1 * const h) +{ +// Helper function to avoid duplication of code +// Make first guesses on the fit parameters + + // find the intial parameters of the fit !! (thanks George) + Int_t nbinsy = Int_t(.5*h->GetNbinsX()); + Double_t sum = 0.; + for(Int_t jbin=nbinsy-4; jbin<=nbinsy+4; jbin++) sum+=h->GetBinContent(jbin); sum/=9.; + f->SetParLimits(0, 0., 3.*sum); + f->SetParameter(0, .9*sum); + + f->SetParLimits(1, -.2, .2); + f->SetParameter(1, -0.1); + + f->SetParLimits(2, 0., 4.e-1); + f->SetParameter(2, 2.e-2); + if(f->GetNpar() <= 4) return; + + f->SetParLimits(3, 0., sum); + f->SetParameter(3, .1*sum); + + f->SetParLimits(4, -.3, .3); + f->SetParameter(4, 0.); + + f->SetParLimits(5, 0., 1.e2); + f->SetParameter(5, 2.e-1); +} diff --git a/PWG1/TRD/AliTRDrecoTask.h b/PWG1/TRD/AliTRDrecoTask.h new file mode 100644 index 00000000000..66d280583f6 --- /dev/null +++ b/PWG1/TRD/AliTRDrecoTask.h @@ -0,0 +1,88 @@ +#ifndef ALITRDRECOTASK_H +#define ALITRDRECOTASK_H + +/////////////////////////////////////////////////////// +// +// Basic class for Performance/Calibration TRD tasks +// +// Author: Alexandru Bercuci, 10/09/2008 +// +////////////////////////////////////////////////// + +#ifndef ALIANALYSISTASK_H +#include "AliAnalysisTask.h" +#endif + +#ifndef ALITRDTRACKINFO_H +#include "info/AliTRDtrackInfo.h" +#endif + +class TH1; +class TF1; +class TList; +class TObjArray; +class TTreeSRedirector; +class AliTRDtrackV1; +class AliTRDtrackInfo; +class AliTRDrecoTask : public AliAnalysisTask +{ +public: + enum AliTRDrecoSteeringBits{ + kMCdata = BIT(20) + ,kFriends = BIT(21) + ,kPostProcess = BIT(22) + }; + AliTRDrecoTask(const char *name, const char *title); + virtual ~AliTRDrecoTask(); + + + void ConnectInputData(Option_t *); + virtual void CreateOutputObjects() = 0; + virtual void Exec(Option_t *); + + Int_t GetNRefFigures() const { return fNRefFigures; } + TList* GetPlotFunctors() const { return fPlotFuncList;} + virtual Bool_t GetRefFigure(Int_t ifig); + + Bool_t HasFriends() const { return TestBit(kFriends);}; + Bool_t HasMCdata() const { return TestBit(kMCdata);}; + Bool_t HasPostProcess() const { return TestBit(kPostProcess);}; + virtual TObjArray* Histos() { return fContainer;} + + virtual Bool_t Load(const Char_t *filename = "TRD.Performance.root"); + virtual Bool_t Save(TObjArray * const res); + virtual Bool_t PostProcess(); + virtual Bool_t PutTrendValue(const Char_t *name, Double_t val); + virtual void SetDebugLevel(Int_t level); + virtual void SetFriends(Bool_t fr = kTRUE) {SetBit(kFriends, fr);} + virtual void SetMCdata(Bool_t mc = kTRUE) {SetBit(kMCdata, mc);} + virtual void SetPostProcess(Bool_t pp = kTRUE) {SetBit(kPostProcess, pp);} + virtual void Terminate(Option_t *); + +protected: + Int_t DebugLevel() const { return fDebugLevel;} + static TTreeSRedirector* DebugStream() { return fgDebugStream;} + void InitFunctorList(); + void Adjust(TF1 *f, TH1 * const h); + + UChar_t fNRefFigures; //! no of reference figures reported by task + TObjArray *fContainer; //! container to store results + TObjArray *fTracks; //! Array of tracks + const AliTRDtrackV1 *fkTrack; //! current track + const AliTRDtrackInfo::AliMCinfo *fkMC; //! MC info + const AliTRDtrackInfo::AliESDinfo *fkESD;//! ESD info + +private: + AliTRDrecoTask(const AliTRDrecoTask&); + AliTRDrecoTask& operator=(const AliTRDrecoTask&); + + UChar_t fDebugLevel; //! Debug level + TList *fPlotFuncList;//! plot functors list + static TList *fgTrendPoint; //! trend point + static TTreeSRedirector *fgDebugStream; //! Debug stream + + ClassDef(AliTRDrecoTask, 1) // base TRD reconstruction task +}; + +#endif + diff --git a/PWG1/TRD/AliTRDresolution.cxx b/PWG1/TRD/AliTRDresolution.cxx new file mode 100644 index 00000000000..3f346e3d2ab --- /dev/null +++ b/PWG1/TRD/AliTRDresolution.cxx @@ -0,0 +1,2048 @@ +/************************************************************************** +* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* * +* Author: The ALICE Off-line Project. * +* Contributors are mentioned in the code where appropriate. * +* * +* Permission to use, copy, modify and distribute this software and its * +* documentation strictly for non-commercialf purposes is hereby granted * +* without fee, provided that the above copyright notice appears in all * +* copies and that both the copyright notice and this permission notice * +* appear in the supporting documentation. The authors make no claims * +* about the suitability of this software for any purpose. It is * +* provided "as is" without express or implied warranty. * +**************************************************************************/ + +/* $Id: AliTRDresolution.cxx 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// TRD tracking resolution // +// +// The class performs resolution and residual studies +// of the TRD tracks for the following quantities : +// - spatial position (y, [z]) +// - angular (phi) tracklet +// - momentum at the track level +// +// The class has to be used for regular detector performance checks using the official macros: +// - $ALICE_ROOT/TRD/qaRec/run.C +// - $ALICE_ROOT/TRD/qaRec/makeResults.C +// +// For stand alone usage please refer to the following example: +// { +// gSystem->Load("libANALYSIS.so"); +// gSystem->Load("libTRDqaRec.so"); +// AliTRDresolution *res = new AliTRDresolution(); +// //res->SetMCdata(); +// //res->SetVerbose(); +// //res->SetVisual(); +// res->Load(); +// if(!res->PostProcess()) return; +// res->GetRefFigure(0); +// } +// +// Authors: // +// Alexandru Bercuci // +// Markus Fasel // +// // +//////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AliPID.h" + +#include "AliTRDresolution.h" +#include "AliTRDgeometry.h" +#include "AliTRDpadPlane.h" +#include "AliTRDcluster.h" +#include "AliTRDseedV1.h" +#include "AliTRDtrackV1.h" +#include "AliTRDReconstructor.h" +#include "AliTRDrecoParam.h" + +#include "info/AliTRDclusterInfo.h" + +ClassImp(AliTRDresolution) + +UChar_t const AliTRDresolution::fgNElements[kNhistos] = { + 2, 2, 5, 5, + 2, 5, 12, 2, 11 +}; +Char_t const * AliTRDresolution::fgPerformanceName[kNhistos] = { + "Charge" + ,"Cluster2Track" + ,"Tracklet2Track" + ,"Tracklet2TPC" + ,"Cluster2MC" + ,"Tracklet2MC" + ,"TPC2MC" + ,"TOF/HMPID2MC" + ,"TRD2MC" +}; +Char_t const *AliTRDresolution::fgAxTitle[46][4] = { + // Charge + {"Impv", "x [cm]", "I_{mpv}", "x/x_{0}"} + ,{"dI/Impv", "x/x_{0}", "#delta I/I_{mpv}", "x[cm]"} + // Clusters to Kalman + ,{"Pos", "tg(#phi)", "#mu_{y}^{cl} [#mum]", "#sigma_{y}^{cl} [#mum]"} + ,{"Pulls", "tg(#phi)", "PULL: #mu_{y}^{cl}", "PULL: #sigma_{y}^{cl}"} + // TRD tracklet to Kalman fit + ,{"PosY", "tg(#phi)", "#mu_{y}^{trklt} [#mum]", "#sigma_{y}^{trklt} [#mum]"} + ,{"PullsY", "tg(#phi)", "PULL: #mu_{y}^{trklt}", "PULL: #sigma_{y}^{trklt}"} + ,{"PosZ", "tg(#theta)", "#mu_{z}^{trklt} [#mum]", "#sigma_{z}^{trklt} [#mum]"} + ,{"PullsZ", "tg(#theta)", "PULL: #mu_{z}^{trklt}", "PULL: #sigma_{z}^{trklt}"} + ,{"Phi", "tg(#phi)", "#mu_{#phi}^{trklt} [mrad]", "#sigma_{#phi}^{trklt} [mrad]"} + // TPC track 2 first TRD tracklet + ,{"PosY", "tg(#phi)", "#mu_{y}^{TPC trklt} [#mum]", "#sigma_{y}^{TPC trklt} [#mum]"} + ,{"PullsY", "tg(#phi)", "PULL: #mu_{y}^{TPC trklt}", "PULL: #sigma_{y}^{TPC trklt}"} + ,{"PosZ", "tg(#theta)", "#mu_{z}^{TPC trklt} [#mum]", "#sigma_{z}^{TPC trklt} [#mum]"} + ,{"PullsZ", "tg(#theta)", "PULL: #mu_{z}^{TPC trklt}", "PULL: #sigma_{z}^{TPC trklt}"} + ,{"Phi", "tg(#phi)", "#mu_{#phi}^{TPC trklt} [mrad]", "#sigma_{#phi}^{TPC trklt} [mrad]"} + // MC cluster + ,{"Pos", "tg(#phi)", "MC: #mu_{y}^{cl} [#mum]", "MC: #sigma_{y}^{cl} [#mum]"} + ,{"Pulls", "tg(#phi)", "MC PULL: #mu_{y}^{cl}", "MC PULL: #sigma_{y}^{cl}"} + // MC tracklet + ,{"PosY", "tg(#phi)", "MC: #mu_{y}^{trklt} [#mum]", "MC: #sigma_{y}^{trklt} [#mum]"} + ,{"PullsY", "tg(#phi)", "MC PULL: #mu_{y}^{trklt}", "MC PULL: #sigma_{y}^{trklt}"} + ,{"PosZ", "tg(#theta)", "MC: #mu_{z}^{trklt} [#mum]", "MC: #sigma_{z}^{trklt} [#mum]"} + ,{"PullsZ", "tg(#theta)", "MC PULL: #mu_{z}^{trklt}", "MC PULL: #sigma_{z}^{trklt}"} + ,{"Phi", "tg(#phi)", "MC: #mu_{#phi}^{trklt} [mrad]", "MC: #sigma_{#phi}^{trklt} [mrad]"} + // MC track TPC + ,{"PosY", "tg(#phi)", "MC: #mu_{y}^{TPC} [#mum]", "MC: #sigma_{y}^{TPC} [#mum]"} + ,{"PullsY", "tg(#phi)", "MC PULL: #mu_{y}^{TPC}", "MC PULL: #sigma_{y}^{TPC}"} + ,{"PosZ", "tg(#theta)", "MC: #mu_{z}^{TPC} [#mum]", "MC: #sigma_{z}^{TPC} [#mum]"} + ,{"PullsZ", "tg(#theta)", "MC PULL: #mu_{z}^{TPC}", "MC PULL: #sigma_{z}^{TPC}"} + ,{"Phi", "tg(#phi)", "MC: #mu_{#phi}^{TPC} [mrad]", "MC: #sigma_{#phi}^{TPC} [mrad]"} + ,{"PullsSNP", "tg(#phi)", "MC PULL: #mu_{snp}^{TPC}", "MC PULL: #sigma_{snp}^{TPC}"} + ,{"Theta", "tg(#theta)", "MC: #mu_{#theta}^{TPC} [mrad]", "MC: #sigma_{#theta}^{TPC} [mrad]"} + ,{"PullsTGL", "tg(#theta)", "MC PULL: #mu_{tgl}^{TPC}", "MC PULL: #sigma_{tgl}^{TPC}"} + ,{"Pt", "p_{t}^{MC} [GeV/c]", "MC: #mu^{TPC}(#Deltap_{t}/p_{t}^{MC}) [%]", "MC: #sigma^{TPC}(#Deltap_{t}/p_{t}^{MC}) [%]"} + ,{"Pulls1Pt", "1/p_{t}^{MC} [c/GeV]", "MC PULL: #mu_{1/p_{t}}^{TPC}", "MC PULL: #sigma_{1/p_{t}}^{TPC}"} + ,{"P", "p^{MC} [GeV/c]", "MC: #mu^{TPC}(#Deltap/p^{MC}) [%]", "MC: #sigma^{TPC}(#Deltap/p^{MC}) [%]"} + ,{"PullsP", "p^{MC} [GeV/c]", "MC PULL: #mu^{TPC}(#Deltap/#sigma_{p})", "MC PULL: #sigma^{TPC}(#Deltap/#sigma_{p})"} + // MC track TOF + ,{"PosZ", "tg(#theta)", "MC: #mu_{z}^{TOF} [#mum]", "MC: #sigma_{z}^{TOF} [#mum]"} + ,{"PullsZ", "tg(#theta)", "MC PULL: #mu_{z}^{TOF}", "MC PULL: #sigma_{z}^{TOF}"} + // MC track in TRD + ,{"PosY", "tg(#phi)", "MC: #mu_{y}^{Trk} [#mum]", "MC: #sigma_{y}^{Trk} [#mum]"} + ,{"PullsY", "tg(#phi)", "MC PULL: #mu_{y}^{Trk}", "MC PULL: #sigma_{y}^{Trk}"} + ,{"PosZ", "tg(#theta)", "MC: #mu_{z}^{Trk} [#mum]", "MC: #sigma_{z}^{Trk} [#mum]"} + ,{"PullsZ", "tg(#theta)", "MC PULL: #mu_{z}^{Trk}", "MC PULL: #sigma_{z}^{Trk}"} + ,{"Phi", "tg(#phi)", "MC: #mu_{#phi}^{Trk} [mrad]", "MC: #sigma_{#phi}^{Trk} [mrad]"} + ,{"PullsSNP", "tg(#phi)", "MC PULL: #mu_{snp}^{Trk}", "MC PULL: #sigma_{snp}^{Trk}"} + ,{"Theta", "tg(#theta)", "MC: #mu_{#theta}^{Trk} [mrad]", "MC: #sigma_{#theta}^{Trk} [mrad]"} + ,{"PullsTGL", "tg(#theta)", "MC PULL: #mu_{tgl}^{Trk}", "MC PULL: #sigma_{tgl}^{Trk}"} + ,{"Pt", "p_{t}^{MC} [GeV/c]", "MC: #mu^{Trk}(#Deltap_{t}/p_{t}^{MC}) [%]", "MC: #sigma^{Trk}(#Deltap_{t}/p_{t}^{MC}) [%]"} + ,{"Pulls1Pt", "1/p_{t}^{MC} [c/GeV]", "MC PULL: #mu_{1/p_{t}}^{Trk}", "MC PULL: #sigma_{1/p_{t}}^{Trk}"} + ,{"P", "p^{MC} [GeV/c]", "MC: #mu^{Trk}(#Deltap/p^{MC}) [%]", "MC: #sigma^{Trk}(#Deltap/p^{MC}) [%]"} +}; + +//________________________________________________________ +AliTRDresolution::AliTRDresolution() + :AliTRDrecoTask("resolution", "Spatial and momentum TRD resolution checker") + ,fStatus(0) + ,fIdxPlot(0) + ,fReconstructor(0x0) + ,fGeo(0x0) + ,fGraphS(0x0) + ,fGraphM(0x0) + ,fCl(0x0) + ,fTrklt(0x0) + ,fMCcl(0x0) + ,fMCtrklt(0x0) +{ + // + // Default constructor + // + + fReconstructor = new AliTRDReconstructor(); + fReconstructor->SetRecoParam(AliTRDrecoParam::GetLowFluxParam()); + fGeo = new AliTRDgeometry(); + + InitFunctorList(); + + DefineOutput(1, TObjArray::Class()); // cluster2track + DefineOutput(2, TObjArray::Class()); // tracklet2track + DefineOutput(3, TObjArray::Class()); // cluster2mc + DefineOutput(4, TObjArray::Class()); // tracklet2mc +} + +//________________________________________________________ +AliTRDresolution::~AliTRDresolution() +{ + // + // Destructor + // + + if(fGraphS){fGraphS->Delete(); delete fGraphS;} + if(fGraphM){fGraphM->Delete(); delete fGraphM;} + delete fGeo; + delete fReconstructor; + if(gGeoManager) delete gGeoManager; + if(fCl){fCl->Delete(); delete fCl;} + if(fTrklt){fTrklt->Delete(); delete fTrklt;} + if(fMCcl){fMCcl->Delete(); delete fMCcl;} + if(fMCtrklt){fMCtrklt->Delete(); delete fMCtrklt;} +} + + +//________________________________________________________ +void AliTRDresolution::CreateOutputObjects() +{ + // spatial resolution + OpenFile(0, "RECREATE"); + + fContainer = Histos(); + + fCl = new TObjArray(); + fCl->SetOwner(kTRUE); + fTrklt = new TObjArray(); + fTrklt->SetOwner(kTRUE); + fMCcl = new TObjArray(); + fMCcl->SetOwner(kTRUE); + fMCtrklt = new TObjArray(); + fMCtrklt->SetOwner(kTRUE); +} + +//________________________________________________________ +void AliTRDresolution::Exec(Option_t *opt) +{ + // + // Execution part + // + + fCl->Delete(); + fTrklt->Delete(); + fMCcl->Delete(); + fMCtrklt->Delete(); + + AliTRDrecoTask::Exec(opt); + + PostData(1, fCl); + PostData(2, fTrklt); + PostData(3, fMCcl); + PostData(4, fMCtrklt); +} + +//________________________________________________________ +TH1* AliTRDresolution::PlotCharge(const AliTRDtrackV1 *track) +{ + // + // Plots the charge distribution + // + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TObjArray *arr = 0x0; + if(!(arr = ((TObjArray*)fContainer->At(kCharge)))){ + AliWarning("No output container defined."); + return 0x0; + } + TH3S* h = 0x0; + + AliTRDseedV1 *fTracklet = 0x0; + AliTRDcluster *c = 0x0; + for(Int_t ily=0; ilyGetTracklet(ily))) continue; + if(!fTracklet->IsOK()) continue; + Float_t x0 = fTracklet->GetX0(); + Float_t dq, dl; + for(Int_t itb=AliTRDseedV1::kNtb; itb--;){ + if(!(c = fTracklet->GetClusters(itb))){ + if(!(c = fTracklet->GetClusters(AliTRDseedV1::kNtb+itb))) continue; + } + dq = fTracklet->GetdQdl(itb, &dl); + dl /= 0.15; // dl/dl0, dl0 = 1.5 mm for nominal vd + (h = (TH3S*)arr->At(0))->Fill(dl, x0-c->GetX(), dq); + } + +// if(!HasMCdata()) continue; +// UChar_t s; +// Float_t pt0, y0, z0, dydx0, dzdx0; +// if(!fMC->GetDirections(x0, y0, z0, dydx0, dzdx0, pt0, s)) continue; + + } + return h; +} + + +//________________________________________________________ +TH1* AliTRDresolution::PlotCluster(const AliTRDtrackV1 *track) +{ + // + // Plot the cluster distributions + // + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TObjArray *arr = 0x0; + if(!(arr = ((TObjArray*)fContainer->At(kCluster)))){ + AliWarning("No output container defined."); + return 0x0; + } + + Double_t cov[7]; + Float_t x0, y0, z0, dy, dydx, dzdx; + AliTRDseedV1 *fTracklet = 0x0; + for(Int_t ily=0; ilyGetTracklet(ily))) continue; + if(!fTracklet->IsOK()) continue; + x0 = fTracklet->GetX0(); + + // retrive the track angle with the chamber + y0 = fTracklet->GetYref(0); + z0 = fTracklet->GetZref(0); + dydx = fTracklet->GetYref(1); + dzdx = fTracklet->GetZref(1); + fTracklet->GetCovRef(cov); + Float_t tilt = fTracklet->GetTilt(); + AliTRDcluster *c = 0x0; + fTracklet->ResetClusterIter(kFALSE); + while((c = fTracklet->PrevCluster())){ + Float_t xc = c->GetX(); + Float_t yc = c->GetY(); + Float_t zc = c->GetZ(); + Float_t dx = x0 - xc; + Float_t yt = y0 - dx*dydx; + Float_t zt = z0 - dx*dzdx; + yc -= tilt*(zc-zt); // tilt correction + dy = yt - yc; + + //Float_t sx2 = dydx*c->GetSX(c->GetLocalTimeBin()); sx2*=sx2; + Float_t sy2 = c->GetSigmaY2(); + if(sy2<=0.) continue; + ((TH2I*)arr->At(0))->Fill(dydx, dy); + ((TH2I*)arr->At(1))->Fill(dydx, dy/TMath::Sqrt(cov[0] /*+ sx2*/ + sy2)); + +/* if(DebugLevel()>=3){ + // Get z-position with respect to anode wire + //AliTRDSimParam *simParam = AliTRDSimParam::Instance(); + Int_t istk = fGeo->GetStack(c->GetDetector()); + AliTRDpadPlane *pp = fGeo->GetPadPlane(ily, istk); + Float_t row0 = pp->GetRow0(); + Float_t d = row0 - zt + pp->GetAnodeWireOffset(); + d -= ((Int_t)(2 * d)) / 2.0; + if (d > 0.25) d = 0.5 - d; + + AliTRDclusterInfo *clInfo = new AliTRDclusterInfo; + fCl->Add(clInfo); + clInfo->SetCluster(c); + clInfo->SetGlobalPosition(yt, zt, dydx, dzdx); + clInfo->SetResolution(dy); + clInfo->SetAnisochronity(d); + clInfo->SetDriftLength(dx); + (*DebugStream()) << "ClusterResiduals" + <<"clInfo.=" << clInfo + << "\n"; + }*/ + } + } + return (TH2I*)arr->At(0); +} + + +//________________________________________________________ +TH1* AliTRDresolution::PlotTracklet(const AliTRDtrackV1 *track) +{ +// Plot normalized residuals for tracklets to track. +// +// We start from the result that if X=N(|m|, |Cov|) +// BEGIN_LATEX +// (Cov^{-1})^{1/2}X = N((Cov^{-1})^{1/2}*|m|, |1|) +// END_LATEX +// in our case X=(y_trklt - y_trk z_trklt - z_trk) and |Cov| = |Cov_trklt| + |Cov_trk| at the radial +// reference position. + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TObjArray *arr = 0x0; + if(!(arr = (TObjArray*)fContainer->At(kTrackTRD ))){ + AliWarning("No output container defined."); + return 0x0; + } + + Double_t cov[3], covR[7]/*, sqr[3], inv[3]*/; + Float_t x, dx, dy, dz; + AliTRDseedV1 *fTracklet = 0x0; + for(Int_t il=AliTRDgeometry::kNlayer; il--;){ + if(!(fTracklet = fkTrack->GetTracklet(il))) continue; + if(!fTracklet->IsOK()) continue; + x = fTracklet->GetX(); + dx = fTracklet->GetX0() - x; + // compute dy^2 and dz^2 + dy = fTracklet->GetYref(0)-dx*fTracklet->GetYref(1) - fTracklet->GetY(); + dz = fTracklet->GetZref(0)-dx*fTracklet->GetZref(1) - fTracklet->GetZ(); + // compute covariance matrix + fTracklet->GetCovAt(x, cov); + fTracklet->GetCovRef(covR); + cov[0] += covR[0]; cov[1] += covR[1]; cov[2] += covR[2]; +/* // Correct PULL calculation by considering off + // diagonal elements in the covariance matrix + // compute square root matrix + if(AliTRDseedV1::GetCovInv(cov, inv)==0.) continue; + if(AliTRDseedV1::GetCovSqrt(inv, sqr)<0.) continue; + Double_t y = sqr[0]*dy+sqr[1]*dz; + Double_t z = sqr[1]*dy+sqr[2]*dz; + ((TH3*)h)->Fill(y, z, fTracklet->GetYref(1));*/ + + ((TH2I*)arr->At(0))->Fill(fTracklet->GetYref(1), dy); + ((TH2I*)arr->At(1))->Fill(fTracklet->GetYref(1), dy/TMath::Sqrt(cov[0])); + ((TH2I*)arr->At(4))->Fill(fTracklet->GetYref(1), TMath::ATan((fTracklet->GetYref(1)-fTracklet->GetYfit(1))/(1-fTracklet->GetYref(1)*fTracklet->GetYfit(1)))); + if(!fTracklet->IsRowCross()) continue; + ((TH2I*)arr->At(2))->Fill(fTracklet->GetZref(1), dz); + ((TH2I*)arr->At(3))->Fill(fTracklet->GetZref(1), dz/TMath::Sqrt(cov[2])); + } + + + return (TH2I*)arr->At(0); +} + + +//________________________________________________________ +TH1* AliTRDresolution::PlotTrackTPC(const AliTRDtrackV1 *track) +{ +// Store resolution/pulls of Kalman before updating with the TRD information +// at the radial position of the first tracklet. The following points are used +// for comparison +// - the (y,z,snp) of the first TRD tracklet +// - the (y, z, snp, tgl, pt) of the MC track reference +// +// Additionally the momentum resolution/pulls are calculated for usage in the +// PID calculation. + + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + AliExternalTrackParam *tin = 0x0; + if(!(tin = fkTrack->GetTrackLow())){ + AliWarning("Track did not entered TRD fiducial volume."); + return 0x0; + } + TH1 *h = 0x0; + + Double_t x = tin->GetX(); + AliTRDseedV1 *tracklet = 0x0; + for(Int_t ily=0; ilyGetTracklet(ily))) continue; + break; + } + if(!tracklet || TMath::Abs(x-tracklet->GetX())>1.e-3){ + AliWarning("Tracklet did not match TRD entrance."); + return 0x0; + } + const Int_t kNPAR(5); + Double_t parR[kNPAR]; memcpy(parR, tin->GetParameter(), kNPAR*sizeof(Double_t)); + Double_t covR[3*kNPAR]; memcpy(covR, tin->GetCovariance(), 3*kNPAR*sizeof(Double_t)); + Double_t cov[3]; tracklet->GetCovAt(x, cov); + + // define sum covariances + TMatrixDSym COV(kNPAR); TVectorD PAR(kNPAR); + Double_t *pc = &covR[0], *pp = &parR[0]; + for(Int_t ir=0; irGetY(); + TObjArray *arr = (TObjArray*)fContainer->At(kTrackTPC); + ((TH2I*)arr->At(0))->Fill(tracklet->GetYref(1), dy); + ((TH2I*)arr->At(1))->Fill(tracklet->GetYref(1), dy/TMath::Sqrt(COV(0,0)+cov[0])); + if(tracklet->IsRowCross()){ + Double_t dz = parR[1] - tracklet->GetZ(); + ((TH2I*)arr->At(2))->Fill(tracklet->GetZref(1), dz); + ((TH2I*)arr->At(3))->Fill(tracklet->GetZref(1), dz/TMath::Sqrt(COV(1,1)+cov[2])); + } + Double_t dphi = TMath::ASin(PAR[2])-TMath::ATan(tracklet->GetYfit(1)); ((TH2I*)arr->At(4))->Fill(tracklet->GetYref(1), dphi); + + + // register reference histo for mini-task + h = (TH2I*)arr->At(0); + + if(DebugLevel()>=1){ + (*DebugStream()) << "trackIn" + << "x=" << x + << "P=" << &PAR + << "C=" << &COV + << "\n"; + + Double_t y = tracklet->GetY(); + Double_t z = tracklet->GetZ(); + (*DebugStream()) << "trackletIn" + << "y=" << y + << "z=" << z + << "Vy=" << cov[0] + << "Cyz=" << cov[1] + << "Vz=" << cov[2] + << "\n"; + } + + + if(!HasMCdata()) return h; + UChar_t s; + Float_t dx, pt0, x0=tracklet->GetX0(), y0, z0, dydx0, dzdx0; + if(!fkMC->GetDirections(x0, y0, z0, dydx0, dzdx0, pt0, s)) return h; + // translate to reference radial position + dx = x0 - x; y0 -= dx*dydx0; z0 -= dx*dzdx0; + Float_t norm = 1./TMath::Sqrt(1.+dydx0*dydx0); // 1/sqrt(1+tg^2(phi)) + //Fill MC info + TVectorD PARMC(kNPAR); + PARMC[0]=y0; PARMC[1]=z0; + PARMC[2]=dydx0*norm; PARMC[3]=dzdx0*norm; + PARMC[4]=1./pt0; + +// TMatrixDSymEigen eigen(COV); +// TVectorD evals = eigen.GetEigenValues(); +// TMatrixDSym evalsm(kNPAR); +// for(Int_t ir=0; irAt(kMCtrackTPC); + // y resolution/pulls + ((TH2I*)arr->At(0))->Fill(dydx0, PARMC[0]-PAR[0]); + ((TH2I*)arr->At(1))->Fill(dydx0, (PARMC[0]-PAR[0])/TMath::Sqrt(COV(0,0))); + // z resolution/pulls + ((TH2I*)arr->At(2))->Fill(dzdx0, PARMC[1]-PAR[1]); + ((TH2I*)arr->At(3))->Fill(dzdx0, (PARMC[1]-PAR[1])/TMath::Sqrt(COV(1,1))); + // phi resolution/snp pulls + ((TH2I*)arr->At(4))->Fill(dydx0, TMath::ASin(PARMC[2])-TMath::ASin(PAR[2])); + ((TH2I*)arr->At(5))->Fill(dydx0, (PARMC[2]-PAR[2])/TMath::Sqrt(COV(2,2))); + // theta resolution/tgl pulls + ((TH2I*)arr->At(6))->Fill(dzdx0, TMath::ATan((PARMC[3]-PAR[3])/(1-PARMC[3]*PAR[3]))); + ((TH2I*)arr->At(7))->Fill(dzdx0, (PARMC[3]-PAR[3])/TMath::Sqrt(COV(3,3))); + // pt resolution\\1/pt pulls\\p resolution/pull + for(Int_t is=AliPID::kSPECIES; is--;){ + if(TMath::Abs(fkMC->GetPDG())!=AliPID::ParticleCode(is)) continue; + ((TH3S*)arr->At(8))->Fill(pt0, PARMC[4]/PAR[4]-1., is); + ((TH3S*)arr->At(9))->Fill(PARMC[4], (PARMC[4]-PAR[4])/TMath::Sqrt(COV(4,4)), is); + + Double_t p0 = TMath::Sqrt(1.+ PARMC[3]*PARMC[3])*pt0, p; + Float_t sp; + p = tracklet->GetMomentum(&sp); + ((TH3S*)arr->At(10))->Fill(p0, p/p0-1., is); + ((TH3S*)arr->At(11))->Fill(p0, (p0-p)/sp, is); + break; + } + + // fill debug for MC + if(DebugLevel()>=1){ + (*DebugStream()) << "trackInMC" + << "P=" << &PARMC + << "\n"; + } + return h; +} + +//________________________________________________________ +TH1* AliTRDresolution::PlotMC(const AliTRDtrackV1 *track) +{ + // + // Plot MC distributions + // + + if(!HasMCdata()){ + AliWarning("No MC defined. Results will not be available."); + return 0x0; + } + if(track) fkTrack = track; + if(!fkTrack){ + AliWarning("No Track defined."); + return 0x0; + } + TObjArray *arr = 0x0; + TH1 *h = 0x0; + UChar_t s; + Int_t pdg = fkMC->GetPDG(), det=-1; + Int_t label = fkMC->GetLabel(); + Double_t xAnode, x, y, z, pt, dydx, dzdx, dzdl; + Float_t pt0, x0, y0, z0, dx, dy, dz, dydx0, dzdx0; + Double_t covR[7]/*, cov[3]*/; + + if(DebugLevel()>=1){ + Double_t dX[12], dY[12], dZ[12], dPt[12], cCOV[12][15]; + fkMC->PropagateKalman(dX, dY, dZ, dPt, cCOV); + (*DebugStream()) << "MCkalman" + << "pdg=" << pdg + << "dx0=" << dX[0] + << "dx1=" << dX[1] + << "dx2=" << dX[2] + << "dy0=" << dY[0] + << "dy1=" << dY[1] + << "dy2=" << dY[2] + << "dz0=" << dZ[0] + << "dz1=" << dZ[1] + << "dz2=" << dZ[2] + << "dpt0=" << dPt[0] + << "dpt1=" << dPt[1] + << "dpt2=" << dPt[2] + << "\n"; + } + + AliTRDReconstructor rec; + AliTRDseedV1 *fTracklet = 0x0; + for(Int_t ily=0; ilyGetTracklet(ily)))/* || + !fTracklet->IsOK())*/ continue; + + det = fTracklet->GetDetector(); + x0 = fTracklet->GetX0(); + //radial shift with respect to the MC reference (radial position of the pad plane) + x= fTracklet->GetX(); + if(!fkMC->GetDirections(x0, y0, z0, dydx0, dzdx0, pt0, s)) continue; + xAnode = fTracklet->GetX0(); + + // MC track position at reference radial position + dx = x0 - x; + if(DebugLevel()>=1){ + (*DebugStream()) << "MC" + << "det=" << det + << "pdg=" << pdg + << "pt=" << pt0 + << "x=" << x0 + << "y=" << y0 + << "z=" << z0 + << "dydx=" << dydx0 + << "dzdx=" << dzdx0 + << "\n"; + } + Float_t ymc = y0 - dx*dydx0; + Float_t zmc = z0 - dx*dzdx0; + //p = pt0*TMath::Sqrt(1.+dzdx0*dzdx0); // pt -> p + + // Kalman position at reference radial position + dx = xAnode - x; + dydx = fTracklet->GetYref(1); + dzdx = fTracklet->GetZref(1); + dzdl = fTracklet->GetTgl(); + y = fTracklet->GetYref(0) - dx*dydx; + dy = y - ymc; + z = fTracklet->GetZref(0) - dx*dzdx; + dz = z - zmc; + pt = TMath::Abs(fTracklet->GetPt()); + fTracklet->GetCovRef(covR); + + arr = (TObjArray*)fContainer->At(kMCtrackTRD); + // y resolution/pulls + ((TH2I*)arr->At(0))->Fill(dydx0, dy); + ((TH2I*)arr->At(1))->Fill(dydx0, dy/TMath::Sqrt(covR[0])); + // z resolution/pulls + ((TH2I*)arr->At(2))->Fill(dzdx0, dz); + ((TH2I*)arr->At(3))->Fill(dzdx0, dz/TMath::Sqrt(covR[2])); + // phi resolution/ snp pulls + Double_t dtgp = (dydx - dydx0)/(1.- dydx*dydx0); + ((TH2I*)arr->At(4))->Fill(dydx0, TMath::ATan(dtgp)); + Double_t dsnp = dydx/TMath::Sqrt(1.+dydx*dydx) - dydx0/TMath::Sqrt(1.+dydx0*dydx0); + ((TH2I*)arr->At(5))->Fill(dydx0, dsnp/TMath::Sqrt(covR[3])); + // theta resolution/ tgl pulls + Double_t dzdl0 = dzdx0/TMath::Sqrt(1.+dydx0*dydx0), + dtgl = (dzdl - dzdl0)/(1.- dzdl*dzdl0); + ((TH2I*)arr->At(6))->Fill(dzdl0, + TMath::ATan(dtgl)); + ((TH2I*)arr->At(7))->Fill(dzdl0, (dzdl - dzdl0)/TMath::Sqrt(covR[4])); + // pt resolution \\ 1/pt pulls \\ p resolution for PID + for(Int_t is=AliPID::kSPECIES; is--;){ + if(TMath::Abs(pdg)!=AliPID::ParticleCode(is)) continue; + ((TH3S*)((TObjArray*)arr->At(8))->At(ily))->Fill(pt0, pt/pt0-1., is); + ((TH3S*)((TObjArray*)arr->At(9))->At(ily))->Fill(1./pt0, (1./pt-1./pt0)/TMath::Sqrt(covR[6]), is); + Double_t p0 = TMath::Sqrt(1.+ dzdl0*dzdl0)*pt0, + p = TMath::Sqrt(1.+ dzdl*dzdl)*pt; + ((TH3S*)((TObjArray*)arr->At(10))->At(ily))->Fill(p0, p/p0-1., is); + break; + } + + // Fill Debug stream for Kalman track + if(DebugLevel()>=1){ + (*DebugStream()) << "MCtrack" + << "pt=" << pt + << "x=" << x + << "y=" << y + << "z=" << z + << "dydx=" << dydx + << "dzdx=" << dzdx + << "s2y=" << covR[0] + << "s2z=" << covR[2] + << "\n"; + } + + // recalculate tracklet based on the MC info + AliTRDseedV1 tt(*fTracklet); + tt.SetZref(0, z0 - (x0-xAnode)*dzdx0); + tt.SetZref(1, dzdx0); + tt.SetReconstructor(&rec); + tt.Fit(kTRUE, kTRUE); + x= tt.GetX();y= tt.GetY();z= tt.GetZ(); + dydx = tt.GetYfit(1); + dx = x0 - x; + ymc = y0 - dx*dydx0; + zmc = z0 - dx*dzdx0; + Bool_t rc = tt.IsRowCross(); + + // add tracklet residuals for y and dydx + arr = (TObjArray*)fContainer->At(kMCtracklet); + if(!rc){ + dy = y-ymc; + + Float_t dphi = (dydx - dydx0); + dphi /= (1.- dydx*dydx0); + + ((TH2I*)arr->At(0))->Fill(dydx0, dy); + if(tt.GetS2Y()>0.) ((TH2I*)arr->At(1))->Fill(dydx0, dy/TMath::Sqrt(tt.GetS2Y())); + ((TH2I*)arr->At(4))->Fill(dydx0, TMath::ATan(dphi)); + } else { + // add tracklet residuals for z + dz = z-zmc; + ((TH2I*)arr->At(2))->Fill(dzdl0, dz); + if(tt.GetS2Z()>0.) ((TH2I*)arr->At(3))->Fill(dzdl0, dz/TMath::Sqrt(tt.GetS2Z())); + } + + // Fill Debug stream for tracklet + if(DebugLevel()>=1){ + Float_t s2y = tt.GetS2Y(); + Float_t s2z = tt.GetS2Z(); + (*DebugStream()) << "MCtracklet" + << "rc=" << rc + << "x=" << x + << "y=" << y + << "z=" << z + << "dydx=" << dydx + << "s2y=" << s2y + << "s2z=" << s2z + << "\n"; + } + + Int_t istk = AliTRDgeometry::GetStack(det); + AliTRDpadPlane *pp = fGeo->GetPadPlane(ily, istk); + Float_t zr0 = pp->GetRow0() + pp->GetAnodeWireOffset(); + Float_t tilt = fTracklet->GetTilt(); + //Double_t exb = AliTRDCommonParam::Instance()->GetOmegaTau(1.5); + + arr = (TObjArray*)fContainer->At(kMCcluster); + AliTRDcluster *c = 0x0; + fTracklet->ResetClusterIter(kFALSE); + while((c = fTracklet->PrevCluster())){ + Float_t q = TMath::Abs(c->GetQ()); + x = c->GetX(); y = c->GetY();z = c->GetZ(); + dx = x0 - x; + ymc= y0 - dx*dydx0; + zmc= z0 - dx*dzdx0; + dy = ymc - (y - tilt*(z-zmc)); + // Fill Histograms + if(q>20. && q<250.){ + ((TH2I*)arr->At(0))->Fill(dydx0, dy); + ((TH2I*)arr->At(1))->Fill(dydx0, dy/TMath::Sqrt(c->GetSigmaY2())); + } + + // Fill calibration container + Float_t d = zr0 - zmc; + d -= ((Int_t)(2 * d)) / 2.0; + if (d > 0.25) d = 0.5 - d; + AliTRDclusterInfo *clInfo = new AliTRDclusterInfo; + fMCcl->Add(clInfo); + clInfo->SetCluster(c); + clInfo->SetMC(pdg, label); + clInfo->SetGlobalPosition(ymc, zmc, dydx0, dzdx0); + clInfo->SetResolution(dy); + clInfo->SetAnisochronity(d); + clInfo->SetDriftLength(((c->GetPadTime()+0.5)*.1)*1.5); + //dx-.5*AliTRDgeometry::CamHght()); + clInfo->SetTilt(tilt); + + // Fill Debug Tree + if(DebugLevel()>=2){ + //clInfo->Print(); + (*DebugStream()) << "MCcluster" + <<"clInfo.=" << clInfo + << "\n"; + } + } + } + return h; +} + + +//________________________________________________________ +Bool_t AliTRDresolution::GetRefFigure(Int_t ifig) +{ + // + // Get the reference figures + // + + Float_t xy[4] = {0., 0., 0., 0.}; + if(!gPad){ + AliWarning("Please provide a canvas to draw results."); + return kFALSE; + } + TList *l = 0x0; TVirtualPad *pad=0x0; + switch(ifig){ + case kCharge: + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + ((TVirtualPad*)l->At(0))->cd(); + ((TGraphAsymmErrors*)((TObjArray*)fGraphM->At(kCharge))->At(0))->Draw("apl"); + ((TVirtualPad*)l->At(1))->cd(); + ((TGraphErrors*)((TObjArray*)fGraphS->At(kCharge))->At(0))->Draw("apl"); + break; + case kCluster: + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0] = -.3; xy[1] = -200.; xy[2] = .3; xy[3] = 1000.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kCluster, 0)) break; + xy[0] = -.3; xy[1] = -0.5; xy[2] = .3; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kCluster, 1)) break; + return kTRUE; + case kTrackTRD : + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0] = -.3; xy[1] = -500.; xy[2] = .3; xy[3] = 1500.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kTrackTRD , 0)) break; + xy[0] = -.3; xy[1] = -0.5; xy[2] = .3; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kTrackTRD , 1)) break; + return kTRUE; + case 3: // kTrackTRD z + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0] = -1.; xy[1] = -1000.; xy[2] = 1.; xy[3] = 4000.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kTrackTRD , 2)) break; + xy[0] = -1.; xy[1] = -0.5; xy[2] = 1.; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kTrackTRD , 3)) break; + return kTRUE; + case 4: // kTrackTRD phi + xy[0] = -.3; xy[1] = -5.; xy[2] = .3; xy[3] = 50.; + if(GetGraphPlot(&xy[0], kTrackTRD , 4)) return kTRUE; + break; + case 5: // kTrackTPC y + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0] = -.3; xy[1] = -500.; xy[2] = .3; xy[3] = 1500.; + pad = ((TVirtualPad*)l->At(0)); pad->cd(); + pad->SetMargin(0.1, 0.1, 0.1, 0.01); + if(!GetGraphPlot(&xy[0], kTrackTPC, 0)) break; + xy[0] = -.3; xy[1] = -0.5; xy[2] = .3; xy[3] = 2.5; + pad=((TVirtualPad*)l->At(1)); pad->cd(); + pad->SetMargin(0.1, 0.1, 0.1, 0.01); + if(!GetGraphPlot(&xy[0], kTrackTPC, 1)) break; + return kTRUE; + case 6: // kTrackTPC z + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0] = -1.; xy[1] = -1000.; xy[2] = 1.; xy[3] = 4000.; + pad = ((TVirtualPad*)l->At(0)); pad->cd(); + pad->SetMargin(0.1, 0.1, 0.1, 0.01); + if(!GetGraphPlot(&xy[0], kTrackTPC, 2)) break; + xy[0] = -1.; xy[1] = -0.5; xy[2] = 1.; xy[3] = 2.5; + pad = ((TVirtualPad*)l->At(1)); pad->cd(); + pad->SetMargin(0.1, 0.1, 0.1, 0.01); + if(!GetGraphPlot(&xy[0], kTrackTPC, 3)) break; + return kTRUE; + case 7: // kTrackTPC phi + xy[0] = -.3; xy[1] = -5.; xy[2] = .3; xy[3] = 50.; + if(GetGraphPlot(&xy[0], kTrackTPC, 4)) return kTRUE; + break; + case 8: // kMCcluster + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0]=-.3; xy[1]=-50.; xy[2]=.3; xy[3]=650.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kMCcluster, 0)) break; + xy[0] = -.3; xy[1] = -0.5; xy[2] = .3; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kMCcluster, 1)) break; + return kTRUE; + case 9: //kMCtracklet [y] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0]=-.2; xy[1]=-50.; xy[2]=.2; xy[3] =250.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kMCtracklet, 0)) break; + xy[0] = -.2; xy[1] = -0.5; xy[2] = .2; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kMCtracklet, 1)) break; + return kTRUE; + case 10: //kMCtracklet [z] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0]=-1.; xy[1]=-100.; xy[2]=1.; xy[3] =2500.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kMCtracklet, 2)) break; + xy[0] = -1.; xy[1] = -0.5; xy[2] = 1.; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kMCtracklet, 3)) break; + return kTRUE; + case 11: //kMCtracklet [phi] + xy[0]=-.3; xy[1]=-3.; xy[2]=.3; xy[3] =25.; + if(!GetGraphPlot(&xy[0], kMCtracklet, 4)) break; + return kTRUE; + case 12: //kMCtrackTRD [y] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0]=-.2; xy[1]=-50.; xy[2]=.2; xy[3] =200.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTRD, 0)) break; + xy[0] = -.2; xy[1] = -0.5; xy[2] = .2; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTRD, 1)) break; + return kTRUE; + case 13: //kMCtrackTRD [z] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0]=-1.; xy[1]=-700.; xy[2]=1.; xy[3] =1500.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTRD, 2)) break; + xy[0] = -1.; xy[1] = -0.5; xy[2] = 1.; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTRD, 3)) break; + return kTRUE; + case 14: //kMCtrackTRD [phi/snp] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0]=-.2; xy[1]=-0.2; xy[2]=.2; xy[3] =2.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTRD, 4)) break; + xy[0] = -.2; xy[1] = -0.5; xy[2] = .2; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTRD, 5)) break; + return kTRUE; + case 15: //kMCtrackTRD [theta/tgl] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0]=-1.; xy[1]=-0.5; xy[2]=1.; xy[3] =5.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTRD, 6)) break; + xy[0] = -.2; xy[1] = -0.5; xy[2] = .2; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTRD, 7)) break; + return kTRUE; + case 16: //kMCtrackTRD [pt] + xy[0] = 0.; xy[1] = -5.; xy[2] = 12.; xy[3] = 7.; + gPad->Divide(2, 3, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + for(Int_t il=0; ilAt(il); pad->cd(); + pad->SetMargin(0.07, 0.07, 0.1, 0.); + if(!GetGraphTrack(&xy[0], 8, il)) break; + } + return kTRUE; + case 17: //kMCtrackTRD [1/pt] pulls + xy[0] = 0.; xy[1] = -1.5; xy[2] = 2.; xy[3] = 2.; + gPad->Divide(2, 3, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + for(Int_t il=0; ilAt(il); pad->cd(); + pad->SetMargin(0.07, 0.07, 0.1, 0.); + if(!GetGraphTrack(&xy[0], 9, il)) break; + } + return kTRUE; + case 18: //kMCtrackTRD [p] + xy[0] = 0.; xy[1] = -7.5; xy[2] = 12.; xy[3] = 10.5; + gPad->Divide(2, 3, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + for(Int_t il=0; ilAt(il); pad->cd(); + pad->SetMargin(0.07, 0.07, 0.1, 0.); + if(!GetGraphTrack(&xy[0], 10, il)) break; + } + return kTRUE; + case 19: // kMCtrackTPC [y] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0]=-.25; xy[1]=-50.; xy[2]=.25; xy[3] =800.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTPC, 0)) break; + xy[0] = -.25; xy[1] = -0.5; xy[2] = .25; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTPC, 1)) break; + return kTRUE; + case 20: // kMCtrackTPC [z] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0]=-1.; xy[1]=-500.; xy[2]=1.; xy[3] =800.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTPC, 2)) break; + xy[0] = -1.; xy[1] = -0.5; xy[2] = 1.; xy[3] = 2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTPC, 3)) break; + return kTRUE; + case 21: // kMCtrackTPC [phi|snp] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0]=-.25; xy[1]=-0.5; xy[2]=.25; xy[3] =2.5; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTPC, 4)) break; + xy[0] = -.25; xy[1] = -0.5; xy[2] = .25; xy[3] = 1.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTPC, 5)) break; + return kTRUE; + case 22: // kMCtrackTPC [theta|tgl] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0]=-1.; xy[1]=-1.; xy[2]=1.; xy[3] =4.; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTPC, 6)) break; + xy[0] = -1.; xy[1] = -0.5; xy[2] = 1.; xy[3] = 1.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphPlot(&xy[0], kMCtrackTPC, 7)) break; + return kTRUE; + case 23: // kMCtrackTPC [pt] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0] = 0.; xy[1] = -.8; xy[2] = 12.; xy[3] = 2.3; + ((TVirtualPad*)l->At(0))->cd(); + if(!GetGraphTrackTPC(xy, 8)) break; + xy[0]=0.; xy[1]=-0.5; xy[2]=2.; xy[3] =2.5; + ((TVirtualPad*)l->At(1))->cd(); + if(!GetGraphTrackTPC(xy, 9)) break; + return kTRUE; + case 24: // kMCtrackTPC [p] + gPad->Divide(2, 1, 1.e-5, 1.e-5); l=gPad->GetListOfPrimitives(); + xy[0] = 0.; xy[1] = -.8; xy[2] = 12.; xy[3] = 2.3; + pad = ((TVirtualPad*)l->At(0));pad->cd(); + pad->SetMargin(0.12, 0.12, 0.1, 0.04); + if(!GetGraphTrackTPC(xy, 10)) break; + xy[0]=0.; xy[1]=-1.5; xy[2]=12.; xy[3] =2.5; + pad = ((TVirtualPad*)l->At(1)); pad->cd(); + pad->SetMargin(0.12, 0.12, 0.1, 0.04); + if(!GetGraphTrackTPC(xy, 11)) break; + return kTRUE; + case 25: // kMCtrackTOF [z] + return kTRUE; + } + AliWarning(Form("Reference plot [%d] missing result", ifig)); + return kFALSE; +} + + +//________________________________________________________ +Bool_t AliTRDresolution::PostProcess() +{ + //fContainer = dynamic_cast(GetOutputData(0)); + if (!fContainer) { + AliError("ERROR: list not available"); + return kFALSE; + } + TGraph *gm= 0x0, *gs= 0x0; + if(!fGraphS && !fGraphM){ + TObjArray *aM(0x0), *aS(0x0), *a(0x0); + Int_t n = fContainer->GetEntriesFast(); + fGraphS = new TObjArray(n); fGraphS->SetOwner(); + fGraphM = new TObjArray(n); fGraphM->SetOwner(); + for(Int_t ig=0; igAddAt(aM = new TObjArray(fgNElements[ig]), ig); + fGraphS->AddAt(aS = new TObjArray(fgNElements[ig]), ig); + + for(Int_t ic=0; ic=8&&ic<=12)){ // TPC momentum plot + aS->AddAt(a = new TObjArray(AliPID::kSPECIES), ic); + for(Int_t is=AliPID::kSPECIES; is--;){ + a->AddAt(gs = new TGraphErrors(), is); + gs->SetMarkerStyle(23); + gs->SetMarkerColor(is ? kRed : kMagenta); + gs->SetLineStyle(is); + gs->SetLineColor(is ? kRed : kMagenta); + gs->SetLineWidth(is ? 1 : 3); + gs->SetNameTitle(Form("s_%d%02d%d", ig, ic, is), ""); + } + aM->AddAt(a = new TObjArray(AliPID::kSPECIES), ic); + for(Int_t is=AliPID::kSPECIES; is--;){ + a->AddAt(gm = new TGraphErrors(), is); + gm->SetLineColor(is ? kBlack : kBlue); + gm->SetLineStyle(is); + gm->SetMarkerStyle(7); + gm->SetMarkerColor(is ? kBlack : kBlue); + gm->SetLineWidth(is ? 1 : 3); + gm->SetNameTitle(Form("m_%d%02d%d", ig, ic, is), ""); + } + continue; + } else if(ig==kMCtrackTRD&&(ic==8||ic==9||ic==10)){ // TRD momentum plot + TObjArray *aaS, *aaM; + aS->AddAt(aaS = new TObjArray(AliTRDgeometry::kNlayer), ic); + aM->AddAt(aaM = new TObjArray(AliTRDgeometry::kNlayer), ic); + for(Int_t il=AliTRDgeometry::kNlayer; il--;){ + aaS->AddAt(a = new TObjArray(AliPID::kSPECIES), il); + for(Int_t is=AliPID::kSPECIES; is--;){ + a->AddAt(gs = new TGraphErrors(), is); + gs->SetMarkerStyle(23); + gs->SetMarkerColor(is ? kRed : kMagenta); + gs->SetLineStyle(is); + gs->SetLineColor(is ? kRed : kMagenta); + gs->SetLineWidth(is ? 1 : 3); + gs->SetNameTitle(Form("s_%d%02d%d%d", ig, ic, is, il), ""); + } + aaM->AddAt(a = new TObjArray(AliPID::kSPECIES), il); + for(Int_t is=AliPID::kSPECIES; is--;){ + a->AddAt(gm = new TGraphErrors(), is); + gm->SetMarkerStyle(7); + gm->SetMarkerColor(is ? kBlack : kBlue); + gm->SetLineStyle(is); + gm->SetLineColor(is ? kBlack : kBlue); + gm->SetLineWidth(is ? 1 : 3); + gm->SetNameTitle(Form("m_%d%02d%d%d", ig, ic, is, il), ""); + } + } + continue; + } + + aS->AddAt(gs = new TGraphErrors(), ic); + gs->SetMarkerStyle(23); + gs->SetMarkerColor(kRed); + gs->SetLineColor(kRed); + gs->SetNameTitle(Form("s_%d%02d", ig, ic), ""); + + aM->AddAt(gm = ig ? (TGraph*)new TGraphErrors() : (TGraph*)new TGraphAsymmErrors(), ic); + gm->SetLineColor(kBlack); + gm->SetMarkerStyle(7); + gm->SetMarkerColor(kBlack); + gm->SetNameTitle(Form("m_%d%02d", ig, ic), ""); + } + } + } + +/* printf("\n\n\n"); fGraphS->ls(); + printf("\n\n\n"); fGraphM->ls();*/ + + + // DEFINE MODELS + // simple gauss + TF1 fg("fGauss", "gaus", -.5, .5); + // Landau for charge resolution + TF1 fl("fLandau", "landau", 0., 1000.); + + //PROCESS EXPERIMENTAL DISTRIBUTIONS + // Charge resolution + //Process3DL(kCharge, 0, &fl); + // Clusters residuals + Process2D(kCluster, 0, &fg, 1.e4); + Process2D(kCluster, 1, &fg); + fNRefFigures = 1; + // Tracklet residual/pulls + Process2D(kTrackTRD , 0, &fg, 1.e4); + Process2D(kTrackTRD , 1, &fg); + Process2D(kTrackTRD , 2, &fg, 1.e4); + Process2D(kTrackTRD , 3, &fg); + Process2D(kTrackTRD , 4, &fg, 1.e3); + fNRefFigures = 4; + // TPC track residual/pulls + Process2D(kTrackTPC, 0, &fg, 1.e4); + Process2D(kTrackTPC, 1, &fg); + Process2D(kTrackTPC, 2, &fg, 1.e4); + Process2D(kTrackTPC, 3, &fg); + Process2D(kTrackTPC, 4, &fg, 1.e3); + fNRefFigures = 7; + + if(!HasMCdata()) return kTRUE; + + + //PROCESS MC RESIDUAL DISTRIBUTIONS + + // CLUSTER Y RESOLUTION/PULLS + Process2D(kMCcluster, 0, &fg, 1.e4); + Process2D(kMCcluster, 1, &fg); + fNRefFigures = 8; + + // TRACKLET RESOLUTION/PULLS + Process2D(kMCtracklet, 0, &fg, 1.e4); // y + Process2D(kMCtracklet, 1, &fg); // y pulls + Process2D(kMCtracklet, 2, &fg, 1.e4); // z + Process2D(kMCtracklet, 3, &fg); // z pulls + Process2D(kMCtracklet, 4, &fg, 1.e3); // phi + fNRefFigures = 11; + + // TRACK RESOLUTION/PULLS + Process2D(kMCtrackTRD, 0, &fg, 1.e4); // y + Process2D(kMCtrackTRD, 1, &fg); // y PULL + Process2D(kMCtrackTRD, 2, &fg, 1.e4); // z + Process2D(kMCtrackTRD, 3, &fg); // z PULL + Process2D(kMCtrackTRD, 4, &fg, 1.e3); // phi + Process2D(kMCtrackTRD, 5, &fg); // snp PULL + Process2D(kMCtrackTRD, 6, &fg, 1.e3); // theta + Process2D(kMCtrackTRD, 7, &fg); // tgl PULL + Process4D(kMCtrackTRD, 8, &fg, 1.e2); // pt resolution + Process4D(kMCtrackTRD, 9, &fg); // 1/pt pulls + Process4D(kMCtrackTRD, 10, &fg, 1.e2); // p resolution + fNRefFigures = 18; + + // TRACK TPC RESOLUTION/PULLS + Process2D(kMCtrackTPC, 0, &fg, 1.e4);// y resolution + Process2D(kMCtrackTPC, 1, &fg); // y pulls + Process2D(kMCtrackTPC, 2, &fg, 1.e4);// z resolution + Process2D(kMCtrackTPC, 3, &fg); // z pulls + Process2D(kMCtrackTPC, 4, &fg, 1.e3);// phi resolution + Process2D(kMCtrackTPC, 5, &fg); // snp pulls + Process2D(kMCtrackTPC, 6, &fg, 1.e3);// theta resolution + Process2D(kMCtrackTPC, 7, &fg); // tgl pulls + Process3D(kMCtrackTPC, 8, &fg, 1.e2);// pt resolution + Process3D(kMCtrackTPC, 9, &fg); // 1/pt pulls + Process3D(kMCtrackTPC, 10, &fg, 1.e2);// p resolution + Process3D(kMCtrackTPC, 11, &fg); // p pulls + fNRefFigures = 24; + + // TRACK HMPID RESOLUTION/PULLS + Process2D(kMCtrackTOF, 0, &fg, 1.e4); // z towards TOF + Process2D(kMCtrackTOF, 1, &fg); // z towards TOF + fNRefFigures = 25; + + return kTRUE; +} + + +//________________________________________________________ +void AliTRDresolution::Terminate(Option_t *opt) +{ + AliTRDrecoTask::Terminate(opt); + if(HasPostProcess()) PostProcess(); +} + +//________________________________________________________ +void AliTRDresolution::AdjustF1(TH1 *h, TF1 *f) +{ +// Helper function to avoid duplication of code +// Make first guesses on the fit parameters + + // find the intial parameters of the fit !! (thanks George) + Int_t nbinsy = Int_t(.5*h->GetNbinsX()); + Double_t sum = 0.; + for(Int_t jbin=nbinsy-4; jbin<=nbinsy+4; jbin++) sum+=h->GetBinContent(jbin); sum/=9.; + f->SetParLimits(0, 0., 3.*sum); + f->SetParameter(0, .9*sum); + Double_t rms = h->GetRMS(); + f->SetParLimits(1, -rms, rms); + f->SetParameter(1, h->GetMean()); + + f->SetParLimits(2, 0., 2.*rms); + f->SetParameter(2, rms); + if(f->GetNpar() <= 4) return; + + f->SetParLimits(3, 0., sum); + f->SetParameter(3, .1*sum); + + f->SetParLimits(4, -.3, .3); + f->SetParameter(4, 0.); + + f->SetParLimits(5, 0., 1.e2); + f->SetParameter(5, 2.e-1); +} + +//________________________________________________________ +TObjArray* AliTRDresolution::Histos() +{ + // + // Define histograms + // + + if(fContainer) return fContainer; + + fContainer = new TObjArray(kNhistos); + //fContainer->SetOwner(kTRUE); + TH1 *h = 0x0; + TObjArray *arr = 0x0; + + // cluster to track residuals/pulls + fContainer->AddAt(arr = new TObjArray(fgNElements[kCharge]), kCharge); + arr->SetName("Charge"); + if(!(h = (TH3S*)gROOT->FindObject("hCharge"))){ + h = new TH3S("hCharge", "Charge Resolution", 20, 1., 2., 24, 0., 3.6, 100, 0., 500.); + h->GetXaxis()->SetTitle("dx/dx_{0}"); + h->GetYaxis()->SetTitle("x_{d} [cm]"); + h->GetZaxis()->SetTitle("dq/dx [ADC/cm]"); + } else h->Reset(); + arr->AddAt(h, 0); + + // cluster to track residuals/pulls + fContainer->AddAt(arr = new TObjArray(fgNElements[kCluster]), kCluster); + arr->SetName("Cl"); + if(!(h = (TH2I*)gROOT->FindObject("hCl"))){ + h = new TH2I("hCl", "Cluster Residuals", 21, -.33, .33, 100, -.5, .5); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 0); + if(!(h = (TH2I*)gROOT->FindObject("hClpull"))){ + h = new TH2I("hClpull", "Cluster Pulls", 21, -.33, .33, 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y/#sigma_{y}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 1); + + // tracklet to track residuals/pulls in y direction + fContainer->AddAt(arr = new TObjArray(fgNElements[kTrackTRD ]), kTrackTRD ); + arr->SetName("Trklt"); + if(!(h = (TH2I*)gROOT->FindObject("hTrkltY"))){ + h = new TH2I("hTrkltY", "Tracklet Y Residuals", 21, -.33, .33, 100, -.5, .5); + h->GetXaxis()->SetTitle("#tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 0); + if(!(h = (TH2I*)gROOT->FindObject("hTrkltYpull"))){ + h = new TH2I("hTrkltYpull", "Tracklet Y Pulls", 21, -.33, .33, 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("#tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y/#sigma_{y}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 1); + // tracklet to track residuals/pulls in z direction + if(!(h = (TH2I*)gROOT->FindObject("hTrkltZ"))){ + h = new TH2I("hTrkltZ", "Tracklet Z Residuals", 50, -1., 1., 100, -1.5, 1.5); + h->GetXaxis()->SetTitle("#tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 2); + if(!(h = (TH2I*)gROOT->FindObject("hTrkltZpull"))){ + h = new TH2I("hTrkltZpull", "Tracklet Z Pulls", 50, -1., 1., 100, -5.5, 5.5); + h->GetXaxis()->SetTitle("#tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z/#sigma_{z}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 3); + // tracklet to track phi residuals + if(!(h = (TH2I*)gROOT->FindObject("hTrkltPhi"))){ + h = new TH2I("hTrkltPhi", "Tracklet #phi Residuals", 21, -.33, .33, 100, -.5, .5); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta phi [rad]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 4); + + + // tracklet to TPC track residuals/pulls in y direction + fContainer->AddAt(arr = new TObjArray(fgNElements[kTrackTPC]), kTrackTPC); + arr->SetName("TrkTPC"); + if(!(h = (TH2I*)gROOT->FindObject("hTrkTPCY"))){ + h = new TH2I("hTrkTPCY", "Track[TPC] Y Residuals", 21, -.33, .33, 100, -.5, .5); + h->GetXaxis()->SetTitle("#tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 0); + if(!(h = (TH2I*)gROOT->FindObject("hTrkTPCYpull"))){ + h = new TH2I("hTrkTPCYpull", "Track[TPC] Y Pulls", 21, -.33, .33, 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("#tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y/#sigma_{y}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 1); + // tracklet to TPC track residuals/pulls in z direction + if(!(h = (TH2I*)gROOT->FindObject("hTrkTPCZ"))){ + h = new TH2I("hTrkTPCZ", "Track[TPC] Z Residuals", 50, -1., 1., 100, -1.5, 1.5); + h->GetXaxis()->SetTitle("#tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 2); + if(!(h = (TH2I*)gROOT->FindObject("hTrkTPCZpull"))){ + h = new TH2I("hTrkTPCZpull", "Track[TPC] Z Pulls", 50, -1., 1., 100, -5.5, 5.5); + h->GetXaxis()->SetTitle("#tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z/#sigma_{z}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 3); + // tracklet to TPC track phi residuals + if(!(h = (TH2I*)gROOT->FindObject("hTrkTPCPhi"))){ + h = new TH2I("hTrkTPCPhi", "Track[TPC] #phi Residuals", 21, -.33, .33, 100, -.5, .5); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta phi [rad]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 4); + + + // Resolution histos + if(!HasMCdata()) return fContainer; + + // cluster y resolution [0] + fContainer->AddAt(arr = new TObjArray(fgNElements[kMCcluster]), kMCcluster); + arr->SetName("McCl"); + if(!(h = (TH2I*)gROOT->FindObject("hMcCl"))){ + h = new TH2I("hMcCl", "Cluster Resolution", 48, -.48, .48, 100, -.3, .3); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 0); + if(!(h = (TH2I*)gROOT->FindObject("hMcClPull"))){ + h = new TH2I("hMcClPull", "Cluster Pulls", 48, -.48, .48, 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Deltay/#sigma_{y}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 1); + + + // TRACKLET RESOLUTION + fContainer->AddAt(arr = new TObjArray(fgNElements[kMCtracklet]), kMCtracklet); + arr->SetName("McTrklt"); + // tracklet y resolution + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkltY"))){ + h = new TH2I("hMcTrkltY", "Tracklet Resolution (Y)", 48, -.48, .48, 100, -.2, .2); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 0); + // tracklet y pulls + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkltYPull"))){ + h = new TH2I("hMcTrkltYPull", "Tracklet Pulls (Y)", 48, -.48, .48, 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y / #sigma_{y}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 1); + // tracklet z resolution + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkltZ"))){ + h = new TH2I("hMcTrkltZ", "Tracklet Resolution (Z)", 100, -1., 1., 100, -1., 1.); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 2); + // tracklet z pulls + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkltZPull"))){ + h = new TH2I("hMcTrkltZPull", "Tracklet Pulls (Z)", 100, -1., 1., 100, -3.5, 3.5); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z / #sigma_{z}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 3); + // tracklet phi resolution + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkltPhi"))){ + h = new TH2I("hMcTrkltPhi", "Tracklet Resolution (#Phi)", 48, -.48, .48, 100, -.15, .15); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta #phi [rad]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 4); + + + // KALMAN TRACK RESOLUTION + fContainer->AddAt(arr = new TObjArray(fgNElements[kMCtrackTRD]), kMCtrackTRD); + arr->SetName("McTrkTRD"); + // Kalman track y resolution + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkY"))){ + h = new TH2I("hMcTrkY", "Track Y Resolution", 48, -.48, .48, 100, -.2, .2); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 0); + // Kalman track y pulls + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkYPull"))){ + h = new TH2I("hMcTrkYPull", "Track Y Pulls", 48, -.48, .48, 100, -4., 4.); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y / #sigma_{y}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 1); + // Kalman track Z + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkZ"))){ + h = new TH2I("hMcTrkZ", "Track Z Resolution", 100, -1., 1., 100, -1., 1.); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 2); + // Kalman track Z pulls + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkZPull"))){ + h = new TH2I("hMcTrkZPull", "Track Z Pulls", 100, -1., 1., 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z / #sigma_{z}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 3); + // Kalman track SNP + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkSNP"))){ + h = new TH2I("hMcTrkSNP", "Track Phi Resolution", 60, -.3, .3, 100, -5e-3, 5e-3); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta #phi [rad]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 4); + // Kalman track SNP pulls + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkSNPPull"))){ + h = new TH2I("hMcTrkSNPPull", "Track SNP Pulls", 60, -.3, .3, 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta(sin(#phi)) / #sigma_{sin(#phi)}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 5); + // Kalman track TGL + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTGL"))){ + h = new TH2I("hMcTrkTGL", "Track Theta Resolution", 100, -1., 1., 100, -5e-3, 5e-3); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta#theta [rad]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 6); + // Kalman track TGL pulls + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTGLPull"))){ + h = new TH2I("hMcTrkTGLPull", "Track TGL Pulls", 100, -1., 1., 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta(tg(#theta)) / #sigma_{tg(#theta)}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 7); + // Kalman track Pt resolution + const Int_t n = AliPID::kSPECIES; + TObjArray *arr2 = 0x0; TH3S* h3=0x0; + arr->AddAt(arr2 = new TObjArray(AliTRDgeometry::kNlayer), 8); + arr2->SetName("Track Pt Resolution"); + for(Int_t il=0; ilFindObject(Form("hMcTrkPt%d", il)))){ + h3 = new TH3S(Form("hMcTrkPt%d", il), "Track Pt Resolution", 40, 0., 20., 150, -.1, .2, n, -.5, n-.5); + h3->GetXaxis()->SetTitle("p_{t} [GeV/c]"); + h3->GetYaxis()->SetTitle("#Delta p_{t}/p_{t}^{MC}"); + h3->GetZaxis()->SetTitle("SPECIES"); + } else h3->Reset(); + arr2->AddAt(h3, il); + } + // Kalman track Pt pulls + arr->AddAt(arr2 = new TObjArray(AliTRDgeometry::kNlayer), 9); + arr2->SetName("Track 1/Pt Pulls"); + for(Int_t il=0; ilFindObject(Form("hMcTrkPtPulls%d", il)))){ + h3 = new TH3S(Form("hMcTrkPtPulls%d", il), "Track 1/Pt Pulls", 40, 0., 2., 100, -4., 4., n, -.5, n-.5); + h3->GetXaxis()->SetTitle("1/p_{t}^{MC} [c/GeV]"); + h3->GetYaxis()->SetTitle("#Delta(1/p_{t})/#sigma(1/p_{t}) "); + h3->GetZaxis()->SetTitle("SPECIES"); + } else h3->Reset(); + arr2->AddAt(h3, il); + } + // Kalman track P resolution + arr->AddAt(arr2 = new TObjArray(AliTRDgeometry::kNlayer), 10); + arr2->SetName("Track P Resolution [PID]"); + for(Int_t il=0; ilFindObject(Form("hMcTrkP%d", il)))){ + h3 = new TH3S(Form("hMcTrkP%d", il), "Track P Resolution", 40, 0., 20., 150, -.15, .35, n, -.5, n-.5); + h3->GetXaxis()->SetTitle("p [GeV/c]"); + h3->GetYaxis()->SetTitle("#Delta p/p^{MC}"); + h3->GetZaxis()->SetTitle("SPECIES"); + } else h3->Reset(); + arr2->AddAt(h3, il); + } + + // TPC TRACK RESOLUTION + fContainer->AddAt(arr = new TObjArray(fgNElements[kMCtrackTPC]), kMCtrackTPC); + arr->SetName("McTrkTPC"); + // Kalman track Y + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTPCY"))){ + h = new TH2I("hMcTrkTPCY", "Track[TPC] Y Resolution", 60, -.3, .3, 100, -.5, .5); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 0); + // Kalman track Y pulls + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTPCYPull"))){ + h = new TH2I("hMcTrkTPCYPull", "Track[TPC] Y Pulls", 60, -.3, .3, 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta y / #sigma_{y}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 1); + // Kalman track Z + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTPCZ"))){ + h = new TH2I("hMcTrkTPCZ", "Track[TPC] Z Resolution", 100, -1., 1., 100, -1., 1.); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 2); + // Kalman track Z pulls + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTPCZPull"))){ + h = new TH2I("hMcTrkTPCZPull", "Track[TPC] Z Pulls", 100, -1., 1., 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z / #sigma_{z}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 3); + // Kalman track SNP + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTPCSNP"))){ + h = new TH2I("hMcTrkTPCSNP", "Track[TPC] Phi Resolution", 60, -.3, .3, 100, -5e-3, 5e-3); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta #phi [rad]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 4); + // Kalman track SNP pulls + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTPCSNPPull"))){ + h = new TH2I("hMcTrkTPCSNPPull", "Track[TPC] SNP Pulls", 60, -.3, .3, 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("tg(#phi)"); + h->GetYaxis()->SetTitle("#Delta(sin(#phi)) / #sigma_{sin(#phi)}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 5); + // Kalman track TGL + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTPCTGL"))){ + h = new TH2I("hMcTrkTPCTGL", "Track[TPC] Theta Resolution", 100, -1., 1., 100, -5e-3, 5e-3); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta#theta [rad]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 6); + // Kalman track TGL pulls + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTPCTGLPull"))){ + h = new TH2I("hMcTrkTPCTGLPull", "Track[TPC] TGL Pulls", 100, -1., 1., 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta(tg(#theta)) / #sigma_{tg(#theta)}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 7); + // Kalman track Pt resolution + if(!(h3 = (TH3S*)gROOT->FindObject("hMcTrkTPCPt"))){ + h3 = new TH3S("hMcTrkTPCPt", "Track[TPC] Pt Resolution", 80, 0., 20., 150, -.1, .2, n, -.5, n-.5); + h3->GetXaxis()->SetTitle("p_{t} [GeV/c]"); + h3->GetYaxis()->SetTitle("#Delta p_{t}/p_{t}^{MC}"); + h3->GetZaxis()->SetTitle("SPECIES"); + } else h3->Reset(); + arr->AddAt(h3, 8); + // Kalman track Pt pulls + if(!(h3 = (TH3S*)gROOT->FindObject("hMcTrkTPCPtPulls"))){ + h3 = new TH3S("hMcTrkTPCPtPulls", "Track[TPC] 1/Pt Pulls", 80, 0., 2., 100, -4., 4., n, -.5, n-.5); + h3->GetXaxis()->SetTitle("1/p_{t}^{MC} [c/GeV]"); + h3->GetYaxis()->SetTitle("#Delta(1/p_{t})/#sigma(1/p_{t}) "); + h3->GetZaxis()->SetTitle("SPECIES"); + } else h3->Reset(); + arr->AddAt(h3, 9); + // Kalman track P resolution + if(!(h3 = (TH3S*)gROOT->FindObject("hMcTrkTPCP"))){ + h3 = new TH3S("hMcTrkTPCP", "Track[TPC] P Resolution", 80, 0., 20., 150, -.15, .35, n, -.5, n-.5); + h3->GetXaxis()->SetTitle("p [GeV/c]"); + h3->GetYaxis()->SetTitle("#Delta p/p^{MC}"); + h3->GetZaxis()->SetTitle("SPECIES"); + } else h3->Reset(); + arr->AddAt(h3, 10); + // Kalman track Pt pulls + if(!(h3 = (TH3S*)gROOT->FindObject("hMcTrkTPCPPulls"))){ + h3 = new TH3S("hMcTrkTPCPPulls", "Track[TPC] P Pulls", 80, 0., 20., 100, -5., 5., n, -.5, n-.5); + h3->GetXaxis()->SetTitle("p^{MC} [GeV/c]"); + h3->GetYaxis()->SetTitle("#Deltap/#sigma_{p}"); + h3->GetZaxis()->SetTitle("SPECIES"); + } else h3->Reset(); + arr->AddAt(h3, 11); + + + + // Kalman track Z resolution [TOF] + fContainer->AddAt(arr = new TObjArray(fgNElements[kMCtrackTOF]), kMCtrackTOF); + arr->SetName("McTrkTOF"); + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTOFZ"))){ + h = new TH2I("hMcTrkTOFZ", "Track[TOF] Z Resolution", 100, -1., 1., 100, -1., 1.); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z [cm]"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 0); + // Kalman track Z pulls + if(!(h = (TH2I*)gROOT->FindObject("hMcTrkTOFZPull"))){ + h = new TH2I("hMcTrkTOFZPull", "Track[TOF] Z Pulls", 100, -1., 1., 100, -4.5, 4.5); + h->GetXaxis()->SetTitle("tg(#theta)"); + h->GetYaxis()->SetTitle("#Delta z / #sigma_{z}"); + h->GetZaxis()->SetTitle("entries"); + } else h->Reset(); + arr->AddAt(h, 1); + + return fContainer; +} + +//________________________________________________________ +Bool_t AliTRDresolution::Process(TH2 * const h2, TF1 *f, Float_t k, TGraphErrors **g) +{ + // + // Do the processing + // + + Char_t pn[10]; sprintf(pn, "p%02d", fIdxPlot); + Int_t n = 0; + if((n=g[0]->GetN())) for(;n--;) g[0]->RemovePoint(n); + if((n=g[1]->GetN())) for(;n--;) g[1]->RemovePoint(n); + + for(Int_t ibin = 1; ibin <= h2->GetNbinsX(); ibin++){ + Double_t x = h2->GetXaxis()->GetBinCenter(ibin); + TH1D *h = h2->ProjectionY(pn, ibin, ibin); + if(h->GetEntries()<100) continue; + //AdjustF1(h, f); + + h->Fit(f, "QN"); + + Int_t ip = g[0]->GetN(); + g[0]->SetPoint(ip, x, k*f->GetParameter(1)); + g[0]->SetPointError(ip, 0., k*f->GetParError(1)); + g[1]->SetPoint(ip, x, k*f->GetParameter(2)); + g[1]->SetPointError(ip, 0., k*f->GetParError(2)); + +/* + g[0]->SetPoint(ip, x, k*h->GetMean()); + g[0]->SetPointError(ip, 0., k*h->GetMeanError()); + g[1]->SetPoint(ip, x, k*h->GetRMS()); + g[1]->SetPointError(ip, 0., k*h->GetRMSError());*/ + } + fIdxPlot++; + return kTRUE; +} + +//________________________________________________________ +Bool_t AliTRDresolution::Process2D(ETRDresolutionPlot plot, Int_t idx, TF1 *f, Float_t k) +{ + // + // Do the processing + // + + if(!fContainer || !fGraphS || !fGraphM) return kFALSE; + + // retrive containers + TH2I *h2 = idx<0 ? (TH2I*)(fContainer->At(plot)) : (TH2I*)((TObjArray*)(fContainer->At(plot)))->At(idx); + if(!h2) return kFALSE; + TGraphErrors *g[2]; + if(!(g[0] = idx<0 ? (TGraphErrors*)fGraphM->At(plot) : (TGraphErrors*)((TObjArray*)(fGraphM->At(plot)))->At(idx))) return kFALSE; + + if(!(g[1] = idx<0 ? (TGraphErrors*)fGraphS->At(plot) : (TGraphErrors*)((TObjArray*)(fGraphS->At(plot)))->At(idx))) return kFALSE; + + return Process(h2, f, k, g); +} + +//________________________________________________________ +Bool_t AliTRDresolution::Process3D(ETRDresolutionPlot plot, Int_t idx, TF1 *f, Float_t k) +{ + // + // Do the processing + // + + if(!fContainer || !fGraphS || !fGraphM) return kFALSE; + + // retrive containers + TH3S *h3 = idx<0 ? (TH3S*)(fContainer->At(plot)) : (TH3S*)((TObjArray*)(fContainer->At(plot)))->At(idx); + if(!h3) return kFALSE; + + TObjArray *gm, *gs; + if(!(gm = (TObjArray*)((TObjArray*)(fGraphM->At(plot)))->At(idx))) return kFALSE; + if(!(gs = (TObjArray*)((TObjArray*)(fGraphS->At(plot)))->At(idx))) return kFALSE; + TGraphErrors *g[2]; + + TAxis *az = h3->GetZaxis(); + for(Int_t iz=1; iz<=az->GetNbins(); iz++){ + if(!(g[0] = (TGraphErrors*)gm->At(iz-1))) return kFALSE; + if(!(g[1] = (TGraphErrors*)gs->At(iz-1))) return kFALSE; + az->SetRange(iz, iz); + if(!Process((TH2*)h3->Project3D("yx"), f, k, g)) return kFALSE; + } + + return kTRUE; +} + +//________________________________________________________ +Bool_t AliTRDresolution::Process3DL(ETRDresolutionPlot plot, Int_t idx, TF1 *f, Float_t k) +{ + // + // Do the processing + // + + if(!fContainer || !fGraphS || !fGraphM) return kFALSE; + + // retrive containers + TH3S *h3 = (TH3S*)((TObjArray*)fContainer->At(plot))->At(idx); + if(!h3) return kFALSE; + + TGraphAsymmErrors *gm; + TGraphErrors *gs; + if(!(gm = (TGraphAsymmErrors*)((TObjArray*)fGraphM->At(plot))->At(0))) return kFALSE; + if(!(gs = (TGraphErrors*)((TObjArray*)fGraphS->At(plot)))) return kFALSE; + + Float_t x, r, mpv, xM, xm; + TAxis *ay = h3->GetYaxis(); + for(Int_t iy=1; iy<=h3->GetNbinsY(); iy++){ + ay->SetRange(iy, iy); + x = ay->GetBinCenter(iy); + TH2F *h2=(TH2F*)h3->Project3D("zx"); + TAxis *ax = h2->GetXaxis(); + for(Int_t ix=1; ix<=h2->GetNbinsX(); ix++){ + r = ax->GetBinCenter(ix); + TH1D *h1 = h2->ProjectionY("py", ix, ix); + if(h1->Integral()<50) continue; + h1->Fit(f, "QN"); + + GetLandauMpvFwhm(f, mpv, xm, xM); + Int_t ip = gm->GetN(); + gm->SetPoint(ip, x, k*mpv); + gm->SetPointError(ip, 0., 0., k*xm, k*xM); + gs->SetPoint(ip, r, k*(xM-xm)/mpv); + gs->SetPointError(ip, 0., 0.); + } + } + + return kTRUE; +} + +//________________________________________________________ +Bool_t AliTRDresolution::Process4D(ETRDresolutionPlot plot, Int_t idx, TF1 *f, Float_t k) +{ + // + // Do the processing + // + + if(!fContainer || !fGraphS || !fGraphM) return kFALSE; + + // retrive containers + TObjArray *arr = (TObjArray*)((TObjArray*)(fContainer->At(plot)))->At(idx); + if(!arr) return kFALSE; + + + TObjArray *gm[2], *gs[2]; + if(!(gm[0] = (TObjArray*)((TObjArray*)(fGraphM->At(plot)))->At(idx))) return kFALSE; + if(!(gs[0] = (TObjArray*)((TObjArray*)(fGraphS->At(plot)))->At(idx))) return kFALSE; + + TGraphErrors *g[2]; + + TH3S *h3 = 0x0; + for(Int_t ix=0; ixGetEntriesFast(); ix++){ + if(!(h3 = (TH3S*)arr->At(ix))) return kFALSE; + if(!(gm[1] = (TObjArray*)gm[0]->At(ix))) return kFALSE; + if(!(gs[1] = (TObjArray*)gs[0]->At(ix))) return kFALSE; + TAxis *az = h3->GetZaxis(); + for(Int_t iz=1; iz<=az->GetNbins(); iz++){ + if(!(g[0] = (TGraphErrors*)gm[1]->At(iz-1))) return kFALSE; + if(!(g[1] = (TGraphErrors*)gs[1]->At(iz-1))) return kFALSE; + az->SetRange(iz, iz); + if(!Process((TH2*)h3->Project3D("yx"), f, k, g)) return kFALSE; + } + } + + return kTRUE; +} + +//________________________________________________________ +Bool_t AliTRDresolution::GetGraphPlot(Float_t *bb, ETRDresolutionPlot ip, Int_t idx) +{ + // + // Get the graphs + // + + if(!fGraphS || !fGraphM) return kFALSE; + TGraphErrors *gm = idx<0 ? (TGraphErrors*)fGraphM->At(ip) : (TGraphErrors*)((TObjArray*)(fGraphM->At(ip)))->At(idx); + if(!gm) return kFALSE; + TGraphErrors *gs = idx<0 ? (TGraphErrors*)fGraphS->At(ip) : (TGraphErrors*)((TObjArray*)(fGraphS->At(ip)))->At(idx); + if(!gs) return kFALSE; + gs->Draw("apl"); gm->Draw("pl"); + + // titles look up + Int_t nref = 0; + for(Int_t jp=0; jp<(Int_t)ip; jp++) nref+=fgNElements[jp]; + UChar_t jdx = idx<0?0:idx; + for(Int_t jc=0; jcGetN())) { + PutTrendValue(Form("%s_%s", fgPerformanceName[ip], at[0]), gm->GetMean(2)); + PutTrendValue(Form("%s_%sRMS", fgPerformanceName[ip], at[0]), gm->GetRMS(2)); + } + + if((n=gs->GetN())){ + gs->Sort(&TGraph::CompareY); + PutTrendValue(Form("%s_%sSigMin", fgPerformanceName[ip], at[0]), gs->GetY()[0]); + PutTrendValue(Form("%s_%sSigMax", fgPerformanceName[ip], at[0]), gs->GetY()[n-1]); + gs->Sort(&TGraph::CompareX); + } + + // axis range + TAxis *ax = 0x0; + ax = gs->GetHistogram()->GetXaxis(); + ax->SetRangeUser(bb[0], bb[2]); + ax->SetTitle(at[1]);ax->CenterTitle(); + + ax = gs->GetHistogram()->GetYaxis(); + ax->SetRangeUser(bb[1], bb[3]); + ax->SetTitleOffset(1.1); + ax->SetTitle(at[2]);ax->CenterTitle(); + + TGaxis *gax = 0x0; + gax = new TGaxis(bb[2], bb[1], bb[2], bb[3], bb[1], bb[3], 510, "+U"); + gax->SetLineColor(kRed);gax->SetLineWidth(2);gax->SetTextColor(kRed); + //gax->SetVertical(); + gax->CenterTitle(); gax->SetTitleOffset(.7); + gax->SetTitle(at[3]); gax->Draw(); + + // bounding box + TBox *b = new TBox(-.15, bb[1], .15, bb[3]); + b->SetFillStyle(3002);b->SetLineColor(0); + b->SetFillColor(ip<=Int_t(kMCcluster)?kGreen:kBlue); + b->Draw(); + return kTRUE; +} + + +//________________________________________________________ +Bool_t AliTRDresolution::GetGraphTrack(Float_t *bb, Int_t idx, Int_t il) +{ + // + // Get the graphs + // + + if(!fGraphS || !fGraphM) return kFALSE; + + // axis titles look up + Int_t nref = 0; + for(Int_t jp=0; jpAt(kMCtrackTRD); a0 = a1; + a1 = (TObjArray*)a0->At(idx); a0 = a1; + a1 = (TObjArray*)a0->At(il); a0 = a1; + for(Int_t is=0; isAt(is))) return kFALSE; + if(!gs->GetN()) continue; + gs->Draw(is ? "pl" : "apl"); + gs->Sort(&TGraph::CompareY); Int_t n = gs->GetN(); + PutTrendValue(Form("%s_%sSigMin%s", fgPerformanceName[kMCtrackTRD], at[0], AliPID::ParticleShortName(is)), gs->GetY()[0]); + PutTrendValue(Form("%s_%sSigMax%s", fgPerformanceName[kMCtrackTRD], at[0], AliPID::ParticleShortName(is)), gs->GetY()[n-1]); + gs->Sort(&TGraph::CompareX); + } + gs = (TGraphErrors*)a0->At(0); + + // axis range + TAxis *ax = gs->GetHistogram()->GetXaxis(); + ax->SetRangeUser(bb[0], bb[2]); + ax->SetTitle(at[1]);ax->CenterTitle(); + + ax = gs->GetHistogram()->GetYaxis(); + ax->SetRangeUser(bb[1], bb[3]); + ax->SetTitleOffset(.5);ax->SetTitleSize(.06); + ax->SetTitle(at[2]);ax->CenterTitle(); + + TGaxis *gax = 0x0; + gax = new TGaxis(bb[2], bb[1], bb[2], bb[3], bb[1], bb[3], 510, "+U"); + gax->SetLineColor(kRed);gax->SetLineWidth(2);gax->SetTextColor(kRed); + //gax->SetVertical(); + gax->CenterTitle(); gax->SetTitleOffset(.5);gax->SetTitleSize(.06); + gax->SetTitle(at[3]); gax->Draw(); + + + a0 = fGraphM; + a1 = (TObjArray*)a0->At(kMCtrackTRD); a0 = a1; + a1 = (TObjArray*)a0->At(idx); a0 = a1; + a1 = (TObjArray*)a0->At(il); a0 = a1; + for(Int_t is=0; isAt(is))) return kFALSE; + if(!gm->GetN()) continue; + gm->Draw("pl"); + PutTrendValue(Form("%s_%s_%s", fgPerformanceName[kMCtrackTRD], at[0], AliPID::ParticleShortName(is)), gm->GetMean(2)); + PutTrendValue(Form("%s_%s_%sRMS", fgPerformanceName[kMCtrackTRD], at[0], AliPID::ParticleShortName(is)), gm->GetRMS(2)); + } + + return kTRUE; +} + + +//________________________________________________________ +Bool_t AliTRDresolution::GetGraphTrackTPC(Float_t *bb, Int_t sel) +{ + // + // Get the graphs + // + + if(!fGraphS || !fGraphM) return kFALSE; + + // axis titles look up + Int_t nref = 0; + for(Int_t jp=0; jpAt(kMCtrackTPC); a0 = a1; + a1 = (TObjArray*)a0->At(sel); a0 = a1; + for(Int_t is=0; isAt(is))) return kFALSE; + if(!gs->GetN()) continue; + gs->Draw(is ? "pl" : "apl"); + gs->Sort(&TGraph::CompareY); Int_t n = gs->GetN(); + PutTrendValue(Form("%s_%sSigMin%s", fgPerformanceName[kMCtrackTPC], at[0], AliPID::ParticleShortName(is)), gs->GetY()[0]); + PutTrendValue(Form("%s_%sSigMax%s", fgPerformanceName[kMCtrackTPC], at[0], AliPID::ParticleShortName(is)), gs->GetY()[n-1]); + gs->Sort(&TGraph::CompareX); + } + gs = (TGraphErrors*)a0->At(0); + // axis range + TAxis *ax = gs->GetHistogram()->GetXaxis(); + ax->SetRangeUser(bb[0], bb[2]); + ax->SetTitle(at[1]);ax->CenterTitle(); + + ax = gs->GetHistogram()->GetYaxis(); + ax->SetRangeUser(bb[1], bb[3]); + ax->SetTitleOffset(1.);ax->SetTitleSize(0.05); + ax->SetTitle(at[2]);ax->CenterTitle(); + + TGaxis *gax = 0x0; + gax = new TGaxis(bb[2], bb[1], bb[2], bb[3], bb[1], bb[3], 510, "+U"); + gax->SetLineColor(kRed);gax->SetLineWidth(2);gax->SetTextColor(kRed); + //gax->SetVertical(); + gax->CenterTitle(); gax->SetTitleOffset(.7);gax->SetTitleSize(0.05); + gax->SetTitle(at[3]); gax->Draw(); + + + a0 = fGraphM; + a1 = (TObjArray*)a0->At(kMCtrackTPC); a0 = a1; + a1 = (TObjArray*)a0->At(sel); a0 = a1; + for(Int_t is=0; isAt(is))) return kFALSE; + if(!gm->GetN()) continue; + gm->Draw("pl"); + PutTrendValue(Form("%s_%s_%s", fgPerformanceName[kMCtrackTPC], at[0], AliPID::ParticleShortName(is)), gm->GetMean(2)); + PutTrendValue(Form("%s_%s_%sRMS", fgPerformanceName[kMCtrackTPC], at[0], AliPID::ParticleShortName(is)), gm->GetRMS(2)); + } + + return kTRUE; +} + +//________________________________________________________ +void AliTRDresolution::GetLandauMpvFwhm(TF1 * const f, Float_t &mpv, Float_t &xm, Float_t &xM) +{ + // + // Get the most probable value and the full width half mean + // of a Landau distribution + // + + const Float_t dx = 1.; + mpv = f->GetParameter(1); + Float_t fx, max = f->Eval(mpv); + + xm = mpv - dx; + while((fx = f->Eval(xm))>.5*max){ + if(fx>max){ + max = fx; + mpv = xm; + } + xm -= dx; + } + + xM += 2*(mpv - xm); + while((fx = f->Eval(xM))>.5*max) xM += dx; +} + + +//________________________________________________________ +void AliTRDresolution::SetRecoParam(AliTRDrecoParam *r) +{ + + fReconstructor->SetRecoParam(r); +} diff --git a/PWG1/TRD/AliTRDresolution.h b/PWG1/TRD/AliTRDresolution.h new file mode 100644 index 00000000000..9830f89020e --- /dev/null +++ b/PWG1/TRD/AliTRDresolution.h @@ -0,0 +1,108 @@ +#ifndef ALITRDRESOLUTION_H +#define ALITRDRESOLUTION_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/* $Id: AliTRDresolution.h 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// TRD Resolution performance // +// // +// Authors: // +// Alexandru Bercuci // +// Markus Fasel // +// // +//////////////////////////////////////////////////////////////////////////// + +#ifndef ALITRDRECOTASK_H +#include "AliTRDrecoTask.h" +#endif + +class TH1; +class TH2; +class TF1; +class TGraphErrors; +class TObjArray; +class AliTRDReconstructor; +class AliTRDgeometry; +class AliTRDrecoParam; +class AliTRDseedV1; +class AliTRDtrackInfo; +class AliTRDresolution : public AliTRDrecoTask +{ +public: + enum ETRDresolutionPlot { + kCharge = 0 // charge resolution + ,kCluster = 1 // cluster - track + ,kTrackTRD = 2 // tracklet - track residuals/pulls + ,kTrackTPC = 3 // tracklet - track residuals/pulls at lower TRD entrance + ,kMCcluster = 4 // cluster-mc resolution/pulls + ,kMCtracklet = 5 // tracklet-mc resolution/pulls + ,kMCtrackTPC = 6 // TPC track monitor + ,kMCtrackTOF = 7 // TOF/HMPID track monitor + ,kMCtrackTRD = 8 // TRD track monitor + ,kNhistos = 9 + }; + enum ETRDresolutionSteer { + kVerbose = 0 + ,kVisual = 1 + }; + + AliTRDresolution(); + virtual ~AliTRDresolution(); + + void CreateOutputObjects(); + Bool_t GetRefFigure(Int_t ifig); + TObjArray* Histos(); + TObjArray* Results(Int_t i=0) const {return i ? fGraphS : fGraphM;} + void Exec(Option_t * opt); + Bool_t IsVerbose() const {return TESTBIT(fStatus, kVerbose);} + Bool_t IsVisual() const {return TESTBIT(fStatus, kVisual);} + Bool_t PostProcess(); + + TH1* PlotCharge(const AliTRDtrackV1 *t=0x0); + TH1* PlotCluster(const AliTRDtrackV1 *t=0x0); + TH1* PlotTracklet(const AliTRDtrackV1 *t=0x0); + TH1* PlotTrackTPC(const AliTRDtrackV1 *t=0x0); + TH1* PlotMC(const AliTRDtrackV1 *t=0x0); + + void SetRecoParam(AliTRDrecoParam *r); + void SetVerbose(Bool_t v = kTRUE) {v ? SETBIT(fStatus ,kVerbose): CLRBIT(fStatus ,kVerbose);} + void SetVisual(Bool_t v = kTRUE) {v ? SETBIT(fStatus, kVisual) : CLRBIT(fStatus, kVisual);} + + void Terminate(Option_t * opt); + Bool_t GetGraphPlot(Float_t *bb, ETRDresolutionPlot ip, Int_t idx=-1); + Bool_t GetGraphTrack(Float_t *bb, Int_t idx, Int_t ily); + Bool_t GetGraphTrackTPC(Float_t *bb, Int_t selector); + +private: + AliTRDresolution(const AliTRDresolution&); + AliTRDresolution& operator=(const AliTRDresolution&); + void AdjustF1(TH1 *h, TF1 *f); + void GetLandauMpvFwhm(TF1 * const f, Float_t &mpv, Float_t &xm, Float_t &xM); + Bool_t Process(TH2* const h2, TF1 *f, Float_t k, TGraphErrors **g); + Bool_t Process2D(ETRDresolutionPlot ip, Int_t idx=-1, TF1 *f=0x0, Float_t scale=1.); + Bool_t Process3D(ETRDresolutionPlot ip, Int_t idx=-1, TF1 *f=0x0, Float_t scale=1.); + Bool_t Process3DL(ETRDresolutionPlot ip, Int_t idx=-1, TF1 *f=0x0, Float_t scale=1.); + Bool_t Process4D(ETRDresolutionPlot ip, Int_t idx=-1, TF1 *f=0x0, Float_t scale=1.); + + UChar_t fStatus; // steer parameter of the task + UChar_t fIdxPlot; //! plot counter (internal) + static Char_t const *fgPerformanceName[kNhistos]; // name of performance plot + static UChar_t const fgNElements[kNhistos]; // number of componets per task + static Char_t const *fgAxTitle[46][4]; // Title for all ref histos + AliTRDReconstructor *fReconstructor; //! local reconstructor + AliTRDgeometry *fGeo; //! TRD geometry + TObjArray *fGraphS; //! result holder - sigma values + TObjArray *fGraphM; //! result holder - mean values + + // calibration containers + TObjArray *fCl; //! cluster2track calib + TObjArray *fTrklt; //! tracklet2track calib + TObjArray *fMCcl; //! cluster2mc calib + TObjArray *fMCtrklt;//! tracklet2mc calib + + ClassDef(AliTRDresolution, 3) // TRD tracking resolution task +}; +#endif diff --git a/PWG1/TRD/info/AliTRDclusterInfo.cxx b/PWG1/TRD/info/AliTRDclusterInfo.cxx new file mode 100644 index 00000000000..dbd8d2f2931 --- /dev/null +++ b/PWG1/TRD/info/AliTRDclusterInfo.cxx @@ -0,0 +1,58 @@ +#include "TMath.h" + +#include "AliLog.h" +#include "AliTRDcluster.h" + +#include "AliTRDclusterInfo.h" + +ClassImp(AliTRDclusterInfo) + +//_________________________________________________ +AliTRDclusterInfo::AliTRDclusterInfo() + : TObject() + ,fDet(0xffff) + ,fPdg(0) + ,fLbl(-1) + ,fLocalTime(-100) + ,fQ(0.) + ,fX(0.) + ,fY(0.) + ,fYd(0.) + ,fZ(0.) + ,fdydx(0.) + ,fdzdx(0.) + ,fXd(0.) + ,fYt(0.) + ,fZt(0.) + ,fdy(0.) + ,fD(0.) + ,fTilt(0.) +{ + fCov[0] = 1.; fCov[1] = 0.; + fCov[2] = 1.; + fCovCl[0] = 1.; fCovCl[1] = 0.; + fCovCl[2] = 1.; +} + +//_________________________________________________ +void AliTRDclusterInfo::SetCluster(const AliTRDcluster *c) +{ + if(!c) return; + fDet = c->GetDetector(); + fX = c->GetX(); + fY = c->GetY(); + fZ = c->GetZ(); + fQ = TMath::Abs(c->GetQ()); + fLocalTime = c->GetLocalTimeBin(); + fYd = c->GetCenter(); + fCovCl[0] = c->GetSigmaY2(); + fCovCl[1] = 0.; + fCovCl[2] = c->GetSigmaZ2(); +} + +//_________________________________________________ +void AliTRDclusterInfo::Print(Option_t */*opt*/) const +{ + printf("Det[%3d] X[%7.2f] Y[%7.2f] Z[%7.2f] Q[%7.2f]\n", fDet==0xffff ? -1 : fDet, fX, fY, fZ, fQ); + printf("\tPdg[%d] Lbl[%d] Yt[%7.2f] Zt[%7.2f]\n", fPdg, fLbl, fYt, fZt); +} diff --git a/PWG1/TRD/info/AliTRDclusterInfo.h b/PWG1/TRD/info/AliTRDclusterInfo.h new file mode 100644 index 00000000000..b946fa38e88 --- /dev/null +++ b/PWG1/TRD/info/AliTRDclusterInfo.h @@ -0,0 +1,89 @@ +#ifndef ALITRDCLUSTERINFO_H +#define ALITRDCLUSTERINFO_H + +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + + +#ifndef Root_TObject +#include "TObject.h" +#endif + +class AliTRDcluster; +class AliTRDclusterInfo : public TObject +{ +public: + AliTRDclusterInfo(); + + Float_t GetAnisochronity() const {return fD;} + inline void GetCluster(Int_t &det, Float_t &x, Float_t &y, Float_t &z, Float_t &q, Int_t &t, Float_t *cov=0x0) const; + void GetMC(Int_t &pdg, Int_t &label) const{ + pdg = fPdg; + label= fLbl; } + void GetGlobalPosition(Float_t &yt, Float_t &zt, Float_t &dydx, Float_t &dzdx, Float_t *cov=0x0) const { + dydx = fdydx; + dzdx = fdzdx; + yt = fYt; + zt = fZt; + if(cov) memcpy(cov, fCov, 3*sizeof(Float_t));} + Float_t GetResolution() const {return fdy;} + Float_t GetDriftLength() const {return fXd;} + Float_t GetYDisplacement() const {return fYd;} + Float_t GetTilt() const { return fTilt;} + + void Print(Option_t *opt="") const; + + void SetAnisochronity(Float_t d) {fD = d;} + void SetCluster(const AliTRDcluster *c); + void SetMC(Int_t pdg, Int_t label){ + fPdg = pdg; + fLbl = label;} + void SetGlobalPosition(Float_t yt, Float_t zt, Float_t dydx, Float_t dzdx, Float_t *cov=0x0) { + fdydx = dydx; + fdzdx = dzdx; + fYt = yt; + fZt = zt; + if(cov) memcpy(fCov, cov, 3*sizeof(Float_t));} + void SetResolution(Float_t dy) {fdy = dy;} + void SetDriftLength(Float_t d) {fXd = d;} + void SetTilt(Float_t t) {fTilt = t;} + +private: + UShort_t fDet; // detector + Short_t fPdg; // particle code + Short_t fLbl; // track label (MC) + Short_t fLocalTime; // calibrate drift time + Float_t fQ; // cluster charge (REC) + Float_t fX; // x coordinate (REC) + Float_t fY; // y coordinate (REC) + Float_t fYd; // displacement from pad center y coordinate + Float_t fZ; // z coordinate (REC) + Float_t fdydx; // slope in phi (MC) + Float_t fdzdx; // slope in theta (MC) + Float_t fXd; // drift length + Float_t fYt; // y coordinate (MC) + Float_t fZt; // z coordinate (MC) + Float_t fCov[3];// covariance matrix in the yz plane (track) + Float_t fCovCl[3];// covariance matrix in the yz plane (cluster) + Float_t fdy; // difference in y after tilt correction + Float_t fD; // distance to the anode wire + Float_t fTilt; // pad tilt; + + ClassDef(AliTRDclusterInfo, 1) // extracted cluster2MC information +}; + + +//_________________________________________________ +inline void AliTRDclusterInfo::GetCluster(Int_t &det, Float_t &x, Float_t &y, Float_t &z, Float_t &q, Int_t &t, Float_t *cov) const +{ + det = fDet; + x = fX; + y = fY; + z = fZ; + q = fQ; + t = fLocalTime; + if(cov) memcpy(cov, fCovCl, 3*sizeof(Float_t)); +} + +#endif + diff --git a/PWG1/TRD/info/AliTRDeventInfo.cxx b/PWG1/TRD/info/AliTRDeventInfo.cxx new file mode 100644 index 00000000000..f6cda69d9c1 --- /dev/null +++ b/PWG1/TRD/info/AliTRDeventInfo.cxx @@ -0,0 +1,79 @@ +#include "AliESDHeader.h" +#include "AliESDRun.h" + +#include "AliTRDeventInfo.h" + +ClassImp(AliTRDeventInfo) + +AliTRDeventInfo::AliTRDeventInfo(): + TObject() + ,fHeader(0x0) + ,fRun(0x0) +{ + // + // Default Constructor + // + SetBit(kOwner, 0); +} + +AliTRDeventInfo::AliTRDeventInfo(AliESDHeader *header, AliESDRun *run): + TObject() + ,fHeader(header) + ,fRun(run) +{ + // + // Constructor with Arguments + // + SetBit(kOwner, 0); +} + +AliTRDeventInfo::AliTRDeventInfo(const AliTRDeventInfo &info): + TObject() + ,fHeader(info.fHeader) + ,fRun(info.fRun) +{ + // + // Copy Constructor + // Flat Copy + // + SetBit(kOwner, 0); +} + +AliTRDeventInfo& AliTRDeventInfo::operator=(const AliTRDeventInfo& info){ + // + // Operator= + // Flat Copy + // + this->fHeader = info.fHeader; + this->fRun = info.fRun; + SetBit(kOwner, 0); + return *this; +} + +AliTRDeventInfo::~AliTRDeventInfo(){ + // + // Destructor + // Delete the entries if it is the Owner + // + Delete(""); +} + +void AliTRDeventInfo::Delete(const Option_t *){ + // + // Delete the Object + // Delete the entries if it is the Owner + // + if(IsOwner()){ + if(fHeader) delete fHeader; + if(fRun) delete fRun; + }; + fHeader = 0x0; + fRun = 0x0; +} + +void AliTRDeventInfo::SetOwner(){ + SetBit(kOwner, 1); + // Do deep copy + fHeader = new AliESDHeader(*fHeader); + fRun = new AliESDRun(*fRun); +} diff --git a/PWG1/TRD/info/AliTRDeventInfo.h b/PWG1/TRD/info/AliTRDeventInfo.h new file mode 100644 index 00000000000..ced9c6578a6 --- /dev/null +++ b/PWG1/TRD/info/AliTRDeventInfo.h @@ -0,0 +1,34 @@ +#ifndef __ALITRDEVENTINFO_H__ +#define __ALITRDEVENTINFO_H__ + +#include + +class AliESDHeader; +class AliESDRun; + +class AliTRDeventInfo : public TObject{ +public: + AliTRDeventInfo(); + AliTRDeventInfo(AliESDHeader *header, AliESDRun *run); + AliTRDeventInfo(const AliTRDeventInfo &info); + AliTRDeventInfo& operator=(const AliTRDeventInfo &info); + virtual ~AliTRDeventInfo(); + virtual void Delete(const Option_t *); + + AliESDHeader *GetEventHeader() const { return fHeader; } + AliESDRun *GetRunInfo() const { return fRun; } + Bool_t IsOwner() const { return TestBit(kOwner); } + void SetEventHeader(AliESDHeader *evHeader){ fHeader = evHeader; } + void SetRunInfo(AliESDRun *evRun) { fRun = evRun; } + void SetOwner(); + +private: + enum{ + kOwner = BIT(14) + }; + AliESDHeader *fHeader; //! The ESD Header + AliESDRun *fRun; //! The ESD Run Info + + ClassDef(AliTRDeventInfo, 1) +}; +#endif diff --git a/PWG1/TRD/info/AliTRDtrackInfo.cxx b/PWG1/TRD/info/AliTRDtrackInfo.cxx new file mode 100644 index 00000000000..c33a8dfb330 --- /dev/null +++ b/PWG1/TRD/info/AliTRDtrackInfo.cxx @@ -0,0 +1,500 @@ +/************************************************************************** +* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* * +* Author: The ALICE Off-line Project. * +* Contributors are mentioned in the code where appropriate. * +* * +* Permission to use, copy, modify and distribute this software and its * +* documentation strictly for non-commercial purposes is hereby granted * +* without fee, provided that the above copyright notice appears in all * +* copies and that both the copyright notice and this permission notice * +* appear in the supporting documentation. The authors make no claims * +* about the suitability of this software for any purpose. It is * +* provided "as is" without express or implied warranty. * +**************************************************************************/ + +/* $Id: AliTRDtrackInfo.cxx 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// Reconstruction QA // +// // +// Authors: // +// Alex Bercuci // +// Markus Fasel // +// // +//////////////////////////////////////////////////////////////////////////// + +#include "TDatabasePDG.h" + +#include "AliTrackReference.h" +#include "AliExternalTrackParam.h" + +#include "AliTRDseedV1.h" +#include "AliTRDtrackV1.h" +#include "AliTRDgeometry.h" +#include "AliTRDtrackerV1.h" + +#include "AliTRDtrackInfo.h" + +ClassImp(AliTRDtrackInfo) +ClassImp(AliTRDtrackInfo::AliMCinfo) +ClassImp(AliTRDtrackInfo::AliESDinfo) + +//___________________________________________________ +AliTRDtrackInfo::AliTRDtrackInfo(): + TObject() + ,fNClusters(0) + ,fTRDtrack(0x0) + ,fMC(0x0) + ,fESD() +{ + // + // Default constructor + // +} + + +//___________________________________________________ +AliTRDtrackInfo::AliTRDtrackInfo(const AliTRDtrackInfo &trdInfo): + TObject((const TObject&)trdInfo) + ,fNClusters(trdInfo.fNClusters) + ,fTRDtrack(0x0) + ,fMC(new AliMCinfo(*trdInfo.fMC)) + ,fESD(trdInfo.fESD) +{ + // + // copy Entries + // + + if(trdInfo.fMC) fMC = new AliMCinfo(*trdInfo.fMC); + + if(trdInfo.fTRDtrack){ + fTRDtrack = new AliTRDtrackV1(*trdInfo.fTRDtrack); + if(trdInfo.fTRDtrack->IsOwner()) fTRDtrack->SetOwner(); + } +} + +//___________________________________________________ +AliTRDtrackInfo::AliMCinfo::AliMCinfo() + :fLabel(0) + ,fPDG(0) + ,fNTrackRefs(0) +{ + // Set 0-Pointers + memset(fTrackRefs, 0, sizeof(AliTrackReference *) * 12); +} + +//___________________________________________________ +AliTRDtrackInfo::AliMCinfo::AliMCinfo(const AliMCinfo &mc) + :fLabel(mc.fLabel) + ,fPDG(mc.fPDG) + ,fNTrackRefs(mc.fNTrackRefs) +{ + // + // Constructor + // + + memset(fTrackRefs, 0, sizeof(AliTrackReference *) * 12); + for(Int_t ien = 0; ien < 12; ien++){ + if(mc.fTrackRefs[ien]) + fTrackRefs[ien] = new AliTrackReference(*(mc.fTrackRefs[ien])); + } +} + +//___________________________________________________ +AliTRDtrackInfo::AliESDinfo::AliESDinfo() + :fId(-1) + ,fStatus(0) + ,fKinkIndex(0) + ,fTPCncls(0) + ,fTRDpidQuality(0) + ,fTRDnSlices(0) + ,fTRDslices(0x0) + ,fOP(0x0) +{ + // + // Constructor + // + + memset(fTRDr, 0, AliPID::kSPECIES*sizeof(Double32_t)); +} + +//___________________________________________________ +AliTRDtrackInfo::AliESDinfo::AliESDinfo(const AliESDinfo &esd) + :fId(esd.fId) + ,fStatus(esd.fStatus) + ,fKinkIndex(esd.fKinkIndex) + ,fTPCncls(esd.fTPCncls) + ,fTRDpidQuality(esd.fTRDpidQuality) + ,fTRDnSlices(esd.fTRDnSlices) + ,fTRDslices(0x0) + ,fOP(0x0) +{ + // + // Constructor + // + + memcpy(fTRDr, esd.fTRDr, AliPID::kSPECIES*sizeof(Double32_t)); + + if(fTRDnSlices){ + fTRDslices = new Double32_t[fTRDnSlices]; + memcpy(fTRDslices, esd.fTRDslices, fTRDnSlices*sizeof(Double32_t)); + } + if(esd.fOP) fOP = new AliExternalTrackParam(*esd.fOP); +} + + +//___________________________________________________ +AliTRDtrackInfo::~AliTRDtrackInfo() +{ + // + // Destructor + // + + if(fMC) delete fMC; + if(fTRDtrack) delete fTRDtrack; +} + +//___________________________________________________ +AliTRDtrackInfo::AliMCinfo::~AliMCinfo() +{ + // + // Destructor + // + + fNTrackRefs = 0; + for(Int_t ien = 0; ien < 12; ien++){ + if(fTrackRefs[ien]) delete fTrackRefs[ien]; + fTrackRefs[ien] = 0x0; + } +} + +//___________________________________________________ +AliTRDtrackInfo::AliESDinfo::~AliESDinfo() +{ + // + // Destructor + // + + if(fTRDnSlices){ + delete [] fTRDslices; + fTRDslices = 0x0; + fTRDnSlices = 0; + } + if(fOP) delete fOP; fOP = 0x0; +} + + +//___________________________________________________ +AliTRDtrackInfo& AliTRDtrackInfo::operator=(const AliTRDtrackInfo &trdInfo) +{ + // + // = Operator + // + + fNClusters = trdInfo.fNClusters; + fESD = trdInfo.fESD; + + if(trdInfo.fMC){ + if(!fMC) + fMC = new AliMCinfo(*trdInfo.fMC); + else + new(fMC) AliMCinfo(*trdInfo.fMC); + } + + if(trdInfo.fTRDtrack){ + if(!fTRDtrack) + fTRDtrack = new AliTRDtrackV1(*trdInfo.fTRDtrack); + else + new(fTRDtrack) AliTRDtrackV1(*trdInfo.fTRDtrack); + if(trdInfo.fTRDtrack->IsOwner()) fTRDtrack->SetOwner(); + } + + return *this; +} + +//___________________________________________________ +AliTRDtrackInfo::AliMCinfo& AliTRDtrackInfo::AliMCinfo::operator=(const AliMCinfo &mc) +{ + // + // Assignment operator + // + + fLabel = mc.fLabel; + fPDG = mc.fPDG; + fNTrackRefs = mc.fNTrackRefs; + + AliTrackReference **itr = &fTrackRefs[0]; + AliTrackReference* const *jtr = &mc.fTrackRefs[0]; + for(Int_t ien = 0; ien < 12; ien++, itr++, jtr++){ + if((*jtr)){ + if(!(*itr)) (*itr) = new AliTrackReference(*(*jtr)); + else new(&(*itr)) AliTrackReference(*(*jtr)); + } else (*itr) = 0x0; + } + return *this; +} + +//___________________________________________________ +AliTRDtrackInfo::AliESDinfo& AliTRDtrackInfo::AliESDinfo::operator=(const AliESDinfo &esd) +{ + // + // Assignment operator + // + + fId = esd.fId; + fStatus = esd.fStatus; + fTRDpidQuality = esd.fTRDpidQuality; + fTRDnSlices = esd.fTRDnSlices; + fTRDslices = 0x0; + + memcpy(fTRDr, esd.fTRDr, AliPID::kSPECIES*sizeof(Double32_t)); + + if(fTRDnSlices){ + fTRDslices = new Double32_t[fTRDnSlices]; + memcpy(fTRDslices, esd.fTRDslices, fTRDnSlices*sizeof(Double32_t)); + } + if(esd.fOP){ + if(fOP) new(fOP) AliExternalTrackParam(esd.fOP); + else fOP = new AliExternalTrackParam(esd.fOP); + } else fOP = 0x0; + + return *this; +} + +//___________________________________________________ +void AliTRDtrackInfo::Delete(const Option_t *) +{ + // + // Delete + // + + fNClusters = 0; + if(fMC) delete fMC; fMC = 0x0; + if(fTRDtrack) delete fTRDtrack; fTRDtrack = 0x0; +} + +//___________________________________________________ +void AliTRDtrackInfo::SetTrack(const AliTRDtrackV1 *track) +{ + // + // Set the TRD track + // + + if(!fTRDtrack) + fTRDtrack = new AliTRDtrackV1(*track); + else + new(fTRDtrack)AliTRDtrackV1(*track); + fTRDtrack->SetOwner(); + // Make a copy for the object in order to avoid ownership problems +} + +//___________________________________________________ +void AliTRDtrackInfo::AddTrackRef(const AliTrackReference *tref) +{ + // + // Add track reference + // + + SetMC(); + if(fMC->fNTrackRefs >= 12){ + SetCurved(); + return; + } + // Make a copy for the object in order to avoid ownership problems + fMC->fTrackRefs[fMC->fNTrackRefs++] = new AliTrackReference(*tref); +} + +//___________________________________________________ +AliTrackReference* AliTRDtrackInfo::GetTrackRef(Int_t idx) const +{ +// +// Returns a track reference +// + if(!fMC) return 0x0; + return (idx>=0 && idx < 12) ? fMC->fTrackRefs[idx] : 0x0; +} + +//___________________________________________________ +AliTrackReference* AliTRDtrackInfo::GetTrackRef(AliTRDseedV1* const tracklet) const +{ +// +// Returns a track reference +// + if(!fMC) return 0x0; + Double_t cw = AliTRDgeometry::CamHght() + AliTRDgeometry::CdrHght(); + AliTrackReference * const* jtr = &(fMC->fTrackRefs[0]); + for(Int_t itr = 0; itr < fMC->fNTrackRefs; itr++, ++jtr){ + if(!(*jtr)) break; + if(TMath::Abs(tracklet->GetX0() - (*jtr)->LocalX()) < cw) return (*jtr); + } + return 0x0; +} + +//___________________________________________________ +Int_t AliTRDtrackInfo::GetNumberOfClusters() const +{ + // + // Returns the number of clusters + // + + Int_t n = 0; + if(!fTRDtrack) return 0; + if(fTRDtrack->GetNumberOfTracklets() == 0) return n; + AliTRDseedV1 *tracklet = 0x0; + for(Int_t ip=0; ip<6; ip++){ + if(!(tracklet = const_cast(fTRDtrack->GetTracklet(ip)))) continue; + n+=tracklet->GetN(); + } + return n; +} + + +//___________________________________________________ +void AliTRDtrackInfo::SetOuterParam(const AliExternalTrackParam *op) +{ + // + // Set outer track parameters + // + + if(!op) return; + if(fESD.fOP) new(fESD.fOP) AliExternalTrackParam(*op); + else fESD.fOP = new AliExternalTrackParam(*op); +} + +//___________________________________________________ +Int_t AliTRDtrackInfo::GetNTracklets() const +{ + // + // Return the number of tracklets + // + + if(!fTRDtrack) return 0x0; + return fTRDtrack->GetNumberOfTracklets(); +} + +//___________________________________________________ +void AliTRDtrackInfo::SetSlices(Int_t n, Double32_t *s) +{ + // + // Set the slices + // + + if(fESD.fTRDnSlices != n){ + fESD.fTRDnSlices = 0; + delete [] fESD.fTRDslices; + fESD.fTRDslices = 0x0; + } + + if(!fESD.fTRDnSlices){ + fESD.fTRDnSlices = n; + fESD.fTRDslices = new Double32_t[n]; + } + + memcpy(fESD.fTRDslices, s, n*sizeof(Double32_t)); +} + +//___________________________________________________ +Bool_t AliTRDtrackInfo::AliMCinfo::GetDirections(Float_t &x0, Float_t &y0, Float_t &z0, Float_t &dydx, Float_t &dzdx, Float_t &pt, UChar_t &status) const +{ +// Check for 2 track ref for the tracklet defined bythe radial position x0 +// The "status" is a bit map and gives a more informative output in case of failure: +// - 0 : everything is OK +// - BIT(0) : 0 track refs found +// - BIT(1) : 1 track reference found +// - BIT(2) : dx <= 0 between track references +// - BIT(3) : dx > 0 && dx < 3.7 - tangent tracks + + status = 0; + Double_t cw = AliTRDgeometry::CamHght() + AliTRDgeometry::CdrHght(); + Int_t nFound = 0; + AliTrackReference *tr[2] = {0x0, 0x0}; + AliTrackReference * const* jtr = &fTrackRefs[0]; + for(Int_t itr = 0; itr < fNTrackRefs; itr++, ++jtr){ + if(!(*jtr)) break; +/* + if(fDebugLevel>=5) printf("\t\tref[%2d] x[%6.3f]\n", itr, (*jtr)->LocalX());*/ + if(TMath::Abs(x0 - (*jtr)->LocalX()) > cw) continue; + tr[nFound++] = (*jtr); + if(nFound == 2) break; + } + if(nFound < 2){ + AliWarningGeneral("AliTRDtrackInfo::AliMCinfo::GetDirections()", Form("Missing track ref x0[%6.3f] nref[%d]\n", x0, nFound)); + if(!nFound) SETBIT(status, 0); + else SETBIT(status, 1); + return kFALSE; + } + if((pt=tr[1]->Pt()) < 1.e-3) return kFALSE; + + Double_t dx = tr[1]->LocalX() - tr[0]->LocalX(); + if(dx <= 0.){ + AliWarningGeneral("AliTRDtrackInfo::AliMCinfo::GetDirections()", Form("Track ref with wrong radial distances refX0[%6.3f] refX1[%6.3f]", tr[0]->LocalX(), tr[1]->LocalX())); + SETBIT(status, 2); + return kFALSE; + } + if(TMath::Abs(dx-AliTRDgeometry::CamHght()-AliTRDgeometry::CdrHght())>1.E-3) SETBIT(status, 3); + + dydx = (tr[1]->LocalY() - tr[0]->LocalY()) / dx; + dzdx = (tr[1]->Z() - tr[0]->Z()) / dx; + //Float_t dx0 = tr[1]->LocalX() - x0; + y0 = tr[1]->LocalY()/* - dydx*dx0*/; + z0 = tr[1]->Z()/* - dzdx*dx0*/; + x0 = tr[1]->LocalX(); + return kTRUE; +} + +//___________________________________________________ +void AliTRDtrackInfo::AliMCinfo::PropagateKalman(Double_t dx[kNTrackRefs], Double_t dy[kNTrackRefs], Double_t dz[kNTrackRefs], Double_t dp[kNTrackRefs], Double_t c[kNTrackRefs][15], Double_t step) const +{ +// Propagate Kalman from the first TRD track reference to +// last one and save residuals in the y, z and pt. +// +// This is to calibrate the dEdx and MS corrections + + for(Int_t itr=kNTrackRefs; itr--;){ + dx[itr] = -1.; dy[itr] = 100.; dz[itr] = 100.; dp[itr] = 100.; + } + if(!fNTrackRefs) return; + + // Initialize TRD track to the first track reference + AliTrackReference *tr = fTrackRefs[0]; + if(tr->Pt()<1.e-3) return; + + AliTRDtrackV1 tt; + Double_t xyz[3]={tr->X(),tr->Y(),tr->Z()}; + Double_t pxyz[3]={tr->Px(),tr->Py(),tr->Pz()}; + Double_t var[6] = {1.e-4, 1.e-4, 1.e-4, 1.e-4, 1.e-4, 1.e-4}; + Double_t cov[21]={ + var[0], 0., 0., 0., 0., 0., + var[1], 0., 0., 0., 0., + var[2], 0., 0., 0., + var[3], 0., 0., + var[4], 0., + var[5] + }; + TDatabasePDG db; + const TParticlePDG *pdg=db.GetParticle(fPDG); + if(!pdg){ + AliWarningGeneral("AliTRDtrackInfo::AliMCinfo::PropagateKalman()", Form("PDG entry missing for code %d. References for track %d", fPDG, fNTrackRefs)); + return; + } + tt.Set(xyz, pxyz, cov, Short_t(pdg->Charge())); + tt.SetMass(pdg->Mass()); + + Double_t x0 = tr->LocalX(); + const Double_t *cc = 0x0; + for(Int_t itr=1, ip=0; itrLocalX(), step)) continue; + + //if(update) ... + dx[ip] = tt.GetX() - x0; + dy[ip] = tt.GetY() - tr->LocalY(); + dz[ip] = tt.GetZ() - tr->Z(); + dp[ip] = tt.Pt()- tr->Pt(); + cc = tt.GetCovariance(); + memcpy(c[ip], cc, 15*sizeof(Double_t)); + ip++; + } +} diff --git a/PWG1/TRD/info/AliTRDtrackInfo.h b/PWG1/TRD/info/AliTRDtrackInfo.h new file mode 100644 index 00000000000..d6d4a5e49c7 --- /dev/null +++ b/PWG1/TRD/info/AliTRDtrackInfo.h @@ -0,0 +1,161 @@ +#ifndef ALITRDTRACKINFO_H +#define ALITRDTRACKINFO_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* See cxx source for full Copyright notice */ + +/* $Id: AliTRDtrackInfo.h 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// Reconstruction QA // +// // +//////////////////////////////////////////////////////////////////////////// + +#ifndef Root_TObject +#include "TObject.h" +#endif + +#ifndef ALIPID_H +#include "AliPID.h" +#endif + +class AliTRDseedV1; +class AliTRDtrackV1; +class AliTrackReference; +class AliExternalTrackParam; +class AliTRDtrackInfo : public TObject{ +public: + enum{ + kNTrackRefs = 12 + }; + class AliESDinfo{ + friend class AliTRDtrackInfo; // Friend class + public: + AliESDinfo(); + AliESDinfo(const AliESDinfo &esd); + virtual ~AliESDinfo(); + AliESDinfo& operator=(const AliESDinfo &esd); + + Int_t GetId() const {return fId;} + ULong_t GetStatus() const {return fStatus;} + Int_t GetKinkIndex() const {return fKinkIndex;} + UShort_t GetTPCncls() const {return fTPCncls;} + UChar_t GetPidQuality() const {return fTRDpidQuality;} + Int_t GetNSlices() const {return fTRDnSlices;} + Double32_t* GetSliceIter() const {return fTRDslices;} + const Double32_t* GetResponseIter() const {return &fTRDr[0];} + AliExternalTrackParam* GetOuterParam() const { return fOP;} + + protected: + Int_t fId; // ESD track id + ULong_t fStatus; // ESD track status + Int_t fKinkIndex; // ESD kink index + UShort_t fTPCncls; // Number of Clusters inside TPC + Double32_t fTRDr[AliPID::kSPECIES]; // TRD radial position + UChar_t fTRDpidQuality; // TRD PID quality + Int_t fTRDnSlices; // number of slices used for PID + Double32_t *fTRDslices; //[fTRDnSlices] + AliExternalTrackParam *fOP; // outer param + + ClassDef(AliESDinfo, 2) // ESD info related to TRD + }; + + class AliMCinfo{ + friend class AliTRDtrackInfo; + public: + //typedef AliTrackReference (const* constAliTrackReference); + AliMCinfo(); + AliMCinfo(const AliMCinfo &mc); + virtual ~AliMCinfo(); + AliMCinfo& operator=(const AliMCinfo &mc); + Int_t GetLabel() const {return fLabel;} + Int_t GetNTrackRefs() const {return fNTrackRefs;} + Int_t GetPDG() const {return fPDG;} + Bool_t GetDirections(Float_t &x0, Float_t &y0, Float_t &z0, Float_t &dydx, Float_t &dzdx, Float_t &pt, UChar_t &s) const; + AliTrackReference const* GetTrackRef(Int_t ref=0) const {return fTrackRefs[ref];} + void PropagateKalman(Double_t dx[kNTrackRefs], Double_t dy[kNTrackRefs], Double_t dz[kNTrackRefs], Double_t dpt[kNTrackRefs], Double_t c[kNTrackRefs][15], Double_t step = 2.) const; + + protected: + Int_t fLabel; // MC label + Int_t fPDG; // particle code + Int_t fNTrackRefs; // number of track refs + AliTrackReference *fTrackRefs[kNTrackRefs]; // track refs array + ClassDef(AliMCinfo, 1) // MC info related to TRD + }; + + AliTRDtrackInfo(); + AliTRDtrackInfo(const AliTRDtrackInfo &trdInfo); + ~AliTRDtrackInfo(); + +// void Clear(const Option_t *){} + void Delete(const Option_t *); + + AliTRDtrackInfo& operator=(const AliTRDtrackInfo &trdInfo); + + void AddTrackRef(const AliTrackReference *trackRef); + + Int_t GetTrackId() const { return fESD.fId;} + const AliESDinfo* GetESDinfo() const { return &fESD; } + const AliMCinfo* GetMCinfo() const { return fMC; } + Int_t GetNumberOfClusters() const; + Int_t GetNumberOfClustersRefit() const {return fNClusters;} + Int_t GetNTracklets() const; + Int_t GetNTrackRefs() const {return fMC ? fMC->fNTrackRefs:0;} + Int_t GetLabel() const { return fMC ? fMC->fLabel:0; } + Int_t GetKinkIndex() const { return fESD.fKinkIndex;} + UShort_t GetTPCncls() const { return fESD.fTPCncls;} + Int_t GetPDG() const { return fMC ? fMC->fPDG : 0; } + ULong_t GetStatus() const {return fESD.fStatus;} + AliTRDtrackV1* GetTrack() const { return fTRDtrack; } + AliTrackReference* GetTrackRef(Int_t entry) const; + AliTrackReference* GetTrackRef(AliTRDseedV1* const tracklet) const; + + Bool_t IsCurved() const {return TestBit(kCurv);} + Bool_t IsPrimary() const {return TestBit(kPrim);} + Bool_t HasESDtrack() const{return ((fTRDtrack != 0x0) ||(fESD.fOP != 0));} + Bool_t HasMCinfo() const { return (Bool_t)fMC; } + + void SetCurved(Bool_t curv = kTRUE) {SetBit(kCurv, curv);} + void SetLabel(Int_t lab) { SetMC(); fMC->fLabel = lab; } + void SetNumberOfClustersRefit(Int_t n) {fNClusters = n;} + inline void SetMC(); + void SetPDG(Int_t pdg) { SetMC(); fMC->fPDG = pdg; } + void SetPrimary(Bool_t prim = kTRUE) {SetBit(kPrim, prim);} + void SetOuterParam(const AliExternalTrackParam *op); + void SetStatus(ULong_t stat) {fESD.fStatus = stat;} + void SetKinkIndex(Int_t kinkIndex) {fESD.fKinkIndex = kinkIndex;} + void SetTPCncls(UShort_t TPCncls) {fESD.fTPCncls = TPCncls;} + void SetTrackId(Int_t id) {fESD.fId = id;} + void SetTrack(const AliTRDtrackV1 *track); + void SetESDpidQuality(UChar_t q) { fESD.fTRDpidQuality = q;} + void SetSlices(Int_t n, Double32_t *s); + inline void SetESDpid(Double_t *); + +private: + enum{ + kCurv = 14, + kPrim = 15 + }; + // this 2 data members have to go to ESD header. + Int_t fNClusters; // Numer of clusters from refit + AliTRDtrackV1 *fTRDtrack; // tracklets data array + AliMCinfo *fMC; // MC extract for TRD + AliESDinfo fESD; // ESD extract for TRD + + ClassDef(AliTRDtrackInfo, 3) // TRD track info +}; + + +//________________________________________________________ +inline void AliTRDtrackInfo::SetMC() +{ + if(!fMC) fMC = new AliMCinfo(); +} + +//________________________________________________________ +inline void AliTRDtrackInfo::SetESDpid(Double_t * const r) +{ + for(Int_t is = AliPID::kSPECIES; is--;) fESD.fTRDr[is] = r[is]; +} + +#endif diff --git a/PWG1/TRD/info/AliTRDv0Info.cxx b/PWG1/TRD/info/AliTRDv0Info.cxx new file mode 100644 index 00000000000..b3f783675f0 --- /dev/null +++ b/PWG1/TRD/info/AliTRDv0Info.cxx @@ -0,0 +1,525 @@ +/************************************************************************** +* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * +* * +* Author: The ALICE Off-line Project. * +* Contributors are mentioned in the code where appropriate. * +* * +* Permission to use, copy, modify and distribute this software and its * +* documentation strictly for non-commercial purposes is hereby granted * +* without fee, provided that the above copyright notice appears in all * +* copies and that both the copyright notice and this permission notice * +* appear in the supporting documentation. The authors make no claims * +* about the suitability of this software for any purpose. It is * +* provided "as is" without express or implied warranty. * +**************************************************************************/ + +/* $Id: AliTRDv0Info.cxx 27496 2008-07-22 08:35:45Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// Reconstruction QA // +// // +// Gathers all information necessary for reference data selection about // +// the track and (in case) its corresponding V0. // +// Carries out the selection of electrons (from gamma conversions), // +// pions (from K0s decays) and protons (from Lambda and Anti-Lambda // +// decays) by cuts specific for the respective decay and particle // +// species. // +// (M.Heide, 2009/10/06) // +// // +// Authors: // +// Alex Bercuci // +// Alex Wilk // +// Markus Heide // +// // +//////////////////////////////////////////////////////////////////////////// + +#include "TMath.h" + +#include "AliESDtrack.h" +#include "AliESDv0.h" +#include "AliESDInputHandler.h" +#include "AliAnalysisManager.h" +#include "AliLog.h" + +#include "AliTRDv0Info.h" +#include "AliTRDtrackInfo.h" +#include "AliTRDtrackInfo.h" + +ClassImp(AliTRDv0Info) + +//_________________________________________________ +AliTRDv0Info::AliTRDv0Info() + : TObject() + ,fESD(0x0) + ,fHasV0(0) + ,fQuality(0) + ,fMomentum(0) + ,fDCA(10) + ,fPointingAngle(10) + ,fOpenAngle(10) + ,fPsiPair(99) + ,fMagField(0) + ,fRadius(0) + ,fTrackID(0) + ,fV0Momentum(0) + ,fTrackP(0x0) + ,fTrackN(0x0) + ,fTrack(0x0) + ,fNindex(0) + ,fPindex(0) +{ + // + // Default constructor + // + + memset(fPplus, 0, 2*kNlayer*sizeof(Float_t)); + memset(fPminus, 0, 2*kNlayer*sizeof(Float_t)); + memset(fDetPID, 0, 2*kNDaughters*kNDetectors*AliPID::kSPECIES*sizeof(Float_t)); + memset(fInvMass, 0, kNMomBins*kNDecays*sizeof(Double_t)); + + ///////////////////////////////////////////////////////////////////////////// + //Set Cut values: First specify decay in brackets, then the actual cut value! + ///////////////////////////////////////////////////////////////////////////// + + //Upper limit for distance of closest approach of two daughter tracks : + fUpDCA[kGamma] = 0.25; + fUpDCA[kK0s] = 0.25; + fUpDCA[kLambda] = 0.25; + fUpDCA[kAntiLambda] = 0.25; + + //Upper limit for pointing angle (= angle between between vector from primary to secondary vertex and reconstructed momentum of V0 mother particle) : + fUpPointingAngle[kGamma] = 0.03; + fUpPointingAngle[kK0s] = 0.03; + fUpPointingAngle[kLambda] = 0.03; + fUpPointingAngle[kAntiLambda] = 0.03; + + //Upper limit for invariant mass of V0 mother : + fUpInvMass[kGamma][0] = 0.04;// second pair of brackets is for momentum bin: 0: below mother momentm of 2.5 GeV + fUpInvMass[kGamma][1] = 0.07;//1: above 2.5 GeV + fUpInvMass[kK0s][0] = fUpInvMass[kK0s][1] = 0.51; + fUpInvMass[kLambda][0] = fUpInvMass[kLambda][1] = 1.22; + fUpInvMass[kAntiLambda][0] = fUpInvMass[kAntiLambda][1] = 1.22; + + //Lower limit for invariant mass of V0 mother : + fDownInvMass[kGamma] = -1.; + fDownInvMass[kK0s] = 0.49; + fDownInvMass[kLambda] = 1.; + fDownInvMass[kAntiLambda] = 1.; + + //Lower limit for distance from secondary vertex to primary vertex in x-y plane : + fDownRadius[kGamma] = 5.7; + fDownRadius[kK0s] = 0.; + fDownRadius[kLambda] = 10.; + fDownRadius[kAntiLambda] = 10.; + + //Upper limit for distance from secondary vertex to primary vertex in x-y plane : + fUpRadius[kGamma] = 1000.; + fUpRadius[kK0s] = 1000.; + fUpRadius[kLambda] = 1000.; + fUpRadius[kAntiLambda] = 1000.; + + //Upper limit for opening angle between two daughter tracks (characteristically near zero for conversions) : + fUpOpenAngle[kGamma] = 0.1; + fUpOpenAngle[kK0s] = 3.15; + fUpOpenAngle[kLambda] = 3.15; + fUpOpenAngle[kAntiLambda] = 3.15; + + //Upper limit for angle between daughter momentum plane and plane perpendicular to magnetic field (characteristically around zero for conversions) : + fUpPsiPair[kGamma] = 0.1; + fUpPsiPair[kK0s] = 1.6; + fUpPsiPair[kLambda] = 1.6; + fUpPsiPair[kAntiLambda] = 1.6; + + //Lower limit for likelihood value of TPC PID : + fDownTPCPIDneg[AliPID::kElectron] = 0.21; + fDownTPCPIDpos[AliPID::kElectron] = 0.21; + + fDownTPCPIDneg[AliPID::kMuon] = 0.21; + fDownTPCPIDpos[AliPID::kMuon] = 0.21; + + fDownTPCPIDneg[AliPID::kPion] = 0.21; + fDownTPCPIDpos[AliPID::kPion] = 0.21; + + fDownTPCPIDneg[AliPID::kKaon] = 0.21; + fDownTPCPIDpos[AliPID::kKaon] = 0.21; + + fDownTPCPIDneg[AliPID::kProton] = 0.21; + fDownTPCPIDpos[AliPID::kProton] = 0.21; + ////////////////////////////////////////////////////////////////////////////////// + +} + +//_________________________________________________ +void AliTRDv0Info::GetESDv0Info(AliESDv0 *esdv0) +{//Gets values of ESDv0 and daughter track properties + //See header file for description of variables + + Int_t part1 = -1; + Int_t part2 = -1; + + fQuality = Quality(esdv0);//Attributes an Int_t to the V0 due to quality cuts (= 1 if V0 is accepted, other integers depending on cut which excludes the vertex) + + fRadius = Radius(esdv0);//distance from secondary vertex to primary vertex in x-y plane + + fDCA = esdv0->GetDcaV0Daughters();//distance of closest approach of two daughter tracks + + fPointingAngle = TMath::ACos(esdv0->GetV0CosineOfPointingAngle());// pointing angle (= angle between between vector from primary to secondary vertex and reconstructed momentum of V0 mother particle) + + fOpenAngle = OpenAngle(esdv0);//Opening angle between two daughter tracks + + fPsiPair = PsiPair(esdv0);//Angle between daughter momentum plane and plane perpendicular to magnetic field + + fV0Momentum = V0Momentum(esdv0);//Reconstructed momentum of the mother particle + + for(Int_t idecay = 0; idecay < kNDecays; idecay++)//4 decay types : conversions, K0s, Lambda, Anti-Lambda + //five particle types: electrons, muons, pions, kaons, protons (muons and kaons not involved) + { + if(idecay == kLambda)//protons and pions from Lambda + { + part1 = AliPID::kProton; + part2 = AliPID::kPion; + } + else if(idecay == kAntiLambda)//antiprotons and pions from Anti-Lambda + { + part1 = AliPID::kPion; + part2 = AliPID::kProton; + } + else if(idecay == kK0s)//pions from K0s + part1 = part2 = AliPID::kPion; + else if(idecay == kGamma)//electrons from conversions + part1 = part2 = AliPID::kElectron; + + fInvMass[idecay] = InvMass(part1, part2, esdv0);//Calculate invariant mass for all of our four supposed decays + } + GetDetectorPID();//Gets all likelihood values from TPC, TOF and ITS PID for the fDetPID[kNDaughters][kNDetectors][AliPID::kSPECIES] array + + +} +//_________________________________________________ +Float_t AliTRDv0Info::V0Momentum(AliESDv0 *esdv0) const +{ + // + // Reconstructed momentum of V0 mother particle + // + + Double_t mn[3] = {0,0,0}; + Double_t mp[3] = {0,0,0}; + + + esdv0->GetNPxPyPz(mn[0],mn[1],mn[2]);//reconstructed cartesian momentum components of negative daughter; + esdv0->GetPPxPyPz(mp[0],mp[1],mp[2]);//reconstructed cartesian momentum components of positive daughter; + + + return TMath::Sqrt((mn[0]+mp[0])*(mn[0]+mp[0]) + (mn[1]+mp[1])*(mn[1]+mp[1])+(mn[2]+mp[2])*(mn[2]+mp[2])); +} + +//_________________________________________________ +Double_t AliTRDv0Info::InvMass(Int_t part1, Int_t part2, AliESDv0 *esdv0) const +{ + // + // Invariant mass of reconstructed V0 mother + // + + const Double_t kpmass[5] = {AliPID::ParticleMass(AliPID::kElectron),AliPID::ParticleMass(AliPID::kMuon),AliPID::ParticleMass(AliPID::kPion),AliPID::ParticleMass(AliPID::kKaon),AliPID::ParticleMass(AliPID::kProton)}; + //Masses of electrons, muons, pions, kaons and protons, as implemented in ROOT + + + Double_t mn[3] = {0,0,0}; + Double_t mp[3] = {0,0,0}; + + esdv0->GetNPxPyPz(mn[0],mn[1],mn[2]);//reconstructed cartesian momentum components of negative daughter; + esdv0->GetPPxPyPz(mp[0],mp[1],mp[2]);//reconstructed cartesian momentum components of positive daughter; + + Double_t mass1 = kpmass[part1];//sets supposed rest masses for both daughters + Double_t mass2 = kpmass[part2]; + + //Calculate daughters' energies : + Double_t e1 = TMath::Sqrt(mass1*mass1+ + mp[0]*mp[0]+ + mp[1]*mp[1]+ + mp[2]*mp[2]); + Double_t e2 = TMath::Sqrt(mass2*mass2+ + mn[0]*mn[0]+ + mn[1]*mn[1]+ + mn[2]*mn[2]); + + //Sum of daughter momenta : + Double_t momsum = + (mn[0]+mp[0])*(mn[0]+mp[0])+ + (mn[1]+mp[1])*(mn[1]+mp[1])+ + (mn[2]+mp[2])*(mn[2]+mp[2]); + + //invariant mass : + Double_t mInv = TMath::Sqrt((e1+e2)*(e1+e2)-momsum); + + return mInv; + +} +//_________________________________________________ +Float_t AliTRDv0Info::OpenAngle(AliESDv0 *esdv0) +{//Opening angle between two daughter tracks + Double_t mn[3] = {0,0,0}; + Double_t mp[3] = {0,0,0}; + + + esdv0->GetNPxPyPz(mn[0],mn[1],mn[2]);//reconstructed cartesian momentum components of negative daughter; + esdv0->GetPPxPyPz(mp[0],mp[1],mp[2]);//reconstructed cartesian momentum components of positive daughter; + + + fOpenAngle = TMath::ACos((mp[0]*mn[0] + mp[1]*mn[1] + mp[2]*mn[2])/(TMath::Sqrt(mp[0]*mp[0] + mp[1]*mp[1] + mp[2]*mp[2])*TMath::Sqrt(mn[0]*mn[0] + mn[1]*mn[1] + mn[2]*mn[2]))); + + return fOpenAngle; +} + +//_________________________________________________ +Float_t AliTRDv0Info::PsiPair(AliESDv0 *esdv0) +{//Angle between daughter momentum plane and plane perpendicular to magnetic field + Double_t x, y, z; + esdv0->GetXYZ(x,y,z);//Reconstructed coordinates of V0; to be replaced by Markus Rammler's method in case of conversions! + + Double_t mn[3] = {0,0,0}; + Double_t mp[3] = {0,0,0}; + + + esdv0->GetNPxPyPz(mn[0],mn[1],mn[2]);//reconstructed cartesian momentum components of negative daughter; + esdv0->GetPPxPyPz(mp[0],mp[1],mp[2]);//reconstructed cartesian momentum components of positive daughter; + + + Double_t deltat = 1.; + deltat = TMath::ATan(mp[2]/(TMath::Sqrt(mp[0]*mp[0] + mp[1]*mp[1])+1.e-13)) - TMath::ATan(mn[2]/(TMath::Sqrt(mn[0]*mn[0] + mn[1]*mn[1])+1.e-13));//difference of angles of the two daughter tracks with z-axis + + Double_t radiussum = TMath::Sqrt(x*x + y*y) + 50;//radius to which tracks shall be propagated + + Double_t momPosProp[3]; + Double_t momNegProp[3]; + + AliExternalTrackParam nt(*fTrackN), pt(*fTrackP); + + fPsiPair = 4.; + + if(nt.PropagateTo(radiussum,fMagField) == 0)//propagate tracks to the outside + fPsiPair = -5.; + if(pt.PropagateTo(radiussum,fMagField) == 0) + fPsiPair = -5.; + pt.GetPxPyPz(momPosProp);//Get momentum vectors of tracks after propagation + nt.GetPxPyPz(momNegProp); + + Double_t pEle = + TMath::Sqrt(momNegProp[0]*momNegProp[0]+momNegProp[1]*momNegProp[1]+momNegProp[2]*momNegProp[2]);//absolute momentum value of negative daughter + Double_t pPos = + TMath::Sqrt(momPosProp[0]*momPosProp[0]+momPosProp[1]*momPosProp[1]+momPosProp[2]*momPosProp[2]);//absolute momentum value of positive daughter + + Double_t scalarproduct = + momPosProp[0]*momNegProp[0]+momPosProp[1]*momNegProp[1]+momPosProp[2]*momNegProp[2];//scalar product of propagated positive and negative daughters' momenta + + Double_t chipair = TMath::ACos(scalarproduct/(pEle*pPos));//Angle between propagated daughter tracks + + fPsiPair = TMath::Abs(TMath::ASin(deltat/chipair)); + + return fPsiPair; + +} + +//_________________________________________________ +void AliTRDv0Info::V0fromTrack(AliTRDtrackInfo * const track, Int_t ivertex) +{//Checks if track is a secondary vertex daughter (due to V0 finder) + + fMagField = fESD->GetMagneticField(); + + fTrackID = track->GetTrackId();//index of the track + + fTrack = fESD->GetTrack(fTrackID);//sets track information + + fHasV0 = 0; + + //comparing index of track with indices of pos./neg. V0 daughter : + AliESDv0 * esdv0 = fESD->GetV0(ivertex); + if((esdv0->GetIndex(0) == fTrackID)||(esdv0->GetIndex(1) == fTrackID)) + { + fHasV0 = 1;//track belongs to vertex found by V0 finder! + fNindex = esdv0->GetIndex(0); + fPindex = esdv0->GetIndex(1); + fTrackN = fESD->GetTrack(esdv0->GetIndex(0));//providing information about the other of the two daughter tracks + fTrackP = fESD->GetTrack(esdv0->GetIndex(1)); + GetESDv0Info(esdv0);//gets all the relevant information about our V0 + } +} +//_________________________________________________ +void AliTRDv0Info::GetDetectorPID() +{//PID likelihoods from TPC, TOF, and ITS, for all particle species + + fTrackN->GetTPCpid(fDetPID[kNeg][kTPC]); + fTrackP->GetTPCpid(fDetPID[kPos][kTPC]); + fTrackN->GetTOFpid(fDetPID[kNeg][kTOF]); + fTrackP->GetTOFpid(fDetPID[kPos][kTOF]); + fTrackN->GetITSpid(fDetPID[kNeg][kITS]); + fTrackP->GetITSpid(fDetPID[kPos][kITS]); + +} + +//_________________________________________________ +Float_t AliTRDv0Info::Radius(AliESDv0 *esdv0) +{//distance from secondary vertex to primary vertex in x-y plane + Double_t x, y, z; + esdv0->GetXYZ(x,y,z); //Reconstructed coordinates of V0; to be replaced by Markus Rammler's method in case of conversions! + fRadius = TMath::Sqrt(x*x + y*y); + return fRadius; + +} + +//_________________________________________________ +Int_t AliTRDv0Info::Quality(AliESDv0 *const esdv0) +{ + // + // Checking track and V0 quality status in order to exclude vertices based on poor information + // + + Float_t nClsN; + nClsN = fTrackN->GetTPCNcls();//number of found clusters in TPC for negative track + Float_t nClsFN; + nClsFN = fTrackN->GetTPCNclsF();//number of findable clusters in TPC for negative track + Float_t nClsP; + nClsP = fTrackP->GetTPCNcls();//number of found clusters in TPC for positive track + Float_t nClsFP; + nClsFP = fTrackP->GetTPCNclsF();//number of findable clusters in TPC for positive track + + fQuality = 0; + + + Float_t clsRatioN; + Float_t clsRatioP; + + if((nClsFN == 0) || (nClsFP == 0)) + return 2; + + clsRatioN = nClsN/nClsFN; //ratios of found to findable clusters in TPC + clsRatioP = nClsP/nClsFP; + + if (!(esdv0->GetOnFlyStatus()))//accept only vertices from online V0 finder + return 3; + if (!((fTrackP->GetStatus() & + AliESDtrack::kTPCrefit)))//accept only vertices in which both tracks have TPC refit + return 4; + if (!((fTrackN->GetStatus() & + AliESDtrack::kTPCrefit))) + return 5; + if (fTrackP->GetKinkIndex(0)>0 || + fTrackN->GetKinkIndex(0)>0 )//exclude tracks with kinks + return 6; + if((clsRatioN < 0.6)||(clsRatioP < 0.6))//exclude tracks with low ratio of found to findable TPC clusters + return 7; + fQuality = 1; + return fQuality; +} +//_________________________________________________ +Bool_t AliTRDv0Info::GetV0PID(Int_t ipart, AliTRDtrackInfo *track) +{//decides if track is accepted for one of the reference data samples + + Int_t iDecay = -1; + + //decide which decay has to be considered for which particle sample (Anti-Lambda will be treated separately) + if(ipart == AliPID::kElectron) + iDecay = kGamma; + else if(ipart == AliPID::kPion) + iDecay = kK0s; + else if(ipart == AliPID::kProton) + iDecay = kLambda; + + Int_t iPSlot;//Mother momentum slots above/below 2.5 GeV + + + Bool_t pid = 0;//return value for V0 PID decision + + if(!(track)) + { + AliError("AliTRDv0Info::GetV0PID(Int_t ipart, AliTRDtrackInfo *track) : No track info found.\n"); + return 0; + } + + AliESDInputHandler *esdH = dynamic_cast(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()); + if(!esdH) + { + AliError("AliTRDv0Info::GetV0PID(Int_t ipart, AliTRDtrackInfo *track) : ERROR - ESD input handler not found"); + return 0; + } + + + fESD = esdH->GetEvent(); + + for(Int_t ivertex=0; ivertexGetNumberOfV0s(); ivertex++) + { + + if(pid == 0) + { + V0fromTrack(track, ivertex);//Get the V0 corresponding to the track (if there is a V0) + + if(fV0Momentum > 2.5)//divide into slots according to reconstructed momentum of the mother particle + {iPSlot = 1;} + else + {iPSlot = 0;} + //Accept track for a sample only if... + + if(!(fHasV0))//... there is a V0 found for it + continue; + if(!(fQuality == 1))//... it fulfills our quality criteria + continue; + if(!(fDCA < fUpDCA[iDecay]))//... distance of closest approach between daughters is reasonably small + continue; + if(!(fPointingAngle < fUpPointingAngle[iDecay]))//... pointing angle between momentum of mother particle and vector from prim. to sec. vertex is small + continue; + if(!(fRadius > fDownRadius[iDecay]))//... x-y plane distance of decay point to prim. vertex is bigger than a certain minimum value (for conversions) + continue; + if(!(fOpenAngle < fUpOpenAngle[iDecay]))//... opening angle is close enough to zero (for conversions) + continue; + if(!(TMath::Abs(fPsiPair) < fUpPsiPair[iDecay]))//... Psi-pair angle is close enough to zero(for conversions) + continue; + + //specific cut criteria : + if(ipart == AliPID::kProton) + {//for proton sample: separate treatment of Lamba and Anti-Lambda decays: + //for Anti-Lambda: + //TPC PID likelihoods high enough for pi+ and anti-proton ; invariant mass calculated postulating these two particle species... + if((fDetPID[kNeg][kTPC][AliPID::kProton] > fDownTPCPIDneg[AliPID::kProton]) && (fDetPID[kPos][kTPC][AliPID::kPion] > fDownTPCPIDpos[AliPID::kPion])) + { + if(fNindex == fTrackID) + { + if((fInvMass[kAntiLambda] < fUpInvMass[kAntiLambda][iPSlot]) && (fInvMass[kAntiLambda] > fDownInvMass[kAntiLambda])) + { + pid = 1; + } + } + } + //for Lambda: + //TPC PID likelihoods high enough for pi- and proton ; invariant mass calculated accordingly + if((fDetPID[kNeg][kTPC][AliPID::kPion] > fDownTPCPIDneg[AliPID::kPion]) && (fDetPID[kPos][kTPC][AliPID::kProton] > fDownTPCPIDpos[AliPID::kProton])) + { + if(fPindex == fTrackID) + { + if((fInvMass[kLambda] < fUpInvMass[kLambda][iPSlot]) && (fInvMass[kLambda] > fDownInvMass[kLambda])) + { + pid = 1; + } + } + } + } + //for photon and K0s decays: equal TPC PID likelihood criteria for both daughters ; invariant mass calculated postulating two electrons/two pions + else + if((fDetPID[kNeg][kTPC][ipart] > fDownTPCPIDneg[ipart]) && (fDetPID[kPos][kTPC][ipart] > fDownTPCPIDpos[ipart])) + { + if((fInvMass[iDecay] < fUpInvMass[iDecay][iPSlot]) && (fInvMass[iDecay] > fDownInvMass[iDecay])) + { + pid = 1; + } + } + } + } + + return pid; + +} +//_________________________________________________ +void AliTRDv0Info::Print(Option_t */*opt*/) const +{ + +} diff --git a/PWG1/TRD/info/AliTRDv0Info.h b/PWG1/TRD/info/AliTRDv0Info.h new file mode 100644 index 00000000000..81738aaa124 --- /dev/null +++ b/PWG1/TRD/info/AliTRDv0Info.h @@ -0,0 +1,182 @@ +#ifndef ALITRDV0INFO_H +#define ALITRDV0INFO_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/* $Id: AliTRDv0Info.h 34132 2009-08-06 11:18:32Z cblume $ */ + +//////////////////////////////////////////////////////////////////////////// +// // +// Reconstruction QA // +// // +//////////////////////////////////////////////////////////////////////////// + +#ifndef Root_TObject +#include "TObject.h" +#endif + +#ifndef ALITRDGEOMETRY_H +#include "AliTRDgeometry.h" +#endif + +#ifndef ALIPID_H +#include "AliPID.h" +#endif + + +class AliESDv0; +class AliESDtrack; +class AliESDEvent; +class AliTRDtrackV1; +class AliTRDtrackInfo; +class AliTRDv0Info : public TObject +{ +public: + enum ETRDv0Info{ + kNV0param = 10 + ,kNlayer = AliTRDgeometry::kNlayer + ,kNDetectors = 3//TPC, TOF, ITS (TOF and ITS not implemented yet) + ,kNDaughters = 2//for positive and negative track + ,kNDecays = 4//number of decay types considered for reference data (conversions, K0s, Lambda, Anti-Lambda) + ,kNMomBins = 2//number of different momentum bins to consider for different cuts; first example: below/above 2.5 GeV -> to be refined! + }; + + enum EDaughter{ + kNeg = 0 + ,kPos = 1 + }; + + enum EDecayType{ + kGamma = 0 + ,kK0s = 1 + ,kLambda = 2 + ,kAntiLambda = 3 + }; + + enum EDetector{ + kTPC = 0 + ,kTOF = 1 + ,kITS = 2 + }; + + + AliTRDv0Info(); + virtual ~AliTRDv0Info(){} + +/* Float_t Pplus[2*kNlayer]; // Positives */ +/* Float_t Pminus[2*kNlayer]; // Negatives */ + + + void Print(Option_t *opt=0x0) const; + + Bool_t GetV0PID(Int_t ipart, AliTRDtrackInfo *track);//decides if a track is accepted for one of the reference samples!! + + //Set values of measured/calculated variables: + void SetQuality(Int_t SQuality){fQuality = SQuality;} + void SetPplus(Int_t iLayer, Float_t SPplus){fPplus[iLayer] = SPplus;} + void SetPminus(Int_t iLayer, Float_t SPminus){fPminus[iLayer] = SPminus;} + void SetDCA(Float_t SDCA){fDCA = SDCA;} + void SetMomentum(Float_t SMomentum){fMomentum = SMomentum;} + void SetPointingAngle(Float_t SPointingAngle){fPointingAngle = SPointingAngle;} + void SetOpenAngle(Float_t SOpenAngle){fOpenAngle = SOpenAngle;} + void SetPsiPair(Float_t SPsiPair){fPsiPair = SPsiPair;} + void SetRadius(Float_t SRadius){fRadius = SRadius;} + void SetInvMass(Int_t iDecay, Float_t SInvMass){fInvMass[iDecay] = SInvMass;} + void SetDetPID(Int_t iDaughter, Int_t iDetector, Int_t iSpecies, Float_t SDetPID){fDetPID[iDaughter][iDetector][iSpecies] = SDetPID;} + +//____________________________________________________________ + //Set cut values: + + void SetUpDCA(Int_t iDecay, Float_t UpDCA){fUpDCA[iDecay] = UpDCA;} + void SetUpPointingAngle(Int_t iDecay, Float_t UpPointingAngle){fUpPointingAngle[iDecay] = UpPointingAngle;} + void SetUpOpenAngle(Int_t iDecay, Float_t UpOpenAngle){fUpOpenAngle[iDecay] = UpOpenAngle;} + void SetDownOpenAngle(Int_t iDecay, Float_t DownOpenAngle){fDownOpenAngle[iDecay] = DownOpenAngle;} + void SetUpPsiPair(Int_t iDecay, Float_t UpPsiPair){fUpPsiPair[iDecay] = UpPsiPair;} + void SetDownPsiPair(Int_t iDecay, Float_t DownPsiPair){fDownPsiPair[iDecay] = DownPsiPair;} + void SetUpRadius(Int_t iDecay, Float_t UpRadius){fUpRadius[iDecay] = UpRadius;} + void SetDownRadius(Int_t iDecay, Float_t DownRadius){fDownRadius[iDecay] = DownRadius;} + void SetUpInvMass(Int_t iDecay, Int_t iMomentum, Double_t UpInvMass){fUpInvMass[iDecay][iMomentum] = UpInvMass;} + void SetDownInvMass(Int_t iDecay, Double_t DownInvMass){fDownInvMass[iDecay] = DownInvMass;} + void SetDownTPCPIDneg(Int_t iDecay, Double_t DownTPCPIDneg){fDownTPCPIDneg[iDecay] = DownTPCPIDneg;} + void SetDownTPCPIDpos(Int_t iDecay, Double_t DownTPCPIDpos){fDownTPCPIDpos[iDecay] = DownTPCPIDpos;} + + + +private: + AliTRDv0Info(const AliTRDv0Info&); + AliTRDv0Info& operator=(const AliTRDv0Info&); + + void GetESDv0Info(AliESDv0 *esdv0);//gets most of the variables below + void GetDetectorPID();//operating with likelihood values of different detectors + Int_t Quality(AliESDv0 * const esdv0);//checks for track/vertex quality criteria + Double_t InvMass(Int_t part1, Int_t part2, AliESDv0 *esdv0) const;//invariant mass of mother + Float_t PsiPair(AliESDv0 *esdv0);//angle between daughters in plane perpendicular to magnetic field (characteristically around zero for conversions) + Float_t OpenAngle(AliESDv0 *esdv0);//opening angle between V0 daughters; close to zero for conversions + Float_t Radius(AliESDv0 *esdv0);//distance of secondary to primary vertex in x-y-plane + Float_t DCA() const {return fDCA;}//distance of closest approach between supposed daughter tracks + Float_t PointingAngle() const {return fPointingAngle;}//pointing angle: between vector from primary to secondary vertex and reconstructed momentum of V0 mother particle + Float_t V0Momentum(AliESDv0 *esdv0) const;//reconstructed momentum of V0 mother particle + void V0fromTrack(AliTRDtrackInfo * const track, Int_t ivertex);//checks if a track belongs to a vertex found by V0 finder + + AliESDEvent *fESD; // ESD event + + Bool_t fHasV0; //Does this track belong to a vertex from a V0 finder? + + Int_t fQuality; // track quality status for both V0 daughters; OnFly, TPCrefit, Kinks, TPC clusters + + Float_t fPplus[2*kNlayer]; // momentum and variance for the positive daughter + Float_t fPminus[2*kNlayer]; // momentum and variance for the negative daughter + Double_t fDetPID[kNDaughters][kNDetectors][AliPID::kSPECIES]; // PID provided by TPC, TOF and ITS + + Float_t fMomentum; // Momentum of track at the vertex + + Float_t fDCA; // Distance of closest approach of daughter tracks + + Float_t fPointingAngle;// = TMath::ACos(esdv0->GetV0CosineOfPointingAngle()); // Cosine of pointing angle + + Float_t fOpenAngle; // opening angle between daughters + + Float_t fPsiPair; // /Angle between daughter momentum plane and plane perpendicular to magnetic field + + Double_t fInvMass[kNDecays]; // invariant mass for different decay scenarios (conversions, K0s, Lambda->p+pi-, Lambda->p-pi+) + + Double_t fMagField; //magnetic field strength + + Float_t fRadius; //distance of decay/conversion from primary vertex in x-y plane + + Int_t fTrackID;//track index + + + Float_t fV0Momentum; //V0 mother's momentum + + //____________________________________________________________ + //Upper and lower limits for cut variables: + + Float_t fUpDCA[kNDecays]; // DCA, upper limit + Float_t fUpPointingAngle[kNDecays]; // pointing angle, upper limit + Float_t fUpOpenAngle[kNDecays]; // opening angle, upper limit + Float_t fDownOpenAngle[kNDecays]; // opening angle, lower limit + Float_t fUpPsiPair[kNDecays]; // psi angle, upper limit + Float_t fDownPsiPair[kNDecays]; // psi angle, lower limit + Double_t fUpInvMass[kNDecays][kNMomBins]; // invariant mass, upper limit + Double_t fDownInvMass[kNDecays]; // invariant mass, lower limit + Float_t fUpRadius[kNDecays]; // radius, upper limit + Float_t fDownRadius[kNDecays]; // radius, lower limit + Float_t fDownTPCPIDneg[AliPID::kSPECIES]; // TPC PID negatives, lower limit + Float_t fDownTPCPIDpos[AliPID::kSPECIES]; // TPC PID positives, lower limit + + AliESDtrack *fTrackP; //positive daughter + AliESDtrack *fTrackN; //negative daughter + AliESDtrack *fTrack; //the current track in the ESDtrack loop (either positive or negative) + + + Int_t fNindex; //indices of positive and negative daughter track + Int_t fPindex; //indices of positive and negative daughter track + + + ClassDef(AliTRDv0Info, 0) // extracted V0 MC information +}; + + +#endif + diff --git a/PWG1/TRD/info/Makefile b/PWG1/TRD/info/Makefile new file mode 100644 index 00000000000..e4da831d84a --- /dev/null +++ b/PWG1/TRD/info/Makefile @@ -0,0 +1,68 @@ +SrcSuf = cxx +HdrSuf = h +ExeSuf = +ObjSuf = o +DllSuf = so +OutPutOpt = -o + +CXX = g++ +LD = g++ +CXXFLAGS = -O -fPIC +LDFLAGS = -O -fPIC +SOFLAGS = -shared + +ROOTCXX = $(shell root-config --cflags) +ROOTLIBS = $(shell root-config --libs) + +ALICXX = -I$(ALICE_ROOT)/include -I$(ALICE_ROOT)/TRD + +CXXFLAGS += $(ROOTCXX) $(ALICXX) + +# define module specific variables +FILE_LIST = $(shell ls -1 ./*.$(SrcSuf)) +FILES = $(basename $(FILE_LIST)) +DICTIONARIES = trdTrackInfoDict +OBJECTS = $(addsuffix .$(ObjSuf),$(FILES)) +OBJECTS += ./$(DICTIONARIES).$(ObjSuf) + +#define headers +HDRS = $(addsuffix .$(HdrSuf),$(FILES)) +HEADERS = $(notdir $(HDRS)) + +# define libs on which the main lib depends ! (this are defined in config/Makefile.flags) +LIBSDEPEND = $(ROOTLIBS) $(ALILIBS) +# define libs build by module +LIBS = libTRDtrackInfo.so + + +# rule for building executables +$(EXECS): $(OBJECTS) + @echo -e "\E[31mBuild executable: \E[1;31m$@\E[0m" + @$(LD) $(LIBSDEPEND) $^ -o $@ + +# rule for building libraries +%.$(DllSuf): $(OBJECTS) + @echo -e "\E[31mBuild library: \E[1;31m$@\E[0m" + @$(LD) $(SOFLAGS) $(LIBSDEPEND) $^ -o $@ + +# rule for building objects +%.$(ObjSuf): %.$(SrcSuf) + @echo -e "\E[31mCompile : \E[1;31m$^\E[0m" + @$(CXX) $(CXXFLAGS) -c $< -o $@ + +#rule for building dictionary +%Dict.$(SrcSuf): %LinkDef.h + @echo -e "\E[31mGenerate dictionary : \E[1;31m$@\E[0m" + @rootcint -f $@ -c $(CXXFLAGS) $(HEADERS) $^ + +all: $(OBJECTS) $(LIBS) $(EXECS) + +clean: + @rm -fv $(DICTIONARIES) + @rm -fv $(OBJECTS) + @rm -fv $(LIBS) + @rm -fv $(EXECS) + @if [ "$(LIBS)" != "" ]; then rm -fv lib/$(LIBS); fi + @if [ "$(EXECS)" != "" ]; then rm -fv bin/$(EXECS); fi + + diff --git a/PWG1/TRD/info/trdTrackInfoLinkDef.h b/PWG1/TRD/info/trdTrackInfoLinkDef.h new file mode 100644 index 00000000000..f1043590c2a --- /dev/null +++ b/PWG1/TRD/info/trdTrackInfoLinkDef.h @@ -0,0 +1,9 @@ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class AliTRDtrackInfo+; + +#endif diff --git a/PWG1/TRD/macros/AddTRDcheckDET.C b/PWG1/TRD/macros/AddTRDcheckDET.C new file mode 100644 index 00000000000..720783e58ef --- /dev/null +++ b/PWG1/TRD/macros/AddTRDcheckDET.C @@ -0,0 +1,47 @@ +#if ! defined (__CINT__) || defined (__MAKECINT__) +#include "AliAnalysisManager.h" +#include "AliAnalysisDataContainer.h" +#include "TRD/qaRec/macros/AliTRDperformanceTrain.h" +#include "TRD/qaRec/AliTRDcheckDET.h" +#include "TRD/qaRec/AliTRDcalibration.h" +#endif + +#include "TRD/qaRec/macros/helper.C" +void AddTRDcheckDET(AliAnalysisManager *mgr, Char_t *trd, AliAnalysisDataContainer **ci/*, AliAnalysisDataContainer **co*/) +{ + Int_t map = ParseOptions(trd); + if(!(TSTBIT(map, kCheckDET))) return; + + AliTRDcheckDET *task = 0x0; + mgr->AddTask(task = new AliTRDcheckDET()); + task->SetDebugLevel(0); + task->SetMCdata(mgr->GetMCtruthEventHandler()); + + // Create containers for input/output + mgr->ConnectInput( task, 0, ci[0]); + mgr->ConnectInput( task, 1, ci[1]); + mgr->ConnectOutput(task, 0, mgr->CreateContainer(task->GetName(), TObjArray::Class(), AliAnalysisManager::kOutputContainer, "TRD.Performance.root")); + + + // CALIBRATION + if(!(TSTBIT(map, kCalibration))) return; + AliTRDcalibration *ctask = 0x0; + mgr->AddTask(ctask = new AliTRDcalibration()); + ctask->SetHisto2d(kTRUE); + ctask->SetVector2d(kTRUE); + ctask->SetVdriftLinear(kTRUE); + ctask->SetNz(0,0); + ctask->SetNrphi(0,0); + ctask->SetNz(0,1); + ctask->SetNrphi(0,1); + ctask->SetNz(0,2); + ctask->SetNrphi(0,2); + ctask->SetLow(0); + ctask->SetHigh(30); + ctask->SetFillZero(kFALSE); + ctask->SetDebugLevel(1); + + // Create containers for input/output + mgr->ConnectInput(ctask, 0, ci[0]); + mgr->ConnectOutput(ctask, 0, mgr->CreateContainer(ctask->GetName(), TObjArray::Class(), AliAnalysisManager::kOutputContainer, Form("TRD.Task%s.root", ctask->GetName()))); +} diff --git a/PWG1/TRD/macros/AddTRDcheckESD.C b/PWG1/TRD/macros/AddTRDcheckESD.C new file mode 100644 index 00000000000..b0b2d899b96 --- /dev/null +++ b/PWG1/TRD/macros/AddTRDcheckESD.C @@ -0,0 +1,14 @@ +#if ! defined (__CINT__) || defined (__MAKECINT__) +#include "AliAnalysisManager.h" +#include "AliAnalysisDataContainer.h" +#include "TRD/qaRec/AliTRDcheckESD.h" +#endif + +void AddTRDcheckESD(AliAnalysisManager *mgr) +{ + AliTRDcheckESD *checkESD = new AliTRDcheckESD(); + checkESD->SetMC(mgr->GetMCtruthEventHandler()); + mgr->AddTask(checkESD); + mgr->ConnectInput(checkESD, 0, mgr->GetCommonInputContainer()); mgr->ConnectOutput(checkESD, 0, mgr->CreateContainer(checkESD->GetName(), TObjArray::Class(), AliAnalysisManager::kOutputContainer, "TRD.Performance.root")); +} + diff --git a/PWG1/TRD/macros/AddTRDcheckPID.C b/PWG1/TRD/macros/AddTRDcheckPID.C new file mode 100644 index 00000000000..dc737c54256 --- /dev/null +++ b/PWG1/TRD/macros/AddTRDcheckPID.C @@ -0,0 +1,38 @@ +#if ! defined (__CINT__) || defined (__MAKECINT__) +#include "TTree.h" +#include "AliLog.h" +#include "AliAnalysisManager.h" +#include "AliAnalysisDataContainer.h" +#include "TRD/qaRec/macros/AliTRDperformanceTrain.h" +#include "TRD/qaRec/AliTRDcheckPID.h" +#include "TRD/qaRec/AliTRDpidRefMaker.h" +#endif + +#include "TRD/qaRec/macros/helper.C" +void AddTRDcheckPID(AliAnalysisManager *mgr, Char_t *trd, AliAnalysisDataContainer **ci/*, AliAnalysisDataContainer **co*/) +{ + Int_t map = ParseOptions(trd); + if(TSTBIT(map, kCheckPID)){ + AliTRDcheckPID *pid = 0x0; + mgr->AddTask(pid = new AliTRDcheckPID()); + pid->SetDebugLevel(0); + pid->SetMCdata(mgr->GetMCtruthEventHandler()); + mgr->ConnectInput(pid, 0, ci[0]); + mgr->ConnectOutput(pid, 0, mgr->CreateContainer(pid->GetName(), TObjArray::Class(), AliAnalysisManager::kOutputContainer, "TRD.Performance.root")); + } + + if(TSTBIT(map, kPIDRefMaker)){ + // TRD pid reference maker + AliTRDpidRefMaker *ref = new AliTRDpidRefMaker(); + mgr->AddTask(ref); + ref->SetDebugLevel(3); + AliLog::SetClassDebugLevel("AliTRDpidRefMaker", 3); + ref->SetMCdata(mgr->GetMCtruthEventHandler()); + ref->SetFriends(kTRUE); + mgr->ConnectInput( ref, 0, ci[0]); + mgr->ConnectInput( ref, 1, ci[2]); + mgr->ConnectOutput(ref, 0, mgr->CreateContainer(Form("Moni%s", ref->GetName()), TObjArray::Class(), AliAnalysisManager::kOutputContainer, Form("TRD.Calib%s.root", ref->GetName()))); + mgr->ConnectOutput(ref, 1, mgr->CreateContainer(ref->GetName(), TTree::Class(), AliAnalysisManager::kOutputContainer, Form("TRD.Calib%s.root", ref->GetName()))); + } +} + diff --git a/PWG1/TRD/macros/AddTRDefficiency.C b/PWG1/TRD/macros/AddTRDefficiency.C new file mode 100644 index 00000000000..6064653b5a5 --- /dev/null +++ b/PWG1/TRD/macros/AddTRDefficiency.C @@ -0,0 +1,44 @@ +#if ! defined (__CINT__) || defined (__MAKECINT__) +#include "AliAnalysisManager.h" +#include "AliAnalysisDataContainer.h" +#include "TRD/qaRec/macros/AliTRDperformanceTrain.h" +#include "TRD/qaRec/AliTRDefficiency.h" +#include "TRD/qaRec/AliTRDefficiencyMC.h" +#include "TRD/qaRec/AliTRDmultiplicity.h" +#endif + +#include "TRD/qaRec/macros/helper.C" +void AddTRDefficiency(AliAnalysisManager *mgr, Char_t *trd, AliAnalysisDataContainer **ci/*, AliAnalysisDataContainer **co*/) +{ + Int_t map = ParseOptions(trd); + if(!(TSTBIT(map, kEfficiency))) return; + + Bool_t mc = mgr->GetMCtruthEventHandler(); + AliTRDefficiency *eff = 0x0; + mgr->AddTask(eff = new AliTRDefficiency()); + eff->SetDebugLevel(0); + mgr->ConnectInput(eff, 0, ci[0]); + mgr->ConnectOutput(eff, 0, mgr->CreateContainer(eff->GetName(), TObjArray::Class(), AliAnalysisManager::kOutputContainer, "TRD.Performance.root")); + + + // TRD combined tracking efficiency + AliTRDefficiencyMC *effMC = 0x0; + if(mc && TSTBIT(map, kEfficiencyMC)){ + mgr->AddTask(effMC = new AliTRDefficiencyMC()); + effMC->SetDebugLevel(0); + + // Create containers for input/output + mgr->ConnectInput(effMC, 0, ci[0]); + mgr->ConnectOutput(effMC, 0, mgr->CreateContainer(effMC->GetName(), TObjArray::Class(), AliAnalysisManager::kOutputContainer, Form("TRD.Task%s.root", effMC->GetName()))); + } + + // TRD single track selection + if(!(TSTBIT(map, kMultiplicity))) return; + + AliTRDmultiplicity *mult = 0x0; + mgr->AddTask(mult = new AliTRDmultiplicity()); + mult->SetDebugLevel(0); + mgr->ConnectInput(mult, 0, ci[0]); + mgr->ConnectOutput(mult, 0, mgr->CreateContainer(mult->GetName(), TObjArray::Class(), AliAnalysisManager::kOutputContainer, Form("TRD.Task%s.root", mult->GetName()))); +} + diff --git a/PWG1/TRD/macros/AddTRDinfoGen.C b/PWG1/TRD/macros/AddTRDinfoGen.C new file mode 100644 index 00000000000..5d52275b65a --- /dev/null +++ b/PWG1/TRD/macros/AddTRDinfoGen.C @@ -0,0 +1,27 @@ +#if ! defined (__CINT__) || defined (__MAKECINT__) +#include "AliAnalysisManager.h" +#include "AliAnalysisDataContainer.h" +#include "TRD/qaRec/AliTRDinfoGen.h" +#include "TRD/qaRec/info/AliTRDeventInfo.h" +#include "TRD/qaRec/macros/AliTRDperformanceTrain.h" +#endif + +#include "TRD/qaRec/macros/helper.C" +void AddTRDinfoGen(AliAnalysisManager *mgr, Char_t *trd, AliAnalysisDataContainer **/*ci*/, AliAnalysisDataContainer **co) +{ + Int_t map = ParseOptions(trd); + if(!(TSTBIT(map, kInfoGen))) return; + + AliTRDinfoGen *info = 0x0; + mgr->AddTask(info = new AliTRDinfoGen()); + info->SetDebugLevel(0); + info->SetMCdata(mgr->GetMCtruthEventHandler()); + mgr->ConnectInput( info, 0, mgr->GetCommonInputContainer()); + co[0] = mgr->CreateContainer("trackInfo", TObjArray::Class(), AliAnalysisManager::kExchangeContainer); + co[1] = mgr->CreateContainer("eventInfo", AliTRDeventInfo::Class(), AliAnalysisManager::kExchangeContainer); + co[2] = mgr->CreateContainer("v0Info", TObjArray::Class(), AliAnalysisManager::kExchangeContainer); + mgr->ConnectOutput(info, 0, co[0]); + mgr->ConnectOutput(info, 1, co[1]); + mgr->ConnectOutput(info, 2, co[2]); +} + diff --git a/PWG1/TRD/macros/AddTRDresolution.C b/PWG1/TRD/macros/AddTRDresolution.C new file mode 100644 index 00000000000..24f3698bfb0 --- /dev/null +++ b/PWG1/TRD/macros/AddTRDresolution.C @@ -0,0 +1,57 @@ +#if ! defined (__CINT__) || defined (__MAKECINT__) +#include "TTree.h" +#include "AliAnalysisManager.h" +#include "AliAnalysisDataContainer.h" +#include "TRD/qaRec/macros/AliTRDperformanceTrain.h" +#include "TRD/qaRec/AliTRDresolution.h" +#include "TRD/qaRec/AliTRDclusterResolution.h" +#include "TRD/qaRec/AliTRDalignmentTask.h" +#endif + +#include "TRD/qaRec/macros/helper.C" +void AddTRDresolution(AliAnalysisManager *mgr, Char_t *trd, AliAnalysisDataContainer **ci/*, AliAnalysisDataContainer **co*/) +{ + Int_t map = ParseOptions(trd); + AliTRDresolution *task = 0x0; + if(!TSTBIT(map, kResolution)) return; + mgr->AddTask(task = new AliTRDresolution()); + task->SetMCdata(mgr->GetMCtruthEventHandler()); + task->SetPostProcess(kFALSE); + task->SetDebugLevel(1); + mgr->ConnectInput( task, 0, ci[0]); + mgr->ConnectOutput(task, 0, mgr->CreateContainer(task->GetName(), TObjArray::Class(), AliAnalysisManager::kOutputContainer, "TRD.Performance.root")); + + // Create output containers for calibration tasks + const Int_t nc = 4; + const Char_t *cn[nc] = {"Cl", "Trklt", "MC_Cl", "MC_Trklt"}; + AliAnalysisDataContainer *co[] = {0x0, 0x0, 0x0, 0x0}; + for(Int_t ic = 0; icCreateContainer(Form("%s%s", task->GetName(), cn[ic]), TObjArray::Class(), AliAnalysisManager::kExchangeContainer); + mgr->ConnectOutput(task, 1+ic, co[ic]); + } + + // Cluster Error Parameterization + if(TSTBIT(map, kClErrParam)){ + AliTRDclusterResolution *taskCl = 0x0; + mgr->AddTask(taskCl = new AliTRDclusterResolution("ESD", "ESD Cluster error parameterization")); + taskCl->SetExB(); + mgr->ConnectInput(taskCl, 0, co[0]); + mgr->ConnectOutput(taskCl, 0, mgr->CreateContainer(taskCl->GetName(), TObjArray::Class(), AliAnalysisManager::kOutputContainer, "TRD.CalibClErrParam.root")); + + mgr->AddTask(taskCl = new AliTRDclusterResolution("MC", "MC Cluster error parameterization")); + taskCl->SetExB(); + mgr->ConnectInput(taskCl, 0, co[2]); + mgr->ConnectOutput(taskCl, 0, mgr->CreateContainer(taskCl->GetName(), TObjArray::Class(), AliAnalysisManager::kOutputContainer, "TRD.CalibClErrParam.root")); + } + + // TRD alignment + if(TSTBIT(map, kAlignment)){ + AliTRDalignmentTask *taskAl = 0x0; + mgr->AddTask(taskAl = new AliTRDalignmentTask()); + taskAl->SetDebugLevel(0); + mgr->ConnectInput(taskAl, 0, ci[0]); + mgr->ConnectOutput(taskAl, 0, mgr->CreateContainer(Form("h%s", taskAl->GetName()), TObjArray::Class(), AliAnalysisManager::kExchangeContainer)); + mgr->ConnectOutput(taskAl, 1, mgr->CreateContainer(task->GetName(), TTree::Class(), AliAnalysisManager::kOutputContainer, Form("TRD.Calib%s.root", task->GetName()))); + } +} + diff --git a/PWG1/TRD/macros/AliTRDperformanceTrain.h b/PWG1/TRD/macros/AliTRDperformanceTrain.h new file mode 100644 index 00000000000..e0f3ede6311 --- /dev/null +++ b/PWG1/TRD/macros/AliTRDperformanceTrain.h @@ -0,0 +1,81 @@ +#ifndef ALITRDPERFORMANCETRAIN_H +#define ALITRDPERFORMANCETRAIN_H + +#define BITBIT(n) (1 << (n)) +#define SETBITT(n,i) ((n) |= BITBIT(i)) +#define TSTBIT(n,i) ((Bool_t)(((n) & BITBIT(i)) != 0)) +#define CLRBITT(n,i) ((n) &= ~BITBIT(i)) + +#define NTRDQATASKS 6 +#define NTRDCALIBTASKS 6 +/* #define NTRDCALIBTASKS 7 */ +const Int_t NTRDTASKS = NTRDQATASKS+NTRDCALIBTASKS; + +enum AliTRDrecoTasks{ + kCheckESD = 0 + ,kInfoGen = 1 + ,kCheckDET = 2 + ,kEfficiency = 3 + ,kResolution = 4 + ,kCheckPID = 5 + ,kCalibration = 6 + ,kEfficiencyMC = 7 + ,kAlignment = 8 + ,kPIDRefMaker = 9 +/* ,kPIDRefMakerLQ = 9 */ +/* ,kPIDRefMakerNN =10 */ +/* ,kClErrParam =11 */ +/* ,kMultiplicity =12 */ + ,kClErrParam =10 + ,kMultiplicity =11 +}; + +const Char_t* fgkTRDtaskClassName[NTRDTASKS] = { + "AliTRDcheckESD" + ,"AliTRDinfoGen" + ,"AliTRDcheckDET" + ,"AliTRDefficiency" + ,"AliTRDresolution" + ,"AliTRDcheckPID" + ,"AliTRDcalibration" + ,"AliTRDefficiencyMC" + ,"AliTRDalignmentTask" + ,"AliTRDpidRefMaker" +/* ,"AliTRDpidRefMakerLQ" */ +/* ,"AliTRDpidRefMakerNN" */ + ,"AliTRDclusterResolution" + ,"AliTRDmultiplicity" +}; + +const Char_t *fgkTRDtaskOpt[NTRDTASKS+1] = { + "" + ,"GEN" + ,"DET" + ,"EFF" + ,"RES" + ,"PID" + ,"CAL" + ,"EFFC" + ,"ALGN" + ,"PIDR" +/* ,"LQR" */ +/* ,"NNR" */ + ,"CLRES" + ,"MULT" + ,"ALL" +}; + +#include + +//____________________________________________ +Bool_t HasReadMCData(Char_t *opt){ + return !(Bool_t)strstr(opt, "NOMC"); +} + +//____________________________________________ +Bool_t HasReadFriendData(Char_t *opt){ + return !(Bool_t)strstr(opt, "NOFR"); +} + +#endif + diff --git a/PWG1/TRD/macros/AliTrackletsinTRD.C b/PWG1/TRD/macros/AliTrackletsinTRD.C new file mode 100644 index 00000000000..dc63df4182b --- /dev/null +++ b/PWG1/TRD/macros/AliTrackletsinTRD.C @@ -0,0 +1,214 @@ +/************************************************************************** + * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * * + * Author: The ALICE Off-line Project. * + * Contributors are mentioned in the code where appropriate. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +//////////////////////////////////////////////////////////////////////////// +// // +// Reconstruction QA // +// // +// Authors: Yvonne C. Pachmayer // +// // +//////////////////////////////////////////////////////////////////////////// + + +#define AliTrackletsinTRD_cxx +#include "AliTrackletsinTRD.h" +#include +#include +#include + +void AliTrackletsinTRD::Loop() +{ + // In a ROOT session, you can do: + // Root > .L AliTrackletsinTRD.C + // Root > AliTrackletsinTRD t + // Root > t.GetEntry(12); // Fill t data members with entry number 12 + // Root > t.Show(); // Show values of entry 12 + // Root > t.Show(16); // Read and show values of entry 16 + // Root > t.Loop(); // Loop on all entries + // + + // This is the loop skeleton where: + // jentry is the global entry number in the chain + // ientry is the entry number in the current Tree + // Note that the argument to GetEntry must be: + // jentry for TChain::GetEntry + // ientry for TTree::GetEntry and TBranch::GetEntry + // + // To read only selected branches, Insert statements like: + // METHOD1: + // fChain->SetBranchStatus("*",0); // disable all branches + // fChain->SetBranchStatus("branchname",1); // activate branchname + // METHOD2: replace line + // fChain->GetEntry(jentry); //read all branches + //by b_branchname->GetEntry(ientry); //read only this branch + + gROOT->SetStyle("Plain"); + gStyle->SetPalette(1); + + + if (fChain == 0) return; + + // open run loader and load gAlice, kinematics and header + AliRunLoader* runLoader = AliRunLoader::Open("galice.root"); + if (!runLoader) + { + printf("Error: readKine:\nGetting run loader from file \"%s\" failed", filename); + return; + } + + runLoader->LoadHeader(); + runLoader->LoadRecPoints("TRD"); + TObjArray *module = new TObjArray(); + + runLoader->CdGAFile(); + + Int_t nEvents = runLoader->GetNumberOfEvents(); + const Int_t nEventsarray=nEvents; + AliTRDcluster *cls = 0; + + Double_t x_clus[540][90]; + Double_t y_clus[540][90]; + + for(Int_t ev = 0; ev < nEvents - 1; ev++) + { + TTree *tree = runLoader->GetTreeR("TRD", 0); + tree->SetBranchAddress("TRDcluster", &module); + + int N = tree->GetEntries(); // number of chamber, max 540 + // Check number of clusters + for(Int_t ind = 0; ind < N; ind++) + { + tree->GetEntry(ind); + Int_t m = module->GetEntries(); + + for (Int_t j = 0; j < m; j++) // loop over clusters of one chamber + { + if(j>=90) break; + if (cls != 0) delete cls; + cls = (AliTRDcluster*)module->At(j); + x_clus[ind][j]=cls->GetX(); + y_clus[ind][j]=cls->GetY(); + + } + } + + + + // loop over debug file and analysis + + Float_t xbmin = 0., xbmax = 380.; + /* // histogram for debugging purpose + Int_t nxbins = 3000, nybins = 280; + Float_t ybmin = -70., ybmax = 70.; + hxy = new TH2F("hxy",";x;y",nxbins,xbmin,xbmax,nybins,ybmin,ybmax); + */ + + Long64_t nentries = fChain->GetEntriesFast(); + + Long64_t nbytes = 0, nb = 0; + Float_t xpos[6]; + Float_t ypos[6]; + Int_t counter_test; + for (Long64_t jentry=0; jentryGetEntry(jentry); nbytes += nb; + xpos[flayer]=fxtrack; + ypos[flayer]=fytrack; + + + if(flayer==5) + { + Float_t x[6]= {xpos[0],xpos[1],xpos[2],xpos[3],xpos[4],xpos[5]}; + Float_t y[6]= {ypos[0],ypos[1],ypos[2],ypos[3],ypos[4],ypos[5]}; + + gxy = new TGraph(6,x,y); + + TF1 *f1 = new TF1("f1","pol1",xbmin,xbmax); + gxy->Fit("f1","RQ"); + // resulting function: y=ax+b --> x*f1->GetParameter(1)+f1->GetParameter(0) + + // graph and fit plotting only for checking + /* + c1 = new TCanvas("c1","hough Transform",0,0,800,800); + c1->cd(1); + hxy->Draw(); + gxy->SetMarkerStyle(3); + gxy->Draw("p"); + */ + + Float_t px; + Float_t py; + + if(feventcounter==ev) + { + for(Int_t b=0;b<540;b++) + { + if(b==fdettracklet) + { + Int_t counter_distcalc; + Float_t distance_sum=0; + + for(Int_t c=0;c<90;c++) + { + px=0; + py=0; + + px=x_clus[b][c]; + py=y_clus[b][c]; + + if(px!=0 && py!=0) + { + // Function to calculate the distance of a point to the above fitted function + Double_t distance = 0; + if((TMath::Sqrt(f1->GetParameter(1)*f1->GetParameter(1)+1))!=0) distance=TMath::Abs(f1->GetParameter(1)*px-py+f1->GetParameter(0))/(TMath::Sqrt(f1->GetParameter(1)*f1->GetParameter(1)+1)); + // if(distance<10) cout << eventcounter << " " << b << " " << c << " " << distance << endl; + if(distance>0.6 && distance<=2) + { + counter_distcalc++; + distance_sum+=distance; + } + } + + } + if(counter_distcalc!=0) + { + // these are tracks which have additional clusters close by: 0.6 < distance <= 2 + } + else + { + // these are good tracks no additional clusters close by + cout <<" good tracks " << endl; + } + counter_distcalc=0; + } + } + } + + if(gxy) delete gxy; + if(f1) delete f1; + } // end of 5 layer loop + + + + + + } // end loop over debug file and analysis + + runLoader->GetNextEvent(); + } + +} + \ No newline at end of file diff --git a/PWG1/TRD/macros/AliTrackletsinTRD.h b/PWG1/TRD/macros/AliTrackletsinTRD.h new file mode 100644 index 00000000000..1e082f959d9 --- /dev/null +++ b/PWG1/TRD/macros/AliTrackletsinTRD.h @@ -0,0 +1,174 @@ +////////////////////////////////////////////////////////// +// This class has been automatically generated on +// Fri Mar 20 09:42:44 2009 by ROOT version 5.21/01 +// from TTree AliTrackletsinTRD/AliTrackletsinTRD +// found on file: TRD.DebugTrackingMultiplicity.root +////////////////////////////////////////////////////////// + +#ifndef ALITRACKLETSINTRD_h +#define ALITRACKLETSINTRD_h + +#include +#include +#include + +class AliTrackletsinTRD { +public : + TTree *fChain; //!pointer to the analyzed TTree or TChain + Int_t fCurrent; //!current Tree number in a TChain + + // Declaration of leaf types + Int_t fstandalone; //!flag is track reconstructed in TPC only or TPC+TRD + Int_t feventcounter; //!event number + Int_t flayer; //!layer number + Float_t fxtracklet; //!x position of tracklet + Double_t fxtrack; //!x position of track + Float_t fytracklet; //!y position of tracklet + Double_t fytrack; //!y position of track + Float_t fztracklet; //!z position of tracklet + Double_t fztrack; //!z position of track + Int_t fnumtracklets; //!number of tracklets + Int_t fdettracklet; //!detector number + + // List of branches + TBranch *fbB0; //! + TBranch *fbB1; //! + TBranch *fbB2; //! + TBranch *fbB3; //! + TBranch *fbB4; //! + TBranch *fbB5; //! + TBranch *fbB6; //! + TBranch *fbB7; //! + TBranch *fbB8; //! + TBranch *fbB9; //! + TBranch *fbB10; //! + + AliTrackletsinTRD(TTree *tree=0); + virtual ~AliTrackletsinTRD(); + virtual Int_t Cut(Long64_t entry); + virtual Int_t GetEntry(Long64_t entry); + virtual Long64_t LoadTree(Long64_t entry); + virtual void Init(TTree *tree); + virtual void Loop(); + virtual Bool_t Notify(); + virtual void Show(Long64_t entry = -1); + + + AliTrackletsinTRD (AliTrackletsinTRD& p): + fChain(p.fChain), + fbB0(p.fbB0), + fbB1(p.fbB1), + fbB2(p.fbB2), + fbB3(p.fbB3), + fbB4(p.fbB4), + fbB5(p.fbB5), + fbB6(p.fbB6), + fbB7(p.fbB7), + fbB8(p.fbB8), + fbB9(p.fbB9), + fbB10(p.fbB10) + { + } + +}; + + + +AliTrackletsinTRD::AliTrackletsinTRD(TTree *tree) +{ +// if parameter tree is not specified (or zero), connect the file +// used to generate this class and read the Tree. + if (tree == 0) { + TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject("/alidata80/alice_u/pachmay/AliRoot/v4-16-Rev-01/TRD/qaRec/TRD.DebugTrackingMultiplicity.root"); + if (!f) { + f = new TFile("/alidata80/alice_u/pachmay/AliRoot/v4-16-Rev-01/TRD/qaRec/TRD.DebugTrackingMultiplicity.root"); + } + tree = (TTree*)gDirectory->Get("TrackletsinTRD"); + + } + Init(tree); +} + +AliTrackletsinTRD::~AliTrackletsinTRD() +{ + if (!fChain) return; + delete fChain->GetCurrentFile(); +} + +Int_t AliTrackletsinTRD::GetEntry(Long64_t entry) +{ +// Read contents of entry. + if (!fChain) return 0; + return fChain->GetEntry(entry); +} +Long64_t AliTrackletsinTRD::LoadTree(Long64_t entry) +{ +// Set the environment to read one entry + if (!fChain) return -5; + Long64_t centry = fChain->LoadTree(entry); + if (centry < 0) return centry; + if (!fChain->InheritsFrom(TChain::Class())) return centry; + TChain *chain = (TChain*)fChain; + if (chain->GetTreeNumber() != fCurrent) { + fCurrent = chain->GetTreeNumber(); + Notify(); + } + return centry; +} + +void AliTrackletsinTRD::Init(TTree *tree) +{ + // The Init() function is called when the selector needs to initialize + // a new tree or chain. Typically here the branch addresses and branch + // pointers of the tree will be set. + // It is normally not necessary to make changes to the generated + // code, but the routine can be extended by the user if needed. + // Init() will be called many times when running on PROOF + // (once per file to be processed). + + // Set branch addresses and branch pointers + if (!tree) return; + fChain = tree; + fCurrent = -1; + fChain->SetMakeClass(1); + + fChain->SetBranchAddress("standalone", &fstandalone, &fbB0); + fChain->SetBranchAddress("eventcounter", &feventcounter, &fbB1); + fChain->SetBranchAddress("layer", &flayer, &fbB2); + fChain->SetBranchAddress("xtracklet", &fxtracklet, &fbB3); + fChain->SetBranchAddress("xtrack", &fxtrack, &fbB4); + fChain->SetBranchAddress("ytracklet", &fytracklet, &fbB5); + fChain->SetBranchAddress("ytrack", &fytrack, &fbB6); + fChain->SetBranchAddress("ztracklet", &fztracklet, &fbB7); + fChain->SetBranchAddress("ztrack", &fztrack, &fbB8); + fChain->SetBranchAddress("num_tracklets", &fnumtracklets, &fbB9); + fChain->SetBranchAddress("dettracklet", &fdettracklet, &fbB10); + Notify(); +} + +Bool_t AliTrackletsinTRD::Notify() +{ + // The Notify() function is called when a new file is opened. This + // can be either for a new TTree in a TChain or when when a new TTree + // is started when using PROOF. It is normally not necessary to make changes + // to the generated code, but the routine can be extended by the + // user if needed. The return value is currently not used. + + return kTRUE; +} + +void AliTrackletsinTRD::Show(Long64_t entry) +{ +// Print contents of entry. +// If entry is not specified, print current entry + if (!fChain) return; + fChain->Show(entry); +} +Int_t AliTrackletsinTRD::Cut(Long64_t entry) +{ +// This function may be called from Loop. +// returns 1 if entry is accepted. +// returns -1 otherwise. + return 1; +} +#endif // #ifdef AliTrackletsinTRD_cxx diff --git a/PWG1/TRD/macros/EVE/PH.C b/PWG1/TRD/macros/EVE/PH.C new file mode 100644 index 00000000000..4223e9cb760 --- /dev/null +++ b/PWG1/TRD/macros/EVE/PH.C @@ -0,0 +1,41 @@ +#if !defined(__CINT__) || defined(__MAKECINT__) +#include +#include + +#include +#include +#include +#include +#include +#endif + +TH1* PH(const AliTRDtrackV1* track) +{ + if (!track) return 0x0; + + AliTRDcluster* cls = 0; + AliTRDseedV1 *tracklet = 0x0; + + TProfile* ph = 0x0; + if(!(ph = (TProfile*)gROOT->FindObject("PH"))){ + Int_t ntb = AliTRDcalibDB::Instance()->GetNumberOfTimeBins(); + ph = new TProfile("PH", "Average PH", ntb, -.5, ntb-.5); + ph->GetXaxis()->SetTitle("drift time [1/100ns]"); + ph->GetYaxis()->SetTitle(" [a.u.]"); + } else ph->Reset(); + + + for (Int_t ily = 0; ily < AliTRDgeometry::kNlayer; ily++) { + if(!(tracklet = track->GetTracklet(ily))) continue; + if(!tracklet->IsOK()) continue; + + for (Int_t icl = 0; icl < AliTRDseed::knTimebins; icl++) { + if(!(cls = tracklet->GetClusters(icl))) continue; + + ph->Fill(cls->GetLocalTimeBin(), cls->GetQ()); + } + } + + return ph; +} + diff --git a/PWG1/TRD/macros/EVE/nclusters.C b/PWG1/TRD/macros/EVE/nclusters.C new file mode 100644 index 00000000000..eb7344a4c3e --- /dev/null +++ b/PWG1/TRD/macros/EVE/nclusters.C @@ -0,0 +1,16 @@ +#if !defined(__CINT__) || defined(__MAKECINT__) +#include +#include +#include +#endif + +void nclusters(const AliTRDtrackV1* track, Double_t* &res, Int_t& n) +{ + if (!track) return; + + n = 1; + res = new Double_t[n]; + res[0] = track->GetNumberOfClusters(); + return; +} + diff --git a/PWG1/TRD/macros/PID/ConvertMLPs.C b/PWG1/TRD/macros/PID/ConvertMLPs.C new file mode 100644 index 00000000000..b839cd12689 --- /dev/null +++ b/PWG1/TRD/macros/PID/ConvertMLPs.C @@ -0,0 +1,62 @@ +// This macro converts the networks that were saved by the AliTRDpidRefMaker to a root file (NN.root) +// which is readable by the AliTRDpidCDB.C macro to create the pid reference data bases. + +#ifndef __CINT__ +#include "TFile.h" +#include "TMultiLayerPerceptron.h" +#include "TEventList.h" +#include "TTree.h" +#include "TObject.h" + +#include "AliTRDgeometry.h" +#include "AliTRDpidUtil.h" +#include "Cal/AliTRDCalPID.h" +#endif + +Int_t ConvertMLPs(Int_t iDate = 20090129){ + + const Int_t nCha = AliTRDgeometry::kNlayer; + + TFile *fOut = new TFile("NN.root","RECREATE"); + + Float_t fv0pid[AliPID::kSPECIES], fdEdx[AliTRDpidUtil::kNNslices]; + + for(Int_t iMomBin = 0; iMomBin Get("NN"); + +// Create dummy TEventLists to load the weights of the TMultiLayerPerceptron + TEventList* lTrainData = new TEventList(); + TEventList* lTestData = new TEventList(); + lTrainData -> Enter(1); + lTestData -> Enter(1); + + tIn -> SetEventList(lTrainData); + tIn -> SetEventList(lTestData); + + Char_t structure[1024]; + + TMultiLayerPerceptron *mNet[nCha]; + + for(Int_t iCha = 0; iCha < nCha; iCha++){ + sprintf(structure,"fdEdx[0],fdEdx[1],fdEdx[2],fdEdx[3],fdEdx[4],fdEdx[5],fdEdx[6],fdEdx[7]:15:7:fv0pid[0],fv0pid[1],fv0pid[2],fv0pid[3],fv0pid[4]!"); + mNet[iCha] = new TMultiLayerPerceptron(structure,tIn,lTrainData,lTestData); + + printf("Network[%d] is ./%3.1fGeV/Network_%d/MomBin_%d/Net%d_49\n", iCha, AliTRDCalPID::GetMomentum(iMomBin), iDate, iMomBin, iCha); + mNet[iCha] -> LoadWeights(Form("./%3.1fGeV/Network_%d/MomBin_%d/Net%d_49", AliTRDCalPID::GetMomentum(iMomBin), iDate, iMomBin, iCha)); + } + + fOut -> cd(); + for(Int_t iCha = 0; iCha < AliTRDgeometry::kNlayer; iCha++){ + mNet[iCha] -> Write(Form("NN_Mom%d_Plane%d",iMomBin,iCha)); + } + } + + fOut -> Close(); + + return 1; + +} + diff --git a/PWG1/TRD/macros/PID/MonitorTraining.C b/PWG1/TRD/macros/PID/MonitorTraining.C new file mode 100644 index 00000000000..1d288eb554a --- /dev/null +++ b/PWG1/TRD/macros/PID/MonitorTraining.C @@ -0,0 +1,40 @@ +// This macro helps to decide if the training was successful and in addition +// if further training of the network is necessary. The shape of the training +// progress should have a first deep stall and reaching a plateau. After several +// training epochs the plateau will become a sloping line. If this slope results +// again in a flat plateau the training is probably done. +// The networks were saved using the date they were trained (yyyymmdd). +// +// Please enter the date of the network you want to monitor and the momentum bin.. +// Bin 0 = 0.6 GeV/c +// Bin 1 = 0.8 GeV/c +// Bin 2 = 1.0 GeV/c +// Bin 3 = 1.5 GeV/c +// Bin 4 = 2.0 GeV/c +// Bin 5 = 3.0 GeV/c +// Bin 6 = 4.0 GeV/c +// Bin 7 = 5.0 GeV/c +// Bin 8 = 6.0 GeV/c +// Bin 9 = 8.0 GeV/c +// Bin 10 = 10.0 GeV/c + +#ifndef __CINT__ +#include "TSystem.h" +#include "qaRec/AliTRDpidRefMaker.h" +#endif + +Int_t MonitorTraining(Int_t bin, Int_t Date){ + + gSystem -> Load("libANALYSIS.so"); + gSystem -> Load("libTRDqaRec.so"); + + AliTRDpidRefMaker *ref = new AliTRDpidRefMaker(); + ref->SetDebugLevel(2); + + ref->SetDate(Date); + ref->MakeTrainingLists(); + ref->MonitorTraining(bin); + + return 1; + +} diff --git a/PWG1/TRD/macros/PID/makeTrainingData.C b/PWG1/TRD/macros/PID/makeTrainingData.C new file mode 100644 index 00000000000..f7434a6e370 --- /dev/null +++ b/PWG1/TRD/macros/PID/makeTrainingData.C @@ -0,0 +1,153 @@ +// This macro splits the file created by the AliTRDpidRefMaker to smaller training +// samples according to the momentum of the track in order to increase the training +// speed for the TMultiLayerPerceptrons. +// The procedure is the following: +// 1. Create a directory where the training should take place +// 2. Copy the TRD.TaskPidRefMakerNN.root and the TRD.TaskPidRefMakerLQ.root in this directory. +// 3. Run makeTrainingDataNN(). This creates new directories: 0.6GeV, 0.8GeV, ..., 10.0GeV and +// create a subset of the training data according to the momentum. +// 4. Run makeDataLQ(). Does the same as make TraiingDataNN for the LQ data without the creation +// of the directories. +// 5. Run CreateDummy() to create a TRD.TaskPidRefMaker.root file. This is necessary for the +// monitoring of the training progress. +// 6. Go to the subdirectories and run the training. + +#ifndef __CINT__ +#include "TROOT.h" +#include "TSystem.h" +#include "TFile.h" +#include "TTree.h" +#include "TBranch.h" +#include "TObjArray.h" +#include "TGraphErrors.h" + +#include "AliPID.h" +#include "AliTRDpidUtil.h" +#include "Cal/AliTRDCalPID.h" +#include "qaRec/AliTRDpidRefMasker.h" +#endif + +Int_t makeTrainingDataNN(){ + + Int_t fLayer; + Float_t fMom, fv0pid[AliPID::kSPECIES], fdEdx[AliTRDpidUtil::kNNslices]; + + AliTRDpidUtil Util; + TFile *fIn = new TFile("../TRD.TaskPidRefMakerNN.root","READ"); + TTree *tIn = (TTree*) fIn -> Get("NN"); + + tIn -> SetBranchAddress("fLayer", &fLayer); + tIn -> SetBranchAddress("fMom", &fMom); + tIn -> SetBranchAddress("fv0pid", fv0pid); + tIn -> SetBranchAddress("fdEdx", fdEdx); + + for(Int_t iMomBin = 0; iMomBin < AliTRDCalPID::kNMom; iMomBin++){ + + gSystem->Exec(Form("mkdir -v ./%3.1fGeV",AliTRDCalPID::GetMomentum(iMomBin))); + + printf("Extracting training set for momentum bin %3.1f GeV/c\n", AliTRDCalPID::GetMomentum(iMomBin)); + TFile *fOut = new TFile(Form("./%3.1fGeV/TRD.TaskPidRefMakerNN.root",AliTRDCalPID::GetMomentum(iMomBin)),"RECREATE"); + TTree *tOut = new TTree("NN", "Reference data for NN"); + tOut -> Branch("fLayer", &fLayer, "fLayer/I"); + tOut -> Branch("fMom", &fMom, "fMom/F"); + tOut -> Branch("fv0pid", fv0pid, Form("fv0pid[%d]/F",AliPID::kSPECIES)); + tOut -> Branch("fdEdx", fdEdx, Form("fdEdx[%d]/F", AliTRDpidUtil::kNNslices)); + + for(Int_t iEv = 0; iEv < (tIn -> GetEntries()); iEv++){ + fLayer = 0; + fMom = 0.0; + for(Int_t i = 0; i < AliPID::kSPECIES; i++) fv0pid[i] = 0.0; + for(Int_t i = 0; i < AliTRDpidUtil::kNNslices; i++) fdEdx[i] = 0.0; + tIn -> GetEntry(iEv); + if(Util.GetMomentumBin(fMom) == iMomBin){ + tOut -> Fill(); + } + } + + tOut -> Write(); + tOut -> Delete(); + fOut -> Close(); + + } + + printf("Extraction completed!"); + return 1; + +} + + +Int_t makeDataLQ(){ + + Int_t fLayer; + Float_t fMom, fv0pid[AliPID::kSPECIES], fdEdx[AliTRDpidUtil::kLQslices]; + + AliTRDpidUtil Util; + TFile *fIn = new TFile("../TRD.TaskPidRefMakerLQ.root","READ"); + TTree *tIn = (TTree*) fIn -> Get("LQ"); + + tIn -> SetBranchAddress("fLayer", &fLayer); + tIn -> SetBranchAddress("fMom", &fMom); + tIn -> SetBranchAddress("fv0pid", fv0pid); + tIn -> SetBranchAddress("fdEdx", fdEdx); + + for(Int_t iMomBin = 0; iMomBin < AliTRDCalPID::kNMom; iMomBin++){ + printf("Extracting training set for momentum bin %3.1f GeV/c\n", AliTRDCalPID::GetMomentum(iMomBin)); + TFile *fOut = new TFile(Form("./%3.1fGeV/TRD.TaskPidRefMakerLQ.root",AliTRDCalPID::GetMomentum(iMomBin)),"RECREATE"); + TTree *tOut = new TTree("LQ", "Reference data for LQ"); + tOut -> Branch("fLayer", &fLayer, "fLayer/I"); + tOut -> Branch("fMom", &fMom, "fMom/F"); + tOut -> Branch("fv0pid", fv0pid, Form("fv0pid[%d]/F",AliPID::kSPECIES)); + tOut -> Branch("fdEdx", fdEdx, Form("fdEdx[%d]/F", AliTRDpidUtil::kLQslices)); + + for(Int_t iEv = 0; iEv < (tIn -> GetEntries()); iEv++){ + fLayer = 0; + fMom = 0.0; + for(Int_t i = 0; i < AliPID::kSPECIES; i++) fv0pid[i] = 0.0; + for(Int_t i = 0; i < AliTRDpidUtil::kLQslices; i++) fdEdx[i] = 0.0; + tIn -> GetEntry(iEv); + if(Util.GetMomentumBin(fMom) == iMomBin){ + tOut -> Fill(); + } + } + + tOut -> Write(); + tOut -> Delete(); + fOut -> Close(); + + } + + printf("Extraction completed!"); + return 1; + +} + + +Int_t CreateDummy(){ + + for(Int_t iMomBin = 0; iMomBin < AliTRDCalPID::kNMom; iMomBin++){ + printf("Creating dummy for momentum bin %3.1f GeV/c\n", AliTRDCalPID::GetMomentum(iMomBin)); + TFile *fOut = new TFile(Form("./%3.1fGeV/TRD.TaskPidRefMaker.root",AliTRDCalPID::GetMomentum(iMomBin)),"RECREATE"); + TObjArray *fContainer = new TObjArray(); + + TGraphErrors *gEffisTrain = new TGraphErrors(50); +// TGraphErrors *gEffisTrain = new TGraphErrors(AliTRDpidRefMaker::kMoniTrain); + gEffisTrain -> SetLineColor(4); + gEffisTrain -> SetMarkerColor(4); + gEffisTrain -> SetMarkerStyle(29); + gEffisTrain -> SetMarkerSize(1); + + TGraphErrors *gEffisTest = new TGraphErrors(50); +// TGraphErrors *gEffisTest = new TGraphErrors(AliTRDpidRefMaker::kMoniTrain); + gEffisTest -> SetLineColor(2); + gEffisTest -> SetMarkerColor(2); + gEffisTest -> SetMarkerStyle(29); + gEffisTest -> SetMarkerSize(1); + + fContainer -> AddAt(gEffisTrain,0); + fContainer -> AddAt(gEffisTest,1); +// fContainer -> AddAt(gEffisTrain,AliTRDpidRefMaker::kGraphTrain); +// fContainer -> AddAt(gEffisTest,AliTRDpidRefMaker::kGraphTest); + + } + +} diff --git a/PWG1/TRD/macros/PID/runTraining.C b/PWG1/TRD/macros/PID/runTraining.C new file mode 100644 index 00000000000..c3578754b1c --- /dev/null +++ b/PWG1/TRD/macros/PID/runTraining.C @@ -0,0 +1,54 @@ +// It is recommended to train not all momenta at on eturn. The time consumption +// for a training loop is very large! + +// Please be careful if you want to train the networks. The networks will be saved +// in a file ("./Networks_%d", date(yyyymmdd)). You should create seperate directories +// where the training for the several momentum bins should be done. Otherwise the +// networks will be deleted by the following momentum bin training. + +#ifndef __CINT__ +#include "TSystem.h" +#include "$ALICE_ROOT/TRD/qaRec/AliTRDpidRefMaker.h" +#endif + +Int_t runTraining(){ + + gSystem -> Load("libANALYSIS.so"); + gSystem -> Load("libTRDqaRec.so"); + + AliTRDpidRefMaker *ref = new AliTRDpidRefMaker(); + ref->SetDebugLevel(2); + +// Sets the momentum bin that should be trained: +// Bin 0 = 0.6 GeV/c +// Bin 1 = 0.8 GeV/c +// Bin 2 = 1.0 GeV/c +// Bin 3 = 1.5 GeV/c +// Bin 4 = 2.0 GeV/c +// Bin 5 = 3.0 GeV/c +// Bin 6 = 4.0 GeV/c +// Bin 7 = 5.0 GeV/c +// Bin 8 = 6.0 GeV/c +// Bin 9 = 8.0 GeV/c +// Bin 10 = 10.0 GeV/c +// Bin 11 = All + ref->SetTrainMomBin(1); + +// Sets if the network should be trained + ref->SetDoTraining(1); + +// Sets if the training should be continued or an untrained network will be taken. +// If the training should be continued with a pretrained network, +// please uncomment this line +// ref->SetContinueTraining(1); + +// Sets the path for old networks. If the training should be continued +// with a pretrained network, please uncomment this line and set the date (yyyymmdd). +// ref->SetTrainPath(20081022); + +// Do the training + ref->PostProcess(); + + return 1; + +} diff --git a/PWG1/TRD/macros/helper.C b/PWG1/TRD/macros/helper.C new file mode 100644 index 00000000000..270c229acb7 --- /dev/null +++ b/PWG1/TRD/macros/helper.C @@ -0,0 +1,94 @@ +#if ! defined (__CINT__) || defined (__MAKECINT__) +#include "TFileMerger.h" +#include "TSystem.h" +#include "TString.h" +#include "TObjString.h" +#include "TObjArray.h" +#include "TError.h" +#include +#endif + +#ifndef HELPER_C +#define HELPER_C + +//____________________________________________ +Int_t ParseOptions(Char_t *trd) +{ + Int_t fSteerTask = 1; + TObjArray *tasksArray = TString(trd).Tokenize(" "); + for(Int_t isel = 0; isel < tasksArray->GetEntriesFast(); isel++){ + TString s = (dynamic_cast(tasksArray->UncheckedAt(isel)))->String(); + if(s.CompareTo("ALL") == 0){ + for(Int_t itask = 0; itask < NTRDQATASKS; itask++) SETBITT(fSteerTask, itask); + continue; + } else { + Bool_t foundOpt = kFALSE; + for(Int_t itask = 2; itask < NTRDTASKS; itask++){ + if(s.CompareTo(fgkTRDtaskOpt[itask]) != 0) continue; + SETBITT(fSteerTask, itask); SETBITT(fSteerTask, kInfoGen); + foundOpt = kTRUE; + break; + } + if(!foundOpt) Info("ParseOptions()", Form("TRD task %s not implemented (yet).", s.Data())); + } + } + // extra rules for calibration tasks + if(TSTBIT(fSteerTask, kCalibration)) SETBITT(fSteerTask, kCheckDET); + if(TSTBIT(fSteerTask, kMultiplicity)) SETBITT(fSteerTask, kEfficiency); + if(TSTBIT(fSteerTask, kEfficiencyMC)) SETBITT(fSteerTask, kEfficiency); + if(TSTBIT(fSteerTask, kClErrParam)) SETBITT(fSteerTask, kResolution); + if(TSTBIT(fSteerTask, kAlignment)) SETBITT(fSteerTask, kResolution); + if(TSTBIT(fSteerTask, kPIDRefMaker)) SETBITT(fSteerTask, kCheckPID); + + return fSteerTask; +} + +//______________________________________________________ +void mergeProd(const Char_t *mark, const Char_t *files, const Int_t kBatch = 20) +{ + TFileMerger *fFM = 0x0; + Bool_t kSVN = kFALSE; + + Int_t jbatch = 0, nbatch = 0; + string filename; + ifstream file(files); + while(getline(file, filename)){ + if(Int_t(filename.find(mark)) < 0) continue; + if(!nbatch){ + if(fFM){ + delete fFM; + fFM = new TFileMerger(kTRUE); + } else fFM = new TFileMerger(kTRUE); + fFM->OutputFile(Form("%s/%d_%s", gSystem->ExpandPathName("$PWD"), jbatch, mark)); + } + if(!kSVN){ // download SVN info for trending + string base=filename.substr(0, filename.find_last_of('/')); + if(gSystem->Exec(Form("cp -v %s/svnInfo.log .", base.c_str())) == 0) kSVN=kTRUE; + } + fFM->AddFile(filename.c_str()); nbatch++; + if(nbatch==kBatch){ + printf("MERGING BATCH %d [%d] ... \n", jbatch, nbatch); + fFM->Merge(); jbatch++; + nbatch=0; + } + } + if(nbatch){ + printf("MERGING INCOMPLETE BATCH %d [%d] ... \n", jbatch, nbatch); + fFM->Merge(); jbatch++; + } + if(!jbatch){ + delete fFM; + return; + } + + new(fFM) TFileMerger(kTRUE); + fFM->OutputFile(Form("%s/%s", gSystem->ExpandPathName("$PWD"), mark)); + for(Int_t ib=jbatch; ib--;){ + fFM->AddFile(Form("%s/%d_%s", gSystem->ExpandPathName("$PWD"), ib, mark)); + gSystem->Exec(Form("rm -f %s/%d_%s", gSystem->ExpandPathName("$PWD"), ib, mark)); + } + fFM->Merge(); + delete fFM; +} + +#endif diff --git a/PWG1/TRD/macros/makeCalibResults.C b/PWG1/TRD/macros/makeCalibResults.C new file mode 100644 index 00000000000..b751f265e95 --- /dev/null +++ b/PWG1/TRD/macros/makeCalibResults.C @@ -0,0 +1,142 @@ +// Usage: +// makeCalibResults.C("task", "file_list", kGRID) +// tasks : "one/more of the following separated by space: +// "CAL" : TRD calibration +// "ALGN" : TRD alignment +// "PIDR" : TRD PID - reference data +// "CLRES": Cluster position and error parameterization +// "NOFR" : Data set does not have AliESDfriends.root +// "NOMC" : Data set does not have Monte Carlo Informations (real data), so all tasks which rely +// on MC information are switched off +// file_list : is the list of the files to be processed. +// They should contain the full path. Here is an example: +// /lustre/alice/local/TRDdata/SIM/P-Flat/TRUNK/RUN0/TRD.CalibName.root +// or for GRID alien:///alice/cern.ch/user/m/mfasel/MinBiasProd/results/ppMinBias80000/1/TRD.Calib%.root +// kGRID : specify if files are comming from a GRID collection [default kFALSE] +// +// HOW TO BUILD THE FILE LIST +// 1. locally +// ls -1 BaseDir/RUN*/TRD.Calib*.root > files.lst +// +// 2. on Grid +// char *BaseDir="/alice/cern.ch/user/m/mfasel/MinBiasProd/results/ppMinBias80000/"; +// TGrid::Connect("alien://"); +// TGridResult *res = gGrid->Query(BaseDir, "%/TRD.Calib%.root"); +// TGridCollection *col = gGrid->OpenCollectionQuery(res); +// col->Reset(); +// TMap *map = 0x0; +// while(map = (TMap*)col->Next()){ +// TIter it((TCollection*)map); +// TObjString *info = 0x0; +// while(info=(TObjString*)it()){ +// printf("alien://%s\n", col->GetLFN(info->GetString().Data())); +// } +// } +// +// The files which will be processed are the intersection between the +// condition on the tasks and the files in the file list. +// +// In compiled mode : +// Don't forget to load first the libraries +// gSystem->Load("libMemStat.so") +// gSystem->Load("libMemStatGui.so") +// gSystem->Load("libANALYSIS.so") +// gSystem->Load("libANALYSISalice.so") +// gSystem->Load("libTRDqaRec.so") +// gSystem->Load("libSTAT.so") +// gSystem->Load("libPWG1.so"); +// gSystem->Load("libNetx.so") ; +// gSystem->Load("libRAliEn.so"); +// +// Authors: +// Alex Bercuci (A.Bercuci@gsi.de) +// Markus Fasel (m.Fasel@gsi.de) +// + +#if ! defined (__CINT__) || defined (__MAKECINT__) + +#include "qaRec/AliTRDrecoTask.h" +#include +#include +#include +#include +#include +#include + +#endif + +#include "AliTRDperformanceTrain.h" +#include "helper.C" +//#include "../../PWG1/macros/AddPerformanceTask.h" + +Char_t *libs[] = {"libProofPlayer.so", "libANALYSIS.so", "libTRDqaRec.so", "libSTAT.so"}; +// define setup +TCanvas *c = 0x0; +Bool_t mc(kFALSE), friends(kFALSE); + +void calibrateTRD(TNamed* task, Int_t itask); +void makeCalibResults(Char_t *opt, const Char_t *files=0x0, Bool_t kGRID=kFALSE) +{ + if(kGRID){ + if(!gSystem->Getenv("GSHELL_ROOT")){ + Error("makeCalibResults.C", "AliEn not initialized."); + return; + } + TGrid::Connect("alien://"); + } + + // Load Libraries in interactive mode + Int_t nlibs = static_cast(sizeof(libs)/sizeof(Char_t *)); + for(Int_t ilib=0; ilibLoad(libs[ilib]) >= 0) continue; + Error("makeCalibResults.C", Form("Failed to load %s.", libs[ilib])); + return; + } + + mc = HasReadMCData(opt); + friends = HasReadFriendData(opt); + + gStyle->SetOptStat(0); + gStyle->SetOptFit(0); + Int_t fSteerTask = ParseOptions(opt); + + if(!c) c=new TCanvas("c", "Calibration", 10, 10, 800, 500); + + TClass *ctask = new TClass; + AliAnalysisTask *task = 0x0; + for(Int_t itask = NTRDQATASKS; itaskNew(); + if(files) mergeProd(Form("TRD.Calib%s.root", task->GetName()), files); + + if(task->IsA()->InheritsFrom("AliTRDrecoTask")) calibrateTRD(task, itask); + } + delete ctask; + delete c; +} + + +//______________________________________________________ +void calibrateTRD(TNamed *otask, Int_t itask) +{ + AliTRDrecoTask *task = dynamic_cast(otask); + task->SetDebugLevel(0); + + AliLog::SetClassDebugLevel(fgkTRDtaskClassName[itask], 3); + task->SetMCdata(mc); + task->SetFriends(friends); + + if(!task->PostProcess()){ + Error("makeCalibResults.C", Form("Processing data container for task %s failed.", task->GetName())); + delete task; + return; + } + for(Int_t ipic=0; ipicGetNRefFigures(); ipic++){ + c->Clear(); + if(!task->GetRefFigure(ipic)) continue; + c->SaveAs(Form("%s_Fig%02d.gif", task->GetName(), ipic)); + } + delete task; +} + diff --git a/PWG1/TRD/macros/makeResults.C b/PWG1/TRD/macros/makeResults.C new file mode 100644 index 00000000000..29b04987b45 --- /dev/null +++ b/PWG1/TRD/macros/makeResults.C @@ -0,0 +1,171 @@ +// Usage: +// makeResults.C("tasks", "file_list", kGRID) +// tasks : "ALL" or one/more of the following separated by space: +// "EFF" : TRD Tracking Efficiency +// "EFFC" : TRD Tracking Efficiency Combined (barrel + stand alone) - only in case of simulations +// "RES" : TRD tracking Resolution +// "PID" : TRD PID - pion efficiency +// "DET" : Basic TRD Detector checks +// "NOFR" : Data set does not have AliESDfriends.root +// "NOMC" : Data set does not have Monte Carlo Informations (real data), so all tasks which rely +// on MC information are switched off +// file_list : is the list of the files to be processed. +// They should contain the full path. Here is an example: +// /lustre/alice/local/TRDdata/SIM/P-Flat/TRUNK/RUN0/TRD.Performance.root +// or for GRID alien:///alice/cern.ch/user/m/mfasel/MinBiasProd/results/ppMinBias80000/1/TRD.Performance.root +// kGRID : specify if files are comming from a GRID collection [default kFALSE] +// +// HOW TO BUILD THE FILE LIST +// 1. locally +// ls -1 BaseDir/RUN*/TRD.Performance.root > files.lst +// +// 2. on Grid +// char *BaseDir="/alice/cern.ch/user/m/mfasel/MinBiasProd/results/ppMinBias80000/"; +// TGrid::Connect("alien://"); +// TGridResult *res = gGrid->Query(BaseDir, "%/TRD.Performance.root"); +// TGridCollection *col = gGrid->OpenCollectionQuery(res); +// col->Reset(); +// TMap *map = 0x0; +// while(map = (TMap*)col->Next()){ +// TIter it((TCollection*)map); +// TObjString *info = 0x0; +// while(info=(TObjString*)it()){ +// printf("alien://%s\n", col->GetLFN(info->GetString().Data())); +// } +// } +// +// The files which will be processed are the intersection between the +// condition on the tasks and the files in the file list. +// +// Authors: +// Alex Bercuci (A.Bercuci@gsi.de) +// Markus Fasel (m.Fasel@gsi.de) +// + +#if ! defined (__CINT__) || defined (__MAKECINT__) +#include +#include "TError.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qaRec/AliTRDrecoTask.h" + +#endif + +#include "AliTRDperformanceTrain.h" +#include "helper.C" +//#include "../../PWG1/macros/AddPerformanceTask.h" + +Char_t *libs[] = {"libProofPlayer.so", "libANALYSIS.so", "libTRDqaRec.so"}; +// define setup +TCanvas *c = 0x0; +Bool_t mc(kFALSE), friends(kFALSE); + +void processTRD(TNamed* task); +void processESD(TNamed* task); +void makeResults(Char_t *opt = "ALL", const Char_t *files=0x0, Bool_t kGRID=kFALSE) +{ + if(kGRID){ + if(!gSystem->Getenv("GSHELL_ROOT")){ + Error("makeResults.C", "AliEn not initialized."); + return; + } + TGrid::Connect("alien://"); + } + + // Load Libraries in interactive mode + Int_t nlibs = static_cast(sizeof(libs)/sizeof(Char_t *)); + for(Int_t ilib=0; ilibLoad(libs[ilib]) >= 0) continue; + Error("makeResults.C", Form("Failed to load %s.", libs[ilib])); + return; + } + + mc = HasReadMCData(opt); + friends = HasReadFriendData(opt); + + gStyle->SetOptStat(0); + gStyle->SetOptFit(0); + if(files) mergeProd("TRD.Performance.root", files); + Int_t fSteerTask = ParseOptions(opt); + + if(!c) c=new TCanvas("c", "Performance", 10, 10, 800, 500); + + TClass *ctask = new TClass; + AliAnalysisTask *task = 0x0; + for(Int_t itask = NTRDQATASKS; itask--;){ + if(!TSTBIT(fSteerTask, itask)) continue; + new(ctask) TClass(fgkTRDtaskClassName[itask]); + task = (AliAnalysisTask*)ctask->New(); + + if(task->IsA()->InheritsFrom("AliTRDrecoTask")) processTRD(task); + else processESD(task); + } + delete ctask; + delete c; +} + + +//______________________________________________________ +void processTRD(TNamed *otask) +{ + AliTRDrecoTask *task = dynamic_cast(otask); + task->SetDebugLevel(0); + task->SetMCdata(mc); + task->SetFriends(friends); + + if(!task->Load(Form("%s/TRD.Performance.root", gSystem->ExpandPathName("$PWD")))){ + Error("makeResults.C", Form("Load data container for task %s failed.", task->GetName())); + delete task; + return; + } + + if(!task->PostProcess()){ + Error("makeResults.C", Form("Processing data container for task %s failed.", task->GetName())); + delete task; + return; + } + for(Int_t ipic=0; ipicGetNRefFigures(); ipic++){ + c->Clear(); + if(!task->GetRefFigure(ipic)) continue; + c->SaveAs(Form("%s_Fig%02d.gif", task->GetName(), ipic), "gif"); + } + delete task; +} + +//______________________________________________________ +void processESD(TNamed *otask) +{ + AliTRDcheckESD *esd = dynamic_cast(otask); + if(!esd){ + Info("makeResults.C", "Processing of task AliTRDcheckESD failed."); + delete otask; + return; + } + + if(!esd->Load(Form("%s/TRD.Performance.root", gSystem->ExpandPathName("$PWD")))){ + Error("makeResults.C", Form("Load data container for task %s failed.", esd->GetName())); + delete esd; + return; + } + + esd->Terminate(); + + TGraphErrors *g = 0x0; Int_t ipic=0; + while((g=esd->GetGraph(ipic, ""))){ + c->Clear(); g->Draw("apl"); + c->SaveAs(Form("%s_Fig%02d.gif", esd->GetName(), ipic)); + ipic++; + } + delete esd; +} diff --git a/PWG1/TRD/run.C b/PWG1/TRD/run.C new file mode 100644 index 00000000000..7a731cf248f --- /dev/null +++ b/PWG1/TRD/run.C @@ -0,0 +1,290 @@ +// Steer TRD QA train for Reconstruction (Clusterizer, Tracking and PID). +// +// Usage: +// run.C(tasks, files) +// tasks : "ALL" or one/more of the following: +// "EFF" : TRD Tracking Efficiency +// "EFFC" : TRD Tracking Efficiency Combined (barrel + stand alone) - only in case of simulations +// "MULT" : TRD single track selection +// "RES" : TRD tracking Resolution +// "CLRES": clusters Resolution +// "CAL" : TRD calibration +// "ALGN" : TRD alignment +// "PID" : TRD PID - pion efficiency +// "PIDR" : TRD PID - reference data +// "DET" : Basic TRD Detector checks +// "NOFR" : Data set does not have AliESDfriends.root +// "NOMC" : Data set does not have Monte Carlo Informations (real data), so all tasks which rely +// on MC information are switched off +// +// In compiled mode : +// Don't forget to load first the libraries +// gSystem->Load("libMemStat.so") +// gSystem->Load("libMemStatGui.so") +// gSystem->Load("libANALYSIS.so") +// gSystem->Load("libANALYSISalice.so") +// gSystem->Load("libTRDqaRec.so") +// gSystem->Load("libPWG1.so"); +// gSystem->Load("libNetx.so") ; +// gSystem->Load("libRAliEn.so"); +// +// Authors: +// Alex Bercuci (A.Bercuci@gsi.de) +// Markus Fasel (m.Fasel@gsi.de) + +#if ! defined (__CINT__) || defined (__MAKECINT__) +//#ifndef __CINT__ +#include + +#include "TStopwatch.h" +#include "TMemStat.h" +#include "TMemStatViewerGUI.h" + +#include "TROOT.h" +#include "TClass.h" +#include "TSystem.h" +#include "TError.h" +#include "TChain.h" +#include "TGrid.h" +#include "TAlienCollection.h" +#include "TGridCollection.h" +#include "TGridResult.h" +#include "TGeoGlobalMagField.h" + +#include "AliMagF.h" +#include "AliTracker.h" +#include "AliLog.h" +#include "AliCDBManager.h" +#include "AliGRPManager.h" +#include "AliGeomManager.h" +#include "AliAnalysisManager.h" +#include "AliAnalysisDataContainer.h" +#include "AliMCEventHandler.h" +#include "AliESDInputHandler.h" + +#include "TRD/AliTRDtrackerV1.h" +#include "TRD/AliTRDcalibDB.h" + +#include "TRD/qaRec/macros/AliTRDperformanceTrain.h" +#include "TRD/qaRec/macros/AddTRDcheckESD.C" +#include "TRD/qaRec/macros/AddTRDinfoGen.C" +#include "TRD/qaRec/macros/AddTRDcheckDET.C" +#include "TRD/qaRec/macros/AddTRDefficiency.C" +#include "TRD/qaRec/macros/AddTRDresolution.C" +#include "TRD/qaRec/macros/AddTRDcheckPID.C" + +#include "PWG1/macros/AddPerformanceTask.C" +#endif + +#include "../../TRD/qaRec/macros/AliTRDperformanceTrain.h" +#include "../../PWG1/macros/AddPerformanceTask.h" + + +Bool_t MEM = kFALSE; + +TChain* MakeChainLST(const char* filename = 0x0); +TChain* MakeChainXML(const char* filename = 0x0); +void run(Char_t *trd="ALL", Char_t *tpc="ALL", const Char_t *files=0x0, Long64_t nev=1234567890, Long64_t first = 0) +{ + TMemStat *mem = 0x0; + if(MEM){ + gSystem->Load("libMemStat.so"); + gSystem->Load("libMemStatGui.so"); + mem = new TMemStat("new, gnubuildin"); + mem->AddStamp("Start"); + } + TStopwatch timer; + timer.Start(); + + + + // VERY GENERAL SETTINGS + AliLog::SetGlobalLogLevel(AliLog::kError); + if(gSystem->Load("libANALYSIS.so")<0) return; + if(gSystem->Load("libANALYSISalice.so")<0) return; + + Bool_t fHasMCdata = 1;//HasReadMCData(trd); + //Bool_t fHasFriends = HasReadFriendData(trd); + + // INITIALIZATION OF RUNNING ENVIRONMENT + //TODO We should use the GRP if available similar to AliReconstruction::InitGRP()! + // initialize OCDB manager + AliCDBManager *cdbManager = AliCDBManager::Instance(); + cdbManager->SetDefaultStorage("local://$ALICE_ROOT/OCDB"); + cdbManager->SetSpecificStorage("GRP/GRP/Data", Form("local://%s",gSystem->pwd())); + cdbManager->SetRun(0); + cdbManager->SetCacheFlag(kFALSE); + // initialize magnetic field from the GRP manager. + AliGRPManager grpMan; + grpMan.ReadGRPEntry(); + grpMan.SetMagField(); + //AliRunInfo *runInfo = grpMan.GetRunInfo(); + AliGeomManager::LoadGeometry(); + + + // DEFINE DATA CHAIN + TChain *chain = 0x0; + if(!files) chain = MakeChainLST(); + else{ + TString fn(files); + if(fn.EndsWith("xml")) chain = MakeChainXML(files); + else chain = MakeChainLST(files); + } + if(!chain) return; + chain->SetBranchStatus("*FMD*",0); + chain->SetBranchStatus("*Calo*",0); + chain->SetBranchStatus("Tracks", 1); + chain->SetBranchStatus("ESDfriend*",1); + chain->Lookup(); + chain->GetListOfFiles()->Print(); + printf("\n ----> CHAIN HAS %d ENTRIES <----\n\n", (Int_t)chain->GetEntries()); + + + // BUILD ANALYSIS MANAGER + AliAnalysisManager *mgr = new AliAnalysisManager("Post Reconstruction Calibration/QA"); + AliVEventHandler *esdH = 0x0, *mcH = 0x0; + mgr->SetInputEventHandler(esdH = new AliESDInputHandler); + if(fHasMCdata) mgr->SetMCtruthEventHandler(mcH = new AliMCEventHandler()); + //mgr->SetDebugLevel(10); + + + +/////////////////////////////////////////////////////////// +/////////////// TRD /////////// +/////////////////////////////////////////////////////////// + // TRD specific library + if(gSystem->Load("libTRDqaRec.so")<0) return; + // TRD data containers + AliAnalysisDataContainer *ci[] = {0x0, 0x0, 0x0}; + + + // initialize TRD settings + AliTRDcalibDB *cal = AliTRDcalibDB::Instance(); + AliTRDtrackerV1::SetNTimeBins(cal->GetNumberOfTimeBins()); + + // plug (set of) TRD wagons in the train + if(trd){ + for(Int_t it=0; itLoadMacro(Form("$ALICE_ROOT/TRD/qaRec/macros/Add%s.C+", TString(fgkTRDtaskClassName[it])(3,20).Data()))) { + Error("run.C", Form("Error loading %s task.", fgkTRDtaskClassName[it])); + return; + } + + switch(it){ + case kCheckESD: + AddTRDcheckESD(mgr); break; + case kInfoGen: + AddTRDinfoGen(mgr, trd, 0x0, ci); break; + case kCheckDET: + AddTRDcheckDET(mgr, trd, ci); break; + case kEfficiency: + AddTRDefficiency(mgr, trd, ci); break; + case kResolution: + AddTRDresolution(mgr, trd, ci); break; + case kCheckPID: + AddTRDcheckPID(mgr, trd, ci); break; + default: + Warning("run.C", Form("No performance task registered at slot %d.", it)); + } + } + } + +/////////////////////////////////////////////////////////// +/////////////// TPC /////////// +/////////////////////////////////////////////////////////// + if(gSystem->Load("libPWG1.so")<0) return; + + // BUILD STEERING TASK FOR TPC + if(tpc){ + if(gROOT->LoadMacro("$ALICE_ROOT/PWG1/macros/AddPerformanceTask.C+")) { + Error("run.C", "Error loading AliPerformanceTask task."); + return; + } + AddPerformanceTask(mgr, tpc); + } + + if (!mgr->InitAnalysis()) return; + // verbosity + printf("\n\tRUNNING TRAIN FOR TASKS:\n"); + mgr->GetTasks()->ls(); + //mgr->PrintStatus(); + + mgr->StartAnalysis("local", chain, nev, first); + + timer.Stop(); + timer.Print(); + + cal->Terminate(); + TGeoGlobalMagField::Instance()->SetField(NULL); + delete cdbManager; + + // verbosity + printf("\n\tCLEANING UP TRAIN:\n"); + mgr->GetTasks()->Delete(); + + if(mcH) delete mcH; + delete esdH; + delete mgr; + delete chain; + if(MEM) delete mem; + if(MEM) TMemStatViewerGUI::ShowGUI(); +} + +//____________________________________________ +TChain* MakeChainLST(const char* filename) +{ + // Create the chain + TChain* chain = new TChain("esdTree"); + + if(!filename){ + chain->Add(Form("%s/AliESDs.root", gSystem->pwd())); + return chain; + } + + + // read ESD files from the input list. + ifstream in; + in.open(filename); + TString esdfile; + while(in.good()) { + in >> esdfile; + if (!esdfile.Contains("root")) continue; // protection + chain->Add(esdfile.Data()); + } + + in.close(); + + return chain; +} + +//____________________________________________ +TChain* MakeChainXML(const char* xmlfile) +{ + if (!TFile::Open(xmlfile)) { + Error("MakeChainXML", Form("No file %s was found", xmlfile)); + return 0x0; + } + + if(gSystem->Load("libNetx.so")<0) return 0x0; + if(gSystem->Load("libRAliEn.so")<0) return 0x0; + TGrid::Connect("alien://") ; + + TGridCollection *collection = (TGridCollection*) TAlienCollection::Open(xmlfile); + if (!collection) { + Error("MakeChainXML", Form("No collection found in %s", xmlfile)) ; + return 0x0; + } + //collection->CheckIfOnline(); + + TGridResult* result = collection->GetGridResult("",0 ,0); + if(!result->GetEntries()){ + Error("MakeChainXML", Form("No entries found in %s", xmlfile)) ; + return 0x0; + } + // Makes the ESD chain + TChain* chain = new TChain("esdTree"); + for (Int_t idx = 0; idx < result->GetEntries(); idx++) { + chain->Add(result->GetKey(idx, "turl")); + } + return chain; +} diff --git a/PWG1/TRD/run.jdl b/PWG1/TRD/run.jdl new file mode 100644 index 00000000000..6ac69f31a97 --- /dev/null +++ b/PWG1/TRD/run.jdl @@ -0,0 +1,57 @@ +# this is the startup process for root +Executable="run.sh"; + +Jobtag={"comment:Grid analysis test"}; + +# we split per storage element +Split="se"; + +# we want each job to read 10 input files +SplitMaxInputFileNumber="50"; + +# this job has to run in the ANALYSIS partition +#Requirements=( member(other.GridPartitions,"Analysis") ); +#Requirements = other.SPLIT == 1 && ( other.TTL > 20000 ) && ( other.Price <= 1 ); +#Requirements = ( member(other.GridPartitions,"Analysis") ); + +# we need ROOT and the API service configuration package +Packages={"APISCONFIG::V2.4","VO_ALICE@ROOT::v5-22-00", "VO_ALICE@AliRoot::v4-16-Rev-05"}; +TTL = "30000"; +Price = 1; + + +#ROOT will read this collection file to know, which files to analyze +InputDataList="esd.xml"; + +InputDataListFormat="xml-single"; + + +#ROOT requires the collection file in the xml-single format +#InputDataListFormat="merge:/alice/cern.ch/user/a/amarin/global.xml"; + +# this is our collection file containing the files to be analyzed +InputDataCollection="LF:/alice/cern.ch/user/a/amarin/MinBiasProd/xml/$1.xml,nodownload"; + + +InputFile= {"LF:/alice/cern.ch/user/a/abercuci/MinBiasProd/run.C", + "LF:/alice/cern.ch/user/a/abercuci/MinBiasProd/run.h"}; + + +# Output archive +OutputArchive={"log_archive.zip:stdout@Alice::GSI::SE","root_archive.zip:*.root@Alice::GSI::SE"}; + +# Output directory +OutputDir="/alice/cern.ch/user/a/abercuci/MinBiasProd/$1/#alien_counter#"; + +# Output files +OutputFile={"TRD.TaskDetChecker.root", "TRD.TaskResolution.root", "TRD.TaskTrackingEff.root", "TRD.TaskTrackingEffMC.root", "TRD.TaskPID.root"}; + +# Merge the output +Merge={"TRD.TaskDetChecker.root:/alice/cern.ch/user/a/abercuci/test/merge.jdl:TRD.TaskDetCheckerMerged.root"}; +MergeOutputDir={"/alice/cern.ch/user/a/abercuci/test/output"}; + +# Validation +Validationcommand ="/alice/cern.ch/user/a/abercuci/bin/validate.sh"; + +# email +Email="A.Bercuci@gsi.de";