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.95 2006/08/11 12:36:26 cvetan
22 * Update of the PHOS code needed in order to read and reconstruct the beam test raw data (i.e. without an existing galice.root)
24 * Revision 1.94 2006/08/07 12:27:49 hristov
25 * Removing obsolete code which affected the event numbering scheme
27 * Revision 1.93 2006/08/01 12:20:17 cvetan
28 * 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
30 * Revision 1.92 2006/04/29 20:26:46 hristov
31 * Separate EMC and CPV calibration (Yu.Kharlov)
33 * Revision 1.91 2006/04/22 10:30:17 hristov
34 * Add fEnergy to AliPHOSDigit and operate with EMC amplitude in energy units (Yu.Kharlov)
36 * Revision 1.90 2006/04/11 15:22:59 hristov
37 * run number in query set to -1: forces AliCDBManager to use its run number (A.Colla)
39 * Revision 1.89 2006/03/13 14:05:42 kharlov
40 * Calibration objects for EMC and CPV
42 * Revision 1.88 2006/01/11 08:54:52 hristov
43 * Additional protection in case no calibration entry was found
45 * Revision 1.87 2005/11/22 08:46:43 kharlov
46 * Updated to new CDB (Boris Polichtchouk)
48 * Revision 1.86 2005/11/14 21:52:43 hristov
51 * Revision 1.85 2005/09/27 16:08:08 hristov
52 * New version of CDB storage framework (A.Colla)
54 * Revision 1.84 2005/09/21 10:02:47 kharlov
55 * Reading calibration from CDB (Boris Polichtchouk)
57 * Revision 1.82 2005/09/02 15:43:13 kharlov
58 * Add comments in GetCalibrationParameters and Calibrate
60 * Revision 1.81 2005/09/02 14:32:07 kharlov
61 * Calibration of raw data
63 * Revision 1.80 2005/08/24 15:31:36 kharlov
64 * Setting raw digits flag
66 * Revision 1.79 2005/07/25 15:53:53 kharlov
69 * Revision 1.78 2005/05/28 14:19:04 schutz
70 * Compilation warnings fixed by T.P.
74 //*-- Author: Yves Schutz (SUBATECH) & Dmitri Peressounko (SUBATECH & Kurchatov Institute)
75 //////////////////////////////////////////////////////////////////////////////
76 // Clusterization class. Performs clusterization (collects neighbouring active cells) and
77 // unfolds the clusters having several local maxima.
78 // Results are stored in TreeR#, branches PHOSEmcRP (EMC recPoints),
79 // PHOSCpvRP (CPV RecPoints) and AliPHOSClusterizer (Clusterizer with all
80 // parameters including input digits branch title, thresholds etc.)
81 // This TTask is normally called from Reconstructioner, but can as well be used in
84 // root [0] AliPHOSClusterizerv1 * cl = new AliPHOSClusterizerv1("galice.root", "recpointsname", "digitsname")
85 // Warning in <TDatabasePDG::TDatabasePDG>: object already instantiated
86 // // reads gAlice from header file "galice.root", uses digits stored in the branch names "digitsname" (default = "Default")
87 // // and saves recpoints in branch named "recpointsname" (default = "digitsname")
88 // root [1] cl->ExecuteTask()
89 // //finds RecPoints in all events stored in galice.root
90 // root [2] cl->SetDigitsBranch("digits2")
91 // //sets another title for Digitis (input) branch
92 // root [3] cl->SetRecPointsBranch("recp2")
93 // //sets another title four output branches
94 // root [4] cl->SetEmcLocalMaxCut(0.03)
95 // //set clusterization parameters
96 // root [5] cl->ExecuteTask("deb all time")
97 // //once more finds RecPoints options are
98 // // deb - print number of found rec points
99 // // deb all - print number of found RecPoints and some their characteristics
100 // // time - print benchmarking results
102 // --- ROOT system ---
107 #include "TBenchmark.h"
109 // --- Standard library ---
111 // --- AliRoot header files ---
113 #include "AliPHOSGetter.h"
114 #include "AliPHOSGeometry.h"
115 #include "AliPHOSClusterizerv1.h"
116 #include "AliPHOSEmcRecPoint.h"
117 #include "AliPHOSCpvRecPoint.h"
118 #include "AliPHOSDigit.h"
119 #include "AliPHOSDigitizer.h"
120 #include "AliPHOSCalibrationDB.h"
121 #include "AliCDBManager.h"
122 #include "AliCDBStorage.h"
123 #include "AliCDBEntry.h"
125 ClassImp(AliPHOSClusterizerv1)
127 //____________________________________________________________________________
128 AliPHOSClusterizerv1::AliPHOSClusterizerv1() :
129 AliPHOSClusterizer(),
130 fDefaultInit(0), fEmcCrystals(0), fToUnfold(0),
131 fWrite(0), fNumberOfEmcClusters(0), fNumberOfCpvClusters(0),
132 fCalibData(0), fADCchanelEmc(0), fADCpedestalEmc(0),
133 fADCchanelCpv(0), fADCpedestalCpv(0), fEmcClusteringThreshold(0),
134 fCpvClusteringThreshold(0), fEmcMinE(0), fCpvMinE(0),
135 fEmcLocMaxCut(0), fW0(0), fCpvLocMaxCut(0),
136 fW0CPV(0), fRecPointsInRun(0), fEmcTimeGate(0),
139 // default ctor (to be used mainly by Streamer)
142 fDefaultInit = kTRUE ;
145 //____________________________________________________________________________
146 AliPHOSClusterizerv1::AliPHOSClusterizerv1(const TString alirunFileName, const TString eventFolderName) :
147 AliPHOSClusterizer(alirunFileName, eventFolderName),
148 fDefaultInit(0), fEmcCrystals(0), fToUnfold(0),
149 fWrite(0), fNumberOfEmcClusters(0), fNumberOfCpvClusters(0),
150 fCalibData(0), fADCchanelEmc(0), fADCpedestalEmc(0),
151 fADCchanelCpv(0), fADCpedestalCpv(0), fEmcClusteringThreshold(0),
152 fCpvClusteringThreshold(0), fEmcMinE(0), fCpvMinE(0),
153 fEmcLocMaxCut(0), fW0(0), fCpvLocMaxCut(0),
154 fW0CPV(0), fRecPointsInRun(0), fEmcTimeGate(0),
157 // ctor with the indication of the file where header Tree and digits Tree are stored
161 fDefaultInit = kFALSE ;
164 //____________________________________________________________________________
165 AliPHOSClusterizerv1::~AliPHOSClusterizerv1()
170 //____________________________________________________________________________
171 const TString AliPHOSClusterizerv1::BranchName() const
176 //____________________________________________________________________________
177 Float_t AliPHOSClusterizerv1::CalibrateEMC(Float_t amp, Int_t absId)
179 // Convert EMC measured amplitude into real energy.
180 // Calibration parameters are taken from calibration data base for raw data,
181 // or from digitizer parameters for simulated data.
185 AliPHOSGetter *gime = AliPHOSGetter::Instance();
186 gime->PHOSGeometry()->AbsToRelNumbering(absId,relId) ;
187 Int_t module = relId[0];
188 Int_t column = relId[3];
189 Int_t row = relId[2];
190 if(absId <= fEmcCrystals) { // this is EMC
191 fADCchanelEmc = fCalibData->GetADCchannelEmc (module,column,row);
192 return amp*fADCchanelEmc ;
196 if(absId <= fEmcCrystals) // this is EMC
197 return fADCpedestalEmc + amp*fADCchanelEmc ;
202 //____________________________________________________________________________
203 Float_t AliPHOSClusterizerv1::CalibrateCPV(Int_t amp, Int_t absId)
205 // Convert digitized CPV amplitude into charge.
206 // Calibration parameters are taken from calibration data base for raw data,
207 // or from digitizer parameters for simulated data.
211 AliPHOSGetter *gime = AliPHOSGetter::Instance();
212 gime->PHOSGeometry()->AbsToRelNumbering(absId,relId) ;
213 Int_t module = relId[0];
214 Int_t column = relId[3];
215 Int_t row = relId[2];
216 if(absId > fEmcCrystals) { // this is CPV
217 fADCchanelCpv = fCalibData->GetADCchannelCpv (module,column,row);
218 fADCpedestalCpv = fCalibData->GetADCpedestalCpv(module,column,row);
219 return fADCpedestalCpv + amp*fADCchanelCpv ;
223 if(absId > fEmcCrystals) // this is CPV
224 return fADCpedestalCpv+ amp*fADCchanelCpv ;
229 //____________________________________________________________________________
230 void AliPHOSClusterizerv1::Exec(Option_t *option)
232 // Steering method to perform clusterization for events
233 // in the range from fFirstEvent to fLastEvent.
234 // This range is optionally set by SetEventRange().
235 // if fLastEvent=-1 (by default), then process events until the end.
237 if(strstr(option,"tim"))
238 gBenchmark->Start("PHOSClusterizer");
240 if(strstr(option,"print")) {
245 GetCalibrationParameters() ;
247 AliPHOSGetter * gime = AliPHOSGetter::Instance() ;
249 gime->SetRawDigits(kFALSE);
251 gime->SetRawDigits(kTRUE);
253 if (fLastEvent == -1)
254 fLastEvent = gime->MaxEvent() - 1 ;
256 fLastEvent = TMath::Min(fFirstEvent, gime->MaxEvent()); // one event at the time
257 Int_t nEvents = fLastEvent - fFirstEvent + 1;
260 for (ievent = fFirstEvent; ievent <= fLastEvent; ievent++) {
262 gime->Event(ievent ,"D"); // Read digits from simulated data
264 gime->Event(fRawReader,"W",fIsOldRCUFormat); // Read digits from raw data
266 fNumberOfEmcClusters = fNumberOfCpvClusters = 0 ;
275 if(strstr(option,"deb"))
276 PrintRecPoints(option) ;
278 //increment the total number of recpoints per run
279 fRecPointsInRun += gime->EmcRecPoints()->GetEntriesFast() ;
280 fRecPointsInRun += gime->CpvRecPoints()->GetEntriesFast() ;
283 if(fWrite) //do not unload in "on flight" mode
286 if(strstr(option,"tim")){
287 gBenchmark->Stop("PHOSClusterizer");
288 AliInfo(Form("took %f seconds for Clusterizing %f seconds per event \n",
289 gBenchmark->GetCpuTime("PHOSClusterizer"),
290 gBenchmark->GetCpuTime("PHOSClusterizer")/nEvents )) ;
294 //____________________________________________________________________________
295 Bool_t AliPHOSClusterizerv1::FindFit(AliPHOSEmcRecPoint * emcRP, AliPHOSDigit ** maxAt, Float_t * maxAtEnergy,
296 Int_t nPar, Float_t * fitparameters) const
298 // Calls TMinuit to fit the energy distribution of a cluster with several maxima
299 // The initial values for fitting procedure are set equal to the positions of local maxima.
300 // Cluster will be fitted as a superposition of nPar/3 electromagnetic showers
303 AliPHOSGetter * gime = AliPHOSGetter::Instance();
304 TClonesArray * digits = gime->Digits();
307 gMinuit->mncler(); // Reset Minuit's list of paramters
308 gMinuit->SetPrintLevel(-1) ; // No Printout
309 gMinuit->SetFCN(AliPHOSClusterizerv1::UnfoldingChiSquare) ;
310 // To set the address of the minimization function
312 TList * toMinuit = new TList();
313 toMinuit->AddAt(emcRP,0) ;
314 toMinuit->AddAt(digits,1) ;
316 gMinuit->SetObjectFit(toMinuit) ; // To tranfer pointer to UnfoldingChiSquare
318 // filling initial values for fit parameters
319 AliPHOSDigit * digit ;
323 Int_t nDigits = (Int_t) nPar / 3 ;
327 const AliPHOSGeometry * geom = gime->PHOSGeometry() ;
329 for(iDigit = 0; iDigit < nDigits; iDigit++){
330 digit = maxAt[iDigit];
335 geom->AbsToRelNumbering(digit->GetId(), relid) ;
336 geom->RelPosInModule(relid, x, z) ;
338 Float_t energy = maxAtEnergy[iDigit] ;
340 gMinuit->mnparm(index, "x", x, 0.1, 0, 0, ierflg) ;
343 Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : x = %f\n", x ) ;
346 gMinuit->mnparm(index, "z", z, 0.1, 0, 0, ierflg) ;
349 Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : z =%f\n", z ) ;
352 gMinuit->mnparm(index, "Energy", energy , 0.05*energy, 0., 4.*energy, ierflg) ;
355 Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : energy = %f\n", energy ) ;
360 Double_t p0 = 0.1 ; // "Tolerance" Evaluation stops when EDM = 0.0001*p0 ; The number of function call slightly
365 gMinuit->mnexcm("SET STR", &p2, 0, ierflg) ; // force TMinuit to reduce function calls
366 gMinuit->mnexcm("SET GRA", &p1, 1, ierflg) ; // force TMinuit to use my gradient
367 gMinuit->SetMaxIterations(5);
368 gMinuit->mnexcm("SET NOW", &p2 , 0, ierflg) ; // No Warnings
370 gMinuit->mnexcm("MIGRAD", &p0, 0, ierflg) ; // minimize
372 if(ierflg == 4){ // Minimum not found
373 Warning("FindFit", "PHOS Unfolding fit not converged, cluster abandoned\n" );
376 for(index = 0; index < nPar; index++){
379 gMinuit->GetParameter(index, val, err) ; // Returns value and error of parameter index
380 fitparameters[index] = val ;
388 //____________________________________________________________________________
389 void AliPHOSClusterizerv1::GetCalibrationParameters()
391 // Set calibration parameters:
392 // if calibration database exists, they are read from database,
393 // otherwise, they are taken from digitizer.
395 // It is a user responsilibity to open CDB before reconstruction, for example:
396 // AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage("local://CalibDB");
398 AliPHOSGetter * gime = AliPHOSGetter::Instance();
399 // fCalibData = new AliPHOSCalibData(gAlice->GetRunNumber()); //original
401 fCalibData = new AliPHOSCalibData(-1); //use AliCDBManager's run number
405 if ( !gime->Digitizer() )
406 gime->LoadDigitizer();
407 AliPHOSDigitizer * dig = gime->Digitizer();
408 fADCchanelEmc = dig->GetEMCchannel() ;
409 fADCpedestalEmc = dig->GetEMCpedestal();
411 fADCchanelCpv = dig->GetCPVchannel() ;
412 fADCpedestalCpv = dig->GetCPVpedestal() ;
416 //____________________________________________________________________________
417 void AliPHOSClusterizerv1::Init()
419 // Make all memory allocations which can not be done in default constructor.
420 // Attach the Clusterizer task to the list of PHOS tasks
422 AliPHOSGetter* gime = AliPHOSGetter::Instance() ;
424 gime = AliPHOSGetter::Instance(GetTitle(), fEventFolderName.Data());
426 AliPHOSGeometry * geom = gime->PHOSGeometry();
428 fEmcCrystals = geom->GetNModules() * geom->GetNCristalsInModule() ;
431 gMinuit = new TMinuit(100);
433 if ( !gime->Clusterizer() ) {
434 gime->PostClusterizer(this);
438 //____________________________________________________________________________
439 void AliPHOSClusterizerv1::InitParameters()
442 fNumberOfCpvClusters = 0 ;
443 fNumberOfEmcClusters = 0 ;
445 fCpvClusteringThreshold = 0.0;
446 fEmcClusteringThreshold = 0.2;
448 fEmcLocMaxCut = 0.03 ;
449 fCpvLocMaxCut = 0.03 ;
457 fEmcTimeGate = 1.e-8 ;
461 fRecPointsInRun = 0 ;
467 SetEventRange(0,-1) ;
469 fIsOldRCUFormat = kFALSE;
472 //____________________________________________________________________________
473 Int_t AliPHOSClusterizerv1::AreNeighbours(AliPHOSDigit * d1, AliPHOSDigit * d2)const
475 // Gives the neighbourness of two digits = 0 are not neighbour but continue searching
477 // = 2 are not neighbour but do not continue searching
478 // neighbours are defined as digits having at least a common vertex
479 // The order of d1 and d2 is important: first (d1) should be a digit already in a cluster
480 // which is compared to a digit (d2) not yet in a cluster
482 AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
487 geom->AbsToRelNumbering(d1->GetId(), relid1) ;
490 geom->AbsToRelNumbering(d2->GetId(), relid2) ;
492 if ( (relid1[0] == relid2[0]) && (relid1[1]==relid2[1]) ) { // inside the same PHOS module
493 Int_t rowdiff = TMath::Abs( relid1[2] - relid2[2] ) ;
494 Int_t coldiff = TMath::Abs( relid1[3] - relid2[3] ) ;
496 if (( coldiff <= 1 ) && ( rowdiff <= 1 )){
497 if((relid1[1] != 0) || (TMath::Abs(d1->GetTime() - d2->GetTime() ) < fEmcTimeGate))
501 if((relid2[2] > relid1[2]) && (relid2[3] > relid1[3]+1))
502 rv = 2; // Difference in row numbers is too large to look further
508 if( (relid1[0] < relid2[0]) || (relid1[1] != relid2[1]) )
515 //____________________________________________________________________________
516 void AliPHOSClusterizerv1::CleanDigits(TClonesArray * digits)
518 // Remove digits with amplitudes below threshold
520 for(Int_t i=0; i<digits->GetEntriesFast(); i++){
521 AliPHOSDigit * digit = static_cast<AliPHOSDigit*>(digits->At(i)) ;
522 if ( (IsInEmc(digit) && CalibrateEMC(digit->GetEnergy(),digit->GetId()) < fEmcMinE) ||
523 (IsInCpv(digit) && CalibrateCPV(digit->GetAmp() ,digit->GetId()) < fCpvMinE) )
524 digits->RemoveAt(i) ;
527 for (Int_t i = 0 ; i < digits->GetEntriesFast() ; i++) {
528 AliPHOSDigit *digit = static_cast<AliPHOSDigit*>( digits->At(i) ) ;
529 digit->SetIndexInList(i) ;
533 //____________________________________________________________________________
534 Bool_t AliPHOSClusterizerv1::IsInEmc(AliPHOSDigit * digit) const
536 // Tells if (true) or not (false) the digit is in a PHOS-EMC module
539 AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
541 Int_t nEMC = geom->GetNModules()*geom->GetNPhi()*geom->GetNZ();
543 if(digit->GetId() <= nEMC ) rv = kTRUE;
548 //____________________________________________________________________________
549 Bool_t AliPHOSClusterizerv1::IsInCpv(AliPHOSDigit * digit) const
551 // Tells if (true) or not (false) the digit is in a PHOS-CPV module
555 AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
557 Int_t nEMC = geom->GetNModules()*geom->GetNPhi()*geom->GetNZ();
559 if(digit->GetId() > nEMC ) rv = kTRUE;
564 //____________________________________________________________________________
565 void AliPHOSClusterizerv1::Unload()
567 AliPHOSGetter * gime = AliPHOSGetter::Instance() ;
568 gime->PhosLoader()->UnloadDigits() ;
569 gime->PhosLoader()->UnloadRecPoints() ;
572 //____________________________________________________________________________
573 void AliPHOSClusterizerv1::WriteRecPoints()
576 // Creates new branches with given title
577 // fills and writes into TreeR.
579 AliPHOSGetter * gime = AliPHOSGetter::Instance();
581 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
582 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
583 TClonesArray * digits = gime->Digits() ;
587 //Evaluate position, dispersion and other RecPoint properties..
588 Int_t nEmc = emcRecPoints->GetEntriesFast();
589 for(index = 0; index < nEmc; index++){
590 AliPHOSEmcRecPoint * rp = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(index) );
591 rp->Purify(fEmcMinE) ;
592 if(rp->GetMultiplicity()>0.) //If this RP is not empty
593 rp->EvalAll(fW0,digits) ;
595 emcRecPoints->RemoveAt(index) ;
599 emcRecPoints->Compress() ;
600 emcRecPoints->Sort() ;
601 // emcRecPoints->Expand(emcRecPoints->GetEntriesFast()) ;
602 for(index = 0; index < emcRecPoints->GetEntries(); index++){
603 dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(index) )->SetIndexInList(index) ;
606 //Now the same for CPV
607 for(index = 0; index < cpvRecPoints->GetEntries(); index++){
608 AliPHOSCpvRecPoint * rp = dynamic_cast<AliPHOSCpvRecPoint *>( cpvRecPoints->At(index) );
609 rp->EvalAll(fW0CPV,digits) ;
611 cpvRecPoints->Sort() ;
613 for(index = 0; index < cpvRecPoints->GetEntries(); index++)
614 dynamic_cast<AliPHOSCpvRecPoint *>( cpvRecPoints->At(index) )->SetIndexInList(index) ;
616 cpvRecPoints->Expand(cpvRecPoints->GetEntriesFast()) ;
618 if(fWrite){ //We write TreeR
619 TTree * treeR = gime->TreeR();
621 Int_t bufferSize = 32000 ;
622 Int_t splitlevel = 0 ;
625 TBranch * emcBranch = treeR->Branch("PHOSEmcRP","TObjArray",&emcRecPoints,bufferSize,splitlevel);
626 emcBranch->SetTitle(BranchName());
629 TBranch * cpvBranch = treeR->Branch("PHOSCpvRP","TObjArray",&cpvRecPoints,bufferSize,splitlevel);
630 cpvBranch->SetTitle(BranchName());
635 gime->WriteRecPoints("OVERWRITE");
636 gime->WriteClusterizer("OVERWRITE");
640 //____________________________________________________________________________
641 void AliPHOSClusterizerv1::MakeClusters()
643 // Steering method to construct the clusters stored in a list of Reconstructed Points
644 // A cluster is defined as a list of neighbour digits
647 AliPHOSGetter * gime = AliPHOSGetter::Instance();
649 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
650 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
652 emcRecPoints->Delete() ;
653 cpvRecPoints->Delete() ;
655 TClonesArray * digits = gime->Digits() ;
657 //Remove digits below threshold
658 CleanDigits(digits) ;
660 TClonesArray * digitsC = static_cast<TClonesArray*>( digits->Clone() ) ;
662 // Clusterization starts
664 TIter nextdigit(digitsC) ;
665 AliPHOSDigit * digit ;
666 Bool_t notremoved = kTRUE ;
668 while ( (digit = dynamic_cast<AliPHOSDigit *>( nextdigit()) ) ) { // scan over the list of digitsC
671 AliPHOSRecPoint * clu = 0 ;
673 TArrayI clusterdigitslist(1500) ;
676 if (( IsInEmc (digit) &&
677 CalibrateEMC(digit->GetEnergy(),digit->GetId()) > fEmcClusteringThreshold ) ||
679 CalibrateCPV(digit->GetAmp() ,digit->GetId()) > fCpvClusteringThreshold ) ) {
680 Int_t iDigitInCluster = 0 ;
682 if ( IsInEmc(digit) ) {
683 // start a new EMC RecPoint
684 if(fNumberOfEmcClusters >= emcRecPoints->GetSize())
685 emcRecPoints->Expand(2*fNumberOfEmcClusters+1) ;
687 emcRecPoints->AddAt(new AliPHOSEmcRecPoint(""), fNumberOfEmcClusters) ;
688 clu = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(fNumberOfEmcClusters) ) ;
689 fNumberOfEmcClusters++ ;
690 clu->AddDigit(*digit, CalibrateEMC(digit->GetEnergy(),digit->GetId())) ;
691 clusterdigitslist[iDigitInCluster] = digit->GetIndexInList() ;
693 digitsC->Remove(digit) ;
697 // start a new CPV cluster
698 if(fNumberOfCpvClusters >= cpvRecPoints->GetSize())
699 cpvRecPoints->Expand(2*fNumberOfCpvClusters+1);
701 cpvRecPoints->AddAt(new AliPHOSCpvRecPoint(""), fNumberOfCpvClusters) ;
703 clu = dynamic_cast<AliPHOSCpvRecPoint *>( cpvRecPoints->At(fNumberOfCpvClusters) ) ;
704 fNumberOfCpvClusters++ ;
705 clu->AddDigit(*digit, CalibrateCPV(digit->GetAmp(),digit->GetId()) ) ;
706 clusterdigitslist[iDigitInCluster] = digit->GetIndexInList() ;
708 digitsC->Remove(digit) ;
711 // Here we remove remaining EMC digits, which cannot make a cluster
714 while( ( digit = dynamic_cast<AliPHOSDigit *>( nextdigit() ) ) ) {
716 digitsC->Remove(digit) ;
720 notremoved = kFALSE ;
727 AliPHOSDigit * digitN ;
729 while (index < iDigitInCluster){ // scan over digits already in cluster
730 digit = dynamic_cast<AliPHOSDigit*>( digits->At(clusterdigitslist[index]) ) ;
732 while ( (digitN = dynamic_cast<AliPHOSDigit *>( nextdigit() ) ) ) { // scan over the reduced list of digits
733 Int_t ineb = AreNeighbours(digit, digitN); // call (digit,digitN) in THAT oder !!!!!
735 case 0 : // not a neighbour
737 case 1 : // are neighbours
738 if (IsInEmc (digitN))
739 clu->AddDigit(*digitN, CalibrateEMC( digitN->GetEnergy(), digitN->GetId() ) );
741 clu->AddDigit(*digitN, CalibrateCPV( digitN->GetAmp() , digitN->GetId() ) );
743 clusterdigitslist[iDigitInCluster] = digitN->GetIndexInList() ;
745 digitsC->Remove(digitN) ;
747 case 2 : // too far from each other
756 } // loop over cluster
767 //____________________________________________________________________________
768 void AliPHOSClusterizerv1::MakeUnfolding()
770 // Unfolds clusters using the shape of an ElectroMagnetic shower
771 // Performs unfolding of all EMC/CPV clusters
773 AliPHOSGetter * gime = AliPHOSGetter::Instance();
775 const AliPHOSGeometry * geom = gime->PHOSGeometry() ;
777 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
778 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
779 TClonesArray * digits = gime->Digits() ;
781 // Unfold first EMC clusters
782 if(fNumberOfEmcClusters > 0){
784 Int_t nModulesToUnfold = geom->GetNModules() ;
786 Int_t numberofNotUnfolded = fNumberOfEmcClusters ;
788 for(index = 0 ; index < numberofNotUnfolded ; index++){
790 AliPHOSEmcRecPoint * emcRecPoint = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(index) ) ;
791 if(emcRecPoint->GetPHOSMod()> nModulesToUnfold)
794 Int_t nMultipl = emcRecPoint->GetMultiplicity() ;
795 AliPHOSDigit ** maxAt = new AliPHOSDigit*[nMultipl] ;
796 Float_t * maxAtEnergy = new Float_t[nMultipl] ;
797 Int_t nMax = emcRecPoint->GetNumberOfLocalMax(maxAt, maxAtEnergy,fEmcLocMaxCut,digits) ;
799 if( nMax > 1 ) { // if cluster is very flat (no pronounced maximum) then nMax = 0
800 UnfoldCluster(emcRecPoint, nMax, maxAt, maxAtEnergy) ;
801 emcRecPoints->Remove(emcRecPoint);
802 emcRecPoints->Compress() ;
804 fNumberOfEmcClusters -- ;
805 numberofNotUnfolded-- ;
808 emcRecPoint->SetNExMax(1) ; //Only one local maximum
812 delete[] maxAtEnergy ;
815 // Unfolding of EMC clusters finished
818 // Unfold now CPV clusters
819 if(fNumberOfCpvClusters > 0){
821 Int_t nModulesToUnfold = geom->GetNModules() ;
823 Int_t numberofCpvNotUnfolded = fNumberOfCpvClusters ;
825 for(index = 0 ; index < numberofCpvNotUnfolded ; index++){
827 AliPHOSRecPoint * recPoint = dynamic_cast<AliPHOSRecPoint *>( cpvRecPoints->At(index) ) ;
829 if(recPoint->GetPHOSMod()> nModulesToUnfold)
832 AliPHOSEmcRecPoint * emcRecPoint = dynamic_cast<AliPHOSEmcRecPoint*>(recPoint) ;
834 Int_t nMultipl = emcRecPoint->GetMultiplicity() ;
835 AliPHOSDigit ** maxAt = new AliPHOSDigit*[nMultipl] ;
836 Float_t * maxAtEnergy = new Float_t[nMultipl] ;
837 Int_t nMax = emcRecPoint->GetNumberOfLocalMax(maxAt, maxAtEnergy,fCpvLocMaxCut,digits) ;
839 if( nMax > 1 ) { // if cluster is very flat (no pronounced maximum) then nMax = 0
840 UnfoldCluster(emcRecPoint, nMax, maxAt, maxAtEnergy) ;
841 cpvRecPoints->Remove(emcRecPoint);
842 cpvRecPoints->Compress() ;
844 numberofCpvNotUnfolded-- ;
845 fNumberOfCpvClusters-- ;
849 delete[] maxAtEnergy ;
852 //Unfolding of Cpv clusters finished
856 //____________________________________________________________________________
857 Double_t AliPHOSClusterizerv1::ShowerShape(Double_t r)
859 // Shape of the shower (see PHOS TDR)
860 // If you change this function, change also the gradient evaluation in ChiSquare()
862 Double_t r4 = r*r*r*r ;
863 Double_t r295 = TMath::Power(r, 2.95) ;
864 Double_t shape = TMath::Exp( -r4 * (1. / (2.32 + 0.26 * r4) + 0.0316 / (1 + 0.0652 * r295) ) ) ;
868 //____________________________________________________________________________
869 void AliPHOSClusterizerv1::UnfoldCluster(AliPHOSEmcRecPoint * iniEmc,
871 AliPHOSDigit ** maxAt,
872 Float_t * maxAtEnergy)
874 // Performs the unfolding of a cluster with nMax overlapping showers
876 AliPHOSGetter * gime = AliPHOSGetter::Instance();
878 const AliPHOSGeometry * geom = gime->PHOSGeometry() ;
880 const TClonesArray * digits = gime->Digits() ;
881 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
882 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
884 Int_t nPar = 3 * nMax ;
885 Float_t * fitparameters = new Float_t[nPar] ;
887 Bool_t rv = FindFit(iniEmc, maxAt, maxAtEnergy, nPar, fitparameters) ;
889 // Fit failed, return and remove cluster
890 iniEmc->SetNExMax(-1) ;
891 delete[] fitparameters ;
895 // create ufolded rec points and fill them with new energy lists
896 // First calculate energy deposited in each sell in accordance with fit (without fluctuations): efit[]
897 // and later correct this number in acordance with actual energy deposition
899 Int_t nDigits = iniEmc->GetMultiplicity() ;
900 Float_t * efit = new Float_t[nDigits] ;
901 Float_t xDigit=0.,zDigit=0.,distance=0. ;
902 Float_t xpar=0.,zpar=0.,epar=0. ;
904 AliPHOSDigit * digit = 0 ;
905 Int_t * emcDigits = iniEmc->GetDigitsList() ;
909 for(iDigit = 0 ; iDigit < nDigits ; iDigit ++){
910 digit = dynamic_cast<AliPHOSDigit*>( digits->At(emcDigits[iDigit] ) ) ;
911 geom->AbsToRelNumbering(digit->GetId(), relid) ;
912 geom->RelPosInModule(relid, xDigit, zDigit) ;
916 while(iparam < nPar ){
917 xpar = fitparameters[iparam] ;
918 zpar = fitparameters[iparam+1] ;
919 epar = fitparameters[iparam+2] ;
921 distance = (xDigit - xpar) * (xDigit - xpar) + (zDigit - zpar) * (zDigit - zpar) ;
922 distance = TMath::Sqrt(distance) ;
923 efit[iDigit] += epar * ShowerShape(distance) ;
928 // Now create new RecPoints and fill energy lists with efit corrected to fluctuations
929 // so that energy deposited in each cell is distributed betwin new clusters proportionally
930 // to its contribution to efit
932 Float_t * emcEnergies = iniEmc->GetEnergiesList() ;
936 while(iparam < nPar ){
937 xpar = fitparameters[iparam] ;
938 zpar = fitparameters[iparam+1] ;
939 epar = fitparameters[iparam+2] ;
942 AliPHOSEmcRecPoint * emcRP = 0 ;
944 if(iniEmc->IsEmc()){ //create new entries in fEmcRecPoints...
946 if(fNumberOfEmcClusters >= emcRecPoints->GetSize())
947 emcRecPoints->Expand(2*fNumberOfEmcClusters) ;
949 (*emcRecPoints)[fNumberOfEmcClusters] = new AliPHOSEmcRecPoint("") ;
950 emcRP = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(fNumberOfEmcClusters) ) ;
951 fNumberOfEmcClusters++ ;
952 emcRP->SetNExMax((Int_t)nPar/3) ;
954 else{//create new entries in fCpvRecPoints
955 if(fNumberOfCpvClusters >= cpvRecPoints->GetSize())
956 cpvRecPoints->Expand(2*fNumberOfCpvClusters) ;
958 (*cpvRecPoints)[fNumberOfCpvClusters] = new AliPHOSCpvRecPoint("") ;
959 emcRP = dynamic_cast<AliPHOSEmcRecPoint *>( cpvRecPoints->At(fNumberOfCpvClusters) ) ;
960 fNumberOfCpvClusters++ ;
964 for(iDigit = 0 ; iDigit < nDigits ; iDigit ++){
965 digit = dynamic_cast<AliPHOSDigit*>( digits->At( emcDigits[iDigit] ) ) ;
966 geom->AbsToRelNumbering(digit->GetId(), relid) ;
967 geom->RelPosInModule(relid, xDigit, zDigit) ;
968 distance = (xDigit - xpar) * (xDigit - xpar) + (zDigit - zpar) * (zDigit - zpar) ;
969 distance = TMath::Sqrt(distance) ;
970 ratio = epar * ShowerShape(distance) / efit[iDigit] ;
971 eDigit = emcEnergies[iDigit] * ratio ;
972 emcRP->AddDigit( *digit, eDigit ) ;
976 delete[] fitparameters ;
981 //_____________________________________________________________________________
982 void AliPHOSClusterizerv1::UnfoldingChiSquare(Int_t & nPar, Double_t * Grad, Double_t & fret, Double_t * x, Int_t iflag)
984 // Calculates the Chi square for the cluster unfolding minimization
985 // Number of parameters, Gradient, Chi squared, parameters, what to do
987 TList * toMinuit = dynamic_cast<TList*>( gMinuit->GetObjectFit() ) ;
989 AliPHOSEmcRecPoint * emcRP = dynamic_cast<AliPHOSEmcRecPoint*>( toMinuit->At(0) ) ;
990 TClonesArray * digits = dynamic_cast<TClonesArray*>( toMinuit->At(1) ) ;
994 // AliPHOSEmcRecPoint * emcRP = dynamic_cast<AliPHOSEmcRecPoint *>( gMinuit->GetObjectFit() ) ; // EmcRecPoint to fit
996 Int_t * emcDigits = emcRP->GetDigitsList() ;
998 Int_t nOdigits = emcRP->GetDigitsMultiplicity() ;
1000 Float_t * emcEnergies = emcRP->GetEnergiesList() ;
1002 const AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
1007 for(iparam = 0 ; iparam < nPar ; iparam++)
1008 Grad[iparam] = 0 ; // Will evaluate gradient
1012 AliPHOSDigit * digit ;
1015 for( iDigit = 0 ; iDigit < nOdigits ; iDigit++) {
1017 digit = dynamic_cast<AliPHOSDigit*>( digits->At( emcDigits[iDigit] ) );
1023 geom->AbsToRelNumbering(digit->GetId(), relid) ;
1025 geom->RelPosInModule(relid, xDigit, zDigit) ;
1027 if(iflag == 2){ // calculate gradient
1030 while(iParam < nPar ){
1031 Double_t distance = (xDigit - x[iParam]) * (xDigit - x[iParam]) ;
1033 distance += (zDigit - x[iParam]) * (zDigit - x[iParam]) ;
1034 distance = TMath::Sqrt( distance ) ;
1036 efit += x[iParam] * ShowerShape(distance) ;
1039 Double_t sum = 2. * (efit - emcEnergies[iDigit]) / emcEnergies[iDigit] ; // Here we assume, that sigma = sqrt(E)
1041 while(iParam < nPar ){
1042 Double_t xpar = x[iParam] ;
1043 Double_t zpar = x[iParam+1] ;
1044 Double_t epar = x[iParam+2] ;
1045 Double_t dr = TMath::Sqrt( (xDigit - xpar) * (xDigit - xpar) + (zDigit - zpar) * (zDigit - zpar) );
1046 Double_t shape = sum * ShowerShape(dr) ;
1047 Double_t r4 = dr*dr*dr*dr ;
1048 Double_t r295 = TMath::Power(dr,2.95) ;
1049 Double_t deriv =-4. * dr*dr * ( 2.32 / ( (2.32 + 0.26 * r4) * (2.32 + 0.26 * r4) ) +
1050 0.0316 * (1. + 0.0171 * r295) / ( ( 1. + 0.0652 * r295) * (1. + 0.0652 * r295) ) ) ;
1052 Grad[iParam] += epar * shape * deriv * (xpar - xDigit) ; // Derivative over x
1054 Grad[iParam] += epar * shape * deriv * (zpar - zDigit) ; // Derivative over z
1056 Grad[iParam] += shape ; // Derivative over energy
1063 while(iparam < nPar ){
1064 Double_t xpar = x[iparam] ;
1065 Double_t zpar = x[iparam+1] ;
1066 Double_t epar = x[iparam+2] ;
1068 Double_t distance = (xDigit - xpar) * (xDigit - xpar) + (zDigit - zpar) * (zDigit - zpar) ;
1069 distance = TMath::Sqrt(distance) ;
1070 efit += epar * ShowerShape(distance) ;
1073 fret += (efit-emcEnergies[iDigit])*(efit-emcEnergies[iDigit])/emcEnergies[iDigit] ;
1074 // Here we assume, that sigma = sqrt(E)
1079 //____________________________________________________________________________
1080 void AliPHOSClusterizerv1::Print(const Option_t *)const
1082 // Print clusterizer parameters
1085 TString taskName(GetName()) ;
1086 taskName.ReplaceAll(Version(), "") ;
1088 if( strcmp(GetName(), "") !=0 ) {
1090 message = "\n--------------- %s %s -----------\n" ;
1091 message += "Clusterizing digits from the file: %s\n" ;
1092 message += " Branch: %s\n" ;
1093 message += " EMC Clustering threshold = %f\n" ;
1094 message += " EMC Local Maximum cut = %f\n" ;
1095 message += " EMC Logarothmic weight = %f\n" ;
1096 message += " CPV Clustering threshold = %f\n" ;
1097 message += " CPV Local Maximum cut = %f\n" ;
1098 message += " CPV Logarothmic weight = %f\n" ;
1100 message += " Unfolding on\n" ;
1102 message += " Unfolding off\n" ;
1104 message += "------------------------------------------------------------------" ;
1107 message = " AliPHOSClusterizerv1 not initialized " ;
1109 AliInfo(Form("%s, %s %s %s %s %s %s %s %s %s %s", message.Data(),
1114 fEmcClusteringThreshold,
1117 fCpvClusteringThreshold,
1123 //____________________________________________________________________________
1124 void AliPHOSClusterizerv1::PrintRecPoints(Option_t * option)
1126 // Prints list of RecPoints produced at the current pass of AliPHOSClusterizer
1128 AliPHOSGetter * gime = AliPHOSGetter::Instance();
1130 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
1131 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
1133 AliInfo(Form("\nevent %d \n Found %d EMC RecPoints and %d CPV RecPoints",
1134 gAlice->GetEvNumber(),
1135 emcRecPoints->GetEntriesFast(),
1136 cpvRecPoints->GetEntriesFast() )) ;
1138 fRecPointsInRun += emcRecPoints->GetEntriesFast() ;
1139 fRecPointsInRun += cpvRecPoints->GetEntriesFast() ;
1142 if(strstr(option,"all")) {
1143 printf("\n EMC clusters \n") ;
1144 printf("Index Ene(MeV) Multi Module X Y Z Lambdas_1 Lambda_2 # of prim Primaries list\n") ;
1146 for (index = 0 ; index < emcRecPoints->GetEntries() ; index++) {
1147 AliPHOSEmcRecPoint * rp = (AliPHOSEmcRecPoint * )emcRecPoints->At(index) ;
1149 rp->GetLocalPosition(locpos);
1151 rp->GetElipsAxis(lambda);
1154 primaries = rp->GetPrimaries(nprimaries);
1155 printf("\n%6d %8.2f %3d %2d %4.1f %4.1f %4.1f %4f %4f %2d : ",
1156 rp->GetIndexInList(), rp->GetEnergy(), rp->GetMultiplicity(), rp->GetPHOSMod(),
1157 locpos.X(), locpos.Y(), locpos.Z(), lambda[0], lambda[1], nprimaries) ;
1159 for (Int_t iprimary=0; iprimary<nprimaries; iprimary++) {
1160 printf("%d ", primaries[iprimary] ) ;
1165 //Now plot CPV recPoints
1166 printf("\n CPV clusters \n") ;
1167 printf("Index Ene(MeV) Module X Y Z \n") ;
1168 for (index = 0 ; index < cpvRecPoints->GetEntries() ; index++) {
1169 AliPHOSCpvRecPoint * rp = (AliPHOSCpvRecPoint * )cpvRecPoints->At(index) ;
1172 rp->GetLocalPosition(locpos);
1174 printf("\n%6d %8.2f %2d %4.1f %4.1f %4.1f \n",
1175 rp->GetIndexInList(), rp->GetEnergy(), rp->GetPHOSMod(),
1176 locpos.X(), locpos.Y(), locpos.Z()) ;