File indexing completed on 2024-11-27 03:18:08
0001
0002
0003 import argparse
0004 import os, sys
0005 import pprint
0006 from shutil import copy2
0007 import xml.etree.ElementTree as ET
0008
0009 TAG_PREFIX='{http://www.cern.ch/cms/DDL}'
0010 CMSSW_NOT_SET=1
0011 TRACKER_MATERIAL_FILE_MISSING=2
0012 LOCAL_RM = 'trackerRecoMaterialFromRelease.xml'
0013
0014 HEADER = """
0015 #ifndef SIMTRACKER_TRACKERMATERIALANALYSIS_LISTGROUPS_MATERIALDIFFERENCE_H
0016 #define SIMTRACKER_TRACKERMATERIALANALYSIS_LISTGROUPS_MATERIALDIFFERENCE_H
0017
0018 void ListGroups::fillMaterialDifferences() {
0019 """
0020
0021 TRAILER = """
0022 }
0023
0024 #endif // SIMTRACKER_TRACKERMATERIALANALYSIS_LISTGROUPS_MATERIALDIFFERENCE_H
0025 """
0026
0027 def checkEnvironment():
0028 """
0029 Check if the CMSSW environment is set. If not, quit the program.
0030 """
0031 if not 'CMSSW_RELEASE_BASE' in os.environ.keys():
0032 print('CMSSW Environments not setup, quitting\n')
0033 sys.exit(CMSSW_NOT_SET)
0034
0035 def checkFileInRelease(filename):
0036 """
0037 Check if the supplied @filename is avaialble under the central release installation.
0038 Returns None if the file is not present, the full pathname otherwise.
0039 """
0040 fullpathname = os.path.join(os.environ['CMSSW_RELEASE_BASE'], filename)
0041 if not os.path.exists(fullpathname):
0042 return None
0043 return fullpathname
0044
0045 def getTrackerRecoMaterialCopy(source_xml, filename):
0046 """
0047 Take the central @source_XML file file from either the local CMSSW
0048 installation or, if missing, from the central one and copies it over
0049 locally into a file named @filename.
0050 The full relative pathname of source_XML must be supplied, staring
0051 from the src folder (included).
0052 If the file cannot be found anywhere, quit the program.
0053 """
0054 tracker_reco_material = os.path.join(os.environ['CMSSW_BASE'],
0055 source_xml)
0056 if not os.path.exists(tracker_reco_material):
0057 tracker_reco_material = os.path.join(os.environ['CMSSW_RELEASE_BASE'],
0058 source_xml)
0059 if not os.path.exists(tracker_reco_material):
0060 print('Something is wrong with the CMSSW installation. The file %s is missing. Quitting.\n' % source_xml)
0061 sys.exit(TRACKER_MATERIAL_FILE_MISSING)
0062 copy2(tracker_reco_material, filename)
0063
0064 def produceXMLFromParameterFile(args):
0065 """
0066 Starting from the file parameters.xml produced by the
0067 TrackingMaterialAnalyser via cmsRun, it writes out a new XML,
0068 taking into account the proper names and grouping of detectors
0069 together.
0070
0071 The skeleton of the XML file is taken as an input paramter to this
0072 function, in order to support running on several geometries
0073 with one single script.
0074
0075 A new file, named trackerRecoMaterial.xml, is saved in the
0076 current directory.
0077 """
0078
0079 getTrackerRecoMaterialCopy(args.xml, LOCAL_RM)
0080 tracker_reco_material = LOCAL_RM
0081 tracker_reco_material_updated = './parameters.xml'
0082 ET.register_namespace('', "http://www.cern.ch/cms/DDL")
0083 tree = ET.parse(tracker_reco_material)
0084 root = tree.getroot()
0085 tree_updated = ET.parse(tracker_reco_material_updated)
0086 root_updated = tree_updated.getroot()
0087 sections = root.getchildren()
0088 if args.verbose:
0089 for child in sections[0]:
0090 print(child.attrib['name'])
0091
0092 for spec_par in root.iter('%sSpecPar' % TAG_PREFIX):
0093 current_detector = spec_par.attrib['name']
0094 for parameter in spec_par.iter('%sParameter' % TAG_PREFIX):
0095 if args.verbose:
0096 print("Current Detector: %r, name=%s, value=%s" % (current_detector,
0097 parameter.attrib['name'],
0098 parameter.attrib['value']))
0099 updated_current_detector_node = root_updated.find(".//Group[@name='%s']" % current_detector)
0100 if updated_current_detector_node is not None:
0101 for child in updated_current_detector_node:
0102 if child.attrib['name'] == parameter.attrib['name']:
0103 parameter.set('name', child.attrib['name'])
0104 parameter.set('value', child.attrib['value'])
0105 if args.verbose:
0106 print("Updated Detector: %r, name=%s, value=%s\n" % (child.attrib['name'],
0107 parameter.attrib['name'],
0108 parameter.attrib['value']))
0109 else:
0110 print("Missing group: %s" % current_detector)
0111 tree.write('trackerRecoMaterial.xml', encoding='UTF-8', xml_declaration=True)
0112
0113 def compareNewXMLWithOld(args):
0114 """Computes the difference between the old values, stored in the
0115 central repository for the current release, e.g. from
0116 $CMSSW_RELEASE_BASE/src/Geometry/TrackerRecoData/data/trackerRecoMaterial.xml,
0117 and the new values that we assume are present in the same file
0118 under the locally installed release, i.e. under
0119 $CMSSW_BASE/src/Geometry/TrackerRecoData/data/trackerRecoMaterial.xml. No
0120 check is performed to guarantee that the files are already
0121 there. If the file is not there, it is searched in the current
0122 folder. A missing file will result in an exception.
0123
0124 The output of this function is a formatted structured as:
0125 ComponentsName KindOfParameter OldValue NewValue Difference
0126 where the Difference is computed as (NewValue-OldValue)/OldValue.
0127
0128 Results are flushed at the terminal. The header file
0129 ListGroupsMaterialDifference.h is automatically created.
0130
0131 """
0132
0133 getTrackerRecoMaterialCopy(args.xml, LOCAL_RM)
0134 tracker_reco_material = LOCAL_RM
0135 tracker_reco_material_updated = os.path.join(os.environ['CMSSW_BASE'],
0136 'src/SimTracker/TrackerMaterialAnalysis/test/trackerRecoMaterial.xml')
0137 if not os.path.exists(tracker_reco_material_updated):
0138 tracker_reco_material_updated = './trackerRecoMaterial.xml'
0139 if not os.path.exists(tracker_reco_material_updated):
0140 raise os.error('Missing trackerRecoMaterial.xml file.')
0141 ET.register_namespace('', "http://www.cern.ch/cms/DDL")
0142 tree = ET.parse(tracker_reco_material)
0143 root = tree.getroot()
0144 tree_updated = ET.parse(tracker_reco_material_updated)
0145 root_updated = tree_updated.getroot()
0146 sections = root.getchildren()
0147
0148 header = open(os.path.join(os.environ['CMSSW_BASE'],
0149 'src/SimTracker/TrackerMaterialAnalysis/plugins/ListGroupsMaterialDifference.h'), 'w')
0150 header.write(HEADER)
0151 differences = {}
0152 values = {}
0153 ordered_keys = []
0154 for spec_par in root.iter('%sSpecPar' % TAG_PREFIX):
0155 current_detector = spec_par.attrib['name']
0156 ordered_keys.append(current_detector)
0157 for parameter in spec_par.iter('%sParameter' % TAG_PREFIX):
0158 updated_current_detector_node = root_updated.find(".//%sSpecPar[@name='%s']" % (TAG_PREFIX,current_detector))
0159 if updated_current_detector_node is not None:
0160 for child in updated_current_detector_node:
0161 name = child.get('name', None)
0162 if name and name == parameter.attrib['name']:
0163 differences.setdefault(current_detector, {}).setdefault(name, [float(parameter.attrib['value']),
0164 float(child.attrib['value']),
0165 ((float(child.attrib['value'])-float(parameter.attrib['value']))
0166 /float(parameter.attrib['value'])*100.)]
0167 )
0168 else:
0169 print('Element not found: %s' % current_detector)
0170 for group in differences.keys():
0171 header.write(' m_diff["%s"] = std::make_pair<float, float>(%f, %f);\n' % (group,
0172 differences[group]['TrackerRadLength'][2],
0173 differences[group]['TrackerXi'][2]))
0174 for group in differences.keys():
0175 header.write(' m_values["%s"] = std::make_pair<float, float>(%f, %f);\n' % (group,
0176 differences[group]['TrackerRadLength'][1],
0177 differences[group]['TrackerXi'][1]))
0178
0179 for i in xrange(len(ordered_keys)):
0180 key = ordered_keys[i]
0181 if args.twiki:
0182 print("| %s | %f | %f | %f%% | %f | %f | %f%% |" % (key,
0183 differences[key]['TrackerRadLength'][0],
0184 differences[key]['TrackerRadLength'][1],
0185 differences[key]['TrackerRadLength'][2],
0186 differences[key]['TrackerXi'][0],
0187 differences[key]['TrackerXi'][1],
0188 differences[key]['TrackerXi'][2]
0189 ))
0190 else:
0191 print("%s %f %f %f%% %f %f %f%%" % (key,
0192 differences[key]['TrackerRadLength'][0],
0193 differences[key]['TrackerRadLength'][1],
0194 differences[key]['TrackerRadLength'][2],
0195 differences[key]['TrackerXi'][0],
0196 differences[key]['TrackerXi'][1],
0197 differences[key]['TrackerXi'][2]
0198 ))
0199 header.write(TRAILER)
0200 header.close
0201
0202 def createTMGFromRelease(args):
0203 """
0204 Create a local TrackingMaterialGroup file starting from
0205 a tracking material reco XML file in release. This is
0206 useful for the very first time the users want to test a
0207 geoemetry for which no such file has ever been created
0208 in this package.
0209 """
0210 tracker_reco_material = checkFileInRelease(args.createTMG)
0211 if not tracker_reco_material:
0212 print("Input file not found in release, quitting")
0213 sys.exit(1)
0214 ET.register_namespace('', "http://www.cern.ch/cms/DDL")
0215 tree = ET.parse(tracker_reco_material)
0216 root = tree.getroot()
0217 sections = root.getchildren()
0218
0219 for spec_par in root.iter('%sSpecPar' % TAG_PREFIX):
0220 spec_par.attrib.pop('eval', None)
0221
0222 to_be_removed = []
0223 for parameter in spec_par.iter('%sParameter' % TAG_PREFIX):
0224 to_be_removed.append(parameter)
0225 el = ET.Element("Parameter")
0226 el.set('name', 'TrackingMaterialGroup')
0227 el.set('value', spec_par.attrib['name'])
0228 spec_par.append(el)
0229 for d in to_be_removed:
0230 spec_par.remove(d)
0231 tree.write('trackingMaterialGroupFromRelease.xml', encoding='UTF-8', xml_declaration=True)
0232
0233 if __name__ == '__main__':
0234 parser = argparse.ArgumentParser(description='Easily manipulate and inspect XML files related to Tracking Material.')
0235 parser.add_argument('-x', '--xml',
0236 default = 'src/Geometry/TrackerRecoData/data/trackerRecoMaterial.xml',
0237 help="""Source XML file used to perform
0238 all actions against it.
0239 For PhaseI use:
0240 src/Geometry/TrackerRecoData/data/PhaseI/pixfwd/trackerRecoMaterial.xml
0241 For phaseII use:
0242 src/Geometry/TrackerRecoData/data/PhaseII/TiltedTracker/trackerRecoMaterial.xml
0243 """,
0244 required=False)
0245 parser.add_argument('-p', '--produce', action='store_true',
0246 default=False,
0247 help='Produce a trackerRecoMaterial.xml starting from the paramters.xml file produced by the trackingMaterialProducer.')
0248 parser.add_argument('-c', '--compare', action='store_true',
0249 default=False,
0250 help='Compares a local trackerRecoMaterial.xml against the one bundled with the release.')
0251 parser.add_argument('-w', '--twiki', action='store_true',
0252 default=False,
0253 help="""Compares a local trackerRecoMaterial.xml against the one bundled
0254 with the release and produces and output that is Twiki compatible
0255 to be put into a table.""")
0256 parser.add_argument('--createTMG',
0257 help="""Given an input trackerRecoMaterial.xml from the release,
0258 it will produce locally a trackingMaterialGroups.xml files.
0259 The main difference is the addition of a proper naming
0260 parameter, so that the listGroups will be able to identify
0261 and print the detectors gathered in a single group.
0262 No definition of radiation length nor energy loss is
0263 maintained in the converion process. It is mainly useful
0264 only at the very beginnig of the tuning process, when
0265 maybe a local trackingMaterialGroups is missing.""")
0266 parser.add_argument('-v', '--verbose',
0267 default=False,
0268 help="""Be verbose while performing
0269 the required action""",
0270 action='store_true')
0271 args = parser.parse_args()
0272 checkEnvironment()
0273 if args.produce:
0274 produceXMLFromParameterFile(args)
0275 if args.compare or args.twiki:
0276 compareNewXMLWithOld(args)
0277 if args.createTMG != None:
0278 createTMGFromRelease(args)