174 def plot_coverage(self, fig=None, axs=None):
175 """
176 Plots the coverage of the ntuple.
177 """
178 if self.plot_values is None:
179 return
180 vars = set(sum([list(d.keys()) for d in self.plot_values.values()], []))
181 if fig is None:
182 fig, axs = plt.subplots(len(self.plot_values), len(vars), figsize=(5*len(vars), 3*len(self.plot_values)), dpi=120)
183 axs = np.array(axs)
184 if len(axs.shape) < 1:
185 axs = axs.reshape(len(self.plot_values), len(vars))
186 bin_plt = {'linewidth': 3, 'linestyle': '--', 'color': '0.5'}
187 fig.suptitle(f'{self.type} particle {self.prefix.strip("_")}')
188 for (reco_pdg, mc_pdg), ax_row in zip(self.plot_values, axs):
189 for var, ax in zip(self.plot_values[(reco_pdg, mc_pdg)], ax_row):
190 ymin = 0
191 ymax = self.plot_values[(reco_pdg, mc_pdg)][var][1].max()*1.1
192
193 if self.type == 'PID':
194 ax.vlines(self.pdg_binning[(reco_pdg, mc_pdg)][var], ymin, ymax,
195 label='Binning',
196 alpha=0.8,
197 **bin_plt)
198 elif self.type == 'FEI':
199 values = np.array([int(val[4:]) for val in self.pdg_binning[(reco_pdg, mc_pdg)][var]])
200 ax.bar(values+0.5,
201 np.ones(len(values))*ymax,
202 width=1,
203 alpha=0.5,
204 label='Binning',
205 **bin_plt)
206 rest = np.setdiff1d(self.plot_values[(reco_pdg, mc_pdg)][var][0], values)
207 ax.bar(rest+0.5,
208 np.ones(len(rest))*ymax,
209 width=1,
210 alpha=0.2,
211 label='Rest category',
212 **bin_plt)
213
214 widths = (self.plot_values[(reco_pdg, mc_pdg)][var][0][1:] - self.plot_values[(reco_pdg, mc_pdg)][var][0][:-1])
215 centers = self.plot_values[(reco_pdg, mc_pdg)][var][0][:-1] + widths/2
216 ax.bar(centers,
217 self.plot_values[(reco_pdg, mc_pdg)][var][1],
218 width=widths,
219 label='Values',
220 alpha=0.8)
221 ax.set_title(f'True {pdg.to_name(mc_pdg)} to reco {pdg.to_name(reco_pdg)} coverage')
222 ax.set_xlabel(var)
223 axs[-1][-1].legend()
224 fig.tight_layout()
225 return fig, axs
226
227