6import hepunit
as G4Unit
10ROOT.gROOT.ProcessLine(
'#include "Geant4/G4TransportationManager.hh"')
11ROOT.gROOT.ProcessLine(
'#include "Geant4/G4FieldManager.hh"')
12ROOT.gROOT.ProcessLine(
'#include "Geant4/G4UIterminal.hh"')
13ROOT.gROOT.ProcessLine(
'#include "Geant4/G4RunManager.hh"')
14ROOT.gROOT.ProcessLine(
'#include "TG4GeometryServices.h"')
15ROOT.gROOT.ProcessLine(
'#include "TG4GeometryManager.h"')
19 """Recursively walk the geometry tree collecting volume names from nodes."""
20 nodes = volume.GetNodes()
23 for i
in range(nodes.GetEntries()):
25 name = node.GetVolume().GetName()
26 if name
not in listOfVolumes:
27 listOfVolumes.append(name)
33 top = fGeo.GetTopVolume()
34 listOfVolumes = [top.GetName()]
37 gIndex: dict[str, list] = {}
38 for v
in fGeo.GetListOfVolumes():
40 if name
not in listOfVolumes:
42 if name
not in gIndex:
44 gIndex[name].append(v.GetNumber())
45 print(
"list of orphan volumes:", orphan)
48 if len(gIndex[x]) > 1:
49 vSame[x] = len(gIndex[x])
50 print(
"list of volumes with same name", vSame)
54 print(
"setMagnetField() called. Out of date, does not set field for tau neutrino detector!")
55 fGeo = ROOT.gGeoManager
56 vols = fGeo.GetListOfVolumes()
63 bx = field.GetFieldValue()[0] / u.tesla * G4Unit.tesla
64 by = field.GetFieldValue()[1] / u.tesla * G4Unit.tesla
65 bz = field.GetFieldValue()[2] / u.tesla * G4Unit.tesla
66 magFieldIron = ROOT.G4UniformMagField(ROOT.G4ThreeVector(bx, by, bz))
67 FieldIronMgr = ROOT.G4FieldManager(magFieldIron)
68 FieldIronMgr.CreateChordFinder(magFieldIron)
69 listOfFields[v.GetName()] = FieldIronMgr
70 gt = ROOT.G4TransportationManager.GetTransportationManager()
71 gn = gt.GetNavigatorForTracking()
72 world = gn.GetWorldVolume().GetLogicalVolume()
74 for da
in range(world.GetNoDaughters()):
75 vl0 = world.GetDaughter(da)
76 vln = vl0.GetName().c_str()
77 lvl0 = vl0.GetLogicalVolume()
78 if vln
in listOfFields:
80 for dda
in range(lvl0.GetNoDaughters()):
81 vl = lvl0.GetDaughter(dda)
82 vln = vl.GetName().c_str()
83 lvl = vl.GetLogicalVolume()
84 if vln
in listOfFields:
89 fm = lvl.GetFieldManager()
90 if not fm.DoesFieldExist():
91 lvl.SetFieldManager(listOfFields[setField[lvl]],
True)
94 constField = listOfFields[setField[lvl]].GetDetectorField().GetConstantFieldValue()
95 print(
"set field for ", setField[lvl], constField)
98 print(
"field already set:", setField[lvl])
100 g4Run = ROOT.G4RunManager.GetRunManager()
101 g4Run.GeometryHasBeenModified(
True)
104def printWF(vl, alreadyPrinted, onlyWithField: bool =
True):
106 vname = vl.GetName().data()
107 if vname
in alreadyPrinted:
109 vln = vname +
" " + str(vl.GetCopyNo())
110 mvl = vl.GetMotherLogical().GetName().data()
111 alreadyPrinted[vname] = mvl
113 vln = mvl +
"/" + vln
114 lvl = vl.GetLogicalVolume()
115 cvol = lvl.GetSolid().GetCubicVolume() / G4Unit.m3
116 M = lvl.GetMass() / G4Unit.kg
117 fm = lvl.GetFieldManager()
118 if not fm
and onlyWithField:
121 print(
"%-35s volume = %5.2Fm3 mass = %5.2F kg" % (vln, cvol, M))
123 print(
"%-35s volume = %5.2Fm3 mass = %5.2F t" % (vln, cvol, M / 1000.0))
125 fi = fm.GetDetectorField()
126 print(
" Magnetic field:", fi.GetConstantFieldValue() / G4Unit.tesla)
128 name = vl.GetName().c_str()
129 if "_" in name
and "Mag" in name.split(
"_")[1]:
134def nextLevel(lv, magnetMass: int, onlyWithField, exclude, alreadyPrinted):
136 for da
in range(lv.GetNoDaughters()):
137 lvn = lv.GetDaughter(da)
138 name = lvn.GetName().c_str()
141 lvln = lvn.GetLogicalVolume()
142 if lvln.GetNoDaughters() > 0:
143 xtmp, _dummy =
nextLevel(lvln, magnetMass, onlyWithField, exclude, alreadyPrinted)
146 tmp +=
printWF(lvn, alreadyPrinted, onlyWithField)
147 return tmp, magnetMass
153 if len(exclude) != 0:
154 print(
"will not search in ", exclude)
155 gt = ROOT.G4TransportationManager.GetTransportationManager()
156 gn = gt.GetNavigatorForTracking()
157 world = gn.GetWorldVolume().GetLogicalVolume()
159 alreadyPrinted: dict[str, str] = {}
160 _dummy, nM =
nextLevel(world, magnetMass, onlyWithField, exclude, alreadyPrinted)
161 print(
"total magnet mass", nM / 1000.0,
"t")
165def addVMCFields(shipGeo, controlFile: str =
"", verbose: bool =
False, withVirtualMC: bool =
True):
167 Define VMC B fields, e.g. global field, field maps, local
or local+
global fields
169 print("Calling addVMCFields")
171 fieldMaker = ROOT.ShipFieldMaker(verbose)
175 if controlFile !=
"":
176 fieldMaker.readInputFile(controlFile)
179 if hasattr(shipGeo,
"Bfield"):
181 fieldMaker.defineFieldMap(
"MainSpecMap", shipGeo.Bfield.fieldMap, ROOT.TVector3(0.0, 0.0, shipGeo.Bfield.z))
182 fieldsList.append(
"MainSpecMap")
184 if not shipGeo.muShield.WithConstField:
185 offset = shipGeo.muShield.Entrance[0]
187 file_name = f
"files/{shipGeo.shieldName}.root"
188 fieldMaker.defineFieldMap(
189 "muonShieldField", file_name, ROOT.TVector3(0.0, 0.0, offset), ROOT.TVector3(0.0, 0.0, 0.0), quadSymm
191 fieldsList.append(
"muonShieldField")
193 elif not shipGeo.hadronAbsorber.WithConstField:
194 fieldMaker.defineFieldMap(
196 "files/FieldHadronStopper_raised_20190411.root",
197 ROOT.TVector3(0.0, 0.0, shipGeo.hadronAbsorber.z),
199 fieldsList.append(
"HadronAbsorberMap")
202 if len(fieldsList) > 1:
203 fieldMaker.defineComposite(
"TotalField", *fieldsList)
204 fieldMaker.defineGlobalField(
"TotalField")
206 fieldMaker.defineGlobalField(
"MainSpecMap")
210 geom = ROOT.TG4GeometryManager.Instance()
212 geom.SetUserPostDetConstruction(fieldMaker)
214 geom.ConstructSDandField()
223 Method to print out information about VMC fields
225 print("Printing VMC fields and associated volumes")
227 fGeo = ROOT.gGeoManager
228 vols = fGeo.GetListOfVolumes()
233 print(f
"Vol is {v.GetName()}, field is {field}")
235 print(f
"Vol is {v.GetName()}")
240 centre = array(
"d", [0.0, 0.0, 0.0])
241 B = array(
"d", [0.0, 0.0, 0.0])
242 field.Field(centre, B)
243 print(f
"Volume {v.GetName()} has B = ({B[0] / u.tesla}, {B[1] / u.tesla}, {B[2] / u.tesla}) T")
247 return ROOT.G4RunManager.GetRunManager()
251 session = ROOT.G4UIterminal()
252 session.SessionStart()
256 gt = ROOT.G4TransportationManager.GetTransportationManager()
257 gn = gt.GetNavigatorForTracking()
258 world = gn.GetWorldVolume().GetLogicalVolume()
260 for da
in range(world.GetNoDaughters()):
261 vl = world.GetDaughter(da)
262 vmap[vl.GetName().c_str()] = vl
263 print(da, vl.GetName())
264 lvl = vmap[
"MagB"].GetLogicalVolume()
265 print(lvl.GetMass() / G4Unit.kg, lvl.GetMaterial().GetName())
266 print(lvl.GetFieldManager())
268 for da
in range(world.GetNoDaughters()):
269 vl = world.GetDaughter(da)
270 vln = vl.GetName().c_str()
271 lvl = vl.GetLogicalVolume()
272 fm = lvl.GetFieldManager()
274 v = fm.GetDetectorField().GetConstantFieldValue()
275 print(vln, fm, v.getX(), v.getY())
277 fgeom = ROOT.gGeoManager
278 magB = fgeom.GetVolume(
"MagB")
280 print(fl.GetFieldValue()[0], fl.GetFieldValue()[1], fl.GetFieldValue()[2])
None printWeightsandFields(bool onlyWithField=True, exclude=None)
def addVMCFields(shipGeo, str controlFile="", bool verbose=False, bool withVirtualMC=True)
None setMagnetField(flag=None)
def printWF(vl, alreadyPrinted, bool onlyWithField=True)
None _collectVolumeNames(volume, listOfVolumes)
def nextLevel(lv, int magnetMass, onlyWithField, exclude, alreadyPrinted)
None check4OrphanVolumes(fGeo)