Repository: arviz-devs/arviz

Issue:
Change pair_plot behavior for MCMC methods that do not produce divergences
**Describe the bug**
When using metropolis hasting sampler in pymc3, then converting to inference data, then using `az.pair_plot(divergences=True)` raises an index error

**To Reproduce**
```
import matplotlib.pyplot as plt
import arviz as az
import pymc3 as pm

x = [1,2]
y = [1,2]
with pm.Model() as model_g:
    α = pm.Normal('α', mu=0, sd=10)
    β = pm.Normal('β', mu=0, sd=1)
    ϵ = pm.HalfCauchy('ϵ', 5)

    μ = pm.Deterministic('μ', α + β * x)
    y_pred = pm.Normal('y_pred', mu=μ, sd=ϵ, observed=y)

# NUTS sampler works when plotting divergences
"""
with model_g:
    trace_nuts_non_centered = pm.sample()

nuts_non_centered_dataset = az.from_pymc3(trace=trace_nuts_non_centered)
az.plot_pair(nuts_non_centered_dataset, var_names=['α', 'β', 'ϵ'], divergences=True)

plt.show()
"""

# Metropolis Hastings raises indexerror
with model_g:
    step = pm.Metropolis()
    trace_mh_non_centered = pm.sample(step=step)

az.plot_pair(trace_mh_non_centered, var_names=['α', 'β', 'ϵ'], divergences=True)
plt.show()
```



**Expected behavior**
~~Divergences are plotted as expected~~
Show a warning and continue plotting

**Additional context**
Versions of `arviz` and other libraries used, operating system used, and anything else that may be useful.

Arviz Version  '0.3.3'
PyMC3 Version : '3.6'




Discussion:

Resolving patch:
diff --git a/arviz/plots/kdeplot.py b/arviz/plots/kdeplot.py
--- a/arviz/plots/kdeplot.py
+++ b/arviz/plots/kdeplot.py
@@ -27,6 +27,8 @@ def plot_kde(
     fill_kwargs=None,
     rug_kwargs=None,
     contour_kwargs=None,
+    contourf_kwargs=None,
+    pcolormesh_kwargs=None,
     ax=None,
     legend=True,
 ):
