Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DFCALCluster.cc
Go to the documentation of this file.
1 //
2 // FCALCluster member functions
3 //
4 #include <math.h>
5 #include "DFCALCluster.h"
6 #include "DFCALGeometry.h"
7 
8 #ifndef SQR
9 # define SQR(x) (x)*(x)
10 #endif
11 
12 DFCALCluster::DFCALCluster( const int nhits )
13 {
14  fEnergy = 0;
15  fEmax = 0;
16  fTime = 0;
17  fTimeMaxE = 0;
18  fChannelEmax = 0;
19  fTimeEWeight = 0;
20  fCentroid.SetXYZ( 0., 0., 0.);
21  fRMS = 0;
22  fRMS_t = 0;
23  fRMS_x = 0;
24  fRMS_y = 0;
25  fRMS_u = 0;
26  fRMS_v = 0;
27  fNhits = 0;
28  m_nFcalHits = nhits;
29 
30  if ( nhits > 0) {
31  fHit = new int[ nhits ];
32  fHitf = new double[ nhits ];
33  fEallowed = new double[ nhits ];
34  fEexpected = new double[ nhits ];
35  }
36  else {
37  fHit = 0;
38  fHitf = 0;
39  fEallowed = 0;
40  fEexpected = 0;
41  }
42 }
43 
45 {
46  if (fHit)
47  delete [] fHit;
48  if (fHitf)
49  delete [] fHitf;
50  if (fEallowed)
51  delete [] fEallowed;
52  if (fEexpected)
53  delete [] fEexpected;
54 }
55 
56 
57 void DFCALCluster::saveHits( const userhits_t* const hits )
58 {
59 
60  for ( int i=0; i < fNhits; i++) {
62  JObject::oid_t id = getHitID( hits, i ) ;
63  if ( id != 0 ) {
64  h.id = (JObject::oid_t) id;
65  h.ch = getHitCh( hits, i );
66  h.E = getHitE( hits, i ) ;
67  h.x = getHitX( hits, i ) ;
68  h.y = getHitY( hits, i ) ;
69  h.t = getHitT( hits, i ) ;
70  h.intOverPeak = getHitIntOverPeak( hits, i );
71  my_hits.push_back(h);
72  }
73  else {
74  static uint32_t Nwarns=0;
75  if (++Nwarns < 100)
76  std::cout << "Warning: DFCALCluster : corrupted cluster hit "
77  << i << std::endl;
78  if (Nwarns == 100)
79  std::cout << "Last warning!!! (further warnings supressed)"
80  << std::endl;
81  }
82  }
83 }
84 
85 
86 int DFCALCluster::addHit(const int ihit, const double frac)
87 {
88  if (ihit >= 0 ) {
89  fHit[fNhits] = ihit;
90  fHitf[fNhits] = frac;
91  ++fNhits;
92 
93  return 0;
94  }
95  else {
96  return 1;
97  }
98 }
99 
101 {
102  if (fNhits) {
103  fNhits = 0;
104  }
105 }
106 
107 bool DFCALCluster::update( const userhits_t* const hitList,
108  double fcalFaceZ )
109 {
110 
111  double energy = 0;
112  double t2EWeight = 0, tEWeight = 0;
113  for ( int h = 0; h < fNhits; h++ ) {
114  int ih = fHit[h];
115  double frac = fHitf[h];
116  double hitEnergy = hitList->hit[ih].E*frac;
117 
118  energy += hitEnergy;
119 
120  t2EWeight += hitEnergy * hitList->hit[ih].t * hitList->hit[ih].t;
121  tEWeight += hitEnergy * hitList->hit[ih].t;
122  }
123 
124  tEWeight /= energy;
125  t2EWeight /= energy;
126 
127  double eMax=0, timeMax=0;
128  int chMax=0;
129 
130  if (fNhits > 0) {
131  eMax = hitList->hit[fHit[0]].E;
132  timeMax = hitList->hit[fHit[0]].t;
133  chMax = hitList->hit[fHit[0]].ch;
134  }
135 
136  DVector3 centroid;
137  centroid.SetXYZ(0., 0., fcalFaceZ );
138  double xc=0;
139  double yc=0;
140 #ifdef LOG2_WEIGHTING
141  /* This complicated centroid algorithm was copied from
142  * Scott Teige's lgdClusterIU.c code -- don't ask [rtj]
143  */
144  double weight = 0.0;
145  double weightSum = 0.0;
146  double centerWeight = 0.0;
147  double neighborMaxWeight = 0.0;
148  double logFraction = exp(-0.23*(energy));
149  double currentOffset = log(energy)/7.0 + 3.7;
150  for (int h = 0; h < fNhits; h++) {
151  int ih = fHit[h];
152  double frac = fHitf[h];
153 
154  /*
155  * Find the weight - offset determines minimum energy of block
156  * to be used in weighting, since negative weights are thrown out
157  */
158 
159  weight = currentOffset + log(hitList->hit[ih].E*frac/energy);
160  if (h == 0) {
161  centerWeight = weight;
162  }
163  else {
164  neighborMaxWeight =
165  (neighborMaxWeight < weight)? weight:neighborMaxWeight;
166  }
167  if (weight > 0) {
168  xc += hitList->hit[ih].x*weight;
169  yc += hitList->hit[ih].y*weight;
170  weightSum += weight;
171  }
172  }
173  /*
174  * Now patch up the center block's weight if it's got a neighbor
175  * in the cluster that had positive weight
176  */
177  if (neighborMaxWeight > 0) {
178  xc += (logFraction-1)*(centerWeight-neighborMaxWeight)
179  *hitList->hit[0].x;
180  yc += (logFraction-1)*(centerWeight-neighborMaxWeight)
181  *hitList->hit[0].y;
182  weightSum += (logFraction-1)*(centerWeight-neighborMaxWeight);
183  }
184  centroid.SetX(xc/weightSum);
185  centroid.SetY(yc/weightSum);
186 #else
187  for (int h = 0; h < fNhits; h++) {
188  int ih = fHit[h];
189  double frac = fHitf[h];
190  xc += hitList->hit[ih].x*(hitList->hit[ih].E*frac);
191  yc += hitList->hit[ih].y*(hitList->hit[ih].E*frac);
192 
193  }
194  centroid.SetX(xc/energy);
195  centroid.SetY(yc/energy);
196 #endif
197 
198  double MOM1x = 0;
199  double MOM2x = 0;
200  double MOM1y = 0;
201  double MOM2y = 0;
202  double MOM1u = 0;
203  double MOM2u = 0;
204  double MOM1v = 0;
205  double MOM2v = 0;
206  for ( int h = 0; h < fNhits; h++ ) {
207  int ih = fHit[h];
208  double frac = fHitf[h];
209  double x = hitList->hit[ih].x;
210  double y = hitList->hit[ih].y;
211 
212  MOM1x += hitList->hit[ih].E*frac*x;
213  MOM1y += hitList->hit[ih].E*frac*y;
214  MOM2x += hitList->hit[ih].E*frac*SQR(x);
215  MOM2y += hitList->hit[ih].E*frac*SQR(y);
216 
217  double phi = atan2( centroid.y() , centroid.x() );
218  double u = x*cos(phi) + y*sin(phi);
219  double v =-x*sin(phi) + y*cos(phi);
220  MOM1u += hitList->hit[ih].E*frac*u;
221  MOM1v += hitList->hit[ih].E*frac*v;
222  MOM2u += hitList->hit[ih].E*frac*SQR(u);
223  MOM2v += hitList->hit[ih].E*frac*SQR(v);
224  }
225 
226  bool something_changed = false;
227  if (fabs(energy-fEnergy) > 0.001) {
228  fEnergy = energy;
229  something_changed = true;
230  }
231  if (fabs(eMax-fEmax) > 0.001) {
232  fEmax = eMax;
233  fChannelEmax = chMax;
234  fTimeMaxE = timeMax;
235  something_changed = true;
236  }
237  if (fabs(centroid.x()-fCentroid.x()) > 0.1 ||
238  fabs(centroid.y()-fCentroid.y()) > 0.1) {
239  fCentroid = centroid;
240  something_changed = true;
241  }
242 
243  if (something_changed) {
244 
245  fTime = timeMax;
246  fTimeEWeight = tEWeight;
247  fRMS_t = sqrt( t2EWeight - ( tEWeight * tEWeight ) );
248 
249  fRMS = sqrt(energy*(MOM2x+MOM2y)-SQR(MOM1x)-SQR(MOM1y))/(energy);
250  fRMS_x = sqrt(energy*MOM2x - SQR(MOM1x))/(energy);
251  fRMS_y = sqrt(energy*MOM2y - SQR(MOM1y))/(energy);
252  fRMS_u = sqrt(energy*MOM2u - SQR(MOM1u))/(energy);
253  fRMS_v = sqrt(energy*MOM2v - SQR(MOM1v))/(energy);
254 
255  for (int ih = 0; ih < hitList->nhits; ih++) {
256  shower_profile( hitList, ih,fEallowed[ih],fEexpected[ih],
257  fcalFaceZ+0.5*DFCALGeometry::blockLength());
258  }
259  }
260 
261  return something_changed;
262 }
263 
264 void DFCALCluster::shower_profile( const userhits_t* const hitList,
265  const int ihit,
266  double& Eallowed, double& Eexpected,
267  double fcalMidplaneZ) const
268 {
269 
270  //std::cout << " Run profile for hit " << ihit;
271  Eallowed = Eexpected = 0;
272  if (fEnergy == 0)
273  return;
274  double x = hitList->hit[ihit].x;
275  double y = hitList->hit[ihit].y;
276  double dist = sqrt(SQR(x - fCentroid.x()) + SQR(y - fCentroid.y()));
277  if (dist > MAX_SHOWER_RADIUS)
278  return;
279  double theta = atan2((double)sqrt(SQR(fCentroid.x()) + SQR(fCentroid.y())), fcalMidplaneZ);
280  double phi = atan2( fCentroid.y(), fCentroid.x() );
281  double u0 = sqrt(SQR(fCentroid.x())+SQR(fCentroid.y()));
282  double v0 = 0;
283  double u = x*cos(phi) + y*sin(phi);
284  double v =-x*sin(phi) + y*cos(phi);
285  double vVar = SQR(MOLIERE_RADIUS);
286  double uVar = vVar+SQR(SQR(8*theta));
287  double vTail = 4.5+0.9*log(fEnergy+0.05);
288  double uTail = vTail+SQR(10*theta);
289  double core = exp(-0.5*SQR(SQR(u-u0)/uVar + SQR(v-v0)/vVar));
290  double tail = exp(-sqrt(SQR((u-u0)/uTail)+SQR((v-v0)/vTail)));
291  Eexpected = fEnergy*core;
292  Eallowed = 2*fEmax*core + (0.2+0.5*log(fEmax+1.))*tail;
293 
294  if ((dist <= 4.) && (Eallowed < fEmax) ) {
295  std::cerr << "Warning: FCAL cluster Eallowed value out of range!\n";
296  Eallowed = fEmax;
297  }
298 }
double getHitT(const userhits_t *const hitList, const int ihit) const
Definition: DFCALCluster.h:263
static double blockLength()
Definition: DFCALGeometry.h:50
TVector3 DVector3
Definition: DVector3.h:14
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
DFCALCluster(const int nhits)
Definition: DFCALCluster.cc:12
double * fEexpected
Definition: DFCALCluster.h:130
#define y
void shower_profile(const userhits_t *const hitList, const int ihit, double &Eallowed, double &Eexpected, double fcalMidplaneZ) const
double * fEallowed
Definition: DFCALCluster.h:131
#define SQR(x)
Definition: DFCALCluster.cc:9
#define MOLIERE_RADIUS
Definition: DFCALCluster.h:20
void saveHits(const userhits_t *const hit)
Definition: DFCALCluster.cc:57
bool update(const userhits_t *const hitList, double fcalFaceZ)
int addHit(const int ihit, const double frac)
Definition: DFCALCluster.cc:86
double getHitY(const userhits_t *const hitList, const int ihit) const
Definition: DFCALCluster.h:253
double getHitX(const userhits_t *const hitList, const int ihit) const
Definition: DFCALCluster.h:243
vector< DFCALClusterHit_t > my_hits
Definition: DFCALCluster.h:134
double fEnergy
Definition: DFCALCluster.h:112
double * fHitf
Definition: DFCALCluster.h:129
double sqrt(double)
double getHitE(const userhits_t *const hitList, const int ihit) const
Definition: DFCALCluster.h:283
double sin(double)
#define MAX_SHOWER_RADIUS
Definition: DFCALCluster.h:21
oid_t getHitID(const userhits_t *const hitList, const int ihit) const
Definition: DFCALCluster.h:223
double fTimeMaxE
Definition: DFCALCluster.h:114
int getHitCh(const userhits_t *const hitList, const int ihit) const
Definition: DFCALCluster.h:233
double fTimeEWeight
Definition: DFCALCluster.h:115
void resetClusterHits()
double getHitIntOverPeak(const userhits_t *const hitList, const int ihit) const
Definition: DFCALCluster.h:273
union @6::@8 u
DVector3 fCentroid
Definition: DFCALCluster.h:118