Пример #1
0
    def create_histograms(
            self, online_title, offline_title, versus_title, pileup_bins,
            res_n_bins, res_low, res_high, vs_n_bins, vs_low, vs_high):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.offline_title = offline_title
        self.versus_title = versus_title
        self.ymin = res_low
        self.ymax = res_high
        self.pileup_bins = bn.Sorted(pileup_bins, "pileup",
                                     use_everything_bin=True)

        nameTokens = [
            "resolution_vs", self.versus_name,
            self.online_name, self.offline_name, "pu_{pileup}",
        ]
        name = "__".join(nameTokens)
        title = 'Resolution ({online_name} vs. {offline_name}) '
        title += 'against {versus_name}'
        title = title.format(
            online_name=self.online_name,
            offline_name=self.offline_name,
            versus_name=self.versus_name,
        )
        title += " in PU bin: {pileup}"
        title = ";".join([title, self.offline_title, self.online_title])
        self.plots = HistogramCollection(
            [self.pileup_bins],
            "Hist2D", vs_n_bins, vs_low, vs_high,
            res_n_bins, res_low, res_high,
            name=name, title=title)
        self.filename_format = name
Пример #2
0
    def create_histograms(self,
                          online_title,
                          pileup_bins,
                          n_bins,
                          low,
                          high,
                          legend_title=""):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.pileup_bins = bn.Sorted(pileup_bins,
                                     "pileup",
                                     use_everything_bin=True)
        self.legend_title = legend_title

        name = ["rate_vs_threshold", self.online_name, "pu_{pileup}"]
        name = "__".join(name)
        title = " ".join([self.online_name, "vs.", "in PU bin: {pileup}"])
        title = ";".join([title, self.online_title])
        self.plots = HistogramCollection([self.pileup_bins],
                                         "Hist1D",
                                         n_bins,
                                         low,
                                         high,
                                         name=name,
                                         title=title)
        self.filename_format = name
    def create_histograms(self,
                          online_title,
                          thresholds,
                          n_bins,
                          low,
                          high,
                          legend_title=""):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.thresholds = thresholds
        self.thresholds = bn.GreaterThan(thresholds, "threshold", True)
        self.legend_title = legend_title
        name = ["rate_vs_pileup", self.online_name]
        name += ["thresh_{threshold}"]
        name = "__".join(name)
        title = " ".join([
            self.online_name, " rate vs pileup",
            "passing threshold: {threshold}"
        ])
        self.plots = HistogramCollection([self.thresholds],
                                         "Hist1D",
                                         n_bins,
                                         low,
                                         high,
                                         name=name,
                                         title=title)

        self.filename_format = name
Пример #4
0
    def create_histograms(
        self,
        online_title,
        offline_title,
        pileup_bins,
        n_bins,
        low,
        high=400.,
    ):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.offline_title = offline_title
        self.pileup_bins = bn.Sorted(
            pileup_bins,
            "pileup",
            use_everything_bin=True,
        )

        nameTokens = [
            "onlineVsOffline",
            self.online_name,
            self.offline_name,
            "pu_{pileup}",
        ]
        name = "__".join(nameTokens)
        title = " ".join([
            self.online_name,
            "vs.",
            self.offline_name,
            "in PU bin: {pileup}",
        ])
        title = ";".join([title, self.offline_title, self.online_title])
        if isinstance(low, np.ndarray):
            self.plots = HistogramCollection(
                [self.pileup_bins],
                "Hist2D",
                low,
                low,
                name=name,
                title=title,
            )
        else:
            self.plots = HistogramCollection(
                [self.pileup_bins],
                "Hist2D",
                n_bins,
                low,
                high,
                n_bins,
                low,
                high,
                name=name,
                title=title,
            )
        self.filename_format = name
Пример #5
0
    def create_histograms(self,
                          online_title,
                          offline_title,
                          pileup_bins,
                          thresholds,
                          n_bins,
                          low,
                          high=400,
                          legend_title=""):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.offline_title = offline_title
        self.pileup_bins = bn.Sorted(pileup_bins,
                                     "pileup",
                                     use_everything_bin=True)
        self.thresholds = bn.GreaterThan(thresholds, "threshold")
        self.legend_title = legend_title

        name = ["efficiency", self.online_name, self.offline_name]
        name += ["thresh_{threshold}", "pu_{pileup}"]
        name = "__".join(name)
        title = " ".join([
            self.online_name, " in PU bin: {pileup}",
            "and passing threshold: {threshold}"
        ])
        self.filename_format = name

        def make_efficiency(labels):
            this_name = "efficiency" + name.format(**labels)
            this_title = title.format(**labels)
            '''Checking type of 'low' to see whether it's int (x-range minimum)
                    or array (bin edges) for constructing TEfficiency'''
            if isinstance(low, np.ndarray):
                eff = asrootpy(
                    ROOT.TEfficiency(this_name, this_title, n_bins, low))
                self.x_max = 2000
            else:
                eff = asrootpy(
                    ROOT.TEfficiency(this_name, this_title, n_bins, low, high))
                self.x_max = high
            eff.drawstyle = EfficiencyPlot.drawstyle
            return eff

        self.efficiencies = HistogramCollection(
            [self.pileup_bins, self.thresholds], make_efficiency)
Пример #6
0
    def __fit_efficiencies(self):
        def make_fit(labels):
            pileup_bin = labels["pileup"]
            threshold_bin = labels["threshold"]
            efficiency = self.efficiencies.get_bin_contents(
                [pileup_bin, threshold_bin])
            params = fit_efficiency(
                efficiency, self.thresholds.get_bin_center(threshold_bin))
            return params

        # Actually make the efficiencies
        self.fits = HistogramCollection([self.pileup_bins, self.thresholds],
                                        make_fit)
