13 Provides class for tracking retention rate of each cut in a skim.
17 import matplotlib.pyplot
as plt
19 from ROOT
import Belle2
25 """Check the retention rate and the number of candidates for a given set of particle lists.
27 The module stores its results in the static variable "summary".
29 To monitor the effect of every module of an initial path, this module should be added after
30 each module of the path. A function was written (`skim.utils.retention.pathWithRetentionCheck`) to do it:
32 >>> path = pathWithRetentionCheck(particle_lists, path)
34 After the path processing, the result of the RetentionCheck can be printed with
36 >>> RetentionCheck.print_results()
38 or plotted with (check the corresponding documentation)
40 >>> RetentionCheck.plot_retention(...)
42 and the summary dictionary can be accessed through
44 >>> RetentionCheck.summary
48 Cyrille Praz, Slavomira Stefkova
52 module_name (str): name of the module after which the retention rate is measured
53 module_number (int): index of the module after which the retention rate is measured
54 particle_lists (list(str)): list of particle list names which will be tracked by the module
58 output_override =
None
60 def __init__(self, module_name='', module_number=0, particle_lists=None):
62 if particle_lists
is None:
74 type(self).summary[self.
_key_key] = {}
76 if type(self).output_override
is None:
92 if pl.getListSize() != 0:
109 b2.B2WARNING(
"Belle2.Environment.Instance().getNumberOfEvents() gives 0 or less.")
112 type(self).summary[self.
_key_key][particle_list] = {
"retention_rate": retention_rate,
119 """ Print the results, should be called after the path processing."""
121 table_headline =
"{:<100}|{:>9}|{:>12}|{:>22}|{:>12}|\n"
122 table_line =
"{:<100}|{:>9.3f}|{:>12}|{:>22}|{:>12}|\n"
126 for module, module_results
in cls.
summarysummary.items():
128 for particle_list, list_results
in module_results.items():
130 if particle_list
not in summary_tables.keys():
132 atLeastOneEntry[particle_list] =
False
134 summary_tables[particle_list] = table_headline.format(
135 "Module",
"Retention",
"# Candidates",
"# Evts with candidates",
"Total # evts")
136 summary_tables[particle_list] +=
"=" * 160 +
"\n"
140 if list_results[
"retention_rate"] > 0
or atLeastOneEntry[particle_list]:
142 atLeastOneEntry[particle_list] =
True
143 if len(module) > 100:
144 module = module[:96] +
"..."
145 summary_tables[particle_list] += table_line.format(module, *list_results.values())
147 for particle_list, summary_table
in summary_tables.items():
148 b2.B2INFO(
"\n" +
"=" * 160 +
"\n" +
149 "Results of the modules RetentionCheck for the list " + particle_list +
".\n" +
151 "Note: the module RetentionCheck is defined in skim/scripts/skim/utils/retention.py\n" +
155 "End of the results of the modules RetentionCheck for the list " + particle_list +
".\n" +
160 def plot_retention(cls, particle_list, plot_title="", save_as=None, module_name_max_length=80):
161 """ Plot the result of the RetentionCheck for a given particle list.
163 Example of use (to be put after process(path)):
165 >>> RetentionCheck.plot_retention('B+:semileptonic','skim:feiSLBplus','retention_plots/plot.pdf')
169 particle_list (str): particle list name
170 title (str): plot title (overwritten by the -o argument in basf2)
171 save_as (str): output filename (overwritten by the -o argument in basf2)
172 module_name_max_length (int): if the module name length is higher than this value, do not display the full name
177 at_least_one_entry =
False
178 for module, results
in cls.
summarysummary.items():
180 if particle_list
not in results.keys():
181 b2.B2WARNING(particle_list +
" is not present in the results of the RetentionCheck for the module {}."
185 if results[particle_list][
'retention_rate'] > 0
or at_least_one_entry:
186 at_least_one_entry =
True
187 if len(module) > module_name_max_length
and module_name_max_length > 3:
188 module = module[:module_name_max_length - 3] +
"..."
189 module_name.append(module)
190 retention.append(100 * (results[particle_list][
'retention_rate']))
192 if not at_least_one_entry:
193 b2.B2WARNING(particle_list +
" seems to have a zero retention rate when created (if created).")
197 bars = plt.barh(module_name, retention, label=particle_list, color=(0.67, 0.15, 0.31, 0.6))
200 yval = bar.get_width()
201 plt.text(0.5, bar.get_y() + bar.get_height() / 2.0 + 0.1, str(round(yval, 3)))
203 plt.gca().invert_yaxis()
204 plt.xticks(rotation=45)
206 plt.axvline(x=10.0, linewidth=1, linestyle=
"--", color=
'k', alpha=0.5)
207 plt.xlabel(
'Retention Rate [%]')
208 plt.legend(loc=
'lower right')
213 save_as = plot_title +
'.pdf'
215 os.makedirs(os.path.dirname(save_as), exist_ok=
True)
216 plt.title(plot_title)
217 plt.savefig(save_as, bbox_inches=
"tight")
218 b2.B2RESULT(
"Retention rate results for list {} saved in {}."
219 .format(particle_list, os.getcwd() +
"/" + save_as))
222 def pathWithRetentionCheck(particle_lists, path):
223 """ Return a new path with the module RetentionCheck inserted between each module of a given path.
225 This allows for checking how the retention rate is modified by each module of the path.
227 Example of use (to be put just before process(path)):
229 >>> path = pathWithRetentionCheck(['B+:semileptonic'], path)
231 Warning: pathWithRetentionCheck(['B+:semileptonic'], path) does not modify path,
232 it only returns a new one.
234 After the path processing, the result of the RetentionCheck can be printed with
236 >>> RetentionCheck.print_results()
238 or plotted with (check the corresponding documentation)
240 >>> RetentionCheck.plot_retention(...)
242 and the summary dictionary can be accessed through
244 >>> RetentionCheck.summary
248 particle_lists (list(str)): list of particle list names which will be tracked by RetentionCheck
249 path (basf2.Path): initial path (it is not modified, see warning above and example of use)
252 for module_number, module
in enumerate(path.modules()):
253 new_path.add_module(module)
254 if 'ParticleSelector' in module.name():
255 name = module.name() +
'(' + module.available_params()[0].values +
')'
258 new_path.add_module(
RetentionCheck(name, module_number, particle_lists))
static Environment & Instance()
Static method to get a reference to the Environment instance.
a (simplified) python wrapper for StoreObjPtr.
def plot_retention(cls, particle_list, plot_title="", save_as=None, module_name_max_length=80)
event_with_candidate_count