StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StFtpcFastSimu.cc
1 // $Id: StFtpcFastSimu.cc,v 1.32 2007/01/15 07:49:22 jcs Exp $
2 //
3 // $Log: StFtpcFastSimu.cc,v $
4 // Revision 1.32 2007/01/15 07:49:22 jcs
5 // replace printf, cout and gMesMgr with Logger
6 //
7 // Revision 1.31 2004/02/12 19:38:46 oldi
8 // Removal of intermediate tables.
9 //
10 // Revision 1.30 2004/01/28 02:04:43 jcs
11 // replace all instances of StFtpcReducedPoint and StFtpcPoint with StFtpcConfMapPoint
12 //
13 // Revision 1.29 2004/01/28 01:41:15 jeromel
14 // Change OST to OS everywhere since defaultoption is now not to print
15 // the date.
16 //
17 // Revision 1.28 2003/10/24 13:25:35 jcs
18 // calculate azimuthal angle phi in FTPC local coordinate system
19 //
20 // Revision 1.27 2003/10/10 12:36:16 jcs
21 // implement new FTPC geant volume id method
22 // initialize counters and arrays to zero
23 // replace many int,float's wiht Int_t,Float_t
24 //
25 // Revision 1.26 2003/09/02 17:58:14 perev
26 // gcc 3.2 updates + WarnOff
27 //
28 // Revision 1.25 2002/09/16 12:43:22 jcs
29 // replace large statically dimensioned arrays with dynamically dimensioned arrays
30 //
31 // Revision 1.24 2002/03/05 16:51:35 jcs
32 // force data type definitions to avoid compiler warnings (this is a correct
33 // but inelegant fix which must be changed)
34 //
35 // Revision 1.23 2001/04/23 20:30:41 oldi
36 // Output sent to StMessMgr now.
37 //
38 // Revision 1.22 2001/03/19 15:52:47 jcs
39 // use ftpcDimensions from database
40 //
41 // Revision 1.21 2001/01/27 20:10:42 jcs
42 // change name of parameter
43 //
44 // Revision 1.20 2001/01/25 15:25:44 oldi
45 // Fix of several bugs which caused memory leaks:
46 // - Some arrays were not allocated and/or deleted properly.
47 // - TClonesArray seems to have a problem (it could be that I used it in a
48 // wrong way in StFtpcTrackMaker form where Holm cut and pasted it).
49 // I changed all occurences to TObjArray which makes the program slightly
50 // slower but much more save (in terms of memory usage).
51 //
52 // Revision 1.19 2001/01/15 16:08:28 jcs
53 // get phiOrigin and phiPerSector fro ftpcDimensions
54 //
55 // Revision 1.18 2001/01/08 17:09:56 jcs
56 // move remaining constants from code to database
57 //
58 // Revision 1.17 2000/12/11 17:05:24 jcs
59 // use micrometers to convert from microns to cms
60 //
61 // Revision 1.16 2000/12/11 16:38:59 jcs
62 // move FTPC geant volume id and cluster flags from code to parameter reader
63 //
64 // Revision 1.15 2000/12/08 10:06:32 jcs
65 // replace cmath.h and math_constants.h with PhysicalConstants.h
66 //
67 // Revision 1.14 2000/11/24 15:02:33 hummler
68 // commit changes omitted in last commit
69 //
70 // Revision 1.12 2000/09/18 14:26:48 hummler
71 // expand StFtpcParamReader to supply data for slow simulator as well
72 // introduce StFtpcGeantReader to separate g2t tables from simulator code
73 // implement StFtpcGeantReader in StFtpcFastSimu
74 //
75 // Revision 1.11 2000/08/03 14:39:00 hummler
76 // Create param reader to keep parameter tables away from cluster finder and
77 // fast simulator. StFtpcClusterFinder now knows nothing about tables anymore!
78 //
79 // Revision 1.10 2000/02/04 13:49:40 hummler
80 // upgrade ffs:
81 // -remove unused fspar table
82 // -make hit smearing gaussian with decent parameters and static rand engine
83 // -separate hit smearing from cluster width calculation
84 //
85 // Revision 1.9 2000/02/02 15:40:05 hummler
86 // make hit smearing gaussian instead of box-shaped
87 //
88 // Revision 1.8 2000/02/02 15:20:36 hummler
89 // correct acceptance at sector boundaries,
90 // take values from fcl_det
91 //
92 // Revision 1.7 2000/01/27 14:48:06 hummler
93 // correct hit smearing
94 //
95 // Revision 1.6 2000/01/27 09:47:18 hummler
96 // implement raw data reader, remove type ambiguities that bothered kcc
97 //
98 // Revision 1.5 2000/01/05 13:23:40 hummler
99 // make cc5 happy
100 //
101 // Revision 1.4 2000/01/03 12:48:57 jcs
102 // Add CVS Id strings
103 //
104 
105 #include "StFtpcFastSimu.hh"
106 #include "StFtpcParamReader.hh"
107 #include "StFtpcDbReader.hh"
108 #include "StFtpcGeantReader.hh"
109 #include <Stiostream.h>
110 #include <stdlib.h>
111 #include "StMessMgr.h"
112 #include "PhysicalConstants.h"
113 #include "Random.h"
114 #include "RanluxEngine.h"
115 // random number engines from StarClassLibrary
116 #include "RandGauss.h"
117 
118 static RanluxEngine engine;
119 
120 StFtpcFastSimu::StFtpcFastSimu(StFtpcGeantReader *geantReader,
121  StFtpcParamReader *paramReader,
122  StFtpcDbReader *dbReader,
123  TObjArray *pointarray,
124  TObjArray *geantarray)
125 {
126  //-----------------------------------------------------------------------
127 
128  // zero everything that is possible
129  memset(&mStart,0,&mEnd-&mStart+1);
130 
131  // store Readers in data members
132  mParam=paramReader;
133  mDb =dbReader;
134  mGeant=geantReader;
135 
136  // allocate memory for local storage
137  // we need local arrays here that we can mess around in
138  nPoints=mGeant->numberOfHits();
139  mPoint=new StFtpcConfMapPoint[nPoints];
140  mGeantPoint=new StFtpcGeantPoint[nPoints];
141 
142  nPadrows = mDb->numberOfPadrows();
143  nrowmax = new Int_t[nPadrows];
144  memset(nrowmax,0,nPadrows*sizeof(Int_t));
145  nrow = new Int_t[nPadrows*nPoints];
146  memset(nrow,0,(nPadrows*nPoints)*sizeof(Int_t));
147 
148  // check that fppoint and gepoint are large enough to hold g2t_ftp_hit
149 
150  // Read paramenter tables and inititialize
151  ffs_ini();
152 
153  // hh Transfer the usable g2t_ftp_hit-data into fppoint and gepoint
154  ffs_hit_rd();
155 
156  // jr mark each hit with a row-number and a individual id
157  ffs_tag();
158 
159  // generate pad response and spatial resolutions
160  // mk in the routine FFS_GEN_PADRES the routine FFS_HIT_SMEAR is called
161  ffs_gen_padres();
162 
163  // Check for hit-merging
164 
165  ffs_merge_tagger();
166 
167  pointarray->Expand(nPoints);
168  geantarray->Expand(nPoints);
169 
170  for (Int_t i = 0; i < nPoints; i++) {
171  // use (default) copy constructor for StFtpcGeantPoint
172  geantarray->AddAt(new StFtpcGeantPoint(mGeantPoint[i]), i);
173  // as StFtpcPoint is in different package, we have to copy data
174  // from StFtpcReducedPoint
175  // hgrrrumpf!!! Holm
176  // It's not clear to me if this is still necessary since StFtpcReducePoint was eliminated.
177  // oldi 01/28/2004
178  pointarray->AddAt(new StFtpcConfMapPoint(), i);
179  ((StFtpcConfMapPoint *)pointarray->At(i))->SetX(mPoint[i].GetX());
180  ((StFtpcConfMapPoint *)pointarray->At(i))->SetY(mPoint[i].GetY());
181  ((StFtpcConfMapPoint *)pointarray->At(i))->SetZ(mPoint[i].GetZ());
182  ((StFtpcConfMapPoint *)pointarray->At(i))->SetXerr(mPoint[i].GetXerr());
183  ((StFtpcConfMapPoint *)pointarray->At(i))->SetYerr(mPoint[i].GetYerr());
184  ((StFtpcConfMapPoint *)pointarray->At(i))->SetZerr(mPoint[i].GetZerr());
185  ((StFtpcConfMapPoint *)pointarray->At(i))->SetPadRow(mPoint[i].GetPadRow());
186  ((StFtpcConfMapPoint *)pointarray->At(i))->SetSector(mPoint[i].GetSector());
187  ((StFtpcConfMapPoint *)pointarray->At(i))->SetNumberPads(mPoint[i].GetNumberPads());
188  ((StFtpcConfMapPoint *)pointarray->At(i))->SetNumberBins(mPoint[i].GetNumberBins());
189  ((StFtpcConfMapPoint *)pointarray->At(i))->SetMaxADC(mPoint[i].GetMaxADC());
190  ((StFtpcConfMapPoint *)pointarray->At(i))->SetCharge(mPoint[i].GetCharge());
191  ((StFtpcConfMapPoint *)pointarray->At(i))->SetFlags(mPoint[i].GetFlags());
192  ((StFtpcConfMapPoint *)pointarray->At(i))->SetSigmaPhi(mPoint[i].GetSigmaPhi());
193  ((StFtpcConfMapPoint *)pointarray->At(i))->SetSigmaR(mPoint[i].GetSigmaR());
194  }
195 
196  delete[] mGeantPoint;
197  delete[] mPoint;
198  delete[] nrowmax;
199  delete[] nrow;
200 }
201 
202 StFtpcFastSimu::~StFtpcFastSimu()
203 {
204  //LOG_INFO << "StFtpcFastSimu destructed" << endm;
205 }
206 
207 int StFtpcFastSimu::ffs_gen_padres()
208  {
209  // Local Variables:
210  float check1, check2;
211  float xi, yi, zi, phi_local, Rh, Vh, Timeb;
212  float sigTimeb, sigPhi, sigma_tr;
213  float sigma_l, sigma_z;
214  float alpha, lambda;
215  float r, pt;
216  float twist_cosine,twist, theta, cross_ang;
217 
218  // Variables to call ffs_hit_smear
219 
220  float xo, yo, zo, sigma_x, sigma_y;
221 
222  // Loop Variables
223 
224  int k;
225 
226  //-----------------------------------------------------------------------
227 
228 
229 // HepJamesRandom engine;
230  RandGauss quasiRandom(engine);
231 
232 
233  // loop over tracks
234 
235  //mk Check: is s_rad=0 and s_azi=0 then no hit-shifting is wanted.
236 
237  check1 = abs((int)s_rad[0])+abs((int)s_rad[1])+abs((int)s_rad[2])+abs((int)s_rad[3]);
238  check2 = abs((int)s_azi[0])+abs((int)s_azi[1])+abs((int)s_azi[2])+abs((int)s_azi[3]);
239 
240  if(check1==0. && check2 == 0. )
241  {
242  return FALSE;
243  }
244 
245  //mk end of check
246 
247  for(k = 0; k<nPoints; k++)
248  {
249  // get space point
250 
251  xi = mPoint[k].GetX();
252  yi = mPoint[k].GetY();
253  zi = mPoint[k].GetZ();
254 
255  // calculate spatial resolution along the padrow
256 
257  // Azimuthal angle Phi (in radians and in FTPC local coordinate system)
258  if (mGeant->geantPlane(mGeant->geantVolume(k)) <=10 )
259  phi_local = atan2((double) yi,(double) -xi);
260  else
261  phi_local = atan2((double) yi,(double) xi);
262  if(phi_local<0)
263  phi_local += twopi;
264 
265  // Radius of Hit
266  Rh = ::sqrt(xi*xi + yi*yi);
267 
268  // Drift velocity at hit [cm/microsec]
269  Vh = Vhm[0] + Vhm[1]*Rh + Vhm[2]*Rh*Rh + Vhm[3]*Rh*Rh*Rh;
270 
271  // Arrival time at Readout-Chambers in microsec
272  Timeb = Tbm[0] + Tbm[1]*Rh + Tbm[2]*Rh*Rh + Tbm[3]*Rh*Rh*Rh;
273 
274  // Angle-Determination:
275  // Calculate Dip- and Crossing-Angle
276  // For low-momenta particles the ionization is sometimes pointlike;
277  // then at least one of the momentum-components is 0; therefore set the
278  // angles to 0
279 
280  if((mGeantPoint[k].GetLocalMomentum(0)==0.)||
281  (mGeantPoint[k].GetLocalMomentum(0)==0.)||
282  (mGeantPoint[k].GetLocalMomentum(0)==0.))
283  {
284  alpha = 0.;
285  lambda = 0.;
286  }
287  else
288  {
289  // twist-angle:
290  r = sqrt ( sqr(mGeant->x(k)) +
291  sqr(mGeant->y(k)));
292  pt = sqrt ( sqr(mGeant->pLocalX(k)) +
293  sqr(mGeant->pLocalY(k)));
294  twist_cosine=(mGeant->pLocalX(k)*mGeant->x(k)+
295  mGeant->pLocalY(k)*mGeant->y(k))/(r*pt);
296  // protect against cases where abs(twist_cosine)>1.0
297  if ( twist_cosine > 1.0 )
298  twist_cosine = 1.0;
299  if ( twist_cosine < -1.0 )
300  twist_cosine = -1.0;
301  twist = (radian/degree)*acos(twist_cosine);
302 
303  // dip-angle:
304  theta = (radian/degree)*
305  atan2((double) (pt*cos(twist*degree)),
306  (double) ((mGeant->z(k)
307  /fabs(mGeant->z(k)))*
308  mGeant->pLocalZ(k)));
309 
310  // crossing-angle:
311  cross_ang = (radian/degree)*
312  atan2((double) (pt*cos(fabs(90.-twist)*degree)),
313  (double) ((mGeant->z(k)/fabs(mGeant->z(k)))*
314  mGeant->pLocalZ(k)));
315  alpha = fabs(cross_ang*degree);
316  if(alpha>(halfpi))
317  alpha=pi-alpha;
318 
319  lambda = fabs(theta*degree);
320  if(lambda>(halfpi))
321  lambda=pi-lambda;
322 
323  }
324 
325  //>>>>>>>>>>>>>>> AZIMUTHAL Direction>>>>>>>>>>>>>>>>>>>>>>
326 
327  // error sigma in azimuthal-direc. (microns)
328  sigPhi = err_azi[0]+err_azi[1]*Rh+err_azi[2]*sqr(Rh)+err_azi[3]*sqr(Rh)*Rh;
329 
330  // Sigma_tr response
331  sigma_tr = ::sqrt(sqr(sigPhi)+(sqr(mDb->padLength()*tan(alpha))));
332 
333  //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
334 
335  //>>>>>>>>>>>>>>> RADIAL Direction>>>>>>>>>>>>>>>>>>>>>>>>>
336 
337  // error sigma in r-direc. (microns)
338  sigTimeb = err_rad[0] + err_rad[1]*Rh + err_rad[2]*sqr(Rh) +
339  err_rad[3]*sqr(Rh)*Rh;
340 
341  //mk Sigma longitudinal at anode [micron]
342  sigma_l = ::sqrt(sqr(sigTimeb)+sqr(mDb->padLength()*tan(lambda)));
343 
344  //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
345 
346  //>>>>>>>>>>>>>>> Z Direction>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
347  // Sector width
348  sigma_z = 0.;
349 
350  //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
351 
352  //mk Va = velocity at readout-ch. in [cm/microsec]
353  // sigma_l = sigTimeb * Va
354 
355  //-> Smearing
356 
357  ffs_hit_smear( phi_local, xi, yi, zi, &xo, &yo, &zo,
358  sigma_l, sigma_tr,&sigma_z,&sigma_x,&sigma_y,
359  &quasiRandom);
360 
361  mPoint[k].SetX(xo);
362  mPoint[k].SetY(yo);
363  mPoint[k].SetZ(zo);
364  mPoint[k].SetXerr(sigma_x);
365  mPoint[k].SetYerr(sigma_y);
366  mPoint[k].SetZerr(sigma_z);
367  }
368  return TRUE;
369  }
370 
371 int StFtpcFastSimu::ffs_hit_rd()
372  {
373  int ih, ih_max;
374 
375  //-----------------------------------------------------------------------
376 
377  // set ih_max
378 
379  ih_max = mGeant->numberOfHits();
380 
381  // loop over MC hits and extract sector-row information
382 
383  for(ih= 0; ih<ih_max; ih++)
384  {
385  // specification variables:
386  // changed to new structures (gepoint) 01/29/98 hh
387  mGeantPoint[ih].SetGeantPID(mGeant->trackPid(ih));
388  mGeantPoint[ih].SetTrackPointer(mGeant->track(ih)+1);
389  mGeantPoint[ih].SetPrimaryTag(mGeant->trackType(ih));
390  if(mGeant->trackCharge(ih) < 0.0)
391  {
392  mGeantPoint[ih].SetPrimaryTag(-1*mGeantPoint[ih].GetPrimaryTag());
393  }
394 
395  // padrow
396  mPoint[ih].SetPadRow(mGeant->geantPlane(mGeant->geantVolume(ih)));
397 
398  // Vertex-Momenta
399  mGeantPoint[ih].SetVertexMomentum(mGeant->pVertexX(ih),mGeant->pVertexY(ih),mGeant->pVertexZ(ih));
400 
401  // Vertex position
402  mGeantPoint[ih].SetVertexPosition(mGeant->vertexX(ih),mGeant->vertexY(ih),mGeant->vertexZ(ih));
403 
404  // Secondary production process
405  mGeantPoint[ih].SetGeantProcess(mGeant->productionProcess(ih));
406 
407  //local momentum
408  mGeantPoint[ih].SetLocalMomentum(mGeant->pLocalX(ih),mGeant->pLocalY(ih),mGeant->pLocalZ(ih));
409 
410  mPoint[ih].SetX(mGeant->x(ih));
411  mPoint[ih].SetY(mGeant->y(ih));
412  mPoint[ih].SetZ(mGeant->z(ih));
413 
414  //sector number
415  mPoint[ih].SetSector(mGeant->geantSector(mGeant->geantVolume(ih)));
416 
417  //de/dx
418  mPoint[ih].SetMaxADC(int( mParam->adcConversionFactor() * mGeant->energyLoss(ih) ));
419  mPoint[ih].SetCharge((int)(mParam->clusterChargeConversionFactor()*mPoint[ih].GetMaxADC()));
420  // for de/dx simulations, introduce de/dx smearing + adjust factors! hh
421  mPoint[ih].SetNumberPads(mParam->numberOfPadsDedxSmearing());
422  mPoint[ih].SetNumberBins(mParam->numberOfBinsDedxSmearing());
423  // possibly make n_pads, n_bins dependent on exact position, charge
424  }
425 
426  // set the row counter
427  nPoints=ih_max;
428 
429  return TRUE;
430  }
431 
432 int StFtpcFastSimu::ffs_hit_smear(float phi,
433  float xi,
434  float yi,
435  float zi,
436  float *xo,
437  float *yo,
438  float *zo,
439  float st_dev_l,
440  float st_dev_t,
441  float *st_dev_z,
442  float *st_dev_x,
443  float *st_dev_y,
444  RandGauss *quasiRandom)
445  {
446  // Local Variables
447 
448  float err_pad; //ERROR ALONG PAD ROW FOR SPACE POINT
449  float err_drft; //ERROR ALONG DRIFT DIRECTION FOR SPACE POINT
450  float smear;
451  float err_x, err_y;// err_z;
452 
453  //-----------------------------------------------------------------------
454 
455  // Evaluate the sigmas in x- and y-direction out of the sigmas in long.
456  // and transverse direction
457 
458  *st_dev_x = sqr(cos(phi)) * sqr(st_dev_l) + sqr(sin(phi)) * sqr(st_dev_t);
459  *st_dev_x = (::sqrt(*st_dev_x))*micrometer;
460 
461  *st_dev_y = sqr(sin(phi)) * sqr(st_dev_l) + sqr(cos(phi)) * sqr(st_dev_t);
462  *st_dev_y = sqrt (*st_dev_y)*micrometer;
463 
464  smear=(float) quasiRandom->shoot();
465  err_pad = st_dev_t*smear; // box->sigma
466 
467  smear=(float) quasiRandom->shoot();
468  err_drft = st_dev_l*smear;
469 
470  // err_Z = st_dev_Z*SMEAR
471 
472  // Evaluate hit-shift in x- and y-direction as well as the new points xo and yo
473 
474  err_x = cos(phi) * err_drft - sin(phi) * err_pad;
475  *xo = xi + err_x*micrometer;
476 
477  err_y = sin(phi) * err_drft + cos(phi) * err_pad;
478  *yo = yi + err_y*micrometer;
479 
480  // ZO = ZI + err_Z
481  *zo = zi;
482 
483  return TRUE;
484  }
485 
486 int StFtpcFastSimu::ffs_ini()
487  {
488  //-----------------------------------------------------------------------
489  // mk
490  ri = mDb->sensitiveVolumeInnerRadius()+mParam->radiusTolerance();
491  ra = mDb->sensitiveVolumeOuterRadius()-mParam->radiusTolerance();
492 
493  //mk Drift-Velocity:
494  Vhm[0] = mParam->vDriftEstimates(0);
495  Vhm[1] = mParam->vDriftEstimates(1);
496  Vhm[2] = mParam->vDriftEstimates(2);
497  Vhm[3] = mParam->vDriftEstimates(3);
498 
499  //mk Drift_Time
500  Tbm[0] = mParam->tDriftEstimates(0);
501  Tbm[1] = mParam->tDriftEstimates(1);
502  Tbm[2] = mParam->tDriftEstimates(2);
503  Tbm[3] = mParam->tDriftEstimates(3);
504 
505  //mk Radial Sigma
506  s_rad[0] = mParam->sigmaRadialEstimates(0);
507  s_rad[1] = mParam->sigmaRadialEstimates(1);
508  s_rad[2] = 0;
509  s_rad[3] = 0;
510 
511  //mk Azimuthal Sigma
512  s_azi[0] = mParam->sigmaAzimuthalEstimates(0);
513  s_azi[1] = mParam->sigmaAzimuthalEstimates(1);
514  s_azi[2] = 0;
515  s_azi[3] = 0;
516 
517  //Radial Error
518  err_rad[0] = mParam->errorRadialEstimates(0);
519  err_rad[1] = mParam->errorRadialEstimates(1);
520  err_rad[2] = 0;
521  err_rad[3] = 0;
522 
523  //Azimuthal Error
524  err_azi[0] = mParam->errorAzimuthalEstimates(0);
525  err_azi[1] = mParam->errorAzimuthalEstimates(1);
526  err_azi[2] = 0;
527  err_azi[3] = 0;
528 
529  LOG_INFO << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" << endm;
530  LOG_INFO << "Parametrization for vd, Td, sig_rad and sig_azi, err_rad and err_azi:" << endm;
531  LOG_INFO << "vd=" << Vhm[0]<<"+"<<Vhm[1]<<"x+"<<Vhm[2]<<"xx+"
532  <<Vhm[3]<<"xxx" << endm;
533  LOG_INFO << "Td="<<Tbm[0]<<"+"<<Tbm[1]<<"x+"<<Tbm[2]<<"xx+"<<Tbm[3]
534  <<"xxx" << endm;
535  LOG_INFO << "sig_rad="<<s_rad[0]<<"+"<<s_rad[1]<<"x+"<<s_rad[2]
536  <<"xx+"<<s_rad[3]<<"xxx" << endm;
537  LOG_INFO << "sig_azi="<<s_azi[0]<<"+"<<s_azi[1]<<"x+"<<s_azi[2]
538  <<"xx+"<<s_azi[3]<<"xxx" << endm;
539  LOG_INFO << "err_rad="<<err_rad[0]<<"+"<<err_rad[1]<<"x+"<<err_rad[2]
540  <<"xx+"<<err_rad[3]<<"xxx" << endm;
541  LOG_INFO << "err_azi="<<err_azi[0]<<"+"<<err_azi[1]<<"x+"<<err_azi[2]
542  <<"xx+"<<err_azi[3]<<"xxx" << endm;
543  LOG_INFO << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" << endm;
544 
545  // Drift velocity at anode (Ranode = ra from/ftpc_params/ ) [cm/microsec]
546  Va = Vhm[0] + Vhm[1]*ra + Vhm[2]*sqr(ra) + Vhm[3]*ra*sqr(ra);
547 
548  // phi of sector number 1 origin
549  phimin = degree * mDb->phiOrigin();
550 
551  // size of one sector in phi
552  phisec = degree * mDb->phiPerSector();
553 
554  // a cluster is too close to lower sector boundary if it is
555  // not more than 2 pads away
556  sector_phi_min = mDb->radiansPerBoundary()/2 + 2*mDb->radiansPerPad();
557 
558  // a cluster is too close to upper sector boundary if it is
559  // not more than 2 pads away
560  sector_phi_max = phisec-sector_phi_min;
561 
562  return TRUE;
563  }
564 
565 Int_t StFtpcFastSimu::ffs_merge_tagger()
566  {
567  // Local Variables:
568  Int_t id_1, id_2, rem_count1, rem_count2, n_gepoints;
569  Float_t sig_azi_1, v1, sig_rad_1;
570  Float_t dist_rad_in, dist_rad_out;
571  Float_t delta_azi, delta_r;
572 
573  // Loop Variables
574  Int_t h,i,j,k;
575 
576  Float_t * sigazi = new float[nPoints];
577  Float_t * sigrad = new float[nPoints];
578  Float_t * r1 = new float[nPoints];
579  Float_t * phi1_local = new float[nPoints];
580 
581  //-----------------------------------------------------------------------
582 
583  k=0;
584  for(i=0; i<nPoints; i++)
585  {
586  mPoint[i].SetFlags(0);
587 
588  // azimuthal direction (in FTPC local coordinate system)
589  r1[i] = ::sqrt(sqr(mPoint[i].GetX()) + sqr(mPoint[i].GetY()));
590  if (mPoint[i].GetPadRow() <= 10 )
591  phi1_local[i] = atan2((double) mPoint[i].GetY(),
592  (double) -mPoint[i].GetX());
593  else
594  phi1_local[i] = atan2((double) mPoint[i].GetY(),
595  (double) mPoint[i].GetX());
596  if ( phi1_local[i] < 0.0 )
597  phi1_local[i] += twopi;
598 
599  sig_azi_1 = s_azi[0] + s_azi[1]*r1[i] +
600  s_azi[2]*sqr(r1[i]) + s_azi[3]*sqr(r1[i])*r1[i];
601  mPoint[i].SetSigmaPhi(sig_azi_1*micrometer*(r1[i]/ra));
602 
603  sig_azi_1 = (mParam->sigmaSpacingFactor()*sig_azi_1)*micrometer;
604  sigazi[i] = sig_azi_1*(r1[i]/ra);
605 
606  // radial direction
607  v1 = Vhm[0]+Vhm[1]*r1[i] + Vhm[2]*sqr(r1[i])+
608  Vhm[3]*sqr(r1[i])*r1[i];
609  sig_rad_1 = s_rad[0] + s_rad[1]*r1[i] +
610  s_rad[2]*sqr(r1[i]) + s_rad[3]*sqr(r1[i])*r1[i];
611 
612  mPoint[i].SetSigmaR(sig_rad_1*micrometer*(v1/Va));
613 
614  sig_rad_1 = (mParam->sigmaSpacingFactor()*sig_rad_1)*micrometer;
615  sigrad[i] = sig_rad_1*(v1/Va);
616 
617  }
618 
619  for(h=0;h<nPadrows;h++)
620  {
621  if(nrowmax[h]==0)
622  continue;
623 
624  for(i=0;i<nrowmax[h];i++)
625  {
626  id_1 = nrow[h*nPoints+i]-1;
627 
628  for(j=i+1; j<nrowmax[h]; j++)
629  {
630  id_2 = nrow[h*nPoints+j]-1;
631  if((mPoint[id_2].GetFlags()==mParam->mergedClusterFlag()) ||
632  (mPoint[id_2].GetSector()!=mPoint[id_1].GetSector()))
633  continue;
634 
635  delta_azi = fabs(phi1_local[id_1]-phi1_local[id_2])
636  *((r1[id_1]+r1[id_2])/2);
637  delta_r = fabs(r1[id_1]-r1[id_2]);
638 
639  if((delta_r < (2 * sigrad[id_1])) &&
640  (delta_azi < (2 * sigazi[id_1])))
641  {
642  // mark clusters as unfolded
643  if(mPoint[id_1].GetFlags() != mParam->mergedClusterFlag())
644  {
645  mPoint[id_1].SetFlags(mParam->unfoldedClusterFlag());
646  }
647  mPoint[id_2].SetFlags(mParam->unfoldedClusterFlag());
648  }
649 
650  if((delta_r<sigrad[id_1]) &&
651  (delta_azi<sigazi[id_1]))
652  {
653  k++;
654 
655  // merge clusters, mark second for removal
656  if(mPoint[id_1].GetFlags() != mParam->mergedClusterFlag())
657  {
658  mPoint[id_1].SetFlags(mParam->badShapeClusterFlag());
659  }
660  mPoint[id_2].SetFlags(mParam->mergedClusterFlag());
661  mPoint[id_1].SetMaxADC(mPoint[id_1].GetMaxADC()+
662  mPoint[id_2].GetMaxADC() / 2);
663  // maxadc adds up somehow, maybe more, maybe less
664  mPoint[id_1].SetCharge(mPoint[id_1].GetCharge() +
665  mPoint[id_2].GetCharge());
666  // charge adds up exactly
667  mPoint[id_1].SetX((mPoint[id_1].GetX() +
668  mPoint[id_2].GetX()) / 2);
669  mPoint[id_1].SetY((mPoint[id_1].GetY() +
670  mPoint[id_2].GetY()) / 2);
671  mPoint[id_1].SetZ((mPoint[id_1].GetZ() +
672  mPoint[id_2].GetZ()) / 2);
673  // positions average more or less
674  mPoint[id_1].SetSigmaPhi(mPoint[id_1].GetSigmaPhi()+
675  mPoint[id_2].GetSigmaPhi() / 2);
676  mPoint[id_1].SetSigmaR(mPoint[id_1].GetSigmaR()+
677  mPoint[id_2].GetSigmaR() / 2);
678  //widths add up somehow...
679  }
680  }
681  }
682  }
683 
684  rem_count1=0;
685  rem_count2=0;
686 
687  // now remove merged clusters and those on sector border
688  // LOG_INFO << "remove merged and cut-off hits" << endm;
689  id_1 = 0;
690  id_2 = 0;
691  n_gepoints = 0;
692 
693  dist_rad_in = s_rad[0] + s_rad[1]*ri + s_rad[2]*sqr(ri) +
694  s_rad[3]*ri*ri*ri;
695  dist_rad_out = s_rad[0] + s_rad[1]*ra + s_rad[2]*sqr(ra) +
696  s_rad[3]*ra*ra*ra;
697  // minimum distance in cm = 2*cluster sigma in microns
698  dist_rad_in *= 2.*micrometer;
699  dist_rad_out *= 2.*micrometer;
700 
701  while(id_2 < nPoints)
702  {
703  delta_azi = phi1_local[id_2]
704  -myModulo(((mPoint[id_2].GetSector()-1)*phisec+phimin),(twopi));
705  if (delta_azi<0.0)
706  delta_azi += twopi;
707 
708  if((delta_azi < sector_phi_min) ||
709  (delta_azi > sector_phi_max) ||
710  (r1[id_2] < ri+dist_rad_in) ||
711  (r1[id_2] > ra-dist_rad_out) ||
712  (mPoint[id_2].GetFlags() == mParam->mergedClusterFlag()))
713  {
714  if(mPoint[id_2].GetFlags() == mParam->mergedClusterFlag())
715  {
716  rem_count1++;
717  }
718  else
719  {
720  rem_count2++;
721  }
722  }
723  else
724  {
725  if ( id_2 == id_1 )
726  {
727  id_1++;
728  n_gepoints++;
729  }
730  else
731  {
732  mPoint[id_1].SetPadRow(mPoint[id_2].GetPadRow());
733  mPoint[id_1].SetSector(mPoint[id_2].GetSector());
734  mPoint[id_1].SetNumberPads(mPoint[id_2].GetNumberPads());
735  mPoint[id_1].SetNumberBins(mPoint[id_2].GetNumberBins());
736  mPoint[id_1].SetMaxADC(mPoint[id_2].GetMaxADC());
737  mPoint[id_1].SetCharge(mPoint[id_2].GetCharge());
738  mPoint[id_1].SetFlags(mPoint[id_2].GetFlags());
739  mGeantPoint[id_1].SetTrackPointer(mGeantPoint[id_2].GetTrackPointer());
740  mGeantPoint[id_1].SetGeantPID(mGeantPoint[id_2].GetGeantPID());
741  mGeantPoint[id_1].SetPrimaryTag(mGeantPoint[id_2].GetPrimaryTag());
742  mPoint[id_1].SetX(mPoint[id_2].GetX());
743  mPoint[id_1].SetY(mPoint[id_2].GetY());
744  mPoint[id_1].SetZ(mPoint[id_2].GetZ());
745  mPoint[id_1].SetSigmaPhi(mPoint[id_2].GetSigmaPhi());
746  mPoint[id_1].SetSigmaR(mPoint[id_2].GetSigmaR());
747  mGeantPoint[id_1].SetVertexMomentum(mGeantPoint[id_2].GetVertexMomentum(0),
748  mGeantPoint[id_2].GetVertexMomentum(1),
749  mGeantPoint[id_2].GetVertexMomentum(2));
750  mGeantPoint[id_1].SetLocalMomentum(mGeantPoint[id_2].GetLocalMomentum(0),
751  mGeantPoint[id_2].GetLocalMomentum(1),
752  mGeantPoint[id_2].GetLocalMomentum(2));
753  mGeantPoint[id_1].SetVertexPosition(mGeantPoint[id_2].GetVertexPosition(0),
754  mGeantPoint[id_2].GetVertexPosition(1),
755  mGeantPoint[id_2].GetVertexPosition(2));
756  mGeantPoint[id_1].SetGeantProcess(mGeantPoint[id_2].GetGeantProcess());
757  id_1++;
758  n_gepoints++;
759  }
760  }
761  id_2++;
762  }
763 
764  nPoints = n_gepoints;
765 
766  LOG_INFO << "Deleted " << rem_count1 << " merged clusters" << endm;
767  LOG_INFO << "Deleted " << rem_count2 << " clusters on sector limit" << endm;
768  LOG_INFO << " " << nPoints<< " clusters found" << endm;
769 
770  delete [] sigazi;
771  delete [] sigrad;
772  delete [] r1;
773  delete [] phi1_local;
774 
775  return TRUE;
776  }
777 
778 int StFtpcFastSimu::ffs_tag()
779  {
780  int i, k;
781  //-----------------------------------------------------------------------
782  // Tag hits according to row. Up to maximum row number=20
783 
784  // nrowmax(k) is the #of hits in hitplane k
785  // k is the hitplane-# given by gstar
786 
787  for(k=0; k<nPadrows; k++)
788  {
789  nrowmax[k] = 0;
790  }
791 
792 
793  for(i = 0; i< nPoints; i++)
794  {
795  k = mPoint[i].GetPadRow();
796  nrowmax[k-1]++;
797  nrow[(k-1)*nPoints+(nrowmax[k-1]-1)] = i+1;
798  }
799 
800  return TRUE;
801 
802  }