legend-pygeom-hades 0.1.0a0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. legend_pygeom_hades-0.1.0a0.dist-info/METADATA +62 -0
  2. legend_pygeom_hades-0.1.0a0.dist-info/RECORD +85 -0
  3. legend_pygeom_hades-0.1.0a0.dist-info/WHEEL +5 -0
  4. legend_pygeom_hades-0.1.0a0.dist-info/entry_points.txt +2 -0
  5. legend_pygeom_hades-0.1.0a0.dist-info/licenses/LICENSE +674 -0
  6. legend_pygeom_hades-0.1.0a0.dist-info/top_level.txt +1 -0
  7. pygeomhades/__init__.py +6 -0
  8. pygeomhades/_version.py +34 -0
  9. pygeomhades/cli.py +169 -0
  10. pygeomhades/configs/dummy_geom/B99000A.yaml +25 -0
  11. pygeomhades/configs/dummy_geom/C99000A.yaml +31 -0
  12. pygeomhades/configs/dummy_geom/P99000A.yaml +20 -0
  13. pygeomhades/configs/dummy_geom/V99000A.yaml +31 -0
  14. pygeomhades/configs/holder_wrap/B00000B.yaml +37 -0
  15. pygeomhades/configs/holder_wrap/B00000D.yaml +37 -0
  16. pygeomhades/configs/holder_wrap/B00002C.yaml +37 -0
  17. pygeomhades/configs/holder_wrap/B00032B.yaml +37 -0
  18. pygeomhades/configs/holder_wrap/B00035A.yaml +37 -0
  19. pygeomhades/configs/holder_wrap/B00035B.yaml +37 -0
  20. pygeomhades/configs/holder_wrap/B00061C.yaml +37 -0
  21. pygeomhades/configs/holder_wrap/B00076C.yaml +37 -0
  22. pygeomhades/configs/holder_wrap/B00091B.yaml +37 -0
  23. pygeomhades/configs/holder_wrap/V00048B.yaml +37 -0
  24. pygeomhades/configs/holder_wrap/V02160A.yaml +37 -0
  25. pygeomhades/configs/holder_wrap/V02160B.yaml +37 -0
  26. pygeomhades/configs/holder_wrap/V02162B.yaml +37 -0
  27. pygeomhades/configs/holder_wrap/V02166B.yaml +37 -0
  28. pygeomhades/configs/holder_wrap/V03421A.yaml +37 -0
  29. pygeomhades/configs/holder_wrap/V03422A.yaml +37 -0
  30. pygeomhades/configs/holder_wrap/V04199A.yaml +37 -0
  31. pygeomhades/configs/holder_wrap/V04545A.yaml +37 -0
  32. pygeomhades/configs/holder_wrap/V04549A.yaml +37 -0
  33. pygeomhades/configs/holder_wrap/V04549B.yaml +37 -0
  34. pygeomhades/configs/holder_wrap/V05261A.yaml +37 -0
  35. pygeomhades/configs/holder_wrap/V05261B.yaml +37 -0
  36. pygeomhades/configs/holder_wrap/V05266A.yaml +37 -0
  37. pygeomhades/configs/holder_wrap/V05266B.yaml +37 -0
  38. pygeomhades/configs/holder_wrap/V05267A.yaml +37 -0
  39. pygeomhades/configs/holder_wrap/V05267B.yaml +37 -0
  40. pygeomhades/configs/holder_wrap/V05268A.yaml +37 -0
  41. pygeomhades/configs/holder_wrap/V05268B.yaml +37 -0
  42. pygeomhades/configs/holder_wrap/V05612A.yaml +37 -0
  43. pygeomhades/configs/holder_wrap/V05612B.yaml +37 -0
  44. pygeomhades/configs/holder_wrap/V06643A.yaml +29 -0
  45. pygeomhades/configs/holder_wrap/V06649A.yaml +29 -0
  46. pygeomhades/configs/holder_wrap/V06659A.yaml +29 -0
  47. pygeomhades/configs/holder_wrap/V07298B.yaml +37 -0
  48. pygeomhades/configs/holder_wrap/V07302A.yaml +37 -0
  49. pygeomhades/configs/holder_wrap/V07302B.yaml +37 -0
  50. pygeomhades/configs/holder_wrap/V07646A.yaml +37 -0
  51. pygeomhades/configs/holder_wrap/V07647A.yaml +37 -0
  52. pygeomhades/configs/holder_wrap/V07647B.yaml +37 -0
  53. pygeomhades/configs/holder_wrap/V08682A.yaml +37 -0
  54. pygeomhades/configs/holder_wrap/V08682B.yaml +37 -0
  55. pygeomhades/configs/holder_wrap/V09372A.yaml +37 -0
  56. pygeomhades/configs/holder_wrap/V09374A.yaml +37 -0
  57. pygeomhades/configs/holder_wrap/V09724A.yaml +37 -0
  58. pygeomhades/configs/holder_wrap/V10437B.yaml +37 -0
  59. pygeomhades/configs/holder_wrap/V10447B.yaml +37 -0
  60. pygeomhades/configs/holder_wrap/V11924A.yaml +37 -0
  61. pygeomhades/configs/holder_wrap/V11925A.yaml +37 -0
  62. pygeomhades/configs/holder_wrap/V11947B.yaml +37 -0
  63. pygeomhades/configs/holder_wrap/V14673A.yaml +37 -0
  64. pygeomhades/configs/vis-scene.yaml +0 -0
  65. pygeomhades/core.py +275 -0
  66. pygeomhades/create_volumes.py +571 -0
  67. pygeomhades/dimensions.py +283 -0
  68. pygeomhades/metadata.py +28 -0
  69. pygeomhades/models/dummy/bottom_plate_dummy.gdml +44 -0
  70. pygeomhades/models/dummy/cryostat_dummy.gdml +57 -0
  71. pygeomhades/models/dummy/holder_bege_dummy.gdml +61 -0
  72. pygeomhades/models/dummy/holder_icpc_dummy.gdml +78 -0
  73. pygeomhades/models/dummy/lead_castle_table1_dummy.gdml +71 -0
  74. pygeomhades/models/dummy/lead_castle_table2_dummy.gdml +73 -0
  75. pygeomhades/models/dummy/source_am_collimated_dummy.gdml +97 -0
  76. pygeomhades/models/dummy/source_am_dummy.gdml +64 -0
  77. pygeomhades/models/dummy/source_ba_dummy.gdml +72 -0
  78. pygeomhades/models/dummy/source_co_dummy.gdml +71 -0
  79. pygeomhades/models/dummy/source_holder_am_dummy.gdml +73 -0
  80. pygeomhades/models/dummy/source_holder_dummy.gdml +61 -0
  81. pygeomhades/models/dummy/source_holder_th_lat_dummy.gdml +54 -0
  82. pygeomhades/models/dummy/source_th_dummy.gdml +134 -0
  83. pygeomhades/models/dummy/source_th_plates_dummy.gdml +36 -0
  84. pygeomhades/models/dummy/wrap_dummy.gdml +50 -0
  85. pygeomhades/utils.py +101 -0
