Line data Source code
1 : /**************************************************************************
2 : * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 : * *
4 : * Author: The ALICE Off-line Project. *
5 : * Contributors are mentioned in the code where appropriate. *
6 : * *
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 : **************************************************************************/
15 :
16 : /* $Id$ */
17 :
18 : /* History of cvs commits:
19 : *
20 : * $Log: AliPHOSClusterizerv1.cxx,v $
21 : * Revision 1.118 2007/12/11 21:23:26 kharlov
22 : * Added possibility to swith off unfolding
23 : *
24 : * Revision 1.117 2007/10/18 08:42:05 kharlov
25 : * Bad channels cleaned before clusterization
26 : *
27 : * Revision 1.116 2007/10/01 20:24:08 kharlov
28 : * Memory leaks fixed
29 : *
30 : * Revision 1.115 2007/09/26 14:22:17 cvetan
31 : * Important changes to the reconstructor classes. Complete elimination of the run-loaders, which are now steered only from AliReconstruction. Removal of the corresponding Reconstruct() and FillESD() methods.
32 : *
33 : * Revision 1.114 2007/09/06 16:06:44 kharlov
34 : * Absence of sorting results in loose of all unfolded clusters
35 : *
36 : * Revision 1.113 2007/08/28 12:55:07 policheh
37 : * Loaders removed from the reconstruction code (C.Cheshkov)
38 : *
39 : * Revision 1.112 2007/08/22 09:20:50 hristov
40 : * Updated QA classes (Yves)
41 : *
42 : * Revision 1.111 2007/08/08 12:11:28 kharlov
43 : * Protection against uninitialized fQADM
44 : *
45 : * Revision 1.110 2007/08/07 14:16:00 kharlov
46 : * Quality assurance added (Yves Schutz)
47 : *
48 : * Revision 1.109 2007/07/24 17:20:35 policheh
49 : * Usage of RecoParam objects instead of hardcoded parameters in reconstruction.
50 : * (See $ALICE_ROOT/PHOS/macros/BeamTest2006/RawReconstruction.C).
51 : *
52 : * Revision 1.108 2007/06/18 07:00:51 kharlov
53 : * Bug fix for attempt to use AliPHOSEmcRecPoint after its deletion
54 : *
55 : * Revision 1.107 2007/05/25 14:12:26 policheh
56 : * Local to tracking CS transformation added for CPV rec. points
57 : *
58 : * Revision 1.106 2007/05/24 13:01:22 policheh
59 : * Local to tracking CS transformation invoked for each EMC rec.point
60 : *
61 : * Revision 1.105 2007/05/02 13:41:22 kharlov
62 : * Mode protection against absence of calib.data from AliPHOSCalibData to AliPHOSClusterizerv1::GetCalibrationParameters()
63 : *
64 : * Revision 1.104 2007/04/27 16:55:53 kharlov
65 : * Calibration stops if PHOS CDB objects do not exist
66 : *
67 : * Revision 1.103 2007/04/11 11:55:45 policheh
68 : * SetDistancesToBadChannels() added.
69 : *
70 : * Revision 1.102 2007/03/28 19:18:15 kharlov
71 : * RecPoints recalculation in TSM removed
72 : *
73 : * Revision 1.101 2007/03/06 06:51:27 kharlov
74 : * Calculation of cluster properties dep. on vertex posponed to TrackSegmentMaker
75 : *
76 : * Revision 1.100 2007/01/10 11:07:26 kharlov
77 : * Raw digits writing to file (B.Polichtchouk)
78 : *
79 : * Revision 1.99 2006/11/07 16:49:51 kharlov
80 : * Corrections for next event switch in case of raw data (B.Polichtchouk)
81 : *
82 : * Revision 1.98 2006/10/27 17:14:27 kharlov
83 : * Introduce AliDebug and AliLog (B.Polichtchouk)
84 : *
85 : * Revision 1.97 2006/08/29 11:41:19 kharlov
86 : * Missing implementation of ctors and = operator are added
87 : *
88 : * Revision 1.96 2006/08/25 16:56:30 kharlov
89 : * Compliance with Effective C++
90 : *
91 : * Revision 1.95 2006/08/11 12:36:26 cvetan
92 : * Update of the PHOS code needed in order to read and reconstruct the beam test raw data (i.e. without an existing galice.root)
93 : *
94 : * Revision 1.94 2006/08/07 12:27:49 hristov
95 : * Removing obsolete code which affected the event numbering scheme
96 : *
97 : * Revision 1.93 2006/08/01 12:20:17 cvetan
98 : * 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
99 : *
100 : * Revision 1.92 2006/04/29 20:26:46 hristov
101 : * Separate EMC and CPV calibration (Yu.Kharlov)
102 : *
103 : * Revision 1.91 2006/04/22 10:30:17 hristov
104 : * Add fEnergy to AliPHOSDigit and operate with EMC amplitude in energy units (Yu.Kharlov)
105 : *
106 : * Revision 1.90 2006/04/11 15:22:59 hristov
107 : * run number in query set to -1: forces AliCDBManager to use its run number (A.Colla)
108 : *
109 : * Revision 1.89 2006/03/13 14:05:42 kharlov
110 : * Calibration objects for EMC and CPV
111 : *
112 : * Revision 1.88 2006/01/11 08:54:52 hristov
113 : * Additional protection in case no calibration entry was found
114 : *
115 : * Revision 1.87 2005/11/22 08:46:43 kharlov
116 : * Updated to new CDB (Boris Polichtchouk)
117 : *
118 : * Revision 1.86 2005/11/14 21:52:43 hristov
119 : * Coding conventions
120 : *
121 : * Revision 1.85 2005/09/27 16:08:08 hristov
122 : * New version of CDB storage framework (A.Colla)
123 : *
124 : * Revision 1.84 2005/09/21 10:02:47 kharlov
125 : * Reading calibration from CDB (Boris Polichtchouk)
126 : *
127 : * Revision 1.82 2005/09/02 15:43:13 kharlov
128 : * Add comments in GetCalibrationParameters and Calibrate
129 : *
130 : * Revision 1.81 2005/09/02 14:32:07 kharlov
131 : * Calibration of raw data
132 : *
133 : * Revision 1.80 2005/08/24 15:31:36 kharlov
134 : * Setting raw digits flag
135 : *
136 : * Revision 1.79 2005/07/25 15:53:53 kharlov
137 : * Read raw data
138 : *
139 : * Revision 1.78 2005/05/28 14:19:04 schutz
140 : * Compilation warnings fixed by T.P.
141 : *
142 : */
143 :
144 : //*-- Author: Yves Schutz (SUBATECH) & Dmitri Peressounko (SUBATECH & Kurchatov Institute)
145 : //////////////////////////////////////////////////////////////////////////////
146 : // Clusterization class. Performs clusterization (collects neighbouring active cells) and
147 : // unfolds the clusters having several local maxima.
148 : // Results are stored in TreeR#, branches PHOSEmcRP (EMC recPoints),
149 : // PHOSCpvRP (CPV RecPoints) and AliPHOSClusterizer (Clusterizer with all
150 : // parameters including input digits branch title, thresholds etc.)
151 : // This TTask is normally called from Reconstructioner, but can as well be used in
152 : // standalone mode.
153 : // Use Case:
154 : // root [0] AliPHOSClusterizerv1 * cl = new AliPHOSClusterizerv1(<pointer_to_phos_geometry_onject>)
155 : // root [1] cl->Digits2Clusters(digitsTree,clusterTree)
156 : // //finds RecPoints in the current event
157 : // root [2] cl->SetDigitsBranch("digits2")
158 : // //sets another title for Digitis (input) branch
159 : // root [3] cl->SetRecPointsBranch("recp2")
160 : // //sets another title four output branches
161 : // root [4] cl->SetEmcLocalMaxCut(0.03)
162 : // //set clusterization parameters
163 :
164 : // --- ROOT system ---
165 :
166 : #include "TMath.h"
167 : #include "TMinuit.h"
168 : #include "TTree.h"
169 : #include "TBenchmark.h"
170 : #include "TClonesArray.h"
171 :
172 : // --- Standard library ---
173 :
174 : // --- AliRoot header files ---
175 : #include "AliLog.h"
176 : #include "AliConfig.h"
177 : #include "AliPHOSGeometry.h"
178 : #include "AliPHOSClusterizerv1.h"
179 : #include "AliPHOSEmcRecPoint.h"
180 : #include "AliPHOSCpvRecPoint.h"
181 : #include "AliPHOSDigit.h"
182 : #include "AliPHOSDigitizer.h"
183 : #include "AliCDBManager.h"
184 : #include "AliCDBStorage.h"
185 : #include "AliCDBEntry.h"
186 : #include "AliPHOSRecoParam.h"
187 : #include "AliPHOSReconstructor.h"
188 : #include "AliPHOSCalibData.h"
189 :
190 22 : ClassImp(AliPHOSClusterizerv1)
191 :
192 : //____________________________________________________________________________
193 : AliPHOSClusterizerv1::AliPHOSClusterizerv1() :
194 0 : AliPHOSClusterizer(),
195 0 : fDefaultInit(0), fEmcCrystals(0), fToUnfold(0), fToUnfoldCPV(0),
196 0 : fWrite(0),
197 0 : fNumberOfEmcClusters(0), fNumberOfCpvClusters(0),
198 0 : fEmcClusteringThreshold(0), fCpvClusteringThreshold(0),
199 0 : fEmcLocMaxCut(0), fW0(0), fCpvLocMaxCut(0),
200 0 : fW0CPV(0),
201 0 : fTimeGateLowAmp(0.), fTimeGateLow(0.), fTimeGateHigh(0.),
202 0 : fEcoreRadius(0)
203 0 : {
204 : // default ctor (to be used mainly by Streamer)
205 :
206 0 : fDefaultInit = kTRUE ;
207 :
208 0 : for(Int_t i=0; i<53760; i++){
209 0 : fDigitsUsed[i]=0 ;
210 : }
211 0 : }
212 :
213 : //____________________________________________________________________________
214 : AliPHOSClusterizerv1::AliPHOSClusterizerv1(AliPHOSGeometry *geom) :
215 2 : AliPHOSClusterizer(geom),
216 2 : fDefaultInit(0), fEmcCrystals(0), fToUnfold(0), fToUnfoldCPV(0),
217 2 : fWrite(0),
218 2 : fNumberOfEmcClusters(0), fNumberOfCpvClusters(0),
219 2 : fEmcClusteringThreshold(0), fCpvClusteringThreshold(0),
220 2 : fEmcLocMaxCut(0), fW0(0), fCpvLocMaxCut(0),
221 2 : fW0CPV(0),
222 2 : fTimeGateLowAmp(0.), fTimeGateLow(0.), fTimeGateHigh(0.),
223 2 : fEcoreRadius(0)
224 10 : {
225 : // ctor with the indication of the file where header Tree and digits Tree are stored
226 :
227 215044 : for(Int_t i=0; i<53760; i++){
228 107520 : fDigitsUsed[i]=0 ;
229 : }
230 :
231 2 : Init() ;
232 2 : fDefaultInit = kFALSE ;
233 4 : }
234 :
235 : //____________________________________________________________________________
236 : AliPHOSClusterizerv1::~AliPHOSClusterizerv1()
237 8 : {
238 : // dtor
239 :
240 8 : }
241 : //____________________________________________________________________________
242 : void AliPHOSClusterizerv1::Digits2Clusters(Option_t *option)
243 : {
244 : // Steering method to perform clusterization for one event
245 : // The input is the tree with digits.
246 : // The output is the tree with clusters.
247 :
248 16 : if(strstr(option,"tim"))
249 0 : gBenchmark->Start("PHOSClusterizer");
250 :
251 8 : if(strstr(option,"print")) {
252 0 : Print() ;
253 0 : return ;
254 : }
255 :
256 8 : MakeClusters() ;
257 :
258 24 : AliDebug(2,Form("Number of EMC clusters: %d, CPV clusters: %d\n",
259 : fEMCRecPoints->GetEntriesFast(), fCPVRecPoints->GetEntriesFast()));
260 8 : if(AliLog::GetGlobalDebugLevel()>1) {
261 0 : fEMCRecPoints->Print();
262 0 : fCPVRecPoints->Print();
263 0 : }
264 :
265 8 : MakeUnfolding();
266 :
267 8 : WriteRecPoints();
268 :
269 8 : if(strstr(option,"deb"))
270 0 : PrintRecPoints(option) ;
271 :
272 8 : if(strstr(option,"tim")){
273 0 : gBenchmark->Stop("PHOSClusterizer");
274 0 : AliInfo(Form("took %f seconds for Clusterizing\n",
275 : gBenchmark->GetCpuTime("PHOSClusterizer")));
276 0 : }
277 8 : fEMCRecPoints->Delete();
278 8 : fCPVRecPoints->Delete();
279 16 : }
280 :
281 : //____________________________________________________________________________
282 : Bool_t AliPHOSClusterizerv1::FindFit(AliPHOSEmcRecPoint * emcRP, AliPHOSDigit ** maxAt, Float_t * maxAtEnergy,
283 : Int_t nPar, Float_t * fitparameters) const
284 : {
285 : // Calls TMinuit to fit the energy distribution of a cluster with several maxima
286 : // The initial values for fitting procedure are set equal to the positions of local maxima.
287 : // Cluster will be fitted as a superposition of nPar/3 electromagnetic showers
288 :
289 :
290 0 : if(!gMinuit) //it was deleted by someone else
291 0 : gMinuit = new TMinuit(100) ;
292 0 : gMinuit->mncler(); // Reset Minuit's list of paramters
293 0 : gMinuit->SetPrintLevel(-1) ; // No Printout
294 0 : gMinuit->SetFCN(AliPHOSClusterizerv1::UnfoldingChiSquare) ;
295 : // To set the address of the minimization function
296 :
297 0 : TList * toMinuit = new TList();
298 0 : toMinuit->AddAt(emcRP,0) ;
299 0 : toMinuit->AddAt(fDigitsArr,1) ;
300 0 : toMinuit->AddAt(fGeom,2) ;
301 :
302 0 : gMinuit->SetObjectFit(toMinuit) ; // To tranfer pointer to UnfoldingChiSquare
303 :
304 : // filling initial values for fit parameters
305 : AliPHOSDigit * digit ;
306 :
307 0 : Int_t ierflg = 0;
308 : Int_t index = 0 ;
309 0 : Int_t nDigits = (Int_t) nPar / 3 ;
310 :
311 : Int_t iDigit ;
312 :
313 0 : for(iDigit = 0; iDigit < nDigits; iDigit++){
314 0 : digit = maxAt[iDigit];
315 :
316 0 : Int_t relid[4] ;
317 0 : Float_t x = 0.;
318 0 : Float_t z = 0.;
319 0 : fGeom->AbsToRelNumbering(digit->GetId(), relid) ;
320 0 : fGeom->RelPosInModule(relid, x, z) ;
321 :
322 0 : Float_t energy = maxAtEnergy[iDigit] ;
323 :
324 0 : gMinuit->mnparm(index, "x", x, 0.1, 0, 0, ierflg) ;
325 0 : index++ ;
326 0 : if(ierflg != 0){
327 0 : Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : x = %f\n", x ) ;
328 0 : return kFALSE;
329 : }
330 0 : gMinuit->mnparm(index, "z", z, 0.1, 0, 0, ierflg) ;
331 0 : index++ ;
332 0 : if(ierflg != 0){
333 0 : Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : z =%f\n", z ) ;
334 0 : return kFALSE;
335 : }
336 0 : gMinuit->mnparm(index, "Energy", energy , 0.05*energy, 0., 4.*energy, ierflg) ;
337 0 : index++ ;
338 0 : if(ierflg != 0){
339 0 : Warning("FindFit", "PHOS Unfolding unable to set initial value for fit procedure : energy = %f\n", energy ) ;
340 0 : return kFALSE;
341 : }
342 0 : }
343 :
344 0 : Double_t p0 = 0.1 ; // "Tolerance" Evaluation stops when EDM = 0.0001*p0 ; The number of function call slightly
345 : // depends on it.
346 0 : Double_t p1 = 1.0 ;
347 0 : Double_t p2 = 0.0 ;
348 :
349 0 : gMinuit->mnexcm("SET STR", &p2, 0, ierflg) ; // force TMinuit to reduce function calls
350 0 : gMinuit->mnexcm("SET GRA", &p1, 1, ierflg) ; // force TMinuit to use my gradient
351 0 : gMinuit->SetMaxIterations(5);
352 0 : gMinuit->mnexcm("SET NOW", &p2 , 0, ierflg) ; // No Warnings
353 :
354 0 : gMinuit->mnexcm("MIGRAD", &p0, 0, ierflg) ; // minimize
355 :
356 0 : if(ierflg == 4){ // Minimum not found
357 0 : Warning("FindFit", "PHOS Unfolding fit not converged, cluster abandoned\n" );
358 0 : return kFALSE ;
359 : }
360 0 : for(index = 0; index < nPar; index++){
361 0 : Double_t err ;
362 0 : Double_t val ;
363 0 : gMinuit->GetParameter(index, val, err) ; // Returns value and error of parameter index
364 0 : fitparameters[index] = val ;
365 0 : }
366 :
367 0 : delete toMinuit ;
368 0 : return kTRUE;
369 :
370 0 : }
371 :
372 :
373 : //____________________________________________________________________________
374 : void AliPHOSClusterizerv1::Init()
375 : {
376 : // Make all memory allocations which can not be done in default constructor.
377 : // Attach the Clusterizer task to the list of PHOS tasks
378 :
379 4 : fEmcCrystals = fGeom->GetNModules() * fGeom->GetNCristalsInModule() ;
380 :
381 2 : if(!gMinuit)
382 4 : gMinuit = new TMinuit(100);
383 :
384 2 : if (!fgCalibData)
385 4 : fgCalibData = new AliPHOSCalibData(-1); //use AliCDBManager's run number
386 2 : if (fgCalibData->GetCalibDataEmc() == 0)
387 0 : AliFatal("Calibration parameters for PHOS EMC not found. Stop reconstruction.\n");
388 2 : if (fgCalibData->GetCalibDataCpv() == 0)
389 0 : AliFatal("Calibration parameters for PHOS CPV not found. Stop reconstruction.\n");
390 :
391 2 : }
392 :
393 : //____________________________________________________________________________
394 : void AliPHOSClusterizerv1::InitParameters()
395 : {
396 :
397 16 : fNumberOfCpvClusters = 0 ;
398 8 : fNumberOfEmcClusters = 0 ;
399 :
400 8 : const AliPHOSRecoParam* recoParam = AliPHOSReconstructor::GetRecoParam();
401 8 : if(!recoParam) AliFatal("Reconstruction parameters are not set!");
402 :
403 8 : recoParam->Print();
404 :
405 8 : fEmcClusteringThreshold = recoParam->GetEMCClusteringThreshold();
406 8 : fCpvClusteringThreshold = recoParam->GetCPVClusteringThreshold();
407 :
408 8 : fEmcLocMaxCut = recoParam->GetEMCLocalMaxCut();
409 8 : fCpvLocMaxCut = recoParam->GetCPVLocalMaxCut();
410 :
411 8 : fW0 = recoParam->GetEMCLogWeight();
412 8 : fW0CPV = recoParam->GetCPVLogWeight();
413 :
414 8 : fTimeGateLowAmp = recoParam->GetTimeGateAmpThresh() ;
415 8 : fTimeGateLow = recoParam->GetTimeGateLow() ;
416 8 : fTimeGateHigh = recoParam->GetTimeGateHigh() ;
417 :
418 8 : fEcoreRadius = recoParam->GetEMCEcoreRadius();
419 :
420 8 : fToUnfold = recoParam->EMCToUnfold() ;
421 8 : fToUnfoldCPV = recoParam->CPVToUnfold() ;
422 :
423 8 : fWrite = kTRUE ;
424 8 : }
425 :
426 : //____________________________________________________________________________
427 : Int_t AliPHOSClusterizerv1::AreNeighbours(AliPHOSDigit * d1, AliPHOSDigit * d2)const
428 : {
429 : // Gives the neighbourness of two digits = 0 are not neighbour but continue searching
430 : // = 1 are neighbour
431 : // = 2 are not neighbour but do not continue searching
432 : // =-1 are not neighbour, continue searching, but do not look before d2 next time
433 : // neighbours are defined as digits having at least a common vertex
434 : // The order of d1 and d2 is important: first (d1) should be a digit already in a cluster
435 : // which is compared to a digit (d2) not yet in a cluster
436 :
437 2150 : Int_t relid1[4] ;
438 1075 : fGeom->AbsToRelNumbering(d1->GetId(), relid1) ;
439 :
440 1075 : Int_t relid2[4] ;
441 1075 : fGeom->AbsToRelNumbering(d2->GetId(), relid2) ;
442 :
443 1963 : if ( (relid1[0] == relid2[0]) && (relid1[1]==relid2[1]) ) { // inside the same PHOS module
444 888 : Int_t rowdiff = TMath::Abs( relid1[2] - relid2[2] ) ;
445 888 : Int_t coldiff = TMath::Abs( relid1[3] - relid2[3] ) ;
446 :
447 888 : if (( coldiff <= 1 ) && ( rowdiff <= 1 )){ //At least common vertex
448 : // if (( relid1[2]==relid2[2] && coldiff <= 1 ) || ( relid1[3]==relid2[3] && rowdiff <= 1 )){ //common side
449 332 : if((relid1[1] != 0) || CheckTimeGate(d1->GetTime(),d1->GetEnergy(),d2->GetTime(),d2->GetEnergy()))
450 166 : return 1 ;
451 : }
452 : else {
453 1104 : if((relid2[2] > relid1[2]) && (relid2[3] > relid1[3]+1))
454 119 : return 2; // Difference in row numbers is too large to look further
455 : }
456 603 : return 0 ;
457 :
458 : }
459 : else {
460 374 : if(relid1[0] > relid2[0] && relid1[1]==relid2[1] ) //we switched to the next module
461 187 : return -1 ;
462 0 : if(relid1[1] < relid2[1]) //we switched from EMC(0) to CPV(-1)
463 0 : return -1 ;
464 :
465 0 : return 2 ;
466 :
467 : }
468 :
469 : return 0 ;
470 1075 : }
471 : //____________________________________________________________________________
472 : Bool_t AliPHOSClusterizerv1::CheckTimeGate(Float_t t1, Float_t amp1, Float_t t2, Float_t amp2)const{
473 : //Check if two cells have reasonable time difference
474 : //Note that at low amplitude time is defined up to 1 tick == 100 ns.
475 478 : if(amp1<fTimeGateLowAmp || amp2<fTimeGateLowAmp){
476 88 : return (TMath::Abs(t1 - t2 ) < fTimeGateLow) ;
477 : }
478 : else{ //Time should be measured with good accuracy
479 78 : return (TMath::Abs(t1 - t2 ) < fTimeGateHigh) ;
480 : }
481 :
482 166 : }
483 : //____________________________________________________________________________
484 : Bool_t AliPHOSClusterizerv1::IsInEmc(AliPHOSDigit * digit) const
485 : {
486 : // Tells if (true) or not (false) the digit is in a PHOS-EMC module
487 :
488 : Bool_t rv = kFALSE ;
489 :
490 284 : Int_t nEMC = fGeom->GetNModules()*fGeom->GetNPhi()*fGeom->GetNZ();
491 :
492 284 : if(digit->GetId() <= nEMC ) rv = kTRUE;
493 :
494 142 : return rv ;
495 : }
496 :
497 : //____________________________________________________________________________
498 : Bool_t AliPHOSClusterizerv1::IsInCpv(AliPHOSDigit * digit) const
499 : {
500 : // Tells if (true) or not (false) the digit is in a PHOS-CPV module
501 :
502 : Bool_t rv = kFALSE ;
503 :
504 244 : Int_t nEMC = fGeom->GetNModules()*fGeom->GetNPhi()*fGeom->GetNZ();
505 :
506 122 : if(digit->GetId() > nEMC ) rv = kTRUE;
507 :
508 122 : return rv ;
509 : }
510 :
511 : //____________________________________________________________________________
512 : void AliPHOSClusterizerv1::WriteRecPoints()
513 : {
514 :
515 : // Creates new branches with given title
516 : // fills and writes into TreeR.
517 :
518 : Int_t index ;
519 : //Evaluate position, dispersion and other RecPoint properties..
520 16 : Int_t nEmc = fEMCRecPoints->GetEntriesFast();
521 8 : Float_t emcMinE= AliPHOSReconstructor::GetRecoParam()->GetEMCMinE(); //Minimal digit energy
522 8 : TVector3 fakeVtx(0.,0.,0.) ;
523 36 : for(index = 0; index < nEmc; index++){
524 : AliPHOSEmcRecPoint * rp =
525 20 : static_cast<AliPHOSEmcRecPoint *>( fEMCRecPoints->At(index) );
526 10 : rp->Purify(emcMinE,fDigitsArr) ;
527 10 : if(rp->GetMultiplicity()==0){
528 0 : fEMCRecPoints->RemoveAt(index) ;
529 0 : delete rp ;
530 0 : continue;
531 : }
532 :
533 : // No vertex is available now, calculate corrections in PID
534 10 : rp->EvalAll(fDigitsArr) ;
535 10 : rp->EvalCoreEnergy(fW0,fEcoreRadius,fDigitsArr) ;
536 10 : rp->EvalAll(fW0,fakeVtx,fDigitsArr) ;
537 10 : rp->EvalLocal2TrackingCSTransform();
538 10 : }
539 8 : fEMCRecPoints->Compress() ;
540 8 : fEMCRecPoints->Sort() ;
541 : // fEMCRecPoints->Expand(fEMCRecPoints->GetEntriesFast()) ;
542 54 : for(index = 0; index < fEMCRecPoints->GetEntries(); index++){
543 20 : static_cast<AliPHOSEmcRecPoint *>( fEMCRecPoints->At(index) )->SetIndexInList(index) ;
544 : }
545 :
546 : //For each rec.point set the distance to the nearest bad crystal (BVP)
547 8 : SetDistancesToBadChannels();
548 :
549 : //Now the same for CPV
550 16 : Float_t cpvMinE= AliPHOSReconstructor::GetRecoParam()->GetCPVMinE(); //Minimal digit energy
551 24 : for(index = 0; index < fCPVRecPoints->GetEntries(); index++){
552 0 : AliPHOSCpvRecPoint * rp = static_cast<AliPHOSCpvRecPoint *>( fCPVRecPoints->At(index) );
553 0 : rp->Purify(cpvMinE,fDigitsArr) ;
554 0 : if(rp->GetMultiplicity()==0){
555 0 : fCPVRecPoints->RemoveAt(index) ;
556 0 : delete rp ;
557 0 : continue;
558 : }
559 :
560 0 : rp->EvalAll(fDigitsArr) ;
561 0 : rp->EvalAll(fW0CPV,fakeVtx,fDigitsArr) ;
562 0 : rp->EvalLocal2TrackingCSTransform();
563 0 : }
564 8 : fCPVRecPoints->Sort() ;
565 :
566 32 : for(index = 0; index < fCPVRecPoints->GetEntries(); index++)
567 8 : static_cast<AliPHOSCpvRecPoint *>( fCPVRecPoints->At(index) )->SetIndexInList(index) ;
568 :
569 16 : fCPVRecPoints->Expand(fCPVRecPoints->GetEntriesFast()) ;
570 :
571 8 : if(fWrite){ //We write TreeR
572 8 : fTreeR->Fill();
573 : }
574 8 : }
575 :
576 : //____________________________________________________________________________
577 : void AliPHOSClusterizerv1::MakeClusters()
578 : {
579 : // Steering method to construct the clusters stored in a list of Reconstructed Points
580 : // A cluster is defined as a list of neighbour digits
581 :
582 16 : fNumberOfCpvClusters = 0 ;
583 8 : fNumberOfEmcClusters = 0 ;
584 :
585 : //Mark all digits as unused yet
586 : const Int_t maxNDigits = 3584; // There is no clusters larger than PHOS module ;)
587 8 : Int_t nDigits=fDigitsArr->GetEntriesFast() ;
588 :
589 480 : for(Int_t i=0; i<nDigits; i++){
590 232 : fDigitsUsed[i]=0 ;
591 : }
592 : Int_t iFirst = 0 ; //first index of digit which potentially can be a part of cluster
593 : //e.g. first digit in this module, first CPV digit etc.
594 : AliPHOSDigit * digit ;
595 8 : TArrayI clusterdigitslist(maxNDigits) ;
596 : AliPHOSRecPoint * clu = 0 ;
597 488 : for(Int_t i=0; i<nDigits; i++){
598 232 : if(fDigitsUsed[i])
599 : continue ;
600 :
601 264 : digit=static_cast<AliPHOSDigit*>(fDigitsArr->At(i)) ;
602 :
603 : clu=0 ;
604 :
605 : Int_t index ;
606 :
607 : //is this digit so energetic that start cluster?
608 660 : AliDebug(2,Form("Digit %d, energy=%f, ID=%d",i,digit->GetEnergy(),digit->GetId()));
609 528 : if (( IsInEmc(digit) && Calibrate(digit->GetEnergy(),digit->GetId()) > fEmcClusteringThreshold ) ||
610 244 : ( IsInCpv(digit) && Calibrate(digit->GetEnergy(),digit->GetId()) > fCpvClusteringThreshold ) ) {
611 : Int_t iDigitInCluster = 0 ;
612 20 : if ( IsInEmc(digit) ) {
613 : // start a new EMC RecPoint
614 20 : if(fNumberOfEmcClusters >= fEMCRecPoints->GetSize())
615 0 : fEMCRecPoints->Expand(2*fNumberOfEmcClusters+1) ;
616 :
617 30 : fEMCRecPoints->AddAt(new AliPHOSEmcRecPoint(""), fNumberOfEmcClusters) ;
618 20 : clu = static_cast<AliPHOSEmcRecPoint *>( fEMCRecPoints->At(fNumberOfEmcClusters) ) ;
619 10 : fNumberOfEmcClusters++ ;
620 30 : clu->AddDigit(*digit, Calibrate(digit->GetEnergy(),digit->GetId()),CalibrateT(digit->GetTime(),digit->GetId(),digit->IsLG())) ;
621 20 : clusterdigitslist[iDigitInCluster] = digit->GetIndexInList() ;
622 : iDigitInCluster++ ;
623 10 : fDigitsUsed[i]=kTRUE ;
624 10 : } else {
625 : // start a new CPV cluster
626 0 : if(fNumberOfCpvClusters >= fCPVRecPoints->GetSize())
627 0 : fCPVRecPoints->Expand(2*fNumberOfCpvClusters+1);
628 :
629 0 : fCPVRecPoints->AddAt(new AliPHOSCpvRecPoint(""), fNumberOfCpvClusters) ;
630 0 : clu = static_cast<AliPHOSCpvRecPoint *>( fCPVRecPoints->At(fNumberOfCpvClusters) ) ;
631 0 : fNumberOfCpvClusters++ ;
632 0 : clu->AddDigit(*digit, Calibrate(digit->GetEnergy(),digit->GetId()),0.) ; // no timing information in CPV
633 0 : clusterdigitslist[iDigitInCluster] = digit->GetIndexInList() ;
634 : iDigitInCluster++ ;
635 0 : fDigitsUsed[i]=kTRUE ;
636 : } // else
637 :
638 : //Now scan remaining digits in list to find neigbours of our seed
639 :
640 : AliPHOSDigit * digitN ;
641 : index = 0 ;
642 196 : while (index < iDigitInCluster){ // scan over digits already in cluster
643 528 : digit = static_cast<AliPHOSDigit*>( fDigitsArr->At(clusterdigitslist[index]) ) ;
644 176 : index++ ;
645 8089 : for(Int_t j=iFirst; j<nDigits; j++){
646 3959 : if (iDigitInCluster >= maxNDigits) {
647 0 : AliError(Form("The number of digits in cluster is more than %d, skip the rest of event",
648 : maxNDigits));
649 0 : return;
650 : }
651 3959 : if(fDigitsUsed[j])
652 : continue ; //look through remaining digits
653 2150 : digitN = static_cast<AliPHOSDigit*>( fDigitsArr->At(j) ) ;
654 1075 : Int_t ineb = AreNeighbours(digit, digitN); // call (digit,digitN) in THAT oder !!!!!
655 1262 : switch (ineb ) {
656 : case -1: //too early (e.g. previous module), do not look before j at subsequent passes
657 : iFirst=j ;
658 187 : break ;
659 : case 0 : // not a neighbour
660 : break ;
661 : case 1 : // are neighbours
662 498 : clu->AddDigit(*digitN, Calibrate(digitN->GetEnergy(),digitN->GetId()),CalibrateT(digitN->GetTime(),digitN->GetId(),digit->IsLG())) ;
663 332 : clusterdigitslist[iDigitInCluster] = j ;
664 166 : iDigitInCluster++ ;
665 166 : fDigitsUsed[j]=kTRUE ;
666 166 : break ;
667 : case 2 : // too far from each other
668 119 : goto endOfLoop;
669 : } // switch
670 :
671 956 : }
672 :
673 : endOfLoop: ; //scanned all possible neighbours for this digit
674 :
675 : } // loop over cluster
676 10 : } // energy theshold
677 132 : }
678 :
679 16 : }
680 :
681 : //____________________________________________________________________________
682 : void AliPHOSClusterizerv1::MakeUnfolding()
683 : {
684 : // Unfolds clusters using the shape of an ElectroMagnetic shower
685 : // Performs unfolding of all EMC/CPV clusters
686 :
687 24 : if(fToUnfold && (fNumberOfEmcClusters > 0)){ // Unfold first EMC clusters
688 :
689 8 : Int_t nModulesToUnfold = fGeom->GetNModules() ;
690 :
691 8 : Int_t numberofNotUnfolded = fNumberOfEmcClusters ;
692 : Int_t index ;
693 36 : for(index = 0 ; index < numberofNotUnfolded ; index++){
694 :
695 10 : AliPHOSEmcRecPoint * emcRecPoint = static_cast<AliPHOSEmcRecPoint *>( fEMCRecPoints->At(index) ) ;
696 10 : if(emcRecPoint->GetPHOSMod()> nModulesToUnfold)
697 0 : break ;
698 :
699 10 : Int_t nMultipl = emcRecPoint->GetMultiplicity() ;
700 10 : AliPHOSDigit ** maxAt = new AliPHOSDigit*[nMultipl] ;
701 10 : Float_t * maxAtEnergy = new Float_t[nMultipl] ;
702 10 : Int_t nMax = emcRecPoint->GetNumberOfLocalMax(maxAt, maxAtEnergy,fEmcLocMaxCut,fDigitsArr) ;
703 :
704 10 : if( nMax > 1 ) { // if cluster is very flat (no pronounced maximum) then nMax = 0
705 0 : UnfoldCluster(emcRecPoint, nMax, maxAt, maxAtEnergy) ;
706 :
707 0 : fEMCRecPoints->Remove(emcRecPoint);
708 0 : fEMCRecPoints->Compress() ;
709 0 : index-- ;
710 0 : fNumberOfEmcClusters -- ;
711 0 : numberofNotUnfolded-- ;
712 0 : }
713 : else{
714 10 : emcRecPoint->SetNExMax(1) ; //Only one local maximum
715 : }
716 :
717 20 : delete[] maxAt ;
718 20 : delete[] maxAtEnergy ;
719 10 : }
720 8 : }
721 : // Unfolding of EMC clusters finished
722 :
723 :
724 : // Unfold now CPV clusters
725 16 : if(fToUnfoldCPV && (fNumberOfCpvClusters > 0)){
726 :
727 0 : Int_t nModulesToUnfold = fGeom->GetNModules() ;
728 :
729 0 : Int_t numberofCpvNotUnfolded = fNumberOfCpvClusters ;
730 : Int_t index ;
731 0 : for(index = 0 ; index < numberofCpvNotUnfolded ; index++){
732 :
733 0 : AliPHOSRecPoint * recPoint = static_cast<AliPHOSRecPoint *>( fCPVRecPoints->At(index) ) ;
734 :
735 0 : if(recPoint->GetPHOSMod()> nModulesToUnfold)
736 0 : break ;
737 :
738 0 : AliPHOSEmcRecPoint * emcRecPoint = static_cast<AliPHOSEmcRecPoint*>(recPoint) ;
739 :
740 0 : Int_t nMultipl = emcRecPoint->GetMultiplicity() ;
741 0 : AliPHOSDigit ** maxAt = new AliPHOSDigit*[nMultipl] ;
742 0 : Float_t * maxAtEnergy = new Float_t[nMultipl] ;
743 0 : Int_t nMax = emcRecPoint->GetNumberOfLocalMax(maxAt, maxAtEnergy,fCpvLocMaxCut,fDigitsArr) ;
744 :
745 : //Number of points to fit should be larger than number of parameters
746 0 : if( nMax > 1 && emcRecPoint->GetMultiplicity()>3*nMax ) { // if cluster is very flat (no pronounced maximum) then nMax = 0
747 0 : UnfoldCluster(emcRecPoint, nMax, maxAt, maxAtEnergy) ;
748 0 : fCPVRecPoints->Remove(emcRecPoint);
749 0 : fCPVRecPoints->Compress() ;
750 0 : index-- ;
751 0 : numberofCpvNotUnfolded-- ;
752 0 : fNumberOfCpvClusters-- ;
753 0 : }
754 :
755 0 : delete[] maxAt ;
756 0 : delete[] maxAtEnergy ;
757 0 : }
758 0 : }
759 : //Unfolding of Cpv clusters finished
760 :
761 8 : }
762 :
763 : //____________________________________________________________________________
764 : Double_t AliPHOSClusterizerv1::ShowerShape(Double_t x, Double_t z)
765 : {
766 : // Shape of the shower (see PHOS TDR)
767 : // If you change this function, change also the gradient evaluation in ChiSquare()
768 :
769 : //for the moment we neglect dependence on the incident angle.
770 :
771 0 : Double_t r2 = x*x + z*z ;
772 0 : Double_t r4 = r2*r2 ;
773 0 : Double_t r295 = TMath::Power(r2, 2.95/2.) ;
774 0 : Double_t shape = TMath::Exp( -r4 * (1. / (2.32 + 0.26 * r4) + 0.0316 / (1 + 0.0652 * r295) ) ) ;
775 0 : return shape ;
776 : }
777 :
778 : //____________________________________________________________________________
779 : void AliPHOSClusterizerv1::UnfoldCluster(AliPHOSEmcRecPoint * iniEmc,
780 : Int_t nMax,
781 : AliPHOSDigit ** maxAt,
782 : Float_t * maxAtEnergy)
783 : {
784 : // Performs the unfolding of a cluster with nMax overlapping showers
785 :
786 0 : Int_t nPar = 3 * nMax ;
787 0 : Float_t * fitparameters = new Float_t[nPar] ;
788 :
789 0 : Bool_t rv = FindFit(iniEmc, maxAt, maxAtEnergy, nPar, fitparameters) ;
790 :
791 0 : if( !rv ) {
792 : // Fit failed, return and remove cluster
793 0 : iniEmc->SetNExMax(-1) ;
794 0 : delete[] fitparameters ;
795 0 : return ;
796 : }
797 :
798 : // create ufolded rec points and fill them with new energy lists
799 : // First calculate energy deposited in each sell in accordance with fit (without fluctuations): efit[]
800 : // and later correct this number in acordance with actual energy deposition
801 :
802 0 : Int_t nDigits = iniEmc->GetMultiplicity() ;
803 0 : Float_t * efit = new Float_t[nDigits] ;
804 0 : Float_t xDigit=0.,zDigit=0. ;
805 : Float_t xpar=0.,zpar=0.,epar=0. ;
806 0 : Int_t relid[4] ;
807 : AliPHOSDigit * digit = 0 ;
808 0 : Int_t * emcDigits = iniEmc->GetDigitsList() ;
809 :
810 0 : TVector3 vIncid ;
811 :
812 : Int_t iparam ;
813 : Int_t iDigit ;
814 0 : for(iDigit = 0 ; iDigit < nDigits ; iDigit ++){
815 0 : digit = static_cast<AliPHOSDigit*>( fDigitsArr->At(emcDigits[iDigit] ) ) ;
816 0 : fGeom->AbsToRelNumbering(digit->GetId(), relid) ;
817 0 : fGeom->RelPosInModule(relid, xDigit, zDigit) ;
818 0 : efit[iDigit] = 0;
819 :
820 : iparam = 0 ;
821 0 : while(iparam < nPar ){
822 0 : xpar = fitparameters[iparam] ;
823 0 : zpar = fitparameters[iparam+1] ;
824 0 : epar = fitparameters[iparam+2] ;
825 0 : iparam += 3 ;
826 : // fGeom->GetIncidentVector(fVtx,relid[0],xpar,zpar,vIncid) ;
827 : // efit[iDigit] += epar * ShowerShape(xDigit - xpar,zDigit - zpar,vIncid) ;
828 0 : efit[iDigit] += epar * ShowerShape(xDigit - xpar,zDigit - zpar) ;
829 : }
830 : }
831 :
832 : // Now create new RecPoints and fill energy lists with efit corrected to fluctuations
833 : // so that energy deposited in each cell is distributed betwin new clusters proportionally
834 : // to its contribution to efit
835 :
836 0 : Float_t * emcEnergies = iniEmc->GetEnergiesList() ;
837 : Float_t ratio ;
838 :
839 : iparam = 0 ;
840 0 : while(iparam < nPar ){
841 0 : xpar = fitparameters[iparam] ;
842 0 : zpar = fitparameters[iparam+1] ;
843 0 : epar = fitparameters[iparam+2] ;
844 0 : iparam += 3 ;
845 : // fGeom->GetIncidentVector(fVtx,iniEmc->GetPHOSMod(),xpar,zpar,vIncid) ;
846 :
847 : AliPHOSEmcRecPoint * emcRP = 0 ;
848 :
849 0 : if(iniEmc->IsEmc()){ //create new entries in fEMCRecPoints...
850 :
851 0 : if(fNumberOfEmcClusters >= fEMCRecPoints->GetSize())
852 0 : fEMCRecPoints->Expand(2*fNumberOfEmcClusters) ;
853 :
854 0 : (*fEMCRecPoints)[fNumberOfEmcClusters] = new AliPHOSEmcRecPoint("") ;
855 0 : emcRP = static_cast<AliPHOSEmcRecPoint *>( fEMCRecPoints->At(fNumberOfEmcClusters) ) ;
856 0 : fNumberOfEmcClusters++ ;
857 0 : emcRP->SetNExMax((Int_t)nPar/3) ;
858 0 : }
859 : else{//create new entries in fCPVRecPoints
860 0 : if(fNumberOfCpvClusters >= fCPVRecPoints->GetSize())
861 0 : fCPVRecPoints->Expand(2*fNumberOfCpvClusters) ;
862 :
863 0 : (*fCPVRecPoints)[fNumberOfCpvClusters] = new AliPHOSCpvRecPoint("") ;
864 0 : emcRP = static_cast<AliPHOSEmcRecPoint *>( fCPVRecPoints->At(fNumberOfCpvClusters) ) ;
865 0 : fNumberOfCpvClusters++ ;
866 : }
867 :
868 : Float_t eDigit ;
869 0 : for(iDigit = 0 ; iDigit < nDigits ; iDigit ++){
870 0 : digit = static_cast<AliPHOSDigit*>( fDigitsArr->At( emcDigits[iDigit] ) ) ;
871 0 : fGeom->AbsToRelNumbering(digit->GetId(), relid) ;
872 0 : fGeom->RelPosInModule(relid, xDigit, zDigit) ;
873 0 : if(efit[iDigit]>0){
874 : // ratio = epar * ShowerShape(xDigit - xpar,zDigit - zpar,vIncid) / efit[iDigit] ;
875 0 : ratio = epar * ShowerShape(xDigit - xpar,zDigit - zpar) / efit[iDigit] ;
876 0 : eDigit = emcEnergies[iDigit] * ratio ;
877 0 : emcRP->AddDigit( *digit, eDigit,CalibrateT(digit->GetTime(),digit->GetId(),digit->IsLG()) ) ;
878 : }
879 : }
880 : }
881 :
882 0 : delete[] fitparameters ;
883 0 : delete[] efit ;
884 :
885 0 : }
886 :
887 : //_____________________________________________________________________________
888 : void AliPHOSClusterizerv1::UnfoldingChiSquare(Int_t & nPar, Double_t * Grad, Double_t & fret, Double_t * x, Int_t iflag)
889 : {
890 : // Calculates the Chi square for the cluster unfolding minimization
891 : // Number of parameters, Gradient, Chi squared, parameters, what to do
892 :
893 0 : TList * toMinuit = static_cast<TList*>( gMinuit->GetObjectFit() ) ;
894 :
895 0 : AliPHOSEmcRecPoint * emcRP = static_cast<AliPHOSEmcRecPoint*>( toMinuit->At(0) ) ;
896 0 : TClonesArray * digits = static_cast<TClonesArray*>( toMinuit->At(1) ) ;
897 : // A bit buggy way to get an access to the geometry
898 : // To be revised!
899 0 : AliPHOSGeometry *geom = static_cast<AliPHOSGeometry *>(toMinuit->At(2));
900 :
901 : // TVector3 * vtx = static_cast<TVector3*>(toMinuit->At(3)) ; //Vertex position
902 :
903 : // AliPHOSEmcRecPoint * emcRP = static_cast<AliPHOSEmcRecPoint *>( gMinuit->GetObjectFit() ) ; // EmcRecPoint to fit
904 :
905 0 : Int_t * emcDigits = emcRP->GetDigitsList() ;
906 :
907 0 : Int_t nOdigits = emcRP->GetDigitsMultiplicity() ;
908 :
909 0 : Float_t * emcEnergies = emcRP->GetEnergiesList() ;
910 :
911 : // TVector3 vInc ;
912 0 : fret = 0. ;
913 : Int_t iparam ;
914 :
915 0 : if(iflag == 2)
916 0 : for(iparam = 0 ; iparam < nPar ; iparam++)
917 0 : Grad[iparam] = 0 ; // Will evaluate gradient
918 :
919 : Double_t efit ;
920 :
921 : AliPHOSDigit * digit ;
922 : Int_t iDigit ;
923 :
924 0 : for( iDigit = 0 ; iDigit < nOdigits ; iDigit++) {
925 :
926 0 : digit = static_cast<AliPHOSDigit*>( digits->At( emcDigits[iDigit] ) );
927 :
928 0 : Int_t relid[4] ;
929 0 : Float_t xDigit ;
930 0 : Float_t zDigit ;
931 :
932 0 : geom->AbsToRelNumbering(digit->GetId(), relid) ;
933 :
934 0 : geom->RelPosInModule(relid, xDigit, zDigit) ;
935 :
936 0 : if(iflag == 2){ // calculate gradient
937 : Int_t iParam = 0 ;
938 : efit = 0 ;
939 0 : while(iParam < nPar ){
940 0 : Double_t dx = (xDigit - x[iParam]) ;
941 0 : iParam++ ;
942 0 : Double_t dz = (zDigit - x[iParam]) ;
943 0 : iParam++ ;
944 : // fGeom->GetIncidentVector(*vtx,emcRP->GetPHOSMod(),x[iParam-2],x[iParam-1],vInc) ;
945 : // efit += x[iParam] * ShowerShape(dx,dz,vInc) ;
946 0 : efit += x[iParam] * ShowerShape(dx,dz) ;
947 0 : iParam++ ;
948 : }
949 0 : Double_t sum = 2. * (efit - emcEnergies[iDigit]) / emcEnergies[iDigit] ; // Here we assume, that sigma = sqrt(E)
950 : iParam = 0 ;
951 0 : while(iParam < nPar ){
952 0 : Double_t xpar = x[iParam] ;
953 0 : Double_t zpar = x[iParam+1] ;
954 0 : Double_t epar = x[iParam+2] ;
955 : // fGeom->GetIncidentVector(*vtx,emcRP->GetPHOSMod(),xpar,zpar,vInc) ;
956 0 : Double_t dr = TMath::Sqrt( (xDigit - xpar) * (xDigit - xpar) + (zDigit - zpar) * (zDigit - zpar) );
957 : // Double_t shape = sum * ShowerShape(xDigit - xpar,zDigit - zpar,vInc) ;
958 0 : Double_t shape = sum * ShowerShape(xDigit - xpar,zDigit - zpar) ;
959 : //DP: No incident angle dependence in gradient yet!!!!!!
960 0 : Double_t r4 = dr*dr*dr*dr ;
961 0 : Double_t r295 = TMath::Power(dr,2.95) ;
962 0 : Double_t deriv =-4. * dr*dr * ( 2.32 / ( (2.32 + 0.26 * r4) * (2.32 + 0.26 * r4) ) +
963 0 : 0.0316 * (1. + 0.0171 * r295) / ( ( 1. + 0.0652 * r295) * (1. + 0.0652 * r295) ) ) ;
964 :
965 0 : Grad[iParam] += epar * shape * deriv * (xpar - xDigit) ; // Derivative over x
966 : iParam++ ;
967 0 : Grad[iParam] += epar * shape * deriv * (zpar - zDigit) ; // Derivative over z
968 0 : iParam++ ;
969 0 : Grad[iParam] += shape ; // Derivative over energy
970 0 : iParam++ ;
971 : }
972 0 : }
973 : efit = 0;
974 : iparam = 0 ;
975 :
976 0 : while(iparam < nPar ){
977 0 : Double_t xpar = x[iparam] ;
978 0 : Double_t zpar = x[iparam+1] ;
979 0 : Double_t epar = x[iparam+2] ;
980 0 : iparam += 3 ;
981 : // fGeom->GetIncidentVector(*vtx,emcRP->GetPHOSMod(),xpar,zpar,vInc) ;
982 : // efit += epar * ShowerShape(xDigit - xpar,zDigit - zpar,vInc) ;
983 0 : efit += epar * ShowerShape(xDigit - xpar,zDigit - zpar) ;
984 : }
985 :
986 0 : fret += (efit-emcEnergies[iDigit])*(efit-emcEnergies[iDigit])/emcEnergies[iDigit] ;
987 : // Here we assume, that sigma = sqrt(E)
988 0 : }
989 :
990 0 : }
991 :
992 : //____________________________________________________________________________
993 : void AliPHOSClusterizerv1::Print(const Option_t *)const
994 : {
995 : // Print clusterizer parameters
996 :
997 0 : TString message ;
998 0 : TString taskName(GetName()) ;
999 0 : taskName.ReplaceAll(Version(), "") ;
1000 :
1001 0 : if( strcmp(GetName(), "") !=0 ) {
1002 : // Print parameters
1003 0 : message = "\n--------------- %s %s -----------\n" ;
1004 0 : message += "Clusterizing digits from the file: %s\n" ;
1005 0 : message += " Branch: %s\n" ;
1006 0 : message += " EMC Clustering threshold = %f\n" ;
1007 0 : message += " EMC Local Maximum cut = %f\n" ;
1008 0 : message += " EMC Logarothmic weight = %f\n" ;
1009 0 : message += " CPV Clustering threshold = %f\n" ;
1010 0 : message += " CPV Local Maximum cut = %f\n" ;
1011 0 : message += " CPV Logarothmic weight = %f\n" ;
1012 0 : if(fToUnfold)
1013 0 : message += " Unfolding on\n" ;
1014 : else
1015 0 : message += " Unfolding off\n" ;
1016 :
1017 0 : message += "------------------------------------------------------------------" ;
1018 : }
1019 : else
1020 0 : message = " AliPHOSClusterizerv1 not initialized " ;
1021 :
1022 0 : AliInfo(Form("%s, %s %s %s %s %f %f %f %f %f %f", message.Data(),
1023 : taskName.Data(),
1024 : GetTitle(),
1025 : taskName.Data(),
1026 : GetName(),
1027 : fEmcClusteringThreshold,
1028 : fEmcLocMaxCut,
1029 : fW0,
1030 : fCpvClusteringThreshold,
1031 : fCpvLocMaxCut,
1032 : fW0CPV )) ;
1033 0 : }
1034 : //____________________________________________________________________________
1035 : void AliPHOSClusterizerv1::PrintRecPoints(Option_t * option)
1036 : {
1037 : // Prints list of RecPoints produced at the current pass of AliPHOSClusterizer
1038 :
1039 0 : AliInfo(Form("\nFound %d EMC RecPoints and %d CPV RecPoints",
1040 : fEMCRecPoints->GetEntriesFast(),
1041 : fCPVRecPoints->GetEntriesFast() )) ;
1042 :
1043 0 : if(strstr(option,"all")) {
1044 0 : printf("\n EMC clusters \n") ;
1045 0 : printf("Index Ene(MeV) Multi Module X Y Z Lambdas_1 Lambda_2 # of prim Primaries list\n") ;
1046 : Int_t index ;
1047 0 : for (index = 0 ; index < fEMCRecPoints->GetEntries() ; index++) {
1048 0 : AliPHOSEmcRecPoint * rp = (AliPHOSEmcRecPoint * )fEMCRecPoints->At(index) ;
1049 0 : TVector3 locpos;
1050 0 : rp->GetLocalPosition(locpos);
1051 0 : Float_t lambda[2];
1052 0 : rp->GetElipsAxis(lambda);
1053 : Int_t * primaries;
1054 0 : Int_t nprimaries;
1055 0 : primaries = rp->GetPrimaries(nprimaries);
1056 0 : printf("\n%6d %8.2f %3d %2d %4.1f %4.1f %4.1f %4f %4f %2d : ",
1057 0 : rp->GetIndexInList(), rp->GetEnergy(), rp->GetMultiplicity(), rp->GetPHOSMod(),
1058 0 : locpos.X(), locpos.Y(), locpos.Z(), lambda[0], lambda[1], nprimaries) ;
1059 :
1060 0 : for (Int_t iprimary=0; iprimary<nprimaries; iprimary++) {
1061 0 : printf("%d ", primaries[iprimary] ) ;
1062 : }
1063 0 : printf("\n") ;
1064 0 : }
1065 :
1066 : //Now plot CPV recPoints
1067 0 : printf("\n CPV clusters \n") ;
1068 0 : printf("Index Ene(MeV) Module X Y Z \n") ;
1069 0 : for (index = 0 ; index < fCPVRecPoints->GetEntries() ; index++) {
1070 0 : AliPHOSCpvRecPoint * rp = (AliPHOSCpvRecPoint * )fCPVRecPoints->At(index) ;
1071 :
1072 0 : TVector3 locpos;
1073 0 : rp->GetLocalPosition(locpos);
1074 :
1075 0 : printf("\n%6d %8.2f %2d %4.1f %4.1f %4.1f \n",
1076 0 : rp->GetIndexInList(), rp->GetEnergy(), rp->GetPHOSMod(),
1077 0 : locpos.X(), locpos.Y(), locpos.Z()) ;
1078 0 : }
1079 0 : }
1080 0 : }
1081 :
1082 :
1083 : //____________________________________________________________________________
1084 : void AliPHOSClusterizerv1::SetDistancesToBadChannels()
1085 : {
1086 : //For each EMC rec. point set the distance to the nearest bad crystal.
1087 : //Author: Boris Polichtchouk
1088 :
1089 16 : if(!fgCalibData->GetNumOfEmcBadChannels()) return;
1090 :
1091 0 : Int_t badIds[8000];
1092 0 : memset(badIds,0,8000*sizeof(Int_t));
1093 0 : fgCalibData->EmcBadChannelIds(badIds);
1094 :
1095 : AliPHOSEmcRecPoint* rp;
1096 :
1097 0 : TMatrixF gmat;
1098 0 : TVector3 gposRecPoint; // global (in ALICE frame) position of rec. point
1099 0 : TVector3 gposBadChannel; // global position of bad crystal
1100 0 : TVector3 dR;
1101 :
1102 : Float_t dist=0.,minDist=0.;
1103 0 : Int_t relid[4]={0,0,0,0} ;
1104 0 : TVector3 lpos ;
1105 0 : for(Int_t iRP=0; iRP<fEMCRecPoints->GetEntries(); iRP++){
1106 0 : rp = (AliPHOSEmcRecPoint*)fEMCRecPoints->At(iRP);
1107 : //evaluate distance to border
1108 0 : relid[0]=rp->GetPHOSMod() ;
1109 : Float_t xcorner=0,zcorner=0.;
1110 0 : Float_t xmin,xmax,zmin,zmax ;
1111 0 : fGeom->GetCrystalsEdges(rp->GetPHOSMod(),xmin, zmin, xmax, zmax) ;
1112 0 : rp->GetLocalPosition(lpos) ;
1113 0 : Float_t minDistX = 2.2+TMath::Min(lpos.X()-xmin,xmax-lpos.X()); //2.2 - crystal size
1114 0 : Float_t minDistZ = 2.2+TMath::Min(lpos.Z()-zmin,zmax-lpos.Z()); //2.2 - crystal size
1115 0 : minDist=TMath::Min(minDistX,minDistZ) ;
1116 0 : Int_t ixmin=32+Int_t(xmin/2.2) ;
1117 0 : for(Int_t iBad=0; iBad<fgCalibData->GetNumOfEmcBadChannels(); iBad++) {
1118 0 : fGeom->AbsToRelNumbering(badIds[iBad],relid) ;
1119 0 : if(relid[0]!=rp->GetPHOSMod()) //We can not evaluate global position directly since
1120 : continue ; //bad channels can be in the module which does not exist in simulations.
1121 0 : if(relid[2]<=ixmin) //non-existing part of mod 4
1122 : continue ;
1123 0 : rp->GetGlobalPosition(gposRecPoint,gmat);
1124 0 : fGeom->RelPosInAlice(badIds[iBad],gposBadChannel);
1125 0 : AliDebug(2,Form("BC position:[%.3f,%.3f,%.3f], RP position:[%.3f,%.3f,%.3f]. E=%.3f\n",
1126 : gposBadChannel.X(),gposBadChannel.Y(),gposBadChannel.Z(),
1127 : gposRecPoint.X(),gposRecPoint.Y(),gposRecPoint.Z(),rp->GetEnergy()));
1128 0 : dR = gposBadChannel-gposRecPoint;
1129 0 : dist = dR.Mag();
1130 0 : if(dist<minDist) minDist = dist;
1131 : }
1132 :
1133 0 : rp->SetDistanceToBadCrystal(minDist);
1134 0 : }
1135 :
1136 8 : }
1137 : //==================================================================================
1138 : Float_t AliPHOSClusterizerv1::Calibrate(Float_t amp, Int_t absId) const{
1139 : // Calibrate EMC digit, i.e. multiply its Amp by a factor read from CDB
1140 :
1141 616 : const AliPHOSGeometry *geom = AliPHOSGeometry::GetInstance() ;
1142 :
1143 : //Determine rel.position of the cell absolute ID
1144 308 : Int_t relId[4];
1145 308 : geom->AbsToRelNumbering(absId,relId);
1146 308 : Int_t module=relId[0];
1147 308 : Int_t row =relId[2];
1148 308 : Int_t column=relId[3];
1149 308 : if(relId[1]){ //CPV
1150 0 : Float_t calibration = fgCalibData->GetADCchannelCpv(module,column,row);
1151 0 : return amp*calibration ;
1152 : }
1153 : else{ //EMC
1154 308 : Float_t calibration = fgCalibData->GetADCchannelEmc(module,column,row);
1155 308 : return amp*calibration ;
1156 : }
1157 308 : }
1158 : //==================================================================================
1159 : Float_t AliPHOSClusterizerv1::CalibrateT(Float_t time, Int_t absId,Bool_t isLG)const{
1160 : // Calibrate time in EMC digit
1161 :
1162 176 : const AliPHOSGeometry *geom = AliPHOSGeometry::GetInstance() ;
1163 :
1164 : //Determine rel.position of the cell absolute ID
1165 176 : Int_t relId[4];
1166 176 : geom->AbsToRelNumbering(absId,relId);
1167 176 : Int_t module=relId[0];
1168 176 : Int_t row =relId[2];
1169 176 : Int_t column=relId[3];
1170 176 : if(relId[1]){ //CPV
1171 0 : return 0. ;
1172 : }
1173 : else{ //EMC
1174 352 : if(isLG)
1175 194 : time += fgCalibData->GetLGTimeShiftEmc(module,column,row);
1176 : else
1177 158 : time += fgCalibData->GetTimeShiftEmc(module,column,row);
1178 176 : return time ;
1179 : }
1180 176 : }
1181 :
|