Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
odd_light.py
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file odd_light.py
1 import math
2 import acts
3 import argparse
4 import acts.examples
5 import acts.examples.detector as detector
6 from acts.examples import geant4 as acts_g4
7 
8 from acts import (
9  Binning,
10  DetectorBuilder,
11  GeometryIdGenerator,
12  Extent,
13  GeometryContext,
14  KdtSurfaces2D,
15  KdtSurfacesProvider2D,
16  IndexedRootVolumeFinderBuilder,
17  ProtoBinning,
18 )
19 
20 
21 def necBarrelPec(
22  name,
23  rRange,
24  zDivisions,
25  sensitivesKdt,
26  necPositionsZ,
27  necHalfThickness,
28  necBinning,
29  barrelPositionsR,
30  barrelHalfThickness,
31  barrelBinnings,
32  containerIds=[],
33  llevel=acts.logging.INFO,
34 ):
35 
36  # Negative Endcap
37  necEndcapExtent = Extent([[Binning.r, rRange], [Binning.z, zDivisions[0:2]]])
38 
39  necLayers = []
40  for zPos in necPositionsZ:
41  ilay = len(necLayers)
42  lExtent = Extent(
43  [
44  [Binning.r, rRange],
45  [Binning.z, [zPos - necHalfThickness, zPos + necHalfThickness]],
46  ]
47  )
48  provider = KdtSurfacesProvider2D(sensitivesKdt, lExtent)
49  necLayers += [
51  "lay_" + str(ilay), lExtent, provider, necBinning, [], llevel
52  )
53  ]
54 
55  necGig = None
56  if len(containerIds) > 0:
57  necGigConf = GeometryIdGenerator.Config()
58  necGigConf.containerMode = True
59  necGigConf.containerId = containerIds[0]
60  necGig = GeometryIdGenerator(necGigConf, name + "_nec_gig", llevel)
61 
63  name=name + "_nec",
64  extent=necEndcapExtent,
65  volumes=None,
66  layers=necLayers,
67  binning=Binning.z,
68  rootbuilder=None,
69  geoidgenerator=necGig,
70  reversegeoids=True,
71  loglevel=llevel,
72  )
73 
74  # Barrel
75  barrelExtent = Extent([[Binning.r, rRange], [Binning.z, zDivisions[1:3]]])
76 
77  # Create the barrel layers
78  barrelLayers = []
79  for layerR in barrelPositionsR:
80  ilay = len(barrelLayers)
81  lExtent = Extent(
82  [
83  [
84  Binning.r,
85  [layerR - barrelHalfThickness, layerR + barrelHalfThickness],
86  ],
87  [Binning.z, zDivisions[1:3]],
88  ]
89  )
90  provider = KdtSurfacesProvider2D(sensitivesKdt, lExtent)
91  binning = barrelBinnings[ilay]
92  barrelLayers += [
94  "lay_" + str(ilay), lExtent, provider, binning, [], llevel
95  )
96  ]
97 
98  barrelGig = None
99  if len(containerIds) > 1:
100  barrelGiConfg = GeometryIdGenerator.Config()
101  barrelGiConfg.containerMode = True
102  barrelGiConfg.containerId = containerIds[1]
103  barrelGig = GeometryIdGenerator(barrelGiConfg, name + "_barrel_gig", llevel)
104 
106  name=name + "_barrel",
107  extent=barrelExtent,
108  volumes=None,
109  layers=barrelLayers,
110  binning=Binning.r,
111  rootbuilder=None,
112  geoidgenerator=barrelGig,
113  reversegeoids=False,
114  loglevel=llevel,
115  )
116 
117  # Positive Endcap
118  pecEndcapExtent = Extent([[Binning.r, rRange], [Binning.z, zDivisions[2:4]]])
119  necPositionsZ.reverse()
120 
121  pecLayers = []
122  for zPos in necPositionsZ:
123  ilay = len(pecLayers)
124  lExtent = Extent(
125  [
126  [Binning.r, rRange],
127  [
128  Binning.z,
129  [-1 * zPos - necHalfThickness, -1 * zPos + necHalfThickness],
130  ],
131  ]
132  )
133  provider = KdtSurfacesProvider2D(sensitivesKdt, lExtent)
134  pecLayers += [
136  "lay_" + str(ilay), lExtent, provider, necBinning, [], llevel
137  )
138  ]
139 
140  pecGig = None
141  if len(containerIds) > 2:
142  pecGigConf = GeometryIdGenerator.Config()
143  pecGigConf.containerMode = True
144  pecGigConf.containerId = containerIds[2]
145  pecGig = GeometryIdGenerator(pecGigConf, name + "_pec_gig", llevel)
146 
148  name=name + "_pec",
149  extent=pecEndcapExtent,
150  volumes=None,
151  layers=pecLayers,
152  binning=Binning.z,
153  rootbuilder=None,
154  geoidgenerator=pecGig,
155  reversegeoids=False,
156  loglevel=llevel,
157  )
158 
159  # Build the nec - barrel - pec container
161  name=name,
162  extent=None,
163  volumes=[nec, barrel, pec],
164  layers=None,
165  binning=Binning.z,
166  rootbuilder=None,
167  geoidgenerator=None,
168  loglevel=llevel,
169  )
170 
171 
172 def get_detector(geoContext, ssurfaces, psurfaces, llevel=acts.logging.DEBUG):
173 
174  # Build the geometry context & a kdtree for the surfaces
175  sensitivesKdt = KdtSurfaces2D(geoContext, ssurfaces, [Binning.z, Binning.r])
176  passivesKdt = KdtSurfaces2D(geoContext, psurfaces, [Binning.z, Binning.r])
177 
178  # Detector section ############################################################
179  detRrange = [0, 1100]
180  detZrange = [-3100, 3100]
181 
182  # Beam pipe section ###########################################################
183  bpRrange = [detRrange[0], 25.0]
184  bpExtent = Extent([[Binning.r, bpRrange], [Binning.z, detZrange]])
185  bpProvider = KdtSurfacesProvider2D(passivesKdt, bpExtent)
186  bpBinning = [ProtoBinning(Binning.r, Binning.bound, 0, 25, 1, 0)]
188  "ODD_beampipe", bpExtent, bpProvider, bpBinning, [], llevel
189  )
190 
191  # Pixel section ###############################################################
192  pixRrange = [25, 190]
193  pixZdivisions = [detZrange[0], -590, 590, detZrange[1]]
194  pixNecPositionsZ = [-1520, -1320, -1120, -980, -840, -720, -620]
195  pixNecHalfThickness = 5
196  pixNecBinning = [
197  ProtoBinning(Binning.r, Binning.bound, 40, 175, 2, 1),
198  detector.phiBinning(56, 1),
199  ]
200  pixBarrelPositionsR = [34, 70, 116, 172]
201  pixBarrelHalfThickness = 5
202  pixBarrelZbinning = ProtoBinning(Binning.z, Binning.bound, -500, 500, 14, 1)
203  pixBarrelPhiBinnings = [[16, 1], [32, 1], [52, 1], [78, 1]]
204  pixBarrelBinning = [
205  [pixBarrelZbinning, detector.phiBinning(phiBinning[0], phiBinning[1])]
206  for phiBinning in pixBarrelPhiBinnings
207  ]
208 
209  pix = necBarrelPec(
210  "ODD_pixel",
211  pixRrange,
212  pixZdivisions,
213  sensitivesKdt,
214  pixNecPositionsZ,
215  pixNecHalfThickness,
216  pixNecBinning,
217  pixBarrelPositionsR,
218  pixBarrelHalfThickness,
219  pixBarrelBinning,
220  [16, 17, 18],
221  llevel,
222  )
223 
224  # PST section #################################################################
225  pstRrange = [pixRrange[1], 220]
226  pstExtent = Extent([[Binning.r, pstRrange], [Binning.z, detZrange]])
227  pstProvider = KdtSurfacesProvider2D(passivesKdt, pstExtent)
228  pstBinning = [ProtoBinning(Binning.r, Binning.bound, pixRrange[1], 220, 1, 0)]
230  "ODD_pst", pstExtent, pstProvider, pstBinning, [], llevel
231  )
232 
233  # Short strip section #########################################################
234  sstripRrange = [pstRrange[1], 720]
235  sstripZdivisions = [detZrange[0], -1250, 1250, detZrange[1]]
236 
237  sstripNecPositionsZ = [-2950, -2550, -2200, -1850, -1550, -1300]
238  sstripNecHalfThickness = 15
239  sstripNecBinning = [
240  ProtoBinning(Binning.r, Binning.bound, 230, 710, 3, 1),
241  detector.phiBinning(40, 1),
242  ]
243  sstripBarrelPositionsR = [260, 360, 500, 660]
244  sstripBarrelHalfThickness = 25
245  sstripBarrelZbinning = ProtoBinning(Binning.z, Binning.bound, -1100, 1100, 21, 1)
246  sstripBarrelPhiBinnings = [[40, 1], [56, 1], [78, 1], [102, 1]]
247  sstripBarrelBinning = [
248  [sstripBarrelZbinning, detector.phiBinning(phiBinning[0], phiBinning[1])]
249  for phiBinning in sstripBarrelPhiBinnings
250  ]
251 
252  sstrip = necBarrelPec(
253  "ODD_sstrip",
254  sstripRrange,
255  sstripZdivisions,
256  sensitivesKdt,
257  sstripNecPositionsZ,
258  sstripNecHalfThickness,
259  sstripNecBinning,
260  sstripBarrelPositionsR,
261  sstripBarrelHalfThickness,
262  sstripBarrelBinning,
263  [23, 24, 25],
264  llevel,
265  )
266 
267  # Long strip section ##########################################################
268 
269  lstripRrange = [sstripRrange[1], detRrange[1]]
270  lstripZdivisions = [detZrange[0], -1250, 1250, detZrange[1]]
271 
272  lstripNecPositionsZ = [-3000, -2600, -2250, -1900, -1600, -1300]
273  lstripNecHalfThickness = 15
274  lstripNecBinning = [
275  ProtoBinning(Binning.r, Binning.bound, 720, 1020, 2, 1),
276  detector.phiBinning(40, 1),
277  ]
278  lstripBarrelPositionsR = [830, 1030]
279  lstripBarrelHalfThickness = 35
280  lstripBarrelZbinning = ProtoBinning(Binning.z, Binning.bound, -1100, 1100, 21, 1)
281  lstripBarrelPhiBinnings = [[40, 1], [56, 1]]
282  lstripBarrelBinning = [
283  [lstripBarrelZbinning, detector.phiBinning(phiBinning[0], phiBinning[1])]
284  for phiBinning in lstripBarrelPhiBinnings
285  ]
286 
287  lstrip = necBarrelPec(
288  "ODD_lstrip",
289  lstripRrange,
290  lstripZdivisions,
291  sensitivesKdt,
292  lstripNecPositionsZ,
293  lstripNecHalfThickness,
294  lstripNecBinning,
295  lstripBarrelPositionsR,
296  lstripBarrelHalfThickness,
297  lstripBarrelBinning,
298  [28, 29, 30],
299  llevel,
300  )
301 
302  # Root builder from the detector container
303  rootBuilder = IndexedRootVolumeFinderBuilder([Binning.z, Binning.r])
304 
306  name="ODD",
307  extent=None,
308  volumes=[bp, pix, pst, sstrip, lstrip],
309  layers=None,
310  binning=Binning.r,
311  rootbuilder=rootBuilder,
312  geoidgenerator=None,
313  loglevel=llevel,
314  )
315 
316  # All objects that do not have a geometry id will be assigned one
317  gigConfig = GeometryIdGenerator.Config()
318  gigConfig.overrideExistingIds = False
319  gigConfig.resetSubCounters = True
320  gig = GeometryIdGenerator(gigConfig, "GeometryIdGenerator", llevel)
321 
322  # Full detector configuration
323  detConfig = DetectorBuilder.Config()
324  detConfig.name = "ODD"
325  detConfig.builder = det.builder()
326  detConfig.geoIdGenerator = gig
327  detConfig.auxiliary = "Detector[" + detConfig.name + "]"
328 
329  detBuilder = DetectorBuilder(detConfig, detConfig.auxiliary, llevel)
330  return detBuilder.construct(geoContext)
331 
332 
333 def main():
334  # Parse the command line arguments
335  p = argparse.ArgumentParser()
336  p.add_argument(
337  "-i",
338  "--input",
339  type=str,
340  default="odd-light.gdml",
341  help="GDML input file.",
342  )
343  p.add_argument(
344  "-s",
345  "--sensitives",
346  type=str,
347  default="phys_vol",
348  help="Match string for sensitive surfaces",
349  )
350  p.add_argument(
351  "-p",
352  "--passives",
353  type=str,
354  default="pass_vol",
355  help="Match string for passive surfaces",
356  )
357  args = p.parse_args()
358  geoContext = GeometryContext()
359 
360  # Convert the detector surfaces to GDML
361  [elements, ssurfaces, psurfaces] = acts_g4.convertSurfaces(
362  args.input, [args.sensitives], [args.passives]
363  )
364  odd_light = get_detector(geoContext, ssurfaces, psurfaces, acts.logging.DEBUG)
365 
366 
367 if "__main__" == __name__:
368  main()