12 Call this "python3 fei/latexReporting.py summary.tex"
13 in a directory containing the monitoring output of the FEI
14 It will create a latex document containing a summary and plots
15 and tries to compile this summary.tex into a PDF file summary.pdf
17 You can improve / modify this script
18 E.g. If you want to add new plots:
19 Add your plot in the monitoring.py file
20 Add your plot below using b2latex.Graphics
24 from fei
import monitoring
26 from B2Tools
import b2latex
27 from B2Tools
import format
33 if __name__ ==
'__main__':
35 output_file = sys.argv[1]
37 raise AttributeError(
"You have to supply the output tex file.")
39 particles, configuration = monitoring.load_config()
40 monitoringParticle = []
41 for particle
in particles:
42 monitoringParticle.append(monitoring.MonitoringParticle(particle))
45 o = b2latex.LatexFile()
47 o += b2latex.TitlePage(title=
'Full Event Interpretation Report',
48 authors=[
'Thomas Keck',
'Christian Pulvermacher',
'William Sutcliffe'],
50 This report contains key performance indicators and control plots of the Full Event Interpretation.
51 The pre-, and post-cuts as well as trained multivariate selection methods are described.
52 Furthermore the resulting purities and efficiencies are stated.
54 add_table_of_contents=
True).finish()
56 o += b2latex.Section(
"Summary").finish()
57 o += b2latex.String(
r"""
58 For each decay channel of each particle a multivariate selection method is trained after applying
59 a fast pre-cut on the candidates. Afterwards, a post-cut is applied on the signal probability calculated by the method.
60 This reduces combinatorics in the following stages of the Full
64 table = b2latex.LongTable(columnspecs=
r'c|rr|rrrrrr',
65 caption=
'Per-particle efficiency before and after the applied pre- and post-cut.',
66 head=
r'Particle & \multicolumn{2}{c}{Covered BR} '
67 r' & \multicolumn{3}{c}{pre-cut} & \multicolumn{3}{c}{post-cut} \\'
68 r' & exc & inc & user & ranking & vertex '
69 r' & absolute & ranking & unique',
70 format_string=
r'{name} & {exc_br:.3f} & {inc_br:.3f} & {user_pre_cut:.3f} & {ranking_pre_cut:.3f}'
71 r' & {vertex_pre_cut:.3f} & {absolute_post_cut:.3f}'
72 r' & {ranking_post_cut:.3f} & {after_tag:.3f}')
74 for p
in monitoringParticle:
75 table.add(name=format.decayDescriptor(p.particle.identifier),
76 exc_br=sum(p.exc_br_per_channel.values()),
77 inc_br=sum(p.inc_br_per_channel.values()),
78 user_pre_cut=sum(p.before_ranking.values()).efficiency,
79 ranking_pre_cut=sum(p.after_ranking.values()).efficiency,
80 vertex_pre_cut=sum(p.after_vertex.values()).efficiency,
81 absolute_post_cut=p.before_ranking_postcut.efficiency,
82 ranking_post_cut=p.after_ranking_postcut.efficiency,
83 after_tag=p.after_tag.efficiency)
86 table = b2latex.LongTable(columnspecs=
r'c|rrrrrr',
87 caption=
'Per-particle purity before and after the applied pre- and post-cut.',
89 r' & \multicolumn{3}{c}{pre-cut} & \multicolumn{3}{c}{post-cut} \\'
90 r' & user & ranking & vertex '
91 r' & absolute & ranking & unique',
92 format_string=
r'{name} & {user_pre_cut:.3f} & {ranking_pre_cut:.3f}'
93 r' & {vertex_pre_cut:.3f} & {absolute_post_cut:.3f}'
94 r' & {ranking_post_cut:.3f} & {after_tag:.3f}')
96 for p
in monitoringParticle:
97 table.add(name=format.decayDescriptor(p.particle.identifier),
98 user_pre_cut=sum(p.before_ranking.values()).purity,
99 ranking_pre_cut=sum(p.after_ranking.values()).purity,
100 vertex_pre_cut=sum(p.after_vertex.values()).purity,
101 absolute_post_cut=p.before_ranking_postcut.purity,
102 ranking_post_cut=p.after_ranking_postcut.purity,
103 after_tag=p.after_tag.purity)
107 moduleTypes = [
'ParticleCombiner',
'MVAExpert',
'MCMatch',
'ParticleVertexFitter',
'BestCandidateSelection',
'Other']
109 o += b2latex.Section(
"CPU time").finish()
110 colour_list = b2latex.DefineColourList()
111 o += colour_list.finish()
113 for p
in monitoringParticle:
114 o += b2latex.SubSection(format.decayDescriptor(p.particle.identifier)).finish()
116 table = b2latex.LongTable(columnspecs=
r'lrcrr',
117 caption=
'Total CPU time spent in event() calls for each channel. Bars show ' +
118 ', '.join(f
'\\textcolor{{{c}}}{{{m}}}'
119 for c, m
in zip(colour_list.colours, moduleTypes)) +
120 ', in this order. Does not include I/O, initialisation, training, post-cuts etc.',
121 head=
r'Decay & CPU time & by module & per (true) candidate & Relative time ',
122 format_string=
r'{name} & {time} & {bargraph} & {timePerCandidate} & {timePercent:.2f}\% ')
124 tt_channel = sum(p.module_statistic.channel_time.values())
125 tt_particle = p.module_statistic.particle_time + sum(p.module_statistic.channel_time.values())
126 fraction = tt_channel / tt_particle * 100
if tt_particle > 0
else 0.0
128 for channel
in p.particle.channels:
129 time = p.time_per_channel[channel.label]
130 trueCandidates = p.after_classifier[channel.label].nSig
131 allCandidates = p.after_classifier[channel.label].nTotal
133 if trueCandidates == 0
or allCandidates == 0:
136 timePerCandidate = format.duration(time / trueCandidates) +
' (' + format.duration(time / allCandidates) +
')'
137 timePercent = time / tt_particle * 100
if tt_particle > 0
else 0
139 percents = [p.module_statistic.channel_time_per_module[channel.label].get(key, 0.0) / float(time) * 100.0
140 if time > 0
else 0.0
for key
in moduleTypes[:-1]]
141 percents.append(100.0 - sum(percents))
143 table.add(name=format.decayDescriptor(channel.label),
144 bargraph=
r'\plotbar{ %g/, %g/, %g/, %g/, %g/, %g/, }' % tuple(percents),
145 time=format.duration(time),
146 timePerCandidate=timePerCandidate,
147 timePercent=time / tt_particle * 100
if p.total_time > 0
else 0)
149 o += table.finish(tail=f
'Total & & {format.duration(tt_channel)} / {format.duration(tt_particle)} & & {fraction:.2f}')
151 for p
in monitoringParticle:
152 print(p.particle.identifier)
154 o += b2latex.Section(format.decayDescriptor(p.particle.identifier)).finish()
155 string = b2latex.String(
r"In the reconstruction of {name} {nChannels} out of {max_nChannels} possible channels were used. "
156 r"The covered inclusive / exclusive branching fractions is {inc_br:.5f} / {exc_br:.5f}."
157 r"The final unique efficiency and purity was {eff:.5f} / {pur:.5f}")
159 o += string.finish(name=format.decayDescriptor(p.particle.identifier),
160 nChannels=p.reconstructed_number_of_channels,
161 max_nChannels=p.total_number_of_channels,
162 exc_br=sum(p.exc_br_per_channel.values()),
163 inc_br=sum(p.inc_br_per_channel.values()),
164 eff=p.after_tag.efficiency,
165 pur=p.after_tag.purity)
167 roc_plot_filename = monitoring.removeJPsiSlash(p.particle.identifier +
'_ROC')
168 monitoring.MonitorROCPlot(p, roc_plot_filename)
169 o += b2latex.Graphics().add(roc_plot_filename +
'.png', width=0.8).finish()
171 diag_plot_filename = monitoring.removeJPsiSlash(p.particle.identifier +
'_Diag')
172 monitoring.MonitorDiagPlot(p, diag_plot_filename)
173 o += b2latex.Graphics().add(diag_plot_filename +
'.png', width=0.8).finish()
175 if p.particle.identifier
in [
'B+:generic',
'B0:generic',
'B_s0:generic']:
176 money_plot_filename = monitoring.removeJPsiSlash(p.particle.identifier +
'_Money')
177 monitoring.MonitorMbcPlot(p, money_plot_filename)
178 g = b2latex.Graphics()
179 for filename
in glob.glob(money_plot_filename +
'_*.png'):
180 g.add(filename, width=0.49)
183 if p.particle.identifier
in [
'B+:semileptonic',
'B0:semileptonic']:
184 money_plot_filename = monitoring.removeJPsiSlash(p.particle.identifier +
'_Money')
185 monitoring.MonitorCosBDLPlot(p, money_plot_filename)
186 g = b2latex.Graphics()
187 for filename
in glob.glob(money_plot_filename +
'_*.png'):
188 g.add(filename, width=0.49)
191 table = b2latex.LongTable(columnspecs=
r'c|rr|rrr',
192 caption=
'Per-channel efficiency before and after the applied pre-cut.',
193 head=
r'Particle & \multicolumn{2}{c}{Covered BR} '
194 r' & \multicolumn{3}{c}{pre-cut} \\'
195 r' & exc & inc & user & ranking & vertex ',
196 format_string=
r'{name} & {exc_br:.3f} & {inc_br:.3f} & {user_pre_cut:.5f} & '
197 r'{ranking_pre_cut:.5f} & {vertex_pre_cut:.5f}')
199 for channel
in p.particle.channels:
200 table.add(name=format.decayDescriptor(channel.label),
201 exc_br=p.exc_br_per_channel[channel.label],
202 inc_br=p.inc_br_per_channel[channel.label],
203 user_pre_cut=p.before_ranking[channel.label].efficiency,
204 ranking_pre_cut=p.after_ranking[channel.label].efficiency,
205 vertex_pre_cut=p.after_vertex[channel.label].efficiency,
206 absolute_post_cut=p.before_ranking_postcut.efficiency,
207 ranking_post_cut=p.after_ranking_postcut.efficiency,
208 after_tag=p.after_tag.efficiency)
211 table = b2latex.LongTable(columnspecs=
r'c|c|rrr',
212 caption=
'Per-channel purity before and after the applied pre-cut.',
213 head=
r'Particle & Ignored '
214 r' & \multicolumn{3}{c}{pre-cut} \\'
215 r' && user & ranking & vertex ',
216 format_string=
r'{name} & {ignored} & {user_pre_cut:.5f} & {ranking_pre_cut:.5f}'
217 r' & {vertex_pre_cut:.5f}')
219 for channel
in p.particle.channels:
220 table.add(name=format.decayDescriptor(channel.label),
221 ignored=
r'\textcolor{red}{$\blacksquare$}' if p.ignored_channels[channel.label]
else '',
222 user_pre_cut=p.before_ranking[channel.label].purity,
223 ranking_pre_cut=p.after_ranking[channel.label].purity,
224 vertex_pre_cut=p.after_vertex[channel.label].purity)
227 o.save(output_file, compile=
False)