def __init__(self, options): self.projPath = options.projPath + '/' self.regions = options.regions self.name = options.name self.toyDir = 'toy' + options.toynum + '_' + self.name + '_plots/' self.toynum = options.toynum if not os.path.isdir(self.projPath + '/' + self.toyDir): os.mkdir(self.projPath + '/' + self.toyDir) if os.path.isfile(self.projPath + '/fitDiagnostics' + self.name + '.root'): self.fd_file = TFile.Open(self.projPath + '/fitDiagnostics' + self.name + '.root') else: self.fd_file = False if options.workspacefile == '': self.ws_file = TFile.Open(self.projPath + '/higgsCombine' + self.name + '.GoodnessOfFit.mH120.' + options.seed + '.root') else: self.ws_file = TFile.Open(self.projPath + '/' + options.workspacefile) if options.toyfile == '': self.toy_file = self.ws_file else: self.toy_file = TFile.Open(self.projPath + '/' + options.toyfile) # self.ws_file.ls() self.ws = self.ws_file.Get('w') # self.ws.Print() # self.toy_w = self.ws.Clone('toy_w') self.toy = self.toy_file.Get('toys/toy_' + options.toynum) getattr(self.ws, 'import')(self.toy) self.ws.writeToFile( self.projPath + '/' + self.toyDir + '/toy_workspace.root', True) if not options.skipSamples: with header.cd(self.projPath): header.executeCmd( 'PostFit2DShapesFromWorkspace -w ' + self.toyDir + '/toy_workspace.root --dataset model_sData -o ' + self.toyDir + 'postfitshapes_s.root -f fitDiagnostics' + self.name + '.root:fit_s --samples 50 --postfit --sampling --print') with header.cd(self.projPath): # diffnuis_cmd = 'python $CMSSW_BASE/src/HiggsAnalysis/CombinedLimit/test/diffNuisances.py fitDiagnostics'+self.name+'.root --abs -g toy'+options.toynum+'_'+self.name+'_plots/nuisance_pulls.root' # header.executeCmd(diffnuis_cmd) self.plotNuisances() self.post_file = TFile.Open(self.projPath + self.toyDir + 'postfitshapes_s.root') for r in self.regions.split(','): if not os.path.isdir(self.projPath + '/' + self.toyDir + r): os.mkdir(self.projPath + '/' + self.toyDir + r) if os.path.isfile(self.projPath + '/saveOut.p'): pickleFile = pickle.load( open(self.projPath + '/saveOut.p', 'rb')) else: pickleFile = pickle.load( open(self.projPath + r + '/saveOut.p', 'rb')) self.plotFitResults(r, pickleFile)
if options.toys == '': raise ValueError( 'Toy option empty. Scanning data fit not currently supported.') if os.path.exists(options.toysFile): toysFile = options.toysFile elif os.path.exists(projDir + '/' + options.toysFile): toysFile = projDir + '/' + options.toysFile else: raise Exception('Cannot find file %s' % options.toysFile) with header.cd(projDir): if not options.skipScan: header.executeCmd( 'combine -M MultiDimFit -d card_%s.txt --algo grid -P %s --floatOtherPOIs=0 --setParameterRanges %s=%s,%s --cminDefaultMinimizerStrategy 0 --saveNLL -n %s -t %s --toysFile %s' % (tag, options.parameter, options.parameter, rrange[0], rrange[1], runname, options.toys, options.toysFile)) header.executeCmd('mkdir %s_plots/' % runname) f_out = ROOT.TFile.Open('%s_plots/all.root' % runname, 'RECREATE') f = ROOT.TFile.Open('higgsCombine%s.MultiDimFit.mH120.123456.root' % runname) for i in range(1, int(options.toys) + 1): TLimit = f.Get('limit') r = [] nll = [] for ientry in range(1, TLimit.GetEntries()): TLimit.GetEntry(ientry) if TLimit.deltaNLL * 2 != 0 and TLimit.iToy == i: nll.append(2 * TLimit.deltaNLL)
def __init__ (self,fitDict,name,dummy_TH2=None,tag=''): self.fitDict = fitDict self.projDir = name+'/'+tag self.fitType = self.fitType() self.name = name self.rpfVars = {} self.binVars = {} # RooFormulaVars for each bin for later evaluation self.allVars = [] # Initialize rpfVars according to if self.fitType == 'splitPoly': # Do some quick checks to make sure these are formatted correctly header.checkFitForm(self.fitDict['XPFORM'],self.fitDict['YPFORM']) nxparams = max([int(param[1:]) for param in self.fitDict.keys() if param.find('X') != -1 and param != 'XPFORM']) nyparams = max([int(param[1:]) for param in self.fitDict.keys() if param.find('Y') != -1 and param != 'YPFORM']) print 'Total number of x fit parameters is ' + str(nxparams) print 'Total number of y fit parameters is ' + str(nyparams) # Make and store RRVs for each param for this_var in {'X':nxparams, 'Y':nyparams}.keys(): nparams = {'X':nxparams, 'Y':nyparams}[this_var] for ip in range(1,nparams+1): input_param_vals = self.fitDict[this_var+str(ip)] this_nom = input_param_vals['NOMINAL'] varname = self.fitType+this_var+'_'+str(ip)+'_'+self.name # Set ranges if they're defined if 'MIN' in input_param_vals.keys() and 'MAX' in input_param_vals.keys(): this_min = input_param_vals['MIN'] this_max = input_param_vals['MAX'] self.rpfVars[varname] = RooRealVar(varname,varname,this_nom,this_min,this_max) if 'ERROR_UP' in input_param_vals.keys() and 'ERROR_DOWN' in input_param_vals.keys(): self.rpfVars[varname].setAsymError(input_param_vals['ERROR_DOWN'],input_param_vals['ERROR_UP']) elif 'ERROR' in input_param_vals.keys(): self.rpfVars[varname].setError(input_param_vals['ERROR']) else: input_break = raw_input('WARNING: Upper and lower bounds on global fit parameter ' +this_var+str(ip) + ' not defined. Please type "N" if you would like to quit or enter if you would like to treat the parameter as constant') if input_break == 'N': quit() else: self.rpfVars[varname] = RooConstVar(varname,varname,this_nom) self.allVars.append(self.rpfVars[varname]) elif self.fitType == 'fullPoly': # Polynomial Order polXO = 0 polYO = 0 for param_name in [key for key in self.fitDict.keys() if key != 'HELP' and key != 'PFORM']: # Assuming poly order is a single digit (pretty reasonable I think...) tempXorder = int(param_name[param_name.find('X')+1]) tempYorder = int(param_name[param_name.find('Y')+1]) if tempXorder > polXO: polXO = tempXorder if tempYorder > polYO: polYO = tempYorder self.polXO = polXO self.polYO = polYO for yi in range(polYO+1): for xi in range(polXO+1): input_param_vals = self.fitDict['X'+str(xi)+'Y'+str(yi)] this_nom = input_param_vals['NOMINAL'] varname = self.fitType+'X'+str(xi)+'Y'+str(yi)+'_'+self.name if 'MIN' in input_param_vals.keys() and 'MAX' in input_param_vals.keys(): this_min = input_param_vals['MIN'] this_max = input_param_vals['MAX'] self.rpfVars[varname] = RooRealVar(varname,varname,this_nom,this_min,this_max) if 'ERROR_UP' in input_param_vals.keys() and 'ERROR_DOWN' in input_param_vals.keys(): self.rpfVars[varname].setAsymError(input_param_vals['ERROR_DOWN'],input_param_vals['ERROR_UP']) elif 'ERROR' in input_param_vals.keys(): self.rpfVars[varname].setError(input_param_vals['ERROR']) else: input_break = raw_input('WARNING: Upper and lower bounds on fit parameter ' + 'x'+str(xi)+'y'+str(yi) + ' not defined. Please type "N" if you would like to quit or enter if you would like to treat the parameter as constant') if input_break == 'N': quit() else: self.rpfVars[varname] = RooConstVar(varname,varname,this_nom) self.allVars.append(self.rpfVars[varname]) elif self.fitType == 'generic': for c in sorted(self.fitDict.keys()): input_param_vals = self.fitDict[c] if c.isdigit(): this_nom = input_param_vals['NOMINAL'] if 'MIN' in input_param_vals.keys() and 'MAX' in input_param_vals.keys(): this_min = input_param_vals['MIN'] this_max = input_param_vals['MAX'] varname = self.fitType+c+'_'+self.name self.rpfVars[varname] = RooRealVar(varname, varname, this_nom, this_min, this_max) if 'ERROR_UP' in input_param_vals.keys() and 'ERROR_DOWN' in input_param_vals.keys(): self.rpfVars[varname].setAsymError(input_param_vals['ERROR_DOWN'],input_param_vals['ERROR_UP']) elif 'ERROR' in self.fitDict[c].keys(): self.rpfVars[varname].setError(input_param_vals['ERROR']) else: input_break = raw_input('WARNING: Upper and lower bounds on fit parameter ' + c + ' not defined. Please type "N" if you would like to quit or enter if you would like to treat the parameter as constant') if input_break == 'N': quit() else: self.rpfVars[varname] = RooConstVar(varname,varname,this_nom) self.allVars.append(self.rpfVars[varname]) elif self.fitType == 'cheb': # Make a dummy TH2 for binning to be used by the chebyshevBasis class self.chebBasis = chebyshevBasis(name,'chebBasis',self.fitDict['CHEBYSHEV']['XORDER'],self.fitDict['CHEBYSHEV']['YORDER'],dummy_TH2) if os.path.isdir(self.projDir+'/basis_plots'): header.executeCmd('rm -rf %s/basis_plots'%self.projDir) header.executeCmd('mkdir %s/basis_plots'%self.projDir) self.chebBasis.drawBasis(self.projDir+'/basis_plots') # This class handles the RRV management itself so we just keep track of the class instance cheb_coeffs = self.chebBasis.getCoeffs() i = 0 while cheb_coeffs.at(i): c = cheb_coeffs.at(i) self.rpfVars[c.GetName()] = c i += 1
if len(masked_regions) > 0: freeze_r_string = " --fixedSignalStrength 0" else: freeze_r_string = '' if options.freezeFail: freeze_string = ' --freezeParameters "var{Fail_.*}"' else: freeze_string = '' # Make a prefit workspace from the data card if options.workspace == '' and not options.post: workspace_name = 'stats_workspace.root' t2w_cmd = 'text2workspace.py --channel-masks -b card_' + card_tag + '.txt -o ' + workspace_name # if not (os.path.exists(workspace_name)):# and options.ftest == 'pvalue'): header.executeCmd(t2w_cmd, options.dryrun) else: workspace_name = options.workspace # Setup a random seed seed = random.randint(100000, 999999) if options.seed != '': seed = options.seed # Setup run naming if options.gof: expectSignal = '0' run_name = 'gof' gen_name = run_name elif options.signalInjection != '': expectSignal = options.signalInjection run_name = 'signalInjection' + expectSignal.replace('.', 'p')
blind_string += m + '=1,' blind_string = blind_string[:-1] + ' ' blind_string = blind_string + blind_string.replace( 'setParametersForFit', 'setParametersForEval') #.replace('=1','=0') if len(masked_regions) > 0: freeze_r_string = " --fixedSignalStrength 0" else: freeze_r_string = '' # Make a prefit workspace from the data card if options.workspace == '' and not options.post: workspace_name = 'stats_workspace.root' t2w_cmd = 'text2workspace.py --channel-masks -b card_' + card_tag + '.txt -o ' + workspace_name if not (os.path.exists(workspace_name) and options.ftest == 'pvalue'): header.executeCmd(t2w_cmd, options.dryrun) else: workspace_name = options.workspace # Setup a random seed seed = random.randint(100000, 999999) if options.seed != '': seed = options.seed # Setup run naming if options.gof: expectSignal = '0' run_name = 'gof' gen_name = run_name elif options.signalInjection != '': expectSignal = options.signalInjection run_name = 'signalInjection' + expectSignal.replace('.', 'p')
else: card_tag = projDir.split('/')[-2] if taskName == '': raise NameError('ERROR in project directory name (where your workspace and data card lives). Did you accidentally provide a leading slash? (ie /projDir/) Quitting...') if options.condor: print 'Condor task name = '+taskName if not os.path.isdir(projDir): raise TypeError(projDir +' is not a directory. Quitting...') # By default, this calculates the impacts for every RooRealVar in your workspace. # That would mean EVERY FAIL BIN would need to be scanned (100s or even 1000s of parameters). # So instead, we'll be a list of only the nuisance parameters and ask to just fit those if options.condor: header.executeCmd('tar --exclude="*.tgz" --exclude="*.std*" --exclude="run_combine*.sh" --exclude="*GoodnessOfFit*" --exclude="*.png" --exclude="*.pdf" --exclude="*.log" -czvf tarball.tgz '+projDir) header.executeCmd('mv tarball.tgz '+projDir) print 'cd '+projDir with header.cd(projDir): systs = SystematicParser('card_'+card_tag+'.txt') impactNuisanceString = '--named ' for s in systs: impactNuisanceString+=s+',' impactNuisanceString = impactNuisanceString[:-1]# Cut off the trailing comma if not options.post: # Remove old runs if they exist header.executeCmd('rm *_paramFit_*.root *_initialFit_*.root') # Build a post-fit workspace #header.executeCmd('text2workspace.py -b card_'+card_tag+'.txt -o impactworkspace.root') header.setSnapshot()
blind_string = blind_string + blind_string.replace( 'setParametersForFit', 'setParametersForEval') seed = random.randint(100000, 999999) commands.append( 'combine -M GoodnessOfFit card_' + card_tag + '.txt --text2workspace "--channel-masks" -m 120 --algo=saturated ' + blind_string) commands.append( 'combine -M GoodnessOfFit card_' + card_tag + '.txt --text2workspace "--channel-masks" -m 120 --algo=saturated ' + blind_string + ' -t ' + options.toys + ' -s ' + str(seed)) # Run commands for c in commands: header.executeCmd(c, options.dryrun) # Now to analyze the output # Get observation gofOutput = TFile.Open('higgsCombineTest.GoodnessOfFit.mH120.root') gofLimitTree = gofOutput.Get('limit') gofLimitTree.GetEntry(0) gofLimit = gofLimitTree.limit # Get toys toyOutput = TFile.Open('higgsCombineTest.GoodnessOfFit.mH120.' + str(seed) + '.root') toyLimitTree = toyOutput.Get('limit') toyLimitTree.Draw('limit>>hlimit') toyLimits = gDirectory.Get('hlimit')
with header.cd(projDir): twoDAlphaConfig = header.openJSON('rerunConfig.json') impactNuisanceString = '--named ' for s in twoDAlphaConfig['SYSTEMATIC'].keys(): if s != 'HELP': impactNuisanceString += s + ',' # Cut off the trailing comma impactNuisanceString = impactNuisanceString[:-1] commands = [] if not options.post: # Remove old runs if they exist # print 'rm *_paramFit_*.root *_initialFit_*.root' # subprocess.call(['rm *_paramFit_*.root *_initialFit_*.root'],shell=True) header.executeCmd('text2workspace.py -b card_' + card_tag + '.txt -o impactworkspace.root') initialfit_cmd = 'combineTool.py -M Impacts -n ' + taskName + ' -d impactworkspace.root --doInitialFit --robustFit 1 -m 120 ' + impactNuisanceString header.executeCmd(initialfit_cmd) if options.crab: # Need to write a custom crab config for the storage site crabConfig = open('custom_crab.py', 'w') crabConfig.write('def custom_crab(config):') print '>> Customising the crab config' crabConfig.write(" config.Site.storageSite = '" + options.storage + "'") crabConfig.close() print 'Executing dry-run of crab jobs' impact_cmd = 'combineTool.py -M Impacts -n ' + taskName + ' -d impactworkspace.root --robustFit 1 --doFits -m 120 --job-mode crab3 --task-name Impacts' + taskName + ' --custom-crab custom_crab.py ' + impactNuisanceString subprocess.call([impact_cmd + ' --dry-run'], shell=True)