Пример #7
0
class RateVsPileupPlot(BasePlotter):

    def __init__(self, online_name):
        name = ["rate_vs_pileup", online_name]
        super(RateVsPileupPlot, self).__init__("__".join(name))
        self.online_name = online_name

    def create_histograms(self,
                          online_title,
                          thresholds, n_bins, low, high, legend_title=""):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.thresholds = thresholds
        self.thresholds = bn.GreaterThan(thresholds, "threshold", True)
        self.legend_title = legend_title
        name = ["rate_vs_pileup", self.online_name]
        name += ["thresh_{threshold}"]
        name = "__".join(name)
        title = " ".join([self.online_name, " rate vs pileup",
                          "passing threshold: {threshold}"])
        self.plots = HistogramCollection([self.thresholds],
                                         "Hist1D", n_bins, low, high,
                                         name=name, title=title)

        self.filename_format = name

    def fill(self, pileup, online):
        self.plots[online].fill(pileup)

    def draw(self, with_fits=False):

        for (threshold, ), hist in self.plots.flat_items_all():
            hists = []
            labels = []
            fits = []
            thresholds = []
            if not isinstance(threshold, int):
                continue
            label_template = '{online_title} > {threshold} GeV'
            label = label_template.format(
                online_title=self.online_title,
                threshold=self.thresholds.bins[threshold],
            )
            hist.Divide(self.plots.get_bin_contents([bn.Base.everything]))
            hist.drawstyle = "EP"
            hist.SetMarkerColor(2)
            # if with_fits:
            #    fit = self.fits.get_bin_contents([threshold])
            #    fits.append(fit)
            hists.append(hist)
            labels.append(label)
            thresholds.append(threshold)

            self.__make_overlay(hists, fits, labels, thresholds)

    def overlay(self, other_plotters=None, with_fits=False, comp=False):

        hists = []
        labels = []
        fits = []
        thresholds = []
        suffix = '__emu_overlay'
        titles = ['Hw', 'Emu']
        if comp:
            suffix = '__comparison'
            titles = [other_plotter.comp_title for other_plotter in other_plotters]
            titles.insert(0, self.comp_title)

        for (threshold, ), hist in self.plots.flat_items_all():
            if not isinstance(threshold, int):
                continue
            label_template = '{online_title} > {threshold} GeV'
            label = label_template.format(
                online_title='L1 ' + titles[0],
                threshold=self.thresholds.bins[threshold],
            )
            hist.Divide(self.plots.get_bin_contents([bn.Base.everything]))
            hist.Scale(2855)
            hist.drawstyle = "EP"
            hist.SetMarkerColor(1)
            # if with_fits:
            #    fit = self.fits.get_bin_contents([threshold])
            #    fits.append(fit)
            hists.append(hist)
            labels.append(label)
            thresholds.append(threshold)
        for other_plotter in other_plotters:
            for (threshold, ), hist in other_plotter.plots.flat_items_all():
                if not isinstance(threshold, int):
                    continue
                label_template = '{online_title} > {threshold} GeV'
                label = label_template.format(
                    online_title='L1 ' + titles[other_plotters.index(other_plotter) + 1],
                    threshold=other_plotter.thresholds.bins[threshold],
                )
                hist.Divide(other_plotter.plots.get_bin_contents([bn.Base.everything]))
                hist.Scale(2855)
                hist.drawstyle = "EP"
                hist.SetMarkerColor(2)
                hist.markerstyle = 21 + other_plotters.index(other_plotter)
                # if with_fits:
                #    fit = self.fits.get_bin_contents([threshold])
                #    fits.append(fit)
                hists.append(hist)
                labels.append(label)
                thresholds.append(threshold)

        self.__make_overlay(hists, fits, labels, thresholds, suffix)

    def __make_overlay(self, hists, fits, labels, thresholds, suffix=""):
        with preserve_current_style():
            # Draw each rate vs pileup (with fit)
            xtitle = "< \\mu >"
            ytitle = "Rate (kHz)"
            canvas = draw(hists, draw_args={"xtitle": xtitle, "ytitle": ytitle, "xlimits": (20, 50), "ylimits": (0, 5)})
            if fits:
                for fit, hist in zip(fits, hists):
                    fit["asymmetric"].linecolor = hist.GetLineColor()
                    fit["asymmetric"].Draw("same")

            # Add labels
            label_canvas()

            # Add a legend
            legend = Legend(
                len(hists),
                header=self.legend_title,
                topmargin=0.02,
                leftmargin=0.22,
                rightmargin=0.78,
                textsize=0.025,
                entryheight=0.028,
            )

            for hist, label in zip(hists, labels):
                legend.AddEntry(hist, label)

            legend.SetBorderSize(0)
            legend.Draw()

            # Save canvas to file
            name = self.filename_format.format(threshold=thresholds[0])
            self.save_canvas(canvas, name + suffix)

    def _is_consistent(self, new):
        """
        Check the two plotters are the consistent, so same binning and same axis names
        """
        return all([self.thresholds.bins == new.thresholds.bins,
                    self.online_name == new.online_name,
                    ])

    def _merge(self, other):
        """
        Merge another plotter into this one
        """
        self.plots += other.plots
        return self.plots

    def get_stats(self, summary_bins=[], summary_label=''):
        summary_columns = list(self._summary_columns(summary_bins, summary_label))
        stats = list(self._collect_stats(summary_bins, summary_label))
        df = pd.DataFrame(stats)
        return df[['identifier', 'total', 'overflow'] + summary_columns]

    def _summary_columns(self, summary_bins, summary_label):
        for lower, upper in zip(summary_bins[:-1], summary_bins[1:]):
            yield '{} {}-{}'.format(summary_label, lower, upper)

    def _collect_stats(self, summary_bins, summary_label):
        normalisation = self.plots.get_bin_contents([bn.Base.everything]).integral(overflow=True)
        for (threshold, ), hist in self.plots.flat_items():
            human_readable_threshold = '{0} > {1} GeV'.format(self.online_title, self.thresholds.bins[threshold])
            rhist = hist.rebinned(summary_bins)
            stats = {}
            summary_columns = self._summary_columns(summary_bins, summary_label)
            for summary_column, y in zip(summary_columns, rhist.y()):
                stats[summary_column] = y * normalisation
            total = sum(stats.values())
            overflow = rhist.integral(overflow=True) * normalisation - total
            header = dict(identifier=human_readable_threshold, total=total, overflow=overflow)
            header.update(stats)
            yield header