@@ -0,0 +1,571 @@
1
+ from __future__ import annotations
2
+
3
+ from importlib import resources
4
+
5
+ import numpy as np
6
+ from dbetto import AttrsDict
7
+ from pyg4ometry import geant4
8
+
9
+ from pygeomhades.utils import read_gdml_with_replacements
10
+
11
+
12
+ def create_vacuum_cavity(cryostat_metadata: AttrsDict, registry: geant4.Registry) -> geant4.LogicalVolume:
13
+ """Construct the vacuum cavity.
14
+
15
+ Parameters
16
+ ----------
17
+ cryostat_metadata
18
+ The dimensions of the various parts of the cryostat, should have
19
+ the following format
20
+
21
+ .. code-block:: yaml
22
+
23
+ cryostat:
24
+ width: 200
25
+ thickness: 2
26
+ height: 200
27
+ position_cavity_from_top: 10
28
+ position_cavity_from_bottom: 20,
29
+ position_from_bottom: 100
30
+
31
+ registry
32
+ The registry to add the geometry to.
33
+
34
+ Returns
35
+ -------
36
+ The logical volume for the cavity.
37
+ """
38
+ vacuum_cavity_radius = (cryostat_metadata["width"] - 2 * cryostat_metadata["thickness"]) / 2
39
+ vacuum_cavity_z = (
40
+ cryostat_metadata["height"]
41
+ - cryostat_metadata["position_cavity_from_top"]
42
+ - cryostat_metadata["position_cavity_from_bottom"]
43
+ )
44
+ vacuum_cavity = geant4.solid.GenericPolycone(
45
+ "vacuum_cavity",
46
+ 0.0,
47
+ 2.0 * np.pi,
48
+ pR=([0.0, vacuum_cavity_radius, vacuum_cavity_radius, 0.0]),
49
+ pZ=[0.0, 0.0, vacuum_cavity_z, vacuum_cavity_z],
50
+ lunit="mm",
51
+ aunit="rad",
52
+ registry=registry,
53
+ )
54
+ return geant4.LogicalVolume(vacuum_cavity, "G4_Galactic", "cavity_lv", registry)
55
+
56
+
57
+ def create_wrap(wrap_metadata: AttrsDict, from_gdml: bool = False) -> geant4.LogicalVolume:
58
+ """Create the mylar wrap.
59
+
60
+ .. warning::
61
+
62
+ The returned logical volume belongs to its own registry,
63
+ it is necessary to call :func:`reg.addVolumeRecursive` on
64
+ the produced PhysicalVolume to get a sane registry.
65
+
66
+ Parameters
67
+ ----------
68
+ wrap_metadata
69
+ The information on the dimensions of the mylar wrap,
70
+ should be of the format:
71
+
72
+ .. code-block:: yaml
73
+
74
+ outer:
75
+ height_in_mm: 100
76
+ radius_in_mm: 100
77
+ inner:
78
+ height_in_mm: 99
79
+ radius_in_mm: 99
80
+
81
+ from_gdml
82
+ whether to read the geometry from GDML or construct it directly.
83
+ """
84
+ if from_gdml:
85
+ dummy_gdml_path = resources.files("pygeomhades") / "models" / "dummy" / "wrap_dummy.gdml"
86
+
87
+ replacements = {
88
+ "wrap_outer_height_in_mm": wrap_metadata.outer.height_in_mm,
89
+ "wrap_outer_radius_in_mm": wrap_metadata.outer.radius_in_mm,
90
+ "wrap_inner_radius_in_mm": wrap_metadata.inner.radius_in_mm,
91
+ "wrap_top_thickness_in_mm": wrap_metadata.outer.height_in_mm - wrap_metadata.inner.height_in_mm,
92
+ }
93
+ wrap_lv = read_gdml_with_replacements(dummy_gdml_path, replacements)
94
+ else:
95
+ msg = "cannot construct geometry without the gdml for now"
96
+ raise NotImplementedError(msg)
97
+
98
+ return wrap_lv
99
+
100
+
101
+ def create_holder(holder_meta: AttrsDict, det_type: str, from_gdml: bool = True) -> geant4.LogicalVolume:
102
+ """Construct the holder geometry
103
+
104
+ Parameters
105
+ ----------
106
+ holder_meta
107
+ The metadata describing the holder geometry, should be of the format:
108
+
109
+ .. code-block:: yaml
110
+
111
+ cylinder:
112
+ inner:
113
+ height_in_mm: 100
114
+ radius_in_mm: 100
115
+ outer:
116
+ height_in_mm: 104
117
+ radius_in_mm: 104
118
+ bottom_cyl:
119
+ inner:
120
+ height_in_mm: 100
121
+ radius_in_mm: 100
122
+ outer:
123
+ height_in_mm: 104
124
+ radius_in_mm: 104
125
+ rings:
126
+ position_top_ring_in_mm: 20
127
+ position_bottom_ring_in_mm: 30
128
+ radius_in_mm: 150
129
+ height_in_mm: 10
130
+ edge:
131
+ height_in_mm: 1000
132
+
133
+ det_type
134
+ Detector type.
135
+ from_gdml
136
+ Whether to construct from a GDML file
137
+
138
+ """
139
+
140
+ if not from_gdml:
141
+ msg = "cannot construct geometry without the gdml for now"
142
+ raise NotImplementedError(msg)
143
+
144
+ if det_type == "icpc":
145
+ dummy_gdml_path = resources.files("pygeomhades") / "models" / "dummy" / "holder_icpc_dummy.gdml"
146
+
147
+ rings = holder_meta["rings"]
148
+ cylinder = holder_meta["cylinder"]
149
+ bottom_cylinder = holder_meta["bottom_cyl"]
150
+
151
+ replacements = {
152
+ "max_radius_in_mm": rings.radius_in_mm,
153
+ "outer_height_in_mm": cylinder.outer.height_in_mm,
154
+ "inner_height_in_mm": cylinder.inner.height_in_mm,
155
+ "outer_radius_in_mm": cylinder.outer.radius_in_mm,
156
+ "inner_radius_in_mm": cylinder.inner.radius_in_mm,
157
+ "outer_bottom_cyl_radius_in_mm": bottom_cylinder.outer.radius_in_mm,
158
+ "inner_bottom_cyl_radius_in_mm": bottom_cylinder.inner.radius_in_mm,
159
+ "edge_height_in_mm": holder_meta.edge.height_in_mm,
160
+ "pos_top_ring_in_mm": rings.position_top_ring_in_mm,
161
+ "pos_bottom_ring_in_mm": rings.position_bottom_ring_in_mm,
162
+ "end_top_ring_in_mm": rings.position_top_ring_in_mm + rings.height_in_mm,
163
+ "end_bottom_ring_in_mm": rings.position_bottom_ring_in_mm + rings.height_in_mm,
164
+ "end_bottom_cyl_outer_in_mm": cylinder.outer.height_in_mm + bottom_cylinder.outer.height_in_mm,
165
+ "end_bottom_cyl_inner_in_mm": cylinder.inner.height_in_mm + bottom_cylinder.inner.height_in_mm,
166
+ }
167
+
168
+ elif det_type == "bege":
169
+ dummy_gdml_path = resources.files("pygeomhades") / "models" / "dummy" / "holder_bege_dummy.gdml"
170
+
171
+ rings = holder_meta["rings"]
172
+ cylinder = holder_meta["cylinder"]
173
+ bottom_cylinder = holder_meta["bottom_cyl"]
174
+
175
+ replacements = {
176
+ "max_radius_in_mm": rings.radius_in_mm,
177
+ "outer_height_in_mm": cylinder.outer.height_in_mm,
178
+ "inner_height_in_mm": cylinder.inner.height_in_mm,
179
+ "outer_radius_in_mm": cylinder.outer.radius_in_mm,
180
+ "inner_radius_in_mm": cylinder.inner.radius_in_mm,
181
+ "position_top_ring_in_mm": rings.position_top_ring_in_mm,
182
+ "end_top_ring_in_mm": rings.height_in_mm + rings.position_top_ring_in_mm,
183
+ }
184
+ else:
185
+ msg = "cannot construct geometry for coax or ppc"
186
+ raise NotImplementedError(msg)
187
+
188
+ return read_gdml_with_replacements(dummy_gdml_path, replacements)
189
+
190
+
191
+ def create_bottom_plate(plate_metadata: AttrsDict, from_gdml: bool = True) -> geant4.Registry:
192
+ """Create the bottom plate.
193
+
194
+ Parameters
195
+ ----------
196
+ plate_metadata
197
+ Metadata describing the position of the bottom plate.
198
+ This should have the format:
199
+
200
+ .. code-block:: yaml
201
+
202
+ width: 100
203
+ depth: 200
204
+ height: 300
205
+ cavity:
206
+ width: 100
207
+ depth: 200
208
+ height: 200
209
+ from_gdml
210
+ Whether to construct from a GDML file
211
+
212
+ """
213
+ if not from_gdml:
214
+ msg = "cannot construct geometry without the gdml for now"
215
+ raise NotImplementedError(msg)
216
+
217
+ dummy_gdml_path = resources.files("pygeomhades") / "models" / "dummy" / "bottom_plate_dummy.gdml"
218
+
219
+ replacements = {
220
+ "bottom_plate_width": plate_metadata.width,
221
+ "bottom_plate_depth": plate_metadata.depth,
222
+ "bottom_plate_height": plate_metadata.height,
223
+ "bottom_cavity_plate_width": plate_metadata.cavity.width,
224
+ "bottom_cavity_plate_depth": plate_metadata.cavity.depth,
225
+ "bottom_cavity_plate_height": plate_metadata.cavity.height,
226
+ }
227
+ return read_gdml_with_replacements(dummy_gdml_path, replacements)
228
+
229
+
230
+ def create_lead_castle(
231
+ table_num: int, castle_dimensions: AttrsDict, from_gdml: bool = True, volume_name: str = "Lead_castle"
232
+ ) -> geant4.LogicalVolume:
233
+ """Create the lead castle.
234
+
235
+ Parameters
236
+ ----------
237
+ table_num
238
+ Which table the measurements were taken on (1 or 2).
239
+ castle_dimensions
240
+ The metadata describing the lead castle dimensions. This should
241
+ have the fields "base", "inner_cavity", "cavity",
242
+ "top", "front" and "copper_plate".
243
+
244
+ Each should have a subdictionary with this format:
245
+
246
+ .. code-block:: yaml
247
+
248
+ base:
249
+ height: 100
250
+ depth: 100
251
+ width: 100
252
+ volume_name
253
+ Which volume to extract, defaults to "Lead_castle".
254
+
255
+ from_gdml
256
+ Whether to construct from a GDML file
257
+ """
258
+
259
+ if not from_gdml:
260
+ msg = "cannot construct geometry without the gdml for now"
261
+ raise NotImplementedError(msg)
262
+
263
+ if table_num not in [1, 2]:
264
+ msg = f"Table number must be 1 or 2, not {table_num}"
265
+ raise ValueError(msg)
266
+
267
+ dummy_gdml_path = (
268
+ resources.files("pygeomhades") / "models" / "dummy" / f"lead_castle_table{table_num}_dummy.gdml"
269
+ )
270
+
271
+ if table_num == 1:
272
+ replacements = {
273
+ "base_width_1": castle_dimensions.base.width,
274
+ "base_depth_1": castle_dimensions.base.depth,
275
+ "base_height_1": castle_dimensions.base.height,
276
+ "inner_cavity_width_1": castle_dimensions.inner_cavity.width,
277
+ "inner_cavity_depth_1": castle_dimensions.inner_cavity.depth,
278
+ "inner_cavity_height_1": castle_dimensions.inner_cavity.height,
279
+ "cavity_width_1": castle_dimensions.cavity.width,
280
+ "cavity_depth_1": castle_dimensions.cavity.depth,
281
+ "cavity_height_1": castle_dimensions.cavity.height,
282
+ "top_width_1": castle_dimensions.top.width,
283
+ "top_depth_1": castle_dimensions.top.depth,
284
+ "top_height_1": castle_dimensions.top.height,
285
+ "front_width_1": castle_dimensions.front.width,
286
+ "front_depth_1": castle_dimensions.front.depth,
287
+ "front_height_1": castle_dimensions.front.height,
288
+ }
289
+
290
+ elif table_num == 2:
291
+ replacements = {
292
+ "base_width_2": castle_dimensions.base.width,
293
+ "base_depth_2": castle_dimensions.base.depth,
294
+ "base_height_2": castle_dimensions.base.height,
295
+ "inner_cavity_width_2": castle_dimensions.inner_cavity.width,
296
+ "inner_cavity_depth_2": castle_dimensions.inner_cavity.depth,
297
+ "inner_cavity_height_2": castle_dimensions.inner_cavity.height,
298
+ "top_width_2": castle_dimensions.top.width,
299
+ "top_depth_2": castle_dimensions.top.depth,
300
+ "top_height_2": castle_dimensions.top.height,
301
+ "copper_plate_width": castle_dimensions.copper_plate.width,
302
+ "copper_plate_depth": castle_dimensions.copper_plate.depth,
303
+ "copper_plate_height": castle_dimensions.copper_plate.height,
304
+ }
305
+
306
+ return read_gdml_with_replacements(dummy_gdml_path, replacements, vol_name=volume_name)
307
+
308
+
309
+ def create_source(
310
+ source_type: str, source_dims: AttrsDict, holder_dims: AttrsDict | None, from_gdml: bool = False
311
+ ) -> geant4.LogicalVolume:
312
+ """Create the geometry of the source.
313
+
314
+ Parameters
315
+ ----------
316
+ source_type
317
+ The type of source (am_collimated, am, ba, co or th)
318
+ source_dims
319
+ Metadata describing the source geometry.
320
+ Should be of the following format:
321
+
322
+ .. code-block:: yaml
323
+
324
+ height: 0.0
325
+ width: 0.0
326
+
327
+ foil:
328
+ height: 0.0
329
+ width: 0.0
330
+
331
+ al_ring:
332
+ height: 0.0
333
+ width_max: 0.0
334
+ width_min: 0.0
335
+
336
+ capsule:
337
+ width: 0.0
338
+ depth: 0.0
339
+ height: 0.0
340
+
341
+ collimator:
342
+ width: 0.0
343
+ depth: 0.0
344
+ height: 0.0
345
+ beam_width: 0.0
346
+ beam_height: 0.0
347
+ window: 0.0
348
+
349
+ epoxy:
350
+ height: 0.0
351
+ width: 0.0
352
+
353
+ plates:
354
+ height: 0.0
355
+ width: 0.0
356
+ cavity_width: 0.0
357
+
358
+ offset_height: 0.0
359
+
360
+ holder_dims
361
+ Dimensions of the source holder (see :func:`get_source_holder`).
362
+
363
+ from_gdml
364
+ Whether to construct from a GDML file
365
+ """
366
+
367
+ if not from_gdml:
368
+ msg = "cannot construct geometry without the gdml for now"
369
+ raise NotImplementedError(msg)
370
+
371
+ dummy_gdml_path = resources.files("pygeomhades") / "models" / "dummy" / f"source_{source_type}_dummy.gdml"
372
+
373
+ if source_type == "am_collimated":
374
+ replacements = {
375
+ "source_height": source_dims.height,
376
+ "source_width": source_dims.width,
377
+ "source_capsule_height": source_dims.capsule.height,
378
+ "source_capsule_width": source_dims.capsule.width,
379
+ "window_source": source_dims.collimator.window,
380
+ "collimator_height": source_dims.collimator.height,
381
+ "collimator_depth": source_dims.collimator.depth,
382
+ "collimator_width": source_dims.collimator.width,
383
+ "collimator_beam_height": source_dims.collimator.beam_height,
384
+ "collimator_beam_width": source_dims.collimator.beam_width,
385
+ }
386
+
387
+ elif source_type == "am":
388
+ replacements = {
389
+ "source_height": source_dims.height,
390
+ "source_width": source_dims.width,
391
+ "source_capsule_height": source_dims.capsule.height,
392
+ "source_capsule_width": source_dims.capsule.width,
393
+ "source_capsule_depth": source_dims.capsule.depth,
394
+ }
395
+
396
+ elif source_type in ["ba", "co"]:
397
+ replacements = {
398
+ "source_height": source_dims.height,
399
+ "source_width": source_dims.width,
400
+ "source_foil_height": source_dims.foil.height,
401
+ "source_Alring_height": source_dims.al_ring.height,
402
+ "source_Alring_width_min": source_dims.al_ring.width_min,
403
+ "source_Alring_width_max": source_dims.al_ring.width_max,
404
+ }
405
+
406
+ elif source_type == "th":
407
+ replacements = {
408
+ "source_height": source_dims.height,
409
+ "source_width": source_dims.width,
410
+ "source_capsule_height": source_dims.capsule.height,
411
+ "source_capsule_width": source_dims.capsule.width,
412
+ "source_epoxy_height": source_dims.epoxy.height,
413
+ "source_epoxy_width": source_dims.epoxy.width,
414
+ "CuSource_holder_height": holder_dims.copper.height,
415
+ "CuSource_holder_width": holder_dims.copper.width,
416
+ "CuSource_holder_cavity_width": holder_dims.copper.cavity_width,
417
+ "CuSource_holder_bottom_height": holder_dims.copper.bottom_height,
418
+ "CuSource_holder_bottom_width": holder_dims.copper.bottom_width,
419
+ "source_offset_height": source_dims.offset_height,
420
+ }
421
+
422
+ else:
423
+ msg = f"source type of {source_type} is not defined."
424
+ raise RuntimeError(msg)
425
+
426
+ return read_gdml_with_replacements(dummy_gdml_path, replacements)
427
+
428
+
429
+ def create_th_plate(source_dims: AttrsDict, from_gdml: bool = False) -> geant4.LogicalVolume:
430
+ """Construct the plate for the Th source
431
+
432
+ Parameters
433
+ ----------
434
+ source_dims
435
+ See :func:`create_source` for more information.
436
+ from_gdml
437
+ Whether to construct from a GDML file
438
+
439
+ """
440
+ if not from_gdml:
441
+ msg = "cannot construct geometry without the gdml for now"
442
+ raise NotImplementedError(msg)
443
+
444
+ dummy_gdml_path = resources.files("pygeomhades") / "models" / "dummy" / "source_th_plates_dummy.gdml"
445
+ source = source_dims
446
+
447
+ replacements = {
448
+ "source_plates_height": source.plates.height,
449
+ "source_plates_width": source.plates.width,
450
+ "source_plates_cavity_width": source.plates.cavity_width,
451
+ }
452
+
453
+ return read_gdml_with_replacements(dummy_gdml_path, replacements)
454
+
455
+
456
+ def create_source_holder(
457
+ source_type: str, holder_dims: AttrsDict, source_z: float, meas_type: str = "lat", from_gdml: bool = True
458
+ ) -> geant4.LogicalVolume:
459
+ """Get the source holder geometry.
460
+
461
+ Parameters
462
+ ----------
463
+ source_type
464
+ The type of source (am_collimated, am, ba, co or th)
465
+ holder_dims
466
+ The dimensions of the source holder, should be of the format:
467
+
468
+ .. code-block:: yaml
469
+
470
+ source:
471
+ top_plate_height: 10.0
472
+ top_plate_width: 10.0
473
+ top_height: 2.0
474
+ top_inner_width: 2.0
475
+ top_bottom_height: 2.0
476
+ bottom_inner_width: 2.0
477
+ outer_width: 100.0
478
+ inner_width: 10.0
479
+
480
+
481
+ meas_type
482
+ The measurement type (for th only) either lat or top.
483
+ source_z
484
+ The z position of the source from the cryostat bottom.
485
+ from_gdml
486
+ Whether to construct from a GDML file
487
+ """
488
+
489
+ if not from_gdml:
490
+ msg = "cannot construct geometry without the gdml for now"
491
+ raise NotImplementedError(msg)
492
+
493
+ source_holder = holder_dims
494
+ dummy_path = resources.files("pygeomhades") / "models" / "dummy"
495
+
496
+ if source_type == "th" and meas_type == "lat":
497
+ dummy_gdml_path = dummy_path / "source_holder_th_lat_dummy.gdml"
498
+
499
+ replacements = {
500
+ "cavity_source_holder_height": source_holder.source.cavity_height,
501
+ "source_holder_height": source_holder.source.height,
502
+ "source_holder_outer_width": source_holder.outer_width,
503
+ "source_holder_inner_width": source_holder.inner_width,
504
+ "cavity_source_holder_width": source_holder.holder_width,
505
+ }
506
+
507
+ elif source_type in ["am_collimated", "ba", "co", "th"]:
508
+ dummy_gdml_path = dummy_path / "source_holder_dummy.gdml"
509
+
510
+ replacements = {
511
+ "source_holder_top_plate_height": source_holder.source.top_plate_height,
512
+ "source_holder_top_height": source_holder.source.top_height,
513
+ "source_holder_topbottom_height": source_holder.source.top_bottom_height,
514
+ "source_holder_top_plate_width": source_holder.source.top_plate_width,
515
+ "source_holder_top_inner_width": source_holder.source.top_inner_width,
516
+ "source_holder_inner_width": source_holder.inner_width,
517
+ "source_holder_bottom_inner_width": source_holder.source.bottom_inner_width,
518
+ "source_holder_outer_width": source_holder.outer_width,
519
+ "position_source_fromcryostat_z": source_z,
520
+ }
521
+
522
+ elif source_type == "am":
523
+ dummy_gdml_path = dummy_path / "source_holder_am_dummy.gdml"
524
+
525
+ replacements = {
526
+ "source_holder_top_height": source_holder.source.top_height,
527
+ "position_source_fromcryostat_z": source_z,
528
+ "source_holder_top_plate_height": source_holder.source.top_plate_height,
529
+ "source_holder_top_plate_width": source_holder.source.top_plate_width,
530
+ "source_holder_top_plate_depth": source_holder.source.top_plate_depth,
531
+ "source_holder_topbottom_height": source_holder.source.top_bottom_height,
532
+ "source_holder_top_inner_width": source_holder.source.top_inner_width,
533
+ "source_holder_top_inner_depth": source_holder.source.top_inner_depth,
534
+ "source_holder_inner_width": source_holder.inner_width,
535
+ "source_holder_bottom_inner_width": source_holder.source.bottom_inner_width,
536
+ "source_holder_outer_width": source_holder.outer_width,
537
+ }
538
+
539
+ else:
540
+ msg = f"source type {source_type} not implemented."
541
+ raise RuntimeError(msg)
542
+
543
+ return read_gdml_with_replacements(dummy_gdml_path, replacements)
544
+
545
+
546
+ def create_cryostat(cryostat_meta: AttrsDict, from_gdml: bool = True) -> geant4.LogicalVolume:
547
+ """Create the cryostat logical volume.
548
+
549
+ Parameters
550
+ ----------
551
+ cryostat_meta
552
+ Metadata describing the cryostat geometry (see :func:`create_wrap`) for details.
553
+ from_gdml
554
+ Whether to construct from a GDML file
555
+
556
+ """
557
+
558
+ if not from_gdml:
559
+ msg = "cannot construct geometry without the gdml for now"
560
+ raise NotImplementedError(msg)
561
+
562
+ dummy_gdml_path = resources.files("pygeomhades") / "models" / "dummy" / "cryostat_dummy.gdml"
563
+
564
+ replacements = {
565
+ "cryostat_height": cryostat_meta.height,
566
+ "cryostat_width": cryostat_meta.width,
567
+ "cryostat_thickness": cryostat_meta.thickness,
568
+ "position_cryostat_cavity_fromTop": cryostat_meta.position_cavity_from_top,
569
+ "position_cryostat_cavity_fromBottom": cryostat_meta.position_cavity_from_bottom,
570
+ }
571
+ return read_gdml_with_replacements(dummy_gdml_path, replacements)