1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////
19 // Class AliCalcluster
20 // Description of a cluster of calorimeter modules.
21 // A 2D (matrix) geometry is assumed in which a cluster center is identified
22 // by two integer indices (i,j), e.g. row and column indicators.
24 // The 1st signal value is the signal of the complete cluster.
25 // This is the signal which is provided as default by invoking GetSignal().
27 // In case clustering/grouping of module signals was performed over several
28 // rings around the center (see e.g. AliCalorimeter::Group), the following
29 // additional information is provided by the various signal values :
31 // The 2nd signal value is the original signal of the central module.
32 // The 3rd signal value is the total signal within the 1st (i.e. 3x3) ring of
33 // modules around the cluster center.
34 // The 4th signal value is the total signal within the 2nd (i.e. 5x5) ring of
35 // modules around the cluster center.
38 // Note : In case the cluster consists of only 1 module, then only the
39 // 1st signal value will be present (for obvious reasons).
41 // Some dispersion info about cluster topology is provided in order
42 // to enable EM or hadronic cluster identification.
44 //--- Author: Nick van Eijndhoven 13-jun-1997 UU-SAP Utrecht
45 //- Modified: NvE $Date$ UU-SAP Utrecht
46 ///////////////////////////////////////////////////////////////////////////
48 #include "AliCalcluster.h"
49 #include "Riostream.h"
51 ClassImp(AliCalcluster) // Class implementation to enable ROOT I/O
53 AliCalcluster::AliCalcluster() : AliSignal()
55 // Default constructor, all data is set to 0
63 SetName("AliCalcluster [sig, sig11, sig33, sig55,...]");
65 ///////////////////////////////////////////////////////////////////////////
66 AliCalcluster::~AliCalcluster()
68 // Destructor to delete dynamically allocated memory
75 ///////////////////////////////////////////////////////////////////////////
76 AliCalcluster::AliCalcluster(AliCalcluster& c) : AliSignal(c)
86 fVetos=new TObjArray();
89 for (Int_t i=1; i<=fNvetos; i++)
91 AliSignal* sx=c.GetVetoSignal(i);
92 fVetos->Add(new AliSignal(*sx));
95 ///////////////////////////////////////////////////////////////////////////
96 AliCalcluster::AliCalcluster(AliCalmodule& m) : AliSignal()
98 // Cluster constructor with module m as center.
99 // Module data is only entered for a module which contains a signal,
100 // has not been used in a cluster yet, and is not declared dead.
103 // It is advised NOT to start a cluster with modules situated at a detector edge.
104 // This feature is automatically checked when using the built-in clustering
105 // of AliCalorimeter.
109 Float_t sig=m.GetClusteredSignal();
111 if (sig>0. && m.GetDeadValue()==0)
117 sig=m.GetSignal(1,1); // Use the gain etc... corrected module signal
122 m.SetClusteredSignal(0.); // mark module as used in cluster
137 SetName("AliCalcluster [sig, sig11, sig33, sig55,...]");
139 ///////////////////////////////////////////////////////////////////////////
140 Int_t AliCalcluster::GetRow()
142 // Provide the row number of the cluster center
145 ///////////////////////////////////////////////////////////////////////////
146 Int_t AliCalcluster::GetColumn()
148 // Provide the column number of the cluster center
151 ///////////////////////////////////////////////////////////////////////////
152 Int_t AliCalcluster::GetNmodules()
154 // Provide the number of modules in the cluster
157 ///////////////////////////////////////////////////////////////////////////
158 Float_t AliCalcluster::GetRowDispersion()
160 // Provide the normalised row dispersion of the cluster.
161 Float_t sig=GetSignal();
171 ///////////////////////////////////////////////////////////////////////////
172 Float_t AliCalcluster::GetColumnDispersion()
174 // Provide the normalised column dispersion of the cluster
175 Float_t sig=GetSignal();
185 ///////////////////////////////////////////////////////////////////////////
186 void AliCalcluster::Start(AliCalmodule& m)
188 // Reset cluster data and start with module m.
189 // A module can only start a cluster when it contains a signal,
190 // has not been used in a cluster yet, and is not declared dead.
193 // It is advised NOT to start a cluster with modules situated at a detector edge.
194 // This feature is automatically checked when using the built-in clustering
195 // of AliCalorimeter.
201 if (m.GetClusteredSignal()>0. && m.GetDeadValue()==0)
207 SetSignal(m.GetSignal(1,1)); // Use the gain etc... corrected module signal
211 m.SetClusteredSignal(0.); // mark module as used in cluster
223 ///////////////////////////////////////////////////////////////////////////
224 void AliCalcluster::Add(AliCalmodule& m)
226 // Add module data to the cluster.
227 // Dead modules are NOT added to the cluster.
228 // According to the distance of the module w.r.t. the cluster center
229 // the various signal values are updated.
233 if (m.GetClusteredSignal()>0. && m.GetDeadValue()==0) // only add unused modules
235 Float_t sigm=m.GetSignal(1,1); // Use the gain etc... corrected module signal
237 Int_t drow=int(fabs(double(GetRow()-m.GetRow()))); // row distance to center
238 Int_t dcol=int(fabs(double(GetColumn()-m.GetColumn()))); // column distance to center
240 // Determine the ring index for this module around the cluster center
242 if (dcol>drow) jring=dcol;
244 Int_t nvalues=GetNvalues();
246 if ((jring+2)<=nvalues) // Module within existing ring(s) ==> Add module signal to the enclosing ring(s)
248 for (Int_t i=(jring+2); i<=nvalues; i++)
253 else // Module outside all existing rings ==> Init. new ring signals with existing enclosed signal(s)
255 for (Int_t j=(nvalues+1); j<=(jring+2); j++)
257 SetSignal(GetSignal(j-1),j);
259 // Add current module signal to the signal value for the corresponding ring
260 AddSignal(sigm,(jring+2));
263 // Update total cluster signal
267 fRowdisp+=sigm*float(drow*drow);
268 fColdisp+=sigm*float(dcol*dcol);
269 m.SetClusteredSignal(0.); // mark module as used in cluster
274 cout << " *AliCalcluster::Add* No action. Cluster should be started first."
278 ///////////////////////////////////////////////////////////////////////////
279 void AliCalcluster::AddVetoSignal(AliSignal& s,Int_t extr)
281 // Associate an (extrapolated) AliSignal as veto to the cluster.
282 // By default a straight line extrapolation is performed which extrapolates
283 // the signal position until the length of its position vector matches that
284 // of the position vector of the cluster.
285 // In this extrapolation procedure the error propagation is performed
287 // Based on the cluster and extrapolated veto signal (x,y) positions and
288 // position errors the confidence level of association is calculated
289 // and stored as an additional signal value.
290 // By means of the GetVetoSignal memberfunction the confidence level of
291 // association can always be updated by the user.
292 // In case the user wants to invoke a more detailed extrapolation procedure,
293 // the automatic extrapolation can be suppressed by setting the argument
294 // extr=0. In this case it is assumed that the AliSignal as entered via
295 // the argument contains already the extrapolated position vector and
296 // corresponding errors.
297 // Note : Three additional values are added to the original AliSignal
298 // to hold the chi2, ndf and confidence level values of the association.
302 fVetos=new TObjArray();
306 Int_t nvalues=s.GetNvalues();
307 AliSignal* sx=new AliSignal(s); // Additional values will be added
308 TString name=s.GetName();
309 name.Append(" + additional chi2, ndf and CL values");
312 Double_t vecc[3],vecv[3];
315 // Extrapolate the veto hit position
317 GetPosition(vecc,"sph");
318 s.GetPosition(vecv,"sph");
319 if (vecv[0]) scale=vecc[0]/vecv[0];
320 Ali3Vector r=s*scale;
324 // Calculate the confidence level of association
325 GetPosition(vecc,"car");
326 sx->GetPosition(vecv,"car");
327 Double_t dx=vecc[0]-vecv[0];
328 Double_t dy=vecc[1]-vecv[1];
329 GetPositionErrors(vecc,"car");
330 sx->GetPositionErrors(vecv,"car");
331 Double_t sxc2=vecc[0]*vecc[0];
332 Double_t syc2=vecc[1]*vecc[1];
333 Double_t sxv2=vecv[0]*vecv[0];
334 Double_t syv2=vecv[1]*vecv[1];
335 Double_t sumx2=sxc2+sxv2;
336 Double_t sumy2=syc2+syv2;
338 if (sumx2>0 && sumy2>0) chi2=(dx*dx/sumx2)+(dy*dy/sumy2);
341 Double_t prob=m.Prob(chi2,ndf);
342 if (chi2>0) sx->SetSignal(chi2,nvalues+1);
343 if (ndf>0) sx->SetSignal(ndf,nvalues+2);
344 if (prob>0) sx->SetSignal(prob,nvalues+3);
349 ///////////////////////////////////////////////////////////////////////////
350 Int_t AliCalcluster::GetNvetos()
352 // Provide the number of veto signals associated to the cluster
355 ///////////////////////////////////////////////////////////////////////////
356 AliSignal* AliCalcluster::GetVetoSignal(Int_t i)
358 // Provide access to the i-th veto signal of this cluster.
359 // Note : The first hit corresponds to i=1.
362 cout << " *AliCalcluster::GetVetoSignal* No veto signals present." << endl;
367 if (i>0 && i<=fNvetos)
369 return (AliSignal*)fVetos->At(i-1);
373 cout << " *AliCalcluster::GetVetoSignal* Signal number " << i << " out of range."
374 << " Nvetos = " << fNvetos << endl;
379 ///////////////////////////////////////////////////////////////////////////
380 Float_t AliCalcluster::GetVetoLevel()
382 // Provide the confidence level of best associated veto signal.
389 for (Int_t i=0; i<fNvetos; i++)
391 s=((AliSignal*)fVetos->At(i));
394 nvalues=s->GetNvalues();
395 cl=s->GetSignal(nvalues);
396 if (cl>clmax) clmax=cl;
402 ///////////////////////////////////////////////////////////////////////////
403 Int_t AliCalcluster::HasVetoHit(Double_t cl)
405 // Investigate if cluster has an associated veto hit with conf. level > cl.
406 // Returns 1 if there is such an associated veto hit, otherwise returns 0.
407 // Note : This function is faster than GetVetoLevel().
412 for (Int_t i=0; i<fNvetos; i++)
414 s=((AliSignal*)fVetos->At(i));
417 nvalues=s->GetNvalues();
418 if (s->GetSignal(nvalues) > cl) return 1;
424 ///////////////////////////////////////////////////////////////////////////