예제 #1
0
def main(reader_name,
         tags,
         lut_path,
         ptmin,
         ptmax,
         ymin=None,
         ymax=None,
         tag_name=None,
         logx=False,
         logy=False,
         leg_pos=[0.74, 0.2, 0.90, 0.4],
         particles=None,
         eta=0,
         dnch_deta=100,
         rmin=None,
         add_eta_label=True,
         add_alice3_label=True,
         save=None,
         background=False,
         use_p_over_z=True,
         aod=None,
         study_label="ALICE 3 study"):
    gROOT.LoadMacro(reader_name)
    gROOT.LoadMacro("style.C")
    reader_name = reader_name.split(".")[-2]
    reader = getattr(__import__('ROOT', fromlist=[reader_name]), reader_name)
    style = getattr(__import__('ROOT', fromlist=["style"]), "style")

    style()

    p = {
        "el": "e",
        "pi": "#pi",
        "ka": "K",
        "pr": "p",
        "de": "d",
        "tr": "t",
        "he3": "^{3}He"
    }
    charge = {"el": 1, "pi": 1, "ka": 1, "pr": 1, "de": 1, "tr": 1, "he3": 2}
    p_colors = {
        "el": "#e41a1c",
        "pi": "#377eb8",
        "ka": "#4daf4a",
        "pr": "#984ea3",
        "de": "#ff7f00",
        "tr": "#999999",
        "he3": "#a65628"
    }

    if particles is not None:
        to_remove = []
        for i in p:
            if i not in particles:
                to_remove.append(i)
        for i in to_remove:
            p.pop(i)

    latex = TLatex()
    latex.SetTextAlign(33)
    canvas = reader_name
    canvas = canvas.replace("lutRead_", "")
    canvas = TCanvas(canvas, canvas, 800, 800)
    canvas.Divide(2, 2)
    drawn = [canvas]
    drawn_graphs = {}
    drawn_frames = {}
    if ymin is None:
        if "_dca" in reader_name:
            ymin = 0.1
        elif "_pt" in reader_name:
            ymin = 1.
        elif "_eff" in reader_name:
            ymin = 0.
    if ymax is None:
        if "_dca" in reader_name:
            ymax = 1e4
        elif "_pt" in reader_name:
            ymax = 100.
        elif "_eff" in reader_name:
            ymax = 115.

    def adjust_pad():
        if logx:
            gPad.SetLogx()
        if logy:
            gPad.SetLogy()

    counter = 1
    leg = None
    if tag_name is not None:
        leg = TLegend(*leg_pos)
        if add_eta_label:
            label = f"#eta = {int(eta)}"
            label += " dN_{Ch}/d#eta ="
            label += f" {int(dnch_deta)}"
            if rmin is not None:
                label += "   R_{min} = " + rmin
            else:
                leg.SetHeader()
            leg.SetHeader(label)
        leg.SetLineColor(0)
        drawn.append(leg)

    def draw_study_label(x=0.5, y=0.9):
        latex = TLatex()
        latex.SetTextAlign(13)
        drawn.append(latex.DrawLatexNDC(x, y, " ".join(study_label)))

    for i in p:
        c = f"{canvas.GetName()}_{i}"
        c = TCanvas(c, c, 800, 800)
        drawn.append(c)
        adjust_pad()

        frame = c.DrawFrame(ptmin, ymin, ptmax, ymax, "")
        frame.SetDirectory(0)
        drawn_frames[i] = frame
        g_list = []
        extra = {}
        cols = [
            '#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33'
        ]
        for k, j in enumerate(tags):
            lut = f"{lut_path}/lutCovm.{i}.{j}.dat"
            if j == "":
                lut = f"{lut_path}/lutCovm.{i}.dat"
            if not path.isfile(lut):
                print("LUT file", lut, "does not exist")
                return
            g = reader(lut, eta, dnch_deta)
            if g.GetN() <= 0:
                print("Skipping", g.GetName(), "because empty graph")
                continue
            if len(g_list) == 0:
                frame.GetXaxis().SetTitle(g.GetXaxis().GetTitle())
                frame.GetYaxis().SetTitle(g.GetYaxis().GetTitle())
            if use_p_over_z:
                for j in range(g.GetN()):
                    if "_pt" in reader_name:
                        g.SetPoint(j,
                                   g.GetPointX(j) / charge[i],
                                   g.GetPointY(j) / charge[i])
                    else:
                        g.SetPoint(j,
                                   g.GetPointX(j) / charge[i], g.GetPointY(j))
                frame.GetXaxis().SetTitle("#it{p}_{T}/z (GeV/#it{c})")
            col = TColor.GetColor(cols[len(g_list)])
            g.SetLineColor(col)
            g.SetLineStyle(1)
            g.SetLineWidth(3)
            g.Draw("samel")
            if aod is not None:
                f_aod = TFile(aod, "READ")
                if "_eff" in reader_name:
                    extra[g.GetName()] = f_aod.Get(
                        "qa-tracking-efficiency-kaon/pt/num")
                    extra[g.GetName()].Divide(
                        f_aod.Get("qa-tracking-efficiency-kaon/pt/num"),
                        f_aod.Get("qa-tracking-efficiency-kaon/pt/den"), 1, 1,
                        "B")
                    extra[g.GetName()].Scale(100)
                    extra[g.GetName()].Draw("SAME")
                    extra[g.GetName()].SetDirectory(0)
                elif "_pt" in reader_name:
                    extra[g.GetName()] = f_aod.Get(
                        "qa-tracking-efficiency-kaon/pt/num")
                    extra[g.GetName()].Divide(
                        f_aod.Get("qa-tracking-efficiency-kaon/pt/num"),
                        f_aod.Get("qa-tracking-efficiency-kaon/pt/den"), 1, 1,
                        "B")
                    extra[g.GetName()].Scale(100)
                    extra[g.GetName()].Draw("SAME")
                    extra[g.GetName()].SetDirectory(0)
                f_aod.Close()

            print("Drawing", g.GetName())
            if tag_name is not None and counter == 1:
                leg.AddEntry(g, tag_name[k], "l")
            g_list.append(g)
        drawn_graphs[i] = g_list
        if len(g_list) <= 0:
            print("Nothing drawn!")
            continue
        drawn.append(latex.DrawLatexNDC(0.9, 0.9, p[i]))
        if leg is not None:
            leg.Draw()
        draw_study_label(.4, .91)
        gPad.Update()
        canvas.cd(counter)
        clone = c.DrawClonePad()
        if counter != 1:
            l = gPad.GetListOfPrimitives()
            for i in l:
                cn = i.ClassName()
                if cn == "TLegend":
                    l.Remove(i)
                elif cn == "TLatex":
                    if "ALICE" in i.GetTitle():
                        l.Remove(i)
        drawn.append(clone)
        c.SaveAs(f"/tmp/{c.GetName()}.png")
        gPad.Update()
        counter += 1
    canvas_all_species = None
    if len(tags) == 1:
        canvas_all_species = TCanvas("all_spec_" + canvas.GetName(),
                                     "all_spec_" + canvas.GetName(), 800, 800)
        drawn.append(canvas_all_species)
        canvas_all_species.cd()
        drawn_graphs_all_spec = {}
        leg_all_spec = TLegend(*leg_pos)
        leg_all_spec.SetNColumns(2)
        leg_all_spec.SetLineColor(0)
        drawn.append(leg_all_spec)
        for i in drawn_graphs:
            if canvas_all_species.GetListOfPrimitives().GetEntries() == 0:
                drawn_frames[i].Draw()
            g_list = []
            for j in drawn_graphs[i]:
                g_list.append(j.Clone())
                g_list[-1].SetName(g_list[-1].GetName() + "_color")
                g_list[-1].SetLineColor(TColor.GetColor(p_colors[i]))
                g_list[-1].Draw("same")
                leg_all_spec.AddEntry(g_list[-1], p[i], "L")
            drawn_graphs_all_spec[i] = g_list
        for i in drawn_graphs_all_spec:
            drawn_graphs[i + "_allspec"] = drawn_graphs_all_spec[i]
        leg_all_spec.Draw()
        if add_alice3_label:
            draw_study_label()
            latex = TLatex()
            latex.SetTextAlign(13)
            latex.SetTextSize(0.04)
            if tag_name is not None:
                drawn.append(latex.DrawLatexNDC(0.5, 0.80, tag_name[0]))
            drawn.append(
                latex.DrawLatexNDC(
                    0.4, 0.82, f"#eta = {int(eta)}" + "\n dN_{Ch}/d#eta =" +
                    f" {int(dnch_deta)}" +
                    ("\n R_{min} = " + rmin if rmin is not None else "")))

        adjust_pad()
        canvas_all_species.Update()
        canvas_all_species.SaveAs(f"/tmp/{canvas_all_species.GetName()}.png")
    if save is None:
        canvas.SaveAs(f"/tmp/lut_{canvas.GetName()}.root")
    else:
        fo = TFile(save, "RECREATE")
        fo.cd()
        canvas.Write()
        if canvas_all_species is not None:
            canvas_all_species.Write()
        for i in drawn_graphs:
            for j in drawn_graphs[i]:
                j.Write()
    if not background:
        input("Done, press enter to continue")
