Пример #1
0
    def DrawMATPLOTLIB(self, histos, scales, ref, irelhisto, filenamePy,
                       outputnames):

        # Is there any legend?
        legendmode = False
        if len(self.main.datasets) > 1:
            legendmode = True

        # Type of histogram
        frequencyhisto = True
        for histo in histos:
            if histo.__class__.__name__ != 'HistogramFrequency':
                frequencyhisto = False
                break
        logxhisto = True
        for histo in histos:
            if histo.__class__.__name__ != 'HistogramLogX':
                logxhisto = False
                break

        # Stacking or superimposing histos ?
        stackmode = False
        if ref.stack==StackingMethodType.STACK or \
           ( ref.stack==StackingMethodType.AUTO and \
             self.main.stack==StackingMethodType.STACK ):
            stackmode = True

        # Open the file in write-mode
        try:
            outputPy = file(filenamePy, 'w')
        except:
            logging.getLogger('MA5').error('Impossible to write the file: ' +
                                           filenamePy)
            return False

        # File header
        function_name = filenamePy[:-3]
        function_name = function_name.split('/')[-1]
        outputPy.write('def ' + function_name + '():\n')
        outputPy.write('\n')

        # Import Libraries
        outputPy.write('    # Library import\n')
        outputPy.write('    import numpy\n')
        outputPy.write('    import matplotlib\n')
        #        outputPy.write("    matplotlib.use('Agg')\n")
        outputPy.write('    import matplotlib.pyplot   as plt\n')
        outputPy.write('    import matplotlib.gridspec as gridspec\n')
        outputPy.write('\n')

        # Matplotlib & numpy version
        outputPy.write('    # Library version\n')
        outputPy.write('    matplotlib_version = matplotlib.__version__\n')
        outputPy.write('    numpy_version      = numpy.__version__\n')
        outputPy.write('\n')

        # Binning
        # Loop over datasets and histos
        xnbin = histos[0].nbins
        xmin = histos[0].xmin
        xmax = histos[0].xmax
        outputPy.write('    # Histo binning\n')
        if logxhisto:
            outputPy.write('    xBinning = [')
            for bin in range(1, xnbin + 2):
                if bin != 1:
                    outputPy.write(',')
                outputPy.write(str(histos[0].GetBinLowEdge(bin)))
            outputPy.write(']\n')
            outputPy.write('\n')
        else:
            outputPy.write('    xBinning = numpy.linspace('+\
                           str(xmin)+','+str(xmax)+','+str(xnbin+1)+\
                           ',endpoint=True)\n')
        outputPy.write('\n')

        # Data
        outputPy.write('    # Creating data sequence: middle of each bin\n')
        outputPy.write('    xData = numpy.array([')
        for bin in range(0, xnbin):
            if bin != 0:
                outputPy.write(',')
            outputPy.write(str(histos[0].GetBinMean(bin)))
        outputPy.write('])\n\n')

        # Loop over datasets and histos
        ntot = 0
        for ind in range(0, len(histos)):

            # Ntot

            # Creating a new histo
            histoname = 'y' + histos[ind].name + '_' + str(ind)
            outputPy.write('    # Creating weights for histo: ' + histoname +
                           '\n')
            outputPy.write('    ' + histoname + '_weights = numpy.array([')
            for bin in range(1, xnbin + 1):
                ntot += histos[ind].summary.array[bin - 1] * scales[ind]
                if bin != 1:
                    outputPy.write(',')
                outputPy.write(
                    str(histos[ind].summary.array[bin - 1] * scales[ind]))
            outputPy.write('])\n\n')

        # Canvas
        outputPy.write('    # Creating a new Canvas\n')
        dpi = 80
        height = 500
        widthx = 700
        if legendmode:
            widthx = 1000
        outputPy.write('    fig   = plt.figure(figsize=('+\
                       str(widthx/dpi)+','+str(height/dpi)+\
                       '),dpi='+str(dpi)+')\n')
        if not legendmode:
            outputPy.write('    frame = gridspec.GridSpec(1,1)\n')
        else:
            outputPy.write('    frame = gridspec.GridSpec(1,1,right=0.7)\n')
        # subplot argument: nrows, ncols, plot_number
        # outputPy.write('    pad = fig.add_subplot(111)\n')
        outputPy.write('    pad   = fig.add_subplot(frame[0])\n')
        outputPy.write('\n')

        # Stack
        outputPy.write('    # Creating a new Stack\n')
        for ind in range(len(histos) - 1, -1, -1):
            myweight = 'y' + histos[ind].name + '_' + str(ind) + '_weights'
            mytitle = '"' + PlotFlow.NiceTitleMatplotlib(
                self.main.datasets[ind].title) + '"'
            mytitle = mytitle.replace('_', '\_')

            if not stackmode:
                myweights = 'y' + histos[ind].name + '_' + str(
                    ind) + '_weights'
            else:
                myweights = ''
                for ind2 in range(0, ind + 1):
                    if ind2 >= 1:
                        myweights += '+'
                    myweights += 'y' + histos[ind2].name + '_' + str(
                        ind2) + '_weights'

            # reset
            linecolor = 0
            linestyle = 0
            backcolor = 0
            backstyle = 0
            linewidth = 1

            # Setting AUTO settings
            if len(histos) == 1:
                linecolor1 = [9]
                linecolor = linecolor1[ind]
                if stackmode:
                    backstyle1 = [3004]
                    backstyle = backstyle1[ind]
                    backcolor = linecolor1[ind]
            elif len(histos) == 2:
                linecolor2 = [9, 46]
                linecolor = linecolor2[ind]
                if stackmode:
                    backstyle2 = [3004, 3005]
                    backstyle = backstyle2[ind]
                    backcolor = linecolor2[ind]
            elif len(histos) == 3:
                linecolor3 = [9, 46, 8]
                linecolor = linecolor3[ind]
                if stackmode:
                    backstyle3 = [3004, 3005, 3006]
                    backstyle = backstyle3[ind]
                    backcolor = linecolor3[ind]
            elif len(histos) == 4:
                linecolor4 = [9, 46, 8, 4]
                linecolor = linecolor4[ind]
                if stackmode:
                    backstyle4 = [3004, 3005, 3006, 3007]
                    backstyle = backstyle4[ind]
                    backcolor = linecolor4[ind]
            elif len(histos) == 5:
                linecolor5 = [9, 46, 8, 4, 6]
                linecolor = linecolor5[ind]
                if stackmode:
                    backstyle5 = [3004, 3005, 3006, 3007, 3013]
                    backstyle = backstyle5[ind]
                    backcolor = linecolor5[ind]
            elif len(histos) == 6:
                linecolor6 = [9, 46, 8, 4, 6, 2]
                linecolor = linecolor6[ind]
                if stackmode:
                    backstyle6 = [3004, 3005, 3006, 3007, 3013, 3017]
                    backstyle = backstyle6[ind]
                    backcolor = linecolor6[ind]
            elif len(histos) == 7:
                linecolor7 = [9, 46, 8, 4, 6, 2, 7]
                linecolor = linecolor7[ind]
                if stackmode:
                    backstyle7 = [3004, 3005, 3006, 3007, 3013, 3017, 3022]
                    backstyle = backstyle7[ind]
                    backcolor = linecolor7[ind]
            elif len(histos) == 8:
                linecolor8 = [9, 46, 8, 4, 6, 2, 7, 3]
                linecolor = linecolor8[ind]
                if stackmode:
                    backstyle8 = [
                        3004, 3005, 3006, 3007, 3013, 3017, 3022, 3315
                    ]
                    backstyle = backstyle8[ind]
                    backcolor = linecolor8[ind]
            elif len(histos) == 9:
                linecolor9 = [9, 46, 8, 4, 6, 2, 7, 3, 42]
                linecolor = linecolor9[ind]
                if stackmode:
                    backstyle9 = [
                        3004, 3005, 3006, 3007, 3013, 3017, 3022, 3315, 3351
                    ]
                    backstyle = backstyle9[ind]
                    backcolor = linecolor9[ind]
            elif len(histos) == 10:
                linecolor10 = [9, 46, 8, 4, 6, 2, 7, 3, 42, 48]
                linecolor = linecolor10[ind]
                if stackmode:
                    backstyle10 = [
                        3004, 3005, 3006, 3007, 3013, 3017, 3022, 3315, 3351,
                        3481
                    ]
                    backstyle = backstyle10[ind]
                    backcolor = linecolor10[ind]
            else:
                linecolor = self.color
                self.color += 1

            # lineStyle
            linestyle = LineStyleType.convert2code(
                self.main.datasets[ind].linestyle)

            # linewidth
            linewidth = self.main.datasets[ind].linewidth

            # background color
            if self.main.datasets[ind].backcolor != ColorType.AUTO:
                backcolor=ColorType.convert2root( \
                          self.main.datasets[ind].backcolor,\
                          self.main.datasets[ind].backshade)

            # background style
            if self.main.datasets[ind].backstyle != BackStyleType.AUTO:
                backstyle=BackStyleType.convert2matplotlib( \
                          self.main.datasets[ind].backstyle)

            mylinecolor = '"' + madanalysis.enumeration.color_hex.color_hex[
                linecolor] + '"'
            mybackcolor = '"' + madanalysis.enumeration.color_hex.color_hex[
                backcolor] + '"'

            filledmode = '"stepfilled"'
            rWidth = 1.
            if backcolor == 0:  #invisible
                filledmode = '"step"'
                mybackcolor = 'None'
