def checkOneAnalysis(): import argparse #import IPython argparser = argparse.ArgumentParser( description='print the correlations of one specific analysis') argparser.add_argument( '-d', '--dbpath', help='specify path to database [<rundir>/database.pcl]', type=str, default="<rundir>/database.pcl") argparser.add_argument('-a', '--analysis', help='print for <analysis>', type=str, default="CMS-SUS-19-006") args = argparser.parse_args() from smodels.experiment.databaseObj import Database print("[analysisCombiner] checking %s" % args.dbpath) db = Database(args.dbpath) results = db.getExpResults() info = getInfoFromAnaId(args.analysis, results) sqrts = info.sqrts collaboration = getExperimentName(info) prettyName = info.prettyName if args.analysis in moreComments: prettyName += " (%s)" % moreComments[args.analysis] # IPython.embed() print("correlations for %s: %s" % (args.analysis, prettyName)) combs, nocombs = set(), set() pnames = {} for er in results: if er.globalInfo.sqrts != sqrts: continue if getExperimentName(er.globalInfo) != collaboration: continue Id = er.globalInfo.id Id = Id.replace("-eff", "").replace("-agg", "") if Id == "CMS-SUS-19-006-2": Id = "CMS-SUS-19-006" if Id == args.analysis: continue pname = er.globalInfo.prettyName if Id in moreComments: pname += " (%s)" % moreComments[Id] pnames[Id] = pname cc = canCombine(info, er.globalInfo, "aggressive") # cc = canCombine ( pred, er.globalInfo ) if cc: combs.add(Id) else: nocombs.add(Id) print("can combine with: ") for Id in combs: pname = pnames[Id] print(" `- %s: %s" % (Id, pname)) print("cannot combine with: ") for Id in nocombs: pname = pnames[Id] print(" `- %s: %s" % (Id, pname))
def collect(): db = Database ( "./database.pcl" ) # , force_load = "txt" ) ers = db.getExpResults ( dataTypes = [ "upperLimit" ], onlyWithExpected=True ) allSs = [] for er in ers: txnlist = er.datasets[0].txnameList for txn in txnlist: ct=0 origdata = eval(txn.txnameData.origdata) for point in origdata: m = point[0] rul = point[1] ul,eul=None,None try: ul = txn.getULFor(m, False ) eul = txn.getULFor(m, True ) except Exception: pass if type(ul) == type(None) or type(eul) == type(None): continue sigma = eul / 1.96 S = float ( ( ul - eul ) / sigma ) if (S < -1.8 or S > 3.5) and ct<3: # if S > 10. and ct<3: print ( ) print ( "S=%.2f for ul=%s, eul=%s sigma=%s" % ( S, ul, eul, sigma ) ) print ( " at ", er.globalInfo.id, txn.txName, m, "rul", rul ) ct += 1 allSs.append ( S ) # print ( "->", er.globalInfo.id, txn, S ) print ("all", min(allSs), np.mean(allSs), max(allSs) ) f=open("ulSs.pcl","wb") pickle.dump(allSs,f) f.close() sys.exit()
def getSRs(): from smodels.experiment.databaseObj import Database db = Database ( "official" ) ers = db.getExpResults( dataTypes=[ "efficiencyMap" ] ) stats = [] for er in ers: for ds in er.datasets: D = { "obsN": ds.dataInfo.observedN, "expectedBG": ds.dataInfo.expectedBG, "bgError": ds.dataInfo.bgError, "upperLimit": ds.dataInfo.upperLimit, "expectedUpperLimit": ds.dataInfo.expectedUpperLimit } stats.append ( D ) return stats
def getSummary(): from smodels.experiment.databaseObj import Database # dbpath = "official" dbpath = "<rundir>/database.pcl" print("[analysisCombiner] checking %s" % dbpath) db = Database(dbpath) results = db.getExpResults() strategy = "aggressive" ana1 = "CMS-SUS-16-042" ana2 = "CMS-SUS-16-033" canC = canCombine(ana1, ana2, strategy, results) print("[analysisCombiner] can combine %s with %s: %s" % (ana1, ana2, str(canC))) ctr, combinable = 0, 0 for x, e in enumerate(results): for y, f in enumerate(results): if y <= x: continue ctr += 1 isUn = canCombine(e.globalInfo, f.globalInfo, strategy) combinable += isUn print("[analysisCombiner] can combine %d/%d pairs of results" % (combinable, ctr))
from smodels.theory.model import Model from smodels.tools.physicsUnits import fb model = Model(BSMparticles=BSMList, SMparticles=SMList) model.updateParticles(inputFile=args.slhafile) print("[combiner] loading database", args.database) db = Database(args.database) print("[combiner] done loading database") anaIds = ["CMS-SUS-16-033"] anaIds = ["all"] dts = ["all"] if args.upper_limits: dts = ["upperLimit"] if args.efficiencyMaps: dts = ["efficiencyMap"] listOfExpRes = db.getExpResults(analysisIDs=anaIds, dataTypes=dts, onlyWithExpected=True) smses = decomposer.decompose(model, .01 * fb) #print ( "[combiner] decomposed into %d topos" % len(smses) ) from smodels.theory.theoryPrediction import theoryPredictionsFor combiner = Combiner() allps = [] for expRes in listOfExpRes: preds = theoryPredictionsFor(expRes, smses) if preds == None: continue for pred in preds: allps.append(pred) combo, globalZ, llhd, muhat = combiner.findHighestSignificance( allps, "aggressive", expected=args.expected) print("[combiner] global Z is %.2f: %s (muhat=%.2f)" %
class Predictor: def __init__(self, walkerid, dbpath="./default.pcl", expected=False, select="all", do_combine=False): """ :param do_combine: if True, then also use combined results, both via simplified likelihoods and pyhf. """ self.walkerid = walkerid self.do_combine = do_combine self.modifier = None self.select = select self.expected = expected self.rthreshold = 1.3 ## threshold for rmax if expected: from expResModifier import ExpResModifier self.modifier = ExpResModifier() force_load = None if dbpath.endswith(".pcl"): force_load = "pcl" ntries = 0 while not os.path.exists(dbpath): ## give it a few tries ntries += 1 time.sleep(ntries * 5) if ntries > 5: break self.database = Database(dbpath, force_load=force_load) self.fetchResults() self.combiner = Combiner(self.walkerid) def filterForAnaIdsTopos(self, anaIds, topo): """ filter the list of expRes, keep only anaIds """ keepExpRes = [] nbefore = len(self.listOfExpRes) for er in self.listOfExpRes: eid = er.globalInfo.id if not eid in anaIds: continue txnames = [x.txName for x in er.getTxNames()] if not topo in txnames: ## can safely skip continue newDS = [] for dataset in er.datasets: newTxNames = [] for txName in dataset.txnameList: if txName.txName != topo: continue newTxNames.append(txName) if len(newTxNames) > 0: dataset.txnameList = newTxNames newDS.append(dataset) if len(newDS) > 0: er.datasets = newDS keepExpRes.append(er) self.pprint ( "filtered for %s, keeping %d/%d expRes" % \ ( topo, len(keepExpRes), nbefore) ) self.listOfExpRes = keepExpRes def filterForTopos(self, topo): """ filter the list of expRes, keep only the ones for topo """ keepExpRes = [] nbefore = len(self.listOfExpRes) for er in self.listOfExpRes: txnames = [x.txName for x in er.getTxNames()] if not topo in txnames: ## can safely skip continue newDS = [] for dataset in er.datasets: newTxNames = [] for txName in dataset.txnameList: if txName.txName != topo: continue newTxNames.append(txName) if len(newTxNames) > 0: dataset.txnameList = newTxNames newDS.append(dataset) if len(newDS) > 0: er.datasets = newDS keepExpRes.append(er) self.pprint ( "filtered for %s, keeping %d/%d expRes" % \ ( topo, len(keepExpRes), nbefore) ) self.listOfExpRes = keepExpRes def fetchResults(self): """ fetch the list of results, perform all selecting and modding """ dataTypes = ["all"] if self.select == "em": dataTypes = ["efficiencyMap"] if self.select == "ul": dataTypes = ["upperLimit"] txnames = ["all"] if self.select.startswith("txnames:"): s = self.select.replace("txnames:", "") txnames = s.split(",") self.pprint("I have been asked to select txnames for %s" % s) listOfExpRes = self.database.getExpResults(dataTypes=dataTypes, txnames=txnames, useNonValidated=True) if self.modifier: listOfExpRes = self.modifier.modify(listOfExpRes) self.listOfExpRes = listOfExpRes if False: f = open("expresults.txt", "wt") for expRes in self.listOfExpRes: f.write("%s %s\n" % (expRes.id(), expRes.datasets[0])) f.close() def pprint(self, *args): """ logging """ print("[predictor] %s" % (" ".join(map(str, args)))) self.log(*args) def log(self, *args): """ logging to file """ with open("walker%d.log" % self.walkerid, "a") as f: f.write("[predictor-%s] %s\n" % (time.strftime("%H:%M:%S"), " ".join(map(str, args)))) def predict(self, protomodel, sigmacut=0.02 * fb, strategy="aggressive", keep_predictions=False): """ Compute the predictions and statistical variables, for a protomodel. :param sigmacut: weight cut on the predict xsecs for theoryPredictions :param strategy: combination strategy, currently only aggressive is used :param keep_predictions: if True, then keep all predictions (in self, not in protomodel!!) :returns: False, if no combinations could be found, else True """ if hasattr(self, "predictions"): del self.predictions ## make sure we dont accidentally use old preds # Create SLHA file (for running SModelS) slhafile = protomodel.createSLHAFile() # First run SModelS using all results and considering only the best signal region. # thats the run for the critic bestpreds = self.runSModelS(slhafile, sigmacut, allpreds=False, llhdonly=False) if keep_predictions: self.bestpreds = bestpreds # Extract the relevant prediction information and store in the protomodel: self.updateModelPredictions(protomodel, bestpreds) # self.log ( "model is excluded? %s" % str(protomodel.excluded) ) # Compute the maximum allowed (global) mu value given the r-values # stored in protomodel protomodel.mumax = self.getMaxAllowedMu(protomodel) # now use all prediction with likelihood values to compute the Z of the model predictions = self.runSModelS(slhafile, sigmacut, allpreds=True, llhdonly=True) if keep_predictions: self.predictions = predictions # Compute significance and store in the model: self.computeSignificance(protomodel, predictions, strategy) if protomodel.Z is None: self.log( "done with prediction. Could not find combinations (Z=%s)" % (protomodel.Z)) protomodel.delCurrentSLHA() return False else: self.log("done with prediction. best Z=%.2f (muhat=%.2f)" % (protomodel.Z, protomodel.muhat)) protomodel.cleanBestCombo() #Recompute predictions with higher accuracy for high score models: if protomodel.Z > 2.7 and protomodel.nevents < 55000: protomodel.nevents = 100000 protomodel.computeXSecs() self.predict(protomodel, sigmacut=sigmacut, strategy=strategy) protomodel.delCurrentSLHA() return True def runSModelS(self, inputFile, sigmacut, allpreds, llhdonly): """ run smodels proper. :param inputFile: the input slha file :param sigmacut: the cut on the topology weights, typically 0.02*fb :param allpreds: if true, return all predictions of analyses, else only best signal region :param llhdonly: if true, return only results with likelihoods """ if not os.path.exists(inputFile): self.pprint("error, cannot find inputFile %s" % inputFile) return [] model = Model(BSMList, SMList) model.updateParticles(inputFile=inputFile) mingap = 10 * GeV # self.log ( "Now decomposing" ) topos = decomposer.decompose(model, sigmacut, minmassgap=mingap) self.log("decomposed model into %d topologies." % len(topos)) if allpreds: bestDataSet = False combinedRes = False else: bestDataSet = True combinedRes = self.do_combine preds = [] # self.log ( "start getting preds" ) from smodels.tools import runtime runtime._experimental = True for expRes in self.listOfExpRes: predictions = theoryPredictionsFor(expRes, topos, useBestDataset=bestDataSet, combinedResults=combinedRes) if predictions == None: predictions = [] if allpreds: combpreds = theoryPredictionsFor( expRes, topos, useBestDataset=False, combinedResults=self.do_combine) if combpreds != None: for c in combpreds: predictions.append(c) for prediction in predictions: prediction.computeStatistics() if (not llhdonly) or (prediction.likelihood != None): preds.append(prediction) sap = "best preds" if allpreds: sap = "all preds" sllhd = "" if llhdonly: sllhd = ", llhds only" self.log ( "returning %d predictions, %s%s" % \ (len(preds),sap, sllhd ) ) return preds def printPredictions(self): """ if self.predictions exists, pretty print them """ if hasattr(self, "predictions"): print("[predictor] all predictions (for combiner):") for p in self.predictions: print ( " - %s %s, %s %s" % \ ( p.analysisId(), p.dataType(), p.dataset.dataInfo.dataId, p.txnames ) ) if hasattr(self, "bestpreds"): print("[predictor] best SR predictions (for critic):") for p in self.bestpreds: print ( " - %s %s, %s %s" % \ ( p.analysisId(), p.dataType(), p.dataset.dataInfo.dataId, p.txnames ) ) def updateModelPredictions(self, protomodel, predictions): """ Extract information from list of theory predictions and store in the protomodel. :param predictions: all theory predictions :returns: list of tuples with observed r values, r expected and theory prediction info (sorted with highest r-value first) """ rvalues = [] #If there are no predictions set rmax and r2 to 0 tpList = [] for theorypred in predictions: r = theorypred.getRValue(expected=False) if r == None: self.pprint("I received %s as r. What do I do with this?" % r) r = 23. rexp = theorypred.getRValue(expected=True) # tpList.append( (r, rexp, self.combiner.removeDataFromTheoryPred ( theorypred ) ) ) tpList.append((r, rexp, theorypred)) rvalues.append(r) while len(rvalues) < 2: rvalues.append(0.) rvalues.sort(reverse=True) srs = "%s" % ", ".join(["%.2f" % x for x in rvalues[:3]]) self.log("top r values before rescaling are: %s" % srs) protomodel.rvalues = rvalues #Do not include initial zero values # protomodel.excluded = protomodel.rvalues[0] > self.rthreshold #The 0.99 deals with the case rmax = threshold protomodel.tpList = tpList[:] def getMaxAllowedMu(self, protomodel): """ Compute the maximum (global) signal strength normalization given the predictions. """ mumax = float("inf") if protomodel.rvalues[0] > 0.: #Set mumax slightly below threshold, so the model is never excluded mumax = 0.999 * self.rthreshold / protomodel.rvalues[0] return mumax def computeSignificance(self, protomodel, predictions, strategy): """ compute the K and Z values, and attach them to the protomodel """ self.log("now find highest significance for %d predictions" % len(predictions)) ## find highest observed significance #(set mumax just slightly below its value, so muhat is always below) mumax = protomodel.mumax combiner = self.combiner bestCombo, Z, llhd, muhat = combiner.findHighestSignificance( predictions, strategy, expected=False, mumax=mumax) prior = combiner.computePrior(protomodel) if hasattr(protomodel, "keep_meta") and protomodel.keep_meta: protomodel.bestCombo = bestCombo else: protomodel.bestCombo = combiner.removeDataFromBestCombo(bestCombo) protomodel.Z = Z if Z is not None: # Z is None when no combination was found protomodel.K = combiner.computeK(Z, prior) else: protomodel.K = None protomodel.llhd = llhd protomodel.muhat = muhat protomodel.letters = combiner.getLetterCode(protomodel.bestCombo) protomodel.description = combiner.getComboDescription( protomodel.bestCombo)
class LlhdPlot: """ A simple class to make debugging the plots easier """ def __init__ ( self, pid1, pid2, verbose, copy, max_anas, interactive, drawtimestamp, compress, rundir, upload ): """ :param pid1: pid for x axis, possibly a range of pids :param pid2: pid for y axis :param verbose: verbosity (debug, info, warn, or error) :param copy: copy plot to ../../smodels.github.io/protomodels/latest :param max_anas: maximum number of analyses on summary plot :param interactive: prepare for an interactive session? :param drawtimestamp: if true, put a timestamp on plot :param compress: prepare for compression :param upload: upload directory, default is "latest" """ self.rundir = rundir self.upload = upload self.setup( pid1, pid2 ) self.DEBUG, self.INFO = 40, 30 self.drawtimestamp = drawtimestamp self.max_anas = max_anas ## maximum number of analyses self.copy = copy self.rthreshold = 1.7 self.interactive = interactive self.hiscorefile = "./hiscore.hi" if rundir != None: self.hiscorefile = f"{rundir}/hiscore.hi" self.setVerbosity ( verbose ) masspoints,mx,my,nevents,topo,timestamp = self.loadPickleFile( compress ) self.masspoints = masspoints self.mx = mx self.my = my self.nevents = nevents self.topo = topo self.timestamp = timestamp self.massdict = {} self.rdict = {} if masspoints == None: return for m in masspoints: self.massdict[ (m[0],m[1]) ] = m[2] if len(m)>3: self.rdict[ (m[0],m[1]) ] = m[3] def setVerbosity ( self, verbose ): self.verbose = verbose if type(verbose)==str: verbose = verbose.lower() if "deb" in verbose: self.verbose = 40 return if "inf" in verbose: self.verbose = 30 return if "warn" in verbose: self.verbose = 20 return if "err" in verbose: self.verbose = 10 return self.pprint ( "I dont understand verbosity ``%s''. Setting to debug." % verbose ) self.verbose = 40 def getHash ( self, m1=None, m2=None ): """ get hash for point. if None, get hash for self.mx, self.my """ if m1 == None: m1 = self.mx if m2 == None: m2 = self.my return int(1e3*m1) + int(1e0*m2) def getResultFor ( self, ana, masspoint ): """ return result for ana/topo pair :param ana: the analysis id. optionally a data type can be specificed, e.g. as :em. Alternatively, a signal region can be specified. :param masspoint: a point from self.masspoints :returns: results for this analysis (possibly data type, possibly signal region) and topology """ #self.pprint ( "asking for %s" % ana ) ret,sr = None, None dType = "any" if ":" in ana: ana,dType = ana.split(":") for k,v in masspoint.items(): tokens = k.split(":") if dType == "ul" and tokens[1] != "None": continue if dType == "em" and tokens[1] == "None": continue if ana != tokens[0]: continue # self.pprint ( "asking for %s, %s %s" % ( tokens[0], tokens[1], dType ) ) if tokens[1] != None and dType not in [ "any", "ul", "None" ]: # if signal regions are given, they need to match if tokens[1] != dType: continue self.debug ( "found a match for", tokens[0], tokens[1], v ) if self.topo not in tokens[2]: continue if ret == None or v > ret: ret = v sr = tokens[1] return ret,sr def loadPickleFile ( self, returnAll=False ): """ load dictionary from picklefile :param returnAll: return all likelihoods info """ topo, timestamp = "?", "?" allhds = None with open ( self.picklefile, "rb" ) as f: try: allhds = pickle.load ( f ) mx = pickle.load ( f ) my = pickle.load ( f ) nevents = pickle.load ( f ) topo = pickle.load ( f ) timestamp = pickle.load ( f ) except EOFError as e: print ( "[plotLlhds] EOF error %s, when reading %s" % \ ( e, self.picklefile ) ) f.close() if allhds == None: print ( "couldnt read llhds in %s" % self.picklefile ) return None,None,None,None,None,None if returnAll: return allhds,mx,my,nevents,topo,timestamp llhds=[] mu = 1. def getMu1 ( L ): for k,v in L.items(): if abs(k-mu)<1e-9: return v print ( "couldnt find anything" ) return None for llhd in allhds: if self.pid1 in [ 1000001, 1000002, 1000003, 1000004 ]: if llhd[0]<310.: print ( "light squark mass wall, skipping mx %d < 310 GeV" % llhd[0] ) continue if len(llhd)==4: llhds.append ( (llhd[0],llhd[1],getMu1(llhd[2]),llhd[3]) ) else: llhds.append ( (llhd[0],llhd[1],getMu1(llhd[2]),[0.,0.,0.]) ) return llhds,mx,my,nevents,topo,timestamp def pprint ( self, *args ): print ( "[plotLlhds] %s" % " ".join(map(str,args)) ) def debug ( self, *args ): if self.verbose >= self.DEBUG: print ( "[plotLlhds] %s" % " ".join(map(str,args)) ) def setup ( self, pid1, pid2 ): """ setup rundir, picklefile path and hiscore file path """ self.hiscorefile = self.rundir + "/hiscore.hi" if not os.path.exists ( self.hiscorefile ): self.pprint ( "could not find hiscore file %s" % self.hiscorefile ) self.pid1 = pid1 self.pid2 = pid2 if type(self.pid1) in [ tuple, list ]: pid1 = self.pid1[0] self.picklefile = "%s/llhd%d%d.pcl" % ( self.rundir, pid1, self.pid2 ) if not os.path.exists ( self.picklefile ): llhdp = self.picklefile self.picklefile = "%s/mp%d%d.pcl" % ( self.rundir, pid1, self.pid2 ) if not os.path.exists ( self.picklefile ): self.pprint ( "could not find pickle files %s and %s" % \ ( llhdp, self.picklefile ) ) def describe ( self ): """ describe the situation """ print ( "%d masspoints obtained from %s, hiscore stored in %s" % \ ( len ( self.masspoints), self.picklefile, self.hiscorefile ) ) print ( "Data members: plot.masspoints, plot.massdict, plot.timestamp, plot.mx, plot.my" ) print ( " plot.pid1, plot.pid2, plot.topo" ) print ( "Function members: plot.findClosestPoint()" ) def getLClosestTo ( self, L, mx=None, my=None ): """ get the L closest to your point """ if mx == None: mx=self.mx if my == None: my=self.my def distance_ ( k, mx, my ): _x = int(math.floor(k/1000.)) _y = int(math.floor(k % 1000 ) ) ret= (mx - _x)**2 + (my - _y)**2 return ret dmmin, vmin = float("inf"), 23. for k,v in L.items(): dm = distance_ ( k, mx, my ) if dm < dmmin and not np.isnan(v): dmmin = dmmin vmin = v return vmin def getPrettyName ( self, anaid ): """ get pretty name of ana id """ if False: ## set to true and we have the old analysis Ids return anaid if not hasattr ( self, "database" ): from smodels.experiment.databaseObj import Database dbname = "./original.pcl" dbname = "/home/walten/git/smodels-database" dbname = "/scratch-cbe/users/wolfgan.waltenberger/rundir/db31.pcl" self.database = Database ( dbname ) from smodels_utils.helper.prettyDescriptions import prettyTexAnalysisName if ":" in anaid: anaid = anaid[:anaid.find(":")] ers = self.database.getExpResults ( analysisIDs = [ anaid ] ) for er in ers: if hasattr ( er.globalInfo, "prettyName" ): pn = er.globalInfo.prettyName sqrts = er.globalInfo.sqrts.asNumber(TeV) ret = prettyTexAnalysisName ( pn, sqrts, dropEtmiss = True, collaboration = True, anaid = er.globalInfo.id ) # for the 2020 paper to be consistent ret = ret.replace( "+ top tag", "stop" ) ret = ret.replace( "+ 4 (1 b-)jets", "multijet" ) # ret += " -> " + anaid return ret # print ( "found no pretty name", ers[0].globalInfo ) return anaid 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 copyFile ( self, filename ): """ copy filename to smodels.github.io/protomodels/<upload>/ """ dest = os.path.expanduser ( "~/git/smodels.github.io" ) cmd = "cp %s %s/protomodels/%s/" % ( filename, dest, self.upload ) o = subprocess.getoutput ( cmd ) self.pprint ( "%s: %s" % ( cmd, o ) ) def getAnaStats ( self, integrateSRs=True, integrateTopos=True, integrateDataType=True ): """ given the likelihood dictionaries D, get stats of which analysis occurs how often :param integrateTopos: sum over all topologies :param integrateSRs: sum over all signal regions :param integrateDataType: ignore data type """ anas = {} if self.masspoints == None: return None for masspoint in self.masspoints: m1,m2,llhds=masspoint[0],masspoint[1],masspoint[2] if len(masspoint)>3: robs = masspoint[3] for k,v in llhds.items(): tokens = k.split(":") if not integrateTopos and self.topo not in tokens[2]: continue dType = ":em" if tokens[1] in [ "None", None ]: dType = ":ul" name = tokens[0] if not integrateDataType: name = name + dType if not integrateTopos: name = tokens[0]+tokens[1] if not name in anas.keys(): anas[name]=0 anas[name]=anas[name]+1 return anas def listAnalyses( self ): """ :param verbose: verbosity: debug, info, warn, or error """ stats = self.getAnaStats( integrateDataType=False ) print ( "%6d masspoints with %s" % ( len(self.masspoints), self.topo ) ) for k,v in stats.items(): print ( "%6d: %s" % ( v, k ) ) def compress ( self ): """ produce a pcl file with only a fraction of the points. good for testing and development """ backupfile = self.picklefile.replace(".pcl",".bu.pcl") subprocess.getoutput ( "cp %s %s" % ( self.picklefile, backupfile )) newfile = self.picklefile.replace(".pcl",".comp.pcl") mx,my=set(),set() for m in self.masspoints: mx.add ( m[0] ) my.add ( m[1] ) mx=list(mx) my=list(my) with open ( newfile, "wb" ) as f: mps = [] for i,m in enumerate(self.masspoints): if mx.index (m[0] ) % 2 == 0 and \ my.index (m[1] ) % 2 == 0: # if i % 5 == 0: mps.append ( m ) pickle.dump ( mps, f ) pickle.dump ( self.mx, f ) pickle.dump ( self.my, f ) pickle.dump ( self.nevents, f ) pickle.dump ( self.topo, f ) pickle.dump ( self.timestamp, f ) f.close() def findClosestPoint ( self, m1=None, m2=None, nll=False ): """ find the mass point closest to m1, m2. If not specified, return the hiscore point. :param nll: if True, report nlls, else report likelihoods. """ if m1 == None: m1 = self.mx if m2 == None: m2 = self.my dm,point = float("inf"),None def distance ( m ): return (m[0]-m1)**2 + (m[1]-m2)**2 for m in self.masspoints: tmp = distance(m) if tmp < dm: dm = tmp point = m if not nll: return point # asked for NLLs D = {} for k,v in point[2].items(): D[k]=-np.log(v) return ( point[0], point[1], D ) def interact ( self ): import IPython varis = "plot.describe()" print ( "%s[plot] interactive session. Try: %s%s" % \ ( colorama.Fore.GREEN, varis, colorama.Fore.RESET ) ) IPython.embed( using=False )
# In[3]: ## Load the database: databasePath = os.path.join(os.getenv("HOME"), "smodels-database/") db = Database(databasePath) # ## Look up upper limit for an Upper Limit-type result: # In[4]: #Select desired result: resultID = ["CMS-PAS-SUS-13-016"] txname = ["T1tttt"] expResult = db.getExpResults(analysisIDs=resultID, txnames=txname, dataTypes='upperLimit')[0] print 'selected result:', expResult # In[5]: #Define the desired mass vector (must be consistent with the txname/simplified model): masses = [[500 * GeV, 150 * GeV], [500 * GeV, 150 * GeV]] print 'UL for mass\n', masses, ' is: ', expResult.getUpperLimitFor( mass=masses, txname="T1tttt") # ## Look up upper limit for an Efficiency Map-type result: # In[6]: #Select desired result:
#!/usr/bin/env python3 """ just test that the fake signal gets injected in the right part of the UL maps """ import math from smodels.experiment.databaseObj import Database from smodels.tools.physicsUnits import GeV # ./ptools/fetchFromClip.py -R rundir.frozen1 --database db = Database("default.pcl") print("db", db.databaseVersion) er = db.getExpResults(["CMS-SUS-19-006"])[0] ds = er.datasets[0] print(ds.txnameList) txn = ds.txnameList[6] print(txn) def distance(mass): # return math.sqrt ( (mass[0] - 735.)**2 + (mass[1]-162.6)**2 ) return math.sqrt((mass[0] - 1166.)**2 + (mass[1] - 162.6)**2) masses = [] for mLSP in range(100, 240, 50): for msquark in range(850, 1300, 50): masses.append([msquark, mLSP]) # masses.append ( [[msquark*GeV,mLSP*GeV],[msquark*GeV,mLSP*GeV]] ) for mass in masses: mvec = [[mass[0] * GeV, mass[1] * GeV], [mass[0] * GeV, mass[1] * GeV]] oUL = txn.getULFor(mvec, expected=False) eUL = txn.getULFor(mvec, expected=True)
def RunSModelS(self,SLHAFilePath,SummaryFilePath): # Set the path to the database database = Database("/home/oo1m20/softwares/smodels-1.2.2/smodels-database") self.SummaryFilePath = os.path.abspath(SummaryFilePath) #Define your model (list of rEven and rOdd particles) particlesLoader.load( 'smodels.share.models.secumssm' ) #Make sure all the model particles are up-to-date # Path to input file (either a SLHA or LHE file) self.SLHAFilePath = SLHAFilePath slhafile = self.SLHAFilePath #lhefile = 'inputFiles/lhe/gluino_squarks.lhe' # Set main options for decomposition sigmacut = 0.01 * fb mingap = 5. * GeV # Decompose model (use slhaDecomposer for SLHA input or lheDecomposer for LHE input) slhaInput = True if slhaInput: toplist = slhaDecomposer.decompose(slhafile, sigmacut, doCompress=True, doInvisible=True, minmassgap=mingap) else: toplist = lheDecomposer.decompose(lhefile, doCompress=True,doInvisible=True, minmassgap=mingap) # Access basic information from decomposition, using the topology list and topology objects: f= open(self.SummaryFilePath,"a+") print( "\n Decomposition Results: ", file=f ) print( "\t Total number of topologies: %i " %len(toplist), file=f ) nel = sum([len(top.elementList) for top in toplist]) print( "\t Total number of elements = %i " %nel , file=f) #Print information about the m-th topology (if it exists): m = 2 if len(toplist) > m: top = toplist[m] print( "\t\t %i-th topology = " %m,top,"with total cross section =",top.getTotalWeight(), file=f ) #Print information about the n-th element in the m-th topology: n = 0 el = top.elementList[n] print( "\t\t %i-th element from %i-th topology = " %(n,m),el, end="", file=f ) print( "\n\t\t\twith final states =",el.getFinalStates(),"\n\t\t\twith cross section =",el.weight,"\n\t\t\tand masses = ",el.getMasses(), file=f ) # Load the experimental results to be used. # In this case, all results are employed. listOfExpRes = database.getExpResults() # Print basic information about the results loaded. # Count the number of loaded UL and EM experimental results: nUL, nEM = 0, 0 for exp in listOfExpRes: expType = exp.getValuesFor('dataType')[0] if expType == 'upperLimit': nUL += 1 elif expType == 'efficiencyMap': nEM += 1 print( "\n Loaded Database with %i UL results and %i EM results " %(nUL,nEM), file=f ) # Compute the theory predictions for each experimental result and print them: print("\n Theory Predictions and Constraints:", file=f) rmax = 0. bestResult = None for expResult in listOfExpRes: predictions = theoryPredictionsFor(expResult, toplist, combinedResults=False, marginalize=False) if not predictions: continue # Skip if there are no constraints from this result print('\n %s ' %expResult.globalInfo.id, file=f) for theoryPrediction in predictions: dataset = theoryPrediction.dataset datasetID = dataset.dataInfo.dataId mass = theoryPrediction.mass txnames = [str(txname) for txname in theoryPrediction.txnames] PIDs = theoryPrediction.PIDs print( "------------------------", file=f ) print( "Dataset = ", datasetID, file=f ) #Analysis name print( "TxNames = ", txnames, file=f ) print( "Prediction Mass = ",mass, file=f ) #Value for average cluster mass (average mass of the elements in cluster) print( "Prediction PIDs = ",PIDs, file=f ) #Value for average cluster mass (average mass of the elements in cluster) print( "Theory Prediction = ",theoryPrediction.xsection, file=f ) #Signal cross section print( "Condition Violation = ",theoryPrediction.conditions, file=f ) #Condition violation values # Get the corresponding upper limit: print( "UL for theory prediction = ",theoryPrediction.upperLimit, file=f ) # Compute the r-value r = theoryPrediction.getRValue() print( "r = ",r , file=f) #Compute likelihhod and chi^2 for EM-type results: if dataset.dataInfo.dataType == 'efficiencyMap': theoryPrediction.computeStatistics() print( 'Chi2, likelihood=', theoryPrediction.chi2, theoryPrediction.likelihood, file=f ) if r > rmax: rmax = r bestResult = expResult.globalInfo.id # Print the most constraining experimental result print( "\nThe largest r-value (theory/upper limit ratio) is ",rmax, file=f ) if rmax > 1.: print( "(The input model is likely excluded by %s)" %bestResult, file=f ) else: print( "(The input model is not excluded by the simplified model results)", file=f ) f.close()
from smodels.tools.physicsUnits import fb, GeV from smodels.theory.theoryPrediction import theoryPredictionsFor from smodels.experiment.databaseObj import Database # In[3]: #Define the SLHA input file name filename = "%s/inputFiles/slha/gluino_squarks.slha" % installDirectory() # In[4]: #Load the database, do the decomposition and compute theory predictions: #(Look at the theory predictions HowTo to learn how to compute theory predictions) databasepath = os.path.join(os.getenv("HOME"), "smodels-database/") database = Database(databasepath) expResults = database.getExpResults() topList = slhaDecomposer.decompose(filename, sigcut=0.03 * fb, doCompress=True, doInvisible=True, minmassgap=5 * GeV) allThPredictions = [theoryPredictionsFor(exp, topList) for exp in expResults] # In[5]: #Print the value of each theory prediction for each experimental #result and the corresponding upper limit (see the obtain experimental upper limits HowTo to learn how #to compute the upper limits). #Also print the expected upper limit, if available for thPreds in allThPredictions: if not thPreds: continue #skip results with no predictions
## Load the database: dbPath = os.path.join(os.getenv("HOME"), "smodels-database/") database = Database(dbPath) # ## How to select results from one publication (or conference note) # In[6]: #Select only the CMS SUS-12-028 conference note expID = ["CMS-SUS-12-028"] # In[7]: #Loads the selected analyses #(The INFO tells you that superseded analyses are not loaded, see below) results = database.getExpResults(analysisIDs=expID) # In[9]: #Print all the results selected: for exp in results: print exp #Print the txnames constrained by the result in bracket notation: exp = results[0] for tx in exp.getTxNames(): print tx, '=', tx.constraint # In[10]: #Print ALL info fields available: exp = results[0]
def draw( strategy, databasepath, trianglePlot, miscol, diagcol, experiment, S, drawtimestamp, outputfile, nofastlim ): """ :param trianglePlot: if True, then only plot the upper triangle of this symmetrical matrix :param miscol: color to use when likelihood is missing :param diagcol: color to use for diagonal :param experiment: draw only for specific experiment ("CMS", "ATLAS", "all" ) :param S: draw only for specific sqrts ( "8", "13", "all" ) :param drawtimestamp: if true, put a timestamp on plot :param outputfile: file name of output file (matrix.png) :param nofastlim: if True, discard fastlim results """ ROOT.gStyle.SetOptStat(0000) ROOT.gROOT.SetBatch() cols = [ ROOT.kRed+1, ROOT.kWhite, ROOT.kGreen+1, miscol, diagcol ] ROOT.gStyle.SetPalette(len(cols), (ctypes.c_int * len(cols))(*cols) ) ROOT.gStyle.SetNumberContours(len(cols)) ROOT.gStyle.SetPadLeftMargin(.25) sqrtses = [ 8, 13 ] if S not in [ "all" ]: sqrtses = [ int(S) ] colors.on = True setLogLevel ( "debug" ) # dir = "/home/walten/git/smodels-database/" dir = databasepath d=Database( dir, discard_zeroes = True ) print(d) analysisIds = [ "all" ] exps = [ "CMS", "ATLAS" ] if experiment in [ "CMS", "ATLAS" ]: analysisIds = [ experiment+"*" ] exps = [ experiment ] results = d.getExpResults( analysisIDs = analysisIds ) if nofastlim: results = noFastlim ( results ) results = sortOutDupes ( results ) if S in [ "8", "13" ]: results = sortBySqrts ( results, int(S) ) #results.sort() nres = len ( results ) ROOT.c1=ROOT.TCanvas("c1","c1",1770,1540) ROOT.c1.SetLeftMargin(0.18) ROOT.c1.SetBottomMargin(0.21) ROOT.c1.SetTopMargin(0.06) ROOT.c1.SetRightMargin(0.01) if nres > 60: ROOT.c1.SetLeftMargin(0.12) ## seemed to work for 96 results ROOT.c1.SetBottomMargin(0.15) ROOT.c1.SetTopMargin(0.09) ROOT.c1.SetRightMargin(0.015) h=ROOT.TH2F ( "Correlations", "", nres, 0., nres, nres, 0., nres ) xaxis = h.GetXaxis() yaxis = h.GetYaxis() sze = 0.13 / math.sqrt ( nres ) xaxis.SetLabelSize( 1.3*sze ) yaxis.SetLabelSize( 1.3*sze ) bins= { "CMS": { 8: [999,0], 13:[999,0] }, "ATLAS": { 8: [999,0], 13: [999,0] } } n = len(results ) for x,e in enumerate(results): label = e.globalInfo.id hasLikelihood = hasLLHD ( e ) ana = analysisCombiner.getExperimentName ( e.globalInfo ) #if not hasLikelihood: # print ( "no likelihood: %s" % label ) sqrts = int(e.globalInfo.sqrts.asNumber(TeV)) color = ROOT.kCyan+2 ymax=0 if ana == "ATLAS": color = ROOT.kBlue+1 if sqrts > 10.: color += 2 if x < bins[ana][sqrts][0]: bins[ana][sqrts][0]=x if x > bins[ana][sqrts][1]: bins[ana][sqrts][1]=x ymax=x color = ROOT.kGray+2 if len(exps)==1 and len(sqrtses)==1: label = label.replace("CMS-","").replace("ATLAS-","").replace("-agg","") label = "#color[%d]{%s}" % (color, label ) xaxis.SetBinLabel(n-x, label ) yaxis.SetBinLabel(x+1, label ) for y,f in enumerate(results): if trianglePlot and y>x: continue isUn = analysisCombiner.canCombine ( e.globalInfo, f.globalInfo, strategy ) # isUn = e.isUncorrelatedWith ( f ) if isUn: h.SetBinContent ( n-x, y+1, 1. ) else: h.SetBinContent ( n-x, y+1, -1. ) if not hasLikelihood or not hasLLHD ( f ): ## has no llhd? cannot be combined h.SetBinContent ( n-x, y+1, 2. ) if y==x: h.SetBinContent ( n-x, y+1, 3. ) h.Draw("col") ROOT.bins, ROOT.xbins, ROOT.lines = {}, {}, [] if len(exps)==1 and len(sqrtses)==1: ROOT.t1 = ROOT.TLatex() ROOT.t1.SetNDC() ROOT.t1.DrawLatex ( .45, .95, "%s, %d TeV" % ( exps[0], sqrtses[0] ) ) for ana in exps: for sqrts in sqrtses: name= "%s%d" % ( ana, sqrts ) ROOT.bins[name] = ROOT.TLatex() ROOT.bins[name].SetTextColorAlpha(ROOT.kBlack,.7) ROOT.bins[name].SetTextSize(.025) ROOT.bins[name].SetTextAngle(90.) ROOT.xbins[name] = ROOT.TLatex() ROOT.xbins[name].SetTextColorAlpha(ROOT.kBlack,.7) ROOT.xbins[name].SetTextSize(.025) xcoord = .5 * ( bins[ana][sqrts][0] + bins[ana][sqrts][1] ) ycoord = n- .5 * ( bins[ana][sqrts][0] + bins[ana][sqrts][1] ) -3 if len(sqrtses)>1 or len(exps)>1: ROOT.bins[name].DrawLatex(-4,xcoord-3,"#splitline{%s}{%d TeV}" % ( ana, sqrts ) ) ROOT.xbins[name].DrawLatex(ycoord,-5,"#splitline{%s}{%d TeV}" % ( ana, sqrts ) ) yt = bins[ana][sqrts][1] +1 extrudes = 3 # how far does the line extrude into tick labels? xmax = n if trianglePlot: xmax = n-yt line = ROOT.TLine ( -extrudes, yt, xmax, yt ) line.SetLineWidth(2) line.Draw() ymax = n if trianglePlot: ymax = yt xline = ROOT.TLine ( n-yt, ymax, n-yt, -extrudes ) xline.SetLineWidth(2) xline.Draw() ROOT.lines.append ( line ) ROOT.lines.append ( xline ) line = ROOT.TLine ( -extrudes, 0, xmax, 0 ) line.SetLineWidth(2) line.Draw() xline = ROOT.TLine ( n, ymax, n, -extrudes ) xline.SetLineWidth(2) xline.Draw() ROOT.lines.append ( line ) ROOT.lines.append ( xline ) h.LabelsOption("v","X") if trianglePlot: for i in range(n+1): wline = ROOT.TLine ( n, i, n-i, i ) wline.SetLineColor ( ROOT.kWhite ) wline.Draw () ROOT.lines.append ( wline ) vline = ROOT.TLine ( i, n-i, i, n ) vline.SetLineColor ( ROOT.kWhite ) vline.Draw () ROOT.lines.append ( vline ) ROOT.title = ROOT.TLatex() ROOT.title.SetNDC() ROOT.title.SetTextSize(.025 ) ROOT.title.DrawLatex(.28,.89, "#font[132]{Correlations between analyses, combination strategy: ,,%s''}" % strategy ) ROOT.boxes = [] if trianglePlot: for i,b in enumerate ( [ "pair is uncorrelated", "pair is correlated", "likelihood is missing" ] ): bx = 51 by = 68 - 3*i box = ROOT.TBox(bx,by,bx+1,by+1) c = cols[i] if i > 0: c = cols[i+1] box.SetFillColor ( c ) box.Draw() ROOT.boxes.append ( box ) l = ROOT.TLatex() l.SetTextSize(.022) #if i == 2: # c = 16 l.SetTextColor ( c ) b="#font[132]{%s}" % b ## add font l.DrawLatex ( bx+2, by, b ) ROOT.boxes.append ( l ) l = ROOT.TLatex() l.SetNDC() l.SetTextColor(ROOT.kGray+1) l.SetTextSize(.015) if drawtimestamp: l.DrawLatex ( .01, .01, "plot produced %s from database v%s" % \ ( time.strftime("%h %d %Y" ), d.databaseVersion ) ) ROOT.gPad.SetGrid() if "@M" in outputfile: modifiers = "" if len(exps)==1: modifiers += exps[0] if len(sqrtses)==1: modifiers += str(sqrtses[0]) outputfile = outputfile.replace("@M",modifiers) print ( "Plotting to %s" % outputfile ) ROOT.c1.Print( outputfile )