예제 #2
0
class plots(object):
    """ Extract all plots from Middleware scan. """
    def __init__(self, inputfile, outputfolder=''):
        """ Initialize object variables. """

        self._rootfile = TFile(inputfile)
        self._directory = outputfolder
        self._canvas = TCanvas()
        self._histos = []
        self._histos_good = []
        self._histos_bad = []
        self._shifts = []
        self._widths = []
        makedirs(outputfolder)
        gStyle.SetOptStat(000000000)

    def getAllPlots(self):
        """ Get all the plots. """

        for kname in self._getKeys():

            # Clear all objects from canvas
            self._canvas.Clear()

            # Get histogram and draw it
            histo = self._rootfile.Get(kname)
            histo.Draw()

            # Save it as pdf
            self._save(kname)

    def getScurvePerCbc(self, cbcs=range(0, 8), channels=-1):
        """ Fit all Scurves and put them into one histogram. Also plot shifts
        (offsets) and widths (noise).
        Parameters:
            cbcs: List of CBC's to plot
            channels: Number of channels to plot; -1 for all
        """

        for cbc in cbcs:
            self._drawScurves(cbc, channels)

    def _drawScurves(self, cbc, channels):
        """ Make the fits to draw the Scurves.
        Parameters:
            cbc: CBC to plot
            channels: Number of channels to plot; -1 for all
        """

        # Directory name in rootfile
        dirname = 'Final0'

        # Counter of fitted histograms
        count = 0

        # Chi2 limit to distinguish good from bad fits
        chi2 = .05

        # Loop over all keys in subdirectory
        for kname in self._getKeys(dirname):

            # Only plot a limited number of channels
            if channels > 0 and count >= channels:
                break

            # Only select S-Curves of a given CBC
            if not kname.startswith('{}/Scurve_Be0_Fe0_Cbc{}'.format(
                    dirname, cbc)):
                continue

            # Error function with guessed parameters
            errf = TF1('errf', '.5 + .5*erf((x-[0])/[1])', 0., 254.)
            errf.SetParameter(0, 120.)  # shift
            errf.SetParameter(1, 10.)  # width

            # Fit
            histo = self._rootfile.Get(kname)
            histo.Fit('errf', 'RQ')

            # If fit failed, skip it
            try:
                histo.GetFunction('errf').GetParameter(0)
            except TypeError:
                continue

            # Colors!
            histo.SetLineColor(
                self._getColor(count, (channels > 0 and channels < 19)))
            histo.SetMarkerColor(
                self._getColor(count, (channels > 0 and channels < 19)))
            histo.GetFunction('errf').SetLineColor(
                self._getColor(count, (channels > 0 and channels < 19)))

            # Markers!
            histo.SetMarkerStyle(count % 15 + 20)
            histo.SetMarkerSize(.8)

            # Save values for future use
            self._shifts.append(histo.GetFunction('errf').GetParameter(0))
            self._widths.append(histo.GetFunction('errf').GetParameter(1))
            self._histos.append(histo)

            # Save histograms either in list of good fits or in list of bad fits
            if histo.GetFunction('errf').GetChisquare() <= chi2:
                self._histos_good.append(histo)
            else:
                self._histos_bad.append(histo)

            # Save histogram with fit
            histo.Draw()
            self._save('{}_fit'.format(kname))

            # Save smoothed histogram
            histo.Draw('C HIST')
            self._save('{}_smooth'.format(kname))

            # Count the number of histograms
            count += 1

        # Draw all error functions in one histogram
        self._draw_all_errf(self._histos, 'S-curves for CBC {}'.format(cbc),
                            'scurves_cbc{}'.format(cbc))

        # Draw all good error functions in one histogram
        self._draw_all_errf(
            self._histos_good,
            'S-curves for CBC {} (#chi^{{2}} < {})'.format(cbc, chi2),
            'scurves_cbc{}_good'.format(cbc))

        # Draw all bad error functions in one histogram
        self._draw_all_errf(
            self._histos_bad,
            'S-curves for CBC {} (#chi^{{2}} > {})'.format(cbc, chi2),
            'scurves_cbc{}_bad'.format(cbc))

        # Draw all fitted error functions in one histogram
        self._draw_all_errf_fit(self._histos,
                                'Fitted S-curves for CBC {}'.format(cbc),
                                'scurves_cbc{}_fit'.format(cbc))

        # Draw all fitted error functions and measurements in one histogram
        self._draw_all_errf_fit_meas(self._histos,
                                     'Fitted S-curves for CBC {}'.format(cbc),
                                     'scurves_cbc{}_fit_meas'.format(cbc))

    def _draw_all_errf(self, histos, title, name):
        """ Draw all error functions in one histogram
        Parameters:
            histos: List of histograms to plot
            title: Title of histogram
            name: Name of histogram
        """

        self._canvas.Clear()

        for idx, histo in enumerate(histos):

            if idx == 0:
                # Dynamically set plot range
                histo.GetXaxis().SetRangeUser(self._getXmin(), self._getXmax())
                histo.Draw('C HIST')
                histo.SetTitle(title)
                histo.GetXaxis().SetTitle('VCth units')
                histo.GetYaxis().SetTitle('Occupancy')
            else:
                histo.Draw('C HIST SAME')

        self._save(name)
        self._save('{}_log'.format(name), True)

    def _draw_all_errf_fit(self, histos, title, name):
        """ Draw all error functions in one histogram
        Parameters:
            histos: List of histograms to plot
            title: Title of histogram
            name: Name of histogram
        """

        self._canvas.Clear()

        for idx, histo in enumerate(histos):

            # Get fitted function
            func = histo.GetFunction('errf')

            if idx == 0:
                # Dynamically set plot range
                func.SetRange(self._getXmin(), self._getXmax())
                func.Draw()
                func.SetTitle(title)
                func.GetXaxis().SetTitle('VCth units')
                func.GetYaxis().SetTitle('Occupancy')
            else:
                func.Draw('SAME')

        self._save(name)
        self._save('{}_log'.format(name), True)

    def _draw_all_errf_fit_meas(self, histos, title, name):
        """ Draw all error functions in one histogram
        Parameters:
            histos: List of histograms to plot
            title: Title of histogram
            name: Name of histogram
        """

        self._canvas.Clear()

        for idx, histo in enumerate(histos):

            if idx == 0:
                # Dynamically set plot range
                histo.GetXaxis().SetRangeUser(self._getXmin(), self._getXmax())
                histo.Draw('P')
                histo.SetTitle(title)
                histo.GetXaxis().SetTitle('VCth units')
                histo.GetYaxis().SetTitle('Occupancy')
            else:
                histo.Draw('P SAME')

        self._save(name)
        self._save('{}_log'.format(name), True)

    def _getKeys(self, subdir=None):
        """ Loop over all keys in a given subfolder.
        Parameters:
            subdir: Get keys only from that directory, including all
                    subdirectories
        """

        # If subdir is defined, loop over keys in folder, otherwise loop over
        # keys in rootfile
        if subdir:

            obj = self._rootfile.Get(subdir)
        else:
            obj = self._rootfile

        # Loop over all keys
        for key in obj.GetListOfKeys():

            if subdir:
                kname = '{}/{}'.format(subdir, key.GetName())
            else:
                kname = key.GetName()

            # If key is a folder, go into that folder and loop over all keys
            if key.IsFolder():
                for knamesub in self._getKeys(kname):
                    yield knamesub
            else:
                yield kname

    def _save(self, name, logy=False):
        """ Save histogram as *.pdf.
        Parameters:
            name: Name of *.pdf, possibly including path; directories are
                  created on the fly
            logy: Plot Y-axis in log
        """

        # Go into directory if it is defined
        if self._directory:
            cwd = getcwd()

            # Create directory on filesystem
            if not path.exists(self._directory):
                makedirs(self._directory)
            chdir(self._directory)

        # If canvas is to be stored in a subdirectory, create it
        if '/' in name:
            subdir = name[:name.find('/')]
            if not path.exists(subdir):
                makedirs(subdir)

        # Set Y-axis to log if requested
        if logy:
            self._canvas.SetLogy()
            # This is probably not failsafe, empirically, the first primitive
            # is the frame, the second one an object, if this is not the case,
            # it might fail
            try:
                self._canvas.GetListOfPrimitives().At(
                    1).GetYaxis().SetRangeUser(1e-7, 2.)
            except AttributeError:
                LGR.warning('Cannot set Y-Axis to log')

        # Save as *.pdf
        self._canvas.SaveAs('{}.pdf'.format(name))

        # Unset log scale
        if logy:
            self._canvas.SetLogy(False)
            try:
                self._canvas.GetListOfPrimitives().At(
                    1).GetYaxis().SetRangeUser(1e-7, 1.05)
            except AttributeError:
                pass

        # Go back to original working directories
        if self._directory:
            chdir(cwd)

    def _getXmin(self):
        """ Get minimum on X-Axis to plot.
        """

        return min([
            shift - 5 * width
            for shift, width in zip(self._shifts, self._widths)
        ])

    def _getXmax(self):
        """ Get maximum on X-Axis to plot.
        """

        return max([
            shift + 5 * width
            for shift, width in zip(self._shifts, self._widths)
        ])

    def _getColor(self, idx, nice=False):
        """ Get color for a given index (channel).
        Parameters:
            idx: Channel number
            nice: if True, get a handful of easily distinguishable colors; if
                  False, get all colors
        """

        # List with all colors
        colors = []
        if nice:
            colors.extend(range(2, 10))
        else:
            #colors.extend(range(390, 405))
            colors.extend(range(394, 405))
            colors.extend(range(406, 421))
            colors.extend(range(422, 437))
            colors.extend(range(590, 605))
            colors.extend(range(606, 621))
            colors.extend(range(622, 637))
            colors.extend(range(791, 911))

        return colors[idx % len(colors)]
