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.101 2007/03/06 06:51:27 kharlov
22 * Calculation of cluster properties dep. on vertex posponed to TrackSegmentMaker
24 * Revision 1.100 2007/01/10 11:07:26 kharlov
25 * Raw digits writing to file (B.Polichtchouk)
27 * Revision 1.99 2006/11/07 16:49:51 kharlov
28 * Corrections for next event switch in case of raw data (B.Polichtchouk)
30 * Revision 1.98 2006/10/27 17:14:27 kharlov
31 * Introduce AliDebug and AliLog (B.Polichtchouk)
33 * Revision 1.97 2006/08/29 11:41:19 kharlov
34 * Missing implementation of ctors and = operator are added
36 * Revision 1.96 2006/08/25 16:56:30 kharlov
37 * Compliance with Effective C++
39 * Revision 1.95 2006/08/11 12:36:26 cvetan
40 * Update of the PHOS code needed in order to read and reconstruct the beam test raw data (i.e. without an existing galice.root)
42 * Revision 1.94 2006/08/07 12:27:49 hristov
43 * Removing obsolete code which affected the event numbering scheme
45 * Revision 1.93 2006/08/01 12:20:17 cvetan
46 * 1. Adding a possibility to read and reconstruct an old rcu formatted raw data. This is controlled by an option of AliReconstruction and AliPHOSReconstructor. 2. In case of raw data processing (without galice.root) create the default AliPHOSGeometry object. Most likely this should be moved to the CDB
48 * Revision 1.92 2006/04/29 20:26:46 hristov
49 * Separate EMC and CPV calibration (Yu.Kharlov)
51 * Revision 1.91 2006/04/22 10:30:17 hristov
52 * Add fEnergy to AliPHOSDigit and operate with EMC amplitude in energy units (Yu.Kharlov)
54 * Revision 1.90 2006/04/11 15:22:59 hristov
55 * run number in query set to -1: forces AliCDBManager to use its run number (A.Colla)
57 * Revision 1.89 2006/03/13 14:05:42 kharlov
58 * Calibration objects for EMC and CPV
60 * Revision 1.88 2006/01/11 08:54:52 hristov
61 * Additional protection in case no calibration entry was found
63 * Revision 1.87 2005/11/22 08:46:43 kharlov
64 * Updated to new CDB (Boris Polichtchouk)
66 * Revision 1.86 2005/11/14 21:52:43 hristov
69 * Revision 1.85 2005/09/27 16:08:08 hristov
70 * New version of CDB storage framework (A.Colla)
72 * Revision 1.84 2005/09/21 10:02:47 kharlov
73 * Reading calibration from CDB (Boris Polichtchouk)
75 * Revision 1.82 2005/09/02 15:43:13 kharlov
76 * Add comments in GetCalibrationParameters and Calibrate
78 * Revision 1.81 2005/09/02 14:32:07 kharlov
79 * Calibration of raw data
81 * Revision 1.80 2005/08/24 15:31:36 kharlov
82 * Setting raw digits flag
84 * Revision 1.79 2005/07/25 15:53:53 kharlov
87 * Revision 1.78 2005/05/28 14:19:04 schutz
88 * Compilation warnings fixed by T.P.
92 //*-- Author: Yves Schutz (SUBATECH) & Dmitri Peressounko (SUBATECH & Kurchatov Institute)
93 //////////////////////////////////////////////////////////////////////////////
94 // Clusterization class. Performs clusterization (collects neighbouring active cells) and
95 // unfolds the clusters having several local maxima.
96 // Results are stored in TreeR#, branches PHOSEmcRP (EMC recPoints),
97 // PHOSCpvRP (CPV RecPoints) and AliPHOSClusterizer (Clusterizer with all
98 // parameters including input digits branch title, thresholds etc.)
99 // This TTask is normally called from Reconstructioner, but can as well be used in
102 // root [0] AliPHOSClusterizerv1 * cl = new AliPHOSClusterizerv1("galice.root", "recpointsname", "digitsname")
103 // Warning in <TDatabasePDG::TDatabasePDG>: object already instantiated
104 // // reads gAlice from header file "galice.root", uses digits stored in the branch names "digitsname" (default = "Default")
105 // // and saves recpoints in branch named "recpointsname" (default = "digitsname")
106 // root [1] cl->ExecuteTask()
107 // //finds RecPoints in all events stored in galice.root
108 // root [2] cl->SetDigitsBranch("digits2")
109 // //sets another title for Digitis (input) branch
110 // root [3] cl->SetRecPointsBranch("recp2")
111 // //sets another title four output branches
112 // root [4] cl->SetEmcLocalMaxCut(0.03)
113 // //set clusterization parameters
114 // root [5] cl->ExecuteTask("deb all time")
115 // //once more finds RecPoints options are
116 // // deb - print number of found rec points
117 // // deb all - print number of found RecPoints and some their characteristics
118 // // time - print benchmarking results
120 // --- ROOT system ---
125 #include "TBenchmark.h"
127 // --- Standard library ---
129 // --- AliRoot header files ---
131 #include "AliRunLoader.h"
132 #include "AliGenerator.h"
133 #include "AliPHOSGetter.h"
134 #include "AliPHOSGeometry.h"
135 #include "AliPHOSClusterizerv1.h"
136 #include "AliPHOSEmcRecPoint.h"
137 #include "AliPHOSCpvRecPoint.h"
138 #include "AliPHOSDigit.h"
139 #include "AliPHOSDigitizer.h"
140 #include "AliPHOSCalibrationDB.h"
141 #include "AliCDBManager.h"
142 #include "AliCDBStorage.h"
143 #include "AliCDBEntry.h"
145 ClassImp(AliPHOSClusterizerv1)
147 //____________________________________________________________________________
148 AliPHOSClusterizerv1::AliPHOSClusterizerv1() :
149 AliPHOSClusterizer(),
150 fDefaultInit(0), fEmcCrystals(0), fToUnfold(0),
151 fWrite(0), fNumberOfEmcClusters(0), fNumberOfCpvClusters(0),
152 fCalibData(0), fADCchanelEmc(0), fADCpedestalEmc(0),
153 fADCchanelCpv(0), fADCpedestalCpv(0), fEmcClusteringThreshold(0),
154 fCpvClusteringThreshold(0), fEmcMinE(0), fCpvMinE(0),
155 fEmcLocMaxCut(0), fW0(0), fCpvLocMaxCut(0),
156 fW0CPV(0), fRecPointsInRun(0), fEmcTimeGate(0),
159 // default ctor (to be used mainly by Streamer)
162 fDefaultInit = kTRUE ;
165 //____________________________________________________________________________
166 AliPHOSClusterizerv1::AliPHOSClusterizerv1(const TString alirunFileName, const TString eventFolderName) :
167 AliPHOSClusterizer(alirunFileName, eventFolderName),
168 fDefaultInit(0), fEmcCrystals(0), fToUnfold(0),
169 fWrite(0), fNumberOfEmcClusters(0), fNumberOfCpvClusters(0),
170 fCalibData(0), fADCchanelEmc(0), fADCpedestalEmc(0),
171 fADCchanelCpv(0), fADCpedestalCpv(0), fEmcClusteringThreshold(0),
172 fCpvClusteringThreshold(0), fEmcMinE(0), fCpvMinE(0),
173 fEmcLocMaxCut(0), fW0(0), fCpvLocMaxCut(0),
174 fW0CPV(0), fRecPointsInRun(0), fEmcTimeGate(0),
177 // ctor with the indication of the file where header Tree and digits Tree are stored
181 fDefaultInit = kFALSE ;
184 //____________________________________________________________________________
185 AliPHOSClusterizerv1::AliPHOSClusterizerv1(const AliPHOSClusterizerv1 & obj) :
186 AliPHOSClusterizer(obj),
187 fDefaultInit(0), fEmcCrystals(0), fToUnfold(0),
188 fWrite(0), fNumberOfEmcClusters(0), fNumberOfCpvClusters(0),
189 fCalibData(0), fADCchanelEmc(0), fADCpedestalEmc(0),
190 fADCchanelCpv(0), fADCpedestalCpv(0), fEmcClusteringThreshold(0),
191 fCpvClusteringThreshold(0), fEmcMinE(0), fCpvMinE(0),
192 fEmcLocMaxCut(0), fW0(0), fCpvLocMaxCut(0),
193 fW0CPV(0), fRecPointsInRun(0), fEmcTimeGate(0),
198 //____________________________________________________________________________
199 AliPHOSClusterizerv1::~AliPHOSClusterizerv1()
204 //____________________________________________________________________________
205 const TString AliPHOSClusterizerv1::BranchName() const
210 //____________________________________________________________________________
211 Float_t AliPHOSClusterizerv1::CalibrateEMC(Float_t amp, Int_t absId)
213 // Convert EMC measured amplitude into real energy.
214 // Calibration parameters are taken from calibration data base for raw data,
215 // or from digitizer parameters for simulated data.
219 AliPHOSGetter *gime = AliPHOSGetter::Instance();
220 gime->PHOSGeometry()->AbsToRelNumbering(absId,relId) ;
221 Int_t module = relId[0];
222 Int_t column = relId[3];
223 Int_t row = relId[2];
224 if(absId <= fEmcCrystals) { // this is EMC
225 fADCchanelEmc = fCalibData->GetADCchannelEmc (module,column,row);
226 return amp*fADCchanelEmc ;
230 if(absId <= fEmcCrystals) // this is EMC
231 return fADCpedestalEmc + amp*fADCchanelEmc ;
236 //____________________________________________________________________________
237 Float_t AliPHOSClusterizerv1::CalibrateCPV(Int_t amp, Int_t absId)
239 // Convert digitized CPV amplitude into charge.
240 // Calibration parameters are taken from calibration data base for raw data,
241 // or from digitizer parameters for simulated data.
245 AliPHOSGetter *gime = AliPHOSGetter::Instance();
246 gime->PHOSGeometry()->AbsToRelNumbering(absId,relId) ;
247 Int_t module = relId[0];
248 Int_t column = relId[3];
249 Int_t row = relId[2];
250 if(absId > fEmcCrystals) { // this is CPV
251 fADCchanelCpv = fCalibData->GetADCchannelCpv (module,column,row);
252 fADCpedestalCpv = fCalibData->GetADCpedestalCpv(module,column,row);
253 return fADCpedestalCpv + amp*fADCchanelCpv ;
257 if(absId > fEmcCrystals) // this is CPV
258 return fADCpedestalCpv+ amp*fADCchanelCpv ;
263 //____________________________________________________________________________
264 void AliPHOSClusterizerv1::Exec(Option_t *option)
266 // Steering method to perform clusterization for events
267 // in the range from fFirstEvent to fLastEvent.
268 // This range is optionally set by SetEventRange().
269 // if fLastEvent=-1 (by default), then process events until the end.
271 if(strstr(option,"tim"))
272 gBenchmark->Start("PHOSClusterizer");
274 if(strstr(option,"print")) {
279 GetCalibrationParameters() ;
281 AliPHOSGetter * gime = AliPHOSGetter::Instance() ;
283 gime->SetRawDigits(kFALSE);
285 gime->SetRawDigits(kTRUE);
287 if (fLastEvent == -1)
288 fLastEvent = gime->MaxEvent() - 1 ;
290 fLastEvent = TMath::Min(fFirstEvent, gime->MaxEvent()); // one event at the time
291 Int_t nEvents = fLastEvent - fFirstEvent + 1;
294 for (ievent = fFirstEvent; ievent <= fLastEvent; ievent++) {
296 gime->Event(ievent ,"D"); // Read digits from simulated data
298 AliRunLoader * rl = AliRunLoader::GetRunLoader(gime->PhosLoader()->GetTitle());
299 rl->GetEvent(ievent);
300 gime->Event(fRawReader,"W",fIsOldRCUFormat); // Read digits from raw data
302 fNumberOfEmcClusters = fNumberOfCpvClusters = 0 ;
306 AliDebug(2,Form(" ---- Printing clusters (%d) of event %d.\n",
307 gime->EmcRecPoints()->GetEntries(),ievent));
308 if(AliLog::GetGlobalDebugLevel()>1)
309 gime->EmcRecPoints()->Print();
316 if(strstr(option,"deb"))
317 PrintRecPoints(option) ;
319 //increment the total number of recpoints per run
320 fRecPointsInRun += gime->EmcRecPoints()->GetEntriesFast() ;
321 fRecPointsInRun += gime->CpvRecPoints()->GetEntriesFast() ;
324 if(fWrite) //do not unload in "on flight" mode
327 if(strstr(option,"tim")){
328 gBenchmark->Stop("PHOSClusterizer");
329 AliInfo(Form("took %f seconds for Clusterizing %f seconds per event \n",
330 gBenchmark->GetCpuTime("PHOSClusterizer"),
331 gBenchmark->GetCpuTime("PHOSClusterizer")/nEvents )) ;
335 //____________________________________________________________________________
336 Bool_t AliPHOSClusterizerv1::FindFit(AliPHOSEmcRecPoint * emcRP, AliPHOSDigit ** maxAt, Float_t * maxAtEnergy,
337 Int_t nPar, Float_t * fitparameters) const
339 // Calls TMinuit to fit the energy distribution of a cluster with several maxima
340 // The initial values for fitting procedure are set equal to the positions of local maxima.
341 // Cluster will be fitted as a superposition of nPar/3 electromagnetic showers
344 AliPHOSGetter * gime = AliPHOSGetter::Instance();
345 TClonesArray * digits = gime->Digits();
347 gMinuit->mncler(); // Reset Minuit's list of paramters
348 gMinuit->SetPrintLevel(-1) ; // No Printout
349 gMinuit->SetFCN(AliPHOSClusterizerv1::UnfoldingChiSquare) ;
350 // To set the address of the minimization function
352 TList * toMinuit = new TList();
353 toMinuit->AddAt(emcRP,0) ;
354 toMinuit->AddAt(digits,1) ;
356 gMinuit->SetObjectFit(toMinuit) ; // To tranfer pointer to UnfoldingChiSquare
358 // filling initial values for fit parameters
359 AliPHOSDigit * digit ;
363 Int_t nDigits = (Int_t) nPar / 3 ;
367 const AliPHOSGeometry * geom = gime->PHOSGeometry() ;
369 for(iDigit = 0; iDigit < nDigits; iDigit++){
370 digit = maxAt[iDigit];
375 geom->AbsToRelNumbering(digit->GetId(), relid) ;
376 geom->RelPosInModule(relid, x, z) ;
378 Float_t energy = maxAtEnergy[iDigit] ;
380 gMinuit->mnparm(index, "x", x, 0.1, 0, 0, ierflg) ;
383 Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : x = %f\n", x ) ;
386 gMinuit->mnparm(index, "z", z, 0.1, 0, 0, ierflg) ;
389 Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : z =%f\n", z ) ;
392 gMinuit->mnparm(index, "Energy", energy , 0.05*energy, 0., 4.*energy, ierflg) ;
395 Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : energy = %f\n", energy ) ;
400 Double_t p0 = 0.1 ; // "Tolerance" Evaluation stops when EDM = 0.0001*p0 ; The number of function call slightly
405 gMinuit->mnexcm("SET STR", &p2, 0, ierflg) ; // force TMinuit to reduce function calls
406 gMinuit->mnexcm("SET GRA", &p1, 1, ierflg) ; // force TMinuit to use my gradient
407 gMinuit->SetMaxIterations(5);
408 gMinuit->mnexcm("SET NOW", &p2 , 0, ierflg) ; // No Warnings
410 gMinuit->mnexcm("MIGRAD", &p0, 0, ierflg) ; // minimize
412 if(ierflg == 4){ // Minimum not found
413 Warning("FindFit", "PHOS Unfolding fit not converged, cluster abandoned\n" );
416 for(index = 0; index < nPar; index++){
419 gMinuit->GetParameter(index, val, err) ; // Returns value and error of parameter index
420 fitparameters[index] = val ;
428 //____________________________________________________________________________
429 void AliPHOSClusterizerv1::GetCalibrationParameters()
431 // Set calibration parameters:
432 // if calibration database exists, they are read from database,
433 // otherwise, they are taken from digitizer.
435 // It is a user responsilibity to open CDB before reconstruction, for example:
436 // AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage("local://CalibDB");
438 AliPHOSGetter * gime = AliPHOSGetter::Instance();
439 // fCalibData = new AliPHOSCalibData(gAlice->GetRunNumber()); //original
441 fCalibData = new AliPHOSCalibData(-1); //use AliCDBManager's run number
445 if ( !gime->Digitizer() )
446 gime->LoadDigitizer();
447 AliPHOSDigitizer * dig = gime->Digitizer();
448 fADCchanelEmc = dig->GetEMCchannel() ;
449 fADCpedestalEmc = dig->GetEMCpedestal();
451 fADCchanelCpv = dig->GetCPVchannel() ;
452 fADCpedestalCpv = dig->GetCPVpedestal() ;
456 //____________________________________________________________________________
457 void AliPHOSClusterizerv1::Init()
459 // Make all memory allocations which can not be done in default constructor.
460 // Attach the Clusterizer task to the list of PHOS tasks
462 AliPHOSGetter* gime = AliPHOSGetter::Instance() ;
464 gime = AliPHOSGetter::Instance(GetTitle(), fEventFolderName.Data());
466 AliPHOSGeometry * geom = gime->PHOSGeometry();
468 fEmcCrystals = geom->GetNModules() * geom->GetNCristalsInModule() ;
471 gMinuit = new TMinuit(100);
473 if ( !gime->Clusterizer() ) {
474 gime->PostClusterizer(this);
478 //____________________________________________________________________________
479 void AliPHOSClusterizerv1::InitParameters()
482 fNumberOfCpvClusters = 0 ;
483 fNumberOfEmcClusters = 0 ;
485 fCpvClusteringThreshold = 0.0;
486 fEmcClusteringThreshold = 0.2;
488 fEmcLocMaxCut = 0.03 ;
489 fCpvLocMaxCut = 0.03 ;
497 fEmcTimeGate = 1.e-8 ;
501 fRecPointsInRun = 0 ;
507 SetEventRange(0,-1) ;
509 fIsOldRCUFormat = kFALSE;
512 //____________________________________________________________________________
513 Int_t AliPHOSClusterizerv1::AreNeighbours(AliPHOSDigit * d1, AliPHOSDigit * d2)const
515 // Gives the neighbourness of two digits = 0 are not neighbour but continue searching
517 // = 2 are not neighbour but do not continue searching
518 // neighbours are defined as digits having at least a common vertex
519 // The order of d1 and d2 is important: first (d1) should be a digit already in a cluster
520 // which is compared to a digit (d2) not yet in a cluster
522 AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
527 geom->AbsToRelNumbering(d1->GetId(), relid1) ;
530 geom->AbsToRelNumbering(d2->GetId(), relid2) ;
532 if ( (relid1[0] == relid2[0]) && (relid1[1]==relid2[1]) ) { // inside the same PHOS module
533 Int_t rowdiff = TMath::Abs( relid1[2] - relid2[2] ) ;
534 Int_t coldiff = TMath::Abs( relid1[3] - relid2[3] ) ;
536 if (( coldiff <= 1 ) && ( rowdiff <= 1 )){
537 if((relid1[1] != 0) || (TMath::Abs(d1->GetTime() - d2->GetTime() ) < fEmcTimeGate))
541 if((relid2[2] > relid1[2]) && (relid2[3] > relid1[3]+1))
542 rv = 2; // Difference in row numbers is too large to look further
548 if( (relid1[0] < relid2[0]) || (relid1[1] != relid2[1]) )
555 //____________________________________________________________________________
556 void AliPHOSClusterizerv1::CleanDigits(TClonesArray * digits)
558 // Remove digits with amplitudes below threshold
560 for(Int_t i=0; i<digits->GetEntriesFast(); i++){
561 AliPHOSDigit * digit = static_cast<AliPHOSDigit*>(digits->At(i)) ;
562 if ( (IsInEmc(digit) && CalibrateEMC(digit->GetEnergy(),digit->GetId()) < fEmcMinE) ||
563 (IsInCpv(digit) && CalibrateCPV(digit->GetAmp() ,digit->GetId()) < fCpvMinE) )
564 digits->RemoveAt(i) ;
567 for (Int_t i = 0 ; i < digits->GetEntriesFast() ; i++) {
568 AliPHOSDigit *digit = static_cast<AliPHOSDigit*>( digits->At(i) ) ;
569 digit->SetIndexInList(i) ;
572 //Overwrite digits tree
573 AliPHOSGetter* gime = AliPHOSGetter::Instance();
574 TTree * treeD = gime->TreeD();
575 treeD->Branch("PHOS", &digits);
577 gime->WriteDigits("OVERWRITE");
578 gime->PhosLoader()->UnloadDigits() ;
580 //____________________________________________________________________________
581 Bool_t AliPHOSClusterizerv1::IsInEmc(AliPHOSDigit * digit) const
583 // Tells if (true) or not (false) the digit is in a PHOS-EMC module
586 AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
588 Int_t nEMC = geom->GetNModules()*geom->GetNPhi()*geom->GetNZ();
590 if(digit->GetId() <= nEMC ) rv = kTRUE;
595 //____________________________________________________________________________
596 Bool_t AliPHOSClusterizerv1::IsInCpv(AliPHOSDigit * digit) const
598 // Tells if (true) or not (false) the digit is in a PHOS-CPV module
602 AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
604 Int_t nEMC = geom->GetNModules()*geom->GetNPhi()*geom->GetNZ();
606 if(digit->GetId() > nEMC ) rv = kTRUE;
611 //____________________________________________________________________________
612 void AliPHOSClusterizerv1::Unload()
614 AliPHOSGetter * gime = AliPHOSGetter::Instance() ;
615 gime->PhosLoader()->UnloadDigits() ;
616 gime->PhosLoader()->UnloadRecPoints() ;
619 //____________________________________________________________________________
620 void AliPHOSClusterizerv1::WriteRecPoints()
623 // Creates new branches with given title
624 // fills and writes into TreeR.
626 AliPHOSGetter * gime = AliPHOSGetter::Instance();
628 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
629 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
630 TClonesArray * digits = gime->Digits() ;
633 //Evaluate position, dispersion and other RecPoint properties..
634 Int_t nEmc = emcRecPoints->GetEntriesFast();
635 for(index = 0; index < nEmc; index++){
636 AliPHOSEmcRecPoint * rp = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(index) );
637 rp->Purify(fEmcMinE) ;
638 if(rp->GetMultiplicity()==0){
639 emcRecPoints->RemoveAt(index) ;
643 // No vertex is available now, calculate cirrections in PID
644 rp->EvalAll(fW0,digits) ;
645 TVector3 fakeVtx(0.,0.,0.) ;
646 rp->EvalAll(fW0,fakeVtx,digits) ;
648 emcRecPoints->Compress() ;
649 // emcRecPoints->Sort() ; //Can not sort until position is calculated!
650 // emcRecPoints->Expand(emcRecPoints->GetEntriesFast()) ;
651 for(index = 0; index < emcRecPoints->GetEntries(); index++){
652 dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(index) )->SetIndexInList(index) ;
655 //Now the same for CPV
656 for(index = 0; index < cpvRecPoints->GetEntries(); index++){
657 AliPHOSCpvRecPoint * rp = dynamic_cast<AliPHOSCpvRecPoint *>( cpvRecPoints->At(index) );
658 rp->EvalAll(fW0CPV,digits) ;
660 // cpvRecPoints->Sort() ;
662 for(index = 0; index < cpvRecPoints->GetEntries(); index++)
663 dynamic_cast<AliPHOSCpvRecPoint *>( cpvRecPoints->At(index) )->SetIndexInList(index) ;
665 cpvRecPoints->Expand(cpvRecPoints->GetEntriesFast()) ;
667 if(fWrite){ //We write TreeR
668 TTree * treeR = gime->TreeR();
670 Int_t bufferSize = 32000 ;
671 Int_t splitlevel = 0 ;
674 TBranch * emcBranch = treeR->Branch("PHOSEmcRP","TObjArray",&emcRecPoints,bufferSize,splitlevel);
675 emcBranch->SetTitle(BranchName());
678 TBranch * cpvBranch = treeR->Branch("PHOSCpvRP","TObjArray",&cpvRecPoints,bufferSize,splitlevel);
679 cpvBranch->SetTitle(BranchName());
684 gime->WriteRecPoints("OVERWRITE");
685 gime->WriteClusterizer("OVERWRITE");
689 //____________________________________________________________________________
690 void AliPHOSClusterizerv1::MakeClusters()
692 // Steering method to construct the clusters stored in a list of Reconstructed Points
693 // A cluster is defined as a list of neighbour digits
696 AliPHOSGetter * gime = AliPHOSGetter::Instance();
698 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
699 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
701 emcRecPoints->Delete() ;
702 cpvRecPoints->Delete() ;
704 TClonesArray * digits = gime->Digits() ;
706 //Remove digits below threshold
707 CleanDigits(digits) ;
709 TClonesArray * digitsC = static_cast<TClonesArray*>( digits->Clone() ) ;
711 // Clusterization starts
713 TIter nextdigit(digitsC) ;
714 AliPHOSDigit * digit ;
715 Bool_t notremoved = kTRUE ;
717 while ( (digit = dynamic_cast<AliPHOSDigit *>( nextdigit()) ) ) { // scan over the list of digitsC
720 AliPHOSRecPoint * clu = 0 ;
722 TArrayI clusterdigitslist(1500) ;
725 if (( IsInEmc (digit) &&
726 CalibrateEMC(digit->GetEnergy(),digit->GetId()) > fEmcClusteringThreshold ) ||
728 CalibrateCPV(digit->GetAmp() ,digit->GetId()) > fCpvClusteringThreshold ) ) {
729 Int_t iDigitInCluster = 0 ;
731 if ( IsInEmc(digit) ) {
732 // start a new EMC RecPoint
733 if(fNumberOfEmcClusters >= emcRecPoints->GetSize())
734 emcRecPoints->Expand(2*fNumberOfEmcClusters+1) ;
736 emcRecPoints->AddAt(new AliPHOSEmcRecPoint(""), fNumberOfEmcClusters) ;
737 clu = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(fNumberOfEmcClusters) ) ;
738 fNumberOfEmcClusters++ ;
739 clu->AddDigit(*digit, CalibrateEMC(digit->GetEnergy(),digit->GetId())) ;
740 clusterdigitslist[iDigitInCluster] = digit->GetIndexInList() ;
742 digitsC->Remove(digit) ;
746 // start a new CPV cluster
747 if(fNumberOfCpvClusters >= cpvRecPoints->GetSize())
748 cpvRecPoints->Expand(2*fNumberOfCpvClusters+1);
750 cpvRecPoints->AddAt(new AliPHOSCpvRecPoint(""), fNumberOfCpvClusters) ;
752 clu = dynamic_cast<AliPHOSCpvRecPoint *>( cpvRecPoints->At(fNumberOfCpvClusters) ) ;
753 fNumberOfCpvClusters++ ;
754 clu->AddDigit(*digit, CalibrateCPV(digit->GetAmp(),digit->GetId()) ) ;
755 clusterdigitslist[iDigitInCluster] = digit->GetIndexInList() ;
757 digitsC->Remove(digit) ;
760 // Here we remove remaining EMC digits, which cannot make a cluster
763 while( ( digit = dynamic_cast<AliPHOSDigit *>( nextdigit() ) ) ) {
765 digitsC->Remove(digit) ;
769 notremoved = kFALSE ;
776 AliPHOSDigit * digitN ;
778 while (index < iDigitInCluster){ // scan over digits already in cluster
779 digit = dynamic_cast<AliPHOSDigit*>( digits->At(clusterdigitslist[index]) ) ;
781 while ( (digitN = dynamic_cast<AliPHOSDigit *>( nextdigit() ) ) ) { // scan over the reduced list of digits
782 Int_t ineb = AreNeighbours(digit, digitN); // call (digit,digitN) in THAT oder !!!!!
784 case 0 : // not a neighbour
786 case 1 : // are neighbours
787 if (IsInEmc (digitN))
788 clu->AddDigit(*digitN, CalibrateEMC( digitN->GetEnergy(), digitN->GetId() ) );
790 clu->AddDigit(*digitN, CalibrateCPV( digitN->GetAmp() , digitN->GetId() ) );
792 clusterdigitslist[iDigitInCluster] = digitN->GetIndexInList() ;
794 digitsC->Remove(digitN) ;
796 case 2 : // too far from each other
805 } // loop over cluster
816 //____________________________________________________________________________
817 void AliPHOSClusterizerv1::MakeUnfolding()
819 // Unfolds clusters using the shape of an ElectroMagnetic shower
820 // Performs unfolding of all EMC/CPV clusters
822 AliPHOSGetter * gime = AliPHOSGetter::Instance();
824 const AliPHOSGeometry * geom = gime->PHOSGeometry() ;
826 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
827 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
828 TClonesArray * digits = gime->Digits() ;
830 // Unfold first EMC clusters
831 if(fNumberOfEmcClusters > 0){
833 Int_t nModulesToUnfold = geom->GetNModules() ;
835 Int_t numberofNotUnfolded = fNumberOfEmcClusters ;
837 for(index = 0 ; index < numberofNotUnfolded ; index++){
839 AliPHOSEmcRecPoint * emcRecPoint = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(index) ) ;
840 if(emcRecPoint->GetPHOSMod()> nModulesToUnfold)
843 Int_t nMultipl = emcRecPoint->GetMultiplicity() ;
844 AliPHOSDigit ** maxAt = new AliPHOSDigit*[nMultipl] ;
845 Float_t * maxAtEnergy = new Float_t[nMultipl] ;
846 Int_t nMax = emcRecPoint->GetNumberOfLocalMax(maxAt, maxAtEnergy,fEmcLocMaxCut,digits) ;
848 if( nMax > 1 ) { // if cluster is very flat (no pronounced maximum) then nMax = 0
849 UnfoldCluster(emcRecPoint, nMax, maxAt, maxAtEnergy) ;
850 emcRecPoints->Remove(emcRecPoint);
851 emcRecPoints->Compress() ;
853 fNumberOfEmcClusters -- ;
854 numberofNotUnfolded-- ;
857 emcRecPoint->SetNExMax(1) ; //Only one local maximum
861 delete[] maxAtEnergy ;
864 // Unfolding of EMC clusters finished
867 // Unfold now CPV clusters
868 if(fNumberOfCpvClusters > 0){
870 Int_t nModulesToUnfold = geom->GetNModules() ;
872 Int_t numberofCpvNotUnfolded = fNumberOfCpvClusters ;
874 for(index = 0 ; index < numberofCpvNotUnfolded ; index++){
876 AliPHOSRecPoint * recPoint = dynamic_cast<AliPHOSRecPoint *>( cpvRecPoints->At(index) ) ;
878 if(recPoint->GetPHOSMod()> nModulesToUnfold)
881 AliPHOSEmcRecPoint * emcRecPoint = dynamic_cast<AliPHOSEmcRecPoint*>(recPoint) ;
883 Int_t nMultipl = emcRecPoint->GetMultiplicity() ;
884 AliPHOSDigit ** maxAt = new AliPHOSDigit*[nMultipl] ;
885 Float_t * maxAtEnergy = new Float_t[nMultipl] ;
886 Int_t nMax = emcRecPoint->GetNumberOfLocalMax(maxAt, maxAtEnergy,fCpvLocMaxCut,digits) ;
888 if( nMax > 1 ) { // if cluster is very flat (no pronounced maximum) then nMax = 0
889 UnfoldCluster(emcRecPoint, nMax, maxAt, maxAtEnergy) ;
890 cpvRecPoints->Remove(emcRecPoint);
891 cpvRecPoints->Compress() ;
893 numberofCpvNotUnfolded-- ;
894 fNumberOfCpvClusters-- ;
898 delete[] maxAtEnergy ;
901 //Unfolding of Cpv clusters finished
905 //____________________________________________________________________________
906 Double_t AliPHOSClusterizerv1::ShowerShape(Double_t x, Double_t z)
908 // Shape of the shower (see PHOS TDR)
909 // If you change this function, change also the gradient evaluation in ChiSquare()
911 //for the moment we neglect dependence on the incident angle.
913 Double_t r2 = x*x + z*z ;
914 Double_t r4 = r2*r2 ;
915 Double_t r295 = TMath::Power(r2, 2.95/2.) ;
916 Double_t shape = TMath::Exp( -r4 * (1. / (2.32 + 0.26 * r4) + 0.0316 / (1 + 0.0652 * r295) ) ) ;
920 //____________________________________________________________________________
921 void AliPHOSClusterizerv1::UnfoldCluster(AliPHOSEmcRecPoint * iniEmc,
923 AliPHOSDigit ** maxAt,
924 Float_t * maxAtEnergy)
926 // Performs the unfolding of a cluster with nMax overlapping showers
928 AliPHOSGetter * gime = AliPHOSGetter::Instance();
930 const AliPHOSGeometry * geom = gime->PHOSGeometry() ;
932 const TClonesArray * digits = gime->Digits() ;
933 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
934 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
936 Int_t nPar = 3 * nMax ;
937 Float_t * fitparameters = new Float_t[nPar] ;
939 Bool_t rv = FindFit(iniEmc, maxAt, maxAtEnergy, nPar, fitparameters) ;
941 // Fit failed, return and remove cluster
942 iniEmc->SetNExMax(-1) ;
943 delete[] fitparameters ;
947 // create ufolded rec points and fill them with new energy lists
948 // First calculate energy deposited in each sell in accordance with fit (without fluctuations): efit[]
949 // and later correct this number in acordance with actual energy deposition
951 Int_t nDigits = iniEmc->GetMultiplicity() ;
952 Float_t * efit = new Float_t[nDigits] ;
953 Float_t xDigit=0.,zDigit=0. ;
954 Float_t xpar=0.,zpar=0.,epar=0. ;
956 AliPHOSDigit * digit = 0 ;
957 Int_t * emcDigits = iniEmc->GetDigitsList() ;
963 for(iDigit = 0 ; iDigit < nDigits ; iDigit ++){
964 digit = dynamic_cast<AliPHOSDigit*>( digits->At(emcDigits[iDigit] ) ) ;
965 geom->AbsToRelNumbering(digit->GetId(), relid) ;
966 geom->RelPosInModule(relid, xDigit, zDigit) ;
970 while(iparam < nPar ){
971 xpar = fitparameters[iparam] ;
972 zpar = fitparameters[iparam+1] ;
973 epar = fitparameters[iparam+2] ;
975 // geom->GetIncidentVector(fVtx,relid[0],xpar,zpar,vIncid) ;
976 // efit[iDigit] += epar * ShowerShape(xDigit - xpar,zDigit - zpar,vIncid) ;
977 efit[iDigit] += epar * ShowerShape(xDigit - xpar,zDigit - zpar) ;
982 // Now create new RecPoints and fill energy lists with efit corrected to fluctuations
983 // so that energy deposited in each cell is distributed betwin new clusters proportionally
984 // to its contribution to efit
986 Float_t * emcEnergies = iniEmc->GetEnergiesList() ;
990 while(iparam < nPar ){
991 xpar = fitparameters[iparam] ;
992 zpar = fitparameters[iparam+1] ;
993 epar = fitparameters[iparam+2] ;
995 // geom->GetIncidentVector(fVtx,iniEmc->GetPHOSMod(),xpar,zpar,vIncid) ;
997 AliPHOSEmcRecPoint * emcRP = 0 ;
999 if(iniEmc->IsEmc()){ //create new entries in fEmcRecPoints...
1001 if(fNumberOfEmcClusters >= emcRecPoints->GetSize())
1002 emcRecPoints->Expand(2*fNumberOfEmcClusters) ;
1004 (*emcRecPoints)[fNumberOfEmcClusters] = new AliPHOSEmcRecPoint("") ;
1005 emcRP = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(fNumberOfEmcClusters) ) ;
1006 fNumberOfEmcClusters++ ;
1007 emcRP->SetNExMax((Int_t)nPar/3) ;
1009 else{//create new entries in fCpvRecPoints
1010 if(fNumberOfCpvClusters >= cpvRecPoints->GetSize())
1011 cpvRecPoints->Expand(2*fNumberOfCpvClusters) ;
1013 (*cpvRecPoints)[fNumberOfCpvClusters] = new AliPHOSCpvRecPoint("") ;
1014 emcRP = dynamic_cast<AliPHOSEmcRecPoint *>( cpvRecPoints->At(fNumberOfCpvClusters) ) ;
1015 fNumberOfCpvClusters++ ;
1019 for(iDigit = 0 ; iDigit < nDigits ; iDigit ++){
1020 digit = dynamic_cast<AliPHOSDigit*>( digits->At( emcDigits[iDigit] ) ) ;
1021 geom->AbsToRelNumbering(digit->GetId(), relid) ;
1022 geom->RelPosInModule(relid, xDigit, zDigit) ;
1023 // ratio = epar * ShowerShape(xDigit - xpar,zDigit - zpar,vIncid) / efit[iDigit] ;
1024 ratio = epar * ShowerShape(xDigit - xpar,zDigit - zpar) / efit[iDigit] ;
1025 eDigit = emcEnergies[iDigit] * ratio ;
1026 emcRP->AddDigit( *digit, eDigit ) ;
1030 delete[] fitparameters ;
1035 //_____________________________________________________________________________
1036 void AliPHOSClusterizerv1::UnfoldingChiSquare(Int_t & nPar, Double_t * Grad, Double_t & fret, Double_t * x, Int_t iflag)
1038 // Calculates the Chi square for the cluster unfolding minimization
1039 // Number of parameters, Gradient, Chi squared, parameters, what to do
1041 TList * toMinuit = dynamic_cast<TList*>( gMinuit->GetObjectFit() ) ;
1043 AliPHOSEmcRecPoint * emcRP = dynamic_cast<AliPHOSEmcRecPoint*>( toMinuit->At(0) ) ;
1044 TClonesArray * digits = dynamic_cast<TClonesArray*>( toMinuit->At(1) ) ;
1045 // TVector3 * vtx = dynamic_cast<TVector3*>(toMinuit->At(2)) ; //Vertex position
1047 // AliPHOSEmcRecPoint * emcRP = dynamic_cast<AliPHOSEmcRecPoint *>( gMinuit->GetObjectFit() ) ; // EmcRecPoint to fit
1049 Int_t * emcDigits = emcRP->GetDigitsList() ;
1051 Int_t nOdigits = emcRP->GetDigitsMultiplicity() ;
1053 Float_t * emcEnergies = emcRP->GetEnergiesList() ;
1055 const AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
1061 for(iparam = 0 ; iparam < nPar ; iparam++)
1062 Grad[iparam] = 0 ; // Will evaluate gradient
1066 AliPHOSDigit * digit ;
1069 for( iDigit = 0 ; iDigit < nOdigits ; iDigit++) {
1071 digit = dynamic_cast<AliPHOSDigit*>( digits->At( emcDigits[iDigit] ) );
1077 geom->AbsToRelNumbering(digit->GetId(), relid) ;
1079 geom->RelPosInModule(relid, xDigit, zDigit) ;
1081 if(iflag == 2){ // calculate gradient
1084 while(iParam < nPar ){
1085 Double_t dx = (xDigit - x[iParam]) ;
1087 Double_t dz = (zDigit - x[iParam]) ;
1089 // geom->GetIncidentVector(*vtx,emcRP->GetPHOSMod(),x[iParam-2],x[iParam-1],vInc) ;
1090 // efit += x[iParam] * ShowerShape(dx,dz,vInc) ;
1091 efit += x[iParam] * ShowerShape(dx,dz) ;
1094 Double_t sum = 2. * (efit - emcEnergies[iDigit]) / emcEnergies[iDigit] ; // Here we assume, that sigma = sqrt(E)
1096 while(iParam < nPar ){
1097 Double_t xpar = x[iParam] ;
1098 Double_t zpar = x[iParam+1] ;
1099 Double_t epar = x[iParam+2] ;
1100 // geom->GetIncidentVector(*vtx,emcRP->GetPHOSMod(),xpar,zpar,vInc) ;
1101 Double_t dr = TMath::Sqrt( (xDigit - xpar) * (xDigit - xpar) + (zDigit - zpar) * (zDigit - zpar) );
1102 // Double_t shape = sum * ShowerShape(xDigit - xpar,zDigit - zpar,vInc) ;
1103 Double_t shape = sum * ShowerShape(xDigit - xpar,zDigit - zpar) ;
1104 //DP: No incident angle dependence in gradient yet!!!!!!
1105 Double_t r4 = dr*dr*dr*dr ;
1106 Double_t r295 = TMath::Power(dr,2.95) ;
1107 Double_t deriv =-4. * dr*dr * ( 2.32 / ( (2.32 + 0.26 * r4) * (2.32 + 0.26 * r4) ) +
1108 0.0316 * (1. + 0.0171 * r295) / ( ( 1. + 0.0652 * r295) * (1. + 0.0652 * r295) ) ) ;
1110 Grad[iParam] += epar * shape * deriv * (xpar - xDigit) ; // Derivative over x
1112 Grad[iParam] += epar * shape * deriv * (zpar - zDigit) ; // Derivative over z
1114 Grad[iParam] += shape ; // Derivative over energy
1121 while(iparam < nPar ){
1122 Double_t xpar = x[iparam] ;
1123 Double_t zpar = x[iparam+1] ;
1124 Double_t epar = x[iparam+2] ;
1126 // geom->GetIncidentVector(*vtx,emcRP->GetPHOSMod(),xpar,zpar,vInc) ;
1127 // efit += epar * ShowerShape(xDigit - xpar,zDigit - zpar,vInc) ;
1128 efit += epar * ShowerShape(xDigit - xpar,zDigit - zpar) ;
1131 fret += (efit-emcEnergies[iDigit])*(efit-emcEnergies[iDigit])/emcEnergies[iDigit] ;
1132 // Here we assume, that sigma = sqrt(E)
1137 //____________________________________________________________________________
1138 void AliPHOSClusterizerv1::Print(const Option_t *)const
1140 // Print clusterizer parameters
1143 TString taskName(GetName()) ;
1144 taskName.ReplaceAll(Version(), "") ;
1146 if( strcmp(GetName(), "") !=0 ) {
1148 message = "\n--------------- %s %s -----------\n" ;
1149 message += "Clusterizing digits from the file: %s\n" ;
1150 message += " Branch: %s\n" ;
1151 message += " EMC Clustering threshold = %f\n" ;
1152 message += " EMC Local Maximum cut = %f\n" ;
1153 message += " EMC Logarothmic weight = %f\n" ;
1154 message += " CPV Clustering threshold = %f\n" ;
1155 message += " CPV Local Maximum cut = %f\n" ;
1156 message += " CPV Logarothmic weight = %f\n" ;
1158 message += " Unfolding on\n" ;
1160 message += " Unfolding off\n" ;
1162 message += "------------------------------------------------------------------" ;
1165 message = " AliPHOSClusterizerv1 not initialized " ;
1167 AliInfo(Form("%s, %s %s %s %s %s %s %s %s %s %s", message.Data(),
1172 fEmcClusteringThreshold,
1175 fCpvClusteringThreshold,
1179 //____________________________________________________________________________
1180 //void AliPHOSClusterizerv1::GetVertex(void)
1181 //{ //Extracts vertex posisition
1189 // if(gAlice && gAlice->GetMCApp() && gAlice->Generator()){
1191 // gAlice->Generator()->GetOrigin(x,y,z) ;
1192 // fVtx.SetXYZ(x,y,z) ;
1197 // fVtx[0]=fVtx[1]=fVtx[2]=0. ;
1200 //____________________________________________________________________________
1201 void AliPHOSClusterizerv1::PrintRecPoints(Option_t * option)
1203 // Prints list of RecPoints produced at the current pass of AliPHOSClusterizer
1205 AliPHOSGetter * gime = AliPHOSGetter::Instance();
1207 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
1208 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
1210 AliInfo(Form("\nevent %d \n Found %d EMC RecPoints and %d CPV RecPoints",
1211 gAlice->GetEvNumber(),
1212 emcRecPoints->GetEntriesFast(),
1213 cpvRecPoints->GetEntriesFast() )) ;
1215 fRecPointsInRun += emcRecPoints->GetEntriesFast() ;
1216 fRecPointsInRun += cpvRecPoints->GetEntriesFast() ;
1219 if(strstr(option,"all")) {
1220 printf("\n EMC clusters \n") ;
1221 printf("Index Ene(MeV) Multi Module X Y Z Lambdas_1 Lambda_2 # of prim Primaries list\n") ;
1223 for (index = 0 ; index < emcRecPoints->GetEntries() ; index++) {
1224 AliPHOSEmcRecPoint * rp = (AliPHOSEmcRecPoint * )emcRecPoints->At(index) ;
1226 rp->GetLocalPosition(locpos);
1228 rp->GetElipsAxis(lambda);
1231 primaries = rp->GetPrimaries(nprimaries);
1232 printf("\n%6d %8.2f %3d %2d %4.1f %4.1f %4.1f %4f %4f %2d : ",
1233 rp->GetIndexInList(), rp->GetEnergy(), rp->GetMultiplicity(), rp->GetPHOSMod(),
1234 locpos.X(), locpos.Y(), locpos.Z(), lambda[0], lambda[1], nprimaries) ;
1236 for (Int_t iprimary=0; iprimary<nprimaries; iprimary++) {
1237 printf("%d ", primaries[iprimary] ) ;
1242 //Now plot CPV recPoints
1243 printf("\n CPV clusters \n") ;
1244 printf("Index Ene(MeV) Module X Y Z \n") ;
1245 for (index = 0 ; index < cpvRecPoints->GetEntries() ; index++) {
1246 AliPHOSCpvRecPoint * rp = (AliPHOSCpvRecPoint * )cpvRecPoints->At(index) ;
1249 rp->GetLocalPosition(locpos);
1251 printf("\n%6d %8.2f %2d %4.1f %4.1f %4.1f \n",
1252 rp->GetIndexInList(), rp->GetEnergy(), rp->GetPHOSMod(),
1253 locpos.X(), locpos.Y(), locpos.Z()) ;