def initialize(self): """Load the necessary settings from the config file.""" self.p_objects = self.p_settings.get(self.p_cfg_name,'objects') self.p_scalefactor = config.str2bool(self.p_settings.get(self.p_cfg_name,'eventweights')) self.p_lepton = self.p_settings.get(self.p_cfg_name,'lepton') self.p_extra_save = self.p_settings.get(self.p_cfg_name,'extra_saveAs') self.p_plot_type = self.p_settings.get(self.p_cfg_name,'plot_framework') # python/root self.p_plot1d = self.p_settings.get(self.p_cfg_name,'1dplot') # for saving data self.p_plot2d = self.p_settings.get(self.p_cfg_name,'2dplot') # for saving data self.p_cuts = self.p_settings.get(self.p_cfg_name,'cutsfile') self.p_cuts = config.processCuts(self.p_cuts) self.p_variables = self.p_settings.get(self.p_cfg_name,'variables').split(',') self.p_eff_x_vars = self.p_settings.get(self.p_cfg_name,'eff_x').split(',') self.p_treename = self.p_settings.get(self.p_cfg_name,'treename') self.eff_conditions = self.p_settings.get(self.p_cfg_name,'eff_y').split(',') self.p_nevents = int(self.p_settings.get(self.p_cfg_name,'NEvents')) p_files = self.p_settings.get(self.p_cfg_name,'files') self.p_files = open(p_files,'r').readlines() self.p_read_data = config.str2bool(self.p_settings.get(self.p_cfg_name,'read_data')) p_custom_vars = self.p_settings.get(self.p_cfg_name,'custom_variables') if p_custom_vars == 'None': self.p_custom_vars = '' else: self.p_custom_vars = p_custom_vars ## -- Easy variables to initialize -- ## self.p_btag_wkpt = info.btagging_WP(self.p_settings.get(self.p_cfg_name,'btag_wkpt')) self.outputfilenames = ['data/'+fname.split('/')[-1].split('.')[0]+'_'+self.p_lepton+'_'+self.p_extra_save for fname in self.p_files] return self.p_settings
def main(self,parser): """ Main function in the systematics class -- does all the directing for creating histograms and json files. """ ## -- Configuration -- ## p_selection = parser.get('systematics','selection') # ex. pyMiniSL/SelectionBase.py p_make_ntuple = str2bool(parser.get('systematics','make_ntuple')) # ex. True p_make_jsons = str2bool(parser.get('systematics','make_jsons')) # ex. True p_make_hists = str2bool(parser.get('systematics','make_hists')) # ex. True ## ------------------- ## selection = p_selection.split('/')[-1].split('.')[0] # pyMiniSL/SelectionBase.py -> SelectionBase if p_make_ntuple and p_make_jsons and p_make_hists: print print " You have chosen to produce a new ntuples," print " json, and histogram outputs." print " This will take a long time to do." print " If this is not what you meant to do, please" print " exit the program and modify PyMiniAna.cfg." print " Will continue with the program." print if p_make_ntuple: ## Using the same miniSL code to make ntuples for the systematics ## This ensures that the systematics get the same treatment as the nominal from miniSL import MiniSL MakeMiniNtuple = MiniSL() logging.info(" -- Make new ntuples ") print " -- Make new ntuples for a given selection" if selection == 'pre2preSelection': nplist = nuisparams.npdict() for np in nplist: MakeMiniNtuple.execute(parser,treename=np) else: MakeMiniNtuple.execute(parser,treename='systs') if p_make_jsons or p_make_hists: logging.info(" -- Make histograms and json files ") print " -- Make histograms for TXFITTER && json files for Data/Pred. plots" from pySystematics.tree2hist import Tree2Hist MakeHist = Tree2Hist(parser) logging.critical(" Finished systematics.py class Systematics") return
def initialize(self): """initialize some variables using the settings file""" self.p_lepton = self.m_cfg_parser.get(self.p_cfg_name,'lepton') # ex. muel self.p_logplot = str2bool(self.m_cfg_parser.get(self.p_cfg_name,'logplot')) # ex. False self.p_systematics = str2bool(self.m_cfg_parser.get(self.p_cfg_name,'systematics')) # ex. True self.p_ana_status = self.m_cfg_parser.get(self.p_cfg_name,'ana_status') # ex. "Internal" self.p_extra_save = self.m_cfg_parser.get(self.p_cfg_name,'extra_saveAs') self.p_underflow = str2bool(self.m_cfg_parser.get(self.p_cfg_name,'underflow')) # ex. True self.p_overflow = str2bool(self.m_cfg_parser.get(self.p_cfg_name,'overflow')) # ex. True self.p_scalefactor = str2bool(self.m_cfg_parser.get(self.p_cfg_name,'eventweights')) self.p_plot1d_type = self.m_cfg_parser.get(self.p_cfg_name,'1dplot') self.p_plot2d_type = self.m_cfg_parser.get(self.p_cfg_name,'2dplot') self.p_2dvariables = self.m_cfg_parser.get('plot_variables','2dplots') # variables in 2-D plot self.p_1dvariables = self.m_cfg_parser.get('plot_variables','1dplots') # variables in 1-D plot self.eff_conditions = self.m_cfg_parser.get(self.p_cfg_name,'eff_y').split(',') p_files = self.m_cfg_parser.get(self.p_cfg_name,'files') p_files = open(p_files,'r').readlines() ## ------------------- ## if self.p_plot1d_type == 'efficiency' and self.p_1dvariables: self.file_type = 'root' else: self.file_type = 'json' self.inputfilenames = ['data/'+fname.split('/')[-1].split('.')[0]+'_'+self.p_lepton+'_'+self.p_extra_save+'.'+self.file_type for fname in p_files] if self.p_scalefactor: if 'pb' in self.lumi['unit']: lumi = "{0:.1f}".format(self.lumi['lumi']/1000.) unit = 'fb' elif 'fb' in self.lumi['unit']: lumi = "{0:.1f}".format(self.lumi['lumi']) unit = 'fb' else: lumi = "{0}".format(self.lumi['lumi']) unit = self.lumi['unit'].strip('i') self.plot_energy_lumi = self.lumi_label # plot the luminosity self.lumi = {'lumi':lumi,'unit':unit} # reset for use later else: self.plot_energy_lumi = self.PMA_energy_label # plot only sqrt(s) ## - 1D plotting method (use function-pointer syntax to avoid if/else statements) self.p_plot1d = [self.PMA_errorbar,self.PMA_hist_1d][(self.p_plot1d_type.startswith('hist'))] ## - 2D plotting method (use function-pointer syntax to avoid if/else statements) self.p_plot2d = [self.PMA_scatter, self.PMA_hist_2d][(self.p_plot2d_type=='hist')] return
def __init__(self,cfg_parser): """ Initialize the parameters from the config file. @param cfg_parser Object that parsed the configuration file """ logging.getLogger('share/systematics.log') loggingLEVEL = logging.getLogger().getEffectiveLevel() # DEBUG, INFO, ERROR, etc. logging.info("") logging.critical(" -- In tree2hist.py") logging.info(" ------------ ") logging.info(" Initializing the config file.") self.GeV = 1000. ## -- Configuration -- ## self.p_varList = cfg_parser.get('systematics','vars') # ex. share/varNames.txt self.p_rootfiles = cfg_parser.get('systematics','inputfile') # ex. share/systematics_ntuples.txt self.p_selection = cfg_parser.get('systematics','selection') # ex. pre2pre self.p_outputname = cfg_parser.get('systematics','outputname') # ex. pre self.p_makejsons = config.str2bool(cfg_parser.get('systematics','make_jsons')) # ex. True self.p_makehists = config.str2bool(cfg_parser.get('systematics','make_hists')) # ex. True self.p_lepton = cfg_parser.get('systematics','lepton') # ex. muel self.p_nEvents = cfg_parser.get('systematics','nevents') # ex. -1 ## ------------------- ## self.p_varList = open(self.p_varList,'r').readlines() # update the variable self.p_varList = [v.rstrip('\n') for v in self.p_varList] if not self.p_makejsons and not self.p_makehists: print print " You didn't specify outputs (either json, hist, or both)" print " for the systematics output." print sys.exit(1) self.json_path = info.getJsonPath()+self.p_lepton self.hist_path = self.json_path.split('json')[0]+'hists/'+self.p_lepton ## Run the program self.main() return
def getConfig(cfg_parser): """ Determine the configuration option from the config file. Only keeping track of 'miniSL', 'datamc', and 'systematics' by hand -- need to manually insert the configuration options. """ config_options = {'miniSL':False,\ 'datamc':False,\ 'systematics':False} for key in config_options.keys(): config_options[key] = config.str2bool(cfg_parser.get('configuration',key.lower())) # Now safe-guard against incorrect things in the config file # Note: the 'str2bool' function in config.py returns '-1' if # the value given is not related to True or False config_booleans = [] true_configs = [] for k in config_options.keys(): config_booleans.append(config_options[k]) # all options if config_options[k]: true_configs.append(k) # only true options ## Make sure the configurations make sense if any(config_booleans) == -1: print print " Please choose one of the configurations: " print " >> {0}".format(config_options.keys()) print " under the [configuration] section in 'share/PyMiniAna.cfg'." print " with either 'True' or 'False'." print usage() sys.exit(1) ## Make sure at least one of them is chosen if not any(config_booleans): print print " Please choose one of the configurations: " print " >> {0}".format(config_options.keys()) print " under the [configuration] section in 'share/PyMiniAna.cfg'." print usage() sys.exit(1) ## Make sure only one of them is chosen if len(true_configs)>1: print print " Please choose only one of the configurations: " print " >> {0}".format(config_options.keys()) print " under the [configuration] section in 'share/PyMiniAna.cfg'." print usage() sys.exit(1) return true_configs[0]
def initialize(self): """Initialize the class by setting up parameters from the config file""" ## -- Configuration -- ## self.p_lepton = self.m_cfg_parser.get('datamc','lepton') # ex. muel self.p_plot_signal = self.m_cfg_parser.get('datamc','plot_signal') # ex. -1; if not all, plot only the one we are sensitive to? self.p_signal_mag = float(self.m_cfg_parser.get('datamc','signal_mag')) # ex. 10 (increase signal by factor of 10 on plot) self.p_stack_signal = str2bool(self.m_cfg_parser.get('datamc','stack_signal')) # ex. True self.p_blind = str2bool(self.m_cfg_parser.get('datamc','blind')) # ex. True self.p_logplot = str2bool(self.m_cfg_parser.get('datamc','logplot')) # ex. False self.p_systematics = str2bool(self.m_cfg_parser.get('datamc','systematics')) # ex. True self.p_jsonfilename = self.m_cfg_parser.get('datamc','jsonfilename') # ex. 'elLHMedium_pre_1tagin' self.p_ana_status = self.m_cfg_parser.get('datamc','ana_status') # ex. "Internal", "Preliminary", or "" (final) self.p_merged_hists = str2bool(self.m_cfg_parser.get('datamc','merged_hists')) # ex. True self.p_extra_saveAs = self.m_cfg_parser.get('datamc','extra_saveAs') # ex. "1btag" self.p_new_lumi = self.m_cfg_parser.get('datamc','new_lumi') # ex. 1.307 ifb self.p_underflow = str2bool(self.m_cfg_parser.get('datamc','underflow')) # ex. True self.p_overflow = str2bool(self.m_cfg_parser.get('datamc','overflow')) # ex. True self.p_format = self.m_cfg_parser.get('datamc','format') # ex. pdf ## ------------------- ## ## ## ## ---- Set up some things that are universal to all plots ---- ## ## ## ## -- Setting up the output file self.pathSave = info.getFigurePath()+"{0}/".format(self.p_lepton) if not os.path.isdir(self.pathSave): os.makedirs(self.pathSave) if self.p_extra_saveAs: # want something else in the saved filename self.p_extra_saveAs = '_'+self.p_extra_saveAs self.p_hatch_args = {'hatch':'',\ 'color':'none',\ 'edgecolor':'k',\ 'linewidth':0} if self.p_format=='png': self.p_hatch_args['hatch'] = '/' elif self.p_format=='eps': self.p_hatch_args['hatch'] = None self.p_hatch_args['color'] = '#C1E1C0' self.p_hatch_args['edgecolor'] = '#C1E1C0' else: self.p_hatch_args['hatch'] = '/////' self.plot_order = ['ttbarV','diboson','singletop',\ 'zlight','zbbcc','zc','zjets',\ 'wlight','wbbcc','wc','wjets',\ 'ttbar'] # plot order for background samples (stacked) return
def initialize(self): ## -- Configuration -- ## self.p_lepton = self.m_cfg_parser.get(self.p_cfg_name,'lepton') # ex. muel self.p_logplot = str2bool(self.m_cfg_parser.get(self.p_cfg_name,'logplot')) # ex. False self.p_ana_status = self.m_cfg_parser.get(self.p_cfg_name,'ana_status') # ex. "Internal" self.p_extra_save = self.m_cfg_parser.get(self.p_cfg_name,'extra_saveAs') self.p_scalefactor = str2bool(self.m_cfg_parser.get(self.p_cfg_name,'eventweights')) self.p_plot1d_type = self.m_cfg_parser.get(self.p_cfg_name,'1dplot') self.p_plot2d_type = self.m_cfg_parser.get(self.p_cfg_name,'2dplot') self.p_2dvariables = self.m_cfg_parser.get('plot_variables','2dplots') self.p_1dvariables = self.m_cfg_parser.get('plot_variables','1dplots') p_files = self.m_cfg_parser.get(self.p_cfg_name,'files') p_files = open(p_files,'r').readlines() ## ------------------- ## self.inputfilenames = ['data/'+fname.split('/')[-1].split('.')[0]+'_'+self.p_lepton+'_'+self.p_extra_save+'.json' for fname in p_files] if self.p_scalefactor: if 'pb' in self.lumi['unit']: lumi = "{0:.1f}".format(self.lumi['lumi']/1000.) unit = 'fb' elif 'fb' in self.lumi['unit']: lumi = "{0:.1f}".format(self.lumi['lumi']) unit = 'fb' else: lumi = "{0}".format(self.lumi['lumi']) unit = self.lumi['unit'].strip('i') self.plot_energy_lumi = self.lumi_label self.lumi = {'lumi':lumi,'unit':unit} # reset for use later else: self.plot_energy_lumi = self.PMA_energy_label ## - 1D plotting method (use this syntax to avoid if/else statements) self.p_plot1d = self.PMA_errorbar ## - 2D plotting method (use this syntax to avoid if/else statements) self.p_plot2d = self.PMA_hist_2d
def execute(self,parser,treename=''): """ Main function in the miniSL class -- does all the reading/writing of the flat ntuples. Just added the systematics functionality, so we've made this a hybrid class that can run over the nominal tree and trees for each systematics. @param treename The treename that we need to access for data This is now an option because of the systematics """ self.timeStamp = strftime("%d%b%Y",localtime()) cfg_name = 'miniSL' if not treename else 'systematics' ## -- Configuration -- ## p_sel_script = parser.get(cfg_name,'selection') # ex. pyMiniSL/SelectionBase.py p_nEvents = int(parser.get(cfg_name,'nEvents')) # ex. -1 p_firstEvent = int(parser.get(cfg_name,'firstevent')) # ex. 0 p_cutsfile = parser.get(cfg_name,'cutsfile') # ex. share/pre2loose_cuts.txt p_inputfile = parser.get(cfg_name,'inputfile') # ex. share/miniSL_ntuples.txt p_outputname = parser.get(cfg_name,'outputname') # ex. loose p_isLoose = config.str2bool(parser.get(cfg_name,'isLoose')) # ex. False ## ------------------- ## files = open(p_inputfile,'r').readlines() sel_path,selection = p_sel_script.split('.py')[0].split('/') self.selection = selection # for access later selClassName = selection[0].upper()+selection[1:] self.LUMI = info.LUMI() signalIDs = [i for key in info.dsids()['signal'].keys() for i in info.dsids()['signal'][key]] # TTS and XX signals ttbarIDs = [i for i in info.dsids()['background']['ttbar'].keys()] # Dynamic import the file without needing any hard-coding # Assumes that the class is the same as the filename just capitalized! pyEventFile = importlib.import_module(sel_path+"."+selection) pyEventSel = getattr(pyEventFile,selClassName) loggingLEVEL = logging.getLogger().getEffectiveLevel() logging.info(" -- In file {0}".format(os.path.basename(__file__))) logging.info(" -- Files: ") for i in files: logging.info(" "+i.rstrip('\n')) ## -- Load the selection script evtSel = pyEventSel(parser) # imported using 'importlib' above evtSel.initialize(cfg_name) # setup some of the configurations # ----------------------------------------- # # File Loop # # ----------------------------------------- # total_num_files = len(files) for ff,file in enumerate(files): ## -- Open the current file f = ROOT.TFile.Open("{0}".format(file.strip())) if not f or f.IsZombie(): print print " FILE {0} DOES NOT EXIST".format(f.GetName()) print " Continuing to next file in the loop. " print continue ## -- Load the TTree # For nominal, treename is an empty string # For systematics, pre2preSelection: it's the treename for a systematic # SelectionBase: it's a dummy string if cfg_name != 'miniSL': if treename == 'systs': treename = f.GetListOfKeys()[0].GetName() # only 1 tree and it's the systematic systname = '_'+treename new_treename = treename else: if p_isLoose: treename = 'nominal_Loose' else: treename = info.treename() # nominal new_treename = 'nominal' systname = '' t = f.Get(treename) try: t.GetEntry(0) # to get the mcChannelNumber except AttributeError: print " File {0} does not have the GetEntry() attribute.".format(f.GetName()) print " Skipping and going to the next file.\n" continue ## New File Stuff (the one to which we're writing) name,isMC = self.getName(t) newfilename = "data/{0}{1}_{2}.root".format(name,systname,p_outputname) newfile = ROOT.TFile(newfilename,"RECREATE") self.newtree = ROOT.TTree(new_treename,"Event Information") ## Metadata self.setMetaData(p_outputname) ## Log and print to the console before doing anything print " ++ Running over file ({0}/{1}): {2}".format(ff+1,total_num_files,file.strip()) print " ++ Producing new file: {0}{1}_{2}.root".format(name,systname,p_outputname) logging.info(" ----") logging.info(" {0} Selection".format(p_outputname.title())) logging.info(" File: {0}".format(file.strip())) logging.info(" {0}".format(self.timeStamp)) logging.info(" ---- \n") # ----------------------------------------- # # Initialize the branches # # ----------------------------------------- # self.initBranches() # ----------------------------------------- # # Event Loop # # ----------------------------------------- # maxEntries = t.GetEntries() if p_nEvents < 0 or p_nEvents > maxEntries: nEvents = maxEntries logging.info(" Selected nEvents = {0}; running {1}".format(nEvents,maxEntries)) else: nEvents = p_nEvents ## -- While-loop (no list generation with for loop) evtSel.execute(t,f) # setup the details for this particular file in selection entry = p_firstEvent # in case the user has split the file into pieces while entry < nEvents: #### -- APPLY THE SELECTION -- #### results = evtSel.event_loop(entry) #### ------------------------- #### if not results['result']: logging.info(" ---- ") logging.info(" miniSL::Event {0} Failed Selection ".format(entry)) logging.info(" ---- ") entry+=1 # iterate entry to go to the next one continue self.saveEvent(results['objects']) # ----------------------------------------- # # Clear the ROOT Vectors # # ----------------------------------------- # self.clearVectors() ## increment the while loop entry+=1 # ----------------------------------------- # # Write the new file # # ----------------------------------------- # newfile.Write() print print " New output file: {0}".format(newfilename) print " Ended at: {0}".format(strftime("%c",localtime())) print newfile.Close() return
def main(self,parser): """ Main function in the datamc class -- does all the directing for reading/writing of data from ROOT to json files, and plotting histograms. """ ## -- Configuration -- ## self.p_vars_file = parser.get('datamc','vars') # ex. share/varNames.txt self.p_jsonoutput = str2bool(parser.get('datamc','makejsonfile')) # ex. False self.p_plotoutput = str2bool(parser.get('datamc','makeplot')) # ex. True self.p_mergejson = str2bool(parser.get('datamc','mergejson')) # ex. True self.p_outfile = parser.get('datamc','jsonfilename') # ex. pre self.p_lepton = parser.get('datamc','lepton') # ex. muel ## ------------------- ## ## -- Sanity check -- ## if not any([self.p_plotoutput,self.p_jsonoutput,self.p_mergejson]): print print " You have specified that you don't want to " print " make json outputs, don't want to make " print " plots, and don't want to merge json files. " print " There's nothing left to do. " print " Exiting. " print sys.exit(1) ## ------------------ ## self.p_varlist = info.read_txt_file(self.p_vars_file) # variables from text file # for variables that may have [N], e.g., jet_pt[0], make a list # that just contains the name, e.g., jet_pt. # Plan to is to make a single json file for jet_pt, but # only plot [N], or [N+1] (e.g., the user specifies both jet_pt[0] and jet_pt[1] # in the text file) self.p_varlist_nolead = list(set([p_var.split('[')[0] for p_var in self.p_varlist])) loggingLEVEL = logging.getLogger().getEffectiveLevel() logging.info(" -- In file dataMC.py") logging.info(" -- Make json output: {0} ".format(self.p_jsonoutput)) ## -- Conver ROOT to JSON -- ## if self.p_jsonoutput: import pyDataMC.root2json as root2json logging.info(" > Specified json output ") logging.info(" Will produce json files and then plots automatically ") logging.info(" -- Making json output") print "\n -- Converting ROOT to json output -- \n" ## Making json output, and then making plots (one step is easier...) root2json.ROOT2json(parser) ## -- Merge json files -- ## if self.p_mergejson: ## merge before plotting!! self.merge_json_files() ## -- Plot Histograms -- ## if self.p_plotoutput: from pyDataMC.json2hist import DataMCPlotter logging.info(" -- Making plots from json output") print "\n -- Producing figures -- \n" plotter = DataMCPlotter(parser) plotter.initialize() for var in self.p_varlist: print " ++ Plotting {0} ++\n".format(var) logging.info(" ++ Plotting {0} ++".format(var)) plotter.datamcplotter(var) logging.info(" Finished datamc.py class DataMC") return