Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4_Svtx_maps_ladders+intt_ladders+tpc_KalmanPatRec.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4_Svtx_maps_ladders+intt_ladders+tpc_KalmanPatRec.C
1 #include <vector>
2 
3 // if true, refit tracks with primary vertex included in track fit - good for analysis of prompt tracks only
4 // Adds second node to node tree, keeps original track node undisturbed
5 // Adds second evaluator to process refitted tracks and outputs separate ntuples
6 bool use_primary_vertex = false;
7 
8 const int n_maps_layer = 3; // must be 0-3, setting it to zero removes MVTX completely, n < 3 gives the first n layers
9 const int n_intt_layer = 4; // must be 0-4, setting this to zero will remove the INTT completely, n < 4 gives you the first n layers
10 
12 double tpc_layer_thick_inner = 1.25;
14 
15 // make inner layers a factor of 2 thinner
16 /*
17 int n_tpc_layer_inner = 8 * 2;
18 double tpc_layer_thick_inner = 1.25 / 2.0;
19 int tpc_layer_rphi_count_inner = 1920 / 2;
20 */
21 
22 int n_tpc_layer_mid = 16;
23 double tpc_layer_thick_mid = 1.25;
25 
27 double tpc_layer_thick_outer = 1.125; // outer later reach from 60-78 cm (instead of 80 cm), that leads to radial thickness of 1.125 cm
29 
31 
32 double inner_cage_radius = 20.;
33 double inner_readout_radius = 30.;
34 
35 // TPC gas parameters
36 // These are set for a variety of gas choices...
37 //==============================================
38 enum TPC_Gas
39 {
46 };
48 //TPC_Gas ether = TPC_Gas::ByHand;
49 
50 // Data on gasses @20 C and 760 Torr from the following source:
51 // http://www.slac.stanford.edu/pubs/icfa/summer98/paper3/paper3.pdf
52 double Ne_dEdx = 1.56; // keV/cm
53 double CF4_dEdx = 7.00; // keV/cm
54 double iBut_dEdx = 5.93; // keV/cm
55 
56 double Ne_NPrimary = 12; // Number/cm
57 double CF4_NPrimary = 51; // Number/cm
58 double iBut_NPrimary = 84; // Number/cm
59 
60 double Ne_NTotal = 43; // Number/cm
61 double CF4_NTotal = 100; // Number/cm
62 double iBut_NTotal = 195; // Number/cm
63 
64 // TPC Performance Parameter (applies extra smear to mimic the avalanche):
65 double TPC_SigmaT = 0.03; // 0.03 means 300 microns...Prakhar Garg Simulation...desire measurement...
66 
67 // to be overwritten...
71 double TPC_dEdx;
72 double TPC_NPri;
73 double TPC_NTot;
75 
76 // TPC readout shaping time and ADC clock parameters
77 // these set the Z size of the TPC cells
78 // These need to be set in the init since some of them require the drift velocity...
79 //=======================================
80 double TPCADCClock;
83 double tpc_cell_z;
85 double TPC_SmearZ;
86 
88 
89 void SvtxInit(int n_TPC_layers = 40, int verbosity = 0)
90 {
92 
93  switch (ether)
94  {
95  // https://www.phenix.bnl.gov/WWW/p/draft/prakhar/tpc/HTML_Gas_Linear/Ne_CF4_IC4H10_95_3_2.html
96  case TPC_Gas::Ne2K_100:
97  {
98  if (verbosity)
99  cout << "Gas Choice: TPC_Gas::Ne2K_100" << endl;
100  TPCDriftVelocity = 3.2 / 1000.0; // cm/ns
101  TPC_Trans_Diffusion = 0.0065; // cm/SQRT(cm)
102  TPC_Long_Diffusion = 0.0300; // cm/SQRT(cm)
103  TPC_dEdx = 0.95 * Ne_dEdx + 0.03 * CF4_dEdx + 0.02 * iBut_dEdx;
104  TPC_NPri = 0.95 * Ne_NPrimary + 0.03 * CF4_NPrimary + 0.02 * iBut_NPrimary;
105  TPC_NTot = 0.95 * Ne_NTotal + 0.03 * CF4_NTotal + 0.02 * iBut_NTotal;
106  break;
107  }
108  case TPC_Gas::Ne2K_400:
109  {
110  if (verbosity)
111  cout << "Gas Choice: TPC_Gas::Ne2K_400" << endl;
112  TPCDriftVelocity = 5.5 / 1000.0; // cm/ns
113  TPC_Trans_Diffusion = 0.0120; // cm/SQRT(cm)
114  TPC_Long_Diffusion = 0.0175; // cm/SQRT(cm)
115  TPC_dEdx = 0.95 * Ne_dEdx + 0.03 * CF4_dEdx + 0.02 * iBut_dEdx;
116  TPC_NPri = 0.95 * Ne_NPrimary + 0.03 * CF4_NPrimary + 0.02 * iBut_NPrimary;
117  TPC_NTot = 0.95 * Ne_NTotal + 0.03 * CF4_NTotal + 0.02 * iBut_NTotal;
118  break;
119  }
120  // https://www.phenix.bnl.gov/WWW/p/draft/prakhar/tpc/HTML_Gas_Linear/Ne_CF4_90_10.html
121  case TPC_Gas::NeCF4_100:
122  {
123  if (verbosity)
124  cout << "Gas Choice: TPC_Gas::NeCF4_100" << endl;
125  TPCDriftVelocity = 4.0 / 1000.0; // cm/ns
126  TPC_Trans_Diffusion = 0.0045; // cm/SQRT(cm)
127  TPC_Long_Diffusion = 0.0270; // cm/SQRT(cm)
128  TPC_dEdx = 0.90 * Ne_dEdx + 0.10 * CF4_dEdx;
129  TPC_NPri = 0.90 * Ne_NPrimary + 0.10 * CF4_NPrimary;
130  TPC_NTot = 0.90 * Ne_NTotal + 0.10 * CF4_NTotal;
131  break;
132  }
133  case TPC_Gas::NeCF4_300:
134  {
135  if (verbosity)
136  cout << "Gas Choice: TPC_Gas::NeCF4_300" << endl;
137  TPCDriftVelocity = 7.0 / 1000.0; // cm/ns
138  TPC_Trans_Diffusion = 0.0052; // cm/SQRT(cm)
139  TPC_Long_Diffusion = 0.0170; // cm/SQRT(cm)
140  TPC_dEdx = 0.90 * Ne_dEdx + 0.10 * CF4_dEdx;
141  TPC_NPri = 0.90 * Ne_NPrimary + 0.10 * CF4_NPrimary;
142  TPC_NTot = 0.90 * Ne_NTotal + 0.10 * CF4_NTotal;
143  break;
144  }
145  case TPC_Gas::NeCF4_400:
146  {
147  if (verbosity)
148  cout << "Gas Choice: TPC_Gas::NeCF4_400" << endl;
149  TPCDriftVelocity = 8.0 / 1000.0; // cm/ns
150  TPC_Trans_Diffusion = 0.0060; // cm/SQRT(cm)
151  TPC_Long_Diffusion = 0.0150; // cm/SQRT(cm)
152  TPC_dEdx = 0.90 * Ne_dEdx + 0.10 * CF4_dEdx;
153  TPC_NPri = 0.90 * Ne_NPrimary + 0.10 * CF4_NPrimary;
154  TPC_NTot = 0.90 * Ne_NTotal + 0.10 * CF4_NTotal;
155  break;
156  }
157  case TPC_Gas::ByHand:
158  {
159  if (verbosity)
160  cout << "Gas Choice: TPC_Gas::ByHand" << endl;
161  TPCDriftVelocity = 6.0 / 1000.0; // cm/ns
162  TPC_Trans_Diffusion = 0.0130; // cm/SQRT(cm)
163  TPC_Long_Diffusion = 0.0130; // cm/SQRT(cm)
164  TPC_ElectronsPerKeV = 28.0;
165  TPC_dEdx = 0.90 * Ne_dEdx + 0.10 * CF4_dEdx;
166  TPC_NPri = 0.90 * Ne_NPrimary + 0.10 * CF4_NPrimary;
168  break;
169  }
170  default: // defaults to NeCF4_400
171  {
172  if (verbosity)
173  cout << "Gas Choice Undefined...using TPC_Gas::NeCF4_400" << endl;
174  TPCDriftVelocity = 8.0 / 1000.0; // cm/ns
175  TPC_Trans_Diffusion = 0.0060; // cm/SQRT(cm)
176  TPC_Long_Diffusion = 0.0150; // cm/SQRT(cm)
177  TPC_dEdx = 0.90 * Ne_dEdx + 0.10 * CF4_dEdx;
178  TPC_NPri = 0.90 * Ne_NPrimary + 0.10 * CF4_NPrimary;
179  TPC_NTot = 0.90 * Ne_NTotal + 0.10 * CF4_NTotal;
180  break;
181  }
182  }
183 
185 
186  // TPC readout shaping time and ADC clock parameters
187  // these set the Z size of the TPC cells
188  //=======================================
189  // TPCShapingRMSLead = 32.0; // ns, rising RMS equivalent of shaping amplifier for 80 ns SAMPA
190  // TPCShapingRMSTail = 48.0; // ns, falling RMS equivalent of shaping amplifier for 80 ns SAMPA
191  TPCADCClock = 53.0; // ns, corresponds to an ADC clock rate of 18.8 MHz
192  TPCShapingRMSLead = 16.0; // ns, rising RMS equivalent of shaping amplifier for 40 ns SAMPA
193  TPCShapingRMSTail = 24.0; // ns, falling RMS equivalent of shaping amplifier for 40 ns SAMPA
194  // TPCADCClock = 27.0; // ns, corresponds to an ADC clock rate of 18.8 MHz * 2
196 
197  // TKH does not understand the physical origin of these parameters.
198  // however, their impact seems quite small...
199  TPC_SmearRPhi = 0.10;
200  TPC_SmearZ = 0.15;
201 }
202 
203 double Svtx(PHG4Reco* g4Reco, double radius,
204  const int absorberactive = 0,
205  int verbosity = 0)
206 {
207  if (n_maps_layer > 0)
208  {
209  bool maps_overlapcheck = false; // set to true if you want to check for overlaps
210 
211  /*
212  The numbers used in the macro below are from the xml file dump of ITS.gdml
213  As a sanity check, I got numbers from Walt Sondheim's drawings, sent by email June 20, 2017:
214  OD of Be beam pipe is 41.53 mm, ID is 40 mm
215  Layer 0: radius 23.44 mm to sensor center, tilt from normal to radial vector: 17.37 degrees (0.303 rad), spacing btw sensor centers: 30 deg, arc spacing 12.27 mm
216  Layer 1: radius 31.54 mm to sensor center, ttilt from normal to radial vector: 17.53 degrees (0.306 rad), spacing btw sensor centers: 22.5 deg, arc spacing 12.38 mm
217  Layer 2: radius 39.29 to sensor center, tilt from normal to radial vector: 17.02 degrees (0.297 rad), spacing btw sensor centers: 18.0 deg, arc spacing 12.34 mm
218  These are in reasonable agreement with the numbers I extracted from the gdml file, which are what we use below.
219  These use a spacing in arc length of 12.37 mm and a tilt of 0.304 for all of the first three layers
220  */
221 
222  // MAPS inner barrel layers
223  //======================================================
224 
225  double maps_layer_radius[3] = {23.4, 31.5, 39.3}; // mm - precise numbers from ITS.gdml
226  //double maps_layer_radius[3] = {24.9, 33.0, 40.8}; // mm - precise numbers from ITS.gdml + 1.5 mm for greater clearance from beam pipe
227 
228  // type 1 = inner barrel stave, 2 = middle barrel stave, 3 = outer barrel stave
229  // we use only type 0 here
230  int stave_type[3] = {0, 0, 0};
231  int staves_in_layer[3] = {12, 16, 20}; // Number of staves per layer in sPHENIX MVTX
232  double phi_tilt[3] = {0.304, 0.304, 0.304}; // radians, from the gdml file, 0.304 radians is 17.4 degrees
233 
234  for (int ilayer = 0; ilayer < n_maps_layer; ilayer++)
235  {
236  if (verbosity)
237  cout << "Create Maps layer " << ilayer << " with radius " << maps_layer_radius[ilayer] << " mm, stave type " << stave_type[ilayer]
238  << " pixel size 30 x 30 microns "
239  << " active pixel thickness 0.0018 microns" << endl;
240 
241  PHG4MapsSubsystem* lyr = new PHG4MapsSubsystem("MAPS", ilayer, stave_type[ilayer]);
242  lyr->Verbosity(verbosity);
243 
244  lyr->set_double_param("layer_nominal_radius", maps_layer_radius[ilayer]); // thickness in cm
245  lyr->set_int_param("N_staves", staves_in_layer[ilayer]); // uses fixed number of staves regardless of radius, if set. Otherwise, calculates optimum number of staves
246 
247  // The cell size is used only during pixilization of sensor hits, but it is convemient to set it now because the geometry object needs it
248  lyr->set_double_param("pixel_x", 0.0030); // pitch in cm
249  lyr->set_double_param("pixel_z", 0.0030); // length in cm
250  lyr->set_double_param("pixel_thickness", 0.0018); // thickness in cm
251  lyr->set_double_param("phitilt", phi_tilt[ilayer]);
252 
253  lyr->set_int_param("active", 1);
254  lyr->OverlapCheck(maps_overlapcheck);
255 
256  lyr->set_string_param("stave_geometry_file",
257  string(getenv("CALIBRATIONROOT")) + string("/Tracking/geometry/ALICE_ITS_tgeo.gdml"));
258 
259  g4Reco->registerSubsystem(lyr);
260 
261  radius = maps_layer_radius[ilayer];
262  }
263  }
264 
265  if (n_intt_layer > 0)
266  {
267  //-------------------
268  // INTT ladders
269  //-------------------
270 
271  bool intt_overlapcheck = false; // set to true if you want to check for overlaps
272 
273  // instantiate the Silicon tracker subsystem and register it
274  // We make one instance of PHG4TrackerSubsystem for all four layers of tracker
275  // dimensions are in mm, angles are in radians
276 
277  // PHG4SiliconTrackerSubsystem creates the detetor layer using PHG4SiliconTrackerDetector
278  // and instantiates the appropriate PHG4SteppingAction
279  const double intt_radius_max = 140.; // including stagger radius (mm)
280 
281  // The length of vpair is used to determine the number of layers
282  std::vector<std::pair<int, int>> vpair; // (sphxlayer, inttlayer)
283  for (int i = 0; i < n_intt_layer; i++)
284  {
285  // We want the sPHENIX layer numbers for the INTT to be from n_maps_layer to n_maps_layer+n_intt_layer - 1
286  vpair.push_back(std::make_pair(n_maps_layer + i, i)); // sphxlayer=n_maps_layer+i corresponding to inttlayer=i
287  if (verbosity) cout << "Create strip tracker layer " << vpair[i].second << " as sphenix layer " << vpair[i].first << endl;
288  }
289  PHG4SiliconTrackerSubsystem* sitrack = new PHG4SiliconTrackerSubsystem("SILICON_TRACKER", vpair);
290  sitrack->Verbosity(verbosity);
291  sitrack->SetActive(1);
292  sitrack->OverlapCheck(intt_overlapcheck);
293  g4Reco->registerSubsystem(sitrack);
294 
295  // outer radius marker (translation back to cm)
296  radius = intt_radius_max * 0.1;
297  }
298 
299  // time projection chamber layers --------------------------------------------
300 
302 
303  radius = inner_cage_radius;
304 
305  double cage_length = 211.0; // From TPC group, gives eta = 1.1 at 78 cm
306  double n_rad_length_cage = 1.13e-02;
307  double cage_thickness = 28.6 * n_rad_length_cage; // Kapton X_0 = 28.6 cm // mocks up Kapton + carbon fiber structure
308 
309  // inner field cage
310  cyl = new PHG4CylinderSubsystem("SVTXSUPPORT", n_maps_layer + n_intt_layer);
311  cyl->set_double_param("radius", radius);
312  cyl->set_int_param("lengthviarapidity", 0);
313  cyl->set_double_param("length", cage_length);
314  cyl->set_string_param("material", "G4_KAPTON");
315  cyl->set_double_param("thickness", cage_thickness);
316  cyl->SuperDetector("SVTXSUPPORT");
317  cyl->Verbosity(0);
318  g4Reco->registerSubsystem(cyl);
319 
320  radius += cage_thickness;
321 
322  double inner_readout_radius = 30.;
323  if (inner_readout_radius < radius) inner_readout_radius = radius;
324 
325  string tpcgas = "sPHENIX_TPC_Gas"; // Ne(90%) CF4(10%) - defined in g4main/PHG4Reco.cc
326 
327  // Layer of inert TPC gas from 20-30 cm
328  if (inner_readout_radius - radius > 0)
329  {
330  cyl = new PHG4CylinderSubsystem("SVTXSUPPORT", n_maps_layer + n_intt_layer + 1);
331  cyl->set_double_param("radius", radius);
332  cyl->set_int_param("lengthviarapidity", 0);
333  cyl->set_double_param("length", cage_length);
334  cyl->set_string_param("material", tpcgas.c_str());
335  cyl->set_double_param("thickness", inner_readout_radius - radius);
336  cyl->SuperDetector("SVTXSUPPORT");
337  g4Reco->registerSubsystem(cyl);
338  }
339 
340  radius = inner_readout_radius;
341 
342  double outer_radius = 78.;
343  //int npoints = Max_si_layer - n_maps_layer - n_intt_layer;
344  //double delta_radius = ( outer_radius - inner_readout_radius )/( (double)npoints );
345 
346  // Active layers of the TPC from 30-40 cm (inner layers)
347 
348  for (int ilayer = n_maps_layer + n_intt_layer; ilayer < (n_maps_layer + n_intt_layer + n_tpc_layer_inner); ++ilayer)
349  {
350  if (verbosity)
351  cout << "Create TPC gas layer " << ilayer << " with inner radius " << radius << " cm "
352  << " thickness " << tpc_layer_thick_inner - 0.01 << " length " << cage_length << endl;
353 
354  cyl = new PHG4CylinderSubsystem("SVTX", ilayer);
355  cyl->set_double_param("radius", radius);
356  cyl->set_int_param("lengthviarapidity", 0);
357  cyl->set_double_param("length", cage_length);
358  cyl->set_string_param("material", tpcgas.c_str());
359  cyl->set_double_param("thickness", tpc_layer_thick_inner - 0.01);
360  cyl->SetActive();
361  cyl->SuperDetector("SVTX");
362  g4Reco->registerSubsystem(cyl);
363 
364  radius += tpc_layer_thick_inner;
365  }
366 
367  // Active layers of the TPC from 40-60 cm (mid layers)
368 
370  {
371  if (verbosity)
372  cout << "Create TPC gas layer " << ilayer << " with inner radius " << radius << " cm "
373  << " thickness " << tpc_layer_thick_mid - 0.01 << " length " << cage_length << endl;
374 
375  cyl = new PHG4CylinderSubsystem("SVTX", ilayer);
376  cyl->set_double_param("radius", radius);
377  cyl->set_int_param("lengthviarapidity", 0);
378  cyl->set_double_param("length", cage_length);
379  cyl->set_string_param("material", tpcgas.c_str());
380  cyl->set_double_param("thickness", tpc_layer_thick_mid - 0.01);
381  cyl->SetActive();
382  cyl->SuperDetector("SVTX");
383  g4Reco->registerSubsystem(cyl);
384 
385  radius += tpc_layer_thick_mid;
386  }
387 
388  // Active layers of the TPC from 60-80 cm (outer layers)
389 
391  {
392  if (verbosity)
393  cout << "Create TPC gas layer " << ilayer << " with inner radius " << radius << " cm "
394  << " thickness " << tpc_layer_thick_outer - 0.01 << " length " << cage_length << endl;
395 
396  cyl = new PHG4CylinderSubsystem("SVTX", ilayer);
397  cyl->set_double_param("radius", radius);
398  cyl->set_int_param("lengthviarapidity", 0);
399  cyl->set_double_param("length", cage_length);
400  cyl->set_string_param("material", tpcgas.c_str());
401  cyl->set_double_param("thickness", tpc_layer_thick_outer - 0.01);
402  cyl->SetActive();
403  cyl->SuperDetector("SVTX");
404  g4Reco->registerSubsystem(cyl);
405 
406  radius += tpc_layer_thick_outer;
407  }
408 
409  // outer field cage
410  cyl = new PHG4CylinderSubsystem("SVTXSUPPORT", n_maps_layer + n_intt_layer + n_gas_layer);
411  cyl->set_double_param("radius", radius);
412  cyl->set_int_param("lengthviarapidity", 0);
413  cyl->set_double_param("length", cage_length);
414  cyl->set_string_param("material", "G4_KAPTON");
415  cyl->set_double_param("thickness", cage_thickness); // Kapton X_0 = 28.6 cm
416  cyl->SuperDetector("SVTXSUPPORT");
417  g4Reco->registerSubsystem(cyl);
418 
419  radius += cage_thickness;
420 
421  return radius;
422 }
423 
424 void Svtx_Cells(int verbosity = 0)
425 {
426  // runs the cellularization of the energy deposits (g4hits)
427  // into detector hits (g4cells)
428 
429  //---------------
430  // Load libraries
431  //---------------
432 
433  gSystem->Load("libfun4all.so");
434  gSystem->Load("libg4detectors.so");
435 
436  //---------------
437  // Fun4All server
438  //---------------
439 
441 
442  //-----------
443  // SVTX cells
444  //-----------
445 
446  if (verbosity)
447  {
448  cout << " TPC Drift Velocity: " << TPCDriftVelocity << " cm/nsec" << endl;
449  cout << " TPC Transverse Diffusion: " << TPC_Trans_Diffusion << " cm/SQRT(cm)" << endl;
450  cout << " TPC Longitudinal Diffusion: " << TPC_Long_Diffusion << " cm/SQRT(cm)" << endl;
451  cout << " TPC dE/dx: " << TPC_dEdx << " keV/cm" << endl;
452  cout << " TPC N Primary: " << TPC_NPri << " electrons/cm" << endl;
453  cout << " TPC N Total: " << TPC_NTot << " electrons/cm" << endl;
454  cout << " TPC Electrons Per keV: " << TPC_ElectronsPerKeV << " electrons/keV" << endl;
455  cout << " TPC ADC Clock: " << TPCADCClock << " nsec" << endl;
456  cout << " TPC ADC Rate: " << 1000.0 / TPCADCClock << " MHZ" << endl;
457  cout << " TPC Shaping Lead: " << TPCShapingRMSLead << " nsec" << endl;
458  cout << " TPC Shaping Tail: " << TPCShapingRMSTail << " nsec" << endl;
459  cout << " TPC z cell " << tpc_cell_z << " cm" << endl;
460  cout << " TPC Smear R-Phi " << TPC_SmearRPhi << " cm" << endl;
461  cout << " TPC Smear Z " << TPC_SmearZ << " cm" << endl;
462  }
463 
464  if (n_maps_layer > 0)
465  {
466  // MAPS cells
467  PHG4MapsCellReco* maps_cells = new PHG4MapsCellReco("MAPS");
468  maps_cells->Verbosity(verbosity);
469  for (int ilayer = 0; ilayer < n_maps_layer; ilayer++)
470  {
471  maps_cells->set_timing_window(ilayer, -2000, 2000);
472  }
473  se->registerSubsystem(maps_cells);
474  }
475 
476  if (n_intt_layer > 0)
477  {
478  // INTT cells
479  PHG4SiliconTrackerCellReco* reco = new PHG4SiliconTrackerCellReco("SILICON_TRACKER");
480  // The timing windows are hard-coded in the INTT ladder model
481  reco->Verbosity(verbosity);
482  se->registerSubsystem(reco);
483  }
484 
485  // TPC cell sizes are defined at top of macro, this is for backward compatibility with old hits files
486  if (n_gas_layer == 60)
487  {
488  TPCDriftVelocity = 6.0 / 1000.0; // cm/ns
489  tpc_cell_x = 0.12;
490  tpc_cell_y = 0.17;
491  }
492 
493  // Main switch for TPC distortion
494  const bool do_tpc_distortion = true;
495  PHG4TPCSpaceChargeDistortion* tpc_distortion = NULL;
496  if (do_tpc_distortion)
497  {
498  if (inner_cage_radius != 20. && inner_cage_radius != 30.)
499  {
500  cout << "Svtx_Cells - Fatal Error - TPC distortion required that "
501  "inner_cage_radius is either 20 or 30 cm."
502  << endl;
503  exit(3);
504  }
505 
506  string TPC_distortion_file =
507  string(getenv("CALIBRATIONROOT")) +
508  Form("/Tracking/TPC/SpaceChargeDistortion/TPCCAGE_20_78_211_2.root");
509  PHG4TPCSpaceChargeDistortion* tpc_distortion =
510  new PHG4TPCSpaceChargeDistortion(TPC_distortion_file);
511  //tpc_distortion -> setAccuracy(0); // option to over write default factors
512  //tpc_distortion -> setPrecision(0.001); // option to over write default factors // default is 0.001
513  }
514 
515  PHG4CylinderCellTPCReco* svtx_cells = new PHG4CylinderCellTPCReco(n_maps_layer + n_intt_layer);
516  svtx_cells->Detector("SVTX");
517  svtx_cells->setDistortion(tpc_distortion);
518  if (n_gas_layer != 60)
519  {
520  svtx_cells->setDiffusionT(TPC_Trans_Diffusion);
521  svtx_cells->setDiffusionL(TPC_Long_Diffusion);
522  svtx_cells->setSigmaT(TPC_SigmaT);
523 
524  svtx_cells->setShapingRMSLead(TPCShapingRMSLead * TPCDriftVelocity);
525  svtx_cells->setShapingRMSTail(TPCShapingRMSTail * TPCDriftVelocity);
526  // Expected cluster resolutions:
527  // r-phi: diffusion + GEM smearing = 750 microns, assume resolution is 20% of that => 150 microns
528  // Z: amplifier shaping time (RMS 32 ns, 48 ns) and drift vel of 3 cm/microsec gives smearing of 3 x (32+48/2 = 1.2 mm, assume resolution is 20% of that => 240 microns
529  svtx_cells->setSmearRPhi(TPC_SmearRPhi); // additional random displacement of cloud positions wrt hits to give expected cluster resolution of 150 microns for charge at membrane
530  svtx_cells->setSmearZ(TPC_SmearZ); // additional random displacement of cloud positions wrt hits to give expected cluster rsolution of 240 microns for charge at membrane
531  }
532  else
533  {
534  // 60 layer tune
535  svtx_cells->setDiffusionT(0.0120);
536  svtx_cells->setDiffusionL(0.0120);
537  svtx_cells->setSmearRPhi(0.09); // additional smearing of cluster positions
538  svtx_cells->setSmearZ(0.06); // additional smearing of cluster positions
539  }
540  svtx_cells->set_drift_velocity(TPCDriftVelocity);
541  svtx_cells->setHalfLength(105.5);
542  svtx_cells->setElectronsPerKeV(TPC_ElectronsPerKeV);
543  svtx_cells->Verbosity(0);
544 
545  // The maps cell size is set when the detector is constructed because it is needed by the geometry object
546  // The INTT ladder cell size is set in the detector construction code
547 
548  // set cylinder cell TPC cell sizes
549  //======================
550 
551  double tpc_timing_window = 105.5 / TPCDriftVelocity; // half length in cm / Vd in cm/ns => ns
552 
553  // inner layers
554  double radius_layer = inner_readout_radius + tpc_layer_thick_inner / 2.0;
555  int counter_layer = 0;
557  {
558  // this calculates the radius at the middle of the layer
559  if (counter_layer > 0)
560  radius_layer += tpc_layer_thick_inner;
561  double tpc_cell_rphi = 2 * TMath::Pi() * radius_layer / (double) tpc_layer_rphi_count_inner;
562  svtx_cells->cellsize(i, tpc_cell_rphi, tpc_cell_z);
563  svtx_cells->set_timing_window(i, -tpc_timing_window, +tpc_timing_window);
564  if (verbosity)
565  cout << "TPC cells inner: layer " << i << " center radius " << radius_layer << " tpc_cell_rphi " << tpc_cell_rphi << " tpc_cell_z " << tpc_cell_z << endl;
566  counter_layer++;
567  }
568  radius_layer += tpc_layer_thick_inner / 2.0;
569 
570  // mid layers
571  radius_layer += tpc_layer_thick_mid / 2.0;
572  counter_layer = 0;
573  for (int i = n_maps_layer + n_intt_layer + n_tpc_layer_inner; i < n_maps_layer + n_intt_layer + n_tpc_layer_inner + n_tpc_layer_mid; i++)
574  {
575  if (counter_layer > 0)
576  radius_layer += tpc_layer_thick_mid;
577  double tpc_cell_rphi = 2 * TMath::Pi() * radius_layer / (double) tpc_layer_rphi_count_mid;
578  svtx_cells->cellsize(i, tpc_cell_rphi, tpc_cell_z);
579  svtx_cells->set_timing_window(i, -tpc_timing_window, +tpc_timing_window);
580  if (verbosity)
581  cout << "TPC cells mid: layer " << i << " center radius " << radius_layer << " tpc_cell_rphi " << tpc_cell_rphi << " tpc_cell_z " << tpc_cell_z << endl;
582  counter_layer++;
583  }
584  radius_layer += tpc_layer_thick_mid / 2.0;
585 
586  // outer layers
587  radius_layer += tpc_layer_thick_outer / 2.0;
588  counter_layer = 0;
589  for (int i = n_maps_layer + n_intt_layer + n_tpc_layer_inner + n_tpc_layer_mid; i < n_maps_layer + n_intt_layer + n_tpc_layer_inner + n_tpc_layer_mid + n_tpc_layer_outer; i++)
590  {
591  if (counter_layer > 0)
592  radius_layer += tpc_layer_thick_outer;
593  double tpc_cell_rphi = 2 * TMath::Pi() * radius_layer / (double) tpc_layer_rphi_count_outer;
594  svtx_cells->cellsize(i, tpc_cell_rphi, tpc_cell_z);
595  svtx_cells->set_timing_window(i, -tpc_timing_window, +tpc_timing_window);
596  if (verbosity)
597  cout << "TPC cells outer: layer " << i << " center radius " << radius_layer << " tpc_cell_rphi " << tpc_cell_rphi << " tpc_cell_z " << tpc_cell_z << endl;
598  counter_layer++;
599  }
600 
601  se->registerSubsystem(svtx_cells);
602 
603  return;
604 }
605 
606 void Svtx_Reco(int verbosity = 0)
607 {
608  //---------------
609  // Load libraries
610  //---------------
611 
612  gSystem->Load("libfun4all.so");
613  gSystem->Load("libg4hough.so");
614 
615  //---------------
616  // Fun4All server
617  //---------------
618 
620 
621  //----------------------------------
622  // Digitize the cell energy into ADC
623  //----------------------------------
624  PHG4SvtxDigitizer* digi = new PHG4SvtxDigitizer();
625  digi->Verbosity(0);
626  for (int i = 0; i < n_maps_layer; ++i)
627  {
628  digi->set_adc_scale(i, 255, 0.4e-6); // reduced by a factor of 2.5 when going from maps thickess of 50 microns to 18 microns
629  }
630 
631  if (n_intt_layer > 0)
632  {
633  // INTT
634  std::vector<double> userrange; // 3-bit ADC threshold relative to the mip_e at each layer.
635  // these should be used for the INTT
636  userrange.push_back(0.05);
637  userrange.push_back(0.10);
638  userrange.push_back(0.15);
639  userrange.push_back(0.20);
640  userrange.push_back(0.25);
641  userrange.push_back(0.30);
642  userrange.push_back(0.35);
643  userrange.push_back(0.40);
644 
645  PHG4SiliconTrackerDigitizer* digiintt = new PHG4SiliconTrackerDigitizer();
646  digiintt->Verbosity(verbosity);
647  for (int i = 0; i < n_intt_layer; i++)
648  {
649  digiintt->set_adc_scale(n_maps_layer + i, userrange);
650  }
651  se->registerSubsystem(digiintt);
652  }
653 
654  // TPC layers
655  for (int i = n_maps_layer + n_intt_layer; i < Max_si_layer; ++i)
656  {
657  digi->set_adc_scale(i, 30000, 1.0);
658  }
659  se->registerSubsystem(digi);
660 
661  //-------------------------------------
662  // Apply Live Area Inefficiency to Hits
663  //-------------------------------------
664  // defaults to 1.0 (fully active)
665 
666  PHG4SvtxDeadArea* deadarea = new PHG4SvtxDeadArea();
667 
668  for (int i = 0; i < n_maps_layer; i++)
669  {
670  deadarea->Verbosity(verbosity);
671  //deadarea->set_hit_efficiency(i,0.99);
672  deadarea->set_hit_efficiency(i, 1.0);
673  }
674  for (int i = n_maps_layer; i < n_maps_layer + n_intt_layer; i++)
675  {
676  //deadarea->set_hit_efficiency(i,0.99);
677  deadarea->set_hit_efficiency(i, 1.0);
678  }
679  se->registerSubsystem(deadarea);
680 
681  //-----------------------------
682  // Apply MIP thresholds to Hits
683  //-----------------------------
684 
685  PHG4SvtxThresholds* thresholds = new PHG4SvtxThresholds();
686  thresholds->Verbosity(verbosity);
687 
688  // maps
689  for (int i = 0; i < n_maps_layer; i++)
690  {
691  // reduced by x2.5 when going from cylinder maps with 50 microns thickness to actual maps with 18 microns thickness
692  // Note the non-use of set_using_thickness here, this is so that the shortest dimension of the cell sets the mip energy loss
693  thresholds->set_threshold(i, 0.1);
694  }
695  // INTT
696  for (int i = n_maps_layer; i < n_maps_layer + n_intt_layer; i++)
697  {
698  thresholds->set_threshold(i, 0.1);
699  thresholds->set_use_thickness_mip(i, true);
700  }
701 
702  se->registerSubsystem(thresholds);
703 
704  //-------------
705  // Cluster Hits
706  //-------------
707 
708  PHG4SvtxClusterizer* clusterizer = new PHG4SvtxClusterizer("PHG4SvtxClusterizer", 0, n_maps_layer + n_intt_layer - 1);
709  clusterizer->Verbosity(verbosity);
710  // Reduced by 2 relative to the cylinder cell maps macro. I found this necessary to get full efficiency
711  // Many hits in the present simulation are single cell hits, so it is not clear why the cluster threshold should be higher than the cell threshold
712  clusterizer->set_threshold(0.1); // fraction of a mip
713  // no Z clustering for INTT layers (only)
714  for (int i = n_maps_layer; i < n_maps_layer + n_intt_layer; i++)
715  {
716  clusterizer->set_z_clustering(i, false);
717  }
718 
719  se->registerSubsystem(clusterizer);
720 
721  PHG4TPCClusterizer* tpcclusterizer = new PHG4TPCClusterizer();
722  tpcclusterizer->Verbosity(0);
723  tpcclusterizer->setRangeLayers(n_maps_layer + n_intt_layer, Max_si_layer);
724  if (n_gas_layer == 40)
725  {
726  tpcclusterizer->setEnergyCut(12 /*15 adc*/);
727  tpcclusterizer->setFitWindowSigmas(0.0160, 0.0160); // should be changed when TPC cluster resolution changes
728  tpcclusterizer->setFitWindowMax(4 /*rphibins*/, 6 /*zbins*/);
729  tpcclusterizer->setFitEnergyThreshold(0.05 /*fraction*/);
730  }
731  else
732  {
733  // 60 layer tune
734  tpcclusterizer->setEnergyCut(15 /*adc*/);
735  tpcclusterizer->setFitWindowSigmas(0.0150, 0.0160); // should be changed when TPC cluster resolution changes
736  tpcclusterizer->setFitWindowMax(4 /*rphibins*/, 3 /*zbins*/);
737  tpcclusterizer->setFitEnergyThreshold(0.05 /*fraction*/);
738  }
739  se->registerSubsystem(tpcclusterizer);
740 
741  // This should be true for everything except testing!
742  const bool use_kalman_pat_rec = true;
743  if (use_kalman_pat_rec)
744  {
745  //---------------------
746  // PHG4KalmanPatRec
747  //---------------------
748 
749  PHG4KalmanPatRec* kalman_pat_rec = new PHG4KalmanPatRec("PHG4KalmanPatRec", n_maps_layer, n_intt_layer, n_gas_layer);
750  kalman_pat_rec->Verbosity(0);
751  se->registerSubsystem(kalman_pat_rec);
752  }
753  else
754  {
755  //---------------------
756  // Truth Pattern Recognition
757  //---------------------
758  PHG4TruthPatRec* pat_rec = new PHG4TruthPatRec();
759  se->registerSubsystem(pat_rec);
760  }
761 
762  //---------------------
763  // Kalman Filter
764  //---------------------
765 
766  PHG4TrackKalmanFitter* kalman = new PHG4TrackKalmanFitter();
767  kalman->Verbosity(0);
768  if (use_primary_vertex)
769  kalman->set_fit_primary_tracks(true); // include primary vertex in track fit if true
770  se->registerSubsystem(kalman);
771 
772  //------------------
773  // Track Projections
774  //------------------
775  PHG4GenFitTrackProjection* projection = new PHG4GenFitTrackProjection();
776  projection->Verbosity(verbosity);
777  se->registerSubsystem(projection);
778 
779  /*
780  //----------------------
781  // Beam Spot Calculation
782  //----------------------
783  PHG4SvtxBeamSpotReco* beamspot = new PHG4SvtxBeamSpotReco();
784  beamspot->Verbosity(verbosity);
785  se->registerSubsystem( beamspot );
786  */
787 
788  return;
789 }
790 
792 {
793  cout << "\033[31;1m"
794  << "Warning: G4_Svtx_Reco() was moved to G4_Svtx.C and renamed to Svtx_Reco(), please update macros"
795  << "\033[0m" << endl;
796  Svtx_Reco();
797 
798  return;
799 }
800 
801 void Svtx_Eval(std::string outputfile, int verbosity = 0)
802 {
803  //---------------
804  // Load libraries
805  //---------------
806 
807  gSystem->Load("libfun4all.so");
808  gSystem->Load("libg4detectors.so");
809  gSystem->Load("libg4hough.so");
810  gSystem->Load("libg4eval.so");
811 
812  //---------------
813  // Fun4All server
814  //---------------
815 
817 
818  //----------------
819  // SVTX evaluation
820  //----------------
821 
822  SvtxEvaluator* eval;
823  eval = new SvtxEvaluator("SVTXEVALUATOR", outputfile.c_str());
824  eval->do_cluster_eval(true);
825  eval->do_g4hit_eval(true);
826  eval->do_hit_eval(false); // enable to see the hits that includes the chamber physics...
827  eval->do_gpoint_eval(false);
828  eval->scan_for_embedded(false); // take all tracks if false - take only embedded tracks if true
829  eval->Verbosity(verbosity);
830  se->registerSubsystem(eval);
831 
832  if (use_primary_vertex)
833  {
834  // make a second evaluator that records tracks fitted with primary vertex included
835  // good for analysis of prompt tracks, particularly if MVTX is not present
836  SvtxEvaluator* evalp;
837  evalp = new SvtxEvaluator("SVTXEVALUATOR", string(outputfile.c_str()) + "_primary_eval.root", "PrimaryTrackMap");
838  evalp->do_cluster_eval(true);
839  evalp->do_g4hit_eval(true);
840  evalp->do_hit_eval(false);
841  evalp->do_gpoint_eval(false);
842  evalp->scan_for_embedded(true); // take all tracks if false - take only embedded tracks if true
843  evalp->Verbosity(0);
844  se->registerSubsystem(evalp);
845  }
846 
847  // MomentumEvaluator* eval = new MomentumEvaluator(outputfile.c_str(),0.2,0.4,Max_si_layer,2,Max_si_layer-4,10.,80.);
848  // se->registerSubsystem( eval );
849 
850  return;
851 }