257 def plot_coverage(self, fig=None, axs=None):
258 """
259 Plots the coverage of the ntuple.
260 """
261 if self.plot_values is None:
262 return
263 vars = set(sum([list(d.keys()) for d in self.plot_values.values()], []))
264 if fig is None:
265 fig, axs = plt.subplots(len(self.plot_values), len(vars), figsize=(5 * len(vars), 3 * len(self.plot_values)), dpi=120)
266 axs = np.array(axs)
267 if len(axs.shape) < 2:
268 axs = axs.reshape(len(self.plot_values), len(vars))
269 bin_plt = {'linewidth': 3, 'linestyle': '--', 'color': '0.5'}
270 fig.suptitle(f'{self.type} particle {self.prefix.strip("_")}')
271 for (reco_pdg, mc_pdg), ax_row in zip(self.plot_values, axs):
272 for var, ax in zip(self.plot_values[(reco_pdg, mc_pdg)], ax_row):
273 ymin = 0
274 ymax = self.plot_values[(reco_pdg, mc_pdg)][var][1].max() * 1.1
275
276 if self.type == 'PID':
277 ax.vlines(self.pdg_binning[(reco_pdg, mc_pdg)][var], ymin, ymax,
278 label='Binning',
279 alpha=0.8,
280 **bin_plt)
281 elif self.type == 'FEI':
282 values = np.array([int(val[4:]) for val in self.pdg_binning[(reco_pdg, mc_pdg)][var]])
283 ax.bar(values + 0.5,
284 np.ones(len(values)) * ymax,
285 width=1,
286 alpha=0.5,
287 label='Binning',
288 **bin_plt)
289 rest = np.setdiff1d(self.plot_values[(reco_pdg, mc_pdg)][var][0], values)
290 ax.bar(rest + 0.5,
291 np.ones(len(rest)) * ymax,
292 width=1,
293 alpha=0.2,
294 label='Rest category',
295 **bin_plt)
296
297 widths = (self.plot_values[(reco_pdg, mc_pdg)][var][0][1:] - self.plot_values[(reco_pdg, mc_pdg)][var][0][:-1])
298 centers = self.plot_values[(reco_pdg, mc_pdg)][var][0][:-1] + widths / 2
299 ax.bar(centers,
300 self.plot_values[(reco_pdg, mc_pdg)][var][1],
301 width=widths,
302 label='Values',
303 alpha=0.8)
304 ax.set_title(f'True {pdg.to_name(mc_pdg)} to reco {pdg.to_name(reco_pdg)} coverage')
305 ax.set_xlabel(var)
306 axs[-1][-1].legend()
307 fig.tight_layout()
308 return fig, axs
309
310