Пример #8
0
class EfficiencyPlot(BasePlotter):
    drawstyle = 'HIST'
    drawstyle_data = 'P'
    markerstyle_overlay = 23

    def __init__(self, online_name, offline_name):
        name = ["efficiency", online_name, offline_name]
        super(EfficiencyPlot, self).__init__("__".join(name))
        self.online_name = online_name
        self.offline_name = offline_name

    def create_histograms(self,
                          online_title,
                          offline_title,
                          pileup_bins,
                          thresholds,
                          n_bins,
                          low,
                          high=400,
                          legend_title=""):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.offline_title = offline_title
        self.pileup_bins = bn.Sorted(pileup_bins,
                                     "pileup",
                                     use_everything_bin=True)
        self.thresholds = bn.GreaterThan(thresholds, "threshold")
        self.legend_title = legend_title

        name = ["efficiency", self.online_name, self.offline_name]
        name += ["thresh_{threshold}", "pu_{pileup}"]
        name = "__".join(name)
        title = " ".join([
            self.online_name, " in PU bin: {pileup}",
            "and passing threshold: {threshold}"
        ])
        self.filename_format = name

        def make_efficiency(labels):
            this_name = "efficiency" + name.format(**labels)
            this_title = title.format(**labels)
            '''Checking type of 'low' to see whether it's int (x-range minimum)
                    or array (bin edges) for constructing TEfficiency'''
            if isinstance(low, np.ndarray):
                eff = asrootpy(
                    ROOT.TEfficiency(this_name, this_title, n_bins, low))
                self.x_max = 2000
            else:
                eff = asrootpy(
                    ROOT.TEfficiency(this_name, this_title, n_bins, low, high))
                self.x_max = high
            eff.drawstyle = EfficiencyPlot.drawstyle
            return eff

        self.efficiencies = HistogramCollection(
            [self.pileup_bins, self.thresholds], make_efficiency)

    def fill(self, pileup, offline, online):
        efficiencies = {
            (pu, thresh): eff
            for (pu, ), thresholds in self.efficiencies[pileup].items()
            for thresh, eff in thresholds.items()
        }
        for (pu_bin, threshold_bin), efficiency in efficiencies.items():
            threshold = self.thresholds.get_bin_center(threshold_bin)
            passed = False
            if isinstance(threshold, str):
                continue
            elif online > threshold:
                passed = True
            efficiency.fill(passed, offline)

    def draw(self, with_fits=False):
        # Fit the efficiencies if requested
        if with_fits:
            self.__fit_efficiencies()

        # Overlay the "all" pile-up bin for each threshold
        all_pileup_effs = self.efficiencies.get_bin_contents(
            [bn.Base.everything])
        hists = []
        labels = []
        fits = []
        label_template = '{online_title} > {threshold} GeV'
        for threshold in all_pileup_effs.iter_all():
            if not isinstance(threshold, int):
                continue
            hist = all_pileup_effs.get_bin_contents(threshold)
            hist.drawstyle = EfficiencyPlot.drawstyle
            hists.append(hist)

            label = label_template.format(
                online_title=self.online_title,
                threshold=self.thresholds.bins[threshold],
            )
            labels.append(label)
            if with_fits:
                fits.append(
                    self.fits.get_bin_contents([bn.Base.everything,
                                                threshold]))
        self.__make_overlay(
            "all",
            "all",
            hists,
            fits,
            labels,
            self.online_title,
        )

        # Overlay individual pile-up bins for each threshold
        for threshold in self.thresholds:
            hists = []
            labels = []
            fits = []
            for pileup in self.pileup_bins:
                if not isinstance(pileup, int):
                    continue
                hist = self.efficiencies.get_bin_contents([pileup, threshold])
                hist.drawstyle = EfficiencyPlot.drawstyle_data
                hists.append(hist)
                if with_fits:
                    fits.append(self.fits.get_bin_contents([pileup,
                                                            threshold]))
                labels.append(str(self.pileup_bins.bins[pileup]))
            self.__make_overlay(pileup, threshold, hists, fits, labels,
                                "PU bin")

        # Produce the fit summary plot
        if with_fits:
            self.__summarize_fits()

    def overlay_with_emu(self, emu_plotter, with_fits=False):
        # Fit the efficiencies if requested
        if with_fits:
            self.__fit_efficiencies()

        # Overlay the "all" pile-up bin for each threshold
        all_pileup_effs = self.efficiencies.get_bin_contents(
            [bn.Base.everything])
        emu_pileup_effs = emu_plotter.efficiencies.get_bin_contents(
            [bn.Base.everything])
        hists = []
        labels = []
        fits = []
        ROOT.gStyle.SetErrorX(0.)
        label_template = '{online_title} > {threshold} GeV'
        for threshold in all_pileup_effs.iter_all():
            if not isinstance(threshold, int):
                continue
            hist = all_pileup_effs.get_bin_contents(threshold)
            hist.drawstyle = EfficiencyPlot.drawstyle_data
            hists.append(hist)

            label = label_template.format(
                online_title=self.online_title,
                threshold=self.thresholds.bins[threshold],
            )
            labels.append(label)
            if with_fits:
                fits.append(
                    self.fits.get_bin_contents([bn.Base.everything,
                                                threshold]))

        for threshold in emu_pileup_effs.iter_all():
            if not isinstance(threshold, int):
                continue
            hist = emu_pileup_effs.get_bin_contents(threshold)
            hist.drawstyle = EfficiencyPlot.drawstyle_data
            hist.markerstyle = EfficiencyPlot.markerstyle_overlay
            hists.append(hist)

            label = label_template.format(
                online_title=emu_plotter.online_title + ' Emu',
                threshold=emu_plotter.thresholds.bins[threshold],
            )
            labels.append(label)
            if with_fits:
                fits.append(
                    emu_plotter.fits.get_bin_contents(
                        [bn.Base.everything, threshold]))

        self.__make_overlay(
            "all",
            "all_overlay_with_Emu",
            hists,
            fits,
            labels,
            self.online_title,
        )
        '''
        # Overlay individual pile-up bins for each threshold
        for threshold in self.thresholds:
            hists = []
            labels = []
            fits = []
            for pileup in self.pileup_bins:
                if not isinstance(pileup, int):
                    continue
                hist = self.efficiencies.get_bin_contents([pileup, threshold])
                hist.drawstyle = "EP"
                hists.append(hist)
                if with_fits:
                    fits.append(self.fits.get_bin_contents(
                        [pileup, threshold]))
                labels.append(str(self.pileup_bins.bins[pileup]))
            self.__make_overlay(pileup, threshold, hists,
                                fits, labels, "PU bin")
        '''
        # Produce the fit summary plot
        if with_fits:
            self.__summarize_fits()

    def __fit_efficiencies(self):
        def make_fit(labels):
            pileup_bin = labels["pileup"]
            threshold_bin = labels["threshold"]
            efficiency = self.efficiencies.get_bin_contents(
                [pileup_bin, threshold_bin])
            params = fit_efficiency(
                efficiency, self.thresholds.get_bin_center(threshold_bin))
            return params

        # Actually make the efficiencies
        self.fits = HistogramCollection([self.pileup_bins, self.thresholds],
                                        make_fit)

    def __make_overlay(self, pileup, threshold, hists, fits, labels, header):
        with preserve_current_style():
            name = self.filename_format.format(pileup=pileup,
                                               threshold=threshold)
            # Draw each efficiency (with fit)
            draw_args = {"xtitle": self.offline_title, "ytitle": "Efficiency"}
            # TODO: special case should not be implemented here!
            if 'Jet' in name and 'HiRange' in name:
                draw_args['xlimits'] = [20, 2000]

            canvas = draw(hists, draw_args=draw_args)
            if len(fits) > 0:
                for fit, hist in zip(fits, hists):
                    fit["asymmetric"].linecolor = hist.GetLineColor()
                    fit["asymmetric"].Draw("same")

            # Add labels
            label_canvas()

            # Add a legend
            legend = Legend(
                len(hists),
                header=self.legend_title,
                topmargin=0.35,
                rightmargin=0.3,
                leftmargin=0.7,
                textsize=0.025,
                entryheight=0.028,
            )
            for hist, label in zip(hists, labels):
                legend.AddEntry(hist, label)
            legend.SetBorderSize(0)
            legend.Draw()

            xmin = 0
            xmax = self.x_max
            # TODO: also specialisation, needs removal
            if ("HT" in name):
                xmax = 800
                xmin = 30
            if ("MET" in name):
                xmin = 0
                xmax = 400
            if ("Jet" in name):
                xmin = 20
                xmax = 400
            if ("HiRange" in name):
                xmax = 2000

            for val in [0.25, 0.5, 0.75, 0.95, 1.]:
                line = ROOT.TLine(xmin, val, xmax, val)
                line.SetLineStyle("dashed")
                line.SetLineColor(15)
                line.Draw()

            for val in range(100, xmax, 100):
                line = ROOT.TLine(val, 0., val, 1.)
                line.SetLineStyle("dashed")
                line.SetLineColor(15)
                line.Draw()

            # Save canvas to file
            self.save_canvas(canvas, name)

    def __summarize_fits(self):
        """ Implement this to show fit evolution plots """
        # TODO: Implement this __summarize_fits methods
        pass

    def _is_consistent(self, new):
        """
        Check the two plotters are the consistent, so same binning and same axis names
        """
        return all([
            self.pileup_bins.bins == new.pileup_bins.bins,
            self.thresholds.bins == new.thresholds.bins,
            self.online_name == new.online_name,
            self.offline_name == new.offline_name,
        ])

    def _merge(self, other):
        """
        Merge another plotter into this one
        """
        self.efficiencies += other.efficiencies
        return self.efficiencies
