Belle II Software  release-06-02-00
fullTrackingTableValidationAnalyseData.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 """
13 <header>
14  <contact>software-tracking@belle2.org</contact>
15  <output>fullTrackingValidationTable.root</output>
16  <input>matching_validation.root</input>
17  <description>This module generates events for the validation using the full tracking with a tabular output.</description>
18 </header>
19 """
20 import basf2
21 from ROOT import TFile, TNamed
22 import os
23 
24 VALIDATION_OUTPUT_FILE = "fullTrackingTableValidation.root"
25 
26 try:
27  from root_pandas import read_root # noqa
28  import pandas as pd # noqa
29 except ImportError:
30  basf2.B2FATAL("You need to have pandas installed for this validation script to run.")
31 
32 FORMAT_STRING = "&nbsp;{:.2%} <br/> -{:.2%} <br/> <b>-{:.2%}</b> <br/> Matching: {:.2%} <br/> CDC: {:.2%} <br/> VXD: {:.2%}"
33 SHORT_FORMAT_STRING = "MC: &nbsp;{:.2%} <br/>Missing: -{:.2%} <br/>Missing and !fit: <b>-{:.2%}</b>"
34 
35 
36 def reducelist(list_of_cuts, df, current_name=None, current_cut=None, x=0, y=0):
37  if current_name is not None:
38  if y == 5:
39  return_string = FORMAT_STRING.format(current_cut.mean(),
40  (current_cut & (df.is_matched == 0)).mean(),
41  (current_cut & (df.fitted_is_matched == 0)).mean(),
42  (current_cut & (df.both_related == 1)).mean(),
43  (current_cut & (df.cdc_has_related == 1)).mean(),
44  (current_cut & (df.vxd_has_related == 1)).mean())
45  else:
46  return_string = SHORT_FORMAT_STRING.format(current_cut.mean(),
47  (current_cut & (df.is_matched == 0)).mean(),
48  (current_cut & (df.fitted_is_matched == 0)).mean())
49  yield (y, x, current_name), return_string
50 
51  if not list_of_cuts:
52  return
53 
54  name, cut = list_of_cuts[0]
55 
56  if cut is None:
57  # Make a "always true" cut
58  def cut(x):
59  return x.is_missing == x.is_missing
60 
61  if current_name is None:
62  yield from reducelist(list_of_cuts[1:], df, name, cut(df),
63  x + 2 ** (len(list_of_cuts) - 1), y + 1)
64  else:
65  yield from reducelist(list_of_cuts[1:], df, current_name + "_no_" + name, current_cut & (~cut(df)),
66  x, y + 1)
67  yield from reducelist(list_of_cuts[1:], df, current_name + "_" + name, current_cut & (cut(df)),
68  x + 2 ** (len(list_of_cuts) - 1), y + 1)
69 
70 
71 def make_chunks(k, n):
72  return [k[i:i + n] for i in range(0, len(k), n)]
73 
74 
75 def write_value_cell(key, value):
76  y, x, name, _ = key
77  colspan = 2 ** int(5 - y)
78 
79  colors = {
80  3: ["white", "gray", "orange", "green"],
81  4: ["gray", "white", "gray", "gray",
82  "orange", "orange", "green", "green"],
83  5: ["gray", "gray", "red", "green",
84  "gray", "gray", "gray", "gray",
85  "red", "gray", "red", "orange",
86  "green", "gray", "orange", "green"]
87  }
88 
89  if y in colors:
90  color_index = int((x - 2 ** 4) / (2 ** (5 - y)))
91  color = colors[y][color_index]
92  else:
93  color = "white"
94 
95  return """
96  <td style="border: 1px solid black" colspan={colspan}
97  align="center" valign=middle bgcolor="{color}">{value}</td>
98  """.format(colspan=colspan, color=color, value=value)
99 
100 
101 def make_html_row(x):
102  keys = [key for key, _ in x.iteritems()]
103  titles = [key[2] for key, _ in x.iteritems()]
104 
105  chunked_titles = make_chunks(titles, 2)
106  common_prefixes = list(map(os.path.commonprefix, chunked_titles))
107 
108  shorter_titles = [title.replace(prefix, "").replace("_", " ")
109  for list_titles, prefix in zip(chunked_titles, common_prefixes)
110  for title in list_titles]
111 
112  row_content = "".join([write_value_cell(key, value) for key, value in zip(keys, shorter_titles)])
113  html = "<tr>" + row_content + "</tr>"
114 
115  row_content = "".join([write_value_cell(key, value) for key, value in x.sort_index().iteritems()])
116  html += "<tr>" + row_content + "</tr>"
117 
118  return html
119 
120 
121 def get_html(df, test):
122  results = pd.DataFrame(dict(reducelist(test, df)), index=[0]).unstack()
123 
124  last_row_titles = ["", "", "CDCTF may help", "Criteria?", "", "", "", "", "VXDTF may help", "",
125  "hard cases", "CKF may help", "Criteria?", "", "CKF may help", "Merging"]
126 
127  html = "<table>"
128  html += "".join(results.groupby(level=0).apply(make_html_row))
129  html += "<tr>" + ("".join(["<td>" + value + "</td>" for value in last_row_titles])) + "</tr>"
130  html += "</table>"
131 
132  return html
133 
134 
135 if __name__ == '__main__':
136  # These are the categories to be tested successively
137  test = [
138  ("all", None),
139  ("has_vxd", lambda x: (x.n_svd_hits >= 2)),
140  ("vxd_was_found", lambda x: x["vxd_was_found"] == 1),
141  ("has_cdc", lambda x: x.n_cdc_hits >= 3),
142  ("cdc_was_found", lambda x: x["cdc_was_found"] == 1),
143  ]
144 
145  df = read_root("../matching_validation.root")
146  html = get_html(df, test)
147 
148  tfile = TFile(VALIDATION_OUTPUT_FILE, "RECREATE")
149  html_content = TNamed("Tracking Table Validation", html)
150  html_content.Write()
151  tfile.Close()