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)