예제 #1
0
class MassPlane:
    def __init__(self,x_bins,x_min,x_max,y_bins,y_min,y_max,plot_DY=False,plot_TT=False,plot_ZA=False,profile=False):
        self.x_bins     = x_bins
        self.x_min      = x_min
        self.x_max      = x_max
        self.y_bins     = y_bins
        self.y_min      = y_min
        self.y_max      = y_max
        self.model      = None
        self.plot_DY    = plot_DY
        self.plot_TT    = plot_TT
        self.plot_ZA    = plot_ZA
        self.profile    = profile
        self.graph_list = []

        # Produce grid #
        self.produce_grid()


    def produce_grid(self):
        self.X,self.Y = np.meshgrid(np.linspace(self.x_min,self.x_max,self.x_bins),np.linspace(self.y_min,self.y_max,self.y_bins))
        bool_upper = np.greater_equal(self.Y,self.X)
        self.X = self.X[bool_upper]
        self.Y = self.Y[bool_upper]
        self.x = self.X.reshape(-1,1)
        self.y = self.Y.reshape(-1,1)
        # X, Y are 2D arrays, x,y are vectors of points

    def load_model(self,path_model):
        self.model = Restore(path_model, custom_objects={'PreprocessLayer': PreprocessLayer}).model
        self.model_name = os.path.basename(path_model).replace(".zip","")


    def plotMassPoint(self,mH,mA):
        print ("Producing plot for MH = %.2f GeV, MA = %.2f"%(mH,mA))
        N = self.x.shape[0]
        params = np.c_[np.ones(N)*mA,np.ones(N)*mH]
        inputs = np.c_[self.x,self.y,params]
        output = self.model.predict(inputs)

        g_DY = ROOT.TGraph2D(N)
        g_DY.SetNpx(500)
        g_DY.SetNpy(500)
        g_TT = ROOT.TGraph2D(N)
        g_TT.SetNpx(500)
        g_TT.SetNpy(500)
        g_ZA = ROOT.TGraph2D(N)
        g_ZA.SetNpx(500)
        g_ZA.SetNpy(500)

        g_DY.SetName(("MassPlane_DY_mH_%s_mA_%s"%(mH,mA)).replace('.','p'))
        g_TT.SetName(("MassPlane_TT_mH_%s_mA_%s"%(mH,mA)).replace('.','p'))
        g_ZA.SetName(("MassPlane_ZA_mH_%s_mA_%s"%(mH,mA)).replace('.','p'))

        for i in range(N):
            if self.plot_DY:
                g_DY.SetPoint(i,self.x[i],self.y[i],output[i,0])
            if self.plot_TT:
                g_TT.SetPoint(i,self.x[i],self.y[i],output[i,1])
            if self.plot_ZA:
                g_ZA.SetPoint(i,self.x[i],self.y[i],output[i,2])

        if self.plot_DY:
            self.graph_list.append(g_DY)
            g_DY.GetHistogram().SetTitle("P(DY) for mass point M_{H} = %.2f GeV, M_{A} = %.2f GeV"%(mH,mA))
            g_DY.GetHistogram().GetXaxis().SetTitle("M_{jj} [GeV]")
            g_DY.GetHistogram().GetYaxis().SetTitle("M_{lljj} [GeV]")
            g_DY.GetHistogram().GetZaxis().SetTitle("DNN output")
            g_DY.GetHistogram().GetZaxis().SetRangeUser(0.,1.)
            g_DY.GetHistogram().SetContour(100)
            g_DY.GetXaxis().SetTitleOffset(1.2)
            g_DY.GetYaxis().SetTitleOffset(1.2)
            g_DY.GetZaxis().SetTitleOffset(1.2)
            g_DY.GetXaxis().SetTitleSize(0.045)
            g_DY.GetYaxis().SetTitleSize(0.045)
            g_DY.GetZaxis().SetTitleSize(0.045)

        if self.plot_TT:
            g_TT.GetHistogram().SetTitle("P(t#bar{t}) for mass point M_{H} = %.2f GeV, M_{A} = %.2f GeV"%(mH,mA))
            g_TT.GetHistogram().GetXaxis().SetTitle("M_{jj} [GeV]")
            g_TT.GetHistogram().GetYaxis().SetTitle("M_{lljj} [GeV]")
            g_TT.GetHistogram().GetZaxis().SetTitle("DNN output")
            g_TT.GetHistogram().GetZaxis().SetRangeUser(0.,1.)
            g_TT.GetHistogram().SetContour(100)
            g_TT.GetXaxis().SetTitleOffset(1.2)
            g_TT.GetYaxis().SetTitleOffset(1.2)
            g_TT.GetZaxis().SetTitleOffset(1.2)
            g_TT.GetXaxis().SetTitleSize(0.045)
            g_TT.GetYaxis().SetTitleSize(0.045)
            g_TT.GetZaxis().SetTitleSize(0.045)
            self.graph_list.append(g_TT)

        if self.plot_ZA:
            g_ZA.GetHistogram().SetTitle("P(H#rightarrowZA) for mass point M_{H} = %.2f GeV, M_{A} = %.2f GeV"%(mH,mA))
            g_ZA.GetHistogram().GetXaxis().SetTitle("M_{jj} [GeV]")
            g_ZA.GetHistogram().GetYaxis().SetTitle("M_{lljj} [GeV]")
            g_ZA.GetHistogram().GetZaxis().SetTitle("DNN output")
            g_ZA.GetHistogram().GetZaxis().SetRangeUser(0.,1.)
            g_ZA.GetHistogram().SetContour(100)
            g_ZA.GetXaxis().SetTitleOffset(1.2)
            g_ZA.GetYaxis().SetTitleOffset(1.2)
            g_ZA.GetZaxis().SetTitleOffset(1.2)
            g_ZA.GetXaxis().SetTitleSize(0.045)
            g_ZA.GetYaxis().SetTitleSize(0.045)
            g_ZA.GetZaxis().SetTitleSize(0.045)
            self.graph_list.append(g_ZA)

    @staticmethod
    def getProfiles(g):
        h = g.GetHistogram()
        xproj = h.ProjectionX()
        yproj = h.ProjectionY()
        array = hist2array(h)
        # Need to compensate the triangular binning
        nonzeroXbins = h.GetNbinsY()/np.count_nonzero(array,axis=1)
        nonzeroYbins = h.GetNbinsX()/np.count_nonzero(array,axis=0)
        for x in range(1,h.GetNbinsX()):
            xproj.SetBinContent(x,xproj.GetBinContent(x)*nonzeroXbins[x-1])
        for y in range(1,h.GetNbinsY()):
            yproj.SetBinContent(y,yproj.GetBinContent(y)*nonzeroYbins[y-1])
        xproj.GetYaxis().SetTitle("DNN output")
        yproj.GetYaxis().SetTitle("DNN output")

        return xproj, yproj


    def plotOnCanvas(self):
        setTDRStyle()
        pdf_path = "MassPlane/"+self.model_name+".pdf"
        root_path = pdf_path.replace('.pdf','.root')
        outFile = ROOT.TFile(root_path,"RECREATE")
        C = ROOT.TCanvas("C","C",800,600)
        #C.SetLogz()
        C.Print(pdf_path+"[")
        for g in self.graph_list:
            print ("Plotting %s"%g.GetName())
            g.Draw("colz")
            g_copy = g.Clone()
            contours = np.array([0.90,0.95,0.99])
            g_copy.GetHistogram().SetContour(contours.shape[0],contours)
            g_copy.Draw("cont2 same")
            g.Write()
            C.Print(pdf_path,"Title:"+g.GetName())
            if self.profile:
                xproj,yproj = self.getProfiles(g)
                xproj.Draw("hist")
                xproj.Write()
                C.Print(pdf_path,"Title:"+g.GetName()+" X profile")
                yproj.Draw("hist")
                C.Print(pdf_path,"Title:"+g.GetName()+" Y profile")
                yproj.Write()

        C.Print(pdf_path+"]")
        outFile.Close()
        print ("Root file saved as %s"%root_path)

    def makePavement(self,contours):
        for contour in contours:
            print ("Producing pavement for cut %.2f"%contour)
            pdf_path = "MassPlane/"+self.model_name+("_pave%0.2f"%contour).replace('.','p')+".pdf"
            root_path = pdf_path.replace('.pdf','.root')
            outFile = ROOT.TFile(root_path,"RECREATE")
            C = ROOT.TCanvas("C","C",800,600)
            opt = 'cont2'
            new_graph_list = [g.Clone() for g in self.graph_list]
            # Need them saved in a list otherwise they are deleted and canvas is blank
            for g in new_graph_list:
                print ('Adding to contour plot',g.GetName())
                g.SetTitle("Pavement for cut %0.2f"%contour)
                g.GetHistogram().SetContour(1,np.array([contour]))
                g.Draw(opt)
                if 'same' not in opt : opt += " same"
                g.Write()
            
            C.Print(pdf_path)
            outFile.Close()
