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:
23 //_________________________________________________________________________
24 // Implementation version v0 of the PHOS particle identifier
25 // Particle identification based on the
27 // - Preshower information (in MIXT or GPS2 geometries)
30 // CPV or Preshower clusters should be closer in PHOS plane than fCpvEmcDistance (in cm).
31 // This parameter can be set by method SetCpvtoEmcDistanceCut(Float_t cut)
33 // One can set desirable ID method by the function SetIdentificationMethod(option).
34 // Presently the following options can be used together or separately :
35 // - "disp": use dispersion cut on shower width
36 // (width can be set by method SetDispersionCut(Float_t cut)
37 // - "ell" : use cut on the axis of the ellipse, drawn around shower
38 // (this cut can be changed by SetShowerProfileCut(char* formula),
39 // where formula - any function of two variables f(lambda[0],lambda[1]).
40 // Shower is considered as EM if f() > 0 )
41 // One can visualize current cuts calling method PlotDispersionCuts().
44 // root [0] AliPHOSPIDv0 * p1 = new AliPHOSPIDv0("galice.root")
45 // Warning in <TDatabasePDG::TDatabasePDG>: object already instantiated
46 // root [1] p1->SetIdentificationMethod("disp ellipse")
47 // root [2] p1->ExecuteTask()
48 // root [3] AliPHOSPIDv0 * p2 = new AliPHOSPIDv0("galice1.root","ts1")
49 // Warning in <TDatabasePDG::TDatabasePDG>: object already instantiated
50 // // reading headers from file galice1.root and TrackSegments
51 // // with title "ts1"
52 // root [4] p2->SetRecParticlesBranch("rp1")
53 // // set file name for the branch RecParticles
54 // root [5] p2->ExecuteTask("deb all time")
55 // // available options
56 // // "deb" - prints # of reconstructed particles
57 // // "deb all" - prints # and list of RecParticles
58 // // "time" - prints benchmarking results
60 //*-- Author: Yves Schutz (SUBATECH) & Gines Martinez (SUBATECH) &
61 // Dmitri Peressounko (SUBATECH & Kurchatov Institute)
62 // Completely redesined by Dmitri Peressounko, March 2001
64 // --- ROOT system ---
70 #include "TBenchmark.h"
71 // --- Standard library ---
73 // --- AliRoot header files ---
76 #include "AliGenerator.h"
77 #include "AliPHOSPIDv0.h"
78 #include "AliPHOSEmcRecPoint.h"
79 #include "AliPHOSTrackSegment.h"
80 #include "AliPHOSRecParticle.h"
81 #include "AliPHOSGeometry.h"
82 #include "AliPHOSLoader.h"
84 ClassImp( AliPHOSPIDv0)
86 //____________________________________________________________________________
87 AliPHOSPIDv0::AliPHOSPIDv0():AliPHOSPID()
94 fEventFolderName = "" ;
95 fTrackSegmentsTitle= "" ;
96 fRecPointsTitle = "" ;
97 fRecParticlesTitle = "" ;
98 fIDOptions = "dis time" ;
99 fRecParticlesInRun = 0 ;
104 //____________________________________________________________________________
105 AliPHOSPIDv0::AliPHOSPIDv0(const char * evFolderName,const char * name) : AliPHOSPID(evFolderName, name)
107 //ctor with the indication on where to look for the track segments
109 fFormula = new TFormula("LambdaCuts","(x>1)*(x<2.5)*(y>0)*(y<x)") ;
111 fCpvEmcDistance = 3.0 ;
114 fEventFolderName = GetTitle() ;
115 fTrackSegmentsTitle = GetName();
116 fRecPointsTitle = GetName();
117 fRecParticlesTitle = GetName();
118 fIDOptions = "dis time" ;
120 fRecParticlesInRun = 0 ;
126 //____________________________________________________________________________
127 AliPHOSPIDv0::~AliPHOSPIDv0()
131 //____________________________________________________________________________
132 Float_t AliPHOSPIDv0::GetDistance(AliPHOSEmcRecPoint * emc,AliPHOSRecPoint * cpv, Option_t * Axis)const
134 // Calculates the distance between the EMC RecPoint and the PPSD RecPoint
136 const AliPHOSGeometry * geom = AliPHOSLoader::GetPHOSGeometry() ;
140 emc->GetLocalPosition(vecEmc) ;
141 cpv->GetLocalPosition(vecCpv) ;
142 if(emc->GetPHOSMod() == cpv->GetPHOSMod()){
144 // Correct to difference in CPV and EMC position due to different distance to center.
145 // we assume, that particle moves from center
146 Float_t dCPV = geom->GetIPtoOuterCoverDistance();
147 Float_t dEMC = geom->GetIPtoCrystalSurface() ;
149 vecCpv = dEMC * vecCpv - vecEmc ;
150 if (Axis == "X") return vecCpv.X();
151 if (Axis == "Y") return vecCpv.Y();
152 if (Axis == "Z") return vecCpv.Z();
153 if (Axis == "R") return vecCpv.Mag();
159 //____________________________________________________________________________
160 void AliPHOSPIDv0::Exec(Option_t * option)
164 if( strcmp(GetName(), "")== 0 )
167 if(strstr(option,"tim"))
168 gBenchmark->Start("PHOSPID");
170 if(strstr(option,"print")) {
175 AliRunLoader* runget = AliRunLoader::GetRunLoader(GetTitle());
178 AliError(Form("Can not find run getter in event folder \"%s\"",
183 AliPHOSLoader* gime = dynamic_cast<AliPHOSLoader*>(runget->GetLoader("PHOSLoader"));
186 AliError("Could not obtain the Loader object !");
190 if(gime->BranchExists("RecParticles") )
194 Int_t nevents = runget->GetNumberOfEvents() ; //(Int_t) gAlice->TreeE()->GetEntries() ;
198 for(ievent = 0; ievent < nevents; ievent++){
199 runget->GetEvent(ievent);
200 AliInfo(Form("event %d %d %d",
201 ievent, gime->EmcRecPoints(),
202 gime->TrackSegments())) ;
207 if(strstr(option,"deb"))
208 PrintRecParticles(option) ;
210 //increment the total number of rec particles per run
211 fRecParticlesInRun += gime->RecParticles()->GetEntriesFast() ;
215 if(strstr(option,"tim")){
216 gBenchmark->Stop("PHOSPID");
217 AliInfo(Form("took %f seconds for PID %f seconds per event",
218 gBenchmark->GetCpuTime("PHOSPID"),
219 gBenchmark->GetCpuTime("PHOSPID")/nevents)) ;
223 //____________________________________________________________________________
224 void AliPHOSPIDv0::Init()
226 // Make all memory allocations that are not possible in default constructor
227 // Add the PID task to the list of PHOS tasks
229 AliRunLoader* runget = AliRunLoader::GetRunLoader(GetTitle());
232 AliError(Form("Can not find run getter in event folder \"%s\"",
237 AliPHOSLoader* gime = dynamic_cast<AliPHOSLoader*>(runget->GetLoader("PHOSLoader"));
240 AliError("Could not obtain the Loader object !");
245 gime->LoadRecParticles("UPDATE");
249 //____________________________________________________________________________
250 void AliPHOSPIDv0::MakeRecParticles()
252 // Reconstructs the particles from the tracksegments
254 TString taskName(GetName()) ;
255 taskName.Remove(taskName.Index(Version())-1) ;
257 AliRunLoader* runget = AliRunLoader::GetRunLoader(GetTitle());
260 AliError(Form("Can not find run getter in event folder \"%s\"",
265 AliPHOSLoader* gime = dynamic_cast<AliPHOSLoader*>(runget->GetLoader("PHOSLoader"));
268 AliError("Could not obtain the Loader object !");
272 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
273 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
274 TClonesArray * trackSegments = gime->TrackSegments() ;
275 TClonesArray * recParticles = gime->RecParticles() ;
277 recParticles->Clear();
279 TIter next(trackSegments) ;
280 AliPHOSTrackSegment * ts ;
282 AliPHOSRecParticle * rp ;
284 Bool_t ellips = fIDOptions.Contains("ell",TString::kIgnoreCase ) ;
285 Bool_t disp = fIDOptions.Contains("dis",TString::kIgnoreCase ) ;
286 Bool_t time = fIDOptions.Contains("tim",TString::kIgnoreCase ) ;
288 while ( (ts = (AliPHOSTrackSegment *)next()) ) {
290 new( (*recParticles)[index] ) AliPHOSRecParticle() ;
291 rp = (AliPHOSRecParticle *)recParticles->At(index) ;
292 rp->SetTrackSegment(index) ;
293 rp->SetIndexInList(index) ;
295 AliPHOSEmcRecPoint * emc = 0 ;
296 if(ts->GetEmcIndex()>=0)
297 emc = (AliPHOSEmcRecPoint *) emcRecPoints->At(ts->GetEmcIndex()) ;
299 AliPHOSRecPoint * cpv = 0 ;
300 if(ts->GetCpvIndex()>=0)
301 cpv = (AliPHOSRecPoint *) cpvRecPoints->At(ts->GetCpvIndex()) ;
303 //set momentum and energy first
304 Float_t e = emc->GetEnergy() ;
305 TVector3 dir = GetMomentumDirection(emc,cpv) ;
308 rp->SetMomentum(dir.X(),dir.Y(),dir.Z(),e) ;
311 //now set type (reconstructed) of the particle
312 Int_t showerprofile = 0; // 0 narrow and 1 wide
316 emc->GetElipsAxis(lambda) ;
317 if(fFormula->Eval(lambda[0],lambda[1]) <= 0 )
318 showerprofile = 1 ; // not narrow
322 if(emc->GetDispersion() > fDispersion )
323 showerprofile = 1 ; // not narrow
327 if(emc->GetTime() > fTimeGate )
330 // Looking at the CPV detector
331 Int_t cpvdetector= 0 ; //1 hit and 0 no hit
333 if(GetDistance(emc, cpv, "R") < fCpvEmcDistance)
336 Int_t type = showerprofile + 2 * slow + 4 * cpvdetector ;
338 rp->SetProductionVertex(0,0,0,0);
339 rp->SetFirstMother(-1);
340 rp->SetLastMother(-1);
341 rp->SetFirstDaughter(-1);
342 rp->SetLastDaughter(-1);
343 rp->SetPolarisation(0,0,0);
349 //____________________________________________________________________________
350 void AliPHOSPIDv0:: Print(const Option_t *) const
352 // Print the parameters used for the particle type identification
354 message = "=============== AliPHOSPIDv0 ================\n" ;
355 message += "Making PID\n" ;
356 message += " Headers file: %s\n" ;
357 message += " RecPoints branch title: %s\n" ;
358 message += " TrackSegments Branch title: %s\n" ;
359 message += " RecParticles Branch title %s\n" ;
360 message += "with parameters:\n" ;
361 message += " Maximal EMC - CPV distance (cm) %f\n" ;
362 AliInfo(Form( message.Data(),
364 fRecPointsTitle.Data(),
365 fTrackSegmentsTitle.Data(),
366 fRecParticlesTitle.Data(),
369 if(fIDOptions.Contains("dis",TString::kIgnoreCase ))
370 AliInfo(Form(" dispersion cut %f", fDispersion )) ;
371 if(fIDOptions.Contains("ell",TString::kIgnoreCase ))
372 AliInfo(Form(" Eliptic cuts function: %s",
373 fFormula->GetTitle() )) ;
374 if(fIDOptions.Contains("tim",TString::kIgnoreCase ))
375 AliInfo(Form(" Time Gate used: %f", fTimeGate)) ;
378 //____________________________________________________________________________
379 void AliPHOSPIDv0::SetShowerProfileCut(const char * formula)
381 //set shape of the cut on the axis of ellipce, drown around shouer
382 //shower considered "narrow" if Formula(lambda[0],lambda[1]) > 0.
385 fFormula = new TFormula("Lambda Cut",formula) ;
387 //____________________________________________________________________________
388 void AliPHOSPIDv0::WriteRecParticles()
390 // Saves the reconstructed particles too a file
392 AliRunLoader* runget = AliRunLoader::GetRunLoader(GetTitle());
395 AliError(Form("Can not find run getter in event folder \"%s\"",
400 AliPHOSLoader* gime = dynamic_cast<AliPHOSLoader*>(runget->GetLoader("PHOSLoader"));
403 AliError("Could not obtain the Loader object !");
407 TClonesArray * recParticles = gime->RecParticles() ;
408 recParticles->Expand(recParticles->GetEntriesFast() ) ;
410 TTree * treeR = gime->TreeR();
414 treeR = gime->TreeR() ;
418 Int_t bufferSize = 32000 ;
419 TBranch * rpBranch = treeR->Branch("PHOSRP",&recParticles,bufferSize);
420 rpBranch->SetTitle(fRecParticlesTitle);
423 Int_t splitlevel = 0 ;
424 AliPHOSPIDv0 * pid = this ;
425 TBranch * pidBranch = treeR->Branch("AliPHOSPID","AliPHOSPIDv0",&pid,bufferSize,splitlevel);
426 pidBranch->SetTitle(fRecParticlesTitle.Data());
431 gime->WriteRecParticles("OVERWRITE");
432 gime->WritePID("OVERWRITE");
436 //____________________________________________________________________________
437 void AliPHOSPIDv0::PlotDispersionCuts()const
439 // produces a plot of the dispersion cut
440 TCanvas* lambdas = new TCanvas("lambdas","Cuts on the ellipse axis",200,10,700,500);
442 if(fIDOptions.Contains("ell",TString::kIgnoreCase ) ){
443 TF2 * ell = new TF2("Elliptic Cuts",fFormula->GetName(),0,3,0,3) ;
444 ell->SetMinimum(0.0000001) ;
445 ell->SetMaximum(0.001) ;
446 ell->SetLineStyle(1) ;
447 ell->SetLineWidth(2) ;
451 if( fIDOptions.Contains("dis",TString::kIgnoreCase ) ){
452 TF2 * dsp = new TF2("dispersion","(y<x)*(x*x+y*y < [0]*[0])",0,3,0,3) ;
453 dsp->SetParameter(0,fDispersion) ;
454 dsp->SetMinimum(0.0000001) ;
455 dsp->SetMaximum(0.001) ;
456 dsp->SetLineStyle(1) ;
457 dsp->SetLineColor(2) ;
458 dsp->SetLineWidth(2) ;
461 if(fIDOptions.Contains("ell",TString::kIgnoreCase ) )
469 //____________________________________________________________________________
470 TVector3 AliPHOSPIDv0::GetMomentumDirection(AliPHOSEmcRecPoint * emc, AliPHOSRecPoint * )const
472 // Calculates the momentum direction:
473 // 1. if only a EMC RecPoint, direction is given by IP and this RecPoint
474 // 2. if a EMC RecPoint and CPV RecPoint, direction is given by the line through the 2 recpoints
475 // However because of the poor position resolution of PPSD the direction is always taken as if we were
478 TVector3 dir(0,0,0) ;
480 TVector3 emcglobalpos ;
483 emc->GetGlobalPosition(emcglobalpos, dummy) ;
486 // The following commented code becomes valid once the PPSD provides
487 // a reasonable position resolution, at least as good as EMC !
488 // TVector3 ppsdlglobalpos ;
489 // TVector3 ppsduglobalpos ;
490 // if( fPpsdLowRecPoint ){ // certainly a photon that has concerted
491 // fPpsdLowRecPoint->GetGlobalPosition(ppsdlglobalpos, mdummy) ;
492 // dir = emcglobalpos - ppsdlglobalpos ;
493 // if( fPpsdUpRecPoint ){ // not looks like a charged
494 // fPpsdUpRecPoint->GetGlobalPosition(ppsduglobalpos, mdummy) ;
495 // dir = ( dir + emcglobalpos - ppsduglobalpos ) * 0.5 ;
498 // else { // looks like a neutral
499 // dir = emcglobalpos ;
503 dir.SetZ( -dir.Z() ) ; // why ?
506 //account correction to the position of IP
507 Float_t xo,yo,zo ; //Coordinates of the origin
508 gAlice->Generator()->GetOrigin(xo,yo,zo) ;
509 TVector3 origin(xo,yo,zo);
514 //____________________________________________________________________________
515 void AliPHOSPIDv0::PrintRecParticles(Option_t * option)
517 // Print table of reconstructed particles
519 AliRunLoader* runget = AliRunLoader::GetRunLoader(GetTitle());
522 AliError(Form("Can not find run getter in event folder \"%s\"",
527 AliPHOSLoader* gime = dynamic_cast<AliPHOSLoader*>(runget->GetLoader("PHOSLoader"));
530 AliError("Could not obtain the Loader object !");
534 TString taskName(GetName()) ;
535 taskName.Remove(taskName.Index(Version())-1) ;
536 TClonesArray * recParticles = gime->RecParticles() ;
539 message = "event %d\n" ;
540 message += " found %d RecParticles\n" ;
541 AliInfo(Form(message.Data(),
542 gAlice->GetEvNumber(), recParticles->GetEntriesFast() )) ;
544 if(strstr(option,"all")) { // printing found TS
545 AliInfo(" PARTICLE Index" ) ;
548 for (index = 0 ; index < recParticles->GetEntries() ; index++) {
549 AliPHOSRecParticle * rp = (AliPHOSRecParticle * ) recParticles->At(index) ;
552 switch(rp->GetType()) {
553 case AliPHOSFastRecParticle::kNEUTRALEMFAST:
554 strcpy( particle, "NEUTRAL EM FAST");
556 case AliPHOSFastRecParticle::kNEUTRALHAFAST:
557 strcpy(particle, "NEUTRAL HA FAST");
559 case AliPHOSFastRecParticle::kNEUTRALEMSLOW:
560 strcpy(particle, "NEUTRAL EM SLOW");
562 case AliPHOSFastRecParticle::kNEUTRALHASLOW:
563 strcpy(particle, "NEUTRAL HA SLOW");
565 case AliPHOSFastRecParticle::kCHARGEDEMFAST:
566 strcpy(particle, "CHARGED EM FAST") ;
568 case AliPHOSFastRecParticle::kCHARGEDHAFAST:
569 strcpy(particle, "CHARGED HA FAST") ;
571 case AliPHOSFastRecParticle::kCHARGEDEMSLOW:
572 strcpy(particle, "CHARGEDEMSLOW") ;
574 case AliPHOSFastRecParticle::kCHARGEDHASLOW:
575 strcpy(particle, "CHARGED HA SLOW") ;
579 // Int_t * primaries;
581 // primaries = rp->GetPrimaries(nprimaries);
583 AliInfo(Form(" %s %d",
584 particle, rp->GetIndexInList())) ;