#            if frequencyhisto:
#                filledmode='"bar"'
#                rWidth=0.8
            mylinewidth = self.main.datasets[ind].linewidth
            mylinestyle = LineStyleType.convert2matplotlib(
                self.main.datasets[ind].linestyle)

            outputPy.write('    pad.hist('+\
                               'x=xData, '+\
                               'bins=xBinning, '+\
                               'weights='+myweights+',\\\n'+\
                               '             label='+mytitle+', ')
            if ntot != 0:
                outputPy.write('histtype=' + filledmode + ', ')
            outputPy.write(    'rwidth='+str(rWidth)+',\\\n'+\
                               '             color='+mybackcolor+', '+\
                               'edgecolor='+mylinecolor+', '+\
                               'linewidth='+str(mylinewidth)+', '+\
                               'linestyle='+mylinestyle+',\\\n'+\
                               '             bottom=None, '+\
                               'cumulative=False, normed=False, align="mid", orientation="vertical")\n\n')
        outputPy.write('\n')

        # Label
        outputPy.write('    # Axis\n')
        outputPy.write("    plt.rc('text',usetex=False)\n")

        # X-axis
        if ref.titleX == "":
            axis_titleX = ref.GetXaxis_Matplotlib()
        else:
            axis_titleX = ref.titleX
        axis_titleX = axis_titleX.replace('#DeltaR', '#Delta R')
        axis_titleX = axis_titleX.replace('#', '\\')
        outputPy.write('    plt.xlabel(r"' + axis_titleX + '",\\\n')
        outputPy.write('               fontsize=16,color="black")\n')

        # Y-axis
        axis_titleY = ref.GetYaxis_Matplotlib()

        # Scale to one ?
        scale2one = False
        if ref.stack==StackingMethodType.NORMALIZE2ONE or \
           (self.main.stack==StackingMethodType.NORMALIZE2ONE and \
           ref.stack==StackingMethodType.AUTO):
            scale2one = True

        if scale2one:
            axis_titleY += " $(#mathrm{scaled}\ #mathrm{to}# #mathrm{one})$"
        elif self.main.normalize == NormalizeType.LUMI or \
           self.main.normalize == NormalizeType.LUMI_WEIGHT:
            axis_titleY += " $(#mathcal{L}_{#mathrm{int}} = " + str(
                self.main.lumi) + "# #mathrm{fb}^{-1})$ "
        elif self.main.normalize == NormalizeType.NONE:
            axis_titleY += " $(#mathrm{not}# #mathrm{normalized})$"

        if ref.titleY != "":
            axis_titleY = PlotFlow.NiceTitle(ref.titleY)
        axis_titleY = axis_titleY.replace('#', '\\')
        outputPy.write('    plt.ylabel(r"' + axis_titleY + '",\\\n')
        outputPy.write('               fontsize=16,color="black")\n')
        outputPy.write('\n')

        # Tag Log/Linear
        is_logx = False
        if ref.logX and ntot != 0:
            is_logx = True
        is_logy = False
        if ref.logY and ntot != 0:
            is_logy = True

        # Bound y
        outputPy.write('    # Boundary of y-axis\n')
        myweights = ''
        if stackmode:
            for ind in range(0, len(histos)):
                if ind >= 1:
                    myweights += '+'
                myweights += 'y' + histos[ind].name + '_' + str(
                    ind) + '_weights'
        else:
            myweights = 'numpy.array(['
            for ind in range(0, len(histos)):
                if ind >= 1:
                    myweights += ','
                myweights += 'y' + histos[ind].name + '_' + str(
                    ind) + '_weights.max()'
            myweights += '])'
        outputPy.write('    ymax=(' + myweights + ').max()*1.1\n')
        outputPy.write('    ')
        if is_logy:
            outputPy.write('#')
        outputPy.write('ymin=0 # linear scale\n')

        myweights = ''
        if stackmode:
            for ind in range(0, len(histos)):
                if ind >= 1:
                    myweights += '+'
                myweights += 'y' + histos[ind].name + '_' + str(
                    ind) + '_weights'
        else:
            myweights = 'numpy.array(['
            for ind in range(0, len(histos)):
                if ind >= 1:
                    myweights += ','
                myweights += 'y' + histos[ind].name + '_' + str(
                    ind) + '_weights.min()'
            myweights += ',1.])'
        outputPy.write('    ')
        if not is_logy:
            outputPy.write('#')
        outputPy.write('ymin=min([x for x in (' + myweights +
                       ') if x])/100. # log scale\n')
        outputPy.write('    plt.gca().set_ylim(ymin,ymax)\n')
        outputPy.write('\n')

        # X axis
        outputPy.write('    # Log/Linear scale for X-axis\n')
        # - Linear
        outputPy.write('    ')
        if is_logx:
            outputPy.write('#')
        outputPy.write('plt.gca().set_xscale("linear")\n')
        # - Log
        outputPy.write('    ')
        if not is_logx:
            outputPy.write('#')
        outputPy.write('plt.gca().set_xscale("log",nonposx="clip")\n')
        outputPy.write('\n')

        # Y axis
        outputPy.write('    # Log/Linear scale for Y-axis\n')
        # - Linear
        outputPy.write('    ')
        if is_logy:
            outputPy.write('#')
        outputPy.write('plt.gca().set_yscale("linear")\n')
        # - Log
        outputPy.write('    ')
        if not is_logy:
            outputPy.write('#')
        outputPy.write('plt.gca().set_yscale("log",nonposy="clip")\n')
        outputPy.write('\n')

        # Labels
        if frequencyhisto:
            outputPy.write('    # Labels for x-Axis\n')
            outputPy.write('    xLabels = numpy.array([')
            for bin in range(0, xnbin):
                if bin >= 1:
                    outputPy.write(',')
                outputPy.write(
                    '"' + str(histos[0].stringlabels[bin]).replace('_', '\_') +
                    '"')
            outputPy.write('])\n')
            outputPy.write(
                '    plt.xticks(xData, xLabels, rotation="vertical")\n')
            outputPy.write('\n')

