Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-11-27 03:18:08

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