""" This file provides a parameterized implementation of the cut-based ID described in the CMS analysis "Search for long-lived particles decaying in the endcap muon system in proton-proton collisions at sqrt{s} = 13 TeV". The provided parameterization can reproduce the cut-based ID efficiency from full simulation to within 10% for various LLP masses (7-55 GeV), lifetimes (0.1 - 100 m), and decay modes (a pair of d quarks or a pair of tau leptons) considered. A detailed instruction on the usage of the code is provided in the HEPData record: https://doi.org/10.17182/hepdata.104408 """ import numpy as np import math import ROOT as rt """ The AvgStation takes arrays of LLP decay position z and r in cm, outputs the avgStation prediction. More details in the HEPData entry. """ def AvgStation(z, r): station = np.copy(z) station[np.abs(z)<632] = 1 station[np.logical_and(np.abs(z)<724, np.abs(r)>275)] = 1 station[np.logical_and(station>1, np.abs(z)<850)] = 2 station[np.logical_and(np.abs(z)>=850,np.abs(z)<970)] = 3 station[np.abs(z)>=970] = 4 return station """ The region function outputs the LLP decay region as a string of 'a', 'b', or 'NA', depending on the LLP decay position z and r in cm and the LLP eta """ def region (z_list, r_list, eta_list): region_list = [] for i in range(len(z_list)): z = z_list[i] r = r_list[i] eta = eta_list[i] if r > 391 and r < 695.5 and abs(z) > 400 and abs(z) < 671: region_list.append('a') elif abs(z) > 671 and abs(z) < 1100 and r < 695.5 and abs(eta) < 2: region_list.append('b') else: region_list.append('NA') return np.array(region_list) """ input: list of LLP decay position in z, r, LLP hadronic energy, LLP eta, and a histogram of parametrization of NStation>1 efficiency with respect to the LLP hadronic energy (Additional Figure 8 in HEPData record) input type: z, r, hadE, and eta are numpy arrays and eff_hist is TH1F output: list of probability that the event passes cut-based ID """ def cut_based_id(z, r, hadE, eta, eff_hist_b): avgStation = AvgStation(z, r) regions = region(z, r, eta) eta_cut = np.copy(avgStation) eta_cut[eta_cut==1] = 1.8 #implicitly 1.1 eta_cut[eta_cut==2] = 1.6 eta_cut[eta_cut==3] = 1.6 eta_cut[eta_cut==4] = 1.8 weight=[] for j in range(len(hadE)): if regions[j] == 'NA': weight.append(0.0) elif regions[j] == 'a': weight.append(1.0) else: x = eff_hist_b.GetXaxis().FindFixBin(hadE[j]) weight.append(eff_hist_b.GetBinContent(x)) weight = np.array(weight) #apply eta<1.9 if NStation>1, else apply different eta cut as defined above weight = weight*(np.abs(eta)<1.9)+(1-weight)*(np.abs(eta)