FairRoot/PandaRoot
PndEmcXClMoments.cxx
Go to the documentation of this file.
1 //--------------------------------------------------------------------------
2 // File and Version Information:
3 //
4 // Description:
5 // Class PndEmcXClMoments
6 // A class for description of shower shapes
7 //
8 // Stefan Christ:
9 // Rescaled the lateral distance r by 1/rescaleFactor
10 // This keeps the momentens roughly the same although the digi position
11 // was changed
12 //
13 // Environment:
14 // Software developed for the BaBar Detector at the SLAC B-Factory.
15 //
16 // Author List:
17 // Thorsten Brandt Originator
18 //
19 // Copyright Information:
20 //
21 // Dima Melnichuk, adaption for pandaroot
22 //
23 //------------------------------------------------------------------------
24 
25 #include "PndEmcXClMoments.h"
27 #include "PndEmcTwoCoordIndex.h"
28 #include "PndEmcCluster.h"
29 #include "PndEmcDigi.h"
30 #include "TClonesArray.h"
31 #include <vector>
32 #include <cmath>
33 
34 using std::endl;
35 using std::ostream;
36 
37 
38 PndEmcXClMoments::PndEmcXClMoments(const PndEmcCluster &cluster, const TClonesArray *digiArray):
39  PndEmcAbsClusterProperty( cluster, digiArray ), fEnergyDistribution(), fClusterSize(0)
40 {
41  Init();
42 }
43 
45  PndEmcAbsClusterProperty( other ), fEnergyDistribution(other.fEnergyDistribution), fClusterSize(other.fClusterSize)
46 {
47  Init();
48 }
49 
50 //--------------
51 // Destructor --
52 //--------------
53 
55 {
56  fEnergyDistribution->clear();
57  delete fEnergyDistribution;
59 }
60 
63 {
64  Double_t r,sum=0;
65  for (int i=0; i<fClusterSize; i++)
66  {
67  r=(*fEnergyDistribution)[i].r;
68  sum+=(*fEnergyDistribution)[i].deposited_energy*r*r;
69  }
70  sum/=MyCluster().energy();
71 
72  return sum;
73 }
74 
75 Double_t
77 {
78  Double_t r,sum=0;
79  for (int i=0; i<fClusterSize; i++)
80  {
81  r=(*fEnergyDistribution)[i].r*sin((*fEnergyDistribution)[i].phi);
82  sum+=(*fEnergyDistribution)[i].deposited_energy*r*r;
83  }
84  sum/=MyCluster().energy();
85 
86  return sum;
87 }
88 
89 Double_t
91 {
92  Double_t r,sum=0;
93  for (int i=0; i<fClusterSize; i++)
94  {
95  r=(*fEnergyDistribution)[i].r*cos((*fEnergyDistribution)[i].phi);
96  sum+=(*fEnergyDistribution)[i].deposited_energy*r*r;
97  }
98  sum/=MyCluster().energy();
99 
100  return sum;
101 }
102 
103 Double_t
105 {
106  // 1. Check if n,m are correctly
107  if ((m>n) || ((n-m)%2 != 0) || (n<0) || (m<0))
108  {
109  return -1;
110  }
111 
112  // 2. Check if n,R0 are within validity Range :
113  // n>20 or R0<5cm just makes so sense !
114  if ((n>20) || (R0<=5))
115  {
116  return -1;
117  }
118  if (n<=5)
119  {
120  return Fast_AbsZernikeMoment(n,m,R0);
121  } else {
122  return Calc_AbsZernikeMoment(n,m,R0);
123  }
124 }
125 
126 Double_t
128 {
129  Double_t r,redmoment=0;
130  int n,n1,n2,tmp;
131  if (fClusterSize<3)
132  {
133  return 0;
134  }
135 
136  n1=0; n2=1;
137  if ((*fEnergyDistribution)[1].deposited_energy > (*fEnergyDistribution)[0].deposited_energy)
138  {
139  tmp=n2; n2=n1; n1=tmp;
140  }
141  for (int i=2; i<fClusterSize; i++)
142  {
143  n=i;
144  if ((*fEnergyDistribution)[i].deposited_energy > (*fEnergyDistribution)[n1].deposited_energy)
145  {
146  tmp = n2;
147  n2 = n1; n1 = i; n=tmp;
148  } else {
149  if ((*fEnergyDistribution)[i].deposited_energy > (*fEnergyDistribution)[n2].deposited_energy)
150  {
151  tmp=n2; n2=i; n=tmp;
152  }
153  }
154  r = (*fEnergyDistribution)[n].r;
155  redmoment+= r*r* (*fEnergyDistribution)[n].deposited_energy;
156  }
157  Double_t e1 = (*fEnergyDistribution)[n1].deposited_energy;
158  Double_t e2 = (*fEnergyDistribution)[n2].deposited_energy;
159  Double_t r0 = 2.5;//cm, the average distance between crystals
160  Double_t lat = redmoment/(redmoment+r0*r0*(e1+e2));
161 
162  return lat;
163 }
164 
165 void
166 PndEmcXClMoments::Print(const Option_t* ) const
167 {
168  TVector3 cl( MyCluster().where() );
169  TVector3 ClusDirection(cl.x(),cl.y(),cl.z());
170  ClusDirection *= 1.0/ClusDirection.Mag();
171  TVector3 theta_axis(ClusDirection.y(),-ClusDirection.x(),0.0);
172  theta_axis *= 1.0/theta_axis.Mag();
173  TVector3 phi_axis = theta_axis.Cross(ClusDirection);
174 
175  std::vector<Int_t> digiList = MyCluster().DigiList();
176  std::vector<Int_t>::iterator current;
177 
179  std::cout << "Dump of PndEmcCluster with CoG at (" << cl.x() << "," << cl.y()
180  << "," << cl.z() << ")" << endl;
181  std::cout << "-------------------------------------------------------------"<< endl;
182  std::cout << " theta - axis : (" << theta_axis.x() << "," << theta_axis.y() << ","
183  << theta_axis.z() << ")" << endl;
184  std::cout << " phi - axis : (" << phi_axis.x() << "," << phi_axis.y() << ","
185  << phi_axis.z() << ")" << endl;
186  int i=0;
187 
188  for (current=digiList.begin();current<digiList.end();++current){
189  clEdep = (*fEnergyDistribution)[i];
190  PndEmcDigi *digi = (PndEmcDigi *) DigiArray()->At(*current);
191  digi->Print();
192  std::cout << "Polar coords : (" << clEdep.r << "," << clEdep.phi << ")" << endl;
193  i++;
194  }
195 
196  for (int j=0; j<=8; j++)
197  {
198  std::cout << "f[" << j << "](5) = " << (this->*fFcn[j])(5.0) << endl;
199  }
200 
201  std::cout << "--------------------------------------------------------------"<< endl;
202 }
203 
204 
205 Double_t
206 PndEmcXClMoments::f00(Double_t ) const { return 1; } // r //[R.K.03/2017] unused variable(s)
207 
208 Double_t
209 PndEmcXClMoments::f11(Double_t r) const { return r; }
210 
211 Double_t
212 PndEmcXClMoments::f20(Double_t r) const { return 2.0*r*r-1.0; }
213 
214 Double_t
215 PndEmcXClMoments::f22(Double_t r) const { return r*r; }
216 
217 Double_t
218 PndEmcXClMoments::f31(Double_t r) const { return 3.0*r*r*r - 2.0*r; }
219 
220 Double_t
221 PndEmcXClMoments::f33(Double_t r) const { return r*r*r; }
222 
223 Double_t
224 PndEmcXClMoments::f40(Double_t r) const { return 6.0*r*r*r*r-6.0*r*r+1.0; }
225 
226 Double_t
227 PndEmcXClMoments::f42(Double_t r) const { return 4.0*r*r*r*r-3.0*r*r; }
228 
229 Double_t
230 PndEmcXClMoments::f44(Double_t r) const { return r*r*r*r; }
231 
232 Double_t
233 PndEmcXClMoments::f51(Double_t r) const { return 10.0*pow(r,5)-12.0*pow(r,3)+3.0*r; }
234 
235 Double_t
236 PndEmcXClMoments::f53(Double_t r) const { return 5.0*pow(r,5) - 4.0*pow(r,3); }
237 
238 Double_t
239 PndEmcXClMoments::f55(Double_t r) const { return pow(r,5); }
240 
241 Double_t
243 {
244  Double_t r,ph,e,Re=0,Im=0,result;
245  Double_t TotalEnergy = MyCluster().energy();
246  int index = (n/2)*(n/2)+(n/2)+m;
247  for (int i=0; i<fClusterSize; i++)
248  {
249  r = (*fEnergyDistribution)[i].r / R0;
250  if (r<1)
251  {
252  ph = ((*fEnergyDistribution)[i]).phi;
253  e = (*fEnergyDistribution)[i].deposited_energy;
254  Re = Re + e/TotalEnergy * (this->*fFcn[index])(r) * cos( (Double_t) m * ph);
255  Im = Im - e/TotalEnergy * (this->*fFcn[index])(r) * sin( (Double_t) m * ph);
256  }
257  }
258  result = sqrt(Re*Re+Im*Im);
259 
260  return result;
261 }
262 
263 Double_t
265 {
266  Double_t r,ph,e,Re=0,Im=0,f_nm,result;
267  Double_t TotalEnergy = MyCluster().energy();
268  for (int i=0; i<fClusterSize; i++)
269  {
270  r = (*fEnergyDistribution)[i].r / R0;
271  if (r<1)
272  {
273  ph = ((*fEnergyDistribution)[i]).phi;
274  e = (*fEnergyDistribution)[i].deposited_energy;
275  f_nm=0;
276  for (int s=0; s<=(n-m)/2; s++) {
277  if (s%2==0) {
278  f_nm = f_nm + Fak(n-s)*pow(r,(Double_t) (n-2*s))/(Fak(s)*Fak((n+m)/2-s)*Fak((n-m)/2-s));
279  }else {
280  f_nm = f_nm - Fak(n-s)*pow(r,(Double_t) (n-2*s))/(Fak(s)*Fak((n+m)/2-s)*Fak((n-m)/2-s));
281  }
282  }
283  Re = Re + e/TotalEnergy * f_nm * cos( (Double_t) m*ph);
284  Im = Im - e/TotalEnergy * f_nm * sin( (Double_t) m*ph);
285  }
286  }
287  result = sqrt(Re*Re+Im*Im);
288 
289  return result;
290 }
291 
292 Double_t
294 {
295  Double_t res=1.0;
296  for (int i=2; i<=n; i++)
297  {
298  res=res*(Double_t) i;
299  }
300 
301  return res;
302 }
303 
304 void
306 {
307  // need to get one digi to ask what kind of digi position method is used
308  // or to be more precise what scaling factor has do be used
309  Double_t rescaleFactor = 1.;
311 
312  const PndEmcDigi* pDigi = MyCluster().Maxima(DigiArray());
313  if ( pDigi != 0 ) rescaleFactor = pDigi->getRescaleFactor();
314 
315  // make sure we always use gravWhere for the cluster moments
316  // TVector3 cl( MyCluster().where() );
317  TVector3 cl( properties->GravWhere() );
318  TVector3 ClusDirection(cl.x(),cl.y(),cl.z());
319  ClusDirection *= 1.0/ClusDirection.Mag();
320  TVector3 theta_axis(ClusDirection.y(),-ClusDirection.x(),0.0);
321  theta_axis *= 1.0/theta_axis.Mag();
322  TVector3 phi_axis = theta_axis.Cross(ClusDirection);
323 
324  std::vector<Int_t> digiList = MyCluster().DigiList();
325  std::vector<Int_t>::iterator current;
326 
327  fClusterSize = digiList.size();
328  fEnergyDistribution = new std::vector<PndEmcClEnergyDeposition> (fClusterSize);
329 
330  int i=0;
332 
333  for (current=digiList.begin();current<digiList.end();++current)
334  {
335  PndEmcDigi *digi = (PndEmcDigi *) DigiArray()->At(*current);
336  clEdep.deposited_energy = digi->GetEnergy();
337 
338  TVector3 diff = digi->where() - cl;
339  TVector3 DigiVect = diff - diff.Dot(ClusDirection) * ClusDirection;
340  clEdep.r = DigiVect.Mag() / rescaleFactor;
341  clEdep.phi = DigiVect.Angle(theta_axis);
342  if (DigiVect.Dot(phi_axis)<0)
343  {
344  clEdep.phi = 2*M_PI - clEdep.phi;
345  }
346 
347  (*fEnergyDistribution)[i] = clEdep;
348  i++;
349  }
350 
361  fFcn[10] = &PndEmcXClMoments::f44 ;
362  fFcn[11] = &PndEmcXClMoments::f55 ;
363 }
364 
Double_t f00(Double_t r) const
friend F32vec4 cos(const F32vec4 &a)
Definition: P4_F32vec4.h:112
std::vector< PndEmcClEnergyDeposition > * fEnergyDistribution
TClonesArray * digi
Double_t f55(Double_t r) const
double r
Definition: RiemannTest.C:14
virtual Double_t GetEnergy() const
Definition: PndEmcDigi.cxx:296
represents the reconstructed hit of one emc crystal
Definition: PndEmcDigi.h:40
Int_t res
Definition: anadigi.C:166
Int_t i
Definition: run_full.C:25
__m128 m
Definition: P4_F32vec4.h:28
friend F32vec4 sqrt(const F32vec4 &a)
Definition: P4_F32vec4.h:29
virtual Double_t Lat() const
Double_t f33(Double_t r) const
friend F32vec4 sin(const F32vec4 &a)
Definition: P4_F32vec4.h:111
TLorentzVector s
Definition: Pnd2DStar.C:50
virtual ~PndEmcXClMoments()
int n
const std::vector< Int_t > & DigiList() const
Definition: PndEmcCluster.h:40
virtual Double_t SecondMoment() const
virtual Double_t AbsZernikeMoment(int n, int m, Double_t R0=15) const
virtual Double_t SecondMomentTheta() const
Double_t f31(Double_t r) const
Double_t f40(Double_t r) const
static Double_t getRescaleFactor()
Definition: PndEmcDigi.h:116
Double_t Fast_AbsZernikeMoment(int n, int m, Double_t R0) const
const PndEmcCluster & MyCluster() const
Double_t f44(Double_t r) const
Double_t f53(Double_t r) const
basic_ostream< char, char_traits< char > > ostream
virtual const PndEmcDigi * Maxima(const TClonesArray *digiArray) const
Double_t
Double_t f20(Double_t r) const
a cluster (group of neighboring crystals) of hit emc crystals
Definition: PndEmcCluster.h:29
const TClonesArray * DigiArray() const
Double_t f22(Double_t r) const
Double_t(PndEmcXClMoments::* fFcn[12])(Double_t) const
Double_t Fak(int n) const
Double_t f42(Double_t r) const
Double_t f11(Double_t r) const
virtual Double_t energy() const
ClassImp(PndAnaContFact)
Double_t Calc_AbsZernikeMoment(int n, int m, Double_t R0) const
const TVector3 & where() const
Definition: PndEmcDigi.h:111
virtual void Print(const Option_t *opt="") const
Definition: PndEmcDigi.cxx:337
virtual void Print(const Option_t *opt="") const
Double_t f51(Double_t r) const
virtual Double_t SecondMomentPhi() const