We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
plot_ppc - KeyError: "['y'] var names are not present in dataset"
Hi, I've had troubles using `plot_ppc` in a project I'm working on, so I tried to reproduce it using the quickstart pystan example. This is the code I'm using:

```python
schools_code = """
data {
  int<lower=0> J;
  real y[J];
  real<lower=0> sigma[J];
}

parameters {
  real mu;
  real<lower=0> tau;
  real theta[J];
}

model {
  mu ~ normal(0, 5);
  tau ~ cauchy(0, 5);
  theta ~ normal(mu, tau);
  y ~ normal(theta, sigma);
}
generated quantities {
    vector[J] log_lik;
    vector[J] y_hat;
    for (j in 1:J) {
        log_lik[j] = normal_lpdf(y[j] | theta[j], sigma[j]);
        y_hat[j] = normal_rng(theta[j], sigma[j]);
    }
}
"""

schools_dat = {'J': 8,
               'y': [28,  8, -3,  7, -1,  1, 18, 12],
               'sigma': [15, 10, 16, 11,  9, 11, 10, 18]}

sm = pystan.StanModel(model_code=schools_code, verbose=False)
fit = sm.sampling(data=schools_dat, iter=1000, chains=4)

data = az.from_pystan(posterior=fit,
                      posterior_predictive='y_hat',
                      observed_data=['y'],
                      log_likelihood='log_lik',
                      coords={'school': schools},
                      dims={'theta': ['school'], 'y': ['school'], 'log_lik': ['school'], 'y_hat': ['school'], 'theta_tilde': ['school']})

az.plot_ppc(data)
```

This raises:

```python
KeyError: "['y'] var names are not present in dataset"
```

which is exactly the kind of error I got in my own project... I guess I'm doing something wrong, here, but I can't figure out what it is.