### BENJ: not necessary for getting the png and pdf files
# Draw
#        outputPy.write('    # Draw\n')
#        outputPy.write('    plt.show()\n')
#        outputPy.write('\n')

# Legend
        if legendmode:

            # Reminder for 'loc'
            # -'best'         : 0, (only implemented for axes legends)
            # -'upper right'  : 1,
            # -'upper left'   : 2,
            # -'lower left'   : 3,
            # -'lower right'  : 4,
            # -'right'        : 5,
            # -'center left'  : 6,
            # -'center right' : 7,
            # -'lower center' : 8,
            # -'upper center' : 9,
            # -'center'       : 10,

            outputPy.write('    # Legend\n')
            outputPy.write('    plt.legend(bbox_to_anchor=(1.05,1), loc=2,'+\
                                ' borderaxespad=0.)\n')
            outputPy.write('\n')

        # Producing the image
        outputPy.write('    # Saving the image\n')
        for outputname in outputnames:
            outputPy.write("    plt.savefig('" + outputname + "')\n")
        outputPy.write('\n')

        # Call the function
        outputPy.write('# Running!\n')
        outputPy.write("if __name__ == '__main__':\n")
        outputPy.write('    ' + function_name + '()\n')

        # Close the file
        try:
            outputPy.close()
        except:
            logging.getLogger('MA5').error('Impossible to close the file: ' +
                                           outputPy)
            return False

        # Ok
        return True