import numpy as np
import matplotlib.pyplot as plt
from .wedges import Wedge
from .utils import array_or_dict
[docs]class VegaPlots:
def __init__(self, vega_data=None):
"""Initialize plotting module with the vega internal info
Parameters
----------
vega_data : vega.Data, optional
Vega data object, by default None
models : List[np.array] or List[dict], optional
List of models, by default None
"""
self.cross_flag = {}
self.data = {}
self.cov_mat = {}
self.rp_setup_model = {}
self.rt_setup_model = {}
self.r_setup_model = {}
self.rp_setup_data = {}
self.rt_setup_data = {}
self.r_setup_data = {}
self.has_data = False
self.cuts = {}
self.mask = {}
if vega_data is not None:
for name, data in vega_data.items():
cross_flag = data.tracer1['type'] != data.tracer2['type']
self.cross_flag[name] = cross_flag
self.data[name] = data.data_vec
if data.has_cov_mat:
self.cov_mat[name] = data.cov_mat
# Initialize data coordinates
self.rp_setup_data[name] = (data.rp_min_data, data.rp_max_data,
data.num_bins_rp_data)
self.rt_setup_data[name] = (0., data.rt_max_data, data.num_bins_rt_data)
self.r_setup_data[name] = self.rp_setup_data[name]
self.cuts[name] = {'r_min': data.r_min_cut,
'r_max': data.r_max_cut}
if np.allclose([data.bin_size_rp_data, data.bin_size_rt_data],
[data.bin_size_rp_model, data.bin_size_rt_model]):
# Compute bin centers
bin_index_rp = np.floor((data.corr_item.rp_rt_grid[0] - data.rp_min_model)
/ data.bin_size_rp_model)
bin_center_rp = data.rp_min_model
bin_center_rp += (bin_index_rp + 0.5) * data.bin_size_rp_model
bin_index_rt = np.floor(data.corr_item.rp_rt_grid[1] / data.bin_size_rt_model)
bin_center_rt = (bin_index_rt + 0.5) * data.bin_size_rt_model
# Build the model to data mask
self.mask[name] = (bin_center_rp > data.rp_min_data)
self.mask[name] &= (bin_center_rp < data.rp_max_data)
self.mask[name] &= (bin_center_rt < data.rt_max_data)
# Initialize model coordinates
self.rp_setup_model[name] = (data.rp_min_model, data.rp_max_model,
data.num_bins_rp_model)
self.rt_setup_model[name] = (0., data.rt_max_model, data.num_bins_rt_model)
self.r_setup_model[name] = self.rp_setup_model[name]
self.has_data = True
[docs] def initialize_wedge(self, mu_bin, corr_name=None, is_data=False, cross_flag=False,
rp_setup=None, rt_setup=None, r_setup=None, abs_mu=True, **kwargs):
"""Initialize wedge object
Parameters
----------
mu_bin : (float, float)
Min and max mu value defining the wedge
corr_name : str, optional
Name of the correlation component, by default None
cross_flag : bool, optional
Whether the wedge is for the cross-correlation, by default False
rp_setup : (float, float, int), optional
(min, max, size) specification for input r_parallel, by default None
rt_setup : (float, float, int), optional
(min, max, size) specification for input r_transverse, by default None
r_setup : (float, float, int), optional
(min, max, size) specification for output isotropic r, by default None
abs_mu : bool, optional
Whether to compute wedges in abs(mu), by default True
Returns
-------
vega.Wedge
Vega wedge object
"""
if corr_name is not None:
if is_data:
rp = self.rp_setup_data[corr_name]
rt = self.rt_setup_data[corr_name]
r = self.r_setup_data[corr_name]
else:
rp = self.rp_setup_model[corr_name]
rt = self.rt_setup_model[corr_name]
r = self.r_setup_model[corr_name]
if self.cross_flag[corr_name] and abs_mu:
r = (0, rp[1], rp[2]//2)
else:
if rp_setup is not None:
rp = rp_setup
elif cross_flag:
rp = (-200., 200., 100)
else:
rp = (0., 200., 50)
rt = rt_setup if rt_setup is not None else (0., 200., 50)
r = r_setup if r_setup is not None else (0., 200., 50)
return Wedge(mu=mu_bin, rp=rp, rt=rt, r=r, abs_mu=abs_mu)
[docs] def plot_data(self, ax, mu_bin, data=None, cov_mat=None, cross_flag=False, label=None,
corr_name='lyaxlya', data_fmt='o', data_color=None,
scaling_power=2, use_local_coordinates=True, **kwargs):
"""Plot the data in the input ax object using the input wedge object
Parameters
----------
ax : plt.axes
Axes object to plot the data in
data : array or dict, optional
Data vector as an array or a dictionary of components, by default None
cov_mat : array or dict, optional
Covariance matrix as an array or a dictionary of components, by default None
label : str, optional
Label for the data points, by default None
corr_name : str, optional
Name of the correlation component, by default 'lyaxlya'
data_fmt : str, optional
Data formatting, by default 'o'
data_color : str, optional
Color for the data points, by default None
scaling_power : float, optional
The power of r that multiples the plotted correlation (xi * r^scaling_power),
by default None
use_local_coordinates : bool, optional
Whether to use the stored coordinate settings or defaul/input values, by default True
"""
if use_local_coordinates and self.has_data:
wedge_obj = self.initialize_wedge(mu_bin, corr_name, True, cross_flag, **kwargs)
else:
wedge_obj = self.initialize_wedge(mu_bin, cross_flag=cross_flag, **kwargs)
if data is None:
if corr_name not in self.data:
raise ValueError('Correlation {} not found in input data'.format(corr_name))
data = self.data[corr_name]
data_vec = array_or_dict(data, corr_name)
if cov_mat is None:
if corr_name not in self.cov_mat:
raise ValueError('Correlation {} not found in input data'.format(corr_name))
cov_mat = self.cov_mat[corr_name]
covariance = array_or_dict(cov_mat, corr_name)
rd, dd, cd = wedge_obj(data_vec, covariance=covariance)
ax.errorbar(rd, dd * rd**scaling_power, yerr=np.sqrt(cd.diagonal()) * rd**scaling_power,
fmt=data_fmt, color=data_color, label=label)
return rd, dd, cd
[docs] def plot_model(self, ax, mu_bin, model=None, cov_mat=None, cross_flag=False,
label=None, corr_name='lyaxlya', model_ls='-', model_color=None,
scaling_power=2, use_local_coordinates=True, **kwargs):
"""Plot the model in the input ax object using the input wedge object
Parameters
----------
ax : plt.axes
Axes object to plot the model in
wedge_obj : vega.Wedge
Vega wedge object for computing the wedge
model : array or dict, optional
Model vector as an array or a dictionary of components, by default None
cov_mat : array or dict, optional
Covariance matrix as an array or a dictionary of components, by default None
label : str, optional
Label for the model, by default None
corr_name : str, optional
Name of the correlation component, by default 'lyaxlya'
model_ls : str, optional
Model line style, by default '-'
model_color : str, optional
Color for the model line, by default None
scaling_power : float, optional
The power of r that multiples the plotted correlation (xi * r^scaling_power),
by default None
use_local_coordinates : bool, optional
Whether to use the stored coordinate settings or defaul/input values, by default True
"""
if cov_mat is None:
if corr_name in self.cov_mat:
cov_mat = self.cov_mat[corr_name]
covariance = None
masked_model = None
model_vec = np.array(array_or_dict(model, corr_name))
if cov_mat is not None and corr_name in self.mask:
covariance = array_or_dict(cov_mat, corr_name)
if len(self.mask[corr_name]) == len(model_vec):
masked_model = model_vec[self.mask[corr_name]]
if len(masked_model) != len(self.data[corr_name]):
raise ValueError('Masked model array does not match data array.')
if masked_model is not None:
wedge_obj = self.initialize_wedge(mu_bin, corr_name, True, cross_flag, **kwargs)
elif use_local_coordinates and self.has_data:
wedge_obj = self.initialize_wedge(mu_bin, corr_name, False, cross_flag, **kwargs)
else:
wedge_obj = self.initialize_wedge(mu_bin, cross_flag=cross_flag, **kwargs)
if cov_mat is None or wedge_obj.weights.shape[1] != cov_mat.shape[0]:
r, d = wedge_obj(model_vec)
ax.plot(r, d * r**scaling_power, ls=model_ls, color=model_color, label=label)
else:
covariance = array_or_dict(cov_mat, corr_name)
if masked_model is None:
r, d, _ = wedge_obj(model_vec, covariance=covariance)
else:
r, d, _ = wedge_obj(masked_model, covariance=covariance)
ax.plot(r, d * r**scaling_power, ls=model_ls, color=model_color, label=label)
return r, d
[docs] def plot_sensitivity(self, sensitivity, pname='ap', pname2=None, pct=95,
distorted=True, comp='both', rpow=0, save=None):
"""Plot parameter sensitivities.
Plot the sensitivity to one parameter or the joint sensitivity to a pair of parameters.
The resulting plot shows the partial derivatives of `pname` on the left-hand side and
the distribution of the Fisher information for pname or, if pname2 is specified,
(pname, pname2) on the right-hand side.
Parameters
----------
sensitivity - dict
Dictionary with keys `nominal`, `partials` and `fisher`, normally obtained by calling
`compute_sensitivity()` on a VegaInterface object, then passing its `sensitivity`
attribute here.
pname - str
Name of the first parameter to use. Partial derivatives are only displayed for this
parameter, even when pname2 is specified.
pname2 - str or None
Name of the second parameter to use. Displays the Fisher information associated with
the covariance of (pname,pname2) when specified. If None, then use (pname,pname).
pct - float
Clip the color map for values above this percentile value.
distorted - bool
Plot the sensitivity of the predicted correlation including the distortion matrix
when True. Otherwise, use the undistorted correlation function model.
comp - str
Which component of the signal model to display. Select either `peak`, `smooth`
or `both`.
rpow - float
The power of the radial weight to use for plotting the partial derivatives of pname.
save - str or None
Save the produced plot a file with this name. When None, do not save the plot.
"""
# Get the indices of the requested parameters.
pnames = list(sensitivity['nominal'].keys())
try:
pidx = pnames.index(pname)
except ValueError:
raise RuntimeError(f'Unknown floating parameter "{pname}".')
try:
pidx2 = pnames.index(pname2) if pname2 else pidx
except ValueError:
raise RuntimeError(f'Unknown floating parameter "{pname2}".')
fidx = pidx * len(pnames) + pidx2
if comp not in ('peak', 'smooth', 'both'):
raise ValueError(f'Invalid comp "{comp}" (expected peak/smooth/both)')
fig = plt.figure(figsize=(12, 9), constrained_layout=True)
pvalue, perror = sensitivity['nominal'][pname]
title = f'{pname} = {pvalue:.4f} ± {perror:.3f}'
if pname2:
pvalue2, perror2 = sensitivity['nominal'][pname2]
title += f', {pname2} = {pvalue2:.4f} ± {perror2:.3f}'
fig.suptitle(title)
gs = fig.add_gridspec(3, 4)
# Lookup the max value of the Fisher info over all datasets, to normalize the Fisher info plots.
max_info = np.max([ np.nanpercentile(sensitivity['fisher'][cname][fidx], pct) for cname in sensitivity['fisher'] ])
rtxt = '' if rpow == 0 else ('r ' if rpow == 1 else f'r**{rpow} ')
dist = 0 if distorted else 1
for cname in self.data:
rtgrid = np.linspace(*self.rt_setup_data[cname])
rpgrid = np.linspace(*self.rp_setup_data[cname])
rt, rp = np.meshgrid(rpgrid, rtgrid)
r = np.hypot(rp, rt).reshape(-1)
nrt = len(rtgrid)
nrp = len(rpgrid)
bbox = tuple(np.percentile(rp, (0, 100))) + tuple(np.percentile(rt, (0, 100)))
row = 0 if cname.startswith('lya') else slice(1,None)
col = 0 if cname.endswith('lya') else 1
y1, y2 = (0.92, 0.84) if cname.startswith('lya') else (0.96,0.92)
P = r**rpow * sensitivity['partials'][cname][pidx][dist]
if comp == 'both':
P = P.sum(axis=0)
elif comp == 'peak':
P = P[0]
elif comp == 'smooth':
P = P[1]
if np.all(P == 0):
continue
ax = fig.add_subplot(gs[row, col])
vlim = np.percentile(np.abs(P), pct)
ax.imshow(P.reshape(nrp,nrt), origin='lower', interpolation='none', cmap='seismic',
vmin=-vlim, vmax=+vlim, extent=bbox, aspect='auto')
ax.text(0.95, y1, cname + ':', ha='right', transform=ax.transAxes)
ax.text(0.95, y2, f'{rtxt}∂M(rp,rt)/∂p', ha='right', transform=ax.transAxes)
cmap = plt.get_cmap('afmhot_r').copy()
cmap.set_bad('lightgray')
# Lookup the Fisher distribution for this sample, the specified params, and distortion option.
F = sensitivity['fisher'][cname][fidx][dist]
ax = fig.add_subplot(gs[row, col + 2])
ax.imshow(F.reshape(nrp,nrt), origin='lower', interpolation='none', cmap=cmap,
vmin=0, vmax=max_info, extent=bbox, aspect='auto')
ax.text(0.95, y1, cname + ':', ha='right', transform=ax.transAxes)
ax.text(0.95, y2, '∂$^2$F$_{pq}$(rt,rp)/∂rt∂rp', ha='right', transform=ax.transAxes)
if save:
plt.savefig(save)
[docs] def postprocess_plot(self, ax, mu_bin=None, xlim=(0, 180), ylim=None, no_legend=False,
title='mu_bin', legend_loc='best', legend_ncol=1, **kwargs):
"""Add postprocessing to the plot on input axes
Parameters
----------
ax : plt.axes
Axes object to postprocess
mu_bin : array or tuple
Array or tuple containing mu_min and mu_max of the wedge
xlim : tuple, optional
Limits of the x axis, by default (0, 180)
"""
if not kwargs.get('no_ylabel', False):
ax.set_ylabel(r"$r^2\xi(r)$")
if not kwargs.get('no_xlabel', False):
ax.set_xlabel(r"$r~[\mathrm{Mpc/h}]$")
if title == 'mu_bin' and mu_bin is not None:
ax.set_title(r"${}<\mu<{}$".format(mu_bin[0], mu_bin[1]))
elif title is not None:
ax.set_title(title)
if xlim is not None:
ax.set_xlim(xlim[0], xlim[1])
if ylim is not None:
ax.set_ylim(ylim[0], ylim[1])
if not no_legend:
ax.legend(loc=legend_loc, ncol=legend_ncol)
ax.grid()
@staticmethod
def postprocess_fig(fig, xlim=(0, 180), ylim=None):
for ax in fig.axes:
ax.grid()
ax.set_xlim(xlim[0], xlim[1])
if ylim is not None:
ylim = np.array(ylim)
if ylim.ndim == 1:
for ax in fig.axes:
ax.set_ylim(ylim[0], ylim[1])
elif ylim.ndim == 2:
for ax, (ymin, ymax) in zip(fig.axes, ylim):
ax.set_ylim(ymin, ymax)
else:
raise ValueError(f'ylim variable has unsupported ndim {ylim.ndim}, '
'only 1D and 2D arrays/lists/tuples allowed')
[docs] def plot_wedge(self, ax, mu_bin, models=None, cov_mat=None, labels=None, data=None,
cross_flag=False, corr_name='lyaxlya', models_only=False,
data_only=False, data_label=None, no_postprocess=False, **kwargs):
"""Plot a wedge into the input axes using the input mu_bin
Parameters
----------
ax : plt.axes
Axes object to plot the wedge in
wedge_obj : vega.Wedge
Vega wedge object for computing the wedge
models : List[array] or List[dict], optional
List of models to plot, by default None
cov_mat : array or dict, optional
Covariance matrix as an array or a dictionary of components, by default None
labels : List[str], optional
List of labels for the models, by default None
data : array or dict, optional
Data vector as an array or a dictionary of components, by default None
cross_flag : bool, optional
Whether the wedge is for the cross-correlation, by default False
corr_name : str, optional
Name of the correlation component, by default 'lyaxlya'
models_only : bool, optional
Whether to only plot models and ignore the data, by default False
data_only : bool, optional
Whether to only plot data and ignore the models, by default False
data_label : str, optional
Label for the data, by default None
"""
# if use_local_coordinates and self.has_data:
# wedge_obj = self.initialize_wedge(mu_bin, corr_name, cross_flag, **kwargs)
# else:
# wedge_obj = self.initialize_wedge(mu_bin, cross_flag=cross_flag, **kwargs)
data_wedge = None
if not models_only:
data_wedge = self.plot_data(ax, mu_bin, data, cov_mat, cross_flag, data_label,
corr_name, **kwargs)
model_wedge = None
if not data_only:
models_colors = None
if 'model_colors' in kwargs:
models_colors = kwargs['model_colors']
models_ls = None
if 'models_ls' in kwargs:
models_ls = kwargs['models_ls']
for i, model in enumerate(models):
label = None
if labels is not None and i < len(labels):
label = labels[i]
model_color = None
if models_colors is not None:
model_color = models_colors[i]
model_ls = '-'
if models_ls is not None:
model_ls = models_ls[i]
model_wedge = self.plot_model(ax, mu_bin, model, cov_mat, cross_flag, label,
corr_name, model_ls=model_ls,
model_color=model_color, **kwargs)
if not no_postprocess:
self.postprocess_plot(ax, mu_bin, **kwargs)
return data_wedge, model_wedge
[docs] def plot_1wedge(self, models=None, cov_mat=None, labels=None, data=None, cross_flag=False,
corr_name='lyaxlya', models_only=False, data_only=False, data_label=None,
fig=None, **kwargs):
"""Plot the correlations into one wedge from mu=0 to mu=1
Parameters
----------
models : List[array] or List[dict], optional
List of models to plot, by default None
cov_mat : array or dict, optional
Covariance matrix as an array or a dictionary of components, by default None
labels : List[str], optional
List of labels for the models, by default None
data : array or dict, optional
Data vector as an array or a dictionary of components, by default None
cross_flag : bool, optional
Whether the wedge is for the cross-correlation, by default False
corr_name : str, optional
Name of the correlation component, by default 'lyaxlya'
models_only : bool, optional
Whether to only plot models and ignore the data, by default False
data_only : bool, optional
Whether to only plot data and ignore the models, by default False
data_label : str, optional
Label for the data, by default None
"""
if not kwargs.get('no_font', False):
plt.rcParams['font.size'] = 14
if fig is None:
fig, axs = plt.subplots(1, figsize=(10, 6))
else:
axs = fig.axes[0]
_ = self.plot_wedge(axs, (0, 1), models=models, cov_mat=cov_mat, labels=labels, data=data,
cross_flag=cross_flag, corr_name=corr_name, models_only=models_only,
data_only=data_only, data_label=data_label, **kwargs)
self.fig = fig
[docs] def plot_2wedges(self, mu_bins=(0, 0.5, 1), models=None, cov_mat=None, labels=None,
data=None, cross_flag=False, corr_name='lyaxlya', models_only=False,
data_only=False, data_label=None, vertical_plots=False, fig=None, **kwargs):
"""Plot the correlations into two wedges defined by the limits in mu_bins
Parameters
----------
mu_bins : tuple, optional
Limits of mu bins that define the two wedges, by default (0, 0.5, 1)
models : List[array] or List[dict], optional
List of models to plot, by default None
cov_mat : array or dict, optional
Covariance matrix as an array or a dictionary of components, by default None
labels : List[str], optional
List of labels for the models, by default None
data : array or dict, optional
Data vector as an array or a dictionary of components, by default None
cross_flag : bool, optional
Whether the wedge is for the cross-correlation, by default False
corr_name : str, optional
Name of the correlation component, by default 'lyaxlya'
models_only : bool, optional
Whether to only plot models and ignore the data, by default False
data_only : bool, optional
Whether to only plot data and ignore the models, by default False
data_label : str, optional
Label for the data, by default None
vertical_plots : bool, optional
Whether to plot the two wedges vertically, by default False
"""
assert len(mu_bins) == 3
if not kwargs.get('no_font', False):
plt.rcParams['font.size'] = 14
if fig is None:
if not vertical_plots:
fig, axs = plt.subplots(1, 2, figsize=(18, 6))
else:
fig, axs = plt.subplots(2, 1, figsize=(10, 12))
else:
axs = np.array(fig.axes)
axs = axs.flatten()
mu_bins = np.flip(np.array(mu_bins))
mu_limits = zip(mu_bins[1:], mu_bins[:-1])
for ax, mu_bin in zip(axs, mu_limits):
_ = self.plot_wedge(ax, mu_bin, models=models, cov_mat=cov_mat, labels=labels,
data=data, cross_flag=cross_flag, corr_name=corr_name,
models_only=models_only, data_only=data_only,
data_label=data_label, **kwargs)
self.fig = fig
[docs] def plot_4wedges(self, mu_bins=(0, 0.5, 0.8, 0.95, 1), models=None, cov_mat=None,
labels=None, data=None, cross_flag=False, corr_name='lyaxlya',
models_only=False, data_only=False, data_label=None, figsize=(14, 8),
mu_bin_labels=False, fig=None, **kwargs):
"""Plot the correlations into four wedges defined by the limits in mu_bins
Parameters
----------
mu_bins : tuple, optional
Limits of mu bins that define the two wedges, by default (0, 0.5, 1)
models : List[array] or List[dict], optional
List of models to plot, by default None
cov_mat : array or dict, optional
Covariance matrix as an array or a dictionary of components, by default None
labels : List[str], optional
List of labels for the models, by default None
data : array or dict, optional
Data vector as an array or a dictionary of components, by default None
cross_flag : bool, optional
Whether the wedge is for the cross-correlation, by default False
corr_name : str, optional
Name of the correlation component, by default 'lyaxlya'
models_only : bool, optional
Whether to only plot models and ignore the data, by default False
data_only : bool, optional
Whether to only plot data and ignore the models, by default False
data_label : str, optional
Label for the data, by default None
"""
assert len(mu_bins) == 5
if not kwargs.get('no_font', False):
plt.rcParams['font.size'] = 14
if fig is None:
fig, axs = plt.subplots(2, 2, figsize=figsize)
else:
axs = np.array(fig.axes)
axs = axs.flatten()
mu_bins = np.flip(np.array(mu_bins))
mu_limits = zip(mu_bins[1:], mu_bins[:-1])
no_xlabel = [True, True, False, False]
no_ylabel = [False, True, False, True]
for ax, mu_bin, no_xl, no_yl in zip(axs, mu_limits, no_xlabel, no_ylabel):
if mu_bin_labels:
data_label = r"${}<|\mu|<{}$".format(mu_bin[0], mu_bin[1])
_ = self.plot_wedge(ax, mu_bin, models=models, cov_mat=cov_mat, labels=labels,
data=data, cross_flag=cross_flag, corr_name=corr_name,
models_only=models_only, data_only=data_only,
data_label=data_label, no_xlabel=no_xl, no_ylabel=no_yl, **kwargs)
if self.has_data:
xmin, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()
ax.fill_betweenx((-100, 100), xmin, self.cuts[corr_name]['r_min'],
color='gray', alpha=0.7)
ax.fill_betweenx((-100, 100), self.cuts[corr_name]['r_max'], xmax,
color='gray', alpha=0.7)
ax.set_ylim(ymin, ymax)
ax.set_xlim(xmin, xmax)
plt.tight_layout()
self.fig = fig
[docs] def plot_4wedge_panel(self, mu_bins=(0, 0.5, 0.8, 0.95, 1), model=None, cov_mat=None,
data=None, cross_flag=False, corr_name='lyaxlya', colors=None,
data_only=False, title=None, figsize=(8, 6), fig=None, **kwargs):
"""Plot the correlations into four wedges on one panel
Parameters
----------
mu_bins : tuple, optional
Limits of mu bins that define the two wedges, by default (0, 0.5, 1)
model : array or dict, optional
Model to plot, by default None
cov_mat : array or dict, optional
Covariance matrix as an array or a dictionary of components, by default None
data : array or dict, optional
Data vector as an array or a dictionary of components, by default None
cross_flag : bool, optional
Whether the wedge is for the cross-correlation, by default False
corr_name : str, optional
Name of the correlation component, by default 'lyaxlya'
colors : List[string], optional
List of colors for the wedges, by default None
data_only : bool, optional
Whether to only plot data and ignore the models, by default False
title : string, optional
Title for plot, by default None
figsize : (float, float), optional
figsize object passed to plt.subplots, by default (10, 6)
"""
assert len(mu_bins) == 5
if not kwargs.get('no_font', False):
plt.rcParams['font.size'] = 14
if fig is None:
fig, ax = plt.subplots(1, figsize=figsize)
else:
ax = fig.axes[0]
mu_bins = np.flip(np.array(mu_bins))
mu_limits = zip(mu_bins[1:], mu_bins[:-1])
if colors is None:
cmap = plt.get_cmap('seismic')
colors = cmap((0.03, 0.25, 0.75, 1))
for mu_bin, color in zip(mu_limits, colors):
label = f'{mu_bin[0]:.2f} < ' + r'$|\mu|$' + f' < {mu_bin[1]:.2f}'
data_label = label if data_only else None
_ = self.plot_wedge(ax, mu_bin, models=[model], cov_mat=cov_mat, labels=[label],
model_colors=[color], data_color=color, data=data,
cross_flag=cross_flag, corr_name=corr_name, models_only=False,
data_only=data_only, data_label=data_label,
no_postprocess=True, **kwargs)
xmin, xmax = ax.get_xlim()
self.postprocess_plot(ax, title=title, **kwargs)
if self.has_data:
ymin, ymax = ax.get_ylim()
ax.fill_betweenx((ymin, ymax), xmin, self.cuts[corr_name]['r_min'],
color='gray', alpha=0.7)
ax.fill_betweenx((ymin, ymax), self.cuts[corr_name]['r_max'], xmax,
color='gray', alpha=0.7)
ax.set_ylim(ymin, ymax)
ax.set_xlim(xmin, xmax)
self.fig = fig