Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:45:59

0001 from __future__ import print_function
0002 from __future__ import absolute_import
0003 from builtins import range
0004 import abc
0005 import math
0006 import os
0007 import re
0008 
0009 from .genericValidation import ValidationForPresentation, ValidationWithPlotsSummary
0010 from .helperFunctions import recursivesubclasses
0011 from .presentationTemplates import *
0012 from .TkAlExceptions import AllInOneError
0013 
0014 # Plots related to a single validation:
0015 class ValidationPlots(object):
0016     def __init__(self, path):
0017         if not os.path.isdir(path):
0018             print("Error: Directory "+path+" not found!")
0019             exit(1)
0020         if not path.endswith('/'):
0021             path += '/'
0022         path = path.replace('\\', '/') # Beacause LaTeX has issues with '\'.
0023         self.path = path
0024         # List of plot files in given directory:
0025         self.plots = [file for file in os.listdir(path)
0026                       if file.endswith('.eps')]
0027 
0028     @property
0029     def validationclass(self):
0030         possiblenames = []
0031         for cls in recursivesubclasses(ValidationForPresentation):
0032             if cls.__abstractmethods__: continue
0033             if cls.plotsdirname() == os.path.basename(os.path.realpath(self.path.rstrip("/"))):
0034                 return cls
0035             possiblenames.append(cls.plotsdirname())
0036         raise AllInOneError("{} does not match any of the possible folder names:\n{}".format(self.path, ", ".join(possiblenames)))
0037 
0038 def validationclasses(validations):
0039     from collections import OrderedDict
0040     classes = [validation.validationclass for validation in validations]
0041     #remove duplicates - http://stackoverflow.com/a/39835527/5228524
0042     classes = list(OrderedDict.fromkeys(classes))
0043     return classes
0044 
0045 # Layout of plots on a page:
0046 class PageLayout(object):
0047     def __init__(self, pattern=[], width=1, height=1):
0048         self.pattern = [] # List of rows; row contains the order numbers
0049                           # of its plots; e.g. [[1,2,3], [4,5,6]]
0050         self.width = width # Maximum width of one plot,
0051                            # with respect to textwidth.
0052         self.height = height # Maximum height of one plot,
0053                              # with respect to textheight.
0054 
0055     # Sets variables for the given plots and returns the plots
0056     # in an appropriate order:
0057     def fit(self, plots):
0058         rowlengths = []
0059         # First, try to place plots in a square.
0060         nplots = sum(len(p) for p in plots)
0061         length = int(math.ceil(math.sqrt(nplots)))
0062         # Then, fill the square from the bottom and remove extra rows.
0063         fullRows = int(nplots/length)
0064         residual = nplots - length*fullRows
0065         nrows = fullRows
0066         if residual != 0:
0067             rowlengths.append(residual)
0068             nrows += 1
0069         for _ in range(fullRows):
0070             rowlengths.append(length)
0071 
0072         # Now, fill the pattern.
0073         self.pattern = []
0074         if residual == 0 and len(plots[0])%length != 0 and\
0075            len(plots[0])%nrows == 0:
0076             # It's better to arrange plots in columns, not rows.
0077             self.pattern.extend(list(range(i, i+nrows*(length-1)+1, nrows))
0078                                 for i in range(1, nrows+1))
0079         else:
0080             if residual != 0:
0081                 self.pattern.append(list(range(1, 1+residual)))
0082             self.pattern.extend(list(range(i, i+length)) for i in
0083                                 range(residual+1, nplots-length+2, length))
0084 
0085         self.width = 1.0/length
0086         self.height = 0.8/nrows
0087 
0088 
0089 # Write a set of pages, one for each subdetector.
0090 # Arguments: identifier: regular expression to get the wanted plots,
0091 #                        used together with subdetector name
0092 #            title: title of the plot type
0093 #            validations: list of relevant ValidationPlots objects.
0094 # Returns the parsed script.
0095 class SubsectionBase(object):
0096     __metaclass__ = abc.ABCMeta
0097     def __init__(self, title):
0098         self.title = title
0099     def write(self, validations):
0100         script = '\n'.join(_ for _ in self.pages(validations) if _)
0101         if script != '':
0102             script = subsectionTemplate.replace('[title]', self.title)+script
0103         return script
0104     @abc.abstractmethod
0105     def pages(self, validations):
0106         pass
0107 
0108 class SubsectionOnePage(SubsectionBase):
0109     def __init__(self, identifier, title):
0110         self.identifier = identifier
0111         super(SubsectionOnePage, self).__init__(title)
0112     def pages(self, validations):
0113         return [writePageReg(self.identifier, self.title, validations)]
0114 
0115 class SubsectionFromList(SubsectionBase):
0116     def __init__(self, identifier, title):
0117         self.identifier = identifier
0118         super(SubsectionFromList, self).__init__(title)
0119     def pages(self, validations):
0120         return [writePageReg('(?=.*%s)%s'%(pageidentifier, self.identifier),
0121                              self.title+': ' +pagetitle, validations)
0122                    for pageidentifier, pagetitle in self.pageidentifiers]
0123     @abc.abstractproperty
0124     def pageidentifiers(self):
0125         pass
0126 
0127 class SummarySection(SubsectionBase):
0128     def __init__(self):
0129         super(SummarySection, self).__init__("Summary")
0130     def pages(self, validations):
0131         return [summaryTemplate.replace('[title]', self.title)
0132                                .replace('[summary]', validation.validationclass.summaryitemsstring(folder=validation.path, latex=True))
0133                                .replace("tabular", "longtable") for validation in validations
0134                                                                 if issubclass(validation.validationclass, ValidationWithPlotsSummary)]
0135 
0136 # Write a page containing plots of given type.
0137 # Arguments: identifier: regular expression to get the wanted plots
0138 #            title: title of the plot type
0139 #            validations: list of relevant ValidationPlots objects
0140 #            layout: given page layout.
0141 # Returns the parsed script.
0142 def writePageReg(identifier, title, validations, layout=0):
0143     plots = []
0144     for validation in validations:
0145         valiplots = [validation.path+plot for plot in validation.plots
0146                      if re.search(identifier, plot)]
0147         valiplots.sort(key=plotSortKey)
0148         plots.append(valiplots)
0149     if sum(len(p) for p in plots) == 0:
0150         print('Warning: no plots matching ' + identifier)
0151         return ''
0152 
0153     # Create layout, if not given.
0154     if layout == 0:
0155         layout = PageLayout()
0156         layout.fit(plots)
0157 
0158     return writePage([p for vali in plots for p in vali], title, layout)
0159 
0160 
0161 # Write the given plots on a page.
0162 # Arguments: plots: paths of plots to be drawn on the page
0163 #            title: title of the plot type
0164 #            layout: a PageLayout object definig the layout.
0165 # Returns the parsed script.
0166 def writePage(plots, title, layout):
0167     plotrows = []
0168     for row in layout.pattern:
0169         plotrow = []
0170         for i in range(len(row)):
0171             plotrow.append(plotTemplate.replace('[width]', str(layout.width)).\
0172                            replace('[height]', str(layout.height)).\
0173                            replace('[path]', plots[row[i]-1]))
0174         plotrows.append('\n'.join(plotrow))
0175     script = ' \\\\\n'.join(plotrows)
0176 
0177     return frameTemplate.replace('[plots]', script).replace('[title]', title)
0178 
0179 
0180 # Sort key to rearrange a plot list.
0181 # Arguments: plot: to be sorted.
0182 def plotSortKey(plot):
0183     # Move normchi2 before chi2Prob
0184     if plot.find('normchi2') != -1:
0185         return 'chi2a'
0186     if plot.find('chi2Prob') != -1:
0187         return 'chi2b'
0188     return plot
0189 
0190 import Alignment.OfflineValidation.TkAlAllInOneTool.geometryComparison
0191 import Alignment.OfflineValidation.TkAlAllInOneTool.offlineValidation
0192 import Alignment.OfflineValidation.TkAlAllInOneTool.trackSplittingValidation
0193 import Alignment.OfflineValidation.TkAlAllInOneTool.primaryVertexValidation
0194 import Alignment.OfflineValidation.TkAlAllInOneTool.zMuMuValidation