Source code for contur.run.run_mkthy


# functions build theory reference yodas from various raw inputs.

import contur
import re
import sys
import os
import rivet
import yoda
from contur.data.sm_theory_builders import *
import contur.config.config as cfg
import contur.data.static_db as cdb
import contur.util.utils as cutil
from contur.run.arg_utils import setup_common
from contur.factories.yoda_factories import mkConturFriendlyScatter


[docs] def make_sm_yoda(analysis): ''' Make the SM yoda file for analysis This is a pretty clunky and bespoke set of scripts because it has to handle data from a very varied set of sources. From these sources it produces standard SM prediction files to be stored in data/Theory If source == "REF", will look for additonal y axes on the REF plots (labelled y02 by default, others from axis parameter) and replace them to convert into y01 /THY versions. Filters out analysis objects which are not assigned to an analysis pool. if source == "RAW" will look in the TheoryRaw areas for /THY/ yodas and just filter them. if source == "HEPDATA" will look in the TheoryRaw area for a (possibly modified) HEPDATA download where the y-axis name should be replace y-axis of the REF histogram name if source == "HEPDATA_APPEND" will look in the TheoryRaw area for a (possibly modified) HEPDATA download where the y-axis name should be appended to the REF histogram name if source == "SPECIAL" invoke a special routine for this analysis (usually reading from text files supplied by theorists). the above will only be applied to histograms with a regexp match to the pattern. ''' ao_out = [] a_name = analysis.shortname if analysis.sm() is None: return output_aos = {} # counter to make sure we only take the first prediction got_pred = {} for prediction in analysis.sm(): # only take the first prediction with this ID if not prediction.id in got_pred.keys(): got_pred[prediction.id] = [] # only read each prediction file once if prediction.file_name not in output_aos: output_aos[prediction.file_name] = [] if prediction.origin == "RAW": cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) f = os.path.join(os.getenv("CONTUR_ROOT"),"data","TheoryRaw",a_name,a_name) if prediction.axis is not None: f = f+"-Theory"+prediction.axis+".yoda" else: f = f+"-Theory.yoda" if os.path.isfile(f): cfg.contur_log.debug("Reading from {}".format(f)) aos = yoda.read(f) for path, ao in aos.items(): if path in got_pred[prediction.id]: continue if rivet.isTheoryPath(path) and analysis.name in path: pool = cdb.get_pool(path=path) if pool is not None: ao = mkConturFriendlyScatter(ao,mkthy=True) ao.setTitle(prediction.short_description) output_aos[prediction.file_name].append(ao) else: cfg.contur_log.debug("No pool for {}".format(path)) else: cfg.contur_log.critical("File {} does not exist.".format(f)) elif prediction.origin == "REF": # from the installed ref data cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) f = contur.util.utils.find_ref_file(analysis) aos = yoda.read(f) for short_path, ao in aos.items(): opt_path = "/"+analysis.name+"/"+ao.name() if opt_path in got_pred[prediction.id]: continue pool = cdb.get_pool(path=opt_path) if pool is not None: # print(prediction.pattern, opt_path) if re.search(prediction.pattern, opt_path) and cdb.validHisto(opt_path,filter=False): cfg.contur_log.debug("Found a prediction for {}. Axis is {}.".format(opt_path,prediction.axis)) # get the appropriate theory axis for this plot if re.search("y[0-9]{2}",prediction.axis): # if it's of the form yNN, remove the old one before adding the new one thypath = short_path[:-len(prediction.axis)]+prediction.axis else: # otherwise just append it. thypath = short_path+prediction.axis try: thy_ao = aos[thypath] cfg.contur_log.debug("FOUND! {}".format(thypath)) except: cfg.contur_log.debug("not found {}".format(thypath)) continue got_pred[prediction.id].append(opt_path) thy_ao = mkConturFriendlyScatter(thy_ao,mkthy=True) thy_ao.setPath("/THY"+opt_path) thy_ao.setTitle(prediction.short_description) output_aos[prediction.file_name].append(thy_ao) elif prediction.origin.startswith("HEPDATA"): # from specially downloaded HEPData cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) f = os.path.join(os.getenv("CONTUR_ROOT"),"data","TheoryRaw",a_name,a_name) f = f+".yoda.gz" aos = yoda.read(f) cfg.contur_log.debug("Reading from {}".format(f)) for path, ao in aos.items(): if path in got_pred[prediction.id]: continue pool = cdb.get_pool(path=path) cfg.contur_log.debug("Pool is {} for {}".format(pool.id,path)) if pool is not None: if re.search(prediction.pattern, path) and cdb.validHisto(path,filter=False): cfg.contur_log.debug("Getting a prediction for {}. Axis is {}.".format(path,prediction.axis)) if prediction.origin.endswith("APPEND"): thypath = path+prediction.axis else: thypath = path[:-len(prediction.axis)]+prediction.axis try: thy_ao = aos[thypath] cfg.contur_log.debug("Found a prediction for {} at {}.".format(path,thypath)) except: cfg.contur_log.debug("not found") continue thy_ao = mkConturFriendlyScatter(thy_ao,mkthy=True) thy_ao.setPath("/THY"+path[4:]) thy_ao.setTitle(prediction.short_description) output_aos[prediction.file_name].append(thy_ao) elif prediction.origin == "SPECIAL": histo_lists= {} # Z + high transverse momentum jets at ATLAS histo_lists['ATLAS_2022_I2077570'] = ['d01-x01-y01','d02-x01-y01','d03-x01-y01','d04-x01-y01','d05-x01-y01','d06-x01-y01'] histo_lists['CMS_2021_I1866118'] = ['d01-x01-y01','d02-x01-y01','d03-x01-y01','d04-x01-y01','d05-x01-y01'] histo_lists['CMS_2019_I1753680:LMODE=EMU'] = ['d26-x01-y01','d27-x01-y01','d28-x01-y01','d26-x01-y02','d27-x01-y02','d28-x01-y02'] histo_lists['CMS_2020_I1794169'] = ['d09-x01-y01','d11-x01-y01','d13-x01-y01','d15-x01-y01'] # Measurement of four-jet differential cross sections in √s = 8 TeV proton–proton collisions using the ATLAS detector histo_lists['ATLAS_2015_I1394679'] = ['d01-x01-y01','d02-x01-y01','d03-x01-y01','d04-x01-y01','d05-x01-y01','d06-x01-y01', 'd07-x01-y01','d08-x01-y01','d09-x01-y01','d10-x01-y01','d11-x01-y01','d12-x01-y01', 'd13-x01-y01','d14-x01-y01','d15-x01-y01','d16-x01-y01','d17-x01-y01','d18-x01-y01', 'd19-x01-y01','d20-x01-y01','d21-x01-y01','d22-x01-y01','d23-x01-y01','d24-x01-y01', 'd25-x01-y01','d26-x01-y01'] # Measurement of the Zγ → ννγ¯ production cross section in pp collisions at √s = 13 TeV NB d06 not used, not enough bins. histo_lists['ATLAS_2018_I1698006:LVETO=ON'] = ['d02-x01-y01','d03-x01-y01','d04-x01-y01','d05-x01-y01'] # WZ and same-sign WW boson pairs in association with two jets in proton-proton collisions at √s= 13 TeV histo_lists['ATLAS_2018_I1635273:LMODE=EL'] = ['d01-x01-y01','d06-x01-y01','d11-x01-y01','d16-x01-y01','d21-x01-y01', 'd26-x01-y01','d28-x01-y01','d30-x01-y01','d32-x01-y01'] histo_lists['ATLAS_2016_I1448301:LMODE=LL'] = ['d05-x01-y01','d06-x01-y01','d09-x01-y01','d10-x01-y01'] # Z + high transverse momentum jets at ATLAS histo_lists['ATLAS_2019_I1744201'] = ['d02-x01-y01','d03-x01-y01','d04-x01-y01','d05-x01-y01','d06-x01-y01','d07-x01-y01'] # WW production at 13 TeV histo_lists['ATLAS_2019_I1734263'] = ['d04-x01-y01','d07-x01-y01','d10-x01-y01','d13-x01-y01','d16-x01-y01','d19-x01-y01'] # Triphoton 8 TeV histo_lists['ATLAS_2017_I1644367'] = ['d01-x01-y01','d01-x01-y02','d02-x01-y01','d02-x01-y02','d03-x01-y01','d03-x01-y02', 'd04-x01-y01','d04-x01-y02','d05-x01-y01','d05-x01-y02','d06-x01-y01','d06-x01-y02', 'd07-x01-y01','d07-x01-y02','d08-x01-y01','d08-x01-y02','d09-x01-y01','d09-x01-y02', 'd10-x01-y01','d10-x01-y02','d11-x01-y01','d11-x01-y02','d12-x01-y01','d12-x01-y02', 'd13-x01-y01','d13-x01-y02'] # Z & W bosons produced in proton-proton collisions at 8 TeV histo_lists['CMS_2016_I1471281:VMODE=W'] = ['d01-x01-y01','d02-x01-y01'] histo_lists['CMS_2016_I1471281:VMODE=Z'] = ['d03-x01-y01'] # ttbb produced in proton-proton collisions with additional heavy-flavour jets at 13 TeV histo_lists['ATLAS_2018_I1705857'] = ['d01-x02-y01','d04-x01-y01','d06-x01-y01','d08-x01-y01','d10-x01-y01','d12-x01-y01', 'd14-x01-y01','d16-x01-y01','d18-x01-y01','d20-x01-y01','d22-x01-y01','d24-x01-y01', 'd26-x01-y01','d28-x01-y01','d30-x01-y01','d32-x01-y01','d34-x01-y01','d36-x01-y01', 'd38-x01-y01','d40-x01-y01','d42-x01-y01','d44-x01-y01','d46-x01-y01','d48-x01-y01', 'd50-x01-y01'] # H to diphoton histo_lists['ATLAS_2022_I2023464'] = ['d02-x01-y01','d03-x01-y01','d04-x01-y01','d05-x01-y01','d06-x01-y01','d07-x01-y01', 'd08-x01-y01','d09-x01-y01','d10-x01-y01','d21-x01-y01','d23-x01-y01','d25-x01-y01', 'd27-x01-y01','d29-x01-y01','d31-x01-y01','d33-x01-y01','d35-x01-y01','d37-x01-y01', 'd39-x01-y01','d41-x01-y01','d43-x01-y01','d45-x01-y01','d47-x01-y01','d49-x01-y01', 'd51-x01-y01','d53-x01-y01', 'd57-x01-y01', 'd59-x01-y01'] histo_lists['ATLAS_2018_I1707015:LMODE=SINGLE'] = ['d03-x01-y01','d04-x01-y01','d05-x01-y01'] histo_lists['ATLAS_2018_I1707015:LMODE=DILEPTON']=['d06-x01-y01','d07-x01-y01','d08-x01-y01','d09-x01-y01','d10-x01-y01'] # ttbar to hadrons histo_lists['ATLAS_2022_I2077575'] = ['d02-x01-y01','d75-x01-y01','d76-x01-y01','d77-x01-y01','d78-x01-y01','d79-x01-y01', 'd80-x01-y01','d81-x01-y01','d82-x01-y01','d83-x01-y01','d84-x01-y01','d85-x01-y01', 'd86-x01-y01','d87-x01-y01','d88-x01-y01','d89-x01-y01','d90-x01-y01','d91-x01-y01', 'd92-x01-y01','d93-x01-y01','d94-x01-y01','d95-x01-y01','d96-x01-y01','d97-x01-y01', 'd98-x01-y01','d99-x01-y01','d100-x01-y01','d101-x01-y01','d102-x01-y01','d103-x01-y01', 'd104-x01-y01','d105-x01-y01','d106-x01-y01','d107-x01-y01','d108-x01-y01','d109-x01-y01', 'd110-x01-y01','d111-x01-y01','d112-x01-y01','d113-x01-y01','d114-x01-y01','d115-x01-y01', 'd116-x01-y01','d117-x01-y01','d118-x01-y01','d119-x01-y01','d120-x01-y01','d121-x01-y01', 'd122-x01-y01','d123-x01-y01','d124-x01-y01','d125-x01-y01','d126-x01-y01','d127-x01-y01', 'd128-x01-y01','d129-x01-y01','d130-x01-y01','d131-x01-y01','d132-x01-y01','d133-x01-y01', 'd134-x01-y01','d135-x01-y01','d136-x01-y01','d137-x01-y01','d138-x01-y01','d139-x01-y01', 'd140-x01-y01','d141-x01-y01','d142-x01-y01','d143-x01-y01','d144-x01-y01','d145-x01-y01', 'd146-x01-y01'] histo_lists['ATLAS_2020_I1801434'] = ['d04-x01-y01','d08-x01-y01','d12-x01-y01','d16-x01-y01','d20-x01-y01','d24-x01-y01','d28-x01-y01', 'd32-x01-y01','d36-x01-y01','d40-x01-y01','d44-x01-y01','d48-x01-y01','d52-x01-y01','d56-x01-y01', 'd60-x01-y01','d64-x01-y01','d68-x01-y01','d72-x01-y01','d76-x01-y01','d80-x01-y01','d84-x01-y01', 'd88-x01-y01','d92-x01-y01','d96-x01-y01','d100-x01-y01','d104-x01-y01','d108-x01-y01','d112-x01-y01', 'd116-x01-y01','d120-x01-y01','d124-x01-y01','d128-x01-y01','d132-x01-y01','d136-x01-y01'] # mass dependence of pT of Drell-Yan lepton pairs histo_lists['CMS_2022_I2079374'] = ['d01-x01-y01','d03-x01-y01','d05-x01-y01','d07-x01-y01','d09-x01-y01','d11-x01-y01', 'd13-x01-y01','d15-x01-y01','d17-x01-y01','d19-x01-y01','d21-x01-y01','d23-x01-y01', 'd25-x01-y01','d27-x01-y01'] # dileptonic ttbar histo_lists['ATLAS_2023_I2648096'] = ['d06-x01-y01','d09-x01-y01','d12-x01-y01','d15-x01-y01','d18-x01-y01','d21-x01-y01', 'd24-x01-y01','d27-x01-y01'] # ttbar to lepton, jets and MET histo_lists['CMS_2021_I1901295'] = ['d159-x01-y01','d163-x01-y01','d167-x01-y01','d171-x01-y01','d175-x01-y01','d179-x01-y01', 'd183-x01-y01','d187-x01-y01','d191-x01-y01','d195-x01-y01','d199-x01-y01','d203-x01-y01', 'd207-x01-y01','d211-x01-y01','d317-x01-y01','d321-x01-y01','d325-x01-y01','d329-x01-y01'] if analysis.name in histo_lists.keys(): cfg.contur_log.info("Making SM theory for {} prediction {}".format(analysis.name,prediction.id)) read_from_csv_files(analysis,histo_lists[analysis.name],prediction) if analysis.name == "ATLAS_2016_I1457605": cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2016_I1457605(prediction) if analysis.name == "ATLAS_2017_I1645627": cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2017_I1645627(prediction) if analysis.name == "ATLAS_2012_I1199269": cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2012_I1199269(prediction) if analysis.name == "ATLAS_2017_I1591327": cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2017_I1591327(prediction) if analysis.name == "ATLAS_2016_I1467454:LMODE=MU": cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) # this actually does both EL and MU do_ATLAS_2016_I1467454(prediction) if analysis.name == "CMS_2017_I1467451": cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) do_CMS_2017_I1467451(prediction) if analysis.name == "ATLAS_2015_I1408516:LMODE=MU": cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) # this actually does both EL and MU do_ATLAS_2015_I1408516(prediction) if analysis.name == "ATLAS_2019_I1725190": cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2019_I1725190(prediction) if analysis.name == "ATLAS_2021_I1852328": cfg.contur_log.info("Making SM theory for {}, prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2021_I1852328(prediction) if analysis.name == "ATLAS_2019_I1764342": cfg.contur_log.info("Making SM theory for {} prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2019_I1764342(prediction) if analysis.name == 'ATLAS_2016_I1494075:LMODE=4L': cfg.contur_log.info("Making SM theory for {} prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2016_I1494075(prediction,1) if analysis.name == 'ATLAS_2016_I1494075:LMODE=2L2NU': cfg.contur_log.info("Making SM theory for {} prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2016_I1494075(prediction,2) if analysis.name == 'ATLAS_2019_I1718132:LMODE=ELEL': cfg.contur_log.info("Making SM theory for {} prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2019_I1718132(prediction,1) if analysis.name == 'ATLAS_2019_I1718132:LMODE=MUMU': cfg.contur_log.info("Making SM theory for {} prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2019_I1718132(prediction,2) if analysis.name == 'ATLAS_2019_I1718132:LMODE=ELMU': cfg.contur_log.info("Making SM theory for {} prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2019_I1718132(prediction,3) if analysis.name == "ATLAS_2022_I2037744": cfg.contur_log.info("Making SM theory for {} prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2022_I2037744(prediction) if "ATLAS_2024_I2768921" in analysis.name: # makes both SINGLE and DILEPTON files cfg.contur_log.info("Making SM theory for {} prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2024_I2768921(prediction,analysis) if "ATLAS_2024_I2765017" in analysis.name: # special hack for rmiss to make sure the ratio is exactly the ratio of the xsecs cfg.contur_log.info("Making SM RMISS theory for {} prediction {}".format(analysis.name,prediction.id)) do_ATLAS_2024_I2765017(prediction,analysis,output_aos,got_pred) else: cfg.contur_log.critical("Unknown source {}".format(source)) sys.exit(1) for fname, ao_out in output_aos.items(): if len(ao_out)>0: yoda.write(ao_out, fname) return
[docs] def main(args): """ Main programme to run over the known analysis and build SM theory yodas from the TheoryRaw or REF areas. """ # cfg.setup_logger(filename="contur_mkthy.log") setup_common(args) print("Writing log to {}".format(cfg.logfile_name)) if args['ANAUNPATTERNS']: cfg.vetoAnalyses = args['ANAUNPATTERNS'] if args['ANAPATTERNS']: cfg.onlyAnalyses = args['ANAPATTERNS'] cfg.input_dir = args["INPUTDIR"] cfg.contur_log.info("Looking for raw theory files in {}".format(cfg.input_dir)) # do_all = (args['ANALYSIS'] == "all") # ------------------------------------- for analysis in cdb.get_analyses(filter=False): if cutil.analysis_select(analysis.name): make_sm_yoda(analysis)