"""
M. Littlefield
"""
# This file is part of MAUS: http://micewww.pp.rl.ac.uk:8080/projects/maus
#
# MAUS is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# MAUS is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with MAUS. If not, see .
import shutil
import os
import math
import libxml2
from xml.dom import minidom
from geometry.ConfigReader import Configreader
SCHEMA_PATH = os.environ["MAUS_ROOT_DIR"]+\
"/src/common_py/geometry/GDML_3_0_0/schema/gdml.xsd"
class Formatter: #pylint: disable = R0902, R0912, R0914, R0915, C0103, C0302
"""
@Class formatter this class formats the raw outputted fastrad files so their
schema material file paths are correct
This class opens the files which need the correct paths added and edits the
file in situ.
"""
def __init__(self, path_in, path_out):
"""
@Method Class Constructor
This is the class constructor which sets up the variables so they point
at the correct files ready to edit.
@Param Path The path to the directory which contains the fastrad
outputted GDML files
"""
self.g4_step_max = Configreader().g4_step_max
self.tof_0_file_number = Configreader().tof_0_file_number
self.tof_1_file_number = Configreader().tof_1_file_number
self.tof_2_file_number = Configreader().tof_2_file_number
self.ckov1_file_number = Configreader().ckov1_file_number
self.ckov2_file_number = Configreader().ckov2_file_number
self.kl_file_number = Configreader().kl_file_number
self.emr_file_number = Configreader().emr_file_number
self.tracker0_file_number = Configreader().tracker0_file_number
self.tracker1_file_number = Configreader().tracker1_file_number
self.absorber0_file_number = Configreader().absorber0_file_number
self.absorber1_file_number = Configreader().absorber1_file_number
self.absorber2_file_number = Configreader().absorber2_file_number
self.path_in = path_in
self.path_out = path_out.rstrip('/') + '/'
self.beamline_file = None
self.coolingChannel_file = None
self.maus_information_file = None
self.corrections_file = None
self.configuration_file = None
self.material_file = None
self.tracker_file = None
self.detmodulefiles = []
self.modulefiles = []
self.stepfiles = []
self.formatted = False
self.txt_file = ""
self.schema = SCHEMA_PATH
self.usegdml = False
gdmls = os.listdir(self.path_in)
#if self.path_in == self.path_out:
# paths_equal = True
for fname in gdmls:
print fname
if fname[-5:] != '.gdml' and fname[-4:] != '.xml' and \
fname.find('.table') < 0:
print fname+' not a gdml or xml file - ignored'
elif fname.find('materials') >= 0:
self.material_file = fname
shutil.copy(os.path.join(self.path_in, fname),
os.path.join(self.path_out, fname) )
elif fname.find('fastrad') >= 0 or \
fname.find('Fastrad') >= 0 or \
fname.find('Step_IV')>=0:
self.configuration_file = fname
elif fname.find('Cooling_Channel') >= 0:
self.tracker_file = fname
elif fname.find('Maus_Information') >= 0 \
or fname.find('maus_information') >= 0 \
or fname.find('Field') >= 0 \
or fname.find('field') >= 0:
print 'Found ', fname
self.maus_information_file = fname
elif fname.find('Beamline') >= 0:
self.beamline_file = fname
elif fname.find('AlignmentCorrections') >= 0:
self.corrections_file = fname
elif fname.find('CoolingChannelInfo') >= 0:
self.coolingChannel_file = fname
print 'Found ', fname
fout = open(os.path.join(self.path_in, fname), 'r')
print fout.read()
fout.close()
elif fname.find('Quad') >= 0 \
or fname.find('Dipole') >= 0 \
or fname.find('Solenoid') >= 0 \
or fname.find('AFC') >= 0:
self.modulefiles.append(fname)
elif fname.find('KL') >= 0 \
or fname.find('Tracker') >= 0:
self.detmodulefiles.append(fname)
else:
self.stepfiles.append(fname)
if self.maus_information_file == None:
self.maus_information_file = 'Maus_Information.gdml'
maus_information_location = os.environ['MAUS_ROOT_DIR'] + \
'/tests/py_unit/test_geometry/testCases/mausModuleSource'
shutil.copy(os.path.join(maus_information_location, \
self.maus_information_file),
os.path.join(self.path_in, self.maus_information_file) )
print 'Maus_Information file not found' + \
'Maus_Information.gdml has been copied from ' + \
maus_information_location
else:
info = libxml2.parseFile(os.path.join(self.path_in,
self.maus_information_file))
if len(info.xpathEval(\
"MICE_Information/Other_Information/Module")) > 0:
self.usegdml = True
def format_schema_location(self, gdmlfile):
"""
@method format_schema_location
This method parses the GDML file into memory and alters the location of
the schema location. It then rewrites the GDML with the valid schema.
@param gdmlfile absolute path to the file which will have its schema
location altered.
"""
# ignore the field maps.
if gdmlfile.find('.table') < 0:
xmldoc = minidom.parse(os.path.join(self.path_in, gdmlfile))
for node in xmldoc.getElementsByTagName("gdml"):
if node.hasAttribute("xsi:noNamespaceSchemaLocation"):
node.attributes['xsi:noNamespaceSchemaLocation'] = \
self.schema
# print "Schema location corrected for ",gdmlfile
fout = open(os.path.join(self.path_out, gdmlfile), 'w')
xmldoc.writexml(fout)
fout.close()
else:
shutil.copy(os.path.join(self.path_in, gdmlfile), \
os.path.join(self.path_out, gdmlfile))
def format_gdml_locations(self, gdmlfile):
"""
@method format_gdml_locations
This method parses the GDML file into memoty and alters the location
of the file names to absolute paths.
"""
docfile = os.path.join(self.path_out, gdmlfile)
print "Reviewing content of ", docfile
xmldoc = libxml2.parseFile(docfile)
for vol in xmldoc.xpathEval("gdml/structure/volume/physvol"):
if len(vol.xpathEval("file")) > 0:
filenode = vol.xpathEval("file")[0]
filename = filenode.prop("name")
if filename.find(self.path_out) == -1:
# add the path to the name
newname = os.path.join(self.path_out, filename)
# print "Replacing ", filename, " with ", newname
filenode.setProp("name", newname)
gfile = open(os.path.join(self.path_out, gdmlfile),'w')
xmldoc.saveTo(gfile)
gfile.close()
xmldoc.freeDoc()
def correct_gdml_locations(self, gdmlfile):
"""
@method format_gdml_locations
This method parses the GDML file into memoty and alters the location
of the file names to absolute paths.
"""
docfile = os.path.join(self.path_out, gdmlfile)
# print "Reviewing content of ",docfile
xmldoc = libxml2.parseFile(docfile)
for vol in xmldoc.xpathEval("gdml/structure/volume/physvol"):
if len(vol.xpathEval("file")) > 0:
filenode = vol.xpathEval("file")[0]
filename = filenode.prop("name")
if filename.find(self.path_in) == -1:
# add the path to the name
newname = os.path.join(self.path_out, filename)
# print "Replacing ",filename," with ",newname
filenode.setProp("name", newname)
# print "Saving to",os.path.join(self.path_out, gdmlfile)
f = open(os.path.join(self.path_out, gdmlfile),'w')
xmldoc.saveTo(f)
f.close()
xmldoc.freeDoc()
def apply_rotationsMC(self, pos, rot): #pylint: disable = R0201
"""
@method apply_rotationsMC
Application of rotations for the purpose of placing the
trackers in the global coordinate system from the
solenoid coordinate system.
"""
npos = [x for x in pos]
sumrot = 0
for u in rot:
sumrot += u
if math.fabs(sumrot) > 0:
# apply the rotations for the tracker into MC coordinates
k = math.pi/180.
c = [math.cos(k*th) for th in rot]
s = [math.sin(k*th) for th in rot]
npos[0] = c[1]*c[2]*pos[0] - c[1]*s[2]*pos[1] - s[1]*pos[2]
npos[1] = (-c[0]*s[2] + s[0]*s[1]*c[2])*pos[0] + \
(c[0]*c[2] + s[0]*s[1]*s[2])*pos[1] + s[0]*c[1]*pos[2]
npos[2] = (s[0]*s[2] + c[0]*s[1]*c[2])*pos[0] + \
(-s[0]*c[2] + c[0]*s[1]*s[2])*pos[1] + c[0]*c[1]*pos[2]
# print c
# print s
# print npos
return npos
def apply_alignment_corrections(self, gdmlFile): #pylint: disable = R0201
"""
@method apply_alignment_corrections
This method parses the maus information file into memory (argument) identifies
the detectors towhich the corrections are to be applied, opens the appropriate
GDML file and corrects the detector position (if required).
"""
maus_information = \
libxml2.parseFile(os.path.join(self.path_out, \
self.maus_information_file))
corrpath = "gdml/MICE_Information/Configuration_Information/GeometryID"
corrs = maus_information.xpathEval(corrpath)
config = libxml2.parseFile(os.path.join(self.path_out, \
self.configuration_file))
step_names = ['TOF0', 'TOF1', 'TOF2', 'KL', 'EMR',
'Ckov1', 'Ckov2', 'Tracker1', 'Tracker0']
for name in step_names:
# print name
# Find the positions from the configuration file
# first note that the tracker positions exist in the solenoid GDML
if name.find("Tracker0") >= 0:
solenoid = libxml2.parseFile(os.path.join(self.path_out, \
'SolenoidUS.gdml'))
tmpphys = [x for x in \
solenoid.xpathEval("gdml/structure/volume/physvol")\
if len(x.xpathEval("file")) > 0]
corrphys = \
next(x for x in tmpphys \
if x.xpathEval("file")[0].prop("name").find(name) >=0)
solphys = \
next(x for x in \
config.xpathEval("gdml/structure/volume/physvol")\
if x.xpathEval("file")[0].prop('name').find("SolenoidUS") >= 0)
elif name.find("Tracker1") >= 0:
solenoid = \
libxml2.parseFile(os.path.join(self.path_out, \
'SolenoidDS.gdml'))
tmpphys = \
[x for x in \
solenoid.xpathEval("gdml/structure/volume/physvol") \
if len(x.xpathEval("file")) > 0]
corrphys = \
next(x for x in tmpphys\
if x.xpathEval("file")[0].prop('name').find(name) >= 0)
solphys = \
next(x for x in \
config.xpathEval("gdml/structure/volume/physvol")\
if x.xpathEval("file")[0].prop('name').find("SolenoidDS") >= 0)
else:
tmpphys = [x for x in \
config.xpathEval("gdml/structure/volume/physvol") \
if len(x.xpathEval("file")) > 0]
corrphys = \
next(x for x in tmpphys \
if x.xpathEval("file")[0].prop('name').find(name) >= 0)
# Everything else is in the base configuration file
detinfopath = "gdml/MICE_Information/Detector_Information"
if name.find("TOF") >= 0:
detinfo = \
maus_information.xpathEval(str(detinfopath) + "/TOF/"\
+ str(name) + "/physvol")[0]
elif name.find("Ckov") >= 0:
detinfo = \
maus_information.xpathEval(str(detinfopath) + "/Cherenkov/"\
+ str(name) + "/physvol")[0]
elif name.find("Tracker") >= 0:
detinfo = \
maus_information.xpathEval(str(detinfopath) + "/Tracker/"\
+ str(name) + "/physvol")[0]
else:
detinfo = \
maus_information.xpathEval(str(detinfopath) + "/"\
+ str(name) + "/physvol")[0]
pos = [float(corrphys.xpathEval("position")[0].prop(u)) \
for u in ['x', 'y', 'z'] ]
rot = [float(corrphys.xpathEval("rotation")[0].prop(u)) \
for u in ['x', 'y', 'z'] ]
pos_det = [float(corrphys.xpathEval("position")[0].prop(u)) \
for u in ['x', 'y', 'z'] ]
rot_det = [float(corrphys.xpathEval("rotation")[0].prop(u)) \
for u in ['x', 'y', 'z'] ]
# rec_rot = rot
d_pos = [0, 0, 0]
d_rot = [0, 0, 0]
if len(corrs) > 0:
for node in corrs:
for vol in node.xpathEval("ModuleName"):
if vol.prop("name").find(name) >= 0:
# get the corrections with
# respect to the device centre
d_pos = \
[float(vol.prop(u)) \
for u in ['dx', 'dy', 'dz'] ]
# rotations are measured in
# object coordinate system
d_rot = \
[float(vol.prop(u)) \
for u in ['dx_rot', 'dy_rot', 'dz_rot'] ]
# print name, d_pos, d_rot
sol_pos = [0, 0, 0]
sol_rot = [0, 0, 0]
if name.find("Tracker0") >= 0 or name.find("Tracker1") >= 0:
sol_pos = [float(solphys.xpathEval("position")[0].prop(u)) \
for u in ['x', 'y', 'z'] ]
sol_rot = [float(solphys.xpathEval("rotation")[0].prop(u)) \
for u in ['x', 'y', 'z'] ]
# print name, sol_pos, sol_rot
for i in [0, 1, 2]:
pos[i] += d_pos[i]
# rotations in the simulation alter the coordinate system
# for the object
rot[i] += d_rot[i]
# positions and rotations in the reconstruction rotate the object
d_pos_wrot = self.apply_rotationsMC(pos, sol_rot)
pos_det = [x for x in d_pos_wrot]
for i in [0, 1, 2]:
# solenoid positions should be added to the reconstruction
# positions if necessary
pos_det[i] += sol_pos[i]
rot_det[i] += sol_rot[i]
rot_det[i] += d_rot[i]
# print pos
# print pos_det
u = ['x', 'y', 'z']
if name.find('Tracker0') >= 0:
rot_det[0] = -rot_det[0]
for i in [0, 1, 2]:
corrphys.xpathEval("position")[0].setProp(u[i], \
str(pos[i]))
detinfo.xpathEval("position")[0].setProp(u[i], \
str(pos_det[i]))
corrphys.xpathEval("rotation")[0].setProp(u[i], \
str(rot[i]))
detinfo.xpathEval("rotation")[0].setProp(u[i], \
str(rot_det[i]))
if name.find('Tracker0') >= 0:
# need to write the results to the solenoid GDML if the
# corrections are applied to the tracker
f = open(os.path.join(self.path_out, 'SolenoidUS.gdml'),'w')
solenoid.saveTo(f)
f.close()
solenoid.freeDoc()
elif name.find('Tracker1') >= 0:
# need to write the results to the solenoid GDML if the
# corrections are applied to the tracker
f = open(os.path.join(self.path_out, 'SolenoidDS.gdml'),'w')
solenoid.saveTo(f)
f.close()
solenoid.freeDoc()
f0 = open(os.path.join(self.path_out, self.maus_information_file),'w')
maus_information.saveTo(f0)
f0.close()
maus_information.freeDoc()
f1 = open(os.path.join(self.path_out, gdmlFile), 'w')
config.saveTo(f1)
f1.close()
config.freeDoc()
def add_other_info(self): #pylint: disable = R0914, R0915, C0301
"""
@method add_other_information
THis methods adds other information needed by MAUS.
This is mainly so we can add computer specific environment
variables into the translated gdml files.
"""
maus_information = minidom.parse(os.path.join(self.path_out, \
self.maus_information_file))
file_numbers = None
for node in maus_information.getElementsByTagName("FileNumbers"):
file_numbers = node
doc = minidom.Document()
top_node = doc.createElement("Other_Information")
doc.appendChild(top_node)
maus_dir = doc.createElement("GDML_Files")
path = self.path_out
maus_dir.setAttribute("location", path)
maus_dir.setAttribute("basefile", self.configuration_file)
top_node.appendChild(maus_dir)
g4_step = doc.createElement("G4StepMax")
g4_step.setAttribute("Value", str(self.g4_step_max))
top_node.appendChild(g4_step)
file_numbers = doc.createElement("FileNumbers")
top_node.appendChild(file_numbers)
tof_0_file_number = doc.createElement("Tof0FileNumber")
tof_0_file_number.setAttribute("number", str(self.tof_0_file_number))
file_numbers.appendChild(tof_0_file_number)
tof_1_file_number = doc.createElement("Tof1FileNumber")
tof_1_file_number.setAttribute("number", str(self.tof_1_file_number))
file_numbers.appendChild(tof_1_file_number)
tof_2_file_number = doc.createElement("Tof2FileNumber")
tof_2_file_number.setAttribute("number", str(self.tof_2_file_number))
file_numbers.appendChild(tof_2_file_number)
ckov1_file_number = doc.createElement("Ckov1FileNumber")
ckov1_file_number.setAttribute("number", str(self.ckov1_file_number))
file_numbers.appendChild(ckov1_file_number)
ckov2_file_number = doc.createElement("Ckov2FileNumber")
ckov2_file_number.setAttribute("number", str(self.ckov2_file_number))
file_numbers.appendChild(ckov2_file_number)
kl_file_number = doc.createElement("KLFileNumber")
kl_file_number.setAttribute("number", str(self.kl_file_number))
file_numbers.appendChild(kl_file_number)
emr_file_number = doc.createElement("EMRFileNumber")
emr_file_number.setAttribute("number", str(self.emr_file_number))
file_numbers.appendChild(emr_file_number)
tracker0_file_number = doc.createElement("Tracker0FileNumber")
tracker0_file_number.setAttribute("number",
str(self.tracker0_file_number))
file_numbers.appendChild(tracker0_file_number)
tracker1_file_number = doc.createElement("Tracker1FileNumber")
tracker1_file_number.setAttribute("number",
str(self.tracker1_file_number))
file_numbers.appendChild(tracker1_file_number)
absorber0_file_number = doc.createElement("Absorber0FileNumber")
absorber0_file_number.setAttribute("number",
str(self.absorber0_file_number))
file_numbers.appendChild(absorber0_file_number)
absorber1_file_number = doc.createElement("Absorber1FileNumber")
absorber1_file_number.setAttribute("number",
str(self.absorber1_file_number))
file_numbers.appendChild(absorber1_file_number)
absorber2_file_number = doc.createElement("Absorber2FileNumber")
absorber2_file_number.setAttribute("number",
str(self.absorber2_file_number))
file_numbers.appendChild(absorber2_file_number)
if file_numbers != None:
top_node.appendChild(file_numbers)
maus_information = minidom.parse(os.path.join(self.path_out, \
self.maus_information_file))
old_node = maus_information.childNodes[0].childNodes[7]
new_node = doc.childNodes[0]
base_node = maus_information.childNodes[0]
base_node.replaceChild(new_node, old_node)
fout = open(os.path.join(self.path_out, self.maus_information_file),'w')
maus_information.writexml(fout)
fout.close()
def merge_maus_info(self, gdmlfile):
"""
@method merge_maus_info
This method adds the maus_information information to the
configuration GDML.
"""
self.add_other_info()
config = minidom.parse(os.path.join(self.path_out, gdmlfile))
# print "config file ", os.path.join(self.path_out, gdmlfile)
# print "information file ", os.path.join(self.path_out, \
# self.maus_information_file)
maus_information = minidom.parse(os.path.join(self.path_out, \
self.maus_information_file))
for node in maus_information.getElementsByTagName("MICE_Information"):
maus_info = node
# print str(node)
# print str(config)
root_node = config.childNodes[2]
root_node.insertBefore(maus_info, root_node.childNodes[9])
fout = open(os.path.join(self.path_out, gdmlfile), 'w')
root_node.writexml(fout)
fout.close()
def merge_run_info(self, gdmlfile):
"""
@method merge_run_info
This method adds the run information to the maus_information_file GDML.
"""
run_info = False
fin = open(os.path.join(self.path_in, gdmlfile))
for lines in fin.readlines():
if lines.find('run') >= 0 or lines.find('runs') >= 0:
run_info = True
fin.close()
if run_info == False:
maus_information = \
minidom.parse(os.path.join(self.path_in, gdmlfile))
beamline_path = os.path.join(self.path_in, self.beamline_file)
beamline = minidom.parse(beamline_path)
for node in beamline.getElementsByTagName("run"):
run_info = node
if type(run_info) == bool:
raise IOError("Run number you have selected is not on the CDB")
else:
root_node = maus_information.childNodes[0].childNodes[1]
root_node.insertBefore(run_info, root_node.childNodes[0])
fout = open(os.path.join(self.path_out, gdmlfile), 'w')
maus_information.writexml(fout)
fout.close()
print 'Run information merged!'
def merge_cooling_channel_info(self, gdmlfile):
"""
@method merge_maus_info
This method adds the run information to the maus_information_file GDML.
"""
run_info = False
fin = open(os.path.join(self.path_out, gdmlfile))
#for lines in fin.readlines():
# if lines.find('run') >= 0 or lines.find('runs') >= 0:
# run_info = True
fin.close()
if run_info == False:
maus_information = \
minidom.parse(os.path.join(self.path_out, \
gdmlfile))
coolingChannel_path = os.path.join(self.path_in, \
self.coolingChannel_file)
# print coolingChannel_path
coolingChannel = minidom.parse(coolingChannel_path)
for node in coolingChannel.getElementsByTagName("coolingchannel"):
cc_info = node
if type(cc_info) == bool:
raise IOError(\
"Run number you have selected is not in the coolingchannel CDB")
else:
root_node = maus_information.childNodes[0].childNodes[1]
root_node.insertBefore(cc_info, root_node.childNodes[0])
fout = open(os.path.join(self.path_out, gdmlfile), 'w')
maus_information.writexml(fout)
fout.close()
print 'Cooling channel information merged!'
def merge_alignment_correction_info(self, gdmlfile):
"""
@method merge_alignment_correction_info
This method adds the correction information to the maus_information_file GDML
"""
# fin = open(os.path.join(self.path_out, gdmlfile))
# for lines in fin.readlines():
maus_information = minidom.parse(os.path.join(self.path_out, gdmlfile))
correction_path = os.path.join(self.path_in, self.corrections_file)
correction = minidom.parse(correction_path)
corr_info = next(node for node in \
correction.getElementsByTagName("GeometryID"))
if type(corr_info) == bool:
raise IOError(
"Run number you have selected is not in the correction CDB")
else:
root_node = maus_information.childNodes[0].childNodes[1]
root_node.insertBefore(corr_info, root_node.childNodes[0])
fout = open(os.path.join(self.path_out, gdmlfile), 'w')
maus_information.writexml(fout)
fout.close()
def update_geometry_id_number(self, geoid, gdmlfile):
"""
@ method update geometry id number
This method updates the geometry id number to the number given
in the database rather than trusting the number given to the
upload files.
"""
if geoid != 0:
maus_information = minidom.parse(os.path.join(self.path_out, \
gdmlfile))
# check if the geometry id already exists in this file
geoid_node = maus_information.getElementsByTagName("GeometryID")
if len(geoid_node) > 0:
if geoid_node[0].getAttribute("value") != str(geoid):
# update the geometry id
geoid_node[0].setAttribute("value", str(geoid))
# else do nothing
else:
# create the node if it does not exist
config_node = \
maus_information.getElementsByTagName(\
"Configuration_Information")[0]
newNode = maus_information.createElement("GeometryID")
newNode.setAttribute("value", str(geoid))
config_node.appendChild(newNode)
fout = open(os.path.join(self.path_out, gdmlfile), 'w')
maus_information.writexml(fout)
fout.close()
def format_materials(self, gdmlfile):
"""
@method Format Materials
This method opens a new GDML file in memory and creates a new Document
Type Definition (DTD) which contains the correct location of the
materials reference file produced by fastRad.
@param GDMLFile The name of the file which will have its materials
reference file location altered.
"""
impl = minidom.getDOMImplementation()
docstr = 'gdml []'
doctype = impl.createDocumentType(docstr, None, None)
newdoc = impl.createDocument(None, "MAUS", doctype)
config = minidom.parse(os.path.join(self.path_out, gdmlfile))
for node in config.getElementsByTagName("gdml"):
rootelement = node
for node2 in newdoc.getElementsByTagName("MAUS"):
oldelement = node2
newdoc.replaceChild(rootelement, oldelement)
self.txt_file = os.path.join(self.path_out, gdmlfile[:-5] + '.txt')
fout = open(self.txt_file, 'w')
newdoc.writexml(fout)
fout.close()
def insert_materials_ref(self, inputfile): #pylint: disable = R0201
"""
@method Insert Materials Reference
This method opens the GDML file and replaces the materials file
reference call which is lost during the parsing of the GDML's in other
methods.
@param GDMLFile The name of the file which will have its materials
reference replaced.
"""
fin = open(inputfile, 'r')
gdmlfile = inputfile[:-4] + '.gdml'
fout = open(gdmlfile, 'w')
for line in fin.readlines():
if line.find('')>=0:
matdef = ''
new_line = line.replace(matdef, matdef+'&materials;')
print >> fout, new_line
else:
print >> fout, line
print >> fout, ''
fin.close()
fout.close()
os.remove(inputfile)
def format_check(self, gdmlfile):
"""
@method Format Check
This method checks to see whether the file passed to it
has already been formatted but looking for the string
which will have been put in the file
if it had already been formatted. This is to stop multiple
materials reference calls being added as it cannot be added by parsing
the GDML.
@param GDML File The file to be checked.
"""
self.formatted = False
fin = open(os.path.join(self.path_in, gdmlfile))
for lines in fin.readlines():
if lines.find('') >= 0:
print gdmlfile + ' already formatted!'
self.formatted = True
fin.close()
def format(self):
"""
@method Format
This method calls all the other methods to format the
necessary parts of the file. It will run through all of the
fastRad outputted files within the folder location given to
the class constructor.
"""
self.format_check(self.configuration_file)
if self.beamline_file != None:
self.merge_run_info(self.maus_information_file)
else:
shutil.copy(os.path.join(self.path_in, self.maus_information_file),
os.path.join(self.path_out, self.maus_information_file))
if self.coolingChannel_file != None:
self.merge_cooling_channel_info(self.maus_information_file)
if self.formatted == False:
print self.configuration_file
self.format_schema_location(self.configuration_file)
self.merge_maus_info(self.configuration_file)
self.format_materials(self.configuration_file)
self.format_gdml_locations(self.configuration_file)
self.insert_materials_ref(self.txt_file)
print "Formatted Configuration File"
if self.tracker_file != None:
self.format_check(self.tracker_file)
if self.formatted == False:
print self.tracker_file
self.format_schema_location(self.tracker_file)
self.merge_maus_info(self.tracker_file)
self.format_materials(self.tracker_file)
self.format_gdml_locations(self.tracker_file)
self.insert_materials_ref(self.txt_file)
print "Formatted cooling channel and trackers"
for module in self.modulefiles:
self.format_check(module)
if self.formatted == False:
self.format_schema_location(module)
self.merge_maus_info(module)
self.format_materials(module)
self.format_gdml_locations(module)
self.insert_materials_ref(self.txt_file)
print "Formatted module files"
self.stepfiles.extend(self.detmodulefiles)
noofstepfiles = len(self.stepfiles)
for num in range(0, noofstepfiles):
self.format_check(self.stepfiles[num])
if self.formatted == False:
self.format_schema_location(self.stepfiles[num])
self.format_materials(self.stepfiles[num])
self.insert_materials_ref(self.txt_file)
print "Formatted " + str(num+1) + \
" of " + str(noofstepfiles) + " Geometry Files"
print "Format Complete"
def addDiffuserIrises(self):
"""
@ Module addDiffuserIrises
Add the irises to the output gdml file
"""
mausInfo = libxml2.parseFile(os.path.join(self.path_out, \
self.maus_information_file))
mausInfoIn = libxml2.parseFile(os.path.join(self.path_in, \
self.maus_information_file))
runInfo = mausInfo.xpathEval(\
"MICE_Information/Configuration_Information/run")
# print runInfo
diffuserSetting = []
if len(runInfo) > 0:
diffuserSetting.append(runInfo[0].prop("diffuserThickness"))
print "Will use diffuser setting ", diffuserSetting[0]
else:
print "Will use the default diffuser."
# check the possible keys for suspected
modulekeys = mausInfoIn.xpathEval(\
"MICE_Information/Other_Information/Module")
keynode = next(x for x in \
modulekeys if x.prop('name').find('SolenoidUS') >= 0 \
or x.prop('name').find('Cooling_Channel') >= 0)
key = keynode.prop('name')
modrange = [float(keynode.prop('zmin')), float(keynode.prop('zmax'))]
diffuser = mausInfo.xpathEval(\
"MICE_Information/Detector_Information/Diffuser")
targetname = os.path.join(self.path_in, key+".gdml")
# print targetname
target = libxml2.parseFile(targetname)
vol = next(x for x in target.xpathEval("gdml/structure/volume")
if x.prop("name").find(key + "_structvol") >= 0)
for iris in diffuser:
# extract the iris number, position and rotation
inum = int(iris.xpathEval("Iris")[0].prop("name"))
pos = [float(iris.xpathEval("Position")[0].prop("x")), \
float(iris.xpathEval("Position")[0].prop("y")), \
float(iris.xpathEval("Position")[0].prop("z"))]
# print key, pos[2], modrange
pos[2] = pos[2] - (modrange[1] + modrange[0])/2.
# print key, pos[2], modrange
posUnit = iris.xpathEval("Position")[0].prop("unit")
rot = [float(iris.xpathEval("Rotation")[0].prop("x")), \
float(iris.xpathEval("Rotation")[0].prop("y")), \
float(iris.xpathEval("Rotation")[0].prop("z"))]
rotUnit = iris.xpathEval("Rotation")[0].prop("unit")
newNode = libxml2.newNode("physvol")
fileNode = libxml2.newNode("file")
if len(diffuserSetting) > 0: # test of whether the statement exists.
# print "Using diffuser setting ", int(diffuserSetting[0])
if (inum == 1 and int(diffuserSetting[0]) % 2 == 0) or \
(inum == 2 and (int(diffuserSetting[0]) % 4 == 0 or \
int(diffuserSetting[0]) % 4 == 1)) or \
(inum == 3 and (int(diffuserSetting[0]) < 4 or
(int(diffuserSetting[0]) >= 8 and \
int(diffuserSetting[0]) < 12))) or \
(inum == 4 and int(diffuserSetting[0]) < 8):
newNode.setProp("name", "iris" + str(inum))
fileNode.setProp("name", "iris" + str(inum) + "_open.gdml")
else:
newNode.setProp("name", "iris" + str(inum))
fileNode.setProp("name", "iris" + str(inum) + \
"_closed.gdml")
else:
if inum == 2 or inum == 3:
print "Iris ", inum, " default closed introduced."
newNode.setProp("name", "iris" + str(inum))
fileNode.setProp("name", "iris" + str(inum) + \
"_closed.gdml")
else:
print "Iris ", inum, " default open introduced."
newNode.setProp("name", "iris" + str(inum))
fileNode.setProp("name", "iris" + str(inum) + "_open.gdml")
newNode.addChild(fileNode)
posNode = libxml2.newNode("position")
posNode.setProp("name", "posRef_iris_" + str(inum))
posNode.setProp("x", str(pos[0]))
posNode.setProp("y", str(pos[1]))
posNode.setProp("z", str(pos[2]))
posNode.setProp("unit", posUnit)
newNode.addChild(posNode)
rotNode = libxml2.newNode("rotation")
rotNode.setProp("name", "rotRef_iris_"+str(inum))
rotNode.setProp("x", str(rot[0]))
rotNode.setProp("y", str(rot[1]))
rotNode.setProp("z", str(rot[2]))
rotNode.setProp("unit", rotUnit)
newNode.addChild(rotNode)
vol.addChild(newNode)
diffuser_support = mausInfo.xpathEval(\
"MICE_Information/Detector_Information/DiffuserSupport")
for sup in diffuser_support:
support_pos = [float(sup.xpathEval("Position")[0].prop("x")), \
float(sup.xpathEval("Position")[0].prop("y")), \
float(sup.xpathEval("Position")[0].prop("z"))]
support_rot = [float(sup.xpathEval("Rotation")[0].prop("x")), \
float(sup.xpathEval("Rotation")[0].prop("y")), \
float(sup.xpathEval("Rotation")[0].prop("z"))]
posUnit = sup.xpathEval("Position")[0].prop("unit")
rotUnit = sup.xpathEval("Rotation")[0].prop("unit")
support_pos[2] = support_pos[2] - (modrange[1] + modrange[0])/2.
supNode = libxml2.newNode("physvol")
supFileNode = libxml2.newNode("file")
supNode.setProp("name", "diffuser_support")
supFileNode.setProp("name", "diffuser_support.gdml")
supNode.addChild(supFileNode)
sposNode = libxml2.newNode("position")
sposNode.setProp("name", "posRef_diffsupport")
sposNode.setProp("x", str(support_pos[0]))
sposNode.setProp("y", str(support_pos[1]))
sposNode.setProp("z", str(support_pos[2]))
sposNode.setProp("unit", posUnit)
supNode.addChild(sposNode)
srotNode = libxml2.newNode("rotation")
srotNode.setProp("name", "rotRef_diffsupport")
srotNode.setProp("x", str(support_rot[0]))
srotNode.setProp("y", str(support_rot[1]))
srotNode.setProp("z", str(support_rot[2]))
srotNode.setProp("unit", rotUnit)
supNode.addChild(srotNode)
vol.addChild(supNode)
tgtfile = open(targetname, 'w')
target.saveTo(tgtfile)
tgtfile.close()
target.freeDoc()
mausInfo.freeDoc()
def maus_info_to_gdml(self):
"""
To be used when synthesising the gdml files for direct use to
define the geometry. Reformats the information file to use gdml
headers.
"""
self.add_other_info()
infofile = os.path.join(self.path_out, self.maus_information_file)
info = libxml2.parseFile(infofile)
doc = libxml2.parseDoc("""
""")
root = doc.xpathEval("gdml")[0]
root.addChildList(info.xpathEval("MICE_Information")[0].copyNode(1))
f = open(infofile,"w")
doc.saveTo(f)
f.close()
doc.freeDoc()
info.freeDoc()
def formatForGDML(self, geoid=0):
"""
@method FormatForGDML
This method calls all the other methods to format the
necessary parts of the file. It will run through all of the
fastRad outputted files within the folder location given to
the class constructor.
"""
# self.format_check(self.configuration_file)
if self.beamline_file != None:
self.merge_run_info(self.maus_information_file)
else:
shutil.copy(os.path.join(self.path_in, self.maus_information_file),
os.path.join(self.path_out, self.maus_information_file))
self.add_other_info()
if self.coolingChannel_file != None:
self.merge_cooling_channel_info(self.maus_information_file)
self.update_geometry_id_number(geoid, self.maus_information_file)
if self.corrections_file != None:
self.merge_alignment_correction_info(self.maus_information_file)
# if self.formatted == False:
print self.configuration_file
self.format_schema_location(self.configuration_file)
self.correct_gdml_locations(self.configuration_file)
self.addDiffuserIrises()
# self.merge_maus_info(self.configuration_file)
print "Formatted Configuration File"
self.maus_info_to_gdml()
if self.tracker_file != None:
self.format_check(self.tracker_file)
if self.formatted == False:
print self.tracker_file
self.format_schema_location(self.tracker_file)
self.correct_gdml_locations(self.tracker_file)
# print "Formatted cooling channel and trackers"
for module in self.modulefiles:
self.format_check(module)
if self.formatted == False:
self.format_schema_location(module)
self.correct_gdml_locations(module)
# print "Formatted module file ",module
for module in self.detmodulefiles:
# self.format_check(module)
if self.formatted == False:
self.format_schema_location(module)
self.correct_gdml_locations(module)
# print "Formatted detector module file ",module
noofstepfiles = len(self.stepfiles)
for num in range(0, noofstepfiles):
self.format_schema_location(self.stepfiles[num])
# print "Formatted step file ",self.stepfiles[num]
# self.correct_gdml_locations(self.stepfiles[num])
# now that everything else is formatted and placed, sychronize
# the placement of detectors in the output files
self.apply_alignment_corrections(self.configuration_file)
print "Format Complete"
def main():
"""
Main Function.
"""
if __name__ == "__main__":
main()