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