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
24from fei
import monitoring
26from B2Tools
import b2latex
27from B2Tools
import format
33if __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)