StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StFtpcSlowSimulator.cc
1 // $Id: StFtpcSlowSimulator.cc,v 1.19 2009/11/14 13:18:33 jcs Exp $
2 // $Log: StFtpcSlowSimulator.cc,v $
3 // Revision 1.19 2009/11/14 13:18:33 jcs
4 // change LOG_INFO messages to LOG_DEBUG messages
5 //
6 // Revision 1.18 2007/01/15 15:02:20 jcs
7 // replace printf, cout and gMesMgr with Logger
8 //
9 // Revision 1.17 2003/10/21 19:14:46 jcs
10 // use geantPlane function in debug printout
11 //
12 // Revision 1.16 2003/10/07 12:43:07 jcs
13 // use StFtpcGeantReader member function to extract FTPC plane number from GEANT volumeID
14 //
15 // Revision 1.15 2003/09/02 17:58:16 perev
16 // gcc 3.2 updates + WarnOff
17 //
18 // Revision 1.14 2003/07/04 14:06:43 fsimon
19 // Now rotating hits from global GEANT coordinates into local FTPC coordinates.
20 // This uses the instance of StFtpcTrackingParams defined in StFtpcSlowSimMaker.
21 //
22 // Revision 1.13 2002/09/13 13:46:41 fsimon
23 // Include functionality for smearing and kicking out hits,
24 // uncomment if needed
25 //
26 // Revision 1.12 2002/06/07 10:35:31 fsimon
27 // Additional debug info (tracing of hits)
28 //
29 // Revision 1.11 2002/04/19 22:24:13 perev
30 // fixes for ROOT/3.02.07
31 //
32 // Revision 1.10 2001/04/27 13:18:19 jcs
33 // cleanup comments, use SystemOfUnits for conversion
34 //
35 // Revision 1.9 2001/04/25 13:38:00 jcs
36 // remove obsolete comment
37 //
38 // Revision 1.8 2001/04/20 13:04:25 jcs
39 // this is the routine in which I changed the if/else statements for
40 // calculating the polar coordinates to avoid problems with optimizing
41 //
42 // Revision 1.7 2001/04/20 12:50:29 jcs
43 // cleanup comments
44 //
45 // Revision 1.6 2001/04/02 12:04:39 jcs
46 // get FTPC calibrations,geometry from MySQL database and code parameters from StarDb/ftpc
47 //
48 // Revision 1.5 2001/03/19 15:53:10 jcs
49 // use ftpcDimensions from database
50 //
51 // Revision 1.4 2001/03/06 23:36:24 jcs
52 // use database instead of params
53 //
54 // Revision 1.3 2001/01/11 17:37:25 jcs
55 // replace math.h with PhysicalConstants.h
56 //
57 // Revision 1.2 2000/11/27 14:08:08 hummler
58 // inplement tzero and lorentz angle correction factor
59 //
60 // Revision 1.1 2000/11/23 10:16:44 hummler
61 // New FTPC slow simulator in pure maker form
62 //
63 //
65 //
66 // This is the main routine for the FTPC Simulator
67 //
68 #include <Stiostream.h>
69 #include "PhysicalConstants.h"
70 
71 #include "StFtpcSlowSimulator.hh"
72 #include "StFtpcSlowSimField.hh"
73 #include "StFtpcSlowSimCluster.hh"
74 #include "StFtpcSlowSimReadout.hh"
75 #include "StFtpcRawWriter.hh"
76 #include "StFtpcClusterMaker/StFtpcGeantReader.hh"
77 #include "StFtpcClusterMaker/StFtpcParamReader.hh"
78 #include "StFtpcClusterMaker/StFtpcDbReader.hh"
79 
80 // include for Detector Rotations
81 #include "StFtpcTrackMaker/StFtpcTrackingParams.hh"
82 
83 
84 #include "TF1.h"
85 
86 #ifndef DEBUG
87 #define DEBUG 0
88 #endif
89 
90 StFtpcSlowSimulator::StFtpcSlowSimulator(StFtpcGeantReader *geantReader,
91  StFtpcParamReader *paramReader,
92  StFtpcDbReader *dbReader,
93  StFtpcRawWriter *rawWriter)
94 {
95  mGeant = geantReader;
96  mParam = paramReader;
97  mDb = dbReader;
98  mWriter = rawWriter;
99 }
100 
101 int StFtpcSlowSimulator::simulate()
102 {
103  int i;
104 
105  if(DEBUG) {LOG_DEBUG << "Begin Initialization..." << endm;}
106 
107  // setup fields
108  StFtpcSlowSimField *field = new StFtpcSlowSimField(mParam, mDb); // define the field
109  if(DEBUG) field->Output(); // write out field
110 
111  // setup readout
112  float *ADC = new float[mDb->numberOfPadrows()
113  *mDb->numberOfSectors()
114  *mDb->numberOfPads()
115  *mDb->numberOfTimebins()];
116 
117  StFtpcSlowSimReadout *rdout = new StFtpcSlowSimReadout(mParam, mDb, ADC, field);
118  // create readout
119  if(DEBUG) rdout->Print();
120 
122  // big loop over all the hit points
124  if (DEBUG) {LOG_DEBUG << "Looping over points..." << endm;}
125 
126  // tmp variables
127  float electron;
128  float rad_off;
129  float pad_off;
130  float rad;
131  float phi=0.;
132  float drift_time;
133 
134  float aip = mDb->gasIonizationPotential()*eV; // convert to GeV
135  float px, py, pz, pp;
136  float xx, yy, zz;
137  float de;
138  float r_min = mDb->sensitiveVolumeInnerRadius();
139  float r_max = mDb->sensitiveVolumeOuterRadius();
140  float dip_ang, cross_ang;
141 
142  int number_hits = mGeant->numberOfHits();
143  int rad_rej = 0;
144  int de_zero = 0;
145  int n_cross_ang_max = 0;
146  int counter=0;
147 
148  //create smearing function
149  //TF1* noise = new TF1("noise","gaus",-2,2);
150  //noise->SetParameters(1,0,0.035);
151  //LOG_DEBUG << "Using gaussian smearing of GEANT hits with a sigma of 350 um" << endm;
152 
153  //create smearing function
154  //TF1* kickout = new TF1("kickout","1",0,1);
155  //LOG_DEBUG << "Using Probability Function to throw out a certain percentage of all hits" << endm;
156 
157 
158  for ( i=0; i<number_hits; ++i )
159  {
160 
161 
162  // px = mGeant->pLocalX(i);
163  // py = mGeant->pLocalY(i);
164  // pz = mGeant->pLocalZ(i);
165 
166  // as local momenta from gstar are garbage:
167  // use gstar vertex momenta instead.
168  // errors should be small, except for shower tracks,
169  // where track_p points to the shower generating track...
170  px = mGeant->pVertexX(i);
171  py = mGeant->pVertexY(i);
172  pz = mGeant->pVertexZ(i);
173  pp = sqrt ( px*px + py*py );
174 
175  xx = mGeant->x(i);
176  yy = mGeant->y(i);
177  zz = mGeant->z(i);
178 
179  // Add gaussian smearing to x and y coordinates
180 
181  //xx += noise->GetRandom();
182  //yy += noise->GetRandom();
183 
184 
185  // Throw out a given percentage of hits
186  //if (kickout->GetRandom() < 0.2) continue;
187 
188  // Convert geant volume number into FTPC row number
189  int irow = mGeant->geantPlane(mGeant->geantVolume(i)) -1 ; // Geant goes from 1-20 and C++ counter uses 0-19
190 
191 
192  // Rotate the hit into FTPC - internal coordinate system (GEANT hits are always in global coords)
193  // This function is "stolen" from StFtpcPoint::TransformGlobal2Ftpc()
194 
195  StThreeVectorD org(xx, yy, zz);
196  StThreeVectorD transform = StFtpcTrackingParams::Instance()->GlobalToTpcRotation() * (org - StFtpcTrackingParams::Instance()->TpcPositionInGlobal());
197 
198  // internal FTPC rotation
199  Int_t whichFtpc = (transform.z() < 0) ? 0 : 1; // east or west
200 
201  // first tranformation to new origin (FTPC installation point)
202  transform.setY(transform.y() - StFtpcTrackingParams::Instance()->InstallationPointY(whichFtpc));
203  transform.setZ(transform.z() - StFtpcTrackingParams::Instance()->InstallationPointZ(whichFtpc));
204 
205  // actual rotation
206  transform = StFtpcTrackingParams::Instance()->FtpcRotationInverse(whichFtpc) * transform;
207 
208  // set z-position back to original value
209  transform.setY(transform.y() + StFtpcTrackingParams::Instance()->InstallationPointY(whichFtpc));
210  transform.setZ(transform.z() + StFtpcTrackingParams::Instance()->InstallationPointZ(whichFtpc));
211 
212  xx = transform.x();
213  yy = transform.y();
214  // zz = transform.z(); //not used since z - coordinate is given by the rows, z-rotation is not taken into account in simulations,
215  // but the influence should be quite small
216 
217 
218 
219  // Test that current point is within chamber
220  rad = sqrt ( xx*xx + yy*yy );
221  if(rad < r_min || rad > r_max) {
222  ++rad_rej;
223  continue ;
224  }
225 
226  de = mGeant->energyLoss(i);
227  if ( de == 0 ) {
228  ++de_zero;
229  }
230 
231  if(DEBUG) {
232  LOG_DEBUG << "Now processing hit " << i << " with xx;yy;zz;px;py;pz :"<< xx << "; " <<yy <<"; "<< zz <<"; "<< px <<"; "<< py <<"; "<< pz << endm;
233  }
234 
235 
236  // angle between r and p vectors in xy plane:
237  float fpp=0; if (pp>0) fpp=atan2(py,px);
238  float alpha = fpp - atan2(yy,xx);
239 
240 
241  // momentum components with respect to r in xy plane:
242  float p_perp = pp * sin(alpha);
243  float p_rad = pp * cos(alpha);
244  if(DEBUG) {
245  LOG_DEBUG << "alpha=" << alpha
246  << " pperp=" << p_perp
247  << " prad=" << p_rad
248  << " xx = "<<xx
249  << " yy = "<<yy
250  << " zz = "<<zz
251  << " px = "<<px
252  << " py = "<<py
253  << " pz=" << pz << endm;
254  }
255 
256  // dip angle with respect to plane defined by z- and phi- axes
257  dip_ang = atan(p_perp / pz);
258  // cross angle with respect to plane defined by z- and r- axes
259  cross_ang = atan(p_rad / pz);
260  if(cross_ang>halfpi) cross_ang = cross_ang - pi;
261 
262  // Limit cross_ang and dip_angle to 1.5 to avoid nonsensical results
263  // Holm has inactivated these tests
264  float ang_max = 0;
265  if ( fabs( cross_ang) > ang_max ) {
266  cross_ang = ang_max*cross_ang/fabs(cross_ang) ;
267  ++n_cross_ang_max;
268  }
269  if ( fabs( dip_ang) > ang_max ) {
270  dip_ang = ang_max*dip_ang/fabs(dip_ang) ;
271  ++n_cross_ang_max;
272  }
273 
274  // calculate the polar coordinates
275  // so that phi-phi_min >= 0.0 (phi_min=halfpi)
276 
277  if (xx > 0.0) {
278  phi = twopi + atan(yy/xx);
279  }
280  else if (xx < 0.0) {
281  phi = pi + atan(yy/xx);
282  }
283  else {
284  if (yy >= 0.0)
285  phi = halfpi;
286  else if (yy < 0.0)
287  phi = 1.5*pi ;
288  }
289 
290  if(DEBUG) {
291  LOG_DEBUG << i << " " << xx << " " << yy << " " << zz << " " << rad << " " << phi << endm;
292  }
293 
294  // define cluster for each accepted hit point
295  ++counter;
296  drift_time = -mDb->tZero();
297  electron = de / aip;
298 
299  rad_off = rdout->GetPadLength() * tan(dip_ang);
300  pad_off = rdout->GetPadLength() * tan(cross_ang); // in cm
301 
302 
303  if (DEBUG) {
304  LOG_DEBUG << " ##### Point i= " << i
305  << " counter=" << counter
306  << " nel=" << electron
307  << " rad=" << rad
308  << " phi=" << phi
309  << endm;
310  LOG_DEBUG << " ##### "
311  << " rad_off=" << rad_off
312  << " pad_off=" << pad_off
313  << endm;
314  LOG_DEBUG << " x = " << xx
315  << " y = " << yy
316  << " z = " << zz << endm;
317  LOG_DEBUG << " px = " << px
318  << " py = " << py
319  << " pz = " << pz
320  << " pp = " << pp
321  << " de = " << de << endm;
322  LOG_DEBUG << " dip_angle = " << dip_ang
323  << " cross_angle = " << cross_ang
324  << " row_id = " << mGeant->geantPlane(mGeant->geantVolume(i))-1
325  << " track_id = " << mGeant->track(i)+1
326  << " ge_pid = " << mGeant->trackPid(i)
327  << endm;
328  }
329  StFtpcSlowSimCluster *clus =
330  new StFtpcSlowSimCluster(mParam, mDb, field, electron, rad_off, pad_off,
331  rad, phi, drift_time, irow);
332 
333  clus->DriftDiffuse(field); // transport the cluster
334 
335  rdout->Avalanche(clus); // multiply electrons
336 
337  rdout->PadResponse(clus); // response on pad
338 
339  rdout->ShaperResponse(clus); // response on shaper
340 
341  rdout->Digitize(clus, irow); // digitize signal
342 
343  delete clus;
344 
345  } // end of loop over hit points
346 
347  if (DEBUG) {
348  LOG_DEBUG << "Total number of hit points tested = " << number_hits << endm;
349  LOG_DEBUG << "Number of hit points accepted = " << counter << endm;
350  LOG_DEBUG << "Number of hit points rejected (radius test) = " << rad_rej << endm;
351  LOG_DEBUG << "Number of hit points rejected (de=0 test) = " << de_zero << endm;
352  LOG_DEBUG << "Number of hit points with cross_ang > cross_ang_max = " << n_cross_ang_max << endm;
353  LOG_DEBUG << "Writing out ADC array in raw data structure." << endm;
354  }
355 
356  rdout->OutputADC();
357 
358  mWriter->writeArray(ADC,
359  mDb->numberOfPadrows(),
360  mDb->numberOfSectors(),
361  mDb->numberOfPads(),
362  mDb->numberOfTimebins(),
363  mParam->zeroSuppressThreshold());
364 
365  delete rdout;
366  delete field;
367  delete[] ADC;
368 
369  //delete noise;
370  //delete kickout;
371 
372  return 1;
373 }
374 
375 StFtpcSlowSimulator::~StFtpcSlowSimulator()
376 {
377 
378 }