Any help would be appreciated... thanks!

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `arviz/plots/ppcplot.py`
Content:
```
1 """Posterior/Prior predictive plot."""
2 from numbers import Integral
3 import platform
4 import logging
5 import numpy as np
6 
7 from .plot_utils import (
8     xarray_var_iter,
9     _scale_fig_size,
10     default_grid,
11     filter_plotters_list,
12     get_plotting_function,
13 )
14 from ..utils import _var_names
15 
16 _log = logging.getLogger(__name__)
17 
18 
19 def plot_ppc(
20     data,
21     kind="kde",
22     alpha=None,
23     mean=True,
24     figsize=None,
25     textsize=None,
26     data_pairs=None,
27     var_names=None,
28     coords=None,
29     flatten=None,
30     flatten_pp=None,
31     num_pp_samples=None,
32     random_seed=None,
33     jitter=None,
34     animated=False,
35     animation_kwargs=None,
36     legend=True,
37     ax=None,
38     backend=None,
39     backend_kwargs=None,
40     group="posterior",
41     show=None,
42 ):
43     """
44     Plot for posterior/prior predictive checks.
45 
46     Parameters
47     ----------
48     data : az.InferenceData object
49         InferenceData object containing the observed and posterior/prior predictive data.
50     kind : str
51         Type of plot to display (kde, cumulative, or scatter). Defaults to kde.
52     alpha : float
53         Opacity of posterior/prior predictive density curves.
54         Defaults to 0.2 for kind = kde and cumulative, for scatter defaults to 0.7
55     mean : bool
56         Whether or not to plot the mean posterior/prior predictive distribution. Defaults to True
57     figsize : tuple
58         Figure size. If None it will be defined automatically.
59     textsize: float
60         Text size scaling factor for labels, titles and lines. If None it will be
61         autoscaled based on figsize.
62     data_pairs : dict
63         Dictionary containing relations between observed data and posterior/prior predictive data.
64         Dictionary structure:
65         Key = data var_name
66         Value = posterior/prior predictive var_name
67         For example, `data_pairs = {'y' : 'y_hat'}`
68         If None, it will assume that the observed data and the posterior/prior
69         predictive data have the same variable name.
70     var_names : list
71         List of variables to be plotted. Defaults to all observed variables in the
72         model if None.
73     coords : dict
74         Dictionary mapping dimensions to selected coordinates to be plotted.
75         Dimensions without a mapping specified will include all coordinates for
76         that dimension. Defaults to including all coordinates for all
77         dimensions if None.
78     flatten : list
79         List of dimensions to flatten in observed_data. Only flattens across the coordinates
80         specified in the coords argument. Defaults to flattening all of the dimensions.
81     flatten_pp : list
82         List of dimensions to flatten in posterior_predictive/prior_predictive. Only flattens
83         across the coordinates specified in the coords argument. Defaults to flattening all
84         of the dimensions. Dimensions should match flatten excluding dimensions for data_pairs
85         parameters. If flatten is defined and flatten_pp is None, then `flatten_pp=flatten`.
86     num_pp_samples : int
87         The number of posterior/prior predictive samples to plot. For `kind` = 'scatter' and
88         `animation = False` if defaults to a maximum of 5 samples and will set jitter to 0.7
89         unless defined otherwise. Otherwise it defaults to all provided samples.
90     random_seed : int
91         Random number generator seed passed to numpy.random.seed to allow
92         reproducibility of the plot. By default, no seed will be provided
93         and the plot will change each call if a random sample is specified
94         by `num_pp_samples`.
95     jitter : float
96         If kind is "scatter", jitter will add random uniform noise to the height
97         of the ppc samples and observed data. By default 0.
98     animated : bool
99         Create an animation of one posterior/prior predictive sample per frame. Defaults to False.
100     animation_kwargs : dict
101         Keywords passed to `animation.FuncAnimation`.
102     legend : bool
103         Add legend to figure. By default True.
104     ax: axes, optional
105         Matplotlib axes or bokeh figures.
106     backend: str, optional
107         Select plotting backend {"matplotlib","bokeh"}. Default "matplotlib".
108     backend_kwargs: bool, optional
109         These are kwargs specific to the backend being used. For additional documentation
110         check the plotting method of the backend.
111     group : {"prior", "posterior"}, optional
112         Specifies which InferenceData group should be plotted. Defaults to 'posterior'.
113         Other value can be 'prior'.
114     show : bool, optional
115         Call backend show function.
116 
117     Returns
118     -------
119     axes : matplotlib axes or bokeh figures
120 
121     Examples
122     --------
123     Plot the observed data KDE overlaid on posterior predictive KDEs.
124 
125     .. plot::
126         :context: close-figs
127 
128         >>> import arviz as az
129         >>> data = az.load_arviz_data('radon')
130         >>> az.plot_ppc(data,data_pairs={"obs":"obs"})
131 
132     Plot the overlay with empirical CDFs.
133 
134     .. plot::
135         :context: close-figs
136 
137         >>> az.plot_ppc(data, kind='cumulative')
138 
139     Use the coords and flatten parameters to plot selected variable dimensions
140     across multiple plots.
141 
142     .. plot::
143         :context: close-figs
144 
145         >>> az.plot_ppc(data, coords={'observed_county': ['ANOKA', 'BELTRAMI']}, flatten=[])
146 
147     Plot the overlay using a stacked scatter plot that is particularly useful
148     when the sample sizes are small.
149 
150     .. plot::
151         :context: close-figs
152 
153         >>> az.plot_ppc(data, kind='scatter', flatten=[],
154         >>>             coords={'observed_county': ['AITKIN', 'BELTRAMI']})
155 
156     Plot random posterior predictive sub-samples.
157 
158     .. plot::
159         :context: close-figs
160 
161         >>> az.plot_ppc(data, num_pp_samples=30, random_seed=7)
162     """
163     if group not in ("posterior", "prior"):
164         raise TypeError("`group` argument must be either `posterior` or `prior`")
165 
166     for groups in ("{}_predictive".format(group), "observed_data"):
167         if not hasattr(data, groups):
168             raise TypeError(
169                 '`data` argument must have the group "{group}" for ppcplot'.format(group=groups)
170             )
171 
172     if kind.lower() not in ("kde", "cumulative", "scatter"):
173         raise TypeError("`kind` argument must be either `kde`, `cumulative`, or `scatter`")
174 
175     if data_pairs is None:
176         data_pairs = {}
177 
178     if animation_kwargs is None:
179         animation_kwargs = {}
180     if platform.system() == "Linux":
181         animation_kwargs.setdefault("blit", True)
182     else:
183         animation_kwargs.setdefault("blit", False)
184 
185     if animated and backend == "bokeh":
186         raise TypeError("Animation option is only supported with matplotlib backend.")
187 
188     if animated and animation_kwargs["blit"] and platform.system() != "Linux":
189         _log.warning(
190             "If you experience problems rendering the animation try setting"
191             "`animation_kwargs({'blit':False}) or changing the plotting backend (e.g. to TkAgg)"
192         )
193 
194     if alpha is None:
195         if animated:
196             alpha = 1
197         else:
198             if kind.lower() == "scatter":
199                 alpha = 0.7
200             else:
201                 alpha = 0.2
202 
203     if jitter is None:
204         jitter = 0.0
205     assert jitter >= 0.0
206 
207     observed = data.observed_data
208 
209     if group == "posterior":
210         predictive_dataset = data.posterior_predictive
211     elif group == "prior":
212         predictive_dataset = data.prior_predictive
213 
214     if var_names is None:
215         var_names = list(observed.data_vars)
216     var_names = _var_names(var_names, observed)
217     pp_var_names = [data_pairs.get(var, var) for var in var_names]
218     pp_var_names = _var_names(pp_var_names, predictive_dataset)
219 
220     if flatten_pp is None and flatten is None:
221         flatten_pp = list(predictive_dataset.dims.keys())
222     elif flatten_pp is None:
223         flatten_pp = flatten
224     if flatten is None:
225         flatten = list(observed.dims.keys())
226 
227     if coords is None:
228         coords = {}
229 
230     if random_seed is not None:
231         np.random.seed(random_seed)
232 
233     total_pp_samples = predictive_dataset.sizes["chain"] * predictive_dataset.sizes["draw"]
234     if num_pp_samples is None:
235         if kind == "scatter" and not animated:
236             num_pp_samples = min(5, total_pp_samples)
237         else:
238             num_pp_samples = total_pp_samples
239 
240     if (
241         not isinstance(num_pp_samples, Integral)
242         or num_pp_samples < 1
243         or num_pp_samples > total_pp_samples
244     ):
245         raise TypeError(
246             "`num_pp_samples` must be an integer between 1 and "
247             + "{limit}.".format(limit=total_pp_samples)
248         )
249 
250     pp_sample_ix = np.random.choice(total_pp_samples, size=num_pp_samples, replace=False)
251 
252     for key in coords.keys():
253         coords[key] = np.where(np.in1d(observed[key], coords[key]))[0]
254 
255     obs_plotters = filter_plotters_list(
256         list(
257             xarray_var_iter(
258                 observed.isel(coords), skip_dims=set(flatten), var_names=var_names, combined=True
259             )
260         ),
261         "plot_ppc",
262     )
263     length_plotters = len(obs_plotters)
264     pp_plotters = [
265         tup
266         for _, tup in zip(
267             range(length_plotters),
268             xarray_var_iter(
269                 predictive_dataset.isel(coords),
270                 var_names=pp_var_names,
271                 skip_dims=set(flatten_pp),
272                 combined=True,
273             ),
274         )
275     ]
276     rows, cols = default_grid(length_plotters)
277 
278     (figsize, ax_labelsize, _, xt_labelsize, linewidth, markersize) = _scale_fig_size(
279         figsize, textsize, rows, cols
280     )
281 
282     ppcplot_kwargs = dict(
283         ax=ax,
284         length_plotters=length_plotters,
285         rows=rows,
286         cols=cols,
287         figsize=figsize,
288         animated=animated,
289         obs_plotters=obs_plotters,
290         pp_plotters=pp_plotters,
291         predictive_dataset=predictive_dataset,
292         pp_sample_ix=pp_sample_ix,
293         kind=kind,
294         alpha=alpha,
295         linewidth=linewidth,
296         mean=mean,
297         xt_labelsize=xt_labelsize,
298         ax_labelsize=ax_labelsize,
299         jitter=jitter,
300         total_pp_samples=total_pp_samples,
301         legend=legend,
302         markersize=markersize,
303         animation_kwargs=animation_kwargs,
304         num_pp_samples=num_pp_samples,
305         backend_kwargs=backend_kwargs,
306         show=show,
307     )
308 
309     if backend == "bokeh":
310 
311         ppcplot_kwargs.pop("animated")
312         ppcplot_kwargs.pop("animation_kwargs")
313         ppcplot_kwargs.pop("legend")
314         ppcplot_kwargs.pop("xt_labelsize")
315         ppcplot_kwargs.pop("ax_labelsize")
316 
317     # TODO: Add backend kwargs
318     plot = get_plotting_function("plot_ppc", "ppcplot", backend)
319     axes = plot(**ppcplot_kwargs)
320     return axes
321
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/arviz/plots/ppcplot.py b/arviz/plots/ppcplot.py
--- a/arviz/plots/ppcplot.py
+++ b/arviz/plots/ppcplot.py
@@ -62,8 +62,8 @@
     data_pairs : dict
         Dictionary containing relations between observed data and posterior/prior predictive data.
         Dictionary structure:
