SND@LHC Software
Loading...
Searching...
No Matches
geomGeant4.py
Go to the documentation of this file.
1from __future__ import print_function
2from __future__ import division
3import shipunit as u
4from array import array
5import hepunit as G4Unit
6import ShieldUtils
7import ROOT
8ROOT.gROOT.ProcessLine('#include "Geant4/G4TransportationManager.hh"')
9ROOT.gROOT.ProcessLine('#include "Geant4/G4FieldManager.hh"')
10ROOT.gROOT.ProcessLine('#include "Geant4/G4UIterminal.hh"')
11ROOT.gROOT.ProcessLine('#include "Geant4/G4RunManager.hh"')
12ROOT.gROOT.ProcessLine('#include "TG4GeometryServices.h"')
13ROOT.gROOT.ProcessLine('#include "TG4GeometryManager.h"')
14
16# fill list with volumes from nodes and compare with list of volumes
17 top = fGeo.GetTopVolume()
18 listOfVolumes = [top.GetName()]
19 findNode(top,listOfVolumes)
20 orphan = []
21 gIndex = {}
22 for v in fGeo.GetListOfVolumes():
23 name = v.GetName()
24 if not name in listOfVolumes:
25 orphan.append(name)
26 if not name in gIndex: gIndex[name]=[]
27 gIndex[name].append(v.GetNumber())
28 print("list of orphan volumes:",orphan)
29 vSame = {}
30 for x in gIndex:
31 if len(gIndex[x])>1: vSame[x]=len(gIndex[x])
32 print("list of volumes with same name",vSame)
33
34def setMagnetField(flag=None):
35 print('setMagnetField() called. Out of date, does not set field for tau neutrino detector!')
36 fGeo = ROOT.gGeoManager
37 vols = fGeo.GetListOfVolumes()
38 #copy field by hand to geant4
39 listOfFields={}
40 for v in vols:
41 field = v.GetField()
42 if not field: continue
43 bx = field.GetFieldValue()[0]/u.tesla*G4Unit.tesla
44 by = field.GetFieldValue()[1]/u.tesla*G4Unit.tesla
45 bz = field.GetFieldValue()[2]/u.tesla*G4Unit.tesla
46 magFieldIron = G4UniformMagField(G4ThreeVector(bx,by,bz))
47 FieldIronMgr = G4FieldManager(magFieldIron)
48 FieldIronMgr.CreateChordFinder(magFieldIron)
49 listOfFields[v.GetName()]=FieldIronMgr
50 gt = ROOT.G4TransportationManager.GetTransportationManager()
51 gn = gt.GetNavigatorForTracking()
52 world = gn.GetWorldVolume().GetLogicalVolume()
53 setField = {}
54 for da in range(world.GetNoDaughters()):
55 vl0 = world.GetDaughter(da)
56 vln = vl0.GetName().c_str()
57 lvl0 = vl0.GetLogicalVolume()
58 if vln in listOfFields : setField[lvl0]=vln
59 for dda in range(lvl0.GetNoDaughters()):
60 vl = lvl0.GetDaughter(dda)
61 vln = vl.GetName().c_str()
62 lvl = vl.GetLogicalVolume()
63 if vln in listOfFields : setField[lvl]=vln
64 modified = False
65 for lvl in setField:
66 # check if field already exists
67 fm = lvl.GetFieldManager()
68 if not fm.DoesFieldExist():
69 lvl.SetFieldManager(listOfFields[setField[lvl]],True)
70 modified = True
71 if flag=='dump':
72 constField = listOfFields[setField[lvl]].GetDetectorField().GetConstantFieldValue()
73 print('set field for ',setField[lvl], constField)
74 else:
75 if flag=='dump':
76 print('field already set:',setField[lvl])
77 if modified:
78 g4Run = G4RunManager.GetRunManager()
79 g4Run.GeometryHasBeenModified(True)
80
81def printWF(vl,alreadyPrinted,onlyWithField=True):
82 magnetMass = 0
83 vname = vl.GetName().data()
84 if vname in alreadyPrinted: return magnetMass
85 vln = vname+' '+str(vl.GetCopyNo())
86 mvl = vl.GetMotherLogical().GetName().data()
87 alreadyPrinted[vname]=mvl
88 if mvl !='cave': vln = mvl+'/'+vln
89 lvl = vl.GetLogicalVolume()
90 cvol = lvl.GetSolid().GetCubicVolume()/G4Unit.m3
91 M = lvl.GetMass()/G4Unit.kg
92 fm = lvl.GetFieldManager()
93 if not fm and onlyWithField: return magnetMass
94 if M < 5000.: print('%-35s volume = %5.2Fm3 mass = %5.2F kg'%(vln,cvol,M))
95 else: print('%-35s volume = %5.2Fm3 mass = %5.2F t'%(vln,cvol,M/1000.))
96 if fm:
97 fi = fm.GetDetectorField()
98 if hasattr(fi,'GetConstantFieldValue'):
99 print(' Magnetic field:',fi.GetConstantFieldValue()/G4Unit.tesla)
100 else:
101 serv = ROOT.TG4GeometryServices.Instance()
102 pos = array('d',[0,0,0])
103 bf = array('d',[0,0,0])
104 name = ROOT.G4String(lvl.GetName().c_str())
105 print ('debug',name,lvl.GetName(),lvl)
106 serv.GetField(name,pos,bf)
107 print(' Magnetic field Bx,By,Bz: %4.2F %4.2F %4.2F'%(bf[0]/G4Unit.tesla,bf[1]/G4Unit.tesla,bf[2]/G4Unit.tesla))
108 #if vl.GetName().c_str()[0:3]=='Mag': magnetMass = M # only count volumes starting with Mag
109 name = vl.GetName().c_str()
110 if "_" in name and "Mag" in name.split('_')[1]: magnetMass = M # only count volumes starting with Mag
111 return magnetMass
112def nextLevel(lv,magnetMass,onlyWithField,exclude,alreadyPrinted):
113 tmp = 0
114 for da in range(lv.GetNoDaughters()):
115 lvn = lv.GetDaughter(da)
116 name = lvn.GetName().c_str()
117 if name in exclude: continue
118 lvln = lvn.GetLogicalVolume()
119 if lvln.GetNoDaughters()>0:
120 xtmp,dummy = nextLevel(lvln,magnetMass,onlyWithField,exclude,alreadyPrinted)
121 magnetMass+=xtmp
122 else:
123 tmp+=printWF(lvn,alreadyPrinted,onlyWithField)
124 return tmp,magnetMass
125def printWeightsandFields(onlyWithField = True,exclude=[]):
126 if len(exclude)!=0:
127 print("will not search in ",exclude)
128 gt = ROOT.G4TransportationManager.GetTransportationManager()
129 gn = gt.GetNavigatorForTracking()
130 world = gn.GetWorldVolume().GetLogicalVolume()
131 magnetMass = 0
132 alreadyPrinted = {}
133 dummy,nM = nextLevel(world,magnetMass,onlyWithField,exclude,alreadyPrinted)
134 print('total magnet mass',nM/1000.,'t')
135 return
136
137def addVMCFields(shipGeo, controlFile = '', verbose = False, withVirtualMC = True):
138 '''
139 Define VMC B fields, e.g. global field, field maps, local or local+global fields
140 '''
141 print('Calling addVMCFields')
142
143 fieldMaker = ROOT.ShipFieldMaker(verbose)
144
145 # Read the input control file. If this is empty then the only fields that are
146 # defined (so far) are those within the C++ geometry classes
147 if controlFile != '':
148 fieldMaker.readInputFile(controlFile)
149
150 # Set the main spectrometer field map as a global field
151 if hasattr(shipGeo, 'Bfield'):
152 fieldsList = []
153 fieldMaker.defineFieldMap('MainSpecMap', 'files/MainSpectrometerField.root',
154 ROOT.TVector3(0.0, 0.0, shipGeo.Bfield.z))
155 fieldsList.append('MainSpecMap')
156
157 withConstFieldNuTauDet = False
158 if hasattr(shipGeo.EmuMagnet,'WithConstField'): withConstFieldNuTauDet = shipGeo.EmuMagnet.WithConstField
159 if not withConstFieldNuTauDet:
160 fieldMaker.defineFieldMap('NuMap','files/nuTauDetField.root', ROOT.TVector3(0.0,0.0,shipGeo.EmuMagnet.zC))
161 fieldsList.append('NuMap')
162
163 if not shipGeo.hadronAbsorber.WithConstField:
164 fieldMaker.defineFieldMap('HadronAbsorberMap','files/FieldHadronStopper_raised_20190411.root', ROOT.TVector3(0.0,0.0,shipGeo.hadronAbsorber.z))
165 fieldsList.append('HadronAbsorberMap')
166
167 if not shipGeo.muShield.WithConstField:
168 field_center, _ = ShieldUtils.find_shield_center(shipGeo)
169 fieldMaker.defineFieldMap('muonShieldField', 'files/MuonShieldField.root',
170 ROOT.TVector3(0.0, 0.0, field_center), ROOT.TVector3(0.0, 0.0, 0.0), True)
171 fieldsList.append('muonShieldField')
172 # Combine the fields to obtain the global field
173 if len(fieldsList) > 1:
174 fieldMaker.defineComposite('TotalField', *fieldsList) #fieldsList MUST have length <=4
175 fieldMaker.defineGlobalField('TotalField')
176 else:
177 fieldMaker.defineGlobalField('MainSpecMap')
178 if withVirtualMC:
179 # Force the VMC to update/reset the fields defined by the fieldMaker object.
180 # Get the ROOT/Geant4 geometry manager
181 geom = ROOT.TG4GeometryManager.Instance()
182 # Let the geometry know about the fieldMaker object
183 geom.SetUserPostDetConstruction(fieldMaker)
184 # Update the fields via the overriden ShipFieldMaker::Contruct() function
185 geom.ConstructSDandField()
186
187 # Return the fieldMaker object, otherwise it will "go out of scope" and its
188 # content will be deleted
189 return fieldMaker
190
191
193 '''
194 Method to print out information about VMC fields
195 '''
196 print('Printing VMC fields and associated volumes')
197
198 fGeo = ROOT.gGeoManager
199 vols = fGeo.GetListOfVolumes()
200
201 for v in vols:
202
203 field = v.GetField()
204 if field:
205 print('Vol is {0}, field is {1}'.format(v.GetName(), field))
206 else:
207 print('Vol is {0}'.format(v.GetName()))
208
209 if field:
210 # Get the field value assuming the global co-ordinate origin.
211 # This needs to be modified to use the local volume centre
212 centre = array('d',[0.0, 0.0, 0.0])
213 B = array('d',[0.0, 0.0, 0.0])
214 field.Field(centre, B)
215 print('Volume {0} has B = ({1}, {2}, {3}) T'.format(v.GetName(), B[0]/u.tesla,
216 B[1]/u.tesla, B[2]/u.tesla))
217
219 return ROOT.G4RunManager.GetRunManager()
221 session = ROOT.G4UIterminal()
222 session.SessionStart()
223def debug():
224 gt = ROOT.G4TransportationManager.GetTransportationManager()
225 gn = gt.GetNavigatorForTracking()
226 world = gn.GetWorldVolume().GetLogicalVolume()
227 vmap = {}
228 for da in range(world.GetNoDaughters()):
229 vl = world.GetDaughter(da)
230 vmap[vl.GetName().c_str()] = vl
231 print(da, vl.GetName())
232 lvl = vmap['MagB'].GetLogicalVolume()
233 print(lvl.GetMass()/G4Unit.kg,lvl.GetMaterial().GetName())
234 print(lvl.GetFieldManager())
235#
236 for da in range(world.GetNoDaughters()):
237 vl = world.GetDaughter(da)
238 vln = vl.GetName().c_str()
239 lvl = vl.GetLogicalVolume()
240 fm = lvl.GetFieldManager()
241 if fm :
242 v = fm.GetDetectorField().GetConstantFieldValue()
243 print(vln,fm,v.getX(),v.getY())
244# FairROOT view
245 fgeom = ROOT.gGeoManager
246 magB = fgeom.GetVolume('MagB')
247 fl = magB.GetField()
248 print(fl.GetFieldValue()[0],fl.GetFieldValue()[1],fl.GetFieldValue()[2])
find_shield_center(ship_geo)
Definition ShieldUtils.py:1
nextLevel(lv, magnetMass, onlyWithField, exclude, alreadyPrinted)
printWeightsandFields(onlyWithField=True, exclude=[])
addVMCFields(shipGeo, controlFile='', verbose=False, withVirtualMC=True)
printWF(vl, alreadyPrinted, onlyWithField=True)
Definition geomGeant4.py:81
setMagnetField(flag=None)
Definition geomGeant4.py:34
check4OrphanVolumes(fGeo)
Definition geomGeant4.py:15