예제 #3
0
def mbc_single_3s(evtfile,
                  mc,
                  setMres,
                  setGamma,
                  setR,
                  sp1,
                  sp2,
                  sp3,
                  fa,
                  fb,
                  setmd,
                  setp,
                  setxi,
                  setN1,
                  setN2,
                  setNbkgd1,
                  setNbkgd2,
                  title1,
                  title2,
                  epsfile,
                  txtfile,
                  ymin=0.5,
                  cuts=None,
                  err_type='SYMM',
                  test=False):

    from ROOT import (gROOT, RooRealVar, RooCategory, RooArgSet, RooDataSet,
                      RooFit, RooGaussian, RooArgList, RooAddPdf,
                      RooSimultaneous, RooArgusBG, RooFormulaVar,
                      RooDLineShape, RooAbsData, RooDataHist, TCanvas, kRed,
                      kBlue, kGreen, kMagenta, TPaveText)
    set_root_style(stat=1, grid=0)

    # // sp1 = sigma of signal
    # // sp2 = ratio of sigmas betwwen sigma2 sigma 1
    # // sp3 = ratio of sigmas betwwen sigma3 sigma 2
    # // fa, fb, - fractions
    # // xi_side - slope of argus
    # // p_side - power of argus

    # mc = 1  Monte Carlo Model: EvtGenModels/Class/EvtVPHOtoVISR.cc
    # mc = 3  Data Model: with BES 2007 paper (BES2006 lineshape hepex/0612056)

    mbc = RooRealVar('mbc', 'Beam constrained mass', 1.83, 1.89, 'GeV')
    ebeam = RooRealVar('ebeam', 'Ebeam', 1.8815, 1.892, 'GeV')

    dflav = RooCategory('dflav', 'D flavor')
    dflav.defineType('dflav', 1)
    dflav.defineType('dbarflav', -1)

    if cuts != None:
        if 'kkmass' in cuts:
            kkmass = RooRealVar('kkmass', 'KK invariant mass', 0.97, 1.90,
                                'GeV')
            ras = RooArgSet(mbc, ebeam, kkmass, dflav)
            dataset = RooDataSet.read(evtfile, ras)
        elif 'kpimass' in cuts:
            kpimass = RooRealVar('kpimass', 'Kpi invariant mass', 0.6, 1.4,
                                 'GeV')
            ras = RooArgSet(mbc, ebeam, kpimass, dflav)
            dataset = RooDataSet.read(evtfile, ras)
        else:
            raise NameError(cuts)

        sys.stdout.write('Using cuts: %s...' % cuts)
        dataset = dataset.reduce(cuts)
        sys.stdout.write(' selected %s events.\n' % dataset.numEntries())
    else:
        ras = RooArgSet(mbc, ebeam, dflav)
        dataset = RooDataSet.read(evtfile, ras)

    res = RooRealVar("datares", "datares", mc)
    mres = RooRealVar("mres", "mres", setMres)
    gamma = RooRealVar('gamma', 'gamma', setGamma)

    r = RooRealVar('r', 'r', setR)
    sigmaE = RooRealVar("sigmaE", "sigmaE", 0.0021)

    sigmap1 = RooRealVar("sigmap1", "sigmap1", sp1, 0.002, 0.040)

    scalep2 = RooRealVar("scalep2", "scalep2", 2.00, 1.500, 5.500)
    scalep3 = RooRealVar("scalep3", "scalep3", 5.00, 3.00, 10.000)

    scalep2.setVal(sp2)
    scalep2.setConstant(1)
    scalep3.setVal(sp3)
    scalep3.setConstant(1)

    as12 = RooArgList(sigmap1, scalep2)
    sigmap2 = RooFormulaVar("sigmap2", "sigma2", "sigmap1*scalep2", as12)

    as123 = RooArgList(sigmap1, scalep2, scalep3)
    sigmap3 = RooFormulaVar("sigmap3", "sigma3", "sigmap1*scalep2*scalep3",
                            as123)

    md = RooRealVar("md", "md", setmd, 1.863, 1.875)

    f2 = RooRealVar("f2", "f2", fa)
    f3 = RooRealVar("f3", "f3", fb)
    al23 = RooArgList(f2, f3)
    f1 = RooFormulaVar("f1", "f1", "1.0-f2-f3", al23)

    # Construct signal shape

    fcn1_1 = RooDLineShape("DLineshape1_1", "DLineShape1_1", 4, mbc, ebeam,
                           mres, gamma, r, sigmaE, sigmap1, md, res)
    fcn1_2 = RooDLineShape("DLineshape1_2", "DLineShape1_2", 4, mbc, ebeam,
                           mres, gamma, r, sigmaE, sigmap2, md, res)
    fcn1_3 = RooDLineShape("DLineshape1_3", "DLineShape1_3", 4, mbc, ebeam,
                           mres, gamma, r, sigmaE, sigmap3, md, res)

    fcn2_1 = RooDLineShape("DLineshape2_1", "DLineShape2_1", 4, mbc, ebeam,
                           mres, gamma, r, sigmaE, sigmap1, md, res)
    fcn2_2 = RooDLineShape("DLineshape2_2", "DLineShape2_2", 4, mbc, ebeam,
                           mres, gamma, r, sigmaE, sigmap2, md, res)
    fcn2_3 = RooDLineShape("DLineshape2_3", "DLineShape2_3", 4, mbc, ebeam,
                           mres, gamma, r, sigmaE, sigmap3, md, res)

    alf1_123 = RooArgList(fcn1_1, fcn1_2, fcn1_3)
    af12 = RooArgList(f1, f2)
    signal1_3 = RooAddPdf("signal1_3", "signal1_3", alf1_123, af12)

    alf2_123 = RooArgList(fcn2_1, fcn2_2, fcn2_3)

    signal2_3 = RooAddPdf("signal2_3", "signal2_3", alf2_123, af12)

    p = RooRealVar("p", "p", setp, 0.1, 1.5)
    xi = RooRealVar("xi", "xi", setxi, -100.0, -0.1)

    Bkgd1 = RooArgusBG("argus1", "argus1", mbc, ebeam, xi, p)
    Bkgd2 = RooArgusBG("argus2", "argus2", mbc, ebeam, xi, p)

    shapes1 = RooArgList(signal1_3)
    shapes1.add(signal1_3)
    shapes1.add(Bkgd1)

    shapes2 = RooArgList(signal2_3)
    shapes2.add(signal2_3)
    shapes2.add(Bkgd2)

    N1 = RooRealVar("N1", "N1", setN1, 0.0, 200000000.0)
    N2 = RooRealVar("N2", "N2", setN2, 0.0, 200000000.0)

    Nbkgd1 = RooRealVar("Nbkgd1", "Nbkgd1", setNbkgd1, 0.0, 200000000.0)
    Nbkgd2 = RooRealVar("Nbkgd2", "Nbkgd2", setNbkgd2, 0.0, 200000000.0)

    yields1 = RooArgList(N1)
    yields1.add(N1)
    yields1.add(Nbkgd1)

    yields2 = RooArgList(N2)
    yields2.add(N2)
    yields2.add(Nbkgd2)

    totalPdf1 = RooAddPdf("totalPdf1", "totalPdf1", shapes1, yields1)
    totalPdf2 = RooAddPdf("totalPdf2", "totalPdf2", shapes2, yields2)

    totalPdf = RooSimultaneous("totalPdf", "totalPdf", dflav)
    totalPdf.addPdf(totalPdf1, "dflav")
    totalPdf.addPdf(totalPdf2, "dbarflav")

    # Check fitTo options at:
    # http://root.cern.ch/root/html512/RooAbsPdf.html#RooAbsPdf:fitTo
    #
    # Available fit options:
    #  "m" = MIGRAD only, i.e. no MINOS
    #  "s" = estimate step size with HESSE before starting MIGRAD
    #  "h" = run HESSE after MIGRAD
    #  "e" = Perform extended MLL fit
    #  "0" = Run MIGRAD with strategy MINUIT 0
    #  (no correlation matrix calculation at end)
    #   Does not apply to HESSE or MINOS, if run afterwards.

    #  "q" = Switch off verbose mode
    #  "l" = Save log file with parameter values at each MINUIT step
    #  "v" = Show changed parameters at each MINUIT step
    #  "t" = Time fit
    #  "r" = Save fit output in RooFitResult object
    # Available optimizer options
    #  "c" = Cache and precalculate components of PDF that exclusively
    #  depend on constant parameters
    #  "2" = Do NLL calculation in multi-processor mode on 2 processors
    #  "3" = Do NLL calculation in multi-processor mode on 3 processors
    #  "4" = Do NLL calculation in multi-processor mode on 4 processors

    MINUIT = 'ermh4'

    if err_type == 'ASYM':
        MINUIT = 'erh4'

    if test:
        sys.stdout.write('Will save epsfile as: %s \n' % epsfile)
        sys.stdout.write('Will save txtfile as: %s \n' % txtfile)
        return

    if dataset.numEntries() == 0:
        N1.setVal(0)
        N2.setVal(0)
    else:
        # Start Fitting
        fitres = totalPdf.fitTo(dataset, MINUIT)
        fitres.Print('v')

    # Save plots
    canvas = TCanvas('canvas', 'mbc', 1200, 400)
    canvas.Divide(3, 1)

    canvas_1 = canvas.GetListOfPrimitives().FindObject('canvas_1')
    canvas_2 = canvas.GetListOfPrimitives().FindObject('canvas_2')
    canvas_1.SetLogy(1)
    canvas_2.SetLogy(1)

    LineColorRed = RooFit.LineColor(kRed)
    LineColorBlue = RooFit.LineColor(kBlue)
    LineWidth = RooFit.LineWidth(1)  #0.6)

    # Plot the D
    canvas.cd(1)
    mbcFrame = mbc.frame()
    mbcFrame = mbc.frame(60)

    dflav.setLabel('dflav')
    ebas = RooArgSet(ebeam, dflav)
    ebeamdata = RooDataHist("ebeamdata", "ebeamdata", ebas, dataset)

    dataset.plotOn(mbcFrame, RooFit.Cut("dflav==dflav::dflav"))
    mbcFrame.getAttMarker().SetMarkerSize(0.6)
    mbcFrame.Draw()

    Slice = RooFit.Slice(dflav)
    ProjWData = RooFit.ProjWData(ebas, ebeamdata)

    totalPdf.plotOn(mbcFrame, LineColorRed, LineWidth, Slice, ProjWData)
    chisq1 = mbcFrame.chiSquare() * mbcFrame.GetNbinsX()
    mbcFrame.Draw()

    as_bkg1 = RooArgSet(Bkgd1)
    cp_bkg1 = RooFit.Components(as_bkg1)

    totalPdf.plotOn(mbcFrame, cp_bkg1, Slice, LineColorBlue, LineWidth,
                    ProjWData)

    mbcFrame.SetTitle(title1)
    mbcFrame.SetMinimum(ymin)

    mbcFrame.Draw()

    # Plot the D bar
    canvas.cd(2)
    mbcFrame = mbc.frame()
    mbcFrame = mbc.frame(60)

    dflav.setLabel('dbarflav')
    ebas = RooArgSet(ebeam, dflav)
    ebeamdata = RooDataHist("ebeamdata", "ebeamdata", ebas, dataset)

    dataset.plotOn(mbcFrame, RooFit.Cut("dflav==dflav::dbarflav"))
    mbcFrame.getAttMarker().SetMarkerSize(0.6)
    mbcFrame.Draw()

    Slice = RooFit.Slice(dflav)
    ProjWData = RooFit.ProjWData(ebas, ebeamdata)

    totalPdf.plotOn(mbcFrame, LineColorRed, LineWidth, Slice, ProjWData)
    chisq2 = mbcFrame.chiSquare() * mbcFrame.GetNbinsX()
    mbcFrame.Draw()

    as_bkg2 = RooArgSet(Bkgd2)
    cp_bkg2 = RooFit.Components(as_bkg2)

    totalPdf.plotOn(mbcFrame, cp_bkg2, Slice, LineColorBlue, LineWidth,
                    ProjWData)

    mbcFrame.SetTitle(title2)
    mbcFrame.SetMinimum(ymin)

    mbcFrame.Draw()

    # Plot Statistics Box
    canvas.cd(3)
    mbcFrame = mbc.frame()

    paramWin1 = totalPdf.paramOn(mbcFrame, dataset, "", 2, "NELU", 0.1, 0.9,
                                 0.9)

    mbcFrame.GetXaxis().SetLabelSize(0)
    mbcFrame.GetXaxis().SetTickLength(0)
    mbcFrame.GetXaxis().SetLabelSize(0)
    mbcFrame.GetXaxis().SetTitle("")
    mbcFrame.GetXaxis().CenterTitle()

    mbcFrame.GetYaxis().SetLabelSize(0)
    mbcFrame.GetYaxis().SetTitleSize(0.03)
    mbcFrame.GetYaxis().SetTickLength(0)

    paramWin1.getAttText().SetTextSize(0.06)

    mbcFrame.Draw()
    mbcFrame.SetTitle("Fit Parameters")
    ATextBox = TPaveText(.1, .1, .8, .2, "BRNDC")

    tempString = "#chi^{2}_{1} = %.1f, #chi^{2}_{2} = %.1f" % (chisq1, chisq2)
    ATextBox.AddText(tempString)
    ATextBox.SetFillColor(0)
    ATextBox.SetBorderSize(1)

    mbcFrame.addObject(ATextBox)
    mbcFrame.Draw()
    canvas.Print(epsfile)
    rootfile = epsfile.replace('.eps', '.root')
    canvas.Print(rootfile)

    # Save fitting parameters
    pars = [N1, N2, Nbkgd1, Nbkgd2, md, p, sigmap1, xi]
    save_fit_result(pars, txtfile, err_type=err_type, verbose=1)