def writeRValuesTex(rvalues, usePrettyNames=True): """ write out the leading rvalues of the critic, in latex :param usePrettyNames: use the pretty names, not analysis ids """ namer = SParticleNames(False) g = open("rvalues.tex", "wt") g.write("\\begin{tabular}{l|c|c|c|c|c}\n") g.write( "\\bf{Analysis Name} & \\bf{Production} & $\sigma_{XX}$ (fb) & $\sigma^\mathrm{UL}_\mathrm{obs}$ (fb) & $\sigma^\mathrm{UL}_\mathrm{exp}$ (fb) & $r$ \\\\\n" ) #g.write ( "\\begin{tabular}{l|c|r|r}\n" ) #g.write ( "\\bf{Analysis Name} & \\bf{Topo} & $r_{\mathrm{obs}}$ & $r_{\mathrm{exp}}$ \\\\\n" ) g.write("\\hline\n") bibtex = BibtexWriter() from smodels_utils.helper.prettyDescriptions import prettyTexAnalysisName for rv in rvalues[:5]: srv = "N/A" if type(rv[1]) in [float, numpy.float64, numpy.float32]: srv = "%.2f" % rv[1] else: srv = str(rv[1]) anaId = rv[2].analysisId() prettyName = getPrettyName(rv[2]) prettyName = prettyTexAnalysisName(prettyName, anaid=anaId) ref = bibtex.query(anaId) txnames = ",".join(map(str, rv[2].txnames)) allpids = rv[2].PIDs pids = [] for p in allpids: tmp = [] for b in p: if type(b[0]) == int: tmp.append(b[0]) else: tmp.append(b[0][0]) pids.append(tuple(tmp)) prod = [] for p in pids: tmp = namer.texName(p, addDollars=True, addSign=False, addBrackets=True) prod.append(tmp) prod = "; ".join(prod) sigmapred = "20.13" sigmapred = rv[2].xsection.value.asNumber(fb) sigmaexp = "--" if type(rv[2].expectedUL) != type(None): sigmaexp = "%.2f" % rv[2].expectedUL.asNumber(fb) sigmaobs = rv[2].upperLimit.asNumber(fb) g.write ( "%s~\\cite{%s} & %s & %.2f & %.2f & %s & %.2f\\\\\n" % \ ( prettyName, ref, prod, sigmapred, sigmaobs, sigmaexp, rv[0] ) ) g.write("\\end{tabular}\n") g.close()
def retrieveMasses ( self ): """ retrieve the masses from slha file """ logger=logging.getLogger(__name__) logger.info ( "now extracting masses from slha file %s" % ( self.slhafile) ) namer = SParticleNames( susy = False ) f = pyslha.read ( self.slhafile ) m = f.blocks["MASS"] keys = m.keys() D={} for key in keys: mass = m[key] if mass > 4000.: continue name = namer.texName ( key ) if namer.isSM ( key ): ## skip SM particles continue if self.mergesquark: ## sum up all squarks if namer.particleType ( key ) == "q": name=name.rootName ( 1000001 ) D[key]={ "name": name, "m": mass } self.masspids = D return D
size=30, clip_on=False) lastingHS -= 1 ## count down to zero # arrow = plt.arrow ( currentstep, -50, -currentstep-2, 0, width=20, clip_on=False, transform=ax2.transData, color="black" ) # arrow = patches.FancyArrowPatch((.1, .5), (.1, .5), clip_on=False, #arrow = patches.FancyArrowPatch((firststep+currentstep-5-nstart, firststep-nstart), ( 50, 50), # clip_on=False, connectionstyle="arc3,rad=.1", **kw, transform=ax2.transData ) # plt.gca().add_patch ( arrow ) for pid in pids: if max(masses[pid][firststep:laststep:nsteps]) <= 0.0: continue ctentries += 1 data = df[firststep:laststep:nsteps] datamax = df[stepatmax:stepatmax + 1] datacur = df[firststep + currentstep:firststep + currentstep + 1] tName = r'$%s$' % namer.texName(pid) c = colorDict[pid] #if ctentries>9: # tName="" m = np.where(masses[pid] > 0, masses[pid], np.nan) #Fix for avoid plotting to negative values ## the lines plt.plot(df['step'][firststep:laststep + 2:nsteps], m[firststep:laststep + 2:nsteps], '-', linewidth=2, color=c, alpha=.5) sizes = [] def getSize(k):
axarr[0].annotate(r'$%1.2f$' % row['K'], (row['run'] - 0.2, row['K'] + 0.8), fontsize=13) axarr[0].vlines(x=0, ymin=2, ymax=15, linestyle='--', color='gray') for pid in masses.keys(): if not pid in masses: #Skip particles present in real run, but not the fakes continue data = df sns.scatterplot(x=data['run'], y=data[pid], size=1000, sizes=(1500, 1500), marker='_', label=r'$%s$' % (namer.texName(pid, addOnes=True)), legend=False, color=[colorDict[pid]], ax=axarr[1]) for i, m in enumerate(masses[pid]): if m < 0: continue if 'b' in namer.texName(pid): axarr[1].annotate(r'$%s$' % (namer.texName(pid, addOnes=True)), (runs[i] - 0.3, m + 25.), fontsize=15) else: axarr[1].annotate(r'$%s$' % (namer.texName(pid, addOnes=True)), (runs[i], m + 25.), fontsize=15) axarr[1].set_ylim(0., 1500.0) axarr[1].set_xlabel('run (BSM)', fontsize=23)
def plot ( self, ulSeparately=True, pid1=None ): """ a summary plot, overlaying all contributing analyses :param ulSeparately: if true, then plot UL results on their own """ if pid1 == None and type(self.pid1) in [ list, tuple ]: for p in self.pid1: self.plot ( ulSeparately, p ) return if type(pid1) in [ tuple, list ]: for p in pid1: self.plot ( ulSeparately, p ) return if pid1 == None: pid1 = self.pid1 self.pprint ( "plotting summary for %s, %s" % ( pid1, self.topo ) ) resultsForPIDs = {} from plotting.plotHiscore import getPIDsOfTPred, obtain protomodel = obtain ( 0, self.hiscorefile ) for tpred in protomodel.bestCombo: resultsForPIDs = getPIDsOfTPred ( tpred, resultsForPIDs, integrateSRs=False ) stats = self.getAnaStats( integrateSRs=False ) if stats == None: self.pprint ( "found no ana stats?" ) return anas = list(stats.keys()) if pid1 in resultsForPIDs: self.debug ( "results for PIDs %s" % ", ".join ( resultsForPIDs[pid1] ) ) anas = list ( resultsForPIDs[pid1] ) anas.sort() self.pprint ( "summary plot: %s" % ", ".join ( anas ) ) # print ( stats.keys() ) colors = [ "red", "green", "blue", "orange", "cyan", "magenta", "grey", "brown", "pink", "indigo", "olive", "orchid", "darkseagreen", "teal" ] xmin,xmax,ymin,ymax=9000,0,9000,0 for m in self.masspoints: if m[0] < xmin: xmin = m[0] if m[0] > xmax: xmax = m[0] if m[1] < ymin: ymin = m[1] if m[1] > ymax: ymax = m[1] if abs(xmin-310.)<1e-5: xmin=330. ## cut off the left margin print ( "[plotLlhds] range x [%d,%d] y [%d,%d]" % ( xmin, xmax, ymin, ymax ) ) handles = [] existingPoints = [] combL = {} namer = SParticleNames ( susy = False ) for ctr,ana in enumerate ( anas ): ## loop over the analyses if ctr >= self.max_anas: self.pprint ( "too many (%d > %d) analyses." % (len(anas),self.max_anas) ) for ana in anas[ctr:]: self.pprint ( " - skipping %s" % ana ) break color = colors[ctr] x,y=set(),set() L, R = {}, {} minXY=( 0.,0., float("inf") ) s="" r,sr = self.getResultFor ( ana, self.masspoints[0][2] ) if r: s="(%.2f)" % (-np.log(r)) print ( "[plotLlhds] result for", ana,"is", s ) cresults = 0 for cm,masspoint in enumerate(self.masspoints[1:]): #if cm % 10 != 0: # continue if cm % 1000 == 0: print ( ".", end="", flush=True ) m1,m2,llhds,robs=masspoint[0],masspoint[1],masspoint[2],masspoint[3] rmax=float("nan") if len(robs)>0: rmax=robs[0] if m2 > m1: print ( "m2,m1 mass inversion?",m1,m2 ) x.add ( m1 ) y.add ( m2 ) zt = float("nan") result,sr = self.getResultFor ( ana, llhds ) if result: zt = - np.log( result ) cresults += 1 if zt < minXY[2] and rmax<=self.rthreshold: minXY=(m1,m2,zt) h = self.getHash(m1,m2) L[h]=zt if not h in combL: combL[h]=0. if np.isnan(zt): combL[h] = combL[h] + 100. else: combL[h] = combL[h] + zt R[h]=rmax print () # print ( "\n[plotLlhds] min(xy) for %s is at m=(%d/%d): %.2f(%.2g)" % ( ana, minXY[0], minXY[1], minXY[2], np.exp(-minXY[2] ) ) ) if cresults == 0: print ( "[plotLlhds] warning: found no results for %s. skip" % \ str(masspoint) ) continue # return x.add ( xmax*1.03 ) x.add ( xmin*.93 ) y.add ( ymax+50. ) y.add ( 0. ) x,y=list(x),list(y) x.sort(); y.sort() X, Y = np.meshgrid ( x, y ) Z = float("nan")*X RMAX = float("nan")*X for irow,row in enumerate(Z): for icol,col in enumerate(row): h = 0 if len(x)>= icol and len(y) >= irow: h = self.getHash(list(x)[icol],list(y)[irow]) if h in L: Z[irow,icol]=L[h] if h in R: RMAX[irow,icol]=R[h] if self.interactive: self.RMAX = RMAX # self.ZCOMB = ZCOMB self.Z = Z self.L = L self.R = R self.X = X self.Y = Y hldZ100 = computeHPD ( Z, None, 1., False, rthreshold=self.rthreshold ) cont100 = plt.contour ( X, Y, hldZ100, levels=[0.25], colors = [ color ], linestyles = [ "dotted" ], zorder=10 ) #hldZ95 = computeHPD ( Z, .95, False ) #cont95 = plt.contour ( X, Y, hldZ95, levels=[0.5], colors = [ color ], linestyles = [ "dashed" ] ) #plt.clabel ( cont95, fmt="95%.0s" ) hldZ50 = computeHPD ( Z, RMAX, .68, False, rthreshold=self.rthreshold ) cont50c = plt.contour ( X, Y, hldZ50, levels=[1.0], colors = [ color ], zorder=10 ) cont50 = plt.contourf ( X, Y, hldZ50, levels=[1.,10.], colors = [ color, color ], alpha=getAlpha( color ), zorder=10 ) plt.clabel ( cont50c, fmt="68%.0s" ) if hasattr ( cont50, "axes" ): ax = cont50.axes else: ax = cont50.ax while isCloseToExisting ( minXY, existingPoints ): minXY = ( minXY[0]+8., minXY[1]+8., minXY[2] ) a = ax.scatter( [ minXY[0] ], [ minXY[1] ], marker="*", s=180, color="black", zorder=20 ) anan = ana.replace(":None",":UL") # + " (%.2f)" % (minXY[2]) label = self.getPrettyName ( ana ) a = ax.scatter( [ minXY[0] ], [ minXY[1] ], marker="*", s=110, color=color, label=label, alpha=1., zorder=20 ) existingPoints.append ( minXY ) handles.append ( a ) ZCOMB = float("nan")*X for irow,row in enumerate(Z): for icol,col in enumerate(row): h = 0 if len(x)> icol and len(y) > irow: h = self.getHash(list(x)[icol],list(y)[irow]) if h in combL and not np.isnan(combL[h]): ZCOMB[irow,icol]=combL[h] if combL[h]==0.: ZCOMB[irow,icol]=float("nan") self.ZCOMB = ZCOMB contRMAX = plt.contour ( X, Y, RMAX, levels=[self.rthreshold], colors = [ "gray" ], zorder=10 ) contRMAXf = plt.contourf ( X, Y, RMAX, levels=[self.rthreshold,float("inf")], colors = [ "gray" ], hatches = ['////'], alpha=getAlpha( "gray" ), zorder=10 ) hldZcomb68 = computeHPD ( ZCOMB, RMAX, .68, False, rthreshold=self.rthreshold ) contZCOMB = plt.contour ( X, Y, hldZcomb68, levels=[.25], colors = [ "black" ], zorder=10 ) # ax.scatter( [ minXY[0] ], [ minXY[1] ], marker="s", s=110, color="gray", label="excluded", alpha=.3, zorder=20 ) print() self.pprint ( "timestamp:", self.timestamp, self.topo, max(x) ) dx,dy = max(x)-min(x),max(y)-min(y) if self.drawtimestamp: plt.text( max(x)-.37*dx,min(y)-.11*dy,self.timestamp, c="gray" ) ### the altitude of the alpha quantile is l(nuhat) - .5 chi^2_(1-alpha);ndf ### so for alpha=0.05%, ndf=1 the dl is .5 * 3.841 = 1.9207 ### for ndf=2 the dl is ln(alpha) = .5 * 5.99146 = 2.995732 ### folien slide 317 if hasattr ( cont50, "axes" ): ax = cont50.axes else: ax = cont50.ax # Xs,Ys=X,Y Xs,Ys = filterSmaller ( X, Y ) h = self.getHash() # print ( "hash is", h ) #s=" (??)" #if h in L: # s=" (%.2f)" % L[h] #s=" (%.2f)" % self.getLClosestTo ( L ) s="" ax.scatter( [ self.mx ], [ self.my ], marker="*", s=200, color="white", zorder=20 ) c = ax.scatter( [ self.mx ], [ self.my ], marker="*", s=160, color="black", label="proto-model%s" % s, zorder=20 ) handles.append ( c ) if sr == None: sr = "UL" # plt.title ( "HPD regions, %s [%s]" % ( namer.texName(pid1, addSign=False, addDollars=True), self.topo ), fontsize=14 ) plt.xlabel ( "m(%s) [GeV]" % namer.texName(pid1,addSign=False, addDollars=True), fontsize=14 ) plt.ylabel ( "m(%s) [GeV]" % namer.texName(self.pid2, addSign=False, addDollars=True), fontsize=14 ) circ1 = mpatches.Patch( facecolor="gray",alpha=getAlpha("gray"),hatch=r'////',label='excluded by critic', edgecolor="black" ) handles.append ( circ1 ) plt.legend( handles=handles, loc="upper left", fontsize=12 ) figname = "%s/llhd%d.png" % ( self.rundir, pid1 ) self.pprint ( "saving to %s" % figname ) plt.savefig ( figname ) if self.interactive: self.axes = ax self.plt = plt plt.close() if self.copy: self.copyFile ( figname ) return
def draw( pid= 1000022, interactive=False, pid2=0, copy=False, drawtimestamp = True, rundir = None, plotrmax=False, rthreshold = 1.3, upload = "latest" ): """ draw plots :param copy: copy final plots to ../../smodels.github.io/protomodels/latest :param drawtimestamp: if True, put a timestamp on it :param plotrmax: if True, plot also rmax curve :param upload: upload directory, default is "latest" """ if pid2 == 0: ## means all pidpairs = findPidPairs( rundir ) if len(pidpairs) == 0: print ( "[scanner] could not find ssm*pcl files. Maybe run ./fetchFromClip.py --ssms" ) return for pids in pidpairs: try: draw ( pids[0], interactive, pids[1], copy, drawtimestamp, \ rundir, plotrmax, upload = upload ) except Exception as e: print ( "[scanner] %s" % e ) return def isSSMPlot(): ## is this an ssm or a mass plot return pid2!=-1 import matplotlib matplotlib.use("Agg") from matplotlib import pyplot as plt import pickle namer = SParticleNames ( susy = False ) #if False: # rundir = "" picklefile = "%sscanM%s.pcl" % (rundir, pid ) if isSSMPlot(): picklefile = "%sssm%s%d.pcl" % ( rundir, pid, pid2 ) with open ( picklefile, "rb" ) as f: Zs = pickle.load( f ) cmass = pickle.load ( f ) ## cmass is pids nevents = pickle.load ( f ) timestamp = pickle.load ( f ) x = list(Zs.keys()) x.sort() y, yr, ydashed = [], [], [] rs = [] rsarea = [] for i in x: y_ = Zs[i] y0=y_ if type(y_)==tuple: idx = 2 if len(y_)==2: idx = 0 y0 = y_[idx] if y_[1] > rthreshold+.05 and plotrmax: rsarea.append ( y_[1] ) y0 = -1. else: rsarea.append ( 0. ) rs.append ( y_[1] ) ydashed.append ( Zs[i][idx] ) y2_ = y0 if y2_ < 0.: y2_ = float("nan") y.append ( y0 ) yr.append ( y2_ ) pname = namer.texName ( pid, addDollars=False ) if isSSMPlot(): #pname = namer.texName ( pid, addDollars=False, addSign=True )+","+\ # namer.texName ( pid2, addDollars=False, addSign=True ) pname = namer.texName ( pid2, addDollars=False, addSign=True )+\ namer.texName ( pid, addDollars=False, addSign=True ) fig,ax1 = plt.subplots() plt.plot ( x, ydashed, linewidth=.3, c="tab:blue", zorder=0 ) plt.plot ( x, yr, linewidth=2., label="$K(%s)$" % ( pname ), c="tab:blue", zorder=0 ) #plt.plot ( x, yr, linewidth=2., label="$K(%s)$, %dk events" % ( pname, nevents/1000 ), # c="tab:blue", zorder=0 ) ax1.tick_params ( axis="y", labelcolor="tab:blue", labelsize=12, labelleft=True ) ax1.tick_params ( axis="x", labelsize=12 ) ax1.set_ylabel ( "K", c="tab:blue", fontsize=15 ) # ax1.set_xlabel ( "m [GeV]", fontsize=13 ) ax1.set_xlabel ( "$m(%s)$ [GeV]" % pname, fontsize=16 ) maxyr = numpy.nanmax(ydashed) # print ( "ydashed", ydashed ) ax1.set_ylim ( bottom = 2., top=8.4 ) #ax1.set_ylim ( bottom = 2., top=maxyr*1.03 ) rsarea[0]=0. rsarea[-1]=0. if len(rs) == len(x) and plotrmax: ax2 = ax1.twinx() ax1.plot ([], [], label="$r_\mathrm{max}$", c="tab:red", zorder=1 ) ax2.plot ( x, rs, label="$r_\mathrm{max}$", c="tab:red", zorder=2 ) ax2.tick_params ( axis="y", labelcolor="tab:red", labelsize=12 ) #ax2.set_ylim ( bottom=min(rs)*.7, top = 1.9 ) ax2.set_ylim ( bottom=0.6, top = 1.9 ) ax2.set_ylabel ( "$r_\mathrm{max}$", c="tab:red", fontsize=16 ) if len(rsarea) == len(x) and plotrmax: # ax3 = ax1.twinx() ax2.fill ( x, rsarea, lw=0, edgecolor="white", alpha=.2, facecolor="tab:red", zorder=-1 ) ymax = max(y) imax = y.index ( ymax ) xmax = x[imax] param="%d GeV" % xmax if isSSMPlot(): param="%.3f" % xmax # label = "maximum K\n K(%s)=%.2f" % (param, ymax ) label = "maximum K" ax1.scatter ( [ xmax ], [ ymax ], label=label, s=130, c="k", marker="v", zorder=5 ) if type(cmass)==tuple: cmass = x[int(len(x)/2)] param = "%d GeV" % cmass if isSSMPlot(): param="%.3f" % cmass Zmax = getClosest( cmass, Zs ) if type(Zmax)==tuple: Zmax=Zmax[idx] # label = "proto-model\n K(%s)=%.2f" % (param, Zmax ) label = "proto-model" ax1.scatter ( [ cmass ], [ Zmax ], label=label, marker="^", s=130, c="g", zorder=10 ) # plt.title ( "Test statistic $K=K(%s)$" % pname, fontsize=14 ) if drawtimestamp: plt.text ( .7, -.12, timestamp, c="gray", transform = ax1.transAxes ) if isSSMPlot(): plt.xlabel ( "$\\hat\\mu\\kappa(%s)$" % pname, fontsize=17 ) ax1.set_xlabel ( "$\\hat\\mu\\kappa(%s)$" % pname, fontsize=17 ) ax1.legend( fontsize = 12, loc= "lower left" ) else: ax1.legend( fontsize = 12 ) plt.xlabel ( "$m(%s)$ [GeV]" % pname, fontsize=16 ) # plt.text ( .9*min(x)+.1*(max(x)-min(x)), 1.*max(y), "%d events" % nevents ) figname = "M%d.png" % pid if isSSMPlot(): figname = "ssm_%d_%d.png" % ( pid, pid2 ) stdvar = numpy.std ( y ) if interactive: import IPython IPython.embed( using=False ) if stdvar < 1e-10: print ( "[scanner] standard deviation is a %.2f. Not plotting." % stdvar ) return print ( "[scanner] creating %s" % figname ) plt.tight_layout() plt.savefig ( figname ) plt.close() if copy: dest = os.path.expanduser ( "~/git/smodels.github.io" ) cmd = "cp %s/%s %s/protomodels/%s/" % ( rundir,figname, dest, upload ) o = subprocess.getoutput ( cmd ) print ( "[scanner] %s: %s" % ( cmd, o ) )
class RulerPlot: """ a class that encapsulates a horizontal ruler plot """ def __init__ ( self, inputfile="masses.txt", outputfile="out", Range=(None,None), formats={ "png": True }, printmass=False, mergesquark=True, drawdecays=True, hasResultsFor = None, verbosity="info", susy=False, trim= True ): """ :param mergesquark: if True, merge squarks FIXME :param susy: use SUSY particle names """ self.inputfile = inputfile self.slhafile = inputfile for e in [ "png", "pdf", "eps" ]: if outputfile.endswith(f".{e}"): formats[e]=True outputfile = outputfile.replace(f".{e}","") self.outputfile = outputfile self.range = Range if sum ( formats.values() ) == 0: formats["png"]=True ## if nothing, then pngs self.formats = formats self.printmass = printmass self.mergesquark = mergesquark self.hasResultsFor = hasResultsFor self.verbosity = verbosity self.logger=logging.getLogger("RulerPlot") self.susy = susy self.namer = SParticleNames ( susy = susy ) self.decays = {} self.getMasses() self.getRange() self.drawdecays = drawdecays self.trim = trim if drawdecays: self.getDecays() def getMasses ( self ): """ obtain the masses from input file, remove > 3000 GeV """ if self.inputfile.endswith ( ".slha" ): pmasses = self.retrieveMasses () masses={} # masses=pmasses for (pid,D) in pmasses.items(): masses[D["name"]] = D["m"] ## cut off at 3 TeV ret = [ m for m in masses.values() if m<3000. ] self.masses = ret self.logger.info ( "masses %s" % self.masses ) return ret def getDecays ( self ): """ obtain the decays from input file, remove > 3000 GeV """ f = pyslha.read ( self.slhafile ) massblock = f.blocks["MASS"] mpids = [] for mpid in massblock.keys(): if massblock[mpid]<3000.: mpids.append ( mpid ) decblock = f.decays decays = {} for mpid in mpids: dec = decblock[mpid].decays if len(dec)==0: continue for d in dec: if d.br < 1e-1: ## ignore too small branchings continue if not mpid in decays: decays[mpid]=[] decays[mpid].append( {"br": d.br, "ids": d.ids } ) self.decays = decays def getRange ( self ): """ given self.masses, compute the range that we wish to plot. """ maxvalue=max (self.masses) minvalue=min(self.masses) maxvalue = min ( [ maxvalue, 3100. ] ) minvalue = max ( [ 0, minvalue ] ) dm = maxvalue - minvalue if self.range[0] != None and self.range[0] >=0.: minvalue=self.range[0] if self.range[1] != None and self.range[1] >=0.: maxvalue=self.range[1] self.logger.info ( "range is [%d,%d]" % ( minvalue, maxvalue ) ) self.minmass = minvalue self.maxmass = maxvalue def retrieveMasses ( self ): """ retrieve the masses from slha file """ logger=logging.getLogger(__name__) logger.info ( "now extracting masses from slha file %s" % ( self.slhafile) ) namer = SParticleNames( susy = False ) f = pyslha.read ( self.slhafile ) m = f.blocks["MASS"] keys = m.keys() D={} for key in keys: mass = m[key] if mass > 4000.: continue name = namer.texName ( key ) if namer.isSM ( key ): ## skip SM particles continue if self.mergesquark: ## sum up all squarks if namer.particleType ( key ) == "q": name=name.rootName ( 1000001 ) D[key]={ "name": name, "m": mass } self.masspids = D return D def getSortedPids ( self ): """ get a container of pids, sorted by the masses """ sortedpids = [] for (pid,D) in self.masspids.items(): m = D["m"] sortedpids.append((m,pid)) sortedpids.sort() pids = [ x[1] for x in sortedpids ] return pids def drawHorizontal ( self ): # https://pythonprogramming.net/spines-hline-matplotlib-tutorial/ """ the matplotlib plotting function """ plt.rc("text",usetex=True) dm = self.maxmass - self.minmass ticks = numpy.arange ( self.minmass, self.maxmass, .05*dm ) y = [ 0. ] * len(ticks) y[0]=1. fig = plt.figure(figsize=(10,3)) ax1 = plt.subplot() # ax1 = plt.subplot2grid((1,1), (0,0)) labels = [] for i,label in enumerate(ax1.xaxis.get_ticklabels()): label.set_rotation(45) labels.append ( label.get_label() ) # " GeV" ) ax1.spines['right'].set_color('none') ax1.spines['left'].set_color('none') ax1.spines['top'].set_color('none') ax1.plot ( ticks, y, c="w" ) ax1.set_yticks([]) # plt.xlabel ( "m [GeV]" ) plt.text(self.maxmass+30.,-.12,"m [GeV]" ) sortedpids = self.getSortedPids() for ctr,pid in enumerate(sortedpids): name = self.masspids[pid]["name"] m = self.masspids[pid]["m"] y=(abs(m)-self.minmass)/(self.maxmass-self.minmass) col=self.namer.rgbColor ( name ) coldark=self.namer.rgbColor ( name, bold=True ) label = f"${name}$" yoff = 0. ## yoffset, put every second one halfway down if ctr % 2 == 1: yoff=.5 plt.text ( m, 1.-yoff, label, c = coldark, size=15, fontweight="bold" ) lctr=0 keys = [] if self.hasResultsFor != None: for mana,analyses in self.hasResultsFor.items(): # print ( "m,mana",m,mana ) if abs(m-mana)<.1: ## max mass gap if abs(m-mana)>1e-2: print ( "WARNING: clustering particle masses %.2f and %.2f. hope its ok. check it." % ( m, mana ) ) keys.append ( mana ) for cana,ana in enumerate(analyses): plt.text ( m-50., .91-yoff-.07*cana, ana.replace("201","1" ), c=col ) lctr+=1 plt.savefig ( "horizontal.png" ) self.ax1 = ax1 self.plt = plt def drawVertical ( self ): # https://pythonprogramming.net/spines-hline-matplotlib-tutorial/ """ the matplotlib plotting function """ from matplotlib import pyplot as plt plt.rc("text",usetex=True) import numpy dm = self.maxmass - self.minmass ticks = numpy.arange ( self.minmass, self.maxmass, .05*dm ) x = [ 0. ] * len(ticks) x[0]=1. figratio = ( 3, 10 ) if self.drawdecays: figratio = ( 5, 6 ) fig = plt.figure(figsize=figratio ) ax1 = plt.subplot() labels = [] for i,label in enumerate(ax1.yaxis.get_ticklabels()): # label.set_rotation(45) labels.append ( label.get_label() ) # " GeV" ) ax1.spines['right'].set_color('none') ax1.spines['left'].set_color('none') ax1.spines['top'].set_color('none') ax1.spines['bottom'].set_color('none') ax1.plot ( x, ticks, c="w" ) ax1.set_xticks([]) plt.text(-.22, self.minmass-30., "m [GeV]" ) sortedpids = self.getSortedPids() for ctr,pid in enumerate(sortedpids): name = self.masspids[pid]["name"] m = self.masspids[pid]["m"] # print ( "m", ctr, m, name ) y=(abs(m)-self.minmass)/(self.maxmass-self.minmass) col=self.namer.rgbColor ( name ) coldark=self.namer.rgbColor ( name, bold=True ) label = f"${name}$" ## compute the xoffset, we start at the center the move left and right xoff = 0.5 + (-1)**(ctr) * .15 * math.ceil(ctr/2) side = -1 ## -1 is left 1 is right if ctr % 2 == 0: side = 4. # print ( "mass", label, m, xoff ) plt.text ( xoff, m, label, c = coldark, size=15, fontweight="bold", ha="left" ) x1 = xoff + side * .05 x2 = x1 + numpy.sign(side)*.1 if ctr == 0: x2 = 1. ## small horizontal lines next to the particle names plt.plot ( [ x1, x2 ], [m+10. , m+10. ], c= coldark ) ## the LBP gets horizontal lines in both directions if ctr == 0: x1 = xoff - .05 x2 = .1 plt.plot ( [ x1, x2 ], [m+10. , m+10. ], c= coldark ) ## ## at the center of the decay line xavg = .5*x1 + .5*x2 lctr=0 dm = 20. if self.drawdecays: dm = 35. keys = [] if self.hasResultsFor != None: for mana,analyses in self.hasResultsFor.items(): # print ( "m,mana",m,mana ) if abs(m-mana)<.1: ## max mass gap if abs(m-mana)>1e-2: print ( "WARNING: clustering particle masses %.2f and %.2f. hope its ok. check it." % ( m, mana ) ) keys.append ( mana ) dm1 = 30. ## gap to first ana id if self.drawdecays: dm1 = 50. for cana,ana in enumerate(analyses): plt.text ( xavg, m-dm1-dm*cana, ana.replace("201","1" ), c=col, ha="center" ) lctr+=1 if pid in self.decays: ## now check for decays decays = self.decays[pid] # print ( "[rulerPlotter] check for decays", decays ) for d in decays[:1]: ids = d["ids"] br = d["br"] idBSM = 1000022 idNotBSM = [] for iD in ids: if abs(iD)>1000000: idBSM = iD else: idNotBSM.append( abs(iD) ) mlow = self.masspids[idBSM]["m"] + 20. # delta m that is due to ana ids dmResults = lctr * dm + bool(lctr)*30. mtop = m - dmResults - 10. dm = mlow - m + 20. + dmResults plt.arrow ( xavg, mtop, 0., dm , color="grey", linestyle="dashed", linewidth=.5, head_length=15, head_width=.05 ) label = self.namer.texName(idNotBSM,addDollars=True) if br < 0.95: label += ": %s" % br plt.text ( xavg + .05, mlow + 30., label, color="grey" ) for frmat,runthis in self.formats.items(): if not runthis: continue of = self.outputfile + "." + frmat self.logger.info ( "saving to %s" % of ) plt.savefig ( of ) if frmat == "png" and self.trim: cmd = "convert %s -trim %s" % ( of, of ) subprocess.getoutput ( cmd ) self.ax1 = ax1 self.plt = plt def interactiveShell( self ): import IPython IPython.embed()
def writeIndexTex(protomodel, texdoc): """ write the index.tex file :param texdoc: the source that goes into texdoc.png """ ssm = [] namer = SParticleNames(False) for k, v in protomodel.ssmultipliers.items(): if abs(v - 1.) < 1e-3: continue ssm.append("%s: %.2f" % (namer.texName(k, addSign=True), v)) f = open("index.tex", "w") f.write ( "Our current winner has a score of \\K=%.2f, " % \ ( protomodel.K ) ) strategy = "aggressive" dbver = getDatabaseVersion(protomodel) dotlessv = dbver.replace(".", "") f.write ( " it was produced with database {\\tt v%s}, combination strategy {\\tt %s} walker %d in step %d." % \ ( dotlessv, strategy, protomodel.walkerid, protomodel.step ) ) f.write("\n") if hasattr(protomodel, "tpList"): rvalues = protomodel.tpList rvalues.sort(key=lambda x: x[0], reverse=True) writeRValuesTex(rvalues) #writeRValuesTexOld ( rvalues ) else: print("[plotHiscore] protomodel has no r values!") if hasattr(protomodel, "analysisContributions"): print("[plotHiscore] contributions-per-analysis are defined") # f.write ( "Contributions per analysis:\n\\begin{itemize}[noitemsep,nolistsep]\n" ) f.write( "The contributions per analysis are given in Tab.~\\ref{tab:analysiscontributions}.\n" ) f.write("\\begin{table}\n") f.write("\\begin{center}\n") f.write("\\begin{tabular}{l|c|c}\n") f.write( "\\bf{Analysis Name} & \\bf{\\K(without)} & \\bf{Contribution} \\\\\n" ) f.write("\\hline\n") conts = [] dKtot = 0. Ktot = protomodel.K contributions = protomodel.analysisContributions for k, v in contributions.items(): conts.append((v, k)) dKtot += Ktot - v # dKtot = dKtot # * protomodel.K Ks, Kwo = {}, {} """ for k,v in contributions: Ks[k] = ( protomodel.K - dKtot * v) Kwo[k] = protomodel.K """ conts.sort(reverse=True) for v, k in conts: Kwithout = contributions[k] cont = (Ktot - Kwithout) / dKtot f.write("%s & %.2f & %s%s \\\\ \n" % (k, Kwithout, int(round(100. * cont)), "\\%")) # f.write ( "\item %s: %s%s\n" % ( k, int(round(100.*v)), "\\%" ) ) # f.write ( "\end{itemize}\n" ) f.write("\\end{tabular}\n") f.write("\\end{center}\n") f.write( "\\caption{Contributions to the test statistic \\K. \\K(without) denotes the \\K value obtained in absence of the particular analysis.}\n" ) f.write("\\label{tab:analysiscontributions}\n") f.write("\\end{table}\n") else: print("[plotHiscore] contributions are not defined") height = 32 * int((len(ssm) + 3) / 4) if ssm == []: height = 32 if hasattr(protomodel, "particleContributions"): height += 32 # f.write ( "<td><img width=600px src=./texdoc.png>\n" ) # % height ) # f.write ( "\small{Last updated: %s}\n" % time.asctime() ) # f.write ( "% include decays.png\n" ) contrs = texdoc.replace(":", " are ").replace("S", "The s").replace(";", ", ") contrs = contrs.replace("\\\\\\\\Contr", "; the contr") f.write(contrs + "\n") f.close() print("[plotHiscore] Wrote index.tex")
def writeTex(protomodel, keep_tex): """ write the comment about ss multipliers and particle contributions, in tex. Creates texdoc.png. :param keep_tex: keep tex source of texdoc.png """ cpids = {} frozen = protomodel.frozenParticles() xsecs = protomodel.getXsecs()[0] ssms = getUnfrozenSSMs(protomodel, frozen, includeOnes=True) namer = SParticleNames(susy=False) for pids, v in ssms.items(): xsec = findXSecOfPids(xsecs, pids) if xsec < 0.001 * fb: ## only for xsecs we care about continue sv = "%.2g" % v if v < .1: sv = "%.1g" % v if not sv in cpids: cpids[sv] = [] cpids[sv].append(pids) ssm = {} for v, pids in cpids.items(): sp = [] for pairs in pids: pname = namer.texName(pairs, addSign=True, addBrackets=True) sp.append(pname) ssm[v] = ", ".join(sp) particleContributionList = "" if hasattr(protomodel, "particleContributions"): print("[plotHiscore] contributions-by-particle are defined") #particleContributionList+="\\\\Contributions by particles: $" particleContributionList += "\\\\" particleContributionList += "Contributions by particles: $" totalcont = 0. ## to normalize contributions for k, v in protomodel.particleContributions.items(): totalcont += (protomodel.K - v) tok = {} for k, v in protomodel.particleContributions.items(): if v in tok.keys(): v += 1e-6 perc = 100. if totalcont != 0.: perc = round(100. * (protomodel.K - v) / totalcont) tok[v] = "%s: K_\mathrm{without}=%.2f (%d%s)" % (namer.texName(k), v, perc, "\%") # tok[v] = "%s = (%.2f) %d%s" % ( namer.texName(k), v, perc, "\%" ) keys = list(tok.keys()) keys.sort() for v in keys: particleContributionList += tok[v] + ", " if len(keys) > 0: particleContributionList = particleContributionList[:-2] #particleContributionList+= ", ".join ( tok ) particleContributionList += "$" else: print( "[plotHiscore] protomodel has no ``particleContributions'' defined." ) from plotting import tex2png src = getExtremeSSMs(ssm, largest=True, nm=7) src += "\\\\" nsmallest = min(7, len(ssm) - 7) if nsmallest > 0: src += getExtremeSSMs(ssm, largest=False, nm=nsmallest) src += particleContributionList if keep_tex: with open("texdoc.tex", "wt") as f: f.write(src + "\n") f.close() print("[plotHiscore] wrote %s/texdoc.tex" % os.getcwd()) try: p = tex2png.Latex(src, 600).write() f = open("texdoc.png", "wb") f.write(p[0]) f.close() except Exception as e: print("[plotHiscore] Exception when latexing: %s" % e) return src
def writeRawNumbersLatex(protomodel, usePrettyNames=True): """ write out the raw numbers of the excess, in latex :param usePrettyNames: use the pretty names, not analysis ids """ print("raw numbers of excess") print("=====================") f = open("rawnumbers.tex", "wt") f.write("\\begin{tabular}{l|c|r|r|c|r|r}\n") f.write( "\\bf{Analysis Name} & \\bf{Dataset} & \\bf{Obs} & \\bf{Expected} & \\bf{Z} & \\bf{Particle} & \\bf{Signal} \\\\\n" ) f.write("\\hline\n") namer = SParticleNames(susy=False) bibtex = BibtexWriter() from smodels_utils.helper.prettyDescriptions import prettyTexAnalysisName for tp in protomodel.bestCombo: anaId = tp.analysisId() ananame = anaId if usePrettyNames: ananame = prettyTexAnalysisName(None, anaid=anaId) dtype = tp.dataType() print("[plotHiscore] item %s (%s)" % (anaId, dtype)) dt = {"upperLimit": "ul", "efficiencyMap": "em"} # f.write ( "%s & %s & " % ( anaId, dt[dtype] ) ) ref = bibtex.query(anaId) f.write("%s~\\cite{%s} & " % (ananame, ref)) if dtype == "efficiencyMap": dI = tp.dataset.dataInfo obsN = dI.observedN if (obsN - int(obsN)) < 1e-6: obsN = int(obsN) print ( " `- %s: observedN %s, bg %s +/- %s" % \ ( dI.dataId, obsN, dI.expectedBG, dI.bgError ) ) did = dI.dataId.replace("_", "\_") if len(did) > 9: did = did[:6] + " ..." eBG = dI.expectedBG if eBG == int(eBG): eBG = int(eBG) bgErr = dI.bgError if bgErr == int(bgErr): bgErr = int(bgErr) toterr = math.sqrt(bgErr**2 + eBG) if toterr > 0.: S = "%.1f $\sigma$" % ((dI.observedN - eBG) / toterr) # pids = tp.PIDs pids = set() for prod in tp.PIDs: for branch in prod: for pid in branch: if type(pid) == int and abs(pid) != 1000022: pids.add(abs(pid)) if type(pid) in [list, tuple]: p = abs(pid[0]) if p != 1000022: pids.add(p) particles = namer.texName(pids, addDollars=True, addSign=False, addBrackets=False) obs = dI.observedN if obs == 0.: obs = 0 else: if abs(obs - int(obs)) / obs < 1e-6: obs = int(obs) sigN = tp.xsection.value.asNumber( fb) * tp.dataset.globalInfo.lumi.asNumber(1 / fb) #sigmapred="%.2f fb" % ( tp.xsection.value.asNumber(fb) ) sigmapred = "%.2f" % sigN f.write ( "%s & %s & %s $\\pm$ %s & %s & %s & %s \\\\ \n" % \ ( did, obs, eBG, bgErr, S, particles, sigmapred ) ) if dtype == "upperLimit": S = "?" llhd, chi2 = tp.likelihoodFromLimits(expected=False, chi2also=True) eUL = tp.expectedUL.asNumber(fb) oUL = tp.upperLimit.asNumber(fb) sigma_exp = eUL / 1.96 # the expected scale, sigma Z = (oUL - eUL) / sigma_exp # Z = math.sqrt ( chi2 ) S = "%.1f $\sigma$" % Z pids = set() for prod in tp.PIDs: for branch in prod: for pid in branch: if type(pid) == int and abs(pid) != 1000022: pids.add(abs(pid)) if type(pid) in [tuple, list]: for p in pid: if type(p) == int and abs(p) != 1000022: pids.add(abs(p)) particles = namer.texName(pids, addDollars=True, addSign=False, addBrackets=False) sigmapred = "%.2f fb" % (tp.xsection.value.asNumber(fb)) print(" `- observed %s, expected %s" % (tp.upperLimit, tp.expectedUL)) f.write(" & %.1f fb & %.1f fb & %s & %s & %s \\\\ \n" % (tp.upperLimit.asNumber(fb), tp.expectedUL.asNumber(fb), S, particles, sigmapred)) f.write("\end{tabular}\n") f.close()