eff_plots.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. #!/usr/bin/env python
  2. from itertools import product
  3. from argparse import ArgumentParser
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. from uproot import open as root_open
  7. from matplottery.utils import Hist1D, Hist2D, to_html_table
  8. from matplottery.plotter import set_defaults, plot_2d
  9. import matplotboard as mpb
  10. matching_cuts = {
  11. 'new-extra-narrow': [
  12. dict(
  13. dPhiMaxHighEt=0.025,
  14. dPhiMaxHighEtThres=20.0,
  15. dPhiMaxLowEtGrad=-0.002,
  16. dRzMaxHighEt=9999.0,
  17. dRzMaxHighEtThres=0.0,
  18. dRzMaxLowEtGrad=0.0,
  19. ),
  20. dict(
  21. dPhiMaxHighEt=0.0015,
  22. dPhiMaxHighEtThres=0.0,
  23. dPhiMaxLowEtGrad=0.0,
  24. dRzMaxHighEt=0.025,
  25. dRzMaxHighEtThres=30.0,
  26. dRzMaxLowEtGrad=-0.002,
  27. ),
  28. dict(
  29. dPhiMaxHighEt=0.0015,
  30. dPhiMaxHighEtThres=0.0,
  31. dPhiMaxLowEtGrad=0.0,
  32. dRzMaxHighEt=0.025,
  33. dRzMaxHighEtThres=30.0,
  34. dRzMaxLowEtGrad=-0.002,
  35. )
  36. ],
  37. 'new-default': [
  38. dict(
  39. dPhiMaxHighEt=0.05,
  40. dPhiMaxHighEtThres=20.0,
  41. dPhiMaxLowEtGrad=-0.002,
  42. dRzMaxHighEt=9999.0,
  43. dRzMaxHighEtThres=0.0,
  44. dRzMaxLowEtGrad=0.0,
  45. ),
  46. dict(
  47. dPhiMaxHighEt=0.003,
  48. dPhiMaxHighEtThres=0.0,
  49. dPhiMaxLowEtGrad=0.0,
  50. dRzMaxHighEt=0.05,
  51. dRzMaxHighEtThres=30.0,
  52. dRzMaxLowEtGrad=-0.002,
  53. ),
  54. dict(
  55. dPhiMaxHighEt=0.003,
  56. dPhiMaxHighEtThres=0.0,
  57. dPhiMaxLowEtGrad=0.0,
  58. dRzMaxHighEt=0.05,
  59. dRzMaxHighEtThres=30.0,
  60. dRzMaxLowEtGrad=-0.002,
  61. )
  62. ],
  63. 'new-wide': [
  64. dict(
  65. dPhiMaxHighEt=0.10,
  66. dPhiMaxHighEtThres=20.0,
  67. dPhiMaxLowEtGrad=-0.002,
  68. dRzMaxHighEt=9999.0,
  69. dRzMaxHighEtThres=0.0,
  70. dRzMaxLowEtGrad=0.0,
  71. ),
  72. dict(
  73. dPhiMaxHighEt=0.006,
  74. dPhiMaxHighEtThres=0.0,
  75. dPhiMaxLowEtGrad=0.0,
  76. dRzMaxHighEt=0.10,
  77. dRzMaxHighEtThres=30.0,
  78. dRzMaxLowEtGrad=-0.002,
  79. ),
  80. dict(
  81. dPhiMaxHighEt=0.006,
  82. dPhiMaxHighEtThres=0.0,
  83. dPhiMaxLowEtGrad=0.0,
  84. dRzMaxHighEt=0.10,
  85. dRzMaxHighEtThres=30.0,
  86. dRzMaxLowEtGrad=-0.002,
  87. )
  88. ],
  89. 'new-extra-wide': [
  90. dict(
  91. dPhiMaxHighEt=0.15,
  92. dPhiMaxHighEtThres=20.0,
  93. dPhiMaxLowEtGrad=-0.002,
  94. dRzMaxHighEt=9999.0,
  95. dRzMaxHighEtThres=0.0,
  96. dRzMaxLowEtGrad=0.0,
  97. ),
  98. dict(
  99. dPhiMaxHighEt=0.009,
  100. dPhiMaxHighEtThres=0.0,
  101. dPhiMaxLowEtGrad=0.0,
  102. dRzMaxHighEt=0.15,
  103. dRzMaxHighEtThres=30.0,
  104. dRzMaxLowEtGrad=-0.002,
  105. ),
  106. dict(
  107. dPhiMaxHighEt=0.009,
  108. dPhiMaxHighEtThres=0.0,
  109. dPhiMaxLowEtGrad=0.0,
  110. dRzMaxHighEt=0.15,
  111. dRzMaxHighEtThres=30.0,
  112. dRzMaxLowEtGrad=-0.002,
  113. )
  114. ],
  115. }
  116. samples = None
  117. def load_samples():
  118. global samples
  119. if samples is None:
  120. print("loading samples")
  121. samples = {}
  122. for proc, wp, config in product(procs, wps, configs):
  123. samples[(proc, wp, config)] = root_open(f'../hists/{proc}-{wp}-{config}.root')
  124. # if 'old' in wp:
  125. # samples[(proc, wp)] = root_open(f'../hists/with_skipping/{proc}-{wp}.root')
  126. # elif 'noskip' in wp:
  127. # wpkey = wp.replace('-noskip', '')
  128. # samples[(proc, wp)] = root_open(f'../hists/no_skipping/{proc}-{wpkey}.root')
  129. # elif 'skip' in wp:
  130. # wpkey = wp.replace('-skip', '')
  131. # samples[(proc, wp)] = root_open(f'../hists/with_skipping/{proc}-{wpkey}.root')
  132. return samples
  133. def calc_window(et, eta, hit, variable, cut_sel):
  134. idx = min(hit-1, 2)
  135. cut_sel = cut_sel.replace('-skip', '').replace('-noskip', '')
  136. cuts = matching_cuts[cut_sel][idx]
  137. if 'etaBins' in cuts:
  138. for eta_idx, bin_high in enumerate(cuts['etaBins']):
  139. if eta < bin_high:
  140. high_et = cuts[f'{variable}MaxHighEt'][eta_idx]
  141. high_et_thres = cuts[f'{variable}MaxHighEtThres'][eta_idx]
  142. low_et_grad = cuts[f'{variable}MaxLowEtGrad'][eta_idx]
  143. break
  144. else: # highest bin
  145. high_et = cuts[f'{variable}MaxHighEt'][-1]
  146. high_et_thres = cuts[f'{variable}MaxHighEtThres'][-1]
  147. low_et_grad = cuts[f'{variable}MaxLowEtGrad'][-1]
  148. else:
  149. high_et = cuts[f'{variable}MaxHighEt']
  150. high_et_thres = cuts[f'{variable}MaxHighEtThres']
  151. low_et_grad = cuts[f'{variable}MaxLowEtGrad']
  152. return high_et + min(0, et-high_et_thres)*low_et_grad
  153. def hist_integral_ratio(num, den):
  154. num_int = num.integral
  155. den_int = den.integral
  156. ratio = num_int / den_int
  157. error = np.sqrt(den_int) / den_int # TODO: Check this definition of error
  158. return ratio, error
  159. def center_text(x, y, txt, **kwargs):
  160. plt.text(x, y, txt,
  161. horizontalalignment='center', verticalalignment='center',
  162. transform=plt.gca().transAxes, size=24, **kwargs)
  163. def hist_plot(h: Hist1D, *args, include_errors=False, line_width=1, **kwargs):
  164. """ Plots a 1D ROOT histogram object using matplotlib """
  165. counts = h.counts
  166. edges = h.edges
  167. left, right = edges[:-1], edges[1:]
  168. x = np.array([left, right]).T.flatten()
  169. y = np.array([counts, counts]).T.flatten()
  170. plt.plot(x, y, *args, linewidth=line_width, **kwargs)
  171. if include_errors:
  172. if h.errors_up is not None:
  173. errors = np.vstack((h.errors_down, h.errors_up))
  174. else:
  175. errors = h.errors
  176. plt.errorbar(h.bin_centers, h.counts, yerr=errors,
  177. color='k', marker=None, linestyle='None',
  178. barsabove=True, elinewidth=.7, capsize=1)
  179. def hist2d_percent_contour(h: Hist1D, percent: float, axis: str):
  180. values = h.counts
  181. try:
  182. axis = axis.lower()
  183. axis_idx = {'x': 1, 'y': 0}[axis]
  184. except KeyError:
  185. raise ValueError('axis must be \'x\' or \'y\'')
  186. if percent < 0 or percent > 1:
  187. raise ValueError('percent must be in [0,1]')
  188. with np.warnings.catch_warnings():
  189. np.warnings.filterwarnings('ignore', 'invalid value encountered in true_divide')
  190. values = values / np.sum(values, axis=axis_idx, keepdims=True)
  191. np.nan_to_num(values, copy=False)
  192. values = np.cumsum(values, axis=axis_idx)
  193. idxs = np.argmax(values > percent, axis=axis_idx)
  194. x_centers, y_centers = h.bin_centers
  195. if axis == 'x':
  196. return x_centers[idxs], y_centers
  197. else:
  198. return x_centers, y_centers[idxs]
  199. @mpb.decl_fig
  200. def plot_residuals(sample, layer, hit, variable, subdet):
  201. load_samples()
  202. proc, wp = sample
  203. track_matched = samples[sample][f'{variable}_{subdet}_L{layer}_H{hit}_v_Et_TrackMatched']
  204. # no_match = samples[sample][f'{variable}_{subdet}_L{layer}_H{hit}_v_Et_NoMatch']
  205. h_real = Hist2D(track_matched)
  206. # h_fake = Hist2D(no_match)
  207. def do_plot(h):
  208. plot_2d(h, cmap='viridis')
  209. xs, ys = hist2d_percent_contour(h, .90, 'x')
  210. plt.plot(xs, ys, color='green', label='90\% contour')
  211. xs, ys = hist2d_percent_contour(h, .995, 'x')
  212. plt.plot(xs, ys, color='darkgreen', label='99.5\% contour')
  213. ets = h.edges[1]
  214. cuts = [calc_window(et, 0, hit, variable, wp) for et in ets]
  215. plt.plot(cuts, ets, color='red', label='Cut Value')
  216. plt.xlabel({'dPhi': r'$\delta \phi$ (rads)',
  217. 'dRz': r'$\delta R/z$ (cm)'}[variable])
  218. # plt.sca(plt.subplot(1, 2, 1))
  219. do_plot(h_real)
  220. plt.title('Truth-Matched Seeds')
  221. plt.ylabel('$E_T$ (GeV)')
  222. # plt.sca(plt.subplot(1, 2, 2))
  223. # do_plot(h_fake)
  224. # plt.title('Not Truth-Matched Seeds')
  225. plt.legend(loc='upper right')
  226. @mpb.decl_fig
  227. def plot_residuals_eta(sample, hit, variable):
  228. load_samples()
  229. h = Hist2D(samples[sample][f'{variable}_residuals_v_eta_H{hit}'])
  230. plot_2d(h)
  231. xs, ys = hist2d_percent_contour(h, .90, 'x')
  232. plt.plot(xs, ys, color='green', label='90\% contour')
  233. xs, ys = hist2d_percent_contour(h, .995, 'x')
  234. plt.plot(xs, ys, color='darkgreen', label='99.5\% contour')
  235. plt.xlabel({'dPhi': r'$\delta \phi$ (rads)',
  236. 'dRz': r'$\delta R/z$ (cm)'}[variable])
  237. plt.ylabel(r'$|\eta|$')
  238. @mpb.decl_fig
  239. def plot_hit_vs_layer(sample, region):
  240. load_samples()
  241. if region == 'BPIX':
  242. region = 'barrel'
  243. if region == 'FPIX':
  244. region = 'forward'
  245. h = Hist2D(samples[sample][f'hit_vs_layer_{region}'])
  246. plot_2d(h, colz_fmt='2.0f')
  247. plt.xlabel('Layer #')
  248. plt.ylabel('Hit #')
  249. @mpb.decl_fig
  250. def plot_roc_curve(pfx, ext=''):
  251. load_samples()
  252. show_fr = pfx == "tracking"
  253. def get_num_den(sample, basename):
  254. num = Hist1D(sample[f'{basename}_num'])
  255. den = Hist1D(sample[f'{basename}_den'])
  256. return hist_integral_ratio(num, den)
  257. rows = []
  258. row_labels = []
  259. for i, proc in enumerate(procs):
  260. plt.subplot(len(procs), 1, i+1)
  261. row_labels.append(procs[proc])
  262. row_labels.extend(['']*(len(wps)*len(configs)-2))
  263. for wp, config in product(wps, configs):
  264. sample = samples[(proc, wp, config)]
  265. sample_name = f'{proc}-{wp}-{config}'
  266. if wp == 'old-default' and config == 'noskip': continue
  267. eff, eff_err = get_num_den(sample, f'{pfx}_eff_v_phi{ext}')
  268. pur, pur_err = get_num_den(sample, f'{pfx}_pur_v_phi{ext}')
  269. if show_fr:
  270. fr, fr_err = get_num_den(sample, f'fake_rate_no_e_match_v_phi')
  271. rows.append([wp, config,
  272. rf'${eff*100:0.2f}\pm{eff_err*100:0.2f}\%$',
  273. rf'${pur*100:0.2f}\pm{pur_err*100:0.2f}\%$',
  274. rf'${fr*100:0.2f}\pm{fr_err*100:0.2f}\%$'])
  275. if config == 'skip-pileup':
  276. marker = 'o'
  277. elif config == 'noskip':
  278. marker = '*'
  279. else:
  280. marker = '^'
  281. # plt.errorbar([pur], [eff], xerr=[pur_err], yerr=[eff_err],
  282. # label=sample_name, marker=marker, color=color(proc, wp))
  283. plt.scatter([pur], [eff], label=sample_name, marker=marker, color=color(proc, wp))
  284. # center_text(0.3, 0.3, r'$p_T>20$ and $|\eta|<2.5$')
  285. # plt.axis('equal')
  286. plt.xlim((0.5, 1.02))
  287. plt.ylim((0.5, 1.02))
  288. # plt.xlim((0, 1.02))
  289. # plt.ylim((0.7, 1.02))
  290. plt.ylabel('Efficiency')
  291. plt.grid()
  292. plt.legend(loc='lower right', ncol=1, fancybox=True, numpoints=1)
  293. plt.xlabel('Purity')
  294. col_labels = ['Sample', 'Working Point', 'Config', 'Efficiency', 'Purity']
  295. if show_fr:
  296. col_labels.append("Fake Rate")
  297. return to_html_table(rows, col_labels, row_labels, 'table-condensed')
  298. @mpb.decl_fig
  299. def plot_kinematic_eff(pref, proc, config, ext='', ylim=(None, None), norm=None, label_pfx='', incl_sel=True,
  300. bins_pt=None, bins_eta=None, bins_phi=None, bins_PU=None,
  301. xlim_pt=(None, None), xlim_eta=(None, None), xlim_phi=(None, None),
  302. is_ratio=False):
  303. load_samples()
  304. # Figure out if this one has v_PU
  305. has_PU = f'{pref}_v_PU{ext}' in list(samples.values())[0]
  306. ax_pt = plt.subplot(221)
  307. ax_eta = plt.subplot(222)
  308. ax_phi = plt.subplot(223)
  309. if has_PU:
  310. ax_PU = plt.subplot(224)
  311. errors = True
  312. for (proc_, wp, config_), sample in samples.items():
  313. if proc != proc_ or config != config_: continue
  314. sample_name = f'{proc}-{wp}-{config}'
  315. l = sample_name
  316. c = color(proc, wp)
  317. def do_plot(ax, name, bins):
  318. plt.sca(ax)
  319. if is_ratio:
  320. num = Hist1D(sample[name+"_num"], no_overflow=True)
  321. den = Hist1D(sample[name+"_den"], no_overflow=True)
  322. if bins:
  323. num.rebin(bins)
  324. den.rebin(bins)
  325. h = num // den
  326. else:
  327. h = Hist1D(sample[name], no_overflow=True)
  328. if norm:
  329. h = h / (norm*h.integral)
  330. if bins is not None:
  331. h.rebin(bins)
  332. hist_plot(h, include_errors=errors, label=l, color=c, linestyle=style(config))
  333. do_plot(ax_pt, f'{pref}_v_pt{ext}', bins_pt)
  334. do_plot(ax_eta, f'{pref}_v_eta{ext}', bins_eta)
  335. do_plot(ax_phi, f'{pref}_v_phi{ext}', bins_phi)
  336. if has_PU:
  337. do_plot(ax_PU, f'{pref}_v_PU{ext}', [-0.5, 20, 30, 40, 50, 60, 70, 80, 100.5])
  338. plt.sca(ax_pt)
  339. if not incl_sel: center_text(0.5, 0.15, r'$|\eta|<2.5$')
  340. plt.xlabel(fr"{label_pfx} $p_T$")
  341. plt.ylim(ylim)
  342. plt.xlim(xlim_pt)
  343. plt.sca(ax_eta)
  344. if not incl_sel: center_text(0.5, 0.15, r'$p_T>20$')
  345. plt.xlabel(fr"{label_pfx} $\eta$")
  346. plt.ylim(ylim)
  347. plt.xlim(xlim_eta)
  348. plt.sca(ax_phi)
  349. if not incl_sel: center_text(0.5, 0.15, r'$p_T>20$ and $|\eta|<2.5$')
  350. plt.xlabel(fr"{label_pfx} $\phi$")
  351. plt.ylim(ylim)
  352. plt.xlim(xlim_phi)
  353. if has_PU:
  354. plt.sca(ax_PU)
  355. if not incl_sel: center_text(0.5, 0.15, r'$p_T>20$ and $|\eta|<2.5$')
  356. plt.xlabel("# Pile-up Interactions")
  357. plt.ylim(ylim)
  358. plt.tight_layout()
  359. plt.sca(ax_eta)
  360. plt.legend(loc='best', prop={'size': 10})
  361. else:
  362. plt.tight_layout()
  363. plt.legend(loc='upper left', bbox_to_anchor=(0.6, 0.45), bbox_transform=plt.gcf().transFigure,
  364. prop={'size': 15})
  365. @mpb.decl_fig
  366. def plot_kinematic_eff2d(pref, proc, config, ext=''):
  367. from math import sqrt, ceil
  368. load_samples()
  369. n_col = ceil(sqrt(len(wps)))
  370. n_row = ceil(len(wps) / n_col)
  371. plt_idx = 0
  372. for (proc_, wp, config_), sample in samples.items():
  373. if proc != proc_ or config != config_: continue
  374. sample_name = f'{proc}-{wp}-{config}'
  375. plt_idx += 1
  376. plt.subplot(n_row, n_col, plt_idx)
  377. h = Hist2D(sample[f'{pref}_v_eta_phi{ext}'], no_overflow=True)
  378. h.rebin(div_bins_x=4)
  379. plot_2d(h)
  380. plt.text(0.1, 0.1, sample_name,
  381. transform=plt.gca().transAxes, size=15, backgroundcolor='#FFFFFFA0')
  382. if (plt_idx-1) % n_col == 0: # left col of plots
  383. plt.ylabel(r'$\phi$')
  384. if plt_idx > n_col*(n_row-1): # bottom row of plots
  385. plt.xlabel(r'$\eta$')
  386. @mpb.decl_fig
  387. def plot_ecal_rel_res():
  388. load_samples()
  389. for sample_name, sample in samples.items():
  390. h = Hist1D(sample['ecal_energy_resolution'])
  391. try:
  392. h = h / h.integral
  393. hist_plot(h, label=sample_name)
  394. except ZeroDivisionError:
  395. pass
  396. plt.xlabel(r"ECAL $E_T$ relative error")
  397. plt.legend()
  398. @mpb.decl_fig
  399. def plot_res_contour(proc, hit_number, var, layers, ext='_TrackMatched'):
  400. load_samples()
  401. _, axs = plt.subplots(1, 2, sharey=True)
  402. def do_plot(ax, sample):
  403. plt.sca(ax)
  404. wp = sample[1]
  405. plt.title(wp)
  406. h = None
  407. for subdet, layer in layers:
  408. h = Hist2D(samples[sample][f'{var}_{subdet}_L{layer}_H{hit_number}_v_Et{ext}'])
  409. xs, ys = hist2d_percent_contour(h, .99, 'x')
  410. plt.plot(xs, ys, label=f'{subdet} - L{layer}')
  411. ets = h.edges[1]
  412. cuts = [calc_window(et, 0, hit_number, var, wp) for et in ets]
  413. plt.plot(cuts, ets, color='k', label='Cut Value')
  414. for ax, wp in zip(axs, ['new-default-noskip', 'new-wide-noskip']):
  415. do_plot(ax, (proc, wp))
  416. plt.sca(axs[-1])
  417. plt.legend(loc='upper right')
  418. @mpb.decl_fig
  419. def simple_dist(hist_name, proc=None, wp=None, config=None,
  420. rebin=(), norm=1, xlabel="", ylabel="", xlim=None, ylim=None, line_width=1):
  421. load_samples()
  422. for (proc_, wp_, config_), sample in samples.items():
  423. if proc and proc_ != proc: continue
  424. if wp and wp_ != wp: continue
  425. if config and config_ != config: continue
  426. sample_name = f'{proc_}-{wp_}-{config_}'
  427. h = Hist1D(sample[hist_name])
  428. if rebin:
  429. h.rebin(*rebin)
  430. mean = np.sum(h.counts * h.bin_centers) / h.integral
  431. try:
  432. if norm is not None:
  433. h = h * (norm / h.integral)
  434. hist_plot(h, label=f'{sample_name} ($\\mu={mean:.2f}$)',
  435. color=color(proc_, wp_), line_width=line_width, linestyle=style(config_))
  436. except ZeroDivisionError:
  437. pass
  438. if xlim:
  439. plt.xlim(xlim)
  440. if ylim:
  441. plt.ylim(ylim)
  442. plt.xlabel(xlabel)
  443. plt.ylabel(ylabel)
  444. plt.legend(fontsize=20)
  445. @mpb.decl_fig
  446. def simple_dist2d(hist_name, proc, wp, config, norm=None, colz_fmt='g', clear_zero=False, **kwargs):
  447. load_samples()
  448. sample = samples[(proc, wp, config)]
  449. h = Hist2D(sample[hist_name])
  450. if norm is not None:
  451. h = h * (norm / h.integral)
  452. if clear_zero:
  453. h.counts[0, 0] = 0
  454. plot_2d(h, colz_fmt=colz_fmt, cmap='viridis', **kwargs)
  455. def all_cut_plots(build=True, publish=False):
  456. figures = {
  457. 'tracking_roc_curve': plot_roc_curve('tracking'),
  458. 'tracking_roc_curve_dR': plot_roc_curve('tracking', ext='_dR'),
  459. 'seeding_roc_curve': plot_roc_curve('seed'),
  460. }
  461. for proc, config in product(procs, configs):
  462. figures[f'number_of_seeds_{proc}_{config}'] = simple_dist('n_seeds', rebin=(50, -0.5, 200.5),
  463. xlabel='Number of Seeds', proc=proc, config=config)
  464. figures[f'number_of_good_seeds_{proc}_{config}'] = simple_dist('n_good_seeds', rebin=(50, -0.5, 200.5),
  465. xlabel='Number of Seeds', proc=proc, config=config)
  466. figures[f'number_of_scls_{proc}_{config}'] = simple_dist('n_scl', xlabel='Number of Super-Clusters',
  467. xlim=(-0.5, 25.5), proc=proc, config=config)
  468. figures[f'number_of_good_scls_{proc}_{config}'] = simple_dist('n_good_scl', xlabel='Number of Super-Clusters',
  469. xlim=(-0.5, 25.5), proc=proc, config=config)
  470. figures[f'number_of_sim_els_{proc}_{config}'] = simple_dist('n_good_sim', xlabel='Number of prompt(ish) electrons',
  471. xlim=(-0.5, 20.5), proc=proc, config=config)
  472. figures[f'number_of_gsf_tracks_{proc}_{config}'] = simple_dist('n_gsf_track', xlabel='Number of reco electrons',
  473. xlim=(-0.5, 20.5), proc=proc, config=config)
  474. figures[f'number_of_prompt_{proc}_{config}'] = simple_dist('n_prompt', xlabel='Number of prompt electrons',
  475. xlim=(-0.5, 20.5), proc=proc, config=config)
  476. figures[f'number_of_nonprompt_{proc}_{config}'] = simple_dist('n_nonprompt', xlabel='Number of nonprompt electrons',
  477. xlim=(-0.5, 20.5), proc=proc, config=config)
  478. figures[f'number_of_matched_{proc}_{config}'] = simple_dist('n_matched_dR', xlabel='Number of matched electrons',
  479. xlim=(-0.5, 10.5), line_width=4, proc=proc, config=config)
  480. figures[f'number_of_merged_{proc}_{config}'] = simple_dist('n_merged_dR', xlabel='Number of merged electrons',
  481. xlim=(-0.5, 10.5), line_width=4, proc=proc, config=config)
  482. figures[f'number_of_lost_{proc}_{config}'] = simple_dist('n_lost_dR', xlabel='Number of lost electrons',
  483. xlim=(-0.5, 10.5), line_width=4, proc=proc, config=config)
  484. figures[f'number_of_split_{proc}_{config}'] = simple_dist('n_split_dR', xlabel='Number of split electrons',
  485. xlim=(-0.5, 10.5), line_width=4, proc=proc, config=config)
  486. figures[f'number_of_faked_{proc}_{config}'] = simple_dist('n_faked_dR', xlabel='Number of faked electrons',
  487. xlim=(-0.5, 10.5), line_width=4, proc=proc, config=config)
  488. figures[f'number_of_flipped_{proc}_{config}'] = simple_dist('n_flipped_dR', xlabel='Number of flipped electrons',
  489. xlim=(-0.5, 10.5), line_width=4, proc=proc, config=config)
  490. figures[f'matched_dR_{proc}_{config}'] = simple_dist('matched_dR', xlabel='dR between sim and reco',
  491. proc=proc, config=config)
  492. figures[f'matched_dpT_{proc}_{config}'] = simple_dist('matched_dpT', xlabel='dpT between sim and reco',
  493. proc=proc, config=config)
  494. for wp in wps:
  495. figures[f'hit_v_layer_BPIX_{proc}_{wp}_{config}'] = plot_hit_vs_layer((proc, wp, config), 'barrel')
  496. figures[f'hit_v_layer_FPIX_{proc}_{wp}_{config}'] = plot_hit_vs_layer((proc, wp, config), 'forward')
  497. for proc, config in product(procs, configs):
  498. bins_pt = np.linspace(0, 100, 30)
  499. figures[f'good_sim_kinem_{proc}_{config}'] = plot_kinematic_eff('good_sim', proc, config, norm=1, ylim=(0, None),
  500. bins_eta=30, bins_phi=30, bins_pt=bins_pt)
  501. figures[f'good_sim_kinem2d_{proc}_{config}'] = plot_kinematic_eff2d('good_sim', proc, config)
  502. figures[f'gsf_track_kinem_{proc}_{config}'] = plot_kinematic_eff('gsf_track', proc, config, norm=1, ylim=(0, None),
  503. bins_eta=30, bins_phi=30, bins_pt=bins_pt)
  504. figures[f'gsf_track_kinem2d_{proc}_{config}'] = plot_kinematic_eff2d('gsf_track', proc, config)
  505. figures[f'gsf_high_pt1_kinem_{proc}_{config}'] = plot_kinematic_eff('gsf_high_pt1', proc, config,
  506. norm=1, ylim=(0, None), bins_eta=30,
  507. bins_phi=30, bins_pt=bins_pt)
  508. figures[f'gsf_high_pt1_kinem2d_{proc}_{config}'] = plot_kinematic_eff2d('gsf_high_pt1', proc, config)
  509. figures[f'gsf_high_pt2_kinem_{proc}_{config}'] = plot_kinematic_eff('gsf_high_pt2', proc, config,
  510. norm=1, ylim=(0, None), bins_eta=30,
  511. bins_phi=30, bins_pt=bins_pt)
  512. figures[f'gsf_high_pt2_kinem2d_{proc}_{config}'] = plot_kinematic_eff2d('gsf_high_pt2', proc, config)
  513. # for proc, wp, region in product(procs, wps, ('BPIX', 'FPIX')):
  514. # figures[f'hit_v_layer_{region}_{wp}_{proc}'] = plot_hit_vs_layer((proc, wp), region)
  515. for proc, config in product(procs, configs):
  516. def add_num_den(key, func, args, kwargs):
  517. key = f'{key}_{proc}_{config}'
  518. base_ext = kwargs.get('ext', '')
  519. bins_pt_ = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200, 300]
  520. kwargs['bins_pt'] = kwargs.get('bins_pt', bins_pt_)
  521. kwargs['bins_eta'] = kwargs.get('bins_eta', 15)
  522. kwargs['bins_phi'] = kwargs.get('bins_phi', 15)
  523. args = *args, proc, config
  524. figures[key] = func(*args, ylim=(0, 1.1), is_ratio=True, **kwargs)
  525. kwargs_ = kwargs.copy()
  526. kwargs_['ext'] = base_ext+'_num'
  527. figures[key+'_num'] = func(*args, ylim=(0, None), **kwargs_)
  528. kwargs_ = kwargs.copy()
  529. kwargs_['ext'] = base_ext+'_den'
  530. figures[key+'_den'] = func(*args, ylim=(0, None), **kwargs_)
  531. add_num_den('tracking_eff_dR', plot_kinematic_eff, ('tracking_eff',), dict(ext='_dR', incl_sel=False))
  532. add_num_den('tracking_pur_dR', plot_kinematic_eff, ('tracking_pur',), dict(ext='_dR', incl_sel=False))
  533. # add_num_den('prompt_eff_dR', plot_kinematic_eff, ('prompt_eff',), dict(ext='_dR', incl_sel=False))
  534. # add_num_den('prompt_pur_dR', plot_kinematic_eff, ('prompt_pur',), dict(ext='_dR', incl_sel=False))
  535. # add_num_den('nonprompt_eff_dR', plot_kinematic_eff, ('nonprompt_eff',), dict(ext='_dR', incl_sel=False))
  536. # add_num_den('nonprompt_pur_dR', plot_kinematic_eff, ('nonprompt_pur',), dict(ext='_dR', incl_sel=False))
  537. add_num_den('seeding_eff', plot_kinematic_eff, ('seed_eff',), dict(incl_sel=False))
  538. add_num_den('seeding_pur', plot_kinematic_eff, ('seed_pur',), dict(incl_sel=False))
  539. add_num_den('fake_rate_incl', plot_kinematic_eff, ('fake_rate_incl',), {})
  540. add_num_den('fake_rate_no_e_match_incl', plot_kinematic_eff, ('fake_rate_no_e_match_incl',), {})
  541. add_num_den('partial_fake_rate_incl', plot_kinematic_eff, ('partial_fake_rate_incl',), {})
  542. add_num_den('full_fake_rate_incl', plot_kinematic_eff, ('full_fake_rate_incl',), {})
  543. add_num_den('clean_fake_rate_incl', plot_kinematic_eff, ('clean_fake_rate_incl',), {})
  544. add_num_den('fake_rate', plot_kinematic_eff, ('fake_rate',), dict(incl_sel=False))
  545. add_num_den('fake_rate_no_e_match', plot_kinematic_eff, ('fake_rate_no_e_match',), dict(incl_sel=False))
  546. add_num_den('partial_fake_rate', plot_kinematic_eff, ('partial_fake_rate',), dict(incl_sel=False))
  547. add_num_den('full_fake_rate', plot_kinematic_eff, ('full_fake_rate',), dict(incl_sel=False))
  548. add_num_den('clean_fake_rate', plot_kinematic_eff, ('clean_fake_rate',), dict(incl_sel=False))
  549. # hit_layers = [(1, 1), (1, 2), (2, 2), (2, 3), (3, 3), (3, 4)]
  550. # for proc, wp, (hit, layer), var, subdet in product(['dy', 'tt'], ['new-default-noskip', 'new-wide-noskip'],
  551. # hit_layers, ['dPhi', 'dRz'], ['BPIX', 'FPIX']):
  552. # figures[f'res_{subdet}_L{layer}_H{hit}_{var}_{proc}_{wp}'] = plot_residuals((proc, wp), layer, hit, var, subdet)
  553. # rel_layers = {1: [('BPIX', 1), ('BPIX', 2), ('FPIX', 1), ('FPIX', 2)],
  554. # 2: [('BPIX', 2), ('BPIX', 3), ('FPIX', 2), ('FPIX', 3)],
  555. # 3: [('BPIX', 3), ('BPIX', 4), ('FPIX', 3)], }
  556. # for proc, hit, var in product(['dy', 'tt'], [1, 2, 3], ['dPhi', 'dRz']):
  557. # figures[f'resall_H{hit}_{var}_{proc}'] = plot_res_contour(proc, hit, var, rel_layers[hit])
  558. # for proc, wp, hit, var in product(['dy', 'tt'], ['new-default-noskip', 'new-wide-noskip'], [1, 2, 3], ['dPhi', 'dRz']):
  559. # figures[f'res_v_eta_H{hit}_{var}_{proc}_{wp}'] = plot_residuals_eta((proc, wp), hit, var)
  560. def add_simple_plot(proc, wp, config, plot_name, xlabel, ylabel, is2d=False, xlim=None, ylim=None, clear_zero=False):
  561. if is2d:
  562. figures[f'{plot_name}_{proc}_{wp}_{config}'] = \
  563. simple_dist2d(plot_name, proc, wp, config, colz_fmt='', xlabel=xlabel, ylabel=ylabel, do_profile=True,
  564. xlim=xlim, ylim=ylim, clear_zero=clear_zero)
  565. else:
  566. figures[f'{plot_name}_{proc}_{wp}_{config}'] = \
  567. simple_dist(plot_name, proc, wp, config, xlabel=xlabel, ylabel=ylabel, xlim=xlim, ylim=ylim)
  568. for proc, wp, config, in product(procs, wps, configs):
  569. # add_simple_plot(proc, wp, 'n_pileup')
  570. add_simple_plot(proc, wp, config, 'n_initseeds_v_PU', '# Initial Seeds', '# In-Time Pileup', True)
  571. add_simple_plot(proc, wp, config, 'n_seeds_v_PU', '# Seeds', '# In-Time Pileup', True)
  572. add_simple_plot(proc, wp, config, 'n_good_seeds_v_PU', '# Seeds', '# In-Time Pileup', True, xlim=(-0.5, 40.5))
  573. add_simple_plot(proc, wp, config, 'n_tracks_v_PU', '# GSF Tracks', '# In-Time Pileup', True, xlim=(-0.5, 20.5))
  574. # add_simple_plot(proc, wp, config, 'n_pv_v_PU', '# PV', '# In-Time Pileup', True, xlim=(-0.5, 50.5)) # garbage
  575. # add_simple_plot(proc, wp, config, 'n_seeds_v_tPU', '# Seeds', '# True Pileup', True)
  576. # add_simple_plot(proc, wp, config, 'n_good_seeds_v_tPU', '# Seeds', '# True Pileup', True, xlim=(-0.5, 40.5))
  577. # add_simple_plot(proc, wp, config, 'n_tracks_v_tPU', '# GSF Tracks', '# True Pileup', True, xlim=(-0.5, 20.5))
  578. # add_simple_plot(proc, wp, config, 'n_pv_v_tPU', '# PV', '# True Pileup', True, xlim=(-0.5, 50.5))
  579. # add_simple_plot(proc, wp, config, 'n_seeds_v_n_scl', '# Seeds', '# Super Clusters', True,
  580. # xlim=(-0.5, 20.5), ylim=(-0.5, 20.5), clear_zero=False)
  581. add_simple_plot(proc, wp, config, 'n_good_seeds_v_n_scl', '# Good Seeds', '# Super Clusters', True,
  582. xlim=(-0.5, 20.5), ylim=(-0.5, 20.5), clear_zero=False)
  583. # add_simple_plot(proc, wp, config, 'n_good_seeds_v_n_good_scl', '# Good Seeds', '# Good Super Clusters', True,
  584. # xlim=(-0.5, 20.5), ylim=(-0.5, 20.5), clear_zero=False)
  585. # add_simple_plot(proc, wp, config, 'n_initseeds_v_PU', '# Initial Seeds', '# In-Time Pileup', True,
  586. # xlim=None, ylim=None, clear_zero=False)
  587. # add_simple_plot(proc, wp, config, 'n_initseeds_v_tPU', '# Initial Seeds', '# True Pileup', True,
  588. # xlim=None, ylim=None, clear_zero=False)
  589. mpb.render(figures, build=build)
  590. mpb.generate_report(figures, 'Electron Seeding Studies',
  591. output=f'hists.html',
  592. source=__file__)
  593. # mpb.generate_report(figures, 'Fixing Hit Skipping',
  594. # output='report.html',
  595. # body='../docs/reports/report_2018_08_16.md')
  596. if publish:
  597. mpb.publish()
  598. def color(proc, wp):
  599. from matplotlib.colors import XKCD_COLORS
  600. def f(name):
  601. return XKCD_COLORS['xkcd:'+name]
  602. wp = wp.replace('-skip', '')
  603. wp = wp.replace('-noskip', '')
  604. wp = wp.replace('-pileup', '')
  605. return {
  606. ('dy', 'new-extra-narrow'): f('indigo'),
  607. ('tt', 'new-extra-narrow'): f('bright purple'),
  608. ('dy', 'new-default'): f('red'),
  609. ('tt', 'new-default'): f('pink'),
  610. ('dy', 'new-wide'): f('strong blue'),
  611. ('tt', 'new-wide'): f('bright blue'),
  612. ('dy', 'new-extra-wide'): f('kelly green'),
  613. ('tt', 'new-extra-wide'): f('green'),
  614. ('dy', 'old-default'): f('black'),
  615. ('tt', 'old-default'): f('blue grey'),
  616. }[(proc, wp)]
  617. def style(config):
  618. return {
  619. 'noskip': '-',
  620. 'skip': '--',
  621. 'skip-pileup': '-.',
  622. }[config]
  623. if __name__ == '__main__':
  624. parser = ArgumentParser('Electron Seeding Efficiency Plot Maker')
  625. parser.add_argument('--build', action='store_true')
  626. parser.add_argument('--publish', action='store_true')
  627. args = parser.parse_args()
  628. set_defaults()
  629. mpb.configure(output_dir='seeding_studies',
  630. multiprocess=True,
  631. publish_remote="cfangmeier@t3.unl.edu",
  632. publish_dir="/home/dominguez/cfangmeier/public_html/eg/",
  633. publish_url="t3.unl.edu/~cfangmeier/eg/",
  634. early_abort=True,
  635. )
  636. procs = {
  637. 'dy': r'Drell-Yan',
  638. 'tt': r'$t\bar{t}$'
  639. }
  640. configs = [
  641. 'noskip',
  642. 'skip',
  643. 'skip-pileup',
  644. ]
  645. wps = {
  646. 'old-default': 'Old-Method Seeding',
  647. # 'new-narrow': 'HLT Settings',
  648. 'new-default': 'HLT Settings',
  649. 'new-wide': 'Wide Settings',
  650. 'new-extra-wide': 'Extra Wide Settings',
  651. }
  652. all_cut_plots(build=args.build, publish=args.publish)