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