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.93 2006/08/01 12:20:17 cvetan
22 * 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
24 * Revision 1.92 2006/04/29 20:26:46 hristov
25 * Separate EMC and CPV calibration (Yu.Kharlov)
27 * Revision 1.91 2006/04/22 10:30:17 hristov
28 * Add fEnergy to AliPHOSDigit and operate with EMC amplitude in energy units (Yu.Kharlov)
30 * Revision 1.90 2006/04/11 15:22:59 hristov
31 * run number in query set to -1: forces AliCDBManager to use its run number (A.Colla)
33 * Revision 1.89 2006/03/13 14:05:42 kharlov
34 * Calibration objects for EMC and CPV
36 * Revision 1.88 2006/01/11 08:54:52 hristov
37 * Additional protection in case no calibration entry was found
39 * Revision 1.87 2005/11/22 08:46:43 kharlov
40 * Updated to new CDB (Boris Polichtchouk)
42 * Revision 1.86 2005/11/14 21:52:43 hristov
45 * Revision 1.85 2005/09/27 16:08:08 hristov
46 * New version of CDB storage framework (A.Colla)
48 * Revision 1.84 2005/09/21 10:02:47 kharlov
49 * Reading calibration from CDB (Boris Polichtchouk)
51 * Revision 1.82 2005/09/02 15:43:13 kharlov
52 * Add comments in GetCalibrationParameters and Calibrate
54 * Revision 1.81 2005/09/02 14:32:07 kharlov
55 * Calibration of raw data
57 * Revision 1.80 2005/08/24 15:31:36 kharlov
58 * Setting raw digits flag
60 * Revision 1.79 2005/07/25 15:53:53 kharlov
63 * Revision 1.78 2005/05/28 14:19:04 schutz
64 * Compilation warnings fixed by T.P.
68 //*-- Author: Yves Schutz (SUBATECH) & Dmitri Peressounko (SUBATECH & Kurchatov Institute)
69 //////////////////////////////////////////////////////////////////////////////
70 // Clusterization class. Performs clusterization (collects neighbouring active cells) and
71 // unfolds the clusters having several local maxima.
72 // Results are stored in TreeR#, branches PHOSEmcRP (EMC recPoints),
73 // PHOSCpvRP (CPV RecPoints) and AliPHOSClusterizer (Clusterizer with all
74 // parameters including input digits branch title, thresholds etc.)
75 // This TTask is normally called from Reconstructioner, but can as well be used in
78 // root [0] AliPHOSClusterizerv1 * cl = new AliPHOSClusterizerv1("galice.root", "recpointsname", "digitsname")
79 // Warning in <TDatabasePDG::TDatabasePDG>: object already instantiated
80 // // reads gAlice from header file "galice.root", uses digits stored in the branch names "digitsname" (default = "Default")
81 // // and saves recpoints in branch named "recpointsname" (default = "digitsname")
82 // root [1] cl->ExecuteTask()
83 // //finds RecPoints in all events stored in galice.root
84 // root [2] cl->SetDigitsBranch("digits2")
85 // //sets another title for Digitis (input) branch
86 // root [3] cl->SetRecPointsBranch("recp2")
87 // //sets another title four output branches
88 // root [4] cl->SetEmcLocalMaxCut(0.03)
89 // //set clusterization parameters
90 // root [5] cl->ExecuteTask("deb all time")
91 // //once more finds RecPoints options are
92 // // deb - print number of found rec points
93 // // deb all - print number of found RecPoints and some their characteristics
94 // // time - print benchmarking results
96 // --- ROOT system ---
101 #include "TBenchmark.h"
103 // --- Standard library ---
105 // --- AliRoot header files ---
107 #include "AliPHOSGetter.h"
108 #include "AliPHOSGeometry.h"
109 #include "AliPHOSClusterizerv1.h"
110 #include "AliPHOSEmcRecPoint.h"
111 #include "AliPHOSCpvRecPoint.h"
112 #include "AliPHOSDigit.h"
113 #include "AliPHOSDigitizer.h"
114 #include "AliPHOSCalibrationDB.h"
115 #include "AliCDBManager.h"
116 #include "AliCDBStorage.h"
117 #include "AliCDBEntry.h"
119 ClassImp(AliPHOSClusterizerv1)
121 //____________________________________________________________________________
122 AliPHOSClusterizerv1::AliPHOSClusterizerv1() : AliPHOSClusterizer()
124 // default ctor (to be used mainly by Streamer)
127 fDefaultInit = kTRUE ;
130 //____________________________________________________________________________
131 AliPHOSClusterizerv1::AliPHOSClusterizerv1(const TString alirunFileName, const TString eventFolderName)
132 :AliPHOSClusterizer(alirunFileName, eventFolderName)
134 // ctor with the indication of the file where header Tree and digits Tree are stored
138 fDefaultInit = kFALSE ;
141 //____________________________________________________________________________
142 AliPHOSClusterizerv1::~AliPHOSClusterizerv1()
147 //____________________________________________________________________________
148 const TString AliPHOSClusterizerv1::BranchName() const
153 //____________________________________________________________________________
154 Float_t AliPHOSClusterizerv1::CalibrateEMC(Float_t amp, Int_t absId)
156 // Convert EMC measured amplitude into real energy.
157 // Calibration parameters are taken from calibration data base for raw data,
158 // or from digitizer parameters for simulated data.
162 AliPHOSGetter *gime = AliPHOSGetter::Instance();
163 gime->PHOSGeometry()->AbsToRelNumbering(absId,relId) ;
164 Int_t module = relId[0];
165 Int_t column = relId[3];
166 Int_t row = relId[2];
167 if(absId <= fEmcCrystals) { // this is EMC
168 fADCchanelEmc = fCalibData->GetADCchannelEmc (module,column,row);
169 return amp*fADCchanelEmc ;
173 if(absId <= fEmcCrystals) // this is EMC
174 return fADCpedestalEmc + amp*fADCchanelEmc ;
179 //____________________________________________________________________________
180 Float_t AliPHOSClusterizerv1::CalibrateCPV(Int_t amp, Int_t absId)
182 // Convert digitized CPV amplitude into charge.
183 // Calibration parameters are taken from calibration data base for raw data,
184 // or from digitizer parameters for simulated data.
188 AliPHOSGetter *gime = AliPHOSGetter::Instance();
189 gime->PHOSGeometry()->AbsToRelNumbering(absId,relId) ;
190 Int_t module = relId[0];
191 Int_t column = relId[3];
192 Int_t row = relId[2];
193 if(absId > fEmcCrystals) { // this is CPV
194 fADCchanelCpv = fCalibData->GetADCchannelCpv (module,column,row);
195 fADCpedestalCpv = fCalibData->GetADCpedestalCpv(module,column,row);
196 return fADCpedestalCpv + amp*fADCchanelCpv ;
200 if(absId > fEmcCrystals) // this is CPV
201 return fADCpedestalCpv+ amp*fADCchanelCpv ;
206 //____________________________________________________________________________
207 void AliPHOSClusterizerv1::Exec(Option_t *option)
209 // Steering method to perform clusterization for events
210 // in the range from fFirstEvent to fLastEvent.
211 // This range is optionally set by SetEventRange().
212 // if fLastEvent=-1 (by default), then process events until the end.
214 if(strstr(option,"tim"))
215 gBenchmark->Start("PHOSClusterizer");
217 if(strstr(option,"print")) {
222 GetCalibrationParameters() ;
224 AliPHOSGetter * gime = AliPHOSGetter::Instance() ;
226 gime->SetRawDigits(kFALSE);
228 gime->SetRawDigits(kTRUE);
230 if (fLastEvent == -1)
231 fLastEvent = gime->MaxEvent() - 1 ;
233 fLastEvent = TMath::Min(fFirstEvent, gime->MaxEvent()); // one event at the time
234 Int_t nEvents = fLastEvent - fFirstEvent + 1;
237 for (ievent = fFirstEvent; ievent <= fLastEvent; ievent++) {
239 gime->Event(ievent ,"D"); // Read digits from simulated data
241 gime->Event(fRawReader,"W",fIsOldRCUFormat); // Read digits from raw data
243 fNumberOfEmcClusters = fNumberOfCpvClusters = 0 ;
252 if(strstr(option,"deb"))
253 PrintRecPoints(option) ;
255 //increment the total number of recpoints per run
256 fRecPointsInRun += gime->EmcRecPoints()->GetEntriesFast() ;
257 fRecPointsInRun += gime->CpvRecPoints()->GetEntriesFast() ;
260 if(fWrite) //do not unload in "on flight" mode
263 if(strstr(option,"tim")){
264 gBenchmark->Stop("PHOSClusterizer");
265 AliInfo(Form("took %f seconds for Clusterizing %f seconds per event \n",
266 gBenchmark->GetCpuTime("PHOSClusterizer"),
267 gBenchmark->GetCpuTime("PHOSClusterizer")/nEvents )) ;
271 //____________________________________________________________________________
272 Bool_t AliPHOSClusterizerv1::FindFit(AliPHOSEmcRecPoint * emcRP, AliPHOSDigit ** maxAt, Float_t * maxAtEnergy,
273 Int_t nPar, Float_t * fitparameters) const
275 // Calls TMinuit to fit the energy distribution of a cluster with several maxima
276 // The initial values for fitting procedure are set equal to the positions of local maxima.
277 // Cluster will be fitted as a superposition of nPar/3 electromagnetic showers
280 AliPHOSGetter * gime = AliPHOSGetter::Instance();
281 TClonesArray * digits = gime->Digits();
284 gMinuit->mncler(); // Reset Minuit's list of paramters
285 gMinuit->SetPrintLevel(-1) ; // No Printout
286 gMinuit->SetFCN(AliPHOSClusterizerv1::UnfoldingChiSquare) ;
287 // To set the address of the minimization function
289 TList * toMinuit = new TList();
290 toMinuit->AddAt(emcRP,0) ;
291 toMinuit->AddAt(digits,1) ;
293 gMinuit->SetObjectFit(toMinuit) ; // To tranfer pointer to UnfoldingChiSquare
295 // filling initial values for fit parameters
296 AliPHOSDigit * digit ;
300 Int_t nDigits = (Int_t) nPar / 3 ;
304 const AliPHOSGeometry * geom = gime->PHOSGeometry() ;
306 for(iDigit = 0; iDigit < nDigits; iDigit++){
307 digit = maxAt[iDigit];
312 geom->AbsToRelNumbering(digit->GetId(), relid) ;
313 geom->RelPosInModule(relid, x, z) ;
315 Float_t energy = maxAtEnergy[iDigit] ;
317 gMinuit->mnparm(index, "x", x, 0.1, 0, 0, ierflg) ;
320 Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : x = %f\n", x ) ;
323 gMinuit->mnparm(index, "z", z, 0.1, 0, 0, ierflg) ;
326 Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : z =%f\n", z ) ;
329 gMinuit->mnparm(index, "Energy", energy , 0.05*energy, 0., 4.*energy, ierflg) ;
332 Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : energy = %f\n", energy ) ;
337 Double_t p0 = 0.1 ; // "Tolerance" Evaluation stops when EDM = 0.0001*p0 ; The number of function call slightly
342 gMinuit->mnexcm("SET STR", &p2, 0, ierflg) ; // force TMinuit to reduce function calls
343 gMinuit->mnexcm("SET GRA", &p1, 1, ierflg) ; // force TMinuit to use my gradient
344 gMinuit->SetMaxIterations(5);
345 gMinuit->mnexcm("SET NOW", &p2 , 0, ierflg) ; // No Warnings
347 gMinuit->mnexcm("MIGRAD", &p0, 0, ierflg) ; // minimize
349 if(ierflg == 4){ // Minimum not found
350 Warning("FindFit", "PHOS Unfolding fit not converged, cluster abandoned\n" );
353 for(index = 0; index < nPar; index++){
356 gMinuit->GetParameter(index, val, err) ; // Returns value and error of parameter index
357 fitparameters[index] = val ;
365 //____________________________________________________________________________
366 void AliPHOSClusterizerv1::GetCalibrationParameters()
368 // Set calibration parameters:
369 // if calibration database exists, they are read from database,
370 // otherwise, they are taken from digitizer.
372 // It is a user responsilibity to open CDB before reconstruction, for example:
373 // AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage("local://CalibDB");
375 AliPHOSGetter * gime = AliPHOSGetter::Instance();
376 // fCalibData = new AliPHOSCalibData(gAlice->GetRunNumber()); //original
378 fCalibData = new AliPHOSCalibData(-1); //use AliCDBManager's run number
382 if ( !gime->Digitizer() )
383 gime->LoadDigitizer();
384 AliPHOSDigitizer * dig = gime->Digitizer();
385 fADCchanelEmc = dig->GetEMCchannel() ;
386 fADCpedestalEmc = dig->GetEMCpedestal();
388 fADCchanelCpv = dig->GetCPVchannel() ;
389 fADCpedestalCpv = dig->GetCPVpedestal() ;
393 //____________________________________________________________________________
394 void AliPHOSClusterizerv1::Init()
396 // Make all memory allocations which can not be done in default constructor.
397 // Attach the Clusterizer task to the list of PHOS tasks
399 AliPHOSGetter* gime = AliPHOSGetter::Instance() ;
401 gime = AliPHOSGetter::Instance(GetTitle(), fEventFolderName.Data());
403 AliPHOSGeometry * geom = gime->PHOSGeometry();
405 AliError("Could not find PHOS geometry! Loading the default one !");
406 geom = AliPHOSGeometry::GetInstance("IHEP","");
409 fEmcCrystals = geom->GetNModules() * geom->GetNCristalsInModule() ;
412 gMinuit = new TMinuit(100);
414 if ( !gime->Clusterizer() ) {
415 gime->PostClusterizer(this);
419 //____________________________________________________________________________
420 void AliPHOSClusterizerv1::InitParameters()
423 fNumberOfCpvClusters = 0 ;
424 fNumberOfEmcClusters = 0 ;
426 fCpvClusteringThreshold = 0.0;
427 fEmcClusteringThreshold = 0.2;
429 fEmcLocMaxCut = 0.03 ;
430 fCpvLocMaxCut = 0.03 ;
438 fEmcTimeGate = 1.e-8 ;
442 fRecPointsInRun = 0 ;
448 SetEventRange(0,-1) ;
450 fIsOldRCUFormat = kFALSE;
453 //____________________________________________________________________________
454 Int_t AliPHOSClusterizerv1::AreNeighbours(AliPHOSDigit * d1, AliPHOSDigit * d2)const
456 // Gives the neighbourness of two digits = 0 are not neighbour but continue searching
458 // = 2 are not neighbour but do not continue searching
459 // neighbours are defined as digits having at least a common vertex
460 // The order of d1 and d2 is important: first (d1) should be a digit already in a cluster
461 // which is compared to a digit (d2) not yet in a cluster
463 AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
468 geom->AbsToRelNumbering(d1->GetId(), relid1) ;
471 geom->AbsToRelNumbering(d2->GetId(), relid2) ;
473 if ( (relid1[0] == relid2[0]) && (relid1[1]==relid2[1]) ) { // inside the same PHOS module
474 Int_t rowdiff = TMath::Abs( relid1[2] - relid2[2] ) ;
475 Int_t coldiff = TMath::Abs( relid1[3] - relid2[3] ) ;
477 if (( coldiff <= 1 ) && ( rowdiff <= 1 )){
478 if((relid1[1] != 0) || (TMath::Abs(d1->GetTime() - d2->GetTime() ) < fEmcTimeGate))
482 if((relid2[2] > relid1[2]) && (relid2[3] > relid1[3]+1))
483 rv = 2; // Difference in row numbers is too large to look further
489 if( (relid1[0] < relid2[0]) || (relid1[1] != relid2[1]) )
496 //____________________________________________________________________________
497 void AliPHOSClusterizerv1::CleanDigits(TClonesArray * digits)
499 // Remove digits with amplitudes below threshold
501 for(Int_t i=0; i<digits->GetEntriesFast(); i++){
502 AliPHOSDigit * digit = static_cast<AliPHOSDigit*>(digits->At(i)) ;
503 if ( (IsInEmc(digit) && CalibrateEMC(digit->GetEnergy(),digit->GetId()) < fEmcMinE) ||
504 (IsInCpv(digit) && CalibrateCPV(digit->GetAmp() ,digit->GetId()) < fCpvMinE) )
505 digits->RemoveAt(i) ;
508 for (Int_t i = 0 ; i < digits->GetEntriesFast() ; i++) {
509 AliPHOSDigit *digit = static_cast<AliPHOSDigit*>( digits->At(i) ) ;
510 digit->SetIndexInList(i) ;
514 //____________________________________________________________________________
515 Bool_t AliPHOSClusterizerv1::IsInEmc(AliPHOSDigit * digit) const
517 // Tells if (true) or not (false) the digit is in a PHOS-EMC module
520 AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
522 Int_t nEMC = geom->GetNModules()*geom->GetNPhi()*geom->GetNZ();
524 if(digit->GetId() <= nEMC ) rv = kTRUE;
529 //____________________________________________________________________________
530 Bool_t AliPHOSClusterizerv1::IsInCpv(AliPHOSDigit * digit) const
532 // Tells if (true) or not (false) the digit is in a PHOS-CPV module
536 AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
538 Int_t nEMC = geom->GetNModules()*geom->GetNPhi()*geom->GetNZ();
540 if(digit->GetId() > nEMC ) rv = kTRUE;
545 //____________________________________________________________________________
546 void AliPHOSClusterizerv1::Unload()
548 AliPHOSGetter * gime = AliPHOSGetter::Instance() ;
549 gime->PhosLoader()->UnloadDigits() ;
550 gime->PhosLoader()->UnloadRecPoints() ;
553 //____________________________________________________________________________
554 void AliPHOSClusterizerv1::WriteRecPoints()
557 // Creates new branches with given title
558 // fills and writes into TreeR.
560 AliPHOSGetter * gime = AliPHOSGetter::Instance();
562 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
563 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
564 TClonesArray * digits = gime->Digits() ;
568 //Evaluate position, dispersion and other RecPoint properties..
569 Int_t nEmc = emcRecPoints->GetEntriesFast();
570 for(index = 0; index < nEmc; index++){
571 AliPHOSEmcRecPoint * rp = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(index) );
572 rp->Purify(fEmcMinE) ;
573 if(rp->GetMultiplicity()>0.) //If this RP is not empty
574 rp->EvalAll(fW0,digits) ;
576 emcRecPoints->RemoveAt(index) ;
580 emcRecPoints->Compress() ;
581 emcRecPoints->Sort() ;
582 // emcRecPoints->Expand(emcRecPoints->GetEntriesFast()) ;
583 for(index = 0; index < emcRecPoints->GetEntries(); index++){
584 dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(index) )->SetIndexInList(index) ;
587 //Now the same for CPV
588 for(index = 0; index < cpvRecPoints->GetEntries(); index++){
589 AliPHOSCpvRecPoint * rp = dynamic_cast<AliPHOSCpvRecPoint *>( cpvRecPoints->At(index) );
590 rp->EvalAll(fW0CPV,digits) ;
592 cpvRecPoints->Sort() ;
594 for(index = 0; index < cpvRecPoints->GetEntries(); index++)
595 dynamic_cast<AliPHOSCpvRecPoint *>( cpvRecPoints->At(index) )->SetIndexInList(index) ;
597 cpvRecPoints->Expand(cpvRecPoints->GetEntriesFast()) ;
599 if(fWrite){ //We write TreeR
600 TTree * treeR = gime->TreeR();
602 Int_t bufferSize = 32000 ;
603 Int_t splitlevel = 0 ;
606 TBranch * emcBranch = treeR->Branch("PHOSEmcRP","TObjArray",&emcRecPoints,bufferSize,splitlevel);
607 emcBranch->SetTitle(BranchName());
610 TBranch * cpvBranch = treeR->Branch("PHOSCpvRP","TObjArray",&cpvRecPoints,bufferSize,splitlevel);
611 cpvBranch->SetTitle(BranchName());
616 gime->WriteRecPoints("OVERWRITE");
617 gime->WriteClusterizer("OVERWRITE");
621 //____________________________________________________________________________
622 void AliPHOSClusterizerv1::MakeClusters()
624 // Steering method to construct the clusters stored in a list of Reconstructed Points
625 // A cluster is defined as a list of neighbour digits
628 AliPHOSGetter * gime = AliPHOSGetter::Instance();
630 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
631 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
633 emcRecPoints->Delete() ;
634 cpvRecPoints->Delete() ;
636 TClonesArray * digits = gime->Digits() ;
638 //Remove digits below threshold
639 CleanDigits(digits) ;
641 TClonesArray * digitsC = static_cast<TClonesArray*>( digits->Clone() ) ;
643 // Clusterization starts
645 TIter nextdigit(digitsC) ;
646 AliPHOSDigit * digit ;
647 Bool_t notremoved = kTRUE ;
649 while ( (digit = dynamic_cast<AliPHOSDigit *>( nextdigit()) ) ) { // scan over the list of digitsC
652 AliPHOSRecPoint * clu = 0 ;
654 TArrayI clusterdigitslist(1500) ;
657 if (( IsInEmc (digit) &&
658 CalibrateEMC(digit->GetEnergy(),digit->GetId()) > fEmcClusteringThreshold ) ||
660 CalibrateCPV(digit->GetAmp() ,digit->GetId()) > fCpvClusteringThreshold ) ) {
661 Int_t iDigitInCluster = 0 ;
663 if ( IsInEmc(digit) ) {
664 // start a new EMC RecPoint
665 if(fNumberOfEmcClusters >= emcRecPoints->GetSize())
666 emcRecPoints->Expand(2*fNumberOfEmcClusters+1) ;
668 emcRecPoints->AddAt(new AliPHOSEmcRecPoint(""), fNumberOfEmcClusters) ;
669 clu = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(fNumberOfEmcClusters) ) ;
670 fNumberOfEmcClusters++ ;
671 clu->AddDigit(*digit, CalibrateEMC(digit->GetEnergy(),digit->GetId())) ;
672 clusterdigitslist[iDigitInCluster] = digit->GetIndexInList() ;
674 digitsC->Remove(digit) ;
678 // start a new CPV cluster
679 if(fNumberOfCpvClusters >= cpvRecPoints->GetSize())
680 cpvRecPoints->Expand(2*fNumberOfCpvClusters+1);
682 cpvRecPoints->AddAt(new AliPHOSCpvRecPoint(""), fNumberOfCpvClusters) ;
684 clu = dynamic_cast<AliPHOSCpvRecPoint *>( cpvRecPoints->At(fNumberOfCpvClusters) ) ;
685 fNumberOfCpvClusters++ ;
686 clu->AddDigit(*digit, CalibrateCPV(digit->GetAmp(),digit->GetId()) ) ;
687 clusterdigitslist[iDigitInCluster] = digit->GetIndexInList() ;
689 digitsC->Remove(digit) ;
692 // Here we remove remaining EMC digits, which cannot make a cluster
695 while( ( digit = dynamic_cast<AliPHOSDigit *>( nextdigit() ) ) ) {
697 digitsC->Remove(digit) ;
701 notremoved = kFALSE ;
708 AliPHOSDigit * digitN ;
710 while (index < iDigitInCluster){ // scan over digits already in cluster
711 digit = dynamic_cast<AliPHOSDigit*>( digits->At(clusterdigitslist[index]) ) ;
713 while ( (digitN = dynamic_cast<AliPHOSDigit *>( nextdigit() ) ) ) { // scan over the reduced list of digits
714 Int_t ineb = AreNeighbours(digit, digitN); // call (digit,digitN) in THAT oder !!!!!
716 case 0 : // not a neighbour
718 case 1 : // are neighbours
719 if (IsInEmc (digitN))
720 clu->AddDigit(*digitN, CalibrateEMC( digitN->GetEnergy(), digitN->GetId() ) );
722 clu->AddDigit(*digitN, CalibrateCPV( digitN->GetAmp() , digitN->GetId() ) );
724 clusterdigitslist[iDigitInCluster] = digitN->GetIndexInList() ;
726 digitsC->Remove(digitN) ;
728 case 2 : // too far from each other
737 } // loop over cluster
748 //____________________________________________________________________________
749 void AliPHOSClusterizerv1::MakeUnfolding()
751 // Unfolds clusters using the shape of an ElectroMagnetic shower
752 // Performs unfolding of all EMC/CPV clusters
754 AliPHOSGetter * gime = AliPHOSGetter::Instance();
756 const AliPHOSGeometry * geom = gime->PHOSGeometry() ;
758 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
759 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
760 TClonesArray * digits = gime->Digits() ;
762 // Unfold first EMC clusters
763 if(fNumberOfEmcClusters > 0){
765 Int_t nModulesToUnfold = geom->GetNModules() ;
767 Int_t numberofNotUnfolded = fNumberOfEmcClusters ;
769 for(index = 0 ; index < numberofNotUnfolded ; index++){
771 AliPHOSEmcRecPoint * emcRecPoint = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(index) ) ;
772 if(emcRecPoint->GetPHOSMod()> nModulesToUnfold)
775 Int_t nMultipl = emcRecPoint->GetMultiplicity() ;
776 AliPHOSDigit ** maxAt = new AliPHOSDigit*[nMultipl] ;
777 Float_t * maxAtEnergy = new Float_t[nMultipl] ;
778 Int_t nMax = emcRecPoint->GetNumberOfLocalMax(maxAt, maxAtEnergy,fEmcLocMaxCut,digits) ;
780 if( nMax > 1 ) { // if cluster is very flat (no pronounced maximum) then nMax = 0
781 UnfoldCluster(emcRecPoint, nMax, maxAt, maxAtEnergy) ;
782 emcRecPoints->Remove(emcRecPoint);
783 emcRecPoints->Compress() ;
785 fNumberOfEmcClusters -- ;
786 numberofNotUnfolded-- ;
789 emcRecPoint->SetNExMax(1) ; //Only one local maximum
793 delete[] maxAtEnergy ;
796 // Unfolding of EMC clusters finished
799 // Unfold now CPV clusters
800 if(fNumberOfCpvClusters > 0){
802 Int_t nModulesToUnfold = geom->GetNModules() ;
804 Int_t numberofCpvNotUnfolded = fNumberOfCpvClusters ;
806 for(index = 0 ; index < numberofCpvNotUnfolded ; index++){
808 AliPHOSRecPoint * recPoint = dynamic_cast<AliPHOSRecPoint *>( cpvRecPoints->At(index) ) ;
810 if(recPoint->GetPHOSMod()> nModulesToUnfold)
813 AliPHOSEmcRecPoint * emcRecPoint = dynamic_cast<AliPHOSEmcRecPoint*>(recPoint) ;
815 Int_t nMultipl = emcRecPoint->GetMultiplicity() ;
816 AliPHOSDigit ** maxAt = new AliPHOSDigit*[nMultipl] ;
817 Float_t * maxAtEnergy = new Float_t[nMultipl] ;
818 Int_t nMax = emcRecPoint->GetNumberOfLocalMax(maxAt, maxAtEnergy,fCpvLocMaxCut,digits) ;
820 if( nMax > 1 ) { // if cluster is very flat (no pronounced maximum) then nMax = 0
821 UnfoldCluster(emcRecPoint, nMax, maxAt, maxAtEnergy) ;
822 cpvRecPoints->Remove(emcRecPoint);
823 cpvRecPoints->Compress() ;
825 numberofCpvNotUnfolded-- ;
826 fNumberOfCpvClusters-- ;
830 delete[] maxAtEnergy ;
833 //Unfolding of Cpv clusters finished
837 //____________________________________________________________________________
838 Double_t AliPHOSClusterizerv1::ShowerShape(Double_t r)
840 // Shape of the shower (see PHOS TDR)
841 // If you change this function, change also the gradient evaluation in ChiSquare()
843 Double_t r4 = r*r*r*r ;
844 Double_t r295 = TMath::Power(r, 2.95) ;
845 Double_t shape = TMath::Exp( -r4 * (1. / (2.32 + 0.26 * r4) + 0.0316 / (1 + 0.0652 * r295) ) ) ;
849 //____________________________________________________________________________
850 void AliPHOSClusterizerv1::UnfoldCluster(AliPHOSEmcRecPoint * iniEmc,
852 AliPHOSDigit ** maxAt,
853 Float_t * maxAtEnergy)
855 // Performs the unfolding of a cluster with nMax overlapping showers
857 AliPHOSGetter * gime = AliPHOSGetter::Instance();
859 const AliPHOSGeometry * geom = gime->PHOSGeometry() ;
861 const TClonesArray * digits = gime->Digits() ;
862 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
863 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
865 Int_t nPar = 3 * nMax ;
866 Float_t * fitparameters = new Float_t[nPar] ;
868 Bool_t rv = FindFit(iniEmc, maxAt, maxAtEnergy, nPar, fitparameters) ;
870 // Fit failed, return and remove cluster
871 iniEmc->SetNExMax(-1) ;
872 delete[] fitparameters ;
876 // create ufolded rec points and fill them with new energy lists
877 // First calculate energy deposited in each sell in accordance with fit (without fluctuations): efit[]
878 // and later correct this number in acordance with actual energy deposition
880 Int_t nDigits = iniEmc->GetMultiplicity() ;
881 Float_t * efit = new Float_t[nDigits] ;
882 Float_t xDigit=0.,zDigit=0.,distance=0. ;
883 Float_t xpar=0.,zpar=0.,epar=0. ;
885 AliPHOSDigit * digit = 0 ;
886 Int_t * emcDigits = iniEmc->GetDigitsList() ;
890 for(iDigit = 0 ; iDigit < nDigits ; iDigit ++){
891 digit = dynamic_cast<AliPHOSDigit*>( digits->At(emcDigits[iDigit] ) ) ;
892 geom->AbsToRelNumbering(digit->GetId(), relid) ;
893 geom->RelPosInModule(relid, xDigit, zDigit) ;
897 while(iparam < nPar ){
898 xpar = fitparameters[iparam] ;
899 zpar = fitparameters[iparam+1] ;
900 epar = fitparameters[iparam+2] ;
902 distance = (xDigit - xpar) * (xDigit - xpar) + (zDigit - zpar) * (zDigit - zpar) ;
903 distance = TMath::Sqrt(distance) ;
904 efit[iDigit] += epar * ShowerShape(distance) ;
909 // Now create new RecPoints and fill energy lists with efit corrected to fluctuations
910 // so that energy deposited in each cell is distributed betwin new clusters proportionally
911 // to its contribution to efit
913 Float_t * emcEnergies = iniEmc->GetEnergiesList() ;
917 while(iparam < nPar ){
918 xpar = fitparameters[iparam] ;
919 zpar = fitparameters[iparam+1] ;
920 epar = fitparameters[iparam+2] ;
923 AliPHOSEmcRecPoint * emcRP = 0 ;
925 if(iniEmc->IsEmc()){ //create new entries in fEmcRecPoints...
927 if(fNumberOfEmcClusters >= emcRecPoints->GetSize())
928 emcRecPoints->Expand(2*fNumberOfEmcClusters) ;
930 (*emcRecPoints)[fNumberOfEmcClusters] = new AliPHOSEmcRecPoint("") ;
931 emcRP = dynamic_cast<AliPHOSEmcRecPoint *>( emcRecPoints->At(fNumberOfEmcClusters) ) ;
932 fNumberOfEmcClusters++ ;
933 emcRP->SetNExMax((Int_t)nPar/3) ;
935 else{//create new entries in fCpvRecPoints
936 if(fNumberOfCpvClusters >= cpvRecPoints->GetSize())
937 cpvRecPoints->Expand(2*fNumberOfCpvClusters) ;
939 (*cpvRecPoints)[fNumberOfCpvClusters] = new AliPHOSCpvRecPoint("") ;
940 emcRP = dynamic_cast<AliPHOSEmcRecPoint *>( cpvRecPoints->At(fNumberOfCpvClusters) ) ;
941 fNumberOfCpvClusters++ ;
945 for(iDigit = 0 ; iDigit < nDigits ; iDigit ++){
946 digit = dynamic_cast<AliPHOSDigit*>( digits->At( emcDigits[iDigit] ) ) ;
947 geom->AbsToRelNumbering(digit->GetId(), relid) ;
948 geom->RelPosInModule(relid, xDigit, zDigit) ;
949 distance = (xDigit - xpar) * (xDigit - xpar) + (zDigit - zpar) * (zDigit - zpar) ;
950 distance = TMath::Sqrt(distance) ;
951 ratio = epar * ShowerShape(distance) / efit[iDigit] ;
952 eDigit = emcEnergies[iDigit] * ratio ;
953 emcRP->AddDigit( *digit, eDigit ) ;
957 delete[] fitparameters ;
962 //_____________________________________________________________________________
963 void AliPHOSClusterizerv1::UnfoldingChiSquare(Int_t & nPar, Double_t * Grad, Double_t & fret, Double_t * x, Int_t iflag)
965 // Calculates the Chi square for the cluster unfolding minimization
966 // Number of parameters, Gradient, Chi squared, parameters, what to do
968 TList * toMinuit = dynamic_cast<TList*>( gMinuit->GetObjectFit() ) ;
970 AliPHOSEmcRecPoint * emcRP = dynamic_cast<AliPHOSEmcRecPoint*>( toMinuit->At(0) ) ;
971 TClonesArray * digits = dynamic_cast<TClonesArray*>( toMinuit->At(1) ) ;
975 // AliPHOSEmcRecPoint * emcRP = dynamic_cast<AliPHOSEmcRecPoint *>( gMinuit->GetObjectFit() ) ; // EmcRecPoint to fit
977 Int_t * emcDigits = emcRP->GetDigitsList() ;
979 Int_t nOdigits = emcRP->GetDigitsMultiplicity() ;
981 Float_t * emcEnergies = emcRP->GetEnergiesList() ;
983 const AliPHOSGeometry * geom = AliPHOSGetter::Instance()->PHOSGeometry() ;
988 for(iparam = 0 ; iparam < nPar ; iparam++)
989 Grad[iparam] = 0 ; // Will evaluate gradient
993 AliPHOSDigit * digit ;
996 for( iDigit = 0 ; iDigit < nOdigits ; iDigit++) {
998 digit = dynamic_cast<AliPHOSDigit*>( digits->At( emcDigits[iDigit] ) );
1004 geom->AbsToRelNumbering(digit->GetId(), relid) ;
1006 geom->RelPosInModule(relid, xDigit, zDigit) ;
1008 if(iflag == 2){ // calculate gradient
1011 while(iParam < nPar ){
1012 Double_t distance = (xDigit - x[iParam]) * (xDigit - x[iParam]) ;
1014 distance += (zDigit - x[iParam]) * (zDigit - x[iParam]) ;
1015 distance = TMath::Sqrt( distance ) ;
1017 efit += x[iParam] * ShowerShape(distance) ;
1020 Double_t sum = 2. * (efit - emcEnergies[iDigit]) / emcEnergies[iDigit] ; // Here we assume, that sigma = sqrt(E)
1022 while(iParam < nPar ){
1023 Double_t xpar = x[iParam] ;
1024 Double_t zpar = x[iParam+1] ;
1025 Double_t epar = x[iParam+2] ;
1026 Double_t dr = TMath::Sqrt( (xDigit - xpar) * (xDigit - xpar) + (zDigit - zpar) * (zDigit - zpar) );
1027 Double_t shape = sum * ShowerShape(dr) ;
1028 Double_t r4 = dr*dr*dr*dr ;
1029 Double_t r295 = TMath::Power(dr,2.95) ;
1030 Double_t deriv =-4. * dr*dr * ( 2.32 / ( (2.32 + 0.26 * r4) * (2.32 + 0.26 * r4) ) +
1031 0.0316 * (1. + 0.0171 * r295) / ( ( 1. + 0.0652 * r295) * (1. + 0.0652 * r295) ) ) ;
1033 Grad[iParam] += epar * shape * deriv * (xpar - xDigit) ; // Derivative over x
1035 Grad[iParam] += epar * shape * deriv * (zpar - zDigit) ; // Derivative over z
1037 Grad[iParam] += shape ; // Derivative over energy
1044 while(iparam < nPar ){
1045 Double_t xpar = x[iparam] ;
1046 Double_t zpar = x[iparam+1] ;
1047 Double_t epar = x[iparam+2] ;
1049 Double_t distance = (xDigit - xpar) * (xDigit - xpar) + (zDigit - zpar) * (zDigit - zpar) ;
1050 distance = TMath::Sqrt(distance) ;
1051 efit += epar * ShowerShape(distance) ;
1054 fret += (efit-emcEnergies[iDigit])*(efit-emcEnergies[iDigit])/emcEnergies[iDigit] ;
1055 // Here we assume, that sigma = sqrt(E)
1060 //____________________________________________________________________________
1061 void AliPHOSClusterizerv1::Print(const Option_t *)const
1063 // Print clusterizer parameters
1066 TString taskName(GetName()) ;
1067 taskName.ReplaceAll(Version(), "") ;
1069 if( strcmp(GetName(), "") !=0 ) {
1071 message = "\n--------------- %s %s -----------\n" ;
1072 message += "Clusterizing digits from the file: %s\n" ;
1073 message += " Branch: %s\n" ;
1074 message += " EMC Clustering threshold = %f\n" ;
1075 message += " EMC Local Maximum cut = %f\n" ;
1076 message += " EMC Logarothmic weight = %f\n" ;
1077 message += " CPV Clustering threshold = %f\n" ;
1078 message += " CPV Local Maximum cut = %f\n" ;
1079 message += " CPV Logarothmic weight = %f\n" ;
1081 message += " Unfolding on\n" ;
1083 message += " Unfolding off\n" ;
1085 message += "------------------------------------------------------------------" ;
1088 message = " AliPHOSClusterizerv1 not initialized " ;
1090 AliInfo(Form("%s, %s %s %s %s %s %s %s %s %s %s", message.Data(),
1095 fEmcClusteringThreshold,
1098 fCpvClusteringThreshold,
1104 //____________________________________________________________________________
1105 void AliPHOSClusterizerv1::PrintRecPoints(Option_t * option)
1107 // Prints list of RecPoints produced at the current pass of AliPHOSClusterizer
1109 AliPHOSGetter * gime = AliPHOSGetter::Instance();
1111 TObjArray * emcRecPoints = gime->EmcRecPoints() ;
1112 TObjArray * cpvRecPoints = gime->CpvRecPoints() ;
1114 AliInfo(Form("\nevent %d \n Found %d EMC RecPoints and %d CPV RecPoints",
1115 gAlice->GetEvNumber(),
1116 emcRecPoints->GetEntriesFast(),
1117 cpvRecPoints->GetEntriesFast() )) ;
1119 fRecPointsInRun += emcRecPoints->GetEntriesFast() ;
1120 fRecPointsInRun += cpvRecPoints->GetEntriesFast() ;
1123 if(strstr(option,"all")) {
1124 printf("\n EMC clusters \n") ;
1125 printf("Index Ene(MeV) Multi Module X Y Z Lambdas_1 Lambda_2 # of prim Primaries list\n") ;
1127 for (index = 0 ; index < emcRecPoints->GetEntries() ; index++) {
1128 AliPHOSEmcRecPoint * rp = (AliPHOSEmcRecPoint * )emcRecPoints->At(index) ;
1130 rp->GetLocalPosition(locpos);
1132 rp->GetElipsAxis(lambda);
1135 primaries = rp->GetPrimaries(nprimaries);
1136 printf("\n%6d %8.2f %3d %2d %4.1f %4.1f %4.1f %4f %4f %2d : ",
1137 rp->GetIndexInList(), rp->GetEnergy(), rp->GetMultiplicity(), rp->GetPHOSMod(),
1138 locpos.X(), locpos.Y(), locpos.Z(), lambda[0], lambda[1], nprimaries) ;
1140 for (Int_t iprimary=0; iprimary<nprimaries; iprimary++) {
1141 printf("%d ", primaries[iprimary] ) ;
1146 //Now plot CPV recPoints
1147 printf("\n CPV clusters \n") ;
1148 printf("Index Ene(MeV) Module X Y Z \n") ;
1149 for (index = 0 ; index < cpvRecPoints->GetEntries() ; index++) {
1150 AliPHOSCpvRecPoint * rp = (AliPHOSCpvRecPoint * )cpvRecPoints->At(index) ;
1153 rp->GetLocalPosition(locpos);
1155 printf("\n%6d %8.2f %2d %4.1f %4.1f %4.1f \n",
1156 rp->GetIndexInList(), rp->GetEnergy(), rp->GetPHOSMod(),
1157 locpos.X(), locpos.Y(), locpos.Z()) ;