-        Key = data var_name
-        Value = posterior/prior predictive var_name
+            key = data var_name
+            value = posterior/prior predictive var_name
         For example, `data_pairs = {'y' : 'y_hat'}`
         If None, it will assume that the observed data and the posterior/prior
         predictive data have the same variable name.
@@ -128,6 +128,7 @@
         >>> import arviz as az
         >>> data = az.load_arviz_data('radon')
         >>> az.plot_ppc(data,data_pairs={"obs":"obs"})
+        >>> #az.plot_ppc(data,data_pairs={"obs":"obs_hat"})
 
     Plot the overlay with empirical CDFs.

{"golden_diff": "diff --git a/arviz/plots/ppcplot.py b/arviz/plots/ppcplot.py\n--- a/arviz/plots/ppcplot.py\n+++ b/arviz/plots/ppcplot.py\n@@ -62,8 +62,8 @@\n     data_pairs : dict\n         Dictionary containing relations between observed data and posterior/prior predictive data.\n         Dictionary structure:\n-        Key = data var_name\n-        Value = posterior/prior predictive var_name\n+            key = data var_name\n+            value = posterior/prior predictive var_name\n         For example, `data_pairs = {'y' : 'y_hat'}`\n         If None, it will assume that the observed data and the posterior/prior\n         predictive data have the same variable name.\n@@ -128,6 +128,7 @@\n         >>> import arviz as az\n         >>> data = az.load_arviz_data('radon')\n         >>> az.plot_ppc(data,data_pairs={\"obs\":\"obs\"})\n+        >>> #az.plot_ppc(data,data_pairs={\"obs\":\"obs_hat\"})\n \n     Plot the overlay with empirical CDFs.\n", "issue": "plot_ppc - KeyError: \"['y'] var names are not present in dataset\"\nHi, I've had troubles using `plot_ppc` in a project I'm working on, so I tried to reproduce it using the quickstart pystan example. This is the code I'm using:\r\n\r\n```python\r\nschools_code = \"\"\"\r\ndata {\r\n  int<lower=0> J;\r\n  real y[J];\r\n  real<lower=0> sigma[J];\r\n}\r\n\r\nparameters {\r\n  real mu;\r\n  real<lower=0> tau;\r\n  real theta[J];\r\n}\r\n\r\nmodel {\r\n  mu ~ normal(0, 5);\r\n  tau ~ cauchy(0, 5);\r\n  theta ~ normal(mu, tau);\r\n  y ~ normal(theta, sigma);\r\n}\r\ngenerated quantities {\r\n    vector[J] log_lik;\r\n    vector[J] y_hat;\r\n    for (j in 1:J) {\r\n        log_lik[j] = normal_lpdf(y[j] | theta[j], sigma[j]);\r\n        y_hat[j] = normal_rng(theta[j], sigma[j]);\r\n    }\r\n}\r\n\"\"\"\r\n\r\nschools_dat = {'J': 8,\r\n               'y': [28,  8, -3,  7, -1,  1, 18, 12],\r\n               'sigma': [15, 10, 16, 11,  9, 11, 10, 18]}\r\n\r\nsm = pystan.StanModel(model_code=schools_code, verbose=False)\r\nfit = sm.sampling(data=schools_dat, iter=1000, chains=4)\r\n\r\ndata = az.from_pystan(posterior=fit,\r\n                      posterior_predictive='y_hat',\r\n                      observed_data=['y'],\r\n                      log_likelihood='log_lik',\r\n                      coords={'school': schools},\r\n                      dims={'theta': ['school'], 'y': ['school'], 'log_lik': ['school'], 'y_hat': ['school'], 'theta_tilde': ['school']})\r\n\r\naz.plot_ppc(data)\r\n```\r\n\r\nThis raises:\r\n\r\n```python\r\nKeyError: \"['y'] var names are not present in dataset\"\r\n```\r\n\r\nwhich is exactly the kind of error I got in my own project... I guess I'm doing something wrong, here, but I can't figure out what it is.\r\n\r\nAny help would be appreciated... thanks!\n", "before_files": [{"content": "\"\"\"Posterior/Prior predictive plot.\"\"\"\nfrom numbers import Integral\nimport platform\nimport logging\nimport numpy as np\n\nfrom .plot_utils import (\n    xarray_var_iter,\n    _scale_fig_size,\n    default_grid,\n    filter_plotters_list,\n    get_plotting_function,\n)\nfrom ..utils import _var_names\n\n_log = logging.getLogger(__name__)\n\n\ndef plot_ppc(\n    data,\n    kind=\"kde\",\n    alpha=None,\n    mean=True,\n    figsize=None,\n    textsize=None,\n    data_pairs=None,\n    var_names=None,\n    coords=None,\n    flatten=None,\n    flatten_pp=None,\n    num_pp_samples=None,\n    random_seed=None,\n    jitter=None,\n    animated=False,\n    animation_kwargs=None,\n    legend=True,\n    ax=None,\n    backend=None,\n    backend_kwargs=None,\n    group=\"posterior\",\n    show=None,\n):\n    \"\"\"\n    Plot for posterior/prior predictive checks.\n\n    Parameters\n    ----------\n    data : az.InferenceData object\n        InferenceData object containing the observed and posterior/prior predictive data.\n    kind : str\n        Type of plot to display (kde, cumulative, or scatter). Defaults to kde.\n    alpha : float\n        Opacity of posterior/prior predictive density curves.\n        Defaults to 0.2 for kind = kde and cumulative, for scatter defaults to 0.7\n    mean : bool\n        Whether or not to plot the mean posterior/prior predictive distribution. Defaults to True\n    figsize : tuple\n        Figure size. If None it will be defined automatically.\n    textsize: float\n        Text size scaling factor for labels, titles and lines. If None it will be\n        autoscaled based on figsize.\n    data_pairs : dict\n        Dictionary containing relations between observed data and posterior/prior predictive data.\n        Dictionary structure:\n        Key = data var_name\n        Value = posterior/prior predictive var_name\n        For example, `data_pairs = {'y' : 'y_hat'}`\n        If None, it will assume that the observed data and the posterior/prior\n        predictive data have the same variable name.\n    var_names : list\n        List of variables to be plotted. Defaults to all observed variables in the\n        model if None.\n    coords : dict\n        Dictionary mapping dimensions to selected coordinates to be plotted.\n        Dimensions without a mapping specified will include all coordinates for\n        that dimension. Defaults to including all coordinates for all\n        dimensions if None.\n    flatten : list\n        List of dimensions to flatten in observed_data. Only flattens across the coordinates\n        specified in the coords argument. Defaults to flattening all of the dimensions.\n    flatten_pp : list\n        List of dimensions to flatten in posterior_predictive/prior_predictive. Only flattens\n        across the coordinates specified in the coords argument. Defaults to flattening all\n        of the dimensions. Dimensions should match flatten excluding dimensions for data_pairs\n        parameters. If flatten is defined and flatten_pp is None, then `flatten_pp=flatten`.\n    num_pp_samples : int\n        The number of posterior/prior predictive samples to plot. For `kind` = 'scatter' and\n        `animation = False` if defaults to a maximum of 5 samples and will set jitter to 0.7\n        unless defined otherwise. Otherwise it defaults to all provided samples.\n    random_seed : int\n        Random number generator seed passed to numpy.random.seed to allow\n        reproducibility of the plot. By default, no seed will be provided\n        and the plot will change each call if a random sample is specified\n        by `num_pp_samples`.\n    jitter : float\n        If kind is \"scatter\", jitter will add random uniform noise to the height\n        of the ppc samples and observed data. By default 0.\n    animated : bool\n        Create an animation of one posterior/prior predictive sample per frame. Defaults to False.\n    animation_kwargs : dict\n        Keywords passed to `animation.FuncAnimation`.\n    legend : bool\n        Add legend to figure. By default True.\n    ax: axes, optional\n        Matplotlib axes or bokeh figures.\n    backend: str, optional\n        Select plotting backend {\"matplotlib\",\"bokeh\"}. Default \"matplotlib\".\n    backend_kwargs: bool, optional\n        These are kwargs specific to the backend being used. For additional documentation\n        check the plotting method of the backend.\n    group : {\"prior\", \"posterior\"}, optional\n        Specifies which InferenceData group should be plotted. Defaults to 'posterior'.\n        Other value can be 'prior'.\n    show : bool, optional\n        Call backend show function.\n\n    Returns\n    -------\n    axes : matplotlib axes or bokeh figures\n\n    Examples\n    --------\n    Plot the observed data KDE overlaid on posterior predictive KDEs.\n\n    .. plot::\n        :context: close-figs\n\n        >>> import arviz as az\n        >>> data = az.load_arviz_data('radon')\n        >>> az.plot_ppc(data,data_pairs={\"obs\":\"obs\"})\n\n    Plot the overlay with empirical CDFs.\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_ppc(data, kind='cumulative')\n\n    Use the coords and flatten parameters to plot selected variable dimensions\n    across multiple plots.\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_ppc(data, coords={'observed_county': ['ANOKA', 'BELTRAMI']}, flatten=[])\n\n    Plot the overlay using a stacked scatter plot that is particularly useful\n    when the sample sizes are small.\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_ppc(data, kind='scatter', flatten=[],\n        >>>             coords={'observed_county': ['AITKIN', 'BELTRAMI']})\n\n    Plot random posterior predictive sub-samples.\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_ppc(data, num_pp_samples=30, random_seed=7)\n    \"\"\"\n    if group not in (\"posterior\", \"prior\"):\n        raise TypeError(\"`group` argument must be either `posterior` or `prior`\")\n\n    for groups in (\"{}_predictive\".format(group), \"observed_data\"):\n        if not hasattr(data, groups):\n            raise TypeError(\n                '`data` argument must have the group \"{group}\" for ppcplot'.format(group=groups)\n            )\n\n    if kind.lower() not in (\"kde\", \"cumulative\", \"scatter\"):\n        raise TypeError(\"`kind` argument must be either `kde`, `cumulative`, or `scatter`\")\n\n    if data_pairs is None:\n        data_pairs = {}\n\n    if animation_kwargs is None:\n        animation_kwargs = {}\n    if platform.system() == \"Linux\":\n        animation_kwargs.setdefault(\"blit\", True)\n    else:\n        animation_kwargs.setdefault(\"blit\", False)\n\n    if animated and backend == \"bokeh\":\n        raise TypeError(\"Animation option is only supported with matplotlib backend.\")\n\n    if animated and animation_kwargs[\"blit\"] and platform.system() != \"Linux\":\n        _log.warning(\n            \"If you experience problems rendering the animation try setting\"\n            \"`animation_kwargs({'blit':False}) or changing the plotting backend (e.g. to TkAgg)\"\n        )\n\n    if alpha is None:\n        if animated:\n            alpha = 1\n        else:\n            if kind.lower() == \"scatter\":\n                alpha = 0.7\n            else:\n                alpha = 0.2\n\n    if jitter is None:\n        jitter = 0.0\n    assert jitter >= 0.0\n\n    observed = data.observed_data\n\n    if group == \"posterior\":\n        predictive_dataset = data.posterior_predictive\n    elif group == \"prior\":\n        predictive_dataset = data.prior_predictive\n\n    if var_names is None:\n        var_names = list(observed.data_vars)\n    var_names = _var_names(var_names, observed)\n    pp_var_names = [data_pairs.get(var, var) for var in var_names]\n    pp_var_names = _var_names(pp_var_names, predictive_dataset)\n\n    if flatten_pp is None and flatten is None:\n        flatten_pp = list(predictive_dataset.dims.keys())\n    elif flatten_pp is None:\n        flatten_pp = flatten\n    if flatten is None:\n        flatten = list(observed.dims.keys())\n\n    if coords is None:\n        coords = {}\n\n    if random_seed is not None:\n        np.random.seed(random_seed)\n\n    total_pp_samples = predictive_dataset.sizes[\"chain\"] * predictive_dataset.sizes[\"draw\"]\n    if num_pp_samples is None:\n        if kind == \"scatter\" and not animated:\n            num_pp_samples = min(5, total_pp_samples)\n        else:\n            num_pp_samples = total_pp_samples\n\n    if (\n        not isinstance(num_pp_samples, Integral)\n        or num_pp_samples < 1\n        or num_pp_samples > total_pp_samples\n    ):\n        raise TypeError(\n            \"`num_pp_samples` must be an integer between 1 and \"\n            + \"{limit}.\".format(limit=total_pp_samples)\n        )\n\n    pp_sample_ix = np.random.choice(total_pp_samples, size=num_pp_samples, replace=False)\n\n    for key in coords.keys():\n        coords[key] = np.where(np.in1d(observed[key], coords[key]))[0]\n\n    obs_plotters = filter_plotters_list(\n        list(\n            xarray_var_iter(\n                observed.isel(coords), skip_dims=set(flatten), var_names=var_names, combined=True\n            )\n        ),\n        \"plot_ppc\",\n    )\n    length_plotters = len(obs_plotters)\n    pp_plotters = [\n        tup\n        for _, tup in zip(\n            range(length_plotters),\n            xarray_var_iter(\n                predictive_dataset.isel(coords),\n                var_names=pp_var_names,\n                skip_dims=set(flatten_pp),\n                combined=True,\n            ),\n        )\n    ]\n    rows, cols = default_grid(length_plotters)\n\n    (figsize, ax_labelsize, _, xt_labelsize, linewidth, markersize) = _scale_fig_size(\n        figsize, textsize, rows, cols\n    )\n\n    ppcplot_kwargs = dict(\n        ax=ax,\n        length_plotters=length_plotters,\n        rows=rows,\n        cols=cols,\n        figsize=figsize,\n        animated=animated,\n        obs_plotters=obs_plotters,\n        pp_plotters=pp_plotters,\n        predictive_dataset=predictive_dataset,\n        pp_sample_ix=pp_sample_ix,\n        kind=kind,\n        alpha=alpha,\n        linewidth=linewidth,\n        mean=mean,\n        xt_labelsize=xt_labelsize,\n        ax_labelsize=ax_labelsize,\n        jitter=jitter,\n        total_pp_samples=total_pp_samples,\n        legend=legend,\n        markersize=markersize,\n        animation_kwargs=animation_kwargs,\n        num_pp_samples=num_pp_samples,\n        backend_kwargs=backend_kwargs,\n        show=show,\n    )\n\n    if backend == \"bokeh\":\n\n        ppcplot_kwargs.pop(\"animated\")\n        ppcplot_kwargs.pop(\"animation_kwargs\")\n        ppcplot_kwargs.pop(\"legend\")\n        ppcplot_kwargs.pop(\"xt_labelsize\")\n        ppcplot_kwargs.pop(\"ax_labelsize\")\n\n    # TODO: Add backend kwargs\n    plot = get_plotting_function(\"plot_ppc\", \"ppcplot\", backend)\n    axes = plot(**ppcplot_kwargs)\n    return axes\n", "path": "arviz/plots/ppcplot.py"}], "after_files": [{"content": "\"\"\"Posterior/Prior predictive plot.\"\"\"\nfrom numbers import Integral\nimport platform\nimport logging\nimport numpy as np\n\nfrom .plot_utils import (\n    xarray_var_iter,\n    _scale_fig_size,\n    default_grid,\n    filter_plotters_list,\n    get_plotting_function,\n)\nfrom ..utils import _var_names\n\n_log = logging.getLogger(__name__)\n\n\ndef plot_ppc(\n    data,\n    kind=\"kde\",\n    alpha=None,\n    mean=True,\n    figsize=None,\n    textsize=None,\n    data_pairs=None,\n    var_names=None,\n    coords=None,\n    flatten=None,\n    flatten_pp=None,\n    num_pp_samples=None,\n    random_seed=None,\n    jitter=None,\n    animated=False,\n    animation_kwargs=None,\n    legend=True,\n    ax=None,\n    backend=None,\n    backend_kwargs=None,\n    group=\"posterior\",\n    show=None,\n):\n    \"\"\"\n    Plot for posterior/prior predictive checks.\n\n    Parameters\n    ----------\n    data : az.InferenceData object\n        InferenceData object containing the observed and posterior/prior predictive data.\n    kind : str\n        Type of plot to display (kde, cumulative, or scatter). Defaults to kde.\n    alpha : float\n        Opacity of posterior/prior predictive density curves.\n        Defaults to 0.2 for kind = kde and cumulative, for scatter defaults to 0.7\n    mean : bool\n        Whether or not to plot the mean posterior/prior predictive distribution. Defaults to True\n    figsize : tuple\n        Figure size. If None it will be defined automatically.\n    textsize: float\n        Text size scaling factor for labels, titles and lines. If None it will be\n        autoscaled based on figsize.\n    data_pairs : dict\n        Dictionary containing relations between observed data and posterior/prior predictive data.\n        Dictionary structure:\n            key = data var_name\n            value = posterior/prior predictive var_name\n        For example, `data_pairs = {'y' : 'y_hat'}`\n        If None, it will assume that the observed data and the posterior/prior\n        predictive data have the same variable name.\n    var_names : list\n        List of variables to be plotted. Defaults to all observed variables in the\n        model if None.\n    coords : dict\n        Dictionary mapping dimensions to selected coordinates to be plotted.\n        Dimensions without a mapping specified will include all coordinates for\n        that dimension. Defaults to including all coordinates for all\n        dimensions if None.\n    flatten : list\n        List of dimensions to flatten in observed_data. Only flattens across the coordinates\n        specified in the coords argument. Defaults to flattening all of the dimensions.\n    flatten_pp : list\n        List of dimensions to flatten in posterior_predictive/prior_predictive. Only flattens\n        across the coordinates specified in the coords argument. Defaults to flattening all\n        of the dimensions. Dimensions should match flatten excluding dimensions for data_pairs\n        parameters. If flatten is defined and flatten_pp is None, then `flatten_pp=flatten`.\n    num_pp_samples : int\n        The number of posterior/prior predictive samples to plot. For `kind` = 'scatter' and\n        `animation = False` if defaults to a maximum of 5 samples and will set jitter to 0.7\n        unless defined otherwise. Otherwise it defaults to all provided samples.\n    random_seed : int\n        Random number generator seed passed to numpy.random.seed to allow\n        reproducibility of the plot. By default, no seed will be provided\n        and the plot will change each call if a random sample is specified\n        by `num_pp_samples`.\n    jitter : float\n        If kind is \"scatter\", jitter will add random uniform noise to the height\n        of the ppc samples and observed data. By default 0.\n    animated : bool\n        Create an animation of one posterior/prior predictive sample per frame. Defaults to False.\n    animation_kwargs : dict\n        Keywords passed to `animation.FuncAnimation`.\n    legend : bool\n        Add legend to figure. By default True.\n    ax: axes, optional\n        Matplotlib axes or bokeh figures.\n    backend: str, optional\n        Select plotting backend {\"matplotlib\",\"bokeh\"}. Default \"matplotlib\".\n    backend_kwargs: bool, optional\n        These are kwargs specific to the backend being used. For additional documentation\n        check the plotting method of the backend.\n    group : {\"prior\", \"posterior\"}, optional\n        Specifies which InferenceData group should be plotted. Defaults to 'posterior'.\n        Other value can be 'prior'.\n    show : bool, optional\n        Call backend show function.\n\n    Returns\n    -------\n    axes : matplotlib axes or bokeh figures\n\n    Examples\n    --------\n    Plot the observed data KDE overlaid on posterior predictive KDEs.\n\n    .. plot::\n        :context: close-figs\n\n        >>> import arviz as az\n        >>> data = az.load_arviz_data('radon')\n        >>> az.plot_ppc(data,data_pairs={\"obs\":\"obs\"})\n        >>> #az.plot_ppc(data,data_pairs={\"obs\":\"obs_hat\"})\n\n    Plot the overlay with empirical CDFs.\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_ppc(data, kind='cumulative')\n\n    Use the coords and flatten parameters to plot selected variable dimensions\n    across multiple plots.\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_ppc(data, coords={'observed_county': ['ANOKA', 'BELTRAMI']}, flatten=[])\n\n    Plot the overlay using a stacked scatter plot that is particularly useful\n    when the sample sizes are small.\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_ppc(data, kind='scatter', flatten=[],\n        >>>             coords={'observed_county': ['AITKIN', 'BELTRAMI']})\n\n    Plot random posterior predictive sub-samples.\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_ppc(data, num_pp_samples=30, random_seed=7)\n    \"\"\"\n    if group not in (\"posterior\", \"prior\"):\n        raise TypeError(\"`group` argument must be either `posterior` or `prior`\")\n\n    for groups in (\"{}_predictive\".format(group), \"observed_data\"):\n        if not hasattr(data, groups):\n            raise TypeError(\n                '`data` argument must have the group \"{group}\" for ppcplot'.format(group=groups)\n            )\n\n    if kind.lower() not in (\"kde\", \"cumulative\", \"scatter\"):\n        raise TypeError(\"`kind` argument must be either `kde`, `cumulative`, or `scatter`\")\n\n    if data_pairs is None:\n        data_pairs = {}\n\n    if animation_kwargs is None:\n        animation_kwargs = {}\n    if platform.system() == \"Linux\":\n        animation_kwargs.setdefault(\"blit\", True)\n    else:\n        animation_kwargs.setdefault(\"blit\", False)\n\n    if animated and backend == \"bokeh\":\n        raise TypeError(\"Animation option is only supported with matplotlib backend.\")\n\n    if animated and animation_kwargs[\"blit\"] and platform.system() != \"Linux\":\n        _log.warning(\n            \"If you experience problems rendering the animation try setting\"\n            \"`animation_kwargs({'blit':False}) or changing the plotting backend (e.g. to TkAgg)\"\n        )\n\n    if alpha is None:\n        if animated:\n            alpha = 1\n        else:\n            if kind.lower() == \"scatter\":\n                alpha = 0.7\n            else:\n                alpha = 0.2\n\n    if jitter is None:\n        jitter = 0.0\n    assert jitter >= 0.0\n\n    observed = data.observed_data\n\n    if group == \"posterior\":\n        predictive_dataset = data.posterior_predictive\n    elif group == \"prior\":\n        predictive_dataset = data.prior_predictive\n\n    if var_names is None:\n        var_names = list(observed.data_vars)\n    var_names = _var_names(var_names, observed)\n    pp_var_names = [data_pairs.get(var, var) for var in var_names]\n    pp_var_names = _var_names(pp_var_names, predictive_dataset)\n\n    if flatten_pp is None and flatten is None:\n        flatten_pp = list(predictive_dataset.dims.keys())\n    elif flatten_pp is None:\n        flatten_pp = flatten\n    if flatten is None:\n        flatten = list(observed.dims.keys())\n\n    if coords is None:\n        coords = {}\n\n    if random_seed is not None:\n        np.random.seed(random_seed)\n\n    total_pp_samples = predictive_dataset.sizes[\"chain\"] * predictive_dataset.sizes[\"draw\"]\n    if num_pp_samples is None:\n        if kind == \"scatter\" and not animated:\n            num_pp_samples = min(5, total_pp_samples)\n        else:\n            num_pp_samples = total_pp_samples\n\n    if (\n        not isinstance(num_pp_samples, Integral)\n        or num_pp_samples < 1\n        or num_pp_samples > total_pp_samples\n    ):\n        raise TypeError(\n            \"`num_pp_samples` must be an integer between 1 and \"\n            + \"{limit}.\".format(limit=total_pp_samples)\n        )\n\n    pp_sample_ix = np.random.choice(total_pp_samples, size=num_pp_samples, replace=False)\n\n    for key in coords.keys():\n        coords[key] = np.where(np.in1d(observed[key], coords[key]))[0]\n\n    obs_plotters = filter_plotters_list(\n        list(\n            xarray_var_iter(\n                observed.isel(coords), skip_dims=set(flatten), var_names=var_names, combined=True\n            )\n        ),\n        \"plot_ppc\",\n    )\n    length_plotters = len(obs_plotters)\n    pp_plotters = [\n        tup\n        for _, tup in zip(\n            range(length_plotters),\n            xarray_var_iter(\n                predictive_dataset.isel(coords),\n                var_names=pp_var_names,\n                skip_dims=set(flatten_pp),\n                combined=True,\n            ),\n        )\n    ]\n    rows, cols = default_grid(length_plotters)\n\n    (figsize, ax_labelsize, _, xt_labelsize, linewidth, markersize) = _scale_fig_size(\n        figsize, textsize, rows, cols\n    )\n\n    ppcplot_kwargs = dict(\n        ax=ax,\n        length_plotters=length_plotters,\n        rows=rows,\n        cols=cols,\n        figsize=figsize,\n        animated=animated,\n        obs_plotters=obs_plotters,\n        pp_plotters=pp_plotters,\n        predictive_dataset=predictive_dataset,\n        pp_sample_ix=pp_sample_ix,\n        kind=kind,\n        alpha=alpha,\n        linewidth=linewidth,\n        mean=mean,\n        xt_labelsize=xt_labelsize,\n        ax_labelsize=ax_labelsize,\n        jitter=jitter,\n        total_pp_samples=total_pp_samples,\n        legend=legend,\n        markersize=markersize,\n        animation_kwargs=animation_kwargs,\n        num_pp_samples=num_pp_samples,\n        backend_kwargs=backend_kwargs,\n        show=show,\n    )\n\n    if backend == \"bokeh\":\n\n        ppcplot_kwargs.pop(\"animated\")\n        ppcplot_kwargs.pop(\"animation_kwargs\")\n        ppcplot_kwargs.pop(\"legend\")\n        ppcplot_kwargs.pop(\"xt_labelsize\")\n        ppcplot_kwargs.pop(\"ax_labelsize\")\n\n    # TODO: Add backend kwargs\n    plot = get_plotting_function(\"plot_ppc\", \"ppcplot\", backend)\n    axes = plot(**ppcplot_kwargs)\n    return axes\n", "path": "arviz/plots/ppcplot.py"}]}