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=
'Total & & {tt_channel} / {tt_particle} & & {fraction:.2f}'.format(
150 tt_channel=format.duration(tt_channel), tt_particle=format.duration(tt_particle), fraction=fraction))
152 for p
in monitoringParticle:
153 print(p.particle.identifier)
155 o += b2latex.Section(format.decayDescriptor(p.particle.identifier)).finish()
156 string = b2latex.String(
r"In the reconstruction of {name} {nChannels} out of {max_nChannels} possible channels were used. "
157 r"The covered inclusive / exclusive branching fractions is {inc_br:.5f} / {exc_br:.5f}."
158 r"The final unique efficiency and purity was {eff:.5f} / {pur:.5f}")
160 o += string.finish(name=format.decayDescriptor(p.particle.identifier),
161 nChannels=p.reconstructed_number_of_channels,
162 max_nChannels=p.total_number_of_channels,
163 exc_br=sum(p.exc_br_per_channel.values()),
164 inc_br=sum(p.inc_br_per_channel.values()),
165 eff=p.after_tag.efficiency,
166 pur=p.after_tag.purity)
168 roc_plot_filename = monitoring.removeJPsiSlash(p.particle.identifier +
'_ROC')
169 monitoring.MonitorROCPlot(p, roc_plot_filename)
170 o += b2latex.Graphics().add(roc_plot_filename +
'.png', width=0.8).finish()
172 diag_plot_filename = monitoring.removeJPsiSlash(p.particle.identifier +
'_Diag')
173 monitoring.MonitorDiagPlot(p, diag_plot_filename)
174 o += b2latex.Graphics().add(diag_plot_filename +
'.png', width=0.8).finish()
176 if p.particle.identifier
in [
'B+:generic',
'B0:generic',
'B_s0:generic']:
177 money_plot_filename = monitoring.removeJPsiSlash(p.particle.identifier +
'_Money')
178 monitoring.MonitorMbcPlot(p, money_plot_filename)
179 g = b2latex.Graphics()
180 for filename
in glob.glob(money_plot_filename +
'_*.png'):
181 g.add(filename, width=0.49)
184 if p.particle.identifier
in [
'B+:semileptonic',
'B0:semileptonic']:
185 money_plot_filename = monitoring.removeJPsiSlash(p.particle.identifier +
'_Money')
186 monitoring.MonitorCosBDLPlot(p, money_plot_filename)
187 g = b2latex.Graphics()
188 for filename
in glob.glob(money_plot_filename +
'_*.png'):
189 g.add(filename, width=0.49)
192 table = b2latex.LongTable(columnspecs=
r'c|rr|rrr',
193 caption=
'Per-channel efficiency before and after the applied pre-cut.',
194 head=
r'Particle & \multicolumn{2}{c}{Covered BR} '
195 r' & \multicolumn{3}{c}{pre-cut} \\'
196 r' & exc & inc & user & ranking & vertex ',
197 format_string=
r'{name} & {exc_br:.3f} & {inc_br:.3f} & {user_pre_cut:.5f} & '
198 r'{ranking_pre_cut:.5f} & {vertex_pre_cut:.5f}')
200 for channel
in p.particle.channels:
201 table.add(name=format.decayDescriptor(channel.label),
202 exc_br=p.exc_br_per_channel[channel.label],
203 inc_br=p.inc_br_per_channel[channel.label],
204 user_pre_cut=p.before_ranking[channel.label].efficiency,
205 ranking_pre_cut=p.after_ranking[channel.label].efficiency,
206 vertex_pre_cut=p.after_vertex[channel.label].efficiency,
207 absolute_post_cut=p.before_ranking_postcut.efficiency,
208 ranking_post_cut=p.after_ranking_postcut.efficiency,
209 after_tag=p.after_tag.efficiency)
212 table = b2latex.LongTable(columnspecs=
r'c|c|rrr',
213 caption=
'Per-channel purity before and after the applied pre-cut.',
214 head=
r'Particle & Ignored '
215 r' & \multicolumn{3}{c}{pre-cut} \\'
216 r' && user & ranking & vertex ',
217 format_string=
r'{name} & {ignored} & {user_pre_cut:.5f} & {ranking_pre_cut:.5f}'
218 r' & {vertex_pre_cut:.5f}')
220 for channel
in p.particle.channels:
221 table.add(name=format.decayDescriptor(channel.label),
222 ignored=
r'\textcolor{red}{$\blacksquare$}' if p.ignored_channels[channel.label]
else '',
223 user_pre_cut=p.before_ranking[channel.label].purity,
224 ranking_pre_cut=p.after_ranking[channel.label].purity,
225 vertex_pre_cut=p.after_vertex[channel.label].purity)
228 o.save(output_file, compile=
False)