eff_plots.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. #!/usr/bin/env python
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. from filval.result_set import ResultSet
  5. from filval.histogram import hist, hist_integral, hist_rebin, hist_norm, hist2d, hist2d_percent_contour
  6. from filval.plotting import (decl_plot, render_plots, hist_plot, hist2d_plot,
  7. Plot, generate_dashboard, simple_plot)
  8. matching_cuts = {
  9. 'extra-narrow-window': [
  10. dict(
  11. dPhiMaxHighEt=0.025,
  12. dPhiMaxHighEtThres=20.0,
  13. dPhiMaxLowEtGrad=-0.002,
  14. dRzMaxHighEt=9999.0,
  15. dRzMaxHighEtThres=0.0,
  16. dRzMaxLowEtGrad=0.0,
  17. ),
  18. dict(
  19. dPhiMaxHighEt=0.0015,
  20. dPhiMaxHighEtThres=0.0,
  21. dPhiMaxLowEtGrad=0.0,
  22. dRzMaxHighEt=0.025,
  23. dRzMaxHighEtThres=30.0,
  24. dRzMaxLowEtGrad=-0.002,
  25. ),
  26. dict(
  27. dPhiMaxHighEt=0.0015,
  28. dPhiMaxHighEtThres=0.0,
  29. dPhiMaxLowEtGrad=0.0,
  30. dRzMaxHighEt=0.025,
  31. dRzMaxHighEtThres=30.0,
  32. dRzMaxLowEtGrad=-0.002,
  33. )
  34. ],
  35. 'narrow-window': [
  36. dict(
  37. dPhiMaxHighEt=0.05,
  38. dPhiMaxHighEtThres=20.0,
  39. dPhiMaxLowEtGrad=-0.002,
  40. dRzMaxHighEt=9999.0,
  41. dRzMaxHighEtThres=0.0,
  42. dRzMaxLowEtGrad=0.0,
  43. ),
  44. dict(
  45. dPhiMaxHighEt=0.003,
  46. dPhiMaxHighEtThres=0.0,
  47. dPhiMaxLowEtGrad=0.0,
  48. dRzMaxHighEt=0.05,
  49. dRzMaxHighEtThres=30.0,
  50. dRzMaxLowEtGrad=-0.002,
  51. ),
  52. dict(
  53. dPhiMaxHighEt=0.003,
  54. dPhiMaxHighEtThres=0.0,
  55. dPhiMaxLowEtGrad=0.0,
  56. dRzMaxHighEt=0.05,
  57. dRzMaxHighEtThres=30.0,
  58. dRzMaxLowEtGrad=-0.002,
  59. )
  60. ],
  61. 'wide-window': [
  62. dict(
  63. dPhiMaxHighEt=0.10,
  64. dPhiMaxHighEtThres=20.0,
  65. dPhiMaxLowEtGrad=-0.002,
  66. dRzMaxHighEt=9999.0,
  67. dRzMaxHighEtThres=0.0,
  68. dRzMaxLowEtGrad=0.0,
  69. ),
  70. dict(
  71. dPhiMaxHighEt=0.006,
  72. dPhiMaxHighEtThres=0.0,
  73. dPhiMaxLowEtGrad=0.0,
  74. dRzMaxHighEt=0.10,
  75. dRzMaxHighEtThres=30.0,
  76. dRzMaxLowEtGrad=-0.002,
  77. ),
  78. dict(
  79. dPhiMaxHighEt=0.006,
  80. dPhiMaxHighEtThres=0.0,
  81. dPhiMaxLowEtGrad=0.0,
  82. dRzMaxHighEt=0.10,
  83. dRzMaxHighEtThres=30.0,
  84. dRzMaxLowEtGrad=-0.002,
  85. )
  86. ],
  87. 'extra-wide-window': [
  88. dict(
  89. dPhiMaxHighEt=0.15,
  90. dPhiMaxHighEtThres=20.0,
  91. dPhiMaxLowEtGrad=-0.002,
  92. dRzMaxHighEt=9999.0,
  93. dRzMaxHighEtThres=0.0,
  94. dRzMaxLowEtGrad=0.0,
  95. ),
  96. dict(
  97. dPhiMaxHighEt=0.009,
  98. dPhiMaxHighEtThres=0.0,
  99. dPhiMaxLowEtGrad=0.0,
  100. dRzMaxHighEt=0.15,
  101. dRzMaxHighEtThres=30.0,
  102. dRzMaxLowEtGrad=-0.002,
  103. ),
  104. dict(
  105. dPhiMaxHighEt=0.009,
  106. dPhiMaxHighEtThres=0.0,
  107. dPhiMaxLowEtGrad=0.0,
  108. dRzMaxHighEt=0.15,
  109. dRzMaxHighEtThres=30.0,
  110. dRzMaxLowEtGrad=-0.002,
  111. )
  112. ],
  113. 'nwp-tight-window': [
  114. dict(
  115. dPhiMaxHighEt=0.025,
  116. dPhiMaxHighEtThres=20.0,
  117. dPhiMaxLowEtGrad=-0.002,
  118. dRzMaxHighEt=9999.0,
  119. dRzMaxHighEtThres=0.0,
  120. dRzMaxLowEtGrad=0.0,
  121. ),
  122. dict(
  123. dPhiMaxHighEt=0.005,
  124. dPhiMaxHighEtThres=0.0,
  125. dPhiMaxLowEtGrad=0.0,
  126. dRzMaxHighEt=0.07,
  127. dRzMaxHighEtThres=30.0,
  128. dRzMaxLowEtGrad=-0.002,
  129. ),
  130. dict(
  131. dPhiMaxHighEt=0.006,
  132. dPhiMaxHighEtThres=20.0,
  133. dPhiMaxLowEtGrad=-0.0001,
  134. dRzMaxHighEt=0.08,
  135. dRzMaxHighEtThres=30.0,
  136. dRzMaxLowEtGrad=-0.002,
  137. )
  138. ],
  139. 'nwp-window': [
  140. dict(
  141. dPhiMaxHighEt=0.05,
  142. dPhiMaxHighEtThres=20.0,
  143. dPhiMaxLowEtGrad=-0.002,
  144. dRzMaxHighEt=9999.0,
  145. dRzMaxHighEtThres=0.0,
  146. dRzMaxLowEtGrad=0.0,
  147. ),
  148. dict(
  149. dPhiMaxHighEt=0.005,
  150. dPhiMaxHighEtThres=0.0,
  151. dPhiMaxLowEtGrad=0.0,
  152. dRzMaxHighEt=0.07,
  153. dRzMaxHighEtThres=30.0,
  154. dRzMaxLowEtGrad=-0.002,
  155. ),
  156. dict(
  157. dPhiMaxHighEt=0.006,
  158. dPhiMaxHighEtThres=20.0,
  159. dPhiMaxLowEtGrad=-0.0001,
  160. dRzMaxHighEt=0.08,
  161. dRzMaxHighEtThres=30.0,
  162. dRzMaxLowEtGrad=-0.002,
  163. )
  164. ],
  165. 'nwp-eta-breakdown': [
  166. dict(
  167. dPhiMaxHighEt=[0.05, 0.07, 0.06],
  168. dPhiMaxHighEtThres=[25.0, 25.0, 25.0],
  169. dPhiMaxLowEtGrad=[-0.002, -0.006, -0.002],
  170. dRzMaxHighEt=[9999.0, 9999.0, 9999.0],
  171. dRzMaxHighEtThres=[0.0, 0.0, 0.0],
  172. dRzMaxLowEtGrad=[0.0, 0.0, 0.0],
  173. etaBins = [1.1, 1.8]
  174. ),
  175. dict(
  176. dPhiMaxHighEt=[0.0035, 0.006, 0.007],
  177. dPhiMaxHighEtThres=[0.0, 0.0, 0.0],
  178. dPhiMaxLowEtGrad=[0.0, 0.0, 0.0],
  179. dRzMaxHighEt=[0.045, 0.08, 0.045],
  180. dRzMaxHighEtThres=[30.0, 30.0, 30.0],
  181. dRzMaxLowEtGrad=[-0.002, -0.006, -0.002],
  182. etaBins=[1.4, 2.3]
  183. ),
  184. dict(
  185. dPhiMaxHighEt=[0.006, 0.007, 0.007],
  186. dPhiMaxHighEtThres=[0.0, 20, 20],
  187. dPhiMaxLowEtGrad=[0.0, -0.0002, -0.0002],
  188. dRzMaxHighEt=[0.04, 0.10, 0.60],
  189. dRzMaxHighEtThres=[25.0, 25.0, 25.0],
  190. dRzMaxLowEtGrad=[-0.007, -0.007, -0.007],
  191. etaBins=[1.0, 2.0]
  192. )
  193. ],
  194. }
  195. def calc_window(et, eta, hit, variable, cut_sel):
  196. idx = min(hit-1, 2)
  197. cuts = matching_cuts[cut_sel][idx]
  198. if 'etaBins' in cuts:
  199. for eta_idx, bin_high in enumerate(cuts['etaBins']):
  200. if eta < bin_high:
  201. high_et = cuts[f'{variable}MaxHighEt'][eta_idx]
  202. high_et_thres = cuts[f'{variable}MaxHighEtThres'][eta_idx]
  203. low_et_grad = cuts[f'{variable}MaxLowEtGrad'][eta_idx]
  204. break
  205. else: # highest bin
  206. high_et = cuts[f'{variable}MaxHighEt'][-1]
  207. high_et_thres = cuts[f'{variable}MaxHighEtThres'][-1]
  208. low_et_grad = cuts[f'{variable}MaxLowEtGrad'][-1]
  209. else:
  210. high_et = cuts[f'{variable}MaxHighEt']
  211. high_et_thres = cuts[f'{variable}MaxHighEtThres']
  212. low_et_grad = cuts[f'{variable}MaxLowEtGrad']
  213. return high_et + min(0, et-high_et_thres)*low_et_grad
  214. def center_text(x, y, txt, **kwargs):
  215. plt.text(x, y, txt,
  216. horizontalalignment='center', verticalalignment='center',
  217. transform=plt.gca().transAxes, **kwargs)
  218. def hist_integral_ratio(num, den):
  219. num_int = hist_integral(num, times_bin_width=False)
  220. den_int = hist_integral(den, times_bin_width=False)
  221. ratio = num_int / den_int
  222. error = np.sqrt(den_int) / den_int # TODO: Check this definition of error
  223. return ratio, error
  224. @decl_plot
  225. def plot_residuals(rs, layer, hit, variable, subdet, cut_sel=None):
  226. h_real = hist2d(getattr(rs, f'{variable}_{subdet}_L{layer}_H{hit}_v_Et_TrackMatched'))
  227. h_fake = hist2d(getattr(rs, f'{variable}_{subdet}_L{layer}_H{hit}_v_Et_NoMatch'))
  228. def do_plot(h):
  229. hist2d_plot(h, colorbar=True)
  230. xs, ys = hist2d_percent_contour(h, .90, 'x')
  231. plt.plot(xs, ys, color='green', label='90\% contour')
  232. xs, ys = hist2d_percent_contour(h, .995, 'x')
  233. plt.plot(xs, ys, color='darkgreen', label='99.5\% contour')
  234. if cut_sel:
  235. ets = h[3][:, 0]
  236. cuts = [calc_window(et, 0, hit, variable, cut_sel) for et in ets]
  237. plt.plot(cuts, ets, color='red', label='Cut Value')
  238. plt.xlabel({'dPhi': r'$\delta \phi$ (rads)',
  239. 'dRz': r'$\delta R/z$ (cm)'}[variable])
  240. plt.sca(plt.subplot(1, 2, 1))
  241. do_plot(h_real)
  242. plt.title('Truth-Matched Seeds')
  243. plt.ylabel('$E_T$ (GeV)')
  244. plt.sca(plt.subplot(1, 2, 2))
  245. do_plot(h_fake)
  246. plt.title('Not Truth-Matched Seeds')
  247. plt.legend(loc='upper right')
  248. @decl_plot
  249. def plot_residuals_eta(rs, hit, variable):
  250. h = hist2d(getattr(rs, f'{variable}_residuals_v_eta_H{hit}'))
  251. hist2d_plot(h, colorbar=True)
  252. xs, ys = hist2d_percent_contour(h, .90, 'x')
  253. plt.plot(xs, ys, color='green', label='90\% contour')
  254. xs, ys = hist2d_percent_contour(h, .995, 'x')
  255. plt.plot(xs, ys, color='darkgreen', label='99.5\% contour')
  256. plt.xlabel({'dPhi': r'$\delta \phi$ (rads)',
  257. 'dRz': r'$\delta R/z$ (cm)'}[variable])
  258. plt.ylabel(r'$\eta$ (GeV)')
  259. @decl_plot
  260. def plot_seed_eff(rs):
  261. r"""## ECAL-Driven Seeding Efficiency
  262. The proportion of gen-level electrons originating in the luminous region that have
  263. an associated Seed, matched via rechit-simhit associations in the pixel detector. Cuts are on simtrack quantities.
  264. """
  265. ax_pt = plt.subplot(221)
  266. ax_eta = plt.subplot(222)
  267. ax_phi = plt.subplot(223)
  268. errors = True
  269. plt.sca(ax_pt)
  270. hist_plot(hist(rs.seed_eff_v_pt), include_errors=errors)
  271. center_text(0.5, 0.3, r'$|\eta|<2.4$')
  272. plt.xlabel(r"Sim-Track $p_T$")
  273. plt.ylim((0, 1.1))
  274. plt.sca(ax_eta)
  275. hist_plot(hist(rs.seed_eff_v_eta), include_errors=errors)
  276. center_text(0.5, 0.3, r'$p_T>20$')
  277. plt.xlabel(r"Sim-Track $\eta$")
  278. plt.ylim((0, 1.1))
  279. plt.sca(ax_phi)
  280. hist_plot(hist(rs.seed_eff_v_phi), include_errors=errors)
  281. center_text(0.5, 0.3, r'$p_T>20$ and $|\eta|<2.4$')
  282. plt.xlabel(r"Sim-Track $\phi$")
  283. plt.ylim((0, 1.1))
  284. @decl_plot
  285. def plot_tracking_eff(rs):
  286. r"""## GSF Tracking Efficiency
  287. The proportion of electrons origination in the luminous region from the that have
  288. an associated GSF track. Cuts are on simtrack quantities.
  289. """
  290. ax_pt = plt.subplot(221)
  291. ax_eta = plt.subplot(222)
  292. ax_phi = plt.subplot(223)
  293. ax_eta_pt = plt.subplot(224)
  294. errors = True
  295. plt.sca(ax_pt)
  296. hist_plot(hist(rs.tracking_eff_v_pt), include_errors=errors)
  297. center_text(0.5, 0.3, r'$|\eta|<2.4$')
  298. plt.xlabel(r"Sim-Track $p_T$")
  299. plt.ylim((0, 1.1))
  300. plt.sca(ax_eta)
  301. hist_plot(hist(rs.tracking_eff_v_eta), include_errors=errors)
  302. center_text(0.5, 0.3, r'$p_T>20$')
  303. plt.xlabel(r"Sim-Track $\eta$")
  304. plt.ylim((0, 1.1))
  305. plt.sca(ax_phi)
  306. hist_plot(hist(rs.tracking_eff_v_phi), include_errors=errors)
  307. center_text(0.5, 0.3, r'$p_T>20$ and $|\eta|<2.4$')
  308. plt.xlabel(r"Sim-Track $\phi$")
  309. plt.ylim((0, 1.1))
  310. plt.sca(ax_eta_pt)
  311. hist2d_plot(hist2d(rs.tracking_eff_v_eta_pt))
  312. plt.xlabel(r"Sim-Track $\eta$")
  313. plt.ylabel(r"Sim-Track $p_T$")
  314. plt.colorbar()
  315. @decl_plot
  316. def plot_seed_purity(rs, ext=""):
  317. r"""## ECAL-Driven Seed Purity
  318. The proportion of ECAL-driven seeds that have a matched gen-level electron originating in
  319. the luminous region. Cuts are on seed quantities.
  320. """
  321. ax_pt = plt.subplot(221)
  322. ax_eta = plt.subplot(222)
  323. ax_phi = plt.subplot(223)
  324. def get_hist(base_name):
  325. return hist(getattr(rs, base_name+ext))
  326. errors = True
  327. plt.sca(ax_pt)
  328. hist_plot(get_hist("seed_pur_v_pt"), include_errors=errors)
  329. center_text(0.5, 0.3, r'$|\eta|<2.4$')
  330. plt.xlabel(r"Seed $p_T$")
  331. if not ext:
  332. plt.ylim((0, 1.1))
  333. plt.sca(ax_eta)
  334. hist_plot(get_hist("seed_pur_v_eta"), include_errors=errors)
  335. center_text(0.5, 0.3, r'$p_T>20$')
  336. plt.xlabel(r"Seed $\eta$")
  337. if not ext:
  338. plt.ylim((0, 1.1))
  339. plt.sca(ax_phi)
  340. hist_plot(get_hist("seed_pur_v_phi"), include_errors=errors)
  341. center_text(0.5, 0.3, r'$p_T>20$ and $|\eta|<2.4$')
  342. plt.xlabel(r"Seed $\phi$")
  343. if not ext:
  344. plt.ylim((0, 1.1))
  345. @decl_plot
  346. def plot_track_purity(rs, ext=""):
  347. r"""## GSF Track Purity
  348. The proportion of GSF-tracks w\ ECAL-driven seeds that have a matched gen-level electron originating in
  349. the luminous region. Cuts are on GSF track quantities.
  350. """
  351. ax_pt = plt.subplot(221)
  352. ax_eta = plt.subplot(222)
  353. ax_phi = plt.subplot(223)
  354. def get_hist( base_name):
  355. return hist(getattr(rs, base_name+ext))
  356. errors = True
  357. plt.sca(ax_pt)
  358. hist_plot(get_hist("tracking_pur_v_pt"), include_errors=errors)
  359. center_text(0.5, 0.3, r'$|\eta|<2.4$')
  360. plt.xlabel(r"GSF-Track $p_T$")
  361. plt.ylim((0, 1.1))
  362. plt.sca(ax_eta)
  363. hist_plot(get_hist("tracking_pur_v_eta"), include_errors=errors)
  364. center_text(0.5, 0.3, r'$p_T>20$')
  365. plt.xlabel(r"GSF-Track $\eta$")
  366. plt.ylim((0, 1.1))
  367. plt.sca(ax_phi)
  368. hist_plot(get_hist("tracking_pur_v_phi"), include_errors=errors)
  369. center_text(0.5, 0.3, r'$p_T>20$ and $|\eta|<2.4$')
  370. plt.xlabel(r"GSF-Track $\phi$")
  371. plt.ylim((0, 1.1))
  372. @decl_plot
  373. def plot_hit_vs_layer(rs, region):
  374. h = hist2d(getattr(rs, f'hit_vs_layer_{region}'))
  375. hist2d_plot(h, txt_format='{:2.0f}')
  376. plt.xlabel('Layer \#')
  377. plt.ylabel('Hit \#')
  378. def single_cut_plots(cut_sel):
  379. rs = ResultSet(f'{cut_sel}', f'../hists/{cut_sel}.root')
  380. seed_eff = plot_seed_eff, (rs,)
  381. tracking_eff = plot_tracking_eff, (rs,)
  382. seed_pur = plot_seed_purity, (rs,)
  383. track_pur = plot_track_purity, (rs,)
  384. track_pur_seed_match = plot_track_purity, (rs,), dict(ext='2')
  385. BPIX_residuals_L1_H1_dPhi = plot_residuals, (rs, 1, 1, 'dPhi', 'BPIX'), dict(cut_sel=cut_sel)
  386. BPIX_residuals_L2_H2_dPhi = plot_residuals, (rs, 2, 2, 'dPhi', 'BPIX'), dict(cut_sel=cut_sel)
  387. BPIX_residuals_L3_H3_dPhi = plot_residuals, (rs, 3, 3, 'dPhi', 'BPIX'), dict(cut_sel=cut_sel)
  388. BPIX_residuals_L1_H1_dRz = plot_residuals, (rs, 1, 1, 'dRz', 'BPIX')
  389. BPIX_residuals_L2_H2_dRz = plot_residuals, (rs, 2, 2, 'dRz', 'BPIX'), dict(cut_sel=cut_sel)
  390. BPIX_residuals_L3_H3_dRz = plot_residuals, (rs, 3, 3, 'dRz', 'BPIX'), dict(cut_sel=cut_sel)
  391. BPIX_residuals_L2_H1_dPhi = plot_residuals, (rs, 2, 1, 'dPhi', 'BPIX'), dict(cut_sel=cut_sel)
  392. BPIX_residuals_L3_H2_dPhi = plot_residuals, (rs, 3, 2, 'dPhi', 'BPIX'), dict(cut_sel=cut_sel)
  393. BPIX_residuals_L4_H3_dPhi = plot_residuals, (rs, 4, 3, 'dPhi', 'BPIX'), dict(cut_sel=cut_sel)
  394. BPIX_residuals_L2_H1_dRz = plot_residuals, (rs, 2, 1, 'dRz', 'BPIX')
  395. BPIX_residuals_L3_H2_dRz = plot_residuals, (rs, 3, 2, 'dRz', 'BPIX'), dict(cut_sel=cut_sel)
  396. BPIX_residuals_L4_H3_dRz = plot_residuals, (rs, 4, 3, 'dRz', 'BPIX'), dict(cut_sel=cut_sel)
  397. FPIX_residuals_L1_H1_dPhi = plot_residuals, (rs, 1, 1, 'dPhi', 'FPIX'), dict(cut_sel=cut_sel)
  398. FPIX_residuals_L2_H2_dPhi = plot_residuals, (rs, 2, 2, 'dPhi', 'FPIX'), dict(cut_sel=cut_sel)
  399. FPIX_residuals_L3_H3_dPhi = plot_residuals, (rs, 3, 3, 'dPhi', 'FPIX'), dict(cut_sel=cut_sel)
  400. FPIX_residuals_L1_H1_dRz = plot_residuals, (rs, 1, 1, 'dRz', 'FPIX')
  401. FPIX_residuals_L2_H2_dRz = plot_residuals, (rs, 2, 2, 'dRz', 'FPIX'), dict(cut_sel=cut_sel)
  402. FPIX_residuals_L3_H3_dRz = plot_residuals, (rs, 3, 3, 'dRz', 'FPIX'), dict(cut_sel=cut_sel)
  403. FPIX_residuals_L1_H2_dPhi = plot_residuals, (rs, 1, 2, 'dPhi', 'FPIX'), dict(cut_sel=cut_sel)
  404. FPIX_residuals_L1_H3_dPhi = plot_residuals, (rs, 1, 3, 'dPhi', 'FPIX'), dict(cut_sel=cut_sel)
  405. FPIX_residuals_L2_H3_dPhi = plot_residuals, (rs, 2, 3, 'dPhi', 'FPIX'), dict(cut_sel=cut_sel)
  406. FPIX_residuals_L1_H2_dRz = plot_residuals, (rs, 1, 2, 'dPhi', 'FPIX'), dict(cut_sel=cut_sel)
  407. FPIX_residuals_L1_H3_dRz = plot_residuals, (rs, 1, 3, 'dPhi', 'FPIX'), dict(cut_sel=cut_sel)
  408. FPIX_residuals_L2_H3_dRz = plot_residuals, (rs, 2, 3, 'dPhi', 'FPIX'), dict(cut_sel=cut_sel)
  409. hit_vs_layer_barrel = plot_hit_vs_layer, (rs, 'barrel')
  410. hit_vs_layer_forward = plot_hit_vs_layer, (rs, 'forward')
  411. dRz_residuals_v_eta_H1 = plot_residuals_eta, (rs, 1, 'dRz')
  412. dRz_residuals_v_eta_H2 = plot_residuals_eta, (rs, 2, 'dRz')
  413. dRz_residuals_v_eta_H3 = plot_residuals_eta, (rs, 3, 'dRz')
  414. dPhi_residuals_v_eta_H1 = plot_residuals_eta, (rs, 1, 'dPhi')
  415. dPhi_residuals_v_eta_H2 = plot_residuals_eta, (rs, 2, 'dPhi')
  416. dPhi_residuals_v_eta_H3 = plot_residuals_eta, (rs, 3, 'dPhi')
  417. plots = [
  418. Plot(BPIX_residuals_L1_H1_dPhi, 'Phi Residuals Layer 1 Hit 1 - BPIX'),
  419. Plot(BPIX_residuals_L2_H2_dPhi, 'Phi Residuals Layer 2 Hit 2 - BPIX'),
  420. Plot(BPIX_residuals_L3_H3_dPhi, 'Phi Residuals Layer 3 Hit 3 - BPIX'),
  421. Plot(BPIX_residuals_L1_H1_dRz, 'dZ Residuals Layer 1 Hit 1 without cuts - BPIX'),
  422. Plot(BPIX_residuals_L2_H2_dRz, 'dZ Residuals Layer 2 Hit 2 - BPIX'),
  423. Plot(BPIX_residuals_L3_H3_dRz, 'dZ Residuals Layer 3 Hit 3 - BPIX'),
  424. Plot(BPIX_residuals_L2_H1_dPhi, 'Phi Residuals Layer 2 Hit 1 - BPIX'),
  425. Plot(BPIX_residuals_L3_H2_dPhi, 'Phi Residuals Layer 3 Hit 2 - BPIX'),
  426. Plot(BPIX_residuals_L4_H3_dPhi, 'Phi Residuals Layer 4 Hit 3 - BPIX'),
  427. Plot(BPIX_residuals_L2_H1_dRz, 'dZ Residuals Layer 2 Hit 1 without cuts - BPIX'),
  428. Plot(BPIX_residuals_L3_H2_dRz, 'dZ Residuals Layer 3 Hit 2 - BPIX'),
  429. Plot(BPIX_residuals_L4_H3_dRz, 'dZ Residuals Layer 4 Hit 3 - BPIX'),
  430. Plot(FPIX_residuals_L1_H1_dPhi, 'Phi Residuals Layer 1 Hit 1 - FPIX'),
  431. Plot(FPIX_residuals_L2_H2_dPhi, 'Phi Residuals Layer 2 Hit 2 - FPIX'),
  432. Plot(FPIX_residuals_L3_H3_dPhi, 'Phi Residuals Layer 3 Hit 3 - FPIX'),
  433. Plot(FPIX_residuals_L1_H1_dRz, 'dR Residuals Layer 1 Hit 1 without cuts - FPIX'),
  434. Plot(FPIX_residuals_L2_H2_dRz, 'dR Residuals Layer 2 Hit 2 - FPIX'),
  435. Plot(FPIX_residuals_L3_H3_dRz, 'dR Residuals Layer 3 Hit 3 - FPIX'),
  436. Plot(FPIX_residuals_L1_H2_dPhi, 'Phi Residuals Layer 1 Hit 2 - FPIX'),
  437. Plot(FPIX_residuals_L1_H3_dPhi, 'Phi Residuals Layer 1 Hit 3 - FPIX'),
  438. Plot(FPIX_residuals_L2_H3_dPhi, 'Phi Residuals Layer 2 Hit 3 - FPIX'),
  439. Plot(FPIX_residuals_L1_H2_dRz, 'dR Residuals Layer 1 Hit 2 - FPIX'),
  440. Plot(FPIX_residuals_L1_H3_dRz, 'dR Residuals Layer 1 Hit 3 - FPIX'),
  441. Plot(FPIX_residuals_L2_H3_dRz, 'dR Residuals Layer 2 Hit 3 - FPIX'),
  442. Plot(seed_eff, 'ECAL-Driven Seeding Efficiency'),
  443. Plot(tracking_eff, 'GSF Tracking Efficiency'),
  444. Plot(hit_vs_layer_barrel, 'Hit vs Layer - Barrel'),
  445. Plot(hit_vs_layer_forward, 'Hit vs Layer - Forward'),
  446. Plot(seed_pur, 'ECAL-Driven Seeding Purity'),
  447. Plot(track_pur, 'GSF Track Purity'),
  448. Plot(track_pur_seed_match , 'GSF Track Purity (Seed Truth Match)'),
  449. simple_plot(rs.gsf_tracks_nmatch_sim_tracks, log='y'),
  450. Plot(dRz_residuals_v_eta_H1, 'dRz Hit 1 Residuals v eta'),
  451. Plot(dRz_residuals_v_eta_H2, 'dRz Hit 2 Residuals v eta'),
  452. Plot(dRz_residuals_v_eta_H3, 'dRz Hit 3 Residuals v eta'),
  453. Plot(dPhi_residuals_v_eta_H1, 'dPhi Hit 1 Residuals v eta'),
  454. Plot(dPhi_residuals_v_eta_H2, 'dPhi Hit 2 Residuals v eta'),
  455. Plot(dPhi_residuals_v_eta_H3, 'dPhi Hit 3 Residuals v eta'),
  456. ]
  457. render_plots(plots, directory='output/figures/'+rs.sample_name, to_disk=to_disk)
  458. if not to_disk:
  459. generate_dashboard(plots, 'Seeding Efficiency',
  460. output=f'{rs.sample_name}.html',
  461. source=__file__,
  462. config=rs.config)
  463. def eta_region_plots(cut_sel):
  464. rs = ResultSet(f'{cut_sel}', f'../hists/{cut_sel}.root')
  465. @decl_plot
  466. def residual_in_region(var, hit):
  467. for region in (1, 2, 3):
  468. h = hist2d(getattr(rs, f'{var}_residuals_H{hit}_R{region}'))
  469. xs, ys = hist2d_percent_contour(h, .99, 'x')
  470. plt.plot(xs, ys, label=f'99\%, Region {region}')
  471. plt.legend()
  472. plt.xlabel({'dPhi': r'$\delta \phi$ (rads)',
  473. 'dRz': r'$\delta R/z$ (cm)'}[var])
  474. plt.ylabel('$E_T$ (GeV)')
  475. plots = []
  476. for hit in (1, 2, 3):
  477. plt_tup = residual_in_region, ('dPhi', hit)
  478. plots.append(Plot(plt_tup, f'dPhi residuals, hit {hit}'))
  479. plt_tup = residual_in_region, ('dRz', hit)
  480. plots.append(Plot(plt_tup, f'dRz residuals, hit {hit}'))
  481. render_plots(plots, directory='output/figures/'+rs.sample_name, to_disk=to_disk)
  482. if not to_disk:
  483. generate_dashboard(plots, 'Breakdown by Eta Region',
  484. output=f'{rs.sample_name}-eta-regions.html',
  485. source=__file__,
  486. config=rs.config)
  487. @decl_plot
  488. def plot_seed_roc_curve(rss):
  489. def get_num_den(rs, basename):
  490. num = hist(getattr(rs, f'{basename}_num'))
  491. den = hist(getattr(rs, f'{basename}_den'))
  492. return hist_integral_ratio(num, den)
  493. for rs in rss:
  494. eff, eff_err = get_num_den(rs, 'seed_eff_v_phi')
  495. pur, pur_err = get_num_den(rs, 'seed_pur_v_phi')
  496. if rs.sample_name == 'old-seeding':
  497. plt.errorbar([pur], [eff], xerr=[pur_err], yerr=[eff_err], label=rs.sample_name, color='k', marker='o')
  498. else:
  499. plt.errorbar([pur], [eff], xerr=[pur_err], yerr=[eff_err], label=rs.sample_name[:-7], marker='o')
  500. center_text(0.5, 0.3, r'$p_T>20$ and $|\eta|<2.4$')
  501. plt.axis('equal')
  502. plt.xlim((0.8, 1.0))
  503. plt.ylim((0.8, 1.0))
  504. plt.xlabel('ECAL-Driven Seeding Purity')
  505. plt.ylabel('ECAL-Driven Seeding Efficiency')
  506. plt.grid()
  507. plt.legend()
  508. @decl_plot
  509. def plot_seed_eff_all(rss):
  510. ax_pt = plt.subplot(221)
  511. ax_eta = plt.subplot(222)
  512. ax_phi = plt.subplot(223)
  513. errors = True
  514. for rs in rss:
  515. plt.sca(ax_pt)
  516. hist_plot(hist(rs.seed_eff_v_pt), include_errors=errors, label=rs.sample_name)
  517. plt.sca(ax_eta)
  518. hist_plot(hist(rs.seed_eff_v_eta), include_errors=errors, label=rs.sample_name)
  519. plt.sca(ax_phi)
  520. hist_plot(hist(rs.seed_eff_v_phi), include_errors=errors, label=rs.sample_name)
  521. plt.sca(ax_pt)
  522. center_text(0.5, 0.3, r'$|\eta|<2.4$')
  523. plt.xlabel(r"Sim-Track $p_T$")
  524. plt.ylim((0, 1.1))
  525. plt.sca(ax_eta)
  526. center_text(0.5, 0.3, r'$p_T>20$')
  527. plt.xlabel(r"Sim-Track $\eta$")
  528. plt.ylim((0, 1.1))
  529. plt.legend(loc='lower right')
  530. plt.sca(ax_phi)
  531. center_text(0.5, 0.3, r'$p_T>20$ and $|\eta|<2.4$')
  532. plt.xlabel(r"Sim-Track $\phi$")
  533. plt.ylim((0, 1.1))
  534. @decl_plot
  535. def plot_seed_pur_all(rss):
  536. ax_pt = plt.subplot(221)
  537. ax_eta = plt.subplot(222)
  538. ax_phi = plt.subplot(223)
  539. errors = True
  540. for rs in rss:
  541. plt.sca(ax_pt)
  542. hist_plot(hist(rs.seed_pur_v_pt), include_errors=errors, label=rs.sample_name)
  543. plt.sca(ax_eta)
  544. hist_plot(hist(rs.seed_pur_v_eta), include_errors=errors, label=rs.sample_name)
  545. plt.sca(ax_phi)
  546. hist_plot(hist(rs.seed_pur_v_phi), include_errors=errors, label=rs.sample_name)
  547. plt.sca(ax_pt)
  548. center_text(0.5, 0.3, r'$|\eta|<2.4$')
  549. plt.xlabel(r"Seed $p_T$")
  550. plt.ylim((0, 1.1))
  551. plt.sca(ax_eta)
  552. center_text(0.5, 0.3, r'$p_T>20$')
  553. plt.xlabel(r"Seed $\eta$")
  554. plt.ylim((0, 1.1))
  555. plt.legend(loc='lower right')
  556. plt.sca(ax_phi)
  557. center_text(0.5, 0.3, r'$p_T>20$ and $|\eta|<2.4$')
  558. plt.xlabel(r"Seed $\phi$")
  559. plt.ylim((0, 1.1))
  560. @decl_plot
  561. def plot_tracking_roc_curve(rss, ext=''):
  562. def get_num_den(rs, basename):
  563. num = hist(getattr(rs, f'{basename}{ext}_num'))
  564. den = hist(getattr(rs, f'{basename}{ext}_den'))
  565. return hist_integral_ratio(num, den)
  566. for rs in rss:
  567. eff, eff_err = get_num_den(rs, 'tracking_eff_v_phi')
  568. pur, pur_err = get_num_den(rs, 'tracking_pur_v_phi')
  569. if rs.sample_name == 'old-seeding':
  570. plt.errorbar([pur], [eff], xerr=[pur_err], yerr=[eff_err], label=rs.sample_name, color='k', marker='o')
  571. else:
  572. plt.errorbar([pur], [eff], xerr=[pur_err], yerr=[eff_err], label=rs.sample_name[:-7], marker='o')
  573. center_text(0.5, 0.3, r'$p_T>20$ and $|\eta|<2.4$')
  574. plt.axis('equal')
  575. plt.xlim((0.8, 1.0))
  576. plt.ylim((0.8, 1.0))
  577. plt.xlabel('GSF-Track Purity')
  578. plt.ylabel('GSF-Track Efficiency')
  579. plt.grid()
  580. plt.legend()
  581. @decl_plot
  582. def plot_tracking_eff_all(rss, ext=''):
  583. ax_pt = plt.subplot(221)
  584. ax_eta = plt.subplot(222)
  585. ax_phi = plt.subplot(223)
  586. errors = True
  587. for rs in rss:
  588. plt.sca(ax_pt)
  589. hist_plot(hist(getattr(rs, f'tracking_eff_v_pt{ext}')), include_errors=errors, label=rs.sample_name)
  590. plt.sca(ax_eta)
  591. hist_plot(hist(getattr(rs, f'tracking_eff_v_eta{ext}')), include_errors=errors, label=rs.sample_name)
  592. plt.sca(ax_phi)
  593. hist_plot(hist(getattr(rs, f'tracking_eff_v_phi{ext}')), include_errors=errors, label=rs.sample_name)
  594. plt.sca(ax_pt)
  595. center_text(0.5, 0.3, r'$|\eta|<2.4$')
  596. plt.xlabel(r"Sim-Track $p_T$")
  597. plt.ylim((0, 1.1))
  598. plt.sca(ax_eta)
  599. center_text(0.5, 0.3, r'$p_T>20$')
  600. plt.xlabel(r"Sim-Track $\eta$")
  601. plt.ylim((0, 1.1))
  602. plt.legend(loc='lower right')
  603. plt.sca(ax_phi)
  604. center_text(0.5, 0.3, r'$p_T>20$ and $|\eta|<2.4$')
  605. plt.xlabel(r"Sim-Track $\phi$")
  606. plt.ylim((0, 1.1))
  607. @decl_plot
  608. def plot_tracking_pur_all(rss, ext=''):
  609. ax_pt = plt.subplot(221)
  610. ax_eta = plt.subplot(222)
  611. ax_phi = plt.subplot(223)
  612. errors = True
  613. for rs in rss:
  614. plt.sca(ax_pt)
  615. hist_plot(hist(getattr(rs, f'tracking_pur_v_pt{ext}')), include_errors=errors, label=rs.sample_name)
  616. plt.sca(ax_eta)
  617. hist_plot(hist(getattr(rs, f'tracking_pur_v_eta{ext}')), include_errors=errors, label=rs.sample_name)
  618. plt.sca(ax_phi)
  619. hist_plot(hist(getattr(rs, f'tracking_pur_v_phi{ext}')), include_errors=errors, label=rs.sample_name)
  620. plt.sca(ax_pt)
  621. center_text(0.5, 0.3, r'$|\eta|<2.4$')
  622. plt.xlabel(r"GSF-Track $p_T$")
  623. plt.ylim((0, 1.1))
  624. plt.sca(ax_eta)
  625. center_text(0.5, 0.3, r'$p_T>20$')
  626. plt.xlabel(r"GSF-Track $\eta$")
  627. plt.ylim((0, 1.1))
  628. plt.legend(loc='lower right')
  629. plt.sca(ax_phi)
  630. center_text(0.5, 0.3, r'$p_T>20$ and $|\eta|<2.4$')
  631. plt.xlabel(r"GSF-Track $\phi$")
  632. plt.ylim((0, 1.1))
  633. @decl_plot
  634. def plot_ecal_rel_res(rss):
  635. for rs in rss:
  636. hist_plot(hist(rs.ecal_energy_resolution), label=rs.sample_name)
  637. plt.xlabel(r"ECAL $E_T$ relative error")
  638. plt.legend()
  639. @decl_plot
  640. def plot_res_contour(rss, hit_number, var, layers, ext='_TrackMatched'):
  641. from itertools import chain
  642. _, axs = plt.subplots(2, 3)
  643. axs_all = list(chain(*axs))
  644. def do_plot(ax, rs):
  645. plt.sca(ax)
  646. plt.title(rs.sample_name)
  647. h = None
  648. for layer in layers:
  649. subdet = 'BPIX' if layer[0]=='B' else 'FPIX'
  650. h = hist2d(getattr(rs, f'{var}_{subdet}_L{layer[1]}_H{hit_number}_v_Et{ext}'))
  651. pass
  652. xs, ys = hist2d_percent_contour(h, .99, 'x')
  653. plt.plot(xs, ys, label=f'{subdet} - L{layer[1]}')
  654. ets = h[3][:, 0]
  655. cuts = [calc_window(et, 0, hit_number, var, rs.sample_name) for et in ets]
  656. plt.plot(cuts, ets, color='red', label='Cut Value')
  657. max_x = 0
  658. for ax, rs in zip(axs_all, rss):
  659. try:
  660. do_plot(ax, rs)
  661. _, x_up = ax.get_xlim()
  662. max_x = max((max_x, x_up))
  663. except KeyError:
  664. pass
  665. plt.sca(axs[0][-1])
  666. plt.legend(loc='best')
  667. for ax in axs_all:
  668. ax.set_xlim((None, max_x))
  669. @decl_plot
  670. def number_of_seeds(rss):
  671. from filval.histogram import hist_mean
  672. for rs in rss:
  673. h = hist_rebin(hist(rs.n_seeds), 50, -0.5, 200.5)
  674. h = hist_norm(h)
  675. mean = int(hist_mean(h))
  676. hist_plot(h, label=f'{rs.sample_name} ($\\mu={mean:d}$)')
  677. plt.xlabel('Number of Seeds Produced')
  678. plt.legend()
  679. def all_cut_plots(cuts):
  680. rss = [ResultSet(f'{cut_sel}', f'../hists/{cut_sel}.root') for cut_sel in cuts]
  681. tracking_roc_curve = plot_tracking_roc_curve, (rss,)
  682. tracking_eff_all = plot_tracking_eff_all, (rss,)
  683. tracking_pur_all = plot_tracking_pur_all, (rss,)
  684. tracking_roc_curve2 = plot_tracking_roc_curve, (rss, '2')
  685. tracking_eff_all2 = plot_tracking_eff_all, (rss, '2')
  686. tracking_pur_all2 = plot_tracking_pur_all, (rss, '2')
  687. seed_roc_curve = plot_seed_roc_curve, (rss,)
  688. seed_eff_all = plot_seed_eff_all, (rss,)
  689. seed_pur_all = plot_seed_pur_all, (rss,)
  690. ecal_rel_res = plot_ecal_rel_res, (rss,)
  691. res_contour_dphi_H1 = plot_res_contour, (rss, 1, 'dPhi', ['B1', 'B2', 'F1'])
  692. res_contour_dphi_H2 = plot_res_contour, (rss, 2, 'dPhi', ['B2', 'B3', 'B4', 'F1', 'F2'])
  693. res_contour_dRz_H2 = plot_res_contour, (rss, 2, 'dRz', ['B2', 'B3', 'B4', 'F1', 'F2'])
  694. res_contour_dphi_H3 = plot_res_contour, (rss, 3, 'dPhi', ['B3', 'B4''F1', 'F2', 'F3'])
  695. res_contour_dRz_H3 = plot_res_contour, (rss, 3, 'dRz', ['B3', 'B4''F1', 'F2', 'F3'])
  696. plots = [
  697. Plot(tracking_roc_curve, 'Tracking ROC Curve'),
  698. Plot(tracking_eff_all, 'Tracking Efficiency'),
  699. Plot(tracking_pur_all, 'Tracking Purity'),
  700. Plot(tracking_roc_curve2, 'Tracking ROC Curve (Seed Matched)'),
  701. Plot(tracking_eff_all2, 'Tracking Efficiency (Seed Matched)'),
  702. Plot(tracking_pur_all2, 'Tracking Purity (Seed Matched)'),
  703. Plot(seed_roc_curve, 'Seeding ROC Curve'),
  704. Plot(seed_eff_all, 'ECAL-Driven Seeding Efficiency'),
  705. Plot(seed_pur_all, 'ECAL-Driven Seeding Purity'),
  706. Plot(ecal_rel_res, 'ECAL ET Relative Resolution'),
  707. Plot(res_contour_dphi_H1, 'dPhi Residual 99% Contours - Hit 1'),
  708. Plot(res_contour_dphi_H2, 'dPhi Residual 99% Contours - Hit 2'),
  709. Plot(res_contour_dRz_H2, 'dRz Residual 99% Contours - Hit 2'),
  710. Plot(res_contour_dphi_H3, 'dPhi Residual 99% Contours - Hit 3'),
  711. Plot(res_contour_dRz_H3, 'dRz Residual 99% Contours - Hit 3'),
  712. Plot((number_of_seeds, (rss,)), 'Number of Electron Seeds'),
  713. ]
  714. render_plots(plots, to_disk=to_disk)
  715. if not to_disk:
  716. generate_dashboard(plots, 'Comparisons',
  717. output='comparisons.html',
  718. source=__file__,
  719. config=rss[0].config)
  720. if __name__ == '__main__':
  721. to_disk = False
  722. all_cuts = [
  723. 'extra-narrow-window',
  724. 'narrow-window',
  725. 'wide-window',
  726. 'extra-wide-window',
  727. # 'nwp-window',
  728. # 'nwp-tight-window',
  729. # 'nwp-eta-breakdown',
  730. ]
  731. all_cut_plots(all_cuts+['old-seeding'])
  732. # for cut in all_cuts:
  733. # single_cut_plots(cut)
  734. # eta_region_plots('extra-wide-window')