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 /* History of cvs commits:
21 * Revision 1.14 2006/09/07 18:31:08 kharlov
22 * Effective c++ corrections (T.Pocheptsov)
24 * Revision 1.13 2005/05/28 14:19:04 schutz
25 * Compilation warnings fixed by T.P.
29 //_________________________________________________________________________
30 // Implementation version v0 of the PHOS particle identifier
31 // Particle identification based on the
33 // - Preshower information (in MIXT or GPS2 geometries)
36 // CPV or Preshower clusters should be closer in PHOS plane than fCpvEmcDistance (in cm).
37 // This parameter can be set by method SetCpvtoEmcDistanceCut(Float_t cut)
39 // One can set desirable ID method by the function SetIdentificationMethod(option).
40 // Presently the following options can be used together or separately :
41 // - "disp": use dispersion cut on shower width
42 // (width can be set by method SetDispersionCut(Float_t cut)
43 // - "ell" : use cut on the axis of the ellipse, drawn around shower
44 // (this cut can be changed by SetShowerProfileCut(char* formula),
45 // where formula - any function of two variables f(lambda[0],lambda[1]).
46 // Shower is considered as EM if f() > 0 )
47 // One can visualize current cuts calling method PlotDispersionCuts().
50 // root [0] AliPHOSPIDv0 * p1 = new AliPHOSPIDv0("galice.root")
51 // Warning in <TDatabasePDG::TDatabasePDG>: object already instantiated
52 // root [1] p1->SetIdentificationMethod("disp ellipse")
53 // root [2] p1->ExecuteTask()
54 // root [3] AliPHOSPIDv0 * p2 = new AliPHOSPIDv0("galice1.root","ts1")
55 // Warning in <TDatabasePDG::TDatabasePDG>: object already instantiated
56 // // reading headers from file galice1.root and TrackSegments
57 // // with title "ts1"
58 // root [4] p2->SetRecParticlesBranch("rp1")
59 // // set file name for the branch RecParticles
60 // root [5] p2->ExecuteTask("deb all time")
61 // // available options
62 // // "deb" - prints # of reconstructed particles
63 // // "deb all" - prints # and list of RecParticles
64 // // "time" - prints benchmarking results
66 //*-- Author: Yves Schutz (SUBATECH) & Gines Martinez (SUBATECH) &
67 // Dmitri Peressounko (SUBATECH & Kurchatov Institute)
68 // Completely redesined by Dmitri Peressounko, March 2001
70 // --- ROOT system ---
76 #include "TBenchmark.h"
77 // --- Standard library ---
79 // --- AliRoot header files ---
82 #include "AliGenerator.h"
83 #include "AliPHOSPIDv0.h"
84 #include "AliPHOSEmcRecPoint.h"
85 #include "AliPHOSTrackSegment.h"
86 #include "AliPHOSRecParticle.h"
87 #include "AliPHOSGeometry.h"
88 #include "AliPHOSLoader.h"
90 ClassImp( AliPHOSPIDv0)
92 //____________________________________________________________________________
93 AliPHOSPIDv0::AliPHOSPIDv0():
94 fTrackSegmentsTitle(""),
96 fRecParticlesTitle(""),
97 fIDOptions("dis time"),
103 fCpvEmcDistance(0.f),
105 fRecParticlesInRun(0)
108 fEventFolderName = "";
111 //____________________________________________________________________________
112 AliPHOSPIDv0::AliPHOSPIDv0(const char * evFolderName,const char * name) :
113 AliPHOSPID(evFolderName, name),
114 fTrackSegmentsTitle(GetName()),
115 fRecPointsTitle(GetName()),
116 fRecParticlesTitle(GetName()),
117 fIDOptions("dis time"),
121 fFormula(new TFormula("LambdaCuts","(x>1)*(x<2.5)*(y>0)*(y<x)")),
123 fCpvEmcDistance(3.f),
125 fRecParticlesInRun(0)
127 //ctor with the indication on where to look for the track segments
128 fEventFolderName = GetTitle() ;
132 //____________________________________________________________________________
133 AliPHOSPIDv0::AliPHOSPIDv0(const AliPHOSPIDv0 & rhs) :
135 fTrackSegmentsTitle(rhs.fTrackSegmentsTitle),
136 fRecPointsTitle(rhs.fRecPointsTitle),
137 fRecParticlesTitle(rhs.fRecParticlesTitle),
138 fIDOptions(rhs.fIDOptions),
139 fNEvent(rhs.fNEvent),
140 fClusterizer(rhs.fClusterizer),
141 fTSMaker(rhs.fTSMaker),
142 fFormula(rhs.fFormula),
143 fDispersion(rhs.fDispersion),
144 fCpvEmcDistance(rhs.fCpvEmcDistance),
145 fTimeGate(rhs.fTimeGate),
146 fRecParticlesInRun(rhs.fRecParticlesInRun)
148 //Copy ctor, the same as compiler-generated, possibly wrong if
149 //someone implements dtor correctly.
152 //____________________________________________________________________________
153 AliPHOSPIDv0 & AliPHOSPIDv0::operator = (const AliPHOSPIDv0 & rhs)
155 //Copy-assignment, emulates compiler generated, possibly wrong.
156 AliPHOSPID::operator = (rhs);
157 fTrackSegmentsTitle = rhs.fTrackSegmentsTitle;
158 fRecPointsTitle = rhs.fRecPointsTitle;
159 fRecParticlesTitle = rhs.fRecParticlesTitle;
160 fIDOptions = rhs.fIDOptions;
161 fNEvent = rhs.fNEvent;
162 fClusterizer = rhs.fClusterizer;
163 fTSMaker = rhs.fTSMaker;
164 fFormula = rhs.fFormula;
165 fDispersion = rhs.fDispersion;
166 fCpvEmcDistance = rhs.fCpvEmcDistance;
167 fTimeGate = rhs.fTimeGate;
168 fRecParticlesInRun = rhs.fRecParticlesInRun;
173 //____________________________________________________________________________
174 AliPHOSPIDv0::~AliPHOSPIDv0()
176 //Empty dtor, fFormula leaks
180 ////____________________________________________________________________________
181 //Float_t AliPHOSPIDv0::GetDistance(AliPHOSEmcRecPoint * emc,AliPHOSRecPoint * cpv, Option_t * Axis)const
183 // // Calculates the distance between the EMC RecPoint and the PPSD RecPoint
185 // const AliPHOSGeometry * geom = AliPHOSLoader::GetPHOSGeometry() ;
189 // emc->GetLocalPosition(vecEmc) ;
190 // cpv->GetLocalPosition(vecCpv) ;
191 // if(emc->GetPHOSMod() == cpv->GetPHOSMod()){
193 // // Correct to difference in CPV and EMC position due to different distance to center.
194 // // we assume, that particle moves from center
195 // Float_t dCPV = geom->GetIPtoOuterCoverDistance();
196 // Float_t dEMC = geom->GetIPtoCrystalSurface() ;
197 // dEMC = dEMC / dCPV ;
198 // vecCpv = dEMC * vecCpv - vecEmc ;
199 // if (Axis == "X") return vecCpv.X();
200 // if (Axis == "Y") return vecCpv.Y();
201 // if (Axis == "Z") return vecCpv.Z();
202 // if (Axis == "R") return vecCpv.Mag();
205 // return 100000000 ;
208 //____________________________________________________________________________
209 void AliPHOSPIDv0::Exec(Option_t * option)
213 if( strcmp(GetName(), "")== 0 )
216 if(strstr(option,"tim"))
217 gBenchmark->Start("PHOSPID");
219 if(strstr(option,"print")) {
224 AliRunLoader* runget = AliRunLoader::GetRunLoader(GetTitle());
227 AliError(Form("Can not find run getter in event folder \"%s\"",
232 AliPHOSLoader* gime = dynamic_cast<AliPHOSLoader*>(runget->GetLoader("PHOSLoader"));
235 AliError("Could not obtain the Loader object !");
239 if(gime->BranchExists("RecParticles") )
243 Int_t nevents = runget->GetNumberOfEvents() ; //(Int_t) gAlice->TreeE()->GetEntries() ;
247 for(ievent = 0; ievent < nevents; ievent++){
248 runget->GetEvent(ievent);
249 AliInfo(Form("event %d %d %d",
250 ievent, gime->EmcRecPoints(),
251 gime->TrackSegments())) ;
256 if(strstr(option,"deb"))
257 PrintRecParticles(option) ;
259 //increment the total number of rec particles per run
260 fRecParticlesInRun += gime->RecParticles()->GetEntriesFast() ;
264 if(strstr(option,"tim")){
265 gBenchmark->Stop("PHOSPID");
266 AliInfo(Form("took %f seconds for PID %f seconds per event",
267 gBenchmark->GetCpuTime("PHOSPID"),
268 gBenchmark->GetCpuTime("PHOSPID")/nevents)) ;
272 //____________________________________________________________________________
273 void AliPHOSPIDv0::Init()
275 // Make all memory allocations that are not possible in default constructor
276 // Add the PID task to the list of PHOS tasks
278 AliRunLoader* runget = AliRunLoader::GetRunLoader(GetTitle());
281 AliError(Form("Can not find run getter in event folder \"%s\"",
286 AliPHOSLoader* gime = dynamic_cast<AliPHOSLoader*>(runget->GetLoader("PHOSLoader"));
289 AliError("Could not obtain the Loader object !");
294 gime->LoadRecParticles("UPDATE");
298 //____________________________________________________________________________
299 void AliPHOSPIDv0::MakeRecParticles()
301 // Reconstructs the particles from the tracksegments
303 TString taskName(GetName()) ;
304 taskName.Remove(taskName.Index(Version())-1) ;
306 AliRunLoader* runget = AliRunLoader::GetRunLoader(GetTitle());
309 AliError(Form("Can not find run getter in event folder \"%s\"",
314 AliPHOSLoader* gime = dynamic_cast<AliPHOSLoader*>(runget->GetLoader("PHOSLoader"));
317 AliError("Could not obtain the Loader object !");
321 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
322 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
323 TClonesArray * trackSegments = gime->TrackSegments() ;
324 TClonesArray * recParticles = gime->RecParticles() ;
326 recParticles->Clear();
328 TIter next(trackSegments) ;
329 AliPHOSTrackSegment * ts ;
331 AliPHOSRecParticle * rp ;
333 Bool_t ellips = fIDOptions.Contains("ell",TString::kIgnoreCase ) ;
334 Bool_t disp = fIDOptions.Contains("dis",TString::kIgnoreCase ) ;
335 Bool_t time = fIDOptions.Contains("tim",TString::kIgnoreCase ) ;
337 while ( (ts = (AliPHOSTrackSegment *)next()) ) {
339 new( (*recParticles)[index] ) AliPHOSRecParticle() ;
340 rp = (AliPHOSRecParticle *)recParticles->At(index) ;
341 rp->SetTrackSegment(index) ;
342 rp->SetIndexInList(index) ;
344 AliPHOSEmcRecPoint * emc = 0 ;
345 if(ts->GetEmcIndex()>=0)
346 emc = (AliPHOSEmcRecPoint *) emcRecPoints->At(ts->GetEmcIndex()) ;
348 AliPHOSRecPoint * cpv = 0 ;
349 if(ts->GetCpvIndex()>=0)
350 cpv = (AliPHOSRecPoint *) cpvRecPoints->At(ts->GetCpvIndex()) ;
352 //set momentum and energy first
353 Float_t e = emc->GetEnergy() ;
354 TVector3 dir = GetMomentumDirection(emc,cpv) ;
357 rp->SetMomentum(dir.X(),dir.Y(),dir.Z(),e) ;
360 //now set type (reconstructed) of the particle
361 Int_t showerprofile = 0; // 0 narrow and 1 wide
365 emc->GetElipsAxis(lambda) ;
366 if(fFormula->Eval(lambda[0],lambda[1]) <= 0 )
367 showerprofile = 1 ; // not narrow
371 if(emc->GetDispersion() > fDispersion )
372 showerprofile = 1 ; // not narrow
376 if(emc->GetTime() > fTimeGate )
379 // Looking at the CPV detector
380 Int_t cpvdetector= 0 ; //1 hit and 0 no hit
382 if(ts->GetCpvDistance("R") < fCpvEmcDistance)
385 Int_t type = showerprofile + 2 * slow + 4 * cpvdetector ;
387 rp->SetProductionVertex(0,0,0,0);
388 rp->SetFirstMother(-1);
389 rp->SetLastMother(-1);
390 rp->SetFirstDaughter(-1);
391 rp->SetLastDaughter(-1);
392 rp->SetPolarisation(0,0,0);
398 //____________________________________________________________________________
399 void AliPHOSPIDv0:: Print(const Option_t *) const
401 // Print the parameters used for the particle type identification
403 message = "=============== AliPHOSPIDv0 ================\n" ;
404 message += "Making PID\n" ;
405 message += " Headers file: %s\n" ;
406 message += " RecPoints branch title: %s\n" ;
407 message += " TrackSegments Branch title: %s\n" ;
408 message += " RecParticles Branch title %s\n" ;
409 message += "with parameters:\n" ;
410 message += " Maximal EMC - CPV distance (cm) %f\n" ;
411 AliInfo(Form( message.Data(),
413 fRecPointsTitle.Data(),
414 fTrackSegmentsTitle.Data(),
415 fRecParticlesTitle.Data(),
418 if(fIDOptions.Contains("dis",TString::kIgnoreCase ))
419 AliInfo(Form(" dispersion cut %f", fDispersion )) ;
420 if(fIDOptions.Contains("ell",TString::kIgnoreCase ))
421 AliInfo(Form(" Eliptic cuts function: %s",
422 fFormula->GetTitle() )) ;
423 if(fIDOptions.Contains("tim",TString::kIgnoreCase ))
424 AliInfo(Form(" Time Gate used: %f", fTimeGate)) ;
427 //____________________________________________________________________________
428 void AliPHOSPIDv0::SetShowerProfileCut(const char * formula)
430 //set shape of the cut on the axis of ellipce, drown around shouer
431 //shower considered "narrow" if Formula(lambda[0],lambda[1]) > 0.
434 fFormula = new TFormula("Lambda Cut",formula) ;
436 //____________________________________________________________________________
437 void AliPHOSPIDv0::WriteRecParticles()
439 // Saves the reconstructed particles too a file
441 AliRunLoader* runget = AliRunLoader::GetRunLoader(GetTitle());
444 AliError(Form("Can not find run getter in event folder \"%s\"",
449 AliPHOSLoader* gime = dynamic_cast<AliPHOSLoader*>(runget->GetLoader("PHOSLoader"));
452 AliError("Could not obtain the Loader object !");
456 TClonesArray * recParticles = gime->RecParticles() ;
457 recParticles->Expand(recParticles->GetEntriesFast() ) ;
459 TTree * treeR = gime->TreeR();
463 treeR = gime->TreeR() ;
467 Int_t bufferSize = 32000 ;
468 TBranch * rpBranch = treeR->Branch("PHOSRP",&recParticles,bufferSize);
469 rpBranch->SetTitle(fRecParticlesTitle);
472 Int_t splitlevel = 0 ;
473 AliPHOSPIDv0 * pid = this ;
474 TBranch * pidBranch = treeR->Branch("AliPHOSPID","AliPHOSPIDv0",&pid,bufferSize,splitlevel);
475 pidBranch->SetTitle(fRecParticlesTitle.Data());
480 gime->WriteRecParticles("OVERWRITE");
481 gime->WritePID("OVERWRITE");
485 //____________________________________________________________________________
486 void AliPHOSPIDv0::PlotDispersionCuts()const
488 // produces a plot of the dispersion cut
489 TCanvas* lambdas = new TCanvas("lambdas","Cuts on the ellipse axis",200,10,700,500);
491 if(fIDOptions.Contains("ell",TString::kIgnoreCase ) ){
492 TF2 * ell = new TF2("Elliptic Cuts",fFormula->GetName(),0,3,0,3) ;
493 ell->SetMinimum(0.0000001) ;
494 ell->SetMaximum(0.001) ;
495 ell->SetLineStyle(1) ;
496 ell->SetLineWidth(2) ;
500 if( fIDOptions.Contains("dis",TString::kIgnoreCase ) ){
501 TF2 * dsp = new TF2("dispersion","(y<x)*(x*x+y*y < [0]*[0])",0,3,0,3) ;
502 dsp->SetParameter(0,fDispersion) ;
503 dsp->SetMinimum(0.0000001) ;
504 dsp->SetMaximum(0.001) ;
505 dsp->SetLineStyle(1) ;
506 dsp->SetLineColor(2) ;
507 dsp->SetLineWidth(2) ;
510 if(fIDOptions.Contains("ell",TString::kIgnoreCase ) )
518 //____________________________________________________________________________
519 TVector3 AliPHOSPIDv0::GetMomentumDirection(AliPHOSEmcRecPoint * emc, AliPHOSRecPoint * )const
521 // Calculates the momentum direction:
522 // 1. if only a EMC RecPoint, direction is given by IP and this RecPoint
523 // 2. if a EMC RecPoint and CPV RecPoint, direction is given by the line through the 2 recpoints
524 // However because of the poor position resolution of PPSD the direction is always taken as if we were
527 TVector3 dir(0,0,0) ;
529 TVector3 emcglobalpos ;
532 emc->GetGlobalPosition(emcglobalpos, dummy) ;
535 // The following commented code becomes valid once the PPSD provides
536 // a reasonable position resolution, at least as good as EMC !
537 // TVector3 ppsdlglobalpos ;
538 // TVector3 ppsduglobalpos ;
539 // if( fPpsdLowRecPoint ){ // certainly a photon that has concerted
540 // fPpsdLowRecPoint->GetGlobalPosition(ppsdlglobalpos, mdummy) ;
541 // dir = emcglobalpos - ppsdlglobalpos ;
542 // if( fPpsdUpRecPoint ){ // not looks like a charged
543 // fPpsdUpRecPoint->GetGlobalPosition(ppsduglobalpos, mdummy) ;
544 // dir = ( dir + emcglobalpos - ppsduglobalpos ) * 0.5 ;
547 // else { // looks like a neutral
548 // dir = emcglobalpos ;
552 dir.SetZ( -dir.Z() ) ; // why ?
555 //account correction to the position of IP
556 Float_t xo,yo,zo ; //Coordinates of the origin
557 gAlice->Generator()->GetOrigin(xo,yo,zo) ;
558 TVector3 origin(xo,yo,zo);
563 //____________________________________________________________________________
564 void AliPHOSPIDv0::PrintRecParticles(Option_t * option)
566 // Print table of reconstructed particles
568 AliRunLoader* runget = AliRunLoader::GetRunLoader(GetTitle());
571 AliError(Form("Can not find run getter in event folder \"%s\"",
576 AliPHOSLoader* gime = dynamic_cast<AliPHOSLoader*>(runget->GetLoader("PHOSLoader"));
579 AliError("Could not obtain the Loader object !");
583 TString taskName(GetName()) ;
584 taskName.Remove(taskName.Index(Version())-1) ;
585 TClonesArray * recParticles = gime->RecParticles() ;
588 message = "event %d\n" ;
589 message += " found %d RecParticles\n" ;
590 AliInfo(Form(message.Data(),
591 gAlice->GetEvNumber(), recParticles->GetEntriesFast() )) ;
593 if(strstr(option,"all")) { // printing found TS
594 AliInfo(" PARTICLE Index" ) ;
597 for (index = 0 ; index < recParticles->GetEntries() ; index++) {
598 AliPHOSRecParticle * rp = (AliPHOSRecParticle * ) recParticles->At(index) ;
601 switch(rp->GetType()) {
602 case AliPHOSFastRecParticle::kNEUTRALEMFAST:
603 strcpy( particle, "NEUTRAL EM FAST");
605 case AliPHOSFastRecParticle::kNEUTRALHAFAST:
606 strcpy(particle, "NEUTRAL HA FAST");
608 case AliPHOSFastRecParticle::kNEUTRALEMSLOW:
609 strcpy(particle, "NEUTRAL EM SLOW");
611 case AliPHOSFastRecParticle::kNEUTRALHASLOW:
612 strcpy(particle, "NEUTRAL HA SLOW");
614 case AliPHOSFastRecParticle::kCHARGEDEMFAST:
615 strcpy(particle, "CHARGED EM FAST") ;
617 case AliPHOSFastRecParticle::kCHARGEDHAFAST:
618 strcpy(particle, "CHARGED HA FAST") ;
620 case AliPHOSFastRecParticle::kCHARGEDEMSLOW:
621 strcpy(particle, "CHARGEDEMSLOW") ;
623 case AliPHOSFastRecParticle::kCHARGEDHASLOW:
624 strcpy(particle, "CHARGED HA SLOW") ;
628 // Int_t * primaries;
630 // primaries = rp->GetPrimaries(nprimaries);
632 AliInfo(Form(" %s %d",
633 particle, rp->GetIndexInList())) ;