예제 #2
0
class LikelihoodMap():
    def __init__(self, name, xmin, ymin, xmax, ymax, N, normalize=False):
        self.xmin = xmin
        self.ymin = ymin
        self.xmax = xmax
        self.ymax = ymax
        self.N = N
        self.name = name
        self.normalize = normalize  # Xsec*BR*Acc
        self.nevents = 0  # count the number of events
        custom_objects = {'PreprocessLayer': PreprocessLayer}
        self.model = Restore(os.path.join(
            '/home/users/f/b/fbury/MoMEMtaNeuralNet/model/',
            name + '_HToZA.zip'),
                             custom_objects=custom_objects).model
        #self.model = HyperModel(name,'HToZA')
        # Make directory output #
        self.path_output = os.path.join(
            '/home/ucl/cp3/fbury/MoMEMtaNeuralNet/Plotting/PDF', self.name)
        if not os.path.exists(self.path_output):
            os.makedirs(self.path_output)
        # Get the normalization #
        if self.normalize:
            self._importGraphs()
        # Make the grid #
        self._make_grid()
        # Prepare output #
        self.Z = np.zeros(
            self.N)  # N has chnaged because of unphysical phase space point

        ################################################
        # L(x_i|alpha)       = \prod_i 1/sigma_vis W(x_i|alpha)
        # -ln (L(x_i|alpha)) = \sum_i [ -ln(W(x_i|alpha)) + ln(sigma_vis) ]
        #                    = \sum_i [ output_DNN ] + n*ln(sigma_vis)

    def _make_grid(self):
        x = np.linspace(self.xmin, self.xmax, self.N)
        y = np.linspace(self.ymin, self.ymax, self.N)
        X, Y = np.meshgrid(x, y)
        mA = X.flatten()
        mH = Y.flatten()
        mh = 125
        mZ = 90
        # Unphysical phase-space points #
        condition1 = np.greater(mH, mA)
        condition2 = np.greater(mH, mh)
        condition3 = np.greater(np.subtract(mH, mA), mZ)
        #upper = np.logical_and(condition1,condition2)
        upper = np.logical_and(np.logical_and(condition1, condition2),
                               condition3)
        # Ensure that mH > mh
        # Ensure that mH > mA
        # Ensure that mH-mA > mZ
        self.mA = mA[upper]
        self.mH = mH[upper]
        self.N = self.mA.shape[0]

        # Normalisation with xsec visible #
        self.norm = np.ones(self.N)
        if self.normalize:
            logging.info('Normalization enabled')
            for i in range(0, self.N):
                self.norm[i] *= self.acc.Interpolate(self.mA[i], self.mH[i])
                #self.norm[i] *= self.xsec.Interpolate(self.mA[i],self.mH[i])
                self.norm[i] *= self.BR_HtoZA.Interpolate(
                    self.mA[i], self.mH[i])
                #self.norm[i] *= self.BR_Atobb.Interpolate(self.mA[i],self.mH[i])
                self.norm[i] *= 3.3658 * 2 / 100  # Z-> e+e- + Z-> mu+mu-
                self.norm[i] *= 1e-12  # Xsec in pb
        # Get log(normalization) #
        self.norm = np.log10(
            self.norm
        )  # if normalize == False => norm =1 => log(norm)=0 (thus not used)
        # phase space points non physical(xsec=0) -> will produce -inf

    def AddEvent(self, event):
        # Get the -log(weight) #
        inputs = np.c_[np.tile(event, (self.N, 1)), self.mH, self.mA]
        #outputs = self.model.HyperRestore(inputs)
        outputs = self.model.predict(inputs, batch_size=512)
        self.Z += outputs.reshape(-1, )
        self.nevents += 1

    def MakeGraph(self, title, suffix):
        self.legend_title = title.replace('.root', '').replace('-', '_')
        self.suffix = suffix
        if title.find('DY') != -1:
            title = 'Drell-Yan events'
        elif title.find('TT') != -1:
            title = r't\bar{t} events'
        else:
            mH_value = re.findall(r'\d+', title)[2]
            mA_value = re.findall(r'\d+', title)[3]
            title = 'Signal events with M_{H} = %s GeV and M_{A} = %s GeV' % (
                mH_value, mA_value)

        # Normalize #
        if self.normalize:
            self.Z += self.nevents * self.norm
            title += ' [Normalized]'
            self.legend_title += '_norm'

        # Divide by total entries #
        self.Z /= self.nevents  # Divide by N
        self.Z *= 2  # Because -2 log L

        # check for invalids (nan of inf) might be coming from log10 #
        invalid_entries = np.logical_or(np.isinf(self.Z), np.isnan(self.Z))
        max_Z = np.amax(self.Z[np.invert(invalid_entries)])
        min_Z = np.amin(self.Z[np.invert(invalid_entries)])
        self.Z[invalid_entries] = 0  # removes non physical points

        # Generate graph #
        graph = TGraph2D(self.N)
        print('Generating TGraph2D')
        manager = enlighten.get_manager()
        pbar = manager.counter(total=self.N, desc='Progress', unit='Point')
        for i in range(self.N):
            graph.SetPoint(i, self.mA[i], self.mH[i], self.Z[i])
            pbar.update()
        manager.stop()

        #graph = copy.deepcopy(TGraph2D(self.N,self.mA,self.mH,self.Z))
        graph.SetTitle(
            'Log-Likelihood : %s;M_{A} [GeV]; M_{H} [GeV]; -2log L' % (title))
        graph.SetMaximum(max_Z)
        graph.SetMinimum(min_Z)
        graph.SetNpx(1000)
        graph.SetNpy(1000)

        # Save graph #
        self.graph = graph
        self._saveGraph()

    def _saveGraph(self):
        full_name = self.path_output + '/likelihood_' + self.suffix + '.root'
        if os.path.exists(full_name):
            root_file = TFile(full_name, "update")
            self.graph.Write(self.legend_title, TObject.kOverwrite)
            logging.info("New Graph saved in %s" % full_name)
        else:
            root_file = TFile(full_name, "recreate")
            self.graph.Write(self.legend_title)
            logging.info("Graph replaced in %s" % full_name)

    def _importGraphs(self):
        # import the TGraphs 2D #
        path_graphs = '/home/users/f/b/fbury/MoMEMtaNeuralNet/Plotting/'
        file_xsec = TFile.Open(os.path.join(path_graphs, 'XsecMap_full.root'))
        file_acc = TFile.Open(
            os.path.join(path_graphs, 'AcceptanceMap_full.root'))

        try:  # Deepcopy necessary to avoid seg fault
            self.xsec = copy.deepcopy(file_xsec.Get('Xsec'))
            self.BR_HtoZA = copy.deepcopy(file_xsec.Get('BR_HtoZA'))
            self.BR_Atobb = copy.deepcopy(file_xsec.Get('BR_Atobb'))
            self.BR_Ztoll = copy.deepcopy(file_xsec.Get('BR_Ztoll'))
            self.acc = copy.deepcopy(file_acc.Get('Acceptance'))
        except:
            self.normalize = False
            logging.warning('Could not load the Objects -> normalization off')

        if not isinstance(self.xsec, ROOT.TGraph2D):
            self.normalize = False
            logging.warning(
                'Xsec is %s and not TGraph2D -> normalization off' %
                type(self.xsec))
        if not isinstance(self.BR_HtoZA, ROOT.TGraph2D):
            self.normalize = False
            logging.warning(
                'BR_HtoZA is %s and not TGraph2D -> normalization off' %
                type(self.BR_HtoZA))
        if not isinstance(self.BR_Atobb, ROOT.TGraph2D):
            self.normalize = False
            logging.warning(
                'BR_Atobb is %s and not TGraph2D -> normalization off' %
                type(self.BR_Atobb))
        if not isinstance(self.BR_Ztoll, ROOT.TGraph2D):
            self.normalize = False
            logging.warning(
                'BR_Ztoll is %s and not TGraph2D -> normalization off' %
                type(self.BR_Ztoll))
        if not isinstance(self.acc, ROOT.TGraph2D):
            self.normalize = False
            logging.warning(
                'Acceptance is %s and not TGraph2D -> normalization off' %
                type(self.acc))