1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////////
21 // TRD calibration class for building reference data for PID
22 // - 2D reference histograms (responsible A.Bercuci)
23 // - 3D reference histograms (not yet implemented) (responsible A.Bercuci)
24 // - Neural Network (responsible A.Wilk)
27 // Alex Bercuci (A.Bercuci@gsi.de)
29 ///////////////////////////////////////////////////////////////////////////////
36 #include <TParticle.h>
37 #include <TParticle.h>
38 #include <TPrincipal.h>
40 #include <TLinearFitter.h>
48 #include "AliRunLoader.h"
50 #include "AliHeader.h"
51 #include "AliGenEventHeader.h"
52 #include "AliESDtrack.h"
54 #include "AliTRDCalPIDRefMaker.h"
55 #include "AliTRDCalPID.h"
56 #include "AliTRDcalibDB.h"
57 #include "AliTRDgeometry.h"
59 ClassImp(AliTRDCalPIDRefMaker)
61 TLinearFitter *AliTRDCalPIDRefMaker::fgFitter2D2 = 0x0;
62 TLinearFitter *AliTRDCalPIDRefMaker::fgFitter2D1 = 0x0;
64 //__________________________________________________________________
65 AliTRDCalPIDRefMaker::AliTRDCalPIDRefMaker()
69 // AliTRDCalPIDRefMaker default constructor
73 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++){
79 //__________________________________________________________________
80 AliTRDCalPIDRefMaker::AliTRDCalPIDRefMaker(const AliTRDCalPIDRefMaker &ref)
84 // AliTRDCalPIDRefMaker copy constructor
87 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++){
88 if(ref.fH2dEdx[ispec]){
89 fH2dEdx[ispec] = new TH2D((TH2D&)*(ref.fH2dEdx[ispec]));
90 } else fH2dEdx[ispec] = 0x0;
95 //__________________________________________________________________
96 AliTRDCalPIDRefMaker::~AliTRDCalPIDRefMaker()
99 // AliTRDCalPIDQRef destructor
102 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++){
103 if(fH2dEdx[ispec]) delete fH2dEdx[ispec];
104 if(fPrinc[ispec]) delete fPrinc[ispec];
106 if(fgFitter2D1){ delete fgFitter2D1; fgFitter2D1 = 0x0;}
107 if(fgFitter2D2){ delete fgFitter2D2; fgFitter2D2 = 0x0;}
111 //__________________________________________________________________
112 AliTRDCalPIDRefMaker& AliTRDCalPIDRefMaker::operator=(const AliTRDCalPIDRefMaker &ref)
115 // Assignment operator
118 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++){
119 if(ref.fH2dEdx[ispec]) (ref.fH2dEdx[ispec])->Copy(*fH2dEdx[ispec]);
126 //__________________________________________________________________
127 Bool_t AliTRDCalPIDRefMaker::BuildLQReferences(const Char_t *File, const Char_t *dir)
129 // Build, Fill and write to file the histograms used for PID.
130 // The simulations are looked in the
131 // directories with the general form Form("p%3.1f", momentum)
132 // starting from dir (default .). Here momentum belongs to the list
133 // of known momentum to PID (see trackMomentum).
134 // The output histograms are
135 // written to the file "File" in cwd (default
136 // TRDPIDHistograms.root). In order to build a DB entry
137 // consider running $ALICE_ROOT/Cal/AliTRDpidCDB.C
140 // Alex Bercuci (A.Bercuci@gsi.de)
142 Int_t partCode[AliPID::kSPECIES] =
143 {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton};
145 // check and retrive number of directories in the production
147 if(!(nBatches = CheckProdDirTree(dir))) return kFALSE;
150 // Number of Time bins
152 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
154 AliError("No AliTRDcalibDB available.");
157 nTimeBins = calibration->GetNumberOfTimeBins();
158 // if (calibration->GetRun() > -1) nTimeBins = calibration->GetNumberOfTimeBins();
160 // AliError("No run number set.");
165 // Build PID reference/working objects
166 fH1TB[0] = new TH1F("h1TB_0", "", nTimeBins, -.5, nTimeBins-.5);
167 fH1TB[0]->SetLineColor(4);
168 fH1TB[1] = new TH1F("h1TB_1", "", nTimeBins, -.5, nTimeBins-.5);
169 fH1TB[1]->SetLineColor(2);
170 for(Int_t ispec=0; ispec<AliPID::kSPECIES; ispec++) if(!fPrinc[ispec]) fPrinc[ispec] = new TPrincipal(2, "ND");
172 // Print statistics header
173 Int_t nPart[AliPID::kSPECIES], nTotPart;
175 for(Int_t ispec=0; ispec<AliPID::kSPECIES; ispec++) printf(" %s[%%] ", AliTRDCalPID::GetPartSymb(ispec));
176 printf("\n-----------------------------------------------\n");
178 Float_t trackMomentum[AliTRDCalPID::kNMom];
179 //Float_t trackSegLength[AliTRDCalPID::kNLength];
180 for(int i=0; i<AliTRDCalPID::kNMom; i++) trackMomentum[i] = AliTRDCalPID::GetMomentum(i);
181 AliRunLoader *fRunLoader = 0x0;
182 TFile *esdFile = 0x0;
183 TTree *esdTree = 0x0;
185 AliESDtrack *esdTrack = 0x0;
189 for (Int_t imom = 0; imom < AliTRDCalPID::kNMom; imom++) {
192 // init statistics for momentum
194 for(Int_t ispec=0; ispec<AliPID::kSPECIES; ispec++) nPart[ispec] = 0;
196 // loop over production directories
197 for(Int_t ibatch = 0; ibatch<nBatches; ibatch++){
198 // open run loader and load gAlice, kinematics and header
199 fRunLoader = AliRunLoader::Open(Form("%s/%3.1fGeV/%03d/galice.root", dir, trackMomentum[imom], ibatch));
201 AliError(Form("Getting run loader for momentum %3.1f GeV/c batch %03d failed.", trackMomentum[imom], ibatch));
204 TString s; s.Form("%s/%3.1fGeV/%03d/", dir, trackMomentum[imom], ibatch);
205 fRunLoader->SetDirName(s);
206 fRunLoader->LoadgAlice();
207 gAlice = fRunLoader->GetAliRun();
209 AliError(Form("galice object not found for momentum %3.1f GeV/c batch %03d.", trackMomentum[imom], ibatch));
212 fRunLoader->LoadKinematics();
213 fRunLoader->LoadHeader();
216 esdFile = TFile::Open(Form("%s/%3.1fGeV/%03d/AliESDs.root", dir, trackMomentum[imom], ibatch));
217 if (!esdFile || esdFile->IsZombie()) {
218 AliError(Form("Opening ESD file failed for momentum %3.1f GeV/c batch %03d.", trackMomentum[imom], ibatch));
221 esdTree = (TTree*)esdFile->Get("esdTree");
223 AliError(Form("ESD tree not found for momentum %3.1f GeV/c batch %03d.", trackMomentum[imom], ibatch));
227 esdTree->SetBranchAddress("ESD", &esd);
231 for (Int_t iEvent = 0; iEvent < fRunLoader->GetNumberOfEvents(); iEvent++) {
234 fRunLoader->GetEvent(iEvent);
235 AliStack* stack = AliRunLoader::Instance()->Stack();
237 fRunLoader->GetHeader()->GenEventHeader()->PrimaryVertex(vertex);
239 // Load event summary data
240 esdTree->GetEvent(iEvent);
242 AliWarning(Form("ESD object not found for event %d. (@ momentum %3.1f GeV/c, batch %03d)", iEvent, trackMomentum[imom], ibatch));
247 for(Int_t iTrack=0; iTrack<esd->GetNumberOfTracks(); iTrack++){
248 esdTrack = esd->GetTrack(iTrack);
250 //if(!AliTRDpidESD::CheckTrack(esdTrack)) continue;
252 if((esdTrack->GetStatus() & AliESDtrack::kITSrefit) == 0) continue;
253 if(esdTrack->GetConstrainedChi2() > 1E9) continue;
254 if ((esdTrack->GetStatus() & AliESDtrack::kESDpid) == 0) continue;
255 if (esdTrack->GetTRDsignal() == 0.) continue;
258 Int_t label = esdTrack->GetLabel();
259 if(label<0) continue;
260 if (label > stack->GetNtrack()) continue; // background
261 TParticle* particle = stack->Particle(label);
263 AliWarning(Form("Retriving particle with index %d from AliStack failed. [@ momentum %3.1f batch %03d event %d track %d]", label, trackMomentum[imom], ibatch, iEvent, iTrack));
266 if(particle->Pt() < 1.E-3) continue;
267 // if (TMath::Abs(particle->Eta()) > 0.3) continue;
268 TVector3 dVertex(particle->Vx() - vertex[0],
269 particle->Vy() - vertex[1],
270 particle->Vz() - vertex[2]);
271 if (dVertex.Mag() > 1.E-4){
272 //AliInfo(Form("Particle with index %d generated too far from vertex. Skip from analysis. Details follows. [@ event %d track %d]", label, iEvent, iTrack));
277 for (Int_t ispec=0; ispec<AliPID::kSPECIES; ispec++)
278 if(TMath::Abs(particle->GetPdgCode()) == partCode[ispec]){
284 nPart[iGen]++; nTotPart++;
288 Double_t dedx[AliTRDCalPID::kNSlicesLQ], dEdx;
290 for (Int_t iLayer=0; iLayer<AliTRDgeometry::kNlayer; iLayer++){
291 // read data for track segment
292 for(int iSlice=0; iSlice<AliTRDCalPID::kNSlicesLQ; iSlice++)
293 dedx[iSlice] = esdTrack->GetTRDslice(iLayer, iSlice);
294 dEdx = esdTrack->GetTRDslice(iLayer, -1);
295 timebin = esdTrack->GetTRDTimBin(iLayer);
298 if ((dEdx <= 0.) || (timebin <= -1.)) continue;
300 // retrive kinematic info for this track segment
301 //if(!AliTRDpidESD::RecalculateTrackSegmentKine(esdTrack, iLayer, mom, length)) continue;
302 mom = esdTrack->GetOuterParam()->GetP();
304 // find segment length and momentum bin
305 Int_t jmom = 1, refMom = -1;
306 while(jmom<AliTRDCalPID::kNMom-1 && mom>trackMomentum[jmom]) jmom++;
307 if(TMath::Abs(trackMomentum[jmom-1] - mom) < trackMomentum[jmom-1] * .2) refMom = jmom-1;
308 else if(TMath::Abs(trackMomentum[jmom] - mom) < trackMomentum[jmom] * .2) refMom = jmom;
310 AliInfo(Form("Momentum at plane %d entrance not in momentum window. [@ momentum %3.1f batch %03d event %d track %d]", iLayer, trackMomentum[imom], ibatch, iEvent, iTrack));
313 /*while(jleng<AliTRDCalPID::kNLength-1 && length>trackSegLength[jleng]) jleng++;*/
315 // this track segment has fulfilled all requierments
318 if(dedx[0] > 0. && dedx[1] > 0.){
319 dedx[0] = log(dedx[0]); dedx[1] = log(dedx[1]);
320 fPrinc[iGen]->AddRow(dedx);
322 fH1TB[(iGen>0)?1:0]->Fill(timebin);
327 delete esd; esd = 0x0;
329 delete esdFile; esdFile = 0x0;
331 fRunLoader->UnloadHeader();
332 fRunLoader->UnloadKinematics();
333 delete fRunLoader; fRunLoader = 0x0;
334 } // end directory loop
336 // use data to prepare references
339 SaveReferences(imom, File);
342 // print momentum statistics
343 printf(" %3.1f ", trackMomentum[imom]);
344 for(Int_t ispec=0; ispec<AliPID::kSPECIES; ispec++) printf(" %5.2f ", 100.*nPart[ispec]/nTotPart);
346 } // end momentum loop
349 TListIter it((TList*)gROOT->GetListOfFiles());
350 while((fSave=(TFile*)it.Next()))
351 if(strcmp(File, fSave->GetName())==0) break;
360 //__________________________________________________________________
361 Bool_t AliTRDCalPIDRefMaker::BuildNNReferences(const Char_t* /*File*/, const Char_t* /*dir*/) const
366 //__________________________________________________________________
367 Double_t AliTRDCalPIDRefMaker::Estimate2D2(TH2 * const h, Float_t &x, Float_t &y)
370 // Linear interpolation of data point with a parabolic expresion using
371 // the logarithm of the bin content in a close neighbourhood. It is
372 // assumed that the bin content of h is in number of events !
375 // This function have to be used when the statistics of each bin is
376 // sufficient and all bins are populated. For cases of sparse data
377 // please refere to Estimate2D1().
379 // Author : Alex Bercuci (A.Bercuci@gsi.de)
383 AliErrorGeneral("AliTRDCalPIDRefMaker::Estimate2D2()", "No histogram defined.");
387 TAxis *ax = h->GetXaxis(), *ay = h->GetYaxis();
388 Int_t binx = ax->FindBin(x);
389 Int_t biny = ay->FindBin(y);
390 Int_t nbinsx = ax->GetNbins();
391 Int_t nbinsy = ay->GetNbins();
395 // late construction of fitter
396 if(!fgFitter2D2) fgFitter2D2 = new TLinearFitter(6, "1++x++y++x*x++y*y++x*y");
398 fgFitter2D2->ClearPoints();
400 Int_t binx0, binx1, biny0, biny1;
401 for(int bin=0; bin<5; bin++){
402 binx0 = TMath::Max(1, binx-bin);
403 binx1 = TMath::Min(nbinsx, binx+bin);
404 for(int ibin=binx0; ibin<=binx1; ibin++){
405 biny0 = TMath::Max(1, biny-bin);
406 biny1 = TMath::Min(nbinsy, biny+bin);
407 for(int jbin=biny0; jbin<=biny1; jbin++){
408 if(ibin != binx0 && ibin != binx1 && jbin != biny0 && jbin != biny1) continue;
409 if((entries = h->GetBinContent(ibin, jbin)) == 0.) continue;
410 p[0] = ax->GetBinCenter(ibin);
411 p[1] = ay->GetBinCenter(jbin);
412 fgFitter2D2->AddPoint(p, log(entries), 1./sqrt(entries));
416 if(npoints>=25) break;
418 if(fgFitter2D2->Eval() == 1){
419 printf("<I2> x = %9.4f y = %9.4f\n", x, y);
420 printf("\tbinx %d biny %d\n", binx, biny);
421 printf("\tpoints %d\n", npoints);
426 fgFitter2D2->GetParameters(vec);
427 Double_t result = vec[0] + x*vec[1] + y*vec[2] + x*x*vec[3] + y*y*vec[4] + x*y*vec[5];
432 //__________________________________________________________________
433 Double_t AliTRDCalPIDRefMaker::Estimate2D1(TH2 * const h, Float_t &x, Float_t &y
435 , const Float_t &rmin
436 , const Float_t &rmax)
439 // Linear interpolation of data point with a plane using
440 // the logarithm of the bin content in the area defined by the
441 // d(cos(phi)) and dr=(rmin, rmax). It is assumed that the bin content
442 // of h is number of events !
446 AliErrorGeneral("AliTRDCalPIDRefMaker::Estimate2D1()", "No histogram defined.");
450 TAxis *ax = h->GetXaxis(), *ay = h->GetYaxis();
451 // Int_t binx = ax->FindBin(x);
452 // Int_t biny = ay->FindBin(y);
453 Int_t nbinsx = ax->GetNbins();
454 Int_t nbinsy = ay->GetNbins();
457 Double_t rxy = sqrt(x*x + y*y), rpxy;
459 // late construction of fitter
460 if(!fgFitter2D1) fgFitter2D1 = new TLinearFitter(3, "1++x++y");
462 fgFitter2D1->ClearPoints();
464 for(int ibin=1; ibin<=nbinsx; ibin++){
465 for(int jbin=1; jbin<=nbinsy; jbin++){
466 if((entries = h->GetBinContent(ibin, jbin)) == 0.) continue;
467 p[0] = ax->GetBinCenter(ibin);
468 p[1] = ay->GetBinCenter(jbin);
469 rpxy = sqrt(p[0]*p[0] + p[1]*p[1]);
470 if((x*p[0] + y*p[1])/rxy/rpxy < dCT) continue;
471 if(rpxy<rmin || rpxy > rmax) continue;
473 fgFitter2D1->AddPoint(p, log(entries), 1./sqrt(entries));
477 if(npoints<15) return 0.;
478 if(fgFitter2D1->Eval() == 1){
479 printf("<O2> x = %9.4f y = %9.4f\n", x, y);
480 printf("\tpoints %d\n", npoints);
484 fgFitter2D1->GetParameters(vec);
485 Double_t result = vec[0] + x*vec[1] + y*vec[2];
489 //__________________________________________________________________
490 // Double_t AliTRDCalPIDRefMaker::Estimate3D2(TH3 * const h, Float_t &x, Float_t &y, Float_t &z)
492 // // Author Alex Bercuci (A.Bercuci@gsi.de)
498 ///////////// Private functions ///////////////////////////////////
500 //__________________________________________________________________
501 Int_t AliTRDCalPIDRefMaker::CheckProdDirTree(const Char_t *dir)
503 // Scan directory tree for momenta. Returns the smallest number of
504 // batches found in all directories or 0 if one momentum is missing.
506 const char *pwd = gSystem->pwd();
508 if(!gSystem->ChangeDirectory(dir)){
509 AliError(Form("Couldn't access production root directory %s.", dir));
514 Int_t nDir = Int_t(1.E6);
515 for(int imom=0; imom<AliTRDCalPID::kNMom; imom++){
516 if(!gSystem->ChangeDirectory(Form("%3.1fGeV", AliTRDCalPID::GetMomentum(imom)))){
517 AliError(Form("Couldn't find data for momentum %3.1f GeV/c.", AliTRDCalPID::GetMomentum(imom)));
522 while(gSystem->ChangeDirectory(Form("%03d", iDir))){
524 gSystem->ChangeDirectory("..");
526 if(iDir < nDir) nDir = iDir;
527 gSystem->ChangeDirectory(dir);
530 gSystem->ChangeDirectory(pwd);
536 //__________________________________________________________________
537 void AliTRDCalPIDRefMaker::Prepare2D()
540 // Prepares the 2-dimensional reference histograms
543 // histogram settings
544 Float_t xmin, xmax, ymin, ymax;
545 Int_t nbinsx, nbinsy, nBinsSector, nSectors;
546 const Int_t color[] = {4, 3, 2, 7, 6};
547 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++){
550 AliError(Form("No data defined for %s.", AliTRDCalPID::GetPartName(ispec)));
553 // build reference histograms
556 nbinsx = nbinsy = nBinsSector * nSectors;
558 xmax = 8000.; ymax = 6000.;
560 fH2dEdx[ispec] = new TH2D(Form("h2%s", AliTRDCalPID::GetPartSymb(ispec)), "", nbinsx, xmin, xmax, nbinsy, ymin, ymax);
561 fH2dEdx[ispec]->SetLineColor(color[ispec]);
565 // build transformed rotated histograms
566 nbinsx = nbinsy = 100;
568 xmax = 10.; ymax = 6.;
570 if(!(hProj = (TH2I*)gDirectory->Get("hProj"))) hProj = new TH2I("hProj", "", nbinsx, xmin, xmax, nbinsy, ymin, ymax);
573 printf("Doing interpolation and invertion ... "); fflush(stdout);
574 Bool_t kDebugPlot = kTRUE;
575 //Bool_t kDebugPrint = kFALSE;
578 TEllipse *ellipse = 0x0;
581 c=new TCanvas("c2", "Interpolation 2D", 10, 10, 500, 500);
582 ellipse = new TEllipse();
583 ellipse->SetFillStyle(0); ellipse->SetLineColor(2);
584 mark = new TMarker();
585 mark->SetMarkerColor(2); mark->SetMarkerSize(2); mark->SetMarkerStyle(2);
588 // define observable variables
590 Double_t xy[2], lxy[2], rxy[2];
591 Double_t estimate, position;
592 const TVectorD *eValues;
594 // define radial sectors
595 const Int_t nPhi = 36;
596 const Float_t dPhi = TMath::TwoPi()/nPhi;
597 //const Float_t dPhiRange = .1;
598 Int_t nPoints[nPhi], nFitPoints, binStart, binStop;
599 TLinearFitter refsFitter[nPhi], refsLongFitter(6, "1++x++y++x*x++y*y++x*y");
600 Float_t fgFitterRange[nPhi];
601 Bool_t kFitterStatus[nPhi];
602 for(int iphi=0; iphi<nPhi; iphi++){
603 refsFitter[iphi].SetDim(3);
604 refsFitter[iphi].SetFormula("1++x++y");//++x*x++y*y++x*y");
605 fgFitterRange[iphi] = .8;
606 kFitterStatus[iphi] = kFALSE;
608 std::vector<UShort_t> storeX[nPhi], storeY[nPhi];
610 // define working variables
611 Float_t x0, y0, rx, ry;
612 //Float_t rc, rmin, rmax, dr, dCT;
616 for(int ispec=0; ispec<5; ispec++){
618 for(int iphi=0; iphi<nPhi; iphi++){
620 refsFitter[iphi].ClearPoints();
621 fgFitterRange[iphi] = .8;
622 kFitterStatus[iphi] = kFALSE;
623 storeX[iphi].clear();
624 storeY[iphi].clear();
627 // calculate covariance ellipse
628 fPrinc[ispec]->MakePrincipals();
629 eValues = fPrinc[ispec]->GetEigenValues();
632 rx = 3.5*sqrt((*eValues)[0]);
633 ry = 3.5*sqrt((*eValues)[1]);
635 // rotate to principal axis
638 printf("filling for spec %d ...\n", ispec);
639 while((xx = fPrinc[ispec]->GetRow(irow++))){
640 fPrinc[ispec]->X2P(xx, rxy);
641 hProj->Fill(rxy[0], rxy[1]);
648 // ellipse->DrawEllipse(x0, y0, rx, ry, 0., 360., 0.);
649 // mark->DrawMarker(x0, y0);
650 // gPad->Modified(); gPad->Update();
653 // define radial sectors
654 ax=hProj->GetXaxis();
655 ay=hProj->GetYaxis();
656 for(int ibin=1; ibin<=ax->GetNbins(); ibin++){
657 rxy[0] = ax->GetBinCenter(ibin);
658 for(int jbin=1; jbin<=ay->GetNbins(); jbin++){
659 rxy[1] = ay->GetBinCenter(jbin);
661 if((entries = hProj->GetBinContent(ibin, jbin)) == 0) continue;
663 position = rxy[0]*rxy[0]/rx/rx + rxy[1]*rxy[1]/ry/ry;
664 if(position < 1.) continue;
666 r = sqrt(rxy[0]*rxy[0] + rxy[1]*rxy[1]);
667 phi = ((rxy[1] > 0.) ? 1. : -1.) * TMath::ACos(rxy[0]/r); // [-pi, pi]
668 iPhi = nPhi/2 + Int_t(phi/dPhi) - ((phi/dPhi > 0.) ? 0 : 1);
670 refsFitter[iPhi].AddPoint(rxy, log(entries), 1./sqrt(entries));
676 ax=fH2dEdx[ispec]->GetXaxis();
677 ay=fH2dEdx[ispec]->GetYaxis();
678 for(int ibin=1; ibin<=ax->GetNbins(); ibin++){
679 xy[0] = ax->GetBinCenter(ibin);
681 for(int jbin=1; jbin<=ay->GetNbins(); jbin++){
682 xy[1] = ay->GetBinCenter(jbin);
686 fPrinc[ispec]->X2P(lxy, rxy);
688 // calculate border of covariance ellipse
689 position = rxy[0]*rxy[0]/rx/rx + rxy[1]*rxy[1]/ry/ry;
691 // interpolation inside the covariance ellipse
693 Float_t xTemp = rxy[0];
694 Float_t yTemp = rxy[1];
695 estimate = Estimate2D2((TH2 *) hProj, xTemp, yTemp);
698 // estimate = Estimate2D2((TH2 *) hProj, (Float_t)rxy[0], (Float_t)rxy[1]);
699 fH2dEdx[ispec]->SetBinContent(ibin, jbin, estimate/xy[0]/xy[1]);
700 } else { // interpolation outside the covariance ellipse
701 r = sqrt(rxy[0]*rxy[0] + rxy[1]*rxy[1]);
702 phi = ((rxy[1] > 0.) ? 1. : -1.) * TMath::ACos(rxy[0]/r); // [-pi, pi]
703 iPhi = nPhi/2 + Int_t(phi/dPhi) - ((phi/dPhi > 0.) ? 0 : 1);
705 storeX[iPhi].push_back(ibin);
706 storeY[iPhi].push_back(jbin);
712 // Radial fit on transformed rotated
715 for(int iphi=0; iphi<nPhi; iphi++){
716 phi = iphi * dPhi - TMath::Pi();
717 if(TMath::Abs(TMath::Abs(phi)-TMath::Pi()) < 100.*TMath::DegToRad()) continue;
720 refsFitter[iphi].Eval();
721 refsFitter[iphi].GetParameters(vec);
722 for(UInt_t ipoint=0; ipoint<storeX[iphi].size(); ipoint++){
723 xbin = storeX[iphi].at(ipoint);
724 ybin = storeY[iphi].at(ipoint);
725 xy[0] = ax->GetBinCenter(xbin); lxy[0] = log(xy[0]);
726 xy[1] = ay->GetBinCenter(ybin); lxy[1] = log(xy[1]);
729 fPrinc[ispec]->X2P(lxy, rxy);
730 estimate = exp(vec[0] + rxy[0]*vec[1] + rxy[1]*vec[2]);//+ rxy[0]*rxy[0]*vec[3]+ rxy[1]*rxy[1]*vec[4]+ rxy[0]*rxy[1]*vec[5]);
731 fH2dEdx[ispec]->SetBinContent(xbin, ybin, estimate/xy[0]/xy[1]);
735 // Longitudinal fit on ref histo in y direction
736 for(int isector=1; isector<nSectors; isector++){
738 binStart = ((isector>0)?isector-1:isector)*nBinsSector + 1;
739 binStop = (isector+1)*nBinsSector;
742 refsLongFitter.ClearPoints();
746 for(int ibin=1; ibin<=ax->GetNbins(); ibin++){
747 xy[0] = ax->GetBinCenter(ibin);
748 for(int jbin=binStart; jbin<=binStop; jbin++){
749 xy[1] = ay->GetBinCenter(jbin);
750 if((entries = fH2dEdx[ispec]->GetBinContent(ibin, jbin)) > 0.){
751 refsLongFitter.AddPoint(xy, log(entries), 1.e-7);
754 storeX[0].push_back(ibin);
755 storeY[0].push_back(jbin);
758 if(nPoints[0] >= ((isector==0)?60:420)) break;
762 if(refsLongFitter.Eval() == 1){
763 printf("Error in Y sector %d\n", isector);
766 refsLongFitter.GetParameters(vec);
767 for(UInt_t ipoint=0; ipoint<storeX[0].size(); ipoint++){
768 xbin = storeX[0].at(ipoint);
769 ybin = storeY[0].at(ipoint);
770 xy[0] = ax->GetBinCenter(xbin);
771 xy[1] = ay->GetBinCenter(ybin);
773 estimate = vec[0] + xy[0]*vec[1] + xy[1]*vec[2] + xy[0]*xy[0]*vec[3]+ xy[1]*xy[1]*vec[4]+ xy[0]*xy[1]*vec[5];
774 fH2dEdx[ispec]->SetBinContent(xbin, ybin, exp(estimate));
778 // Longitudinal fit on ref histo in x direction
779 for(int isector=1; isector<nSectors; isector++){
780 binStart = ((isector>0)?isector-1:isector)*nBinsSector + 1;
781 binStop = (isector+1)*nBinsSector;
785 refsLongFitter.ClearPoints();
789 for(int jbin=1; jbin<=ay->GetNbins(); jbin++){
790 xy[1] = ay->GetBinCenter(jbin);
791 for(int ibin=binStart; ibin<=binStop; ibin++){
792 xy[0] = ax->GetBinCenter(ibin);
793 if((entries = fH2dEdx[ispec]->GetBinContent(ibin, jbin)) > 0.){
794 refsLongFitter.AddPoint(xy, log(entries), 1.e-7);
797 storeX[0].push_back(ibin);
798 storeY[0].push_back(jbin);
802 if(nPoints[0] >= ((isector==0)?60:420)) break;
804 if(nFitPoints == 0) continue;
807 if(refsLongFitter.Eval() == 1){
808 printf("Error in X sector %d\n", isector);
811 refsLongFitter.GetParameters(vec);
812 for(UInt_t ipoint=0; ipoint<storeX[0].size(); ipoint++){
813 xbin = storeX[0].at(ipoint);
814 ybin = storeY[0].at(ipoint);
815 xy[0] = ax->GetBinCenter(xbin);
816 xy[1] = ay->GetBinCenter(ybin);
818 estimate = vec[0] + xy[0]*vec[1] + xy[1]*vec[2] + xy[0]*xy[0]*vec[3]+ xy[1]*xy[1]*vec[4]+ xy[0]*xy[1]*vec[5];
819 fH2dEdx[ispec]->SetBinContent(xbin, ybin, exp(estimate));
824 fH2dEdx[ispec]->Scale(1./fH2dEdx[ispec]->Integral());
828 fH2dEdx[ispec]->Draw("cont1"); gPad->SetLogz();
829 gPad->Modified(); gPad->Update();
832 AliInfo("Finish interpolation.");
835 //__________________________________________________________________
836 void AliTRDCalPIDRefMaker::Reset()
839 // Reset reference histograms
842 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++){
843 if(fH2dEdx[ispec]) fH2dEdx[ispec]->Reset();
844 fPrinc[ispec]->Clear();
846 if(fH1TB[0]) fH1TB[0]->Reset();
847 if(fH1TB[1]) fH1TB[1]->Reset();
850 //__________________________________________________________________
851 void AliTRDCalPIDRefMaker::SaveReferences(const Int_t mom, const char *fn)
854 // Save the reference histograms
858 TListIter it((TList*)gROOT->GetListOfFiles());
859 Bool_t kFOUND = kFALSE;
860 TDirectory *pwd = gDirectory;
861 while((fSave=(TFile*)it.Next()))
862 if(strcmp(fn, fSave->GetName())==0){
866 if(!kFOUND) fSave = TFile::Open(fn, "RECREATE");
869 Float_t fmom = AliTRDCalPID::GetMomentum(mom);
871 // save dE/dx references
873 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++){
874 h2 = (TH2D*)fH2dEdx[ispec]->Clone(Form("h2dEdx%s%d", AliTRDCalPID::GetPartSymb(ispec), mom));
875 h2->SetTitle(Form("2D dEdx for particle %s @ %d", AliTRDCalPID::GetPartName(ispec), mom));
876 h2->GetXaxis()->SetTitle("dE/dx_{TRD}^{amplif} [au]");
877 h2->GetYaxis()->SetTitle("dE/dx_{TRD}^{drift} [au]");
878 h2->GetZaxis()->SetTitle("Entries");
882 // save maximum time bin references
884 h1 = (TH1F*)fH1TB[0]->Clone(Form("h1MaxTBEL%02d", mom));
885 h1->SetTitle(Form("Maximum Time Bin distribution for electrons @ %4.1f GeV", fmom));
886 h1->GetXaxis()->SetTitle("time [100 ns]");
887 h1->GetYaxis()->SetTitle("Probability");
890 h1 = (TH1F*)fH1TB[1]->Clone(Form("h1MaxTBPI%02d", mom));
891 h1->SetTitle(Form("Maximum Time Bin distribution for pions @ %4.1f GeV", fmom));
892 h1->GetXaxis()->SetTitle("time [100 ns]");
893 h1->GetYaxis()->SetTitle("Probability");