def test_normal_interval(): from coffea.hist.plot import normal_interval # Reference weighted efficiency and error from ROOTs TEfficiency denom = np.array([ 89.01457591590004, 2177.066076428943, 6122.5256890981855, 0.0, 100.27757990710668, ]) num = np.array([ 75.14287743709515, 2177.066076428943, 5193.454723043864, 0.0, 84.97723540536361, ]) denom_sumw2 = np.array([ 94.37919737476827, 10000.0, 6463.46795877633, 0.0, 105.90898005417333 ]) num_sumw2 = np.array( [67.2202147680005, 10000.0, 4647.983931785646, 0.0, 76.01275761253757]) ref_hi = np.array([ 0.0514643476600107, 0.0, 0.0061403263960343, np.nan, 0.0480731185500146 ]) ref_lo = np.array([ 0.0514643476600107, 0.0, 0.0061403263960343, np.nan, 0.0480731185500146 ]) interval = normal_interval(num, denom, num_sumw2, denom_sumw2) threshold = 1e-6 lo, hi = interval assert len(ref_hi) == len(hi) assert len(ref_lo) == len(lo) for i in range(len(ref_hi)): if np.isnan(ref_hi[i]): assert np.isnan(ref_hi[i]) elif ref_hi[i] == 0.0: assert hi[i] == 0.0 else: assert np.abs(hi[i] / ref_hi[i] - 1) < threshold if np.isnan(ref_lo[i]): assert np.isnan(ref_lo[i]) elif ref_lo[i] == 0.0: assert lo[i] == 0.0 else: assert np.abs(lo[i] / ref_lo[i] - 1) < threshold
def test_hist_compat(): from coffea.util import load test = load('tests/samples/old_hist_format.coffea') expected_bins = np.array([ -np.inf, 0., 20., 40., 60., 80., 100., 120., 140., 160., 180., 200., 220., 240., 260., 280., 300., 320., 340., 360., 380., 400., 420., 440., 460., 480., 500., 520., 540., 560., 580., 600., 620., 640., 660., 680., 700., 720., 740., 760., 780., 800., 820., 840., 860., 880., 900., 920., 940., 960., 980., 1000., 1020., 1040., 1060., 1080., 1100., 1120., 1140., 1160., 1180., 1200., np.inf, np.nan]) assert np.all(test._axes[2]._interval_bins[:-1] == expected_bins[:-1]) assert np.isnan(test._axes[2]._interval_bins[-1])
def test_rochester(): rochester_data = lookup_tools.txt_converters.convert_rochester_file('tests/samples/RoccoR2018.txt.gz',loaduncs=True) rochester = lookup_tools.rochester_lookup.rochester_lookup(rochester_data) # to test 1-to-1 agreement with official Rochester requires loading C++ files # instead, preload the correct scales in the sample directory # the script tests/samples/rochester/build_rochester.py produces these official_data_k = np.load('tests/samples/nano_dimuon_rochester.npy') official_data_err = np.load('tests/samples/nano_dimuon_rochester_err.npy') official_mc_k = np.load('tests/samples/nano_dy_rochester.npy') official_mc_err = np.load('tests/samples/nano_dy_rochester_err.npy') mc_rand = np.load('tests/samples/nano_dy_rochester_rand.npy') # test against nanoaod events = NanoEvents.from_file(os.path.abspath('tests/samples/nano_dimuon.root')) data_k = rochester.kScaleDT(events.Muon.charge, events.Muon.pt, events.Muon.eta, events.Muon.phi) assert(all(np.isclose(data_k.flatten(), official_data_k))) data_err = rochester.kScaleDTerror(events.Muon.charge, events.Muon.pt, events.Muon.eta, events.Muon.phi) data_err = np.array(data_err.flatten(), dtype=float) assert(all(np.isclose(data_err, official_data_err, atol=1e-8))) # test against mc events = NanoEvents.from_file(os.path.abspath('tests/samples/nano_dy.root')) hasgen = ~np.isnan(events.Muon.matched_gen.pt.fillna(np.nan)) mc_rand = JaggedArray.fromoffsets(hasgen.offsets, mc_rand) mc_kspread = rochester.kSpreadMC(events.Muon.charge[hasgen], events.Muon.pt[hasgen], events.Muon.eta[hasgen], events.Muon.phi[hasgen], events.Muon.matched_gen.pt[hasgen]) mc_ksmear = rochester.kSmearMC(events.Muon.charge[~hasgen], events.Muon.pt[~hasgen], events.Muon.eta[~hasgen], events.Muon.phi[~hasgen], events.Muon.nTrackerLayers[~hasgen], mc_rand[~hasgen]) mc_k = np.ones_like(events.Muon.pt.flatten()) mc_k[hasgen.flatten()] = mc_kspread.flatten() mc_k[~hasgen.flatten()] = mc_ksmear.flatten() assert(all(np.isclose(mc_k, official_mc_k))) mc_errspread = rochester.kSpreadMCerror(events.Muon.charge[hasgen], events.Muon.pt[hasgen], events.Muon.eta[hasgen], events.Muon.phi[hasgen], events.Muon.matched_gen.pt[hasgen]) mc_errsmear = rochester.kSmearMCerror(events.Muon.charge[~hasgen], events.Muon.pt[~hasgen], events.Muon.eta[~hasgen], events.Muon.phi[~hasgen], events.Muon.nTrackerLayers[~hasgen], mc_rand[~hasgen]) mc_err = np.ones_like(events.Muon.pt.flatten()) mc_err[hasgen.flatten()] = mc_errspread.flatten() mc_err[~hasgen.flatten()] = mc_errsmear.flatten() assert(all(np.isclose(mc_err, official_mc_err, atol=1e-8)))
def test_rochester(): rochester_data = lookup_tools.txt_converters.convert_rochester_file( "tests/samples/RoccoR2018.txt.gz", loaduncs=True) rochester = lookup_tools.rochester_lookup.rochester_lookup(rochester_data) # to test 1-to-1 agreement with official Rochester requires loading C++ files # instead, preload the correct scales in the sample directory # the script tests/samples/rochester/build_rochester.py produces these official_data_k = np.load("tests/samples/nano_dimuon_rochester.npy") official_data_err = np.load("tests/samples/nano_dimuon_rochester_err.npy") official_mc_k = np.load("tests/samples/nano_dy_rochester.npy") official_mc_err = np.load("tests/samples/nano_dy_rochester_err.npy") mc_rand = np.load("tests/samples/nano_dy_rochester_rand.npy") # test against nanoaod events = NanoEventsFactory.from_root( os.path.abspath("tests/samples/nano_dimuon.root")).events() data_k = rochester.kScaleDT(events.Muon.charge, events.Muon.pt, events.Muon.eta, events.Muon.phi) data_k = np.array(ak.flatten(data_k)) assert all(np.isclose(data_k, official_data_k)) data_err = rochester.kScaleDTerror(events.Muon.charge, events.Muon.pt, events.Muon.eta, events.Muon.phi) data_err = np.array(ak.flatten(data_err), dtype=float) assert all(np.isclose(data_err, official_data_err, atol=1e-8)) # test against mc events = NanoEventsFactory.from_root( os.path.abspath("tests/samples/nano_dy.root")).events() hasgen = ~np.isnan(ak.fill_none(events.Muon.matched_gen.pt, np.nan)) mc_rand = ak.unflatten(mc_rand, ak.num(hasgen)) mc_kspread = rochester.kSpreadMC( events.Muon.charge[hasgen], events.Muon.pt[hasgen], events.Muon.eta[hasgen], events.Muon.phi[hasgen], events.Muon.matched_gen.pt[hasgen], ) mc_ksmear = rochester.kSmearMC( events.Muon.charge[~hasgen], events.Muon.pt[~hasgen], events.Muon.eta[~hasgen], events.Muon.phi[~hasgen], events.Muon.nTrackerLayers[~hasgen], mc_rand[~hasgen], ) mc_k = np.array(ak.flatten(ak.ones_like(events.Muon.pt))) hasgen_flat = np.array(ak.flatten(hasgen)) mc_k[hasgen_flat] = np.array(ak.flatten(mc_kspread)) mc_k[~hasgen_flat] = np.array(ak.flatten(mc_ksmear)) assert all(np.isclose(mc_k, official_mc_k)) mc_errspread = rochester.kSpreadMCerror( events.Muon.charge[hasgen], events.Muon.pt[hasgen], events.Muon.eta[hasgen], events.Muon.phi[hasgen], events.Muon.matched_gen.pt[hasgen], ) mc_errsmear = rochester.kSmearMCerror( events.Muon.charge[~hasgen], events.Muon.pt[~hasgen], events.Muon.eta[~hasgen], events.Muon.phi[~hasgen], events.Muon.nTrackerLayers[~hasgen], mc_rand[~hasgen], ) mc_err = np.array(ak.flatten(ak.ones_like(events.Muon.pt))) mc_err[hasgen_flat] = np.array(ak.flatten(mc_errspread)) mc_err[~hasgen_flat] = np.array(ak.flatten(mc_errsmear)) assert all(np.isclose(mc_err, official_mc_err, atol=1e-8))