def auto_rebin(self, bin_threshold = 1.0, rebin_mode = 0):
		rebin = ch.AutoRebin()
		rebin.SetBinThreshold(bin_threshold)
		rebin.SetRebinMode(rebin_mode)
		rebin.SetPerformRebin(True)
		rebin.SetVerbosity(0)
		rebin.Rebin(self.cb, self.cb)
Beispiel #2
0
 def auto_rebin(self, threshold, mode):
     rebin = ch.AutoRebin()
     rebin.SetBinThreshold(threshold)
     rebin.SetRebinMode(mode)
     rebin.SetPerformRebin(True)
     rebin.SetVerbosity(0)
     if logger.isEnabledFor(logging.DEBUG):
         rebin.SetVerbosity(1)
     rebin.Rebin(self.cb, self.cb)
def prepareShapes(backgrounds, signals, discriminant, discriminantName):
    # Backgrounds is a list of string of the considered backgrounds corresponding to entries in processes_mapping
    # Signals is a list of string of the considered signals corresponding to entries in processes_mapping
    # discriminant is the corresponding entry in the dictionary discriminants

    import CombineHarvester.CombineTools.ch as ch
    root_path = options.root_path

    file, systematics = prepareFile(processes_mapping, discriminants,
                                    root_path, discriminantName)
    if options.dataYear != '2016':
        call([
            'python', 'symmetrize.py', options.output, file, options.dataYear
        ],
             shell=False)

    for signal in signals:
        cb = ch.CombineHarvester()
        cb.AddObservations(['*'], [''], ['_%s' % options.dataYear], [''],
                           discriminant)
        cb.AddProcesses(['*'], [''], ['_%s' % options.dataYear], [''],
                        [signal], discriminant, True)
        #cb.AddProcesses(['*'], [''], ['_%s'%options.dataYear], [''], backgrounds, discriminant, False)
        if options.dataYear == '2016':
            cb.AddProcesses(['*'], [''], ['_%s' % options.dataYear], [''],
                            backgrounds, discriminant, False)
        else:
            if not 'b2j3' in discriminantName:
                try:
                    backgrounds.remove('qcd')
                except:
                    pass
            else:
                if not 'qcd' in backgrounds: backgrounds.append('qcd')
            if 'all' in discriminantName:
                if signal == 'Hut':
                    discriminant.remove((1, 'DNN_Hut_b2j3'))
                    cb.AddProcesses(['*'], [''], ['_%s' % options.dataYear],
                                    [''], backgrounds + ['qcd'],
                                    [(1, 'DNN_Hut_b2j3')], False)
                else:
                    discriminant.remove((1, 'DNN_Hct_b2j3'))
                    cb.AddProcesses(['*'], [''], ['_%s' % options.dataYear],
                                    [''], backgrounds + ['qcd'],
                                    [(1, 'DNN_Hct_b2j3')], False)
                cb.AddProcesses(['*'], [''], ['_%s' % options.dataYear], [''],
                                backgrounds, discriminant, False)
                if signal == 'Hut': discriminant.append((1, 'DNN_Hut_b2j3'))
                else: discriminant.append((1, 'DNN_Hct_b2j3'))
            else:
                cb.AddProcesses(['*'], [''], ['_%s' % options.dataYear], [''],
                                backgrounds, discriminant, False)

        # Systematics
        if not options.nosys:
            for systematic in systematics:
                systematic_only_for_SMtt = False
                systematic_only_for_Sig = False

                for systSMtt in options.sysForSMtt:
                    if CMSNamingConvention(systSMtt) == systematic:
                        systematic_only_for_SMtt = True
                for systSig in options.sysForSig:
                    if CMSNamingConvention(systSig) == systematic:
                        systematic_only_for_Sig = True

                if not systematic_only_for_SMtt and not systematic_only_for_Sig:
                    cb.cp().AddSyst(cb, systematic, 'shape',
                                    ch.SystMap()(1.00))
                elif systematic_only_for_SMtt and not systematic_only_for_Sig:
                    cb.cp().AddSyst(cb, systematic, 'shape',
                                    ch.SystMap('process')(smTTlist, 1.00))
                    #if 'hdamp' in systematic:
                    #    for i in xrange(len(discriminant)):
                    #        if 'b2j3' in discriminant[i][1]:
                    #            cb.cp().AddSyst(cb, systematic, 'shape', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttlf'], 1.00))
                    #            cb.cp().AddSyst(cb, systematic, 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttbb','ttcc'], 1.05))
                    #        elif 'b2j4' in discriminant[i][1]:
                    #            cb.cp().AddSyst(cb, systematic, 'shape', ch.SystMap('bin', 'process')([discriminant[i][1]], smTTlist, 1.00))
                    #        elif 'b3j3' in discriminant[i][1]:
                    #            cb.cp().AddSyst(cb, systematic, 'shape', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttlf'], 1.00))
                    #            cb.cp().AddSyst(cb, systematic, 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttbb','ttcc'], 1.05))
                    #        elif 'b3j4' in discriminant[i][1]:
                    #            cb.cp().AddSyst(cb, systematic, 'shape', ch.SystMap('bin', 'process')([discriminant[i][1]], smTTlist, 1.00))
                    #        elif 'b4j4' in discriminant[i][1]:
                    #            cb.cp().AddSyst(cb, systematic, 'shape', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttbb'], 1.00))
                    #            cb.cp().AddSyst(cb, systematic, 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttcc','ttlf'], 1.05))
                    #else: cb.cp().AddSyst(cb, systematic, 'shape', ch.SystMap('process')(smTTlist, 1.00))
                elif not systematic_only_for_SMtt and systematic_only_for_Sig:
                    cb.cp().AddSyst(cb, systematic, 'shape',
                                    ch.SystMap('process')([signal], 1.00))
                else:
                    cb.cp().AddSyst(
                        cb, systematic, 'shape',
                        ch.SystMap('process')(smTTlist + [signal], 1.00))

            #Lumi corr. https://twiki.cern.ch/twiki/bin/view/CMS/TWikiLUM#LumiComb
            #cb.cp().AddSyst(cb, 'CMS_lumi', 'lnN', ch.SystMap()(options.luminosityError))
            if options.dataYear == '2016':
                cb.cp().AddSyst(cb, 'CMS_lumi_uncorr_2016', 'lnN',
                                ch.SystMap()(1.01))
                cb.cp().AddSyst(cb, 'CMS_lumi_corr_161718', 'lnN',
                                ch.SystMap()(1.006))
                #reproducing 2016
                #cb.cp().AddSyst(cb, 'CMS_lumi_uncorr_2016', 'lnN', ch.SystMap()(1.027))
            elif options.dataYear == '2017':
                cb.cp().AddSyst(cb, 'CMS_lumi_uncorr_2017', 'lnN',
                                ch.SystMap()(1.02))
                cb.cp().AddSyst(cb, 'CMS_lumi_corr_161718', 'lnN',
                                ch.SystMap()(1.009))
                cb.cp().AddSyst(cb, 'CMS_lumi_corr_1718', 'lnN',
                                ch.SystMap()(1.006))
            elif options.dataYear == '2018':
                cb.cp().AddSyst(cb, 'CMS_lumi_uncorr_2018', 'lnN',
                                ch.SystMap()(1.015))
                cb.cp().AddSyst(cb, 'CMS_lumi_corr_161718', 'lnN',
                                ch.SystMap()(1.02))
                cb.cp().AddSyst(cb, 'CMS_lumi_corr_1718', 'lnN',
                                ch.SystMap()(1.002))

            cb.cp().AddSyst(
                cb, 'tt_xsec', 'lnN',
                ch.SystMap('process')(['ttbb', 'ttcc', 'ttlf'], 1.055))
            cb.cp().AddSyst(cb, 'Other_xsec', 'lnN',
                            ch.SystMap('process')(['other'], 1.1))
            #cb.cp().AddSyst(cb, 'hdamp', 'lnN', ch.SystMap('process')(smTTlist, 1.05))
            #cb.cp().AddSyst(cb, 'TuneCP5', 'lnN', ch.SystMap('process')(smTTlist, 1.03))

            for i in xrange(len(discriminant)):
                if 'b2j3' in discriminant[i][1]:
                    cb.cp().AddSyst(cb, '$PROCESS_norm', 'lnN',
                                    ch.SystMap('process')(['qcd'], 1.5))
                #reproducing 2016 ### comment out Other_xsec above!
                #if 'b2j3' in discriminant[i][1]: cb.cp().AddSyst(cb, 'Other_xsec_b2j3', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['other'], 1.1))
                #if 'b2j4' in discriminant[i][1]: cb.cp().AddSyst(cb, 'Other_xsec_b2j4', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['other'], 1.1))
                #if 'b3j3' in discriminant[i][1]: cb.cp().AddSyst(cb, 'Other_xsec_b3j3', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['other'], 1.1))
                #if 'b3j4' in discriminant[i][1]: cb.cp().AddSyst(cb, 'Other_xsec_b3j4', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['other'], 1.1))
                #if 'b4j4' in discriminant[i][1]: cb.cp().AddSyst(cb, 'Other_xsec_b4j4', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['other'], 1.1))

            if options.dataYear == '2016':
                #reproducing 2016
                #cb.cp().AddSyst(cb, 'hdamp_2016', 'lnN', ch.SystMap('process')(['ttbb', 'ttcc', 'ttlf'], 1.05))
                #cb.cp().AddSyst(cb, 'scale_2016', 'lnN', ch.SystMap('process')(['ttbb', 'ttcc', 'ttlf'], 1.15))
                #for i in xrange(len(discriminant)):
                #    if 'j3' in discriminant[i][1]:
                #        cb.cp().AddSyst(cb, '$PROCESS_norm_j3', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttbb'], 1.5))
                #        cb.cp().AddSyst(cb, '$PROCESS_norm_j3', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttcc'], 1.5))
                #        cb.cp().AddSyst(cb, 'jec_2016', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttbb', 'ttcc', 'ttlf', 'other', signal], 1.01))
                #    else:
                #        cb.cp().AddSyst(cb, '$PROCESS_norm_j4', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttbb'], 1.5))
                #        cb.cp().AddSyst(cb, '$PROCESS_norm_j4', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttcc'], 1.5))
                #        cb.cp().AddSyst(cb, 'jec_2016', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttbb', 'ttcc', 'ttlf', 'other', signal], 1.05))#1.05 for j4
                for i in xrange(len(discriminant)):
                    if 'b2' in discriminant[i][1]:
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b2_2016', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttbb'], 1.3))
                        #cb.cp().AddSyst(cb, '$PROCESS_norm_b2_2016', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttcc'], 1.5))
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b2', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttcc'], 1.5))
                    elif 'b3' in discriminant[i][1]:
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b3_2016', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttbb'], 1.3))
                        #cb.cp().AddSyst(cb, '$PROCESS_norm_b3_2016', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttcc'], 1.5))
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b3', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttcc'], 1.5))
                    elif 'b4' in discriminant[i][1]:
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b4_2016', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttbb'], 1.3))
                        #cb.cp().AddSyst(cb, '$PROCESS_norm_b4_2016', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttcc'], 1.5))
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b4', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttcc'], 1.5))
            else:
                for i in xrange(len(discriminant)):
                    if 'b2' in discriminant[i][1]:
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b2', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttbb'], 1.2))
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b2', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttcc'], 1.5))
                    elif 'b3' in discriminant[i][1]:
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b3', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttbb'], 1.22))
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b3', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttcc'], 1.5))
                    elif 'b4' in discriminant[i][1]:
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b4', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttbb'], 1.2))
                        cb.cp().AddSyst(
                            cb, '$PROCESS_norm_b4', 'lnN',
                            ch.SystMap('bin', 'process')([discriminant[i][1]],
                                                         ['ttcc'], 1.5))

                #if 'j3' in discriminant[i][1]:
                #    #cb.cp().AddSyst(cb, '$PROCESS_norm_j3', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttbb'], 1.5))
                #    cb.cp().AddSyst(cb, '$PROCESS_norm_j3', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttbb'], 1.3))
                #    cb.cp().AddSyst(cb, '$PROCESS_norm_j3', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttcc'], 1.5))
                #else:
                #    #cb.cp().AddSyst(cb, '$PROCESS_norm_j4', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttbb'], 1.5))
                #    cb.cp().AddSyst(cb, '$PROCESS_norm_j4', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttbb'], 1.3))
                #    cb.cp().AddSyst(cb, '$PROCESS_norm_j4', 'lnN', ch.SystMap('bin', 'process')([discriminant[i][1]], ['ttcc'], 1.5))

        # Import shapes from ROOT file
        cb.cp().backgrounds().ExtractShapes(file, '$BIN/$PROCESS',
                                            '$BIN/$PROCESS__$SYSTEMATIC')
        cb.cp().signals().ExtractShapes(file, '$BIN/$PROCESS',
                                        '$BIN/$PROCESS__$SYSTEMATIC')

        #reproducing 2016 - comment out
        if options.dataYear == '2016':
            rebin = ch.AutoRebin().SetBinThreshold(100).SetBinUncertFraction(
                0.1)
            rebin.Rebin(cb.cp(), cb)

        #elif options.dataYear == '2017':
        #    #rebin_b2j3 = ch.AutoRebin().SetBinThreshold(5400)#.SetBinUncertFraction(0.1)
        #    #rebin_b2j3.Rebin(cb.cp().bin(["DNN_Hut_b2j3", "DNN_Hct_b2j3"]), cb)

        #AutoMCStat
        cb.SetAutoMCStats(cb, 0.1)
        #reproducing 2016
        #print "Treating bbb"
        #bbb = ch.BinByBinFactory()
        #bbb.SetAddThreshold(0.0001)
        #bbb.AddBinByBin(cb.cp().backgrounds(), cb)
        #bbb.AddBinByBin(cb.cp().signals(), cb)

        output_prefix = 'FCNC_%s_Discriminant_%s' % (signal, discriminantName)

        output_dir = os.path.join(options.output, '%s' % (signal))
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)

        fake_mass = '125'

        # Write card
        datacard = os.path.join(output_dir, output_prefix + '.dat')
        cb.cp().mass([fake_mass, "*"]).WriteDatacard(
            os.path.join(output_dir, output_prefix + '.dat'),
            os.path.join(output_dir, output_prefix + '_shapes.root'))

        # Write small script to compute the limit
        workspace_file = os.path.basename(
            os.path.join(output_dir,
                         output_prefix + '_combine_workspace.root'))
        script = """#! /bin/bash

text2workspace.py {datacard} -m {fake_mass} -o {workspace_root}

# Run limit

echo combine -M AsymptoticLimits -n {name} {workspace_root} -S {systematics} #--run blind #-v +2
#combine -M AsymptoticLimits -n {name} {workspace_root} -S {systematics} #--run expected #-v +2
combine -M AsymptoticLimits -n {name} {workspace_root} -S {systematics} #--run blind #-v +2
#combine -H AsymptoticLimits -M HybridNew -n {name} {workspace_root} -S {systematics} --LHCmode LHC-limits --expectedFromGrid 0.5 #for ecpected, use 0.84 and 0.16
""".format(workspace_root=workspace_file,
           datacard=os.path.basename(datacard),
           name=output_prefix,
           fake_mass=fake_mass,
           systematics=(0 if options.nosys else 1))
        script_file = os.path.join(output_dir,
                                   output_prefix + '_run_limits.sh')
        with open(script_file, 'w') as f:
            f.write(script)

        st = os.stat(script_file)
        os.chmod(script_file, st.st_mode | stat.S_IEXEC)

        # Write small script for datacard checks
        script = """#! /bin/bash

# Run checks
echo combine -M FitDiagnostics -t -1 --expectSignal 0 {datacard} -n fitDiagnostics_{name}_bkgOnly -m 125 --robustHesse 1 --robustFit=1 --rMin -20 --rMax 20 #--plots
echo python ../../../../HiggsAnalysis/CombinedLimit/test/diffNuisances.py -a fitDiagnostics_{name}_bkgOnly.root -g fitDiagnostics_{name}_bkgOnly_plots.root
combine -M FitDiagnostics -t -1 --expectSignal 0 {datacard} -n _{name}_bkgOnly -m 125 --robustHesse 1 --robustFit=1 --rMin -20 --rMax 20 #--plots
python ../../../../HiggsAnalysis/CombinedLimit/test/diffNuisances.py -a fitDiagnostics_{name}_bkgOnly.root -g fitDiagnostics_{name}_bkgOnly_plots.root --skipFitS > fitDiagnostics_{name}_bkgOnly.log
python ../../printPulls.py fitDiagnostics_{name}_bkgOnly_plots.root
combine -M FitDiagnostics -t -1 --expectSignal 1 {datacard} -n _{name}_bkgPlusSig -m 125 --robustHesse 1 --robustFit=1 --rMin -20 --rMax 20 #--plots
python ../../../../HiggsAnalysis/CombinedLimit/test/diffNuisances.py -a fitDiagnostics_{name}_bkgPlusSig.root -g fitDiagnostics_{name}_bkgPlusSig_plots.root --skipFitB > fitDiagnostics_{name}_bkgPlusSig.log
python ../../printPulls.py fitDiagnostics_{name}_bkgPlusSig_plots.root

#print NLL for check
combineTool.py -M FastScan -w {name}_combine_workspace.root:w -o {name}_nll
""".format(workspace_root=workspace_file,
           datacard=os.path.basename(datacard),
           name=output_prefix,
           fake_mass=fake_mass,
           systematics=(0 if options.nosys else 1))
        script_file = os.path.join(output_dir,
                                   output_prefix + '_run_closureChecks.sh')
        with open(script_file, 'w') as f:
            f.write(script)

        st = os.stat(script_file)
        os.chmod(script_file, st.st_mode | stat.S_IEXEC)

        # Write small script for impacts
        script = """#! /bin/bash

# Run impacts
combineTool.py -M Impacts -d {name}_combine_workspace.root -m 125 --doInitialFit --robustFit=1 --robustHesse 1 --rMin -20 --rMax 20 -t -1
combineTool.py -M Impacts -d {name}_combine_workspace.root -m 125 --robustFit=1 --robustHesse 1 --doFits --rMin -20 --rMax 20 -t -1 --parallel 32
combineTool.py -M Impacts -d {name}_combine_workspace.root -m 125 -o {name}_expected_impacts.json --rMin -20 --rMax 20 -t -1
plotImpacts.py -i {name}_expected_impacts.json -o {name}_expected_impacts --per-page 50

combineTool.py -M Impacts -d {name}_combine_workspace.root -m 125 --doInitialFit --robustFit=1 --robustHesse 1 --rMin -20 --rMax 20
combineTool.py -M Impacts -d {name}_combine_workspace.root -m 125 --robustFit=1 --doFits --robustHesse 1 --rMin -20 --rMax 20 --parallel 32
combineTool.py -M Impacts -d {name}_combine_workspace.root -m 125 -o {name}_impacts.json --rMin -20 --rMax 20
plotImpacts.py -i {name}_impacts.json -o {name}_impacts --per-page 50
""".format(workspace_root=workspace_file,
           datacard=os.path.basename(datacard),
           name=output_prefix,
           fake_mass=fake_mass,
           systematics=(0 if options.nosys else 1))
        script_file = os.path.join(output_dir,
                                   output_prefix + '_run_impacts.sh')
        with open(script_file, 'w') as f:
            f.write(script)

        st = os.stat(script_file)
        os.chmod(script_file, st.st_mode | stat.S_IEXEC)

        # Write small script for postfit shapes
        script = """#! /bin/bash

# Run postfit
echo combine -M FitDiagnostics {datacard} -n _{name}_postfit --saveNormalizations --saveShapes --saveWithUncertainties --preFitValue 0 --rMin -20 --rMax 20 --robustHesse 1 --robustFit=1 -v 1
combine -M FitDiagnostics {datacard} -n _{name}_postfit --saveNormalizations --saveShapes --saveWithUncertainties --preFitValue 0 --rMin -20 --rMax 20 --robustHesse 1 --robustFit=1 -v 1 #--plots
PostFitShapesFromWorkspace -w {name}_combine_workspace.root -d {datacard} -o postfit_shapes_{name}.root -f fitDiagnostics_{name}_postfit.root:fit_b --postfit --sampling
python ../../convertPostfitShapesForPlotIt.py -i postfit_shapes_{name}.root
$CMSSW_BASE/src/UserCode/HEPToolsFCNC/plotIt/plotIt -o postfit_shapes_{name}_forPlotIt ../../postfit_plotIt_config_{coupling}_{year}.yml -y
$CMSSW_BASE/src/UserCode/HEPToolsFCNC/plotIt/plotIt -o postfit_shapes_{name}_forPlotIt ../../postfit_plotIt_config_{coupling}_{year}_qcd.yml -y
""".format(workspace_root=workspace_file,
           datacard=os.path.basename(datacard),
           name=output_prefix,
           fake_mass=fake_mass,
           systematics=(0 if options.nosys else 1),
           coupling=("Hut" if "Hut" in output_prefix else "Hct"),
           year=options.dataYear)
        script_file = os.path.join(output_dir,
                                   output_prefix + '_run_postfit.sh')
        with open(script_file, 'w') as f:
            f.write(script)

        st = os.stat(script_file)
        os.chmod(script_file, st.st_mode | stat.S_IEXEC)
assert (len(args) >= 2)

BIN = args[0]
KD = args[1]

print BIN, KD

cmb = ch.CombineHarvester()
cmb.SetFlag('check-negative-bins-on-import', 0)

cmb.ParseDatacard("datacards/" + BIN + "/" + KD + "/datacard.txt")

# Rebin Mode 1 : Starts from bin with lowest content which fails the condition. Tries moving left and right merging bins until threshold is met.
# Chooses from left and right to minimise number of bins lost
# Repeats with new lowest bin until all bins pass threshold
# SetBinUncertFraction : The threshold on the bin uncertainty fraction for which we consider merging bins

rebin = ch.AutoRebin()
rebin.SetBinThreshold(0.0)
rebin.SetBinUncertFraction(0.25)
rebin.SetRebinMode(1)
rebin.SetPerformRebin(True)
rebin.SetVerbosity(0)
rebin.Rebin(cmb, cmb)

writer = ch.CardWriter(
    'datacards/' + BIN + '/' + KD + '_Proc/datacard.txt',
    'datacards/' + BIN + '/' + KD + '_Proc/shapes/histos_' + BIN + '.root')

writer.WriteCards('', cmb)