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