yields.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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_utils import hist, hist_add, hist_normalize, hist_scale
  6. from filval.plotter import (decl_plot, render_plots, hist_plot, hist_plot_stack, Plot, generate_dashboard)
  7. @decl_plot
  8. def plot_yield_grid(rss):
  9. r"""## Event Yield
  10. The event yield for the eight signal regions defined in AN-17-115. Data is normalized
  11. to the Moriond 2018 integrated luminosity ($35.9\textrm{fb}^{-1}$). Code for the histogram generation is
  12. here: <https://github.com/cfangmeier/FTAnalysis/blob/master/studies/tau/Yield.C>
  13. """
  14. _, ((ax_tttt, ax_ttw), (ax_ttz, ax_tth)) = plt.subplots(2, 2)
  15. ft, ttw, ttz, tth = map(lambda rs: hist(rs.SRs), rss)
  16. # ft, ttw = map(lambda rs: hist(rs.SRs), rss[:2])
  17. plt.sca(ax_tttt)
  18. an = ((0.47, 0.33, 0.18, 0.78, 0.49, 0.52, 0.33, 0.49),
  19. (0, 0, 0, 0, 0, 0, 0, 0), [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5])
  20. hist_plot(ft, title='TTTT', stats=False, label='Mock')
  21. hist_plot(an, title='TTTT', stats=False, label='AN')
  22. plt.sca(ax_ttw)
  23. an = ([2.29663, 0.508494, 0.161166, 1.03811, 0.256401, 0.127582, 0.181522, 0.141659],
  24. [0, 0, 0, 0, 0, 0, 0, 0], [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5])
  25. hist_plot(ttw, title='TTW', stats=False, label='Mock')
  26. hist_plot(an, title='TTW', stats=False, label='AN')
  27. plt.legend()
  28. plt.sca(ax_ttz)
  29. an = ([0.974751, 0.269195, 1e-06, 0.395831, 0.0264703, 0.06816, 0.8804, 0.274265],
  30. [0, 0, 0, 0, 0, 0, 0, 0], [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5])
  31. hist_plot(ttz, title='TTZ', stats=False, label='Mock')
  32. hist_plot(an, title='TTZ', stats=False, label='AN')
  33. plt.xlabel('Signal Region')
  34. plt.sca(ax_tth)
  35. an = ([1.13826, 0.361824, 0.162123, 0.683917, 0.137608, 0.0632719, 0.554491, 0.197864],
  36. [0, 0, 0, 0, 0, 0, 0, 0], [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5])
  37. hist_plot(tth, title='TTH', stats=False, label='Mock')
  38. hist_plot(an, title='TTH', stats=False, label='AN')
  39. plt.xlabel('Signal Region')
  40. @decl_plot
  41. def plot_yield_stack(rss):
  42. r"""## Event Yield - Stacked
  43. The event yield for the eight signal regions defined in AN-17-115. Data is normalized
  44. to the Moriond 2018 integrated luminosity ($35.9\textrm{fb}^{-1}$). Code for the histogram generation is
  45. here: <https://github.com/cfangmeier/FTAnalysis/blob/master/studies/tau/Yield.C>
  46. """
  47. ft, ttw, ttz, tth = map(lambda rs: hist(rs.SRs), rss)
  48. hist_plot_stack([ttw, ttz, tth], labels=['TTW', 'TTZ', 'TTH'])
  49. ft = ft[0]*10, ft[1], ft[2]
  50. hist_plot(ft, label='TTTT (x10)', stats=False, color='k')
  51. plt.ylim((0, 60))
  52. plt.xlabel('Signal Region')
  53. plt.legend()
  54. @decl_plot
  55. def plot_lep_multi(rss, dataset):
  56. _, (ax_els, ax_mus, ax_taus) = plt.subplots(3, 1)
  57. els = list(map(lambda rs: hist_normalize(hist(rs.nEls)), rss))
  58. mus = list(map(lambda rs: hist_normalize(hist(rs.nMus)), rss))
  59. taus = list(map(lambda rs: hist_normalize(hist(rs.nTaus)), rss))
  60. def _plot(ax, procs):
  61. plt.sca(ax)
  62. ft, ttw, ttz, tth = procs
  63. h = {'TTTT': ft,
  64. 'TTW': ttw,
  65. 'TTZ': ttz,
  66. 'TTH': tth}[dataset]
  67. hist_plot(h, stats=False, label=dataset)
  68. _plot(ax_els, els)
  69. plt.xlabel('\\# Good Electrons')
  70. plt.legend()
  71. _plot(ax_mus, mus)
  72. plt.xlabel('\\# Good Muons')
  73. _plot(ax_taus, taus)
  74. plt.xlabel('\\# Good Taus')
  75. @decl_plot
  76. def plot_sig_strength(rss):
  77. r""" The signal strength of the TTTT signal defined as
  78. $\frac{S}{\sqrt{S+B}}$
  79. """
  80. ft, ttw, ttz, tth = map(lambda rs: hist(rs.SRs), rss)
  81. bg = hist_add(ttw, ttz, tth)
  82. strength = ft[0] / np.sqrt(ft[0] + bg[0])
  83. hist_plot((strength, ft[1], ft[2]), stats=False)
  84. @decl_plot
  85. def plot_event_obs(rss, dataset):
  86. r"""
  87. """
  88. _, ((ax_njet, ax_nbjet), (ax_ht, ax_met)) = plt.subplots(2, 2)
  89. # ft, ttw, ttz, tth = map(lambda rs: hist(rs.SRs), rss)
  90. ft, ttw, ttz, tth = rss
  91. rs = {'TTTT': ft,
  92. 'TTW': ttw,
  93. 'TTZ': ttz,
  94. 'TTH': tth}[dataset]
  95. def _plot(ax, obs):
  96. plt.sca(ax)
  97. h = {'MET': rs.met_in_SR,
  98. 'HT': rs.ht_in_SR,
  99. 'NJET': rs.njet_in_SR,
  100. 'NBJET': rs.nbjet_in_SR}[obs]
  101. hist_plot(hist(h), stats=False, label=dataset, xlabel=obs)
  102. _plot(ax_njet, 'NJET')
  103. _plot(ax_nbjet, 'NBJET')
  104. _plot(ax_ht, 'HT')
  105. _plot(ax_met, 'MET')
  106. @decl_plot
  107. def plot_event_obs_stack(rss):
  108. r"""
  109. """
  110. _, ((ax_njet, ax_nbjet), (ax_ht, ax_met)) = plt.subplots(2, 2)
  111. def _plot(ax, obs):
  112. plt.sca(ax)
  113. attr = {'MET': 'met_in_SR',
  114. 'HT': 'ht_in_SR',
  115. 'NJET': 'njet_in_SR',
  116. 'NBJET': 'nbjet_in_SR'}[obs]
  117. ft, ttw, ttz, tth = map(lambda rs: hist(getattr(rs, attr)), rss)
  118. hist_plot_stack([ttw, ttz, tth], labels=["TTW", "TTZ", "TTH"])
  119. hist_plot(hist_scale(ft, 5), label="TTTT (x5)", color='k')
  120. plt.xlabel(obs)
  121. _plot(ax_njet, 'NJET')
  122. _plot(ax_nbjet, 'NBJET')
  123. plt.legend()
  124. _plot(ax_ht, 'HT')
  125. _plot(ax_met, 'MET')
  126. @decl_plot
  127. def plot_tau_purity(rss):
  128. _, ((ax_ft, ax_ttw), (ax_ttz, ax_tth)) = plt.subplots(2, 2)
  129. ft, ttw, ttz, tth = list(map(lambda rs: hist(rs.tau_purity_v_pt), rss))
  130. def _plot(ax, dataset):
  131. plt.sca(ax)
  132. h = {'TTTT': ft,
  133. 'TTW': ttw,
  134. 'TTZ': ttz,
  135. 'TTH': tth}[dataset]
  136. hist_plot(h, stats=False, label=dataset)
  137. plt.text(200, 0.05, dataset)
  138. plt.xlabel(r"$P_T$(GeV)")
  139. _plot(ax_ft, 'TTTT')
  140. _plot(ax_ttw, 'TTW')
  141. _plot(ax_ttz, 'TTZ')
  142. _plot(ax_tth, 'TTH')
  143. if __name__ == '__main__':
  144. # First create a ResultSet object which loads all of the objects from output.root
  145. # into memory and makes them available as attributes
  146. rss = (ResultSet("ft", 'data/yield_ft.root'),
  147. ResultSet("ttw", 'data/yield_ttw.root'),
  148. ResultSet("ttz", 'data/yield_ttz.root'),
  149. ResultSet("tth", 'data/yield_tth.root'))
  150. rss_notau = (ResultSet("ft_notau", 'data/yield_ft_notau.root'),
  151. ResultSet("ttw_notau", 'data/yield_ttw_notau.root'),
  152. ResultSet("ttz_notau", 'data/yield_ttz_notau.root'),
  153. ResultSet("tth_notau", 'data/yield_tth_notau.root'))
  154. # Next, declare all of the (sub)plots that will be assembled into full
  155. # figures later
  156. yield_tau = (plot_yield_grid, (rss,), {})
  157. yield_notau = (plot_yield_grid, (rss_notau,), {})
  158. yield_tau_stack = (plot_yield_stack, (rss,), {})
  159. yield_notau_stack = (plot_yield_stack, (rss_notau,), {})
  160. sig_strength_tau = (plot_sig_strength, (rss,), {})
  161. sig_strength_notau = (plot_sig_strength, (rss_notau,), {})
  162. ft_lep_multi = (plot_lep_multi, (rss, 'TTTT'), {})
  163. ttw_lep_multi = (plot_lep_multi, (rss, 'TTW'), {})
  164. ttz_lep_multi = (plot_lep_multi, (rss, 'TTZ'), {})
  165. tth_lep_multi = (plot_lep_multi, (rss, 'TTH'), {})
  166. ft_event_obs = (plot_event_obs, (rss_notau, 'TTTT'), {})
  167. ttw_event_obs = (plot_event_obs, (rss_notau, 'TTW'), {})
  168. ttz_event_obs = (plot_event_obs, (rss_notau, 'TTZ'), {})
  169. tth_event_obs = (plot_event_obs, (rss_notau, 'TTH'), {})
  170. event_obs_stack = (plot_event_obs_stack, (rss_notau,), {})
  171. tau_purity = (plot_tau_purity, (rss,), {})
  172. # Now assemble the plots into figures.
  173. plots = [
  174. Plot([[yield_tau]],
  175. 'Yield With Tau'),
  176. Plot([[yield_notau]],
  177. 'Yield Without Tau'),
  178. Plot([[yield_tau_stack]],
  179. 'Yield With Tau Stacked'),
  180. Plot([[yield_notau_stack]],
  181. 'Yield Without Tau Stacked'),
  182. Plot([[yield_tau_stack],
  183. [yield_notau_stack]],
  184. 'Event Yield, top: with tau, bottom: no tau'),
  185. Plot([[sig_strength_tau],
  186. [sig_strength_notau]],
  187. 'Signal Strength'),
  188. Plot([[ft_lep_multi]],
  189. 'Lepton Multiplicity - TTTT'),
  190. Plot([[ttw_lep_multi]],
  191. 'Lepton Multiplicity - TTW'),
  192. Plot([[ttz_lep_multi]],
  193. 'Lepton Multiplicity - TTZ'),
  194. Plot([[tth_lep_multi]],
  195. 'Lepton Multiplicity - TTH'),
  196. Plot([[ft_event_obs]],
  197. 'TTTT - Event Observables'),
  198. Plot([[ttw_event_obs]],
  199. 'TTW - Event Observables'),
  200. Plot([[ttz_event_obs]],
  201. 'TTZ - Event Observables'),
  202. Plot([[tth_event_obs]],
  203. 'TTH - Event Observables'),
  204. Plot([[event_obs_stack]],
  205. 'Event Observables'),
  206. Plot([[tau_purity]],
  207. 'Tau Purity'),
  208. ]
  209. # Finally, render and save the plots and generate the html+bootstrap
  210. # dashboard to view them
  211. render_plots(plots, to_disk=False)
  212. generate_dashboard(plots, 'TTTT Yields', output='yield2.html', source_file=__file__)