""" 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()