Пример #9
0
class RatesPlot(BasePlotter):
    def __init__(self, online_name):
        name = ["rates", online_name]
        super(RatesPlot, self).__init__("__".join(name))
        self.online_name = online_name

    def create_histograms(self,
                          online_title,
                          pileup_bins,
                          n_bins,
                          low,
                          high,
                          legend_title=""):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.pileup_bins = bn.Sorted(pileup_bins,
                                     "pileup",
                                     use_everything_bin=True)
        self.legend_title = legend_title

        name = ["rate_vs_threshold", self.online_name, "pu_{pileup}"]
        name = "__".join(name)
        title = " ".join([self.online_name, "vs.", "in PU bin: {pileup}"])
        title = ";".join([title, self.online_title])
        self.plots = HistogramCollection([self.pileup_bins],
                                         "Hist1D",
                                         n_bins,
                                         low,
                                         high,
                                         name=name,
                                         title=title)
        self.filename_format = name

    def fill(self, pileup, online):
        self.plots[pileup].fill(online)

    def draw(self, with_fits=False):
        hists = []
        labels = []
        fits = []
        for (pile_up, ), hist in self.plots.flat_items_all():
            h = cumulative_hist(hist)
            h = normalise_to_collision_rate(h)
            if pile_up == bn.Base.everything:
                h.linestyle = "dashed"
                label = "Everything"
            elif isinstance(pile_up, int):
                h.drawstyle = "EP"
                label = "~ {:.0f}".format(
                    self.pileup_bins.get_bin_center(pile_up))
            else:
                continue
            h.SetMarkerSize(0.5)
            hists.append(h)
            labels.append(label)
            # if with_fits:
            #     fits.append(self.fits.get_bin_contents([pile_up]))
        self.__make_overlay(hists, fits, labels, "Number of events")

        normed_hists = list(normalise_to_unit_area(hists))
        self.__make_overlay(normed_hists, fits, labels, "Fraction of events",
                            "__shapes")

    def overlay_with_emu(self, emu_plotter, with_fits=False):

        hists = []
        labels = []
        fits = []

        hist = self.plots.get_bin_contents([bn.Base.everything])
        hist = cumulative_hist(hist)

        hist.drawstyle = "EP"
        hist.SetMarkerSize(0.5)
        hist.SetMarkerColor(1)
        # if with_fits:
        #    fit = self.fits.get_bin_contents([threshold])
        #    fits.append(fit)
        hists.append(hist)
        labels.append("HW")

        emu_hist = emu_plotter.plots.get_bin_contents([bn.Base.everything])
        emu_hist = cumulative_hist(emu_hist)

        emu_hist.drawstyle = "EP"
        emu_hist.SetMarkerSize(0.5)
        emu_hist.SetMarkerColor(2)
        # if with_fits:
        #    emu_fit = self.fits.get_bin_contents([threshold])
        #    fits.append(emu_fit)
        hists.append(emu_hist)
        labels.append("Emu")

        self.__make_overlay(hists, fits, labels, "# Events", setlogy=True)

    def __make_overlay(self,
                       hists,
                       fits,
                       labels,
                       ytitle,
                       suffix="",
                       setlogy=False):
        with preserve_current_style():
            # Draw each resolution (with fit)
            xtitle = self.online_title
            canvas = draw(hists,
                          draw_args={
                              "xtitle": xtitle,
                              "ytitle": ytitle,
                              "logy": setlogy
                          })
            if fits:
                for fit, hist in zip(fits, hists):
                    fit["asymmetric"].linecolor = hist.GetLineColor()
                    fit["asymmetric"].Draw("same")

            # Add labels
            label_canvas()

            # Add a legend
            legend = Legend(len(hists),
                            header=self.legend_title,
                            topmargin=0.35,
                            rightmargin=0.2,
                            leftmargin=0.8,
                            entryheight=0.028)
            for hist, label in zip(hists, labels):
                legend.AddEntry(hist, label)
            legend.SetBorderSize(0)
            legend.Draw()

            # Save canvas to file
            name = self.filename_format.format(pileup="all")
            self.save_canvas(canvas, name + suffix)

    def _is_consistent(self, new):
        """
        Check the two plotters are the consistent, so same binning and same axis names
        """
        return all([
            self.pileup_bins.bins == new.pileup_bins.bins,
            self.online_name == new.online_name,
        ])

    def _merge(self, other):
        """
        Merge another plotter into this one
        """
        self.plots += other.plots
        return self.plots
