diff --git a/Analysis/hh_bbww.py b/Analysis/hh_bbww.py index b731918..9a7a1cd 100644 --- a/Analysis/hh_bbww.py +++ b/Analysis/hh_bbww.py @@ -77,14 +77,17 @@ def GetBTagWeight(global_cfg_dict, cat, applyBtag=False): btagshape_weight = "weight_bTagShape_Central" return f"{btag_weight}*{btagshape_weight}" - -def GetWeight(channel, cat, boosted_categories): # do you need all these args? +def GetWeight( + channel, cat, boosted_categories, apply_btag_shape_weights=False +): # do you need all these args? # weights_to_apply = ["weight_base", "ExtraDYWeight"] weights_to_apply = ["weight_base"] total_weight = "*".join(weights_to_apply) for lep_index in [1, 2]: total_weight = f"{total_weight} * {GetLepWeight(lep_index)}" total_weight = f"{total_weight} * {GetTriggerWeight()}" + if apply_btag_shape_weights: + total_weight = f"{total_weight} * weight_bTagShape_Central" return total_weight diff --git a/Analysis/histTupleDef.py b/Analysis/histTupleDef.py index 02aff39..6cb95c4 100644 --- a/Analysis/histTupleDef.py +++ b/Analysis/histTupleDef.py @@ -42,7 +42,79 @@ def GetDfw(df, setup, dataset_name): central_df_weights_computed = False +btag_shape_weight_corrected = False +cat_to_channelId = {"e": 1, "mu": 2, "eE": 11, "eMu": 12, "muMu": 22} + + +class BtagShapeWeightCorrector: + def __init__(self, btag_integral_ratios): + self.exisiting_srcScale_combs = [key for key in btag_integral_ratios.keys()] + # if the btag_integral_ratios dictionary is not empty, do stuff + if self.exisiting_srcScale_combs: + ROOT.gInterpreter.Declare("#include ") + + for key in btag_integral_ratios.keys(): + # key in btag_integral_ratios has form f"{source}_{scale}", so function expects that + # and creates a map and function to rescale btag weights for each f"{source}_{scale}" value + self._declare_cpp_map_and_resc_func(btag_integral_ratios, key) + + def _declare_cpp_map_and_resc_func(self, btag_integral_ratios, unc_src_scale): + correction_factors = btag_integral_ratios[unc_src_scale] + + # init c++ map + cpp_map_entries = [] + for cat, multipl_dict in correction_factors.items(): + channelId = cat_to_channelId[cat] + for key, ratio in multipl_dict.items(): + # key has structure f"ratio_ncetnralJet_{number}"" + num_jet = int(key.split("_")[-1]) + cpp_map_entries.append(f"{{{{{channelId}, {num_jet}}}, {ratio}}}") + cpp_init = ", ".join(cpp_map_entries) + + ROOT.gInterpreter.Declare( + f""" + static const std::map, float> ratios_{unc_src_scale} = {{ + {cpp_init} + }}; + + float integral_correction_ratio_{unc_src_scale}(int ncentralJet, int channelId) {{ + std::pair key{{channelId, ncentralJet}}; + try + {{ + float ratio = ratios_{unc_src_scale}.at(key); + return ratio; + }} + catch (...) + {{ + return 1.0f; + }} + }}""" + ) + + def UpdateBtagWeight(self, dfw, unc_src="Central", unc_scale=None): + # return original dfw if empty dict was passed to constructor + if not self.exisiting_srcScale_combs: + return dfw + + if unc_scale is None: + unc_src_scale = unc_src + else: + unc_src_scale = f"{unc_src}_{unc_scale}" + + if unc_src_scale not in self.exisiting_srcScale_combs: + raise RuntimeError( + f"`BtagShapeWeightCorrection.json` does not contain key `{unc_src_scale}`." + ) + + dfw.df = dfw.df.Redefine( + "weight_bTagShape_Central", + f"""if (ncentralJet >= 2 && ncentralJet <= 8) + return integral_correction_ratio_{unc_src_scale}(ncentralJet, channelId)*weight_bTagShape_Central; + return weight_bTagShape_Central;""", + ) + + return dfw def DefineWeightForHistograms( *, @@ -55,6 +127,7 @@ def DefineWeightForHistograms( global_params, final_weight_name, df_is_central, + btag_integral_ratios, ): global central_df_weights_computed is_central = uncName == central @@ -87,12 +160,24 @@ def DefineWeightForHistograms( if df_is_central: central_df_weights_computed = True + # btag shape weight column appears here + correct_btagShape_weights = global_params.get("correct_btagShape_weights", False) + global btag_shape_weight_corrected + if correct_btagShape_weights and not btag_shape_weight_corrected and btag_integral_ratios: + isMC = not isData + if is_central and isMC: + weight_corrector = BtagShapeWeightCorrector(btag_integral_ratios) + print(f"Calling weight_corrector.UpdateBtagWeight for unc_source={uncName} unc_scale={uncScale}") + weight_corrector.UpdateBtagWeight(dfw, unc_src=uncName) + btag_shape_weight_corrected = True + categories = global_params["categories"] boosted_categories = global_params.get("boosted_categories", []) process_group = global_params["process_group"] total_weight_expression = ( # channel, cat, boosted_categories --> these are not needed in the GetWeight function therefore I just put some placeholders - analysis.GetWeight("", "", boosted_categories) + # if btag shape weight was corrected => must be applied, else no + analysis.GetWeight("", "", boosted_categories, apply_btag_shape_weights=btag_shape_weight_corrected) if process_group != "data" else "1" ) # are we sure? diff --git a/Corrections b/Corrections index dbecc97..77e8939 160000 --- a/Corrections +++ b/Corrections @@ -1 +1 @@ -Subproject commit dbecc9725e37cfccbc89b60f313077d39c60628a +Subproject commit 77e893974a7d181cd0dbb3720dcf19b5dd770a97 diff --git a/FLAF b/FLAF index 37aa49f..cc60b4d 160000 --- a/FLAF +++ b/FLAF @@ -1 +1 @@ -Subproject commit 37aa49fe8777dbd01023db0d71363c6e7994fec6 +Subproject commit cc60b4d37e642e0d432a54ddd9c68cbb01badc4e diff --git a/config/global.yaml b/config/global.yaml index 7ea4f58..4b4708f 100644 --- a/config/global.yaml +++ b/config/global.yaml @@ -57,6 +57,8 @@ muIsoWP: "Loose" treeName: "Events" +correct_btagShape_weights: True + nPbPerFile: 2_000 # 2fb-1 per split data file nEventsPerFile: 100_000 # 100k events per MC file @@ -256,6 +258,31 @@ payload_producers: awkward_based: True uproot_stepsize: '50MB' dependencies: + BtagShape: + producers_module_name: BtagShapeProducer + producer_name: BtagShapeProducer + save_as: json + columns : [] + lepton_categories: + e: 1 + mu: 2 + eE: 11 + eMu: 12 + muMu: 22 + jet_multiplicities: + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + n_cpus: 4 + max_runtime: 8.0 + cmssw_env: False + awkward_based: True + uproot_stepsize: '50MB' + dependencies: region: All region_default: SR