Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 14:30:45

0001 #!/usr/bin/env python
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 #    pprint.pprint(differences)
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         # Cannot remove elements in place: store them all here and remove them later on.
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)