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