Пример #10
0
class EfficiencyPlot(BasePlotter):
    drawstyle = 'HISTC'
    drawstyle_data = 'PC'

    def __init__(self, online_name, offline_name):
        name = ["efficiency", online_name, offline_name]
        super(EfficiencyPlot, self).__init__("__".join(name))
        self.online_name = online_name
        self.offline_name = offline_name

    def create_histograms(self,
                          online_title,
                          offline_title,
                          pileup_bins,
                          thresholds,
                          n_bins,
                          low,
                          high=400,
                          legend_title=""):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.offline_title = offline_title
        self.pileup_bins = bn.Sorted(pileup_bins,
                                     "pileup",
                                     use_everything_bin=True)
        self.thresholds = bn.GreaterThan(thresholds, "threshold")
        self.legend_title = legend_title

        name = ["efficiency", self.online_name, self.offline_name]
        name += ["thresh_{threshold}", "pu_{pileup}"]
        name = "__".join(name)
        title = " ".join([
            self.online_name, " in PU bin: {pileup}",
            "and passing threshold: {threshold}"
        ])
        self.filename_format = name

        def make_efficiency(labels):
            this_name = "efficiency" + name.format(**labels)
            this_title = title.format(**labels)
            '''Checking type of 'low' to see whether it's int (x-range minimum)
                    or array (bin edges) for constructing TEfficiency'''
            if isinstance(low, np.ndarray):
                eff = asrootpy(
                    ROOT.TEfficiency(this_name, this_title, n_bins, low))
            else:
                eff = asrootpy(
                    ROOT.TEfficiency(this_name, this_title, n_bins, low, high))
            eff.drawstyle = EfficiencyPlot.drawstyle
            return eff

        self.efficiencies = HistogramCollection(
            [self.pileup_bins, self.thresholds], make_efficiency)

    def fill(self, pileup, offline, online):
        efficiencies = {
            (pu, thresh): eff
            for (pu, ), thresholds in self.efficiencies[pileup].items()
            for thresh, eff in thresholds.items()
        }
        for (pu_bin, threshold_bin), efficiency in efficiencies.items():
            threshold = self.thresholds.get_bin_center(threshold_bin)
            passed = False
            if isinstance(threshold, str):
                continue
            elif online > threshold:
                passed = True
            efficiency.fill(passed, offline)

    def draw(self, with_fits=False):
        # Fit the efficiencies if requested
        if with_fits:
            self.__fit_efficiencies()

        # Overlay the "all" pile-up bin for each threshold
        all_pileup_effs = self.efficiencies.get_bin_contents(
            [bn.Base.everything])
        hists = []
        labels = []
        fits = []
        label_template = '{online_title} > {threshold} GeV'
        for threshold in all_pileup_effs.iter_all():
            if not isinstance(threshold, int):
                continue
            hist = all_pileup_effs.get_bin_contents(threshold)
            hist.drawstyle = EfficiencyPlot.drawstyle_data
            self._dynamic_bin(hist)
            hists.append(hist)

            label = label_template.format(
                online_title=self.online_title,
                threshold=self.thresholds.bins[threshold],
            )
            labels.append(label)
            if with_fits:
                fits.append(
                    self.fits.get_bin_contents([bn.Base.everything,
                                                threshold]))
        self.__make_overlay(
            "all",
            "all",
            hists,
            fits,
            labels,
            self.online_title,
        )

        if 'HiRange' not in self.filename_format:
            # Overlay individual pile-up bins for each threshold
            for threshold in self.thresholds:
                hists = []
                labels = []
                fits = []
                for pileup in self.pileup_bins:
                    if not isinstance(pileup, int):
                        continue
                    hist = self.efficiencies.get_bin_contents(
                        [pileup, threshold])
                    hist.drawstyle = EfficiencyPlot.drawstyle_data
                    self._dynamic_bin(hist)
                    hists.append(hist)
                    if with_fits:
                        fits.append(
                            self.fits.get_bin_contents([pileup, threshold]))
                    labels.append(str(self.pileup_bins.bins[pileup]))
                self.__make_overlay(pileup, threshold, hists, fits, labels,
                                    "PU bin")

        # Produce the fit summary plot
        if with_fits:
            self.__summarize_fits()

    def overlay(self, other_plotters=None, with_fits=False):

        suffix = '__emu_overlay'
        titles = ['Hw', 'Emu']
        if self.comp_title:
            suffix = '__comparison'
            titles = [
                other_plotter.comp_title for other_plotter in other_plotters
            ]
            titles.insert(0, self.comp_title)

        # Fit the efficiencies if requested
        if with_fits:
            self.__fit_efficiencies()

        # Overlay the "all" pile-up bin for each threshold
        all_pileup_effs = self.efficiencies.get_bin_contents(
            [bn.Base.everything])

        hists = []
        labels = []
        fits = []
        label_template = '{online_title} > {threshold} GeV'
        for threshold in all_pileup_effs.iter_all():
            if not isinstance(threshold, int):
                continue
            hist = all_pileup_effs.get_bin_contents(threshold)
            hist.drawstyle = EfficiencyPlot.drawstyle_data
            self._dynamic_bin(hist)
            hists.append(hist)

            label = label_template.format(
                online_title='L1 ' + titles[0],
                threshold=self.thresholds.bins[threshold],
            )
            labels.append(label)
            if with_fits:
                fits.append(
                    self.fits.get_bin_contents([bn.Base.everything,
                                                threshold]))

        for other_plotter in other_plotters:
            pileup_effs = other_plotter.efficiencies.get_bin_contents(
                [bn.Base.everything])
            for threshold in pileup_effs.iter_all():
                if not isinstance(threshold, int):
                    continue
                hist = pileup_effs.get_bin_contents(threshold)
                hist.drawstyle = EfficiencyPlot.drawstyle_data
                self._dynamic_bin(hist)
                hists.append(hist)

                label = label_template.format(
                    online_title='L1 ' +
                    titles[other_plotters.index(other_plotter) + 1],
                    threshold=other_plotter.thresholds.bins[threshold],
                )
                labels.append(label)
                if with_fits:
                    fits.append(
                        other_plotter.fits.get_bin_contents(
                            [bn.Base.everything, threshold]))

        self.__make_overlay(
            "all",
            suffix,
            hists,
            fits,
            labels,
            self.online_title,
        )
        '''
        # Overlay individual pile-up bins for each threshold
        for threshold in self.thresholds:
            hists = []
            labels = []
            fits = []
            for pileup in self.pileup_bins:
                if not isinstance(pileup, int):
                    continue
                hist = self.efficiencies.get_bin_contents([pileup, threshold])
                hist.drawstyle = "EP"
                hists.append(hist)
                if with_fits:
                    fits.append(self.fits.get_bin_contents(
                        [pileup, threshold]))
                labels.append(str(self.pileup_bins.bins[pileup]))
            self.__make_overlay(pileup, threshold, hists,
                                fits, labels, "PU bin")
        '''
        # Produce the fit summary plot
        if with_fits:
            self.__summarize_fits()

    def __fit_efficiencies(self):
        def make_fit(labels):
            pileup_bin = labels["pileup"]
            threshold_bin = labels["threshold"]
            efficiency = self.efficiencies.get_bin_contents(
                [pileup_bin, threshold_bin])
            params = fit_efficiency(
                efficiency, self.thresholds.get_bin_center(threshold_bin))
            return params

        # Actually make the efficiencies
        self.fits = HistogramCollection([self.pileup_bins, self.thresholds],
                                        make_fit)

    def __make_overlay(self, pileup, threshold, hists, fits, labels, header):
        with preserve_current_style():
            name = self.filename_format.format(pileup=pileup,
                                               threshold=threshold)

            xmin = int(hists[0].GetTotalHistogram().GetBinLowEdge(1))
            xmax = int(hists[0].GetTotalHistogram().GetBinLowEdge(
                hists[0].GetTotalHistogram().GetNbinsX() + 1))

            xtitle = ""
            if 'Jet' in self.online_title:
                xtitle = "Jet #it{p}_{T} (GeV)"
            if 'HT' in self.online_title:
                xtitle = "#it{H}_{T} (GeV)"
            if 'MET' in self.online_title:
                xtitle = "#it{E}_{T}^{miss} (GeV)"

            # Draw each efficiency (with fit)
            draw_args = {
                "xtitle": xtitle,
                "ytitle": "Efficiency",
                "xlimits": [xmin, xmax]
            }

            canvas = draw(hists, draw_args=draw_args)
            if len(fits) > 0:
                for fit, hist in zip(fits, hists):
                    fit["asymmetric"].linecolor = hist.GetLineColor()
                    fit["asymmetric"].Draw("same")

            # Add labels
            label_canvas()

            # Add a legend
            legend = Legend(
                len(hists),
                header=self.legend_title,
                topmargin=0.25,
                rightmargin=0.25,
                leftmargin=0.69,
                textsize=0.025,
                entryheight=0.028,
            )

            for hist, label in zip(hists, labels):
                legend.AddEntry(hist, label)

            legend.SetBorderSize(0)
            legend.Draw()

            for val in [0.25, 0.5, 0.75, 0.95, 1.]:
                line = ROOT.TLine(xmin, val, xmax, val)
                line.SetLineStyle("dashed")
                line.SetLineColor(15)
                line.Draw()

            for t in xrange(xmin, xmax, 20):
                line = ROOT.TLine(t, 0., t, 1.)
                line.SetLineStyle("dashed")
                line.SetLineColor(15)
                line.Draw()

            # Save canvas to file
            self.save_canvas(canvas, name)

    def __summarize_fits(self):
        """ Implement this to show fit evolution plots """
        # TODO: Implement this __summarize_fits methods
        pass

    def _is_consistent(self, new):
        """
        Check the two plotters are the consistent, so same binning and same axis names
        """
        return all([
            self.pileup_bins.bins == new.pileup_bins.bins,
            self.thresholds.bins == new.thresholds.bins,
            self.online_name == new.online_name,
            self.offline_name == new.offline_name,
        ])

    def _merge(self, other):
        """
        Merge another plotter into this one
        """
        self.efficiencies += other.efficiencies
        return self.efficiencies

    def _dynamic_bin(self, eff):
        """
        Re-build efficiency plots so that there are no bins with < min_ entries
        """

        min_ = 16
        total = []
        passed = []
        bins = []
        bins.append(eff.GetTotalHistogram().GetBinLowEdge(1))
        nbins = eff.GetTotalHistogram().GetNbinsX()

        merge_total = 0
        merge_passed = 0

        for bin in range(1, nbins + 1):

            next_bin_total = eff.GetTotalHistogram().GetBinContent(bin + 1)
            merge_total += eff.GetTotalHistogram().GetBinContent(bin)
            merge_passed += eff.GetPassedHistogram().GetBinContent(bin)
            if bin == nbins:
                merge_total += eff.GetTotalHistogram().GetBinContent(bin + 1)
                merge_passed += eff.GetPassedHistogram().GetBinContent(bin + 1)

            if (next_bin_total > min_ and merge_total > min_) or bin == nbins:
                bins.append(eff.GetTotalHistogram().GetBinLowEdge(bin + 1))
                total.append(merge_total)
                passed.append(merge_passed)
                merge_total = 0
                merge_passed = 0

        npbins = np.asarray(bins)

        hist_total = asrootpy(
            ROOT.TH1I("total", "total",
                      len(bins) - 1, npbins))
        hist_passed = asrootpy(
            ROOT.TH1I("passed", "passed",
                      len(bins) - 1, npbins))

        for bin in range(1, len(bins)):
            hist_total.SetBinContent(bin, total[bin - 1])
            hist_passed.SetBinContent(bin, passed[bin - 1])

        hist_total.Sumw2(False)
        hist_passed.Sumw2(False)

        eff.SetTotalHistogram(hist_total, "f")
        eff.SetPassedHistogram(hist_passed, "f")