@@ -71,7 +73,11 @@ def plot_kde(
         Use `space` keyword (float) to control the position of the rugplot. The larger this number
         the lower the rugplot.
     contour_kwargs : dict
-        Keywords passed to the contourplot. Ignored for 1D KDE.
+        Keywords passed to ax.contour. Ignored for 1D KDE.
+    contourf_kwargs : dict
+        Keywords passed to ax.contourf. Ignored for 1D KDE.
+    pcolormesh_kwargs : dict
+        Keywords passed to ax.pcolormesh. Ignored for 1D KDE.
     ax : matplotlib axes
     legend : bool
         Add legend to the figure. By default True.
@@ -227,6 +233,10 @@ def plot_kde(
         if contour_kwargs is None:
             contour_kwargs = {}
         contour_kwargs.setdefault("colors", "0.5")
+        if contourf_kwargs is None:
+            contourf_kwargs = {}
+        if pcolormesh_kwargs is None:
+            pcolormesh_kwargs = {}
 
         gridsize = (128, 128) if contour else (256, 256)
 
@@ -238,14 +248,13 @@ def plot_kde(
         ax.set_xlim(xmin, xmax)
         ax.set_ylim(ymin, ymax)
         if contour:
-            qcfs = ax.contourf(x_x, y_y, density, antialiased=True)
-            if not fill_last:
-                qcfs.collections[0].set_alpha(0)
+            qcfs = ax.contourf(x_x, y_y, density, antialiased=True, **contourf_kwargs)
             qcs = ax.contour(x_x, y_y, density, **contour_kwargs)
             if not fill_last:
+                qcfs.collections[0].set_alpha(0)
                 qcs.collections[0].set_alpha(0)
         else:
-            ax.pcolormesh(x_x, y_y, density)
+            ax.pcolormesh(x_x, y_y, density, **pcolormesh_kwargs)
 
     return ax
 
diff --git a/arviz/plots/pairplot.py b/arviz/plots/pairplot.py
--- a/arviz/plots/pairplot.py
+++ b/arviz/plots/pairplot.py
@@ -1,10 +1,11 @@
 """Plot a scatter or hexbin of sampled parameters."""
+import warnings
 import numpy as np
 import matplotlib.pyplot as plt
 from matplotlib.ticker import NullFormatter
 from mpl_toolkits.axes_grid1 import make_axes_locatable
 
-from ..data import convert_to_dataset
+from ..data import convert_to_dataset, convert_to_inference_data
 from .kdeplot import plot_kde
 from .plot_utils import _scale_fig_size, xarray_to_ndarray, get_coords
 from ..utils import _var_names
@@ -133,6 +134,7 @@ def plot_pair(
     divergences_kwargs.setdefault("lw", 0)
 
     # Get posterior draws and combine chains
+    data = convert_to_inference_data(data)
     posterior_data = convert_to_dataset(data, group="posterior")
     var_names = _var_names(var_names, posterior_data)
     flat_var_names, _posterior = xarray_to_ndarray(
@@ -141,11 +143,21 @@ def plot_pair(
 
     # Get diverging draws and combine chains
     if divergences:
-        divergent_data = convert_to_dataset(data, group="sample_stats")
-        _, diverging_mask = xarray_to_ndarray(
-            divergent_data, var_names=("diverging",), combined=True
-        )
-        diverging_mask = np.squeeze(diverging_mask)
+        if hasattr(data, "sample_stats") and hasattr(data.sample_stats, "diverging"):
+            divergent_data = convert_to_dataset(data, group="sample_stats")
+            _, diverging_mask = xarray_to_ndarray(
+                divergent_data, var_names=("diverging",), combined=True
+            )
+            diverging_mask = np.squeeze(diverging_mask)
+        else:
+            divergences = False
+            warnings.warn(
+                "Divergences data not found, plotting without divergences. "
+                "Make sure the sample method provides divergences data and "
+                "that it is present in the `diverging` field of `sample_stats` "
+                "or set divergences=False",
+                SyntaxWarning,
+            )
 
     if gridsize == "auto":
         gridsize = int(len(_posterior[0]) ** 0.35)


Test patch:
diff --git a/arviz/tests/test_plots.py b/arviz/tests/test_plots.py
--- a/arviz/tests/test_plots.py
+++ b/arviz/tests/test_plots.py
@@ -272,7 +272,13 @@ def test_plot_joint_bad(models, model_fit):
     [
         {"plot_kwargs": {"linestyle": "-"}},
         {"contour": True, "fill_last": False},
+        {
+            "contour": True,
+            "contourf_kwargs": {"cmap": "plasma"},
+            "contour_kwargs": {"linewidths": 1},
+        },
         {"contour": False},
+        {"contour": False, "pcolormesh_kwargs": {"cmap": "plasma"}},
     ],
 )
 def test_plot_kde(continuous_model, kwargs):
@@ -280,7 +286,15 @@ def test_plot_kde(continuous_model, kwargs):
     assert axes
 
 
-@pytest.mark.parametrize("kwargs", [{"cumulative": True}, {"rug": True}])
+@pytest.mark.parametrize(
+    "kwargs",
+    [
+        {"cumulative": True},
+        {"cumulative": True, "plot_kwargs": {"linestyle": "--"}},
+        {"rug": True},
+        {"rug": True, "rug_kwargs": {"alpha": 0.2}},
+    ],
+)
 def test_plot_kde_cumulative(continuous_model, kwargs):
     axes = plot_kde(continuous_model["x"], quantiles=[0.25, 0.5, 0.75], **kwargs)
     assert axes
@@ -387,6 +401,20 @@ def test_plot_pair_bad(models, model_fit):
         plot_pair(obj, var_names=["mu"])
 
 
+@pytest.mark.parametrize("has_sample_stats", [True, False])
+def test_plot_pair_divergences_warning(has_sample_stats):
+    data = load_arviz_data("centered_eight")
+    if has_sample_stats:
+        # sample_stats present, diverging field missing
+        data.sample_stats = data.sample_stats.rename({"diverging": "diverging_missing"})
+    else:
+        # sample_stats missing
+        data = data.posterior
+    with pytest.warns(SyntaxWarning):
+        ax = plot_pair(data, divergences=True)
+    assert np.all(ax)
+
+
 @pytest.mark.parametrize("kind", ["density", "cumulative", "scatter"])
 @pytest.mark.parametrize("alpha", [None, 0.2, 1])
 @pytest.mark.parametrize("animated", [False, True])