Пример #11
0
class ResolutionPlot(BasePlotter):
    drawstyle = 'P'

    def __init__(self, resolution_type, online_name, offline_name):
        name = ["resolution", online_name, offline_name]
        super(ResolutionPlot, self).__init__("__".join(name))
        self.online_name = online_name
        self.offline_name = offline_name
        self.resolution_method = get_resolution_function(resolution_type)

    def create_histograms(self,
                          online_title, offline_title,
                          pileup_bins, n_bins, low, high, legend_title=''):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.offline_title = offline_title
        self.legend_title = legend_title
        self.pileup_bins = bn.Sorted(pileup_bins, "pileup",
                                     use_everything_bin=True)

        name = ["resolution", self.online_name,
                self.offline_name, "pu_{pileup}"]
        name = "__".join(name)
        title = " ".join(
            [self.online_name, "vs.", self.offline_name, "in PU bin: {pileup}"])
        title = ";".join([title, self.offline_title, self.online_title])
        self.plots = HistogramCollection([self.pileup_bins],
                                         "Hist1D", n_bins, low, high,
                                         name=name, title=title)
        self.filename_format = name

    def fill(self, pileup, offline, online):
        difference = self.resolution_method(online, offline)
        self.plots[pileup].fill(difference)

    def draw(self, with_fits=False):
        hists = []
        labels = []
        fits = []
        for (pile_up, ), hist in self.plots.flat_items_all():
            if pile_up == bn.Base.everything:
                # hist.linestyle = "dashed"
                hist.drawstyle = ResolutionPlot.drawstyle
                label = "All PU"
            elif isinstance(pile_up, int):
                hist.drawstyle = ResolutionPlot.drawstyle
                if self.pileup_bins.get_bin_upper(pile_up) < 500:
                    label = "{:.0f} \\leq PU < {:.0f}".format(
                        self.pileup_bins.get_bin_lower(pile_up),
                        self.pileup_bins.get_bin_upper(pile_up),
                    )
                else:
                    label = "{:.0f} < PU".format(
                        self.pileup_bins.get_bin_lower(pile_up))
            else:
                continue
            hist.SetMarkerSize(0.5)
            hist.SetLineWidth(1)
            hists.append(hist)
            labels.append(label)
            # if with_fits:
            #     fits.append(self.fits.get_bin_contents([pile_up]))
        # self.__make_overlay(hists, fits, labels, "Number of events")

        normed_hists = list(normalise_to_unit_area(hists))
        for hist in normed_hists:
            hist.GetYaxis().SetRangeUser(-0.1, 1.1)
        self.__make_overlay(normed_hists, fits, labels, "a.u.")

    def overlay_with_emu(self, emu_plotter, with_fits=False):
        hists = []
        labels = []
        fits = []
        for (pile_up, ), hist in self.plots.flat_items_all():
            if pile_up == bn.Base.everything:
                hist.SetLineStyle(1)
                hist.drawstyle = ResolutionPlot.drawstyle
                label = "HW, all PU"
            else:
                continue
            hist.SetMarkerSize(0.5)
            hist.SetLineWidth(1)
            hists.append(hist)
            labels.append(label)

        for (pile_up, ), hist in emu_plotter.plots.flat_items_all():
            if pile_up == bn.Base.everything:
                hist.SetLineStyle(1)
                hist.drawstyle = ResolutionPlot.drawstyle
                label = "Emu, all PU"
            else:
                continue
            hist.SetMarkerSize(0.5)
            hist.SetLineWidth(1)
            hists.append(hist)
            labels.append(label)

        # self.__make_overlay(hists, fits, labels,
        #                    "Number of events", "__Overlay_Emu")

        normed_hists = list(normalise_to_unit_area(hists))
        for hist in normed_hists:
            hist.GetYaxis().SetRangeUser(-0.1, 1.1)
        self.__make_overlay(normed_hists, fits, labels,
                            "a.u.", "__Overlay_Emu")

    def __make_overlay(self, hists, fits, labels, ytitle, suffix=""):
        with preserve_current_style():
            # Draw each resolution (with fit)
            # TODO: this feels like it does not belong here
            for hist in hists:
                hist.GetYaxis().SetRangeUser(0, 0.1)
                hist.GetYaxis().SetTitleOffset(1.4)

            xtitle = self.resolution_method.label.format(
                on=self.online_title, off=self.offline_title)
            canvas = draw(hists, draw_args={
                          "xtitle": xtitle, "ytitle": ytitle})
            if fits:
                for fit, hist in zip(fits, hists):
                    fit["asymmetric"].linecolor = hist.GetLineColor()
                    fit["asymmetric"].Draw("same")

            # Add labels
            label_canvas()

            # Add a legend
            legend = Legend(
                len(hists),
                header=self.legend_title,
                topmargin=0.35,
                rightmargin=0.3,
                leftmargin=0.7,
                textsize=0.03,
                entryheight=0.03,
            )

            for hist, label in zip(hists, labels):
                legend.AddEntry(hist, label)
            legend.SetBorderSize(0)
            legend.Draw()

            ymax = 1.2 * max([hist.GetMaximum() for hist in hists])
            line = ROOT.TLine(0., 0., 0., ymax)
            line.SetLineColor(15)

            # Save canvas to file
            name = self.filename_format.format(pileup="all")
            self.save_canvas(canvas, name + suffix)

    def _is_consistent(self, new):
        """
        Check the two plotters are the consistent, so same binning and same axis names
        """
        return all([self.pileup_bins.bins == new.pileup_bins.bins,
                    self.resolution_method == new.resolution_method,
                    self.online_name == new.online_name,
                    self.offline_name == new.offline_name,
                    ])

    def _merge(self, other):
        """
        Merge another plotter into this one
        """
        self.plots += other.plots
        return self.plots
Пример #12
0
class OnlineVsOffline(BasePlotter):
    def __init__(self, online_name, offline_name):
        name = ["online_vs_offline", online_name, offline_name]
        super(OnlineVsOffline, self).__init__("__".join(name))
        self.online_name = online_name
        self.offline_name = offline_name

    def create_histograms(
        self,
        online_title,
        offline_title,
        pileup_bins,
        n_bins,
        low,
        high=400.,
    ):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.offline_title = offline_title
        self.pileup_bins = bn.Sorted(
            pileup_bins,
            "pileup",
            use_everything_bin=True,
        )

        nameTokens = [
            "onlineVsOffline",
            self.online_name,
            self.offline_name,
            "pu_{pileup}",
        ]
        name = "__".join(nameTokens)
        title = " ".join([
            self.online_name,
            "vs.",
            self.offline_name,
            "in PU bin: {pileup}",
        ])
        title = ";".join([title, self.offline_title, self.online_title])
        if isinstance(low, np.ndarray):
            self.plots = HistogramCollection(
                [self.pileup_bins],
                "Hist2D",
                low,
                low,
                name=name,
                title=title,
            )
        else:
            self.plots = HistogramCollection(
                [self.pileup_bins],
                "Hist2D",
                n_bins,
                low,
                high,
                n_bins,
                low,
                high,
                name=name,
                title=title,
            )
        self.filename_format = name

    def fill(self, pileup, offline, online):
        self.plots[pileup].fill(offline, online)

    def draw(self, with_fits=True):
        for pileup in self.pileup_bins.iter_all():
            plot = self.plots.get_bin_contents([pileup])
            self.__do_draw(self.pileup_bins.get_bin_center(pileup), plot)

    def __do_draw(self, pileup, hist):
        with preserve_current_style():
            # Draw each efficiency (with fit)
            canvas = draw2D(hist,
                            draw_args={
                                "xtitle": self.offline_title,
                                "ytitle": self.online_title
                            })
            canvas.SetLogz(True)

            # Add labels
            label_canvas()

            # Save canvas to file
            name = self.filename_format.format(pileup=pileup)
            self.save_canvas(canvas, name)

    def _is_consistent(self, new):
        """
        Check the two plotters are the consistent, so same binning and same axis names
        """
        return all([
            self.pileup_bins.bins == new.pileup_bins.bins,
            self.online_name == new.online_name,
            self.offline_name == new.offline_name,
        ])

    def _merge(self, other):
        """
        Merge another plotter into this one
        """
        self.plots += other.plots
        return self.plots
Пример #13
0
class ResolutionVsXPlot(BasePlotter):

    def __init__(self, resolution_type, online_name, offline_name, versus_name):
        name = ["resolution_vs_" + versus_name, online_name, offline_name]
        super(ResolutionVsXPlot, self).__init__("__".join(name))
        self.online_name = online_name
        self.offline_name = offline_name
        self.versus_name = versus_name
        self.resolution_method = get_resolution_function(resolution_type)

    def create_histograms(
            self, online_title, offline_title, versus_title, pileup_bins,
            res_n_bins, res_low, res_high, vs_n_bins, vs_low, vs_high):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.offline_title = offline_title
        self.versus_title = versus_title
        self.ymin = res_low
        self.ymax = res_high
        self.pileup_bins = bn.Sorted(pileup_bins, "pileup",
                                     use_everything_bin=True)

        nameTokens = [
            "resolution_vs", self.versus_name,
            self.online_name, self.offline_name, "pu_{pileup}",
        ]
        name = "__".join(nameTokens)
        title = 'Resolution ({online_name} vs. {offline_name}) '
        title += 'against {versus_name}'
        title = title.format(
            online_name=self.online_name,
            offline_name=self.offline_name,
            versus_name=self.versus_name,
        )
        title += " in PU bin: {pileup}"
        title = ";".join([title, self.offline_title, self.online_title])
        self.plots = HistogramCollection(
            [self.pileup_bins],
            "Hist2D", vs_n_bins, vs_low, vs_high,
            res_n_bins, res_low, res_high,
            name=name, title=title)
        self.filename_format = name

    def fill(self, pileup, versus, offline, online):
        difference = self.resolution_method(online, offline)
        self.plots[pileup].fill(versus, difference)

    def draw(self, with_fits=True):
        for (pileup, ), hist in self.plots.flat_items_all():
            self.__do_draw(pileup, hist)
            profileX = hist.ProfileX()
            projectionX = deepcopy(hist.ProjectionX())

            for i in range(hist.GetNbinsX()):
                pX_i = profileX.GetBinContent(i)
                if pX_i == 0:
                    projectionX.SetBinContent(i, 0.)
                    continue
                pX_i_err = profileX.GetBinError(i)
                projX_i = projectionX.GetBinContent(i)

                newValue = sqrt(projX_i) * pX_i_err / pX_i
                newError = projX_i * pX_i_err

                projectionX.SetBinContent(i, newValue)
                projectionX.SetBinError(i, 0.)
                profileX.SetBinError(i, newError)

            if projectionX.GetMaximum() > 3.:
                projectionX.GetYaxis().SetRangeUser(0., 2.)
            self.__do_draw(pileup, profileX, "_profile2")
            self.__do_draw(pileup, projectionX, "_profile")

    def __do_draw(self, pileup, hist, suffix=""):
        with preserve_current_style():
            # Draw each efficiency (with fit)
            if suffix == "":
                ytitle = "Online Jet Energy / Offline Jet Energy"
            elif suffix == "_profile":
                ytitle = "RMS/Mean (Online Jet Energy/Offline Jet Energy)"
            else:
                ytitle = self.resolution_method.label.format(
                    on=self.online_title,
                    off=self.offline_title,
                )
            canvas = draw2D(
                hist,
                draw_args={"xtitle": self.versus_title, "ytitle": ytitle},
            )

            # Add labels
            label_canvas()

            # Save canvas to file
            name = self.filename_format.format(pileup=pileup)
            self.save_canvas(canvas, name + suffix)

    def _is_consistent(self, new):
        """
            Check the two plotters are the consistent,
            so same binning and same axis names
        """
        return all([
            self.pileup_bins.bins == new.pileup_bins.bins,
            self.resolution_method == new.resolution_method,
            self.versus_name == new.versus_name,
            self.online_name == new.online_name,
            self.offline_name == new.offline_name,
        ])

    def _merge(self, other):
        """
        Merge another plotter into this one
        """
        self.plots += other.plots
        return self.plots
Пример #14
0
class RatesPlot(BasePlotter):
    def __init__(self, online_name):
        name = ["rates", online_name]
        super(RatesPlot, self).__init__("__".join(name))
        self.online_name = online_name

    def create_histograms(self,
                          online_title,
                          pileup_bins,
                          n_bins,
                          low,
                          high,
                          legend_title=""):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.pileup_bins = bn.Sorted(pileup_bins,
                                     "pileup",
                                     use_everything_bin=True)
        self.legend_title = legend_title
        name = ["rate_vs_threshold", self.online_name, "pu_{pileup}"]
        name = "__".join(name)
        title = " ".join([self.online_name, "vs.", "in PU bin: {pileup}"])
        title = ";".join([title, self.online_title])
        self.plots = HistogramCollection([self.pileup_bins],
                                         "Hist1D",
                                         n_bins,
                                         low,
                                         high,
                                         name=name,
                                         title=title)
        self.filename_format = name

    def fill(self, pileup, online):
        self.plots[pileup].fill(online)

    def draw(self, with_fits=False):
        hists = []
        labels = []
        fits = []
        for (pile_up, ), hist in self.plots.flat_items_all():
            h = cumulative_hist(hist)
            h = normalise_to_collision_rate(h)
            if pile_up == bn.Base.everything:
                h.linestyle = "dashed"
                label = "L1 Rate"
            # elif isinstance(pile_up, int):
            #    h.drawstyle = "HIST"
            #    label = str(self.pileup_bins.bins[pile_up])
            else:
                continue
            hists.append(h)
            labels.append(label)
            # if with_fits:
            #     fits.append(self.fits.get_bin_contents([pile_up]))
        self.__make_overlay(hists, fits, labels, "Rate (kHz)", setlogy=True)

        normed_hists = list(normalise_to_unit_area(hists))
        self.__make_overlay(normed_hists, fits, labels, "Fraction of events",
                            "__shapes")

    def overlay(self, other_plotters=None, with_fits=False, comp=False):

        hists = []
        labels = []
        fits = []
        suffix = '__emu_overlay'
        titles = ['Hw', 'Emu']
        if comp:
            suffix = '__comparison'
            titles = [
                other_plotter.comp_title for other_plotter in other_plotters
            ]
            titles.insert(0, self.comp_title)

        hist = self.plots.get_bin_contents([bn.Base.everything])
        hist = cumulative_hist(hist)
        hist = normalise_to_collision_rate(hist)
        hist.drawstyle = "HIST"
        hist.SetLineWidth(3)
        hist.SetMarkerColor(1)
        # if with_fits:
        #    fit = self.fits.get_bin_contents([threshold])
        #    fits.append(fit)
        hists.append(hist)
        labels.append('L1 ' + titles[0])

        for other_plotter in other_plotters:
            hist = other_plotter.plots.get_bin_contents([bn.Base.everything])
            hist = cumulative_hist(hist)
            hist = normalise_to_collision_rate(hist)

            hist.drawstyle = "HIST"
            hist.SetLineWidth(3)
            hist.SetMarkerColor(2)
            hist.markerstyle = 21 + other_plotters.index(other_plotter)
            # if with_fits:
            #    fit = self.fits.get_bin_contents([threshold])
            #    fits.append(fit)
            hists.append(hist)
            labels.append('L1 ' +
                          titles[other_plotters.index(other_plotter) + 1])

        self.__make_overlay(hists,
                            fits,
                            labels,
                            "Rate (kHz)",
                            suffix,
                            setlogy=True)

    def __make_overlay(self,
                       hists,
                       fits,
                       labels,
                       ytitle,
                       suffix="",
                       setlogy=False):
        with preserve_current_style():
            # Draw each resolution (with fit)

            xtitle = ""
            if 'Jet' in self.online_title:
                xtitle = "Jet #it{p}_{T} (GeV)"
            if 'HT' in self.online_title:
                xtitle = "#it{H}_{T} (GeV)"
            if 'MET' in self.online_title:
                xtitle = "#it{E}_{T}^{miss} (GeV)"

            canvas = draw(hists,
                          draw_args={
                              "xtitle": xtitle,
                              "ytitle": ytitle,
                              "logy": setlogy,
                              "ylimits": (0.1, 50000)
                          })
            if fits:
                for fit, hist in zip(fits, hists):
                    fit["asymmetric"].linecolor = hist.GetLineColor()
                    fit["asymmetric"].Draw("same")

            # Add labels
            label_canvas()

            # Add a legend
            legend = Legend(len(hists),
                            header=self.legend_title,
                            topmargin=0.35,
                            rightmargin=0.2,
                            leftmargin=0.8,
                            entryheight=0.028,
                            textsize=0.03)
            for hist, label in zip(hists, labels):
                legend.AddEntry(hist, label)
            legend.SetBorderSize(0)
            legend.Draw()

            # Save canvas to file
            name = self.filename_format.format(pileup="all")
            self.save_canvas(canvas, name + suffix)

    def _is_consistent(self, new):
        """
        Check the two plotters are the consistent, so same binning and same axis names
        """
        return all([
            self.pileup_bins.bins == new.pileup_bins.bins,
            self.online_name == new.online_name,
        ])

    def _merge(self, other):
        """
        Merge another plotter into this one
        """
        self.plots += other.plots
        return self.plots

    def get_stats(self, summary_bins=[], summary_label=''):
        summary_columns = list(
            self._summary_columns(summary_bins, summary_label))
        stats = list(self._collect_stats(summary_bins, summary_label))
        df = pd.DataFrame(stats)
        return df[['identifier', 'total', 'overflow'] + summary_columns]

    def _summary_columns(self, summary_bins, summary_label):
        for lower, upper in zip(summary_bins[:-1], summary_bins[1:]):
            yield '{} {}-{}'.format(summary_label, lower, upper)

    def _collect_stats(self, summary_bins, summary_label):
        for (pileup, ), hist in self.plots.flat_items():
            human_readable_threshold = '{0}; PU > {1}'.format(
                self.online_title, self.pileup_bins.bins[pileup])
            rhist = hist.rebinned(summary_bins)
            stats = {}
            summary_columns = self._summary_columns(summary_bins,
                                                    summary_label)
            for summary_column, y in zip(summary_columns, rhist.y()):
                stats[summary_column] = y
            total = sum(stats.values())
            overflow = rhist.integral(overflow=True) - total
            header = dict(identifier=human_readable_threshold,
                          total=total,
                          overflow=overflow)
            header.update(stats)
            yield header
Пример #15
0
class RateVsPileupPlot(BasePlotter):
    def __init__(self, online_name):
        name = ["rate_vs_pileup", online_name]
        super(RateVsPileupPlot, self).__init__("__".join(name))
        self.online_name = online_name

    def create_histograms(self,
                          online_title,
                          thresholds, n_bins, low, high, legend_title=""):
        """ This is not in an init function so that we can by-pass this in the
        case where we reload things from disk """
        self.online_title = online_title
        self.thresholds = thresholds
        self.thresholds = bn.GreaterThan(thresholds, "threshold", True)
        self.legend_title = legend_title
        name = ["rate_vs_pileup", self.online_name]
        name += ["thresh_{threshold}"]
        name = "__".join(name)
        title = " ".join([self.online_name, " rate vs pileup",
                          "passing threshold: {threshold}"])
        self.plots = HistogramCollection([self.thresholds],
                                         "Hist1D", n_bins, low, high,
                                         name=name, title=title)

        self.filename_format = name

    def fill(self, pileup, online):
        self.plots[online].fill(pileup)

    def draw(self, with_fits=False):

        for (threshold, ), hist in self.plots.flat_items_all():
            hists = []
            labels = []
            fits = []
            thresholds = []
            if not isinstance(threshold, int):
                continue
            label_template = '{online_title} > {threshold} GeV'
            label = label_template.format(
                online_title=self.online_title,
                threshold=self.thresholds.bins[threshold],
            )
            hist.Divide(self.plots.get_bin_contents([bn.Base.everything]))
            hist.drawstyle = "EP"
            hist.SetMarkerSize(0.5)
            hist.SetMarkerColor(2)
            # if with_fits:
            #    fit = self.fits.get_bin_contents([threshold])
            #    fits.append(fit)
            hists.append(hist)
            labels.append(label)
            thresholds.append(threshold)

            self.__make_overlay(hists, fits, labels, thresholds)

    def overlay_with_emu(self, emu_plotter, with_fits=False):

        for (threshold, ), hist in self.plots.flat_items_all():
            hists = []
            labels = []
            fits = []
            thresholds = []
            if not isinstance(threshold, int):
                continue
            label_template = '{online_title} > {threshold} GeV'
            label = label_template.format(
                online_title=self.online_title,
                threshold=self.thresholds.bins[threshold],
            )
            hist.Divide(self.plots.get_bin_contents([bn.Base.everything]))
            hist.drawstyle = "EP"
            hist.SetMarkerSize(0.5)
            hist.SetMarkerColor(1)
            # if with_fits:
            #    fit = self.fits.get_bin_contents([threshold])
            #    fits.append(fit)
            hists.append(hist)
            labels.append(label)
            thresholds.append(threshold)
            for (emu_threshold, ), emu_hist in emu_plotter.plots.flat_items_all():
                if emu_threshold == threshold:
                    label_template = '{online_title} > {threshold} GeV'
                    emu_label = label_template.format(
                        online_title=emu_plotter.online_title,
                        threshold=emu_plotter.thresholds.bins[threshold],
                    )
                    emu_hist.Divide(emu_plotter.plots.get_bin_contents([bn.Base.everything]))
                    emu_hist.drawstyle = "EP"
                    emu_hist.SetMarkerSize(0.5)
                    emu_hist.SetMarkerColor(2)
                    # if with_fits:
                    #    emu_fit = self.fits.get_bin_contents([threshold])
                    #    fits.append(emu_fit)
                    hists.append(emu_hist)
                    labels.append(emu_label)
                    thresholds.append(emu_threshold)

            self.__make_overlay(hists, fits, labels, thresholds)

    def __make_overlay(self, hists, fits, labels, thresholds, suffix=""):
        with preserve_current_style():
            # Draw each rate vs pileup (with fit)
            xtitle = "# reco vertices"
            ytitle = "a.u."
            canvas = draw(hists, draw_args={"xtitle": xtitle, "ytitle": ytitle})
            if fits:
                for fit, hist in zip(fits, hists):
                    fit["asymmetric"].linecolor = hist.GetLineColor()
                    fit["asymmetric"].Draw("same")

            # Add labels
            label_canvas()

            # Add a legend
            legend = Legend(
                len(hists),
                header=self.legend_title,
                topmargin=0.35,
                rightmargin=0.7,
                leftmargin=0.3,
                textsize=0.025,
                entryheight=0.028,
            )
            for hist, label in zip(hists, labels):
                legend.AddEntry(hist, label)
                legend.SetBorderSize(0)
                legend.Draw()

            # Save canvas to file
            name = self.filename_format.format(threshold=thresholds[0])
            self.save_canvas(canvas, name + suffix)

    def _is_consistent(self, new):
        """
        Check the two plotters are the consistent, so same binning and same axis names
        """
        return all([self.thresholds.bins == new.thresholds.bins,
                    self.online_name == new.online_name,
                    ])

    def _merge(self, other):
        """
        Merge another plotter into this one
        """
        self.plots += other.plots
        return self.plots