We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
plot_trace lines is unclear and it may yield unexpected results
**Describe the bug**
The argument `lines` for the function `plot_trace` can give unexpected results. Moreover, the documentation is a bit nebulous.
 
**To Reproduce**
A toy example is defined
```python
import pymc3 as pm
import arviz as az
import numpy as np

# fake data
mu_real = 0
sigma_real = 1
n_samples = 150

Y = np.random.normal(loc=mu_real, scale=sigma_real, size=n_samples)

with pm.Model() as model:
    mu = pm.Normal('mu', mu=0, sigma=10)  
    sigma = pm.HalfNormal('sigma', sigma=10)
    likelihood = pm.Normal('likelihood', mu=mu, sigma=sigma, observed=Y)
    trace = pm.sample()
```
As per [documentation](https://arviz-devs.github.io/arviz/generated/arviz.plot_trace.html#arviz.plot_trace), the argument `lines` accepts a tuple in the form `(var_name, {‘coord’: selection}, [line, positions])`. So, the command 
```python
az.plot_trace(trace, lines=(('mu', {}, mu_real),))
```
yields correctly 
![image](https://user-images.githubusercontent.com/18400141/69927034-b7327f80-1484-11ea-8f4c-5f52563413be.png)

I can also pass a list of tuples or a list of tuples and lists and it will work fine:
```
az.plot_trace(trace, lines=[('mu', {}, mu_real)]) # list of tuples
az.plot_trace(trace, lines=[['mu', {}, mu_real]]) # list of lists
az.plot_trace(trace, lines=[['mu', {}, mu_real], ('sigma', {}, sigma_real)]) # list of lists and tuples
```
however, I cannot pass a simple tuple because I will get a `KeyError: 0`
```python
az.plot_trace(trace, lines=(['mu', {}, mu_real]))
az.plot_trace(trace, lines=(('mu', {}, mu_real)))
```
Also, I can pass a variable or coordinate name that do not exist and Arviz will not complain---but not lines will be plotted (here I would expect a warning)
```python
az.plot_trace(trace, lines=[('hey', {}, mu_real)])
az.plot_trace(trace, lines=[('mu', {'hey'}, mu_real)])
```
![image](https://user-images.githubusercontent.com/18400141/69927389-d251bf00-1485-11ea-8d5c-7630a6763728.png)
The weird behavior happens when I pass a string:
```python
az.plot_trace(trace, lines=[('mu', {}, 'hey')])
```
![image](https://user-images.githubusercontent.com/18400141/69927502-32e0fc00-1486-11ea-8f6a-3f012017e932.png)

**Expected behavior**
The [documentation](https://arviz-devs.github.io/arviz/generated/arviz.plot_trace.html#arviz.plot_trace) could be improved and the function could check the inputs. In addition to what described above, the placeholder `[line, positions]` in `(var_name, {‘coord’: selection}, [line, positions])` should be something like `[line_positions]` otherwise one may think (like myself :) ) that two values should be inserted (one for `line` and one for `positions`).

**Additional context**
I am using Win10, fresh conda environment with PyMC3 and Arviz from master.

Possibly related https://github.com/pymc-devs/pymc3/issues/3495, https://github.com/pymc-devs/pymc3/issues/3497

--- 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/backends/matplotlib/traceplot.py`
Content:
```
1 """Matplotlib traceplot."""
2 
3 import matplotlib.pyplot as plt
4 from matplotlib.lines import Line2D
5 import numpy as np
6 
7 from . import backend_kwarg_defaults, backend_show
8 from ...distplot import plot_dist
9 from ...plot_utils import _scale_fig_size, get_bins, make_label
10 
11 
12 def plot_trace(
13     data,
14     var_names,  # pylint: disable=unused-argument
15     divergences,
16     figsize,
17     rug,
18     lines,
19     combined,
20     legend,
21     plot_kwargs,
22     fill_kwargs,
23     rug_kwargs,
24     hist_kwargs,
25     trace_kwargs,
26     plotters,
27     divergence_data,
28     colors,
29     backend_kwargs,
30     show,
31 ):
32     """Plot distribution (histogram or kernel density estimates) and sampled values.
33 
34     If `divergences` data is available in `sample_stats`, will plot the location of divergences as
35     dashed vertical lines.
36 
37     Parameters
38     ----------
39     data : obj
40         Any object that can be converted to an az.InferenceData object
41         Refer to documentation of az.convert_to_dataset for details
42     var_names : string, or list of strings
43         One or more variables to be plotted.
44     divergences : {"bottom", "top", None, False}
45         Plot location of divergences on the traceplots. Options are "bottom", "top", or False-y.
46     figsize : figure size tuple
47         If None, size is (12, variables * 2)
48     rug : bool
49         If True adds a rugplot. Defaults to False. Ignored for 2D KDE. Only affects continuous
50         variables.
51     lines : tuple
52         Tuple of (var_name, {'coord': selection}, [line, positions]) to be overplotted as
53         vertical lines on the density and horizontal lines on the trace.
54     combined : bool
55         Flag for combining multiple chains into a single line. If False (default), chains will be
56         plotted separately.
57     legend : bool
58         Add a legend to the figure with the chain color code.
59     plot_kwargs : dict
60         Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables.
61     fill_kwargs : dict
62         Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables.
63     rug_kwargs : dict
64         Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables.
65     hist_kwargs : dict
66         Extra keyword arguments passed to `arviz.plot_dist`. Only affects discrete variables.
67     trace_kwargs : dict
68         Extra keyword arguments passed to `plt.plot`
69     Returns
70     -------
71     axes : matplotlib axes
72 
73 
74     Examples
75     --------
76     Plot a subset variables
77 
78     .. plot::
79         :context: close-figs
80 
81         >>> import arviz as az
82         >>> data = az.load_arviz_data('non_centered_eight')
83         >>> coords = {'school': ['Choate', 'Lawrenceville']}
84         >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords)
85 
86     Show all dimensions of multidimensional variables in the same plot
87 
88     .. plot::
89         :context: close-figs
90 
91         >>> az.plot_trace(data, compact=True)
92 
93     Combine all chains into one distribution
94 
95     .. plot::
96         :context: close-figs
97 
98         >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords, combined=True)
99 
100 
101     Plot reference lines against distribution and trace
102 
103     .. plot::
104         :context: close-figs
105 
106         >>> lines = (('theta_t',{'school': "Choate"}, [-1]),)
107         >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords, lines=lines)
108 
109     """
110     # Set plot default backend kwargs
111     if backend_kwargs is None:
112         backend_kwargs = {}
113 
114     backend_kwargs = {**backend_kwarg_defaults(), **backend_kwargs}
115 
116     textsize = plot_kwargs.pop("textsize", 10)
117 
118     figsize, _, titlesize, xt_labelsize, linewidth, _ = _scale_fig_size(
119         figsize, textsize, rows=len(plotters), cols=2
120     )
121 
122     trace_kwargs.setdefault("linewidth", linewidth)
123     plot_kwargs.setdefault("linewidth", linewidth)
124 
125     _, axes = plt.subplots(len(plotters), 2, squeeze=False, figsize=figsize, **backend_kwargs)
126 
127     for idx, (var_name, selection, value) in enumerate(plotters):
128         value = np.atleast_2d(value)
129 
130         if len(value.shape) == 2:
131             _plot_chains_mpl(
132                 axes,
133                 idx,
134                 value,
135                 data,
136                 colors,
137                 combined,
138                 xt_labelsize,
139                 rug,
140                 trace_kwargs,
141                 hist_kwargs,
142                 plot_kwargs,
143                 fill_kwargs,
144                 rug_kwargs,
145             )
146         else:
147             value = value.reshape((value.shape[0], value.shape[1], -1))
148             for sub_idx in range(value.shape[2]):
149                 _plot_chains_mpl(
150                     axes,
151                     idx,
152                     value[..., sub_idx],
153                     data,
154                     colors,
155                     combined,
156                     xt_labelsize,
157                     rug,
158                     trace_kwargs,
159                     hist_kwargs,
160                     plot_kwargs,
161                     fill_kwargs,
162                     rug_kwargs,
163                 )
164 
165         if value[0].dtype.kind == "i":
166             xticks = get_bins(value)
167             axes[idx, 0].set_xticks(xticks[:-1])
168         axes[idx, 0].set_yticks([])
169         for col in (0, 1):
170             axes[idx, col].set_title(make_label(var_name, selection), fontsize=titlesize, wrap=True)
171             axes[idx, col].tick_params(labelsize=xt_labelsize)
172 
173         xlims = [ax.get_xlim() for ax in axes[idx, :]]
174         ylims = [ax.get_ylim() for ax in axes[idx, :]]
175 
176         if divergences:
177             div_selection = {k: v for k, v in selection.items() if k in divergence_data.dims}
178             divs = divergence_data.sel(**div_selection).values
179             # if combined:
180             #     divs = divs.flatten()
181             divs = np.atleast_2d(divs)
182 
183             for chain, chain_divs in enumerate(divs):
184                 div_draws = data.draw.values[chain_divs]
185                 div_idxs = np.arange(len(chain_divs))[chain_divs]
186                 if div_idxs.size > 0:
187                     if divergences == "top":
188                         ylocs = [ylim[1] for ylim in ylims]
189                     else:
190                         ylocs = [ylim[0] for ylim in ylims]
191                     values = value[chain, div_idxs]
192                     axes[idx, 1].plot(
193                         div_draws,
194                         np.zeros_like(div_idxs) + ylocs[1],
195                         marker="|",
196                         color="black",
197                         markeredgewidth=1.5,
198                         markersize=30,
199                         linestyle="None",
200                         alpha=hist_kwargs["alpha"],
201                         zorder=-5,
202                     )
203                     axes[idx, 1].set_ylim(*ylims[1])
204                     axes[idx, 0].plot(
205                         values,
206                         np.zeros_like(values) + ylocs[0],
207                         marker="|",
208                         color="black",
209                         markeredgewidth=1.5,
210                         markersize=30,
211                         linestyle="None",
212                         alpha=trace_kwargs["alpha"],
213                         zorder=-5,
214                     )
215                     axes[idx, 0].set_ylim(*ylims[0])
216 
217         for _, _, vlines in (j for j in lines if j[0] == var_name and j[1] == selection):
218             if isinstance(vlines, (float, int)):
219                 line_values = [vlines]
220             else:
221                 line_values = np.atleast_1d(vlines).ravel()
222             axes[idx, 0].vlines(line_values, *ylims[0], colors="black", linewidth=1.5, alpha=0.75)
223             axes[idx, 1].hlines(
224                 line_values, *xlims[1], colors="black", linewidth=1.5, alpha=trace_kwargs["alpha"]
225             )
226         axes[idx, 0].set_ylim(bottom=0, top=ylims[0][1])
227         axes[idx, 1].set_xlim(left=data.draw.min(), right=data.draw.max())
228         axes[idx, 1].set_ylim(*ylims[1])
229     if legend:
230         handles = [
231             Line2D([], [], color=color, label=chain_id)
232             for chain_id, color in zip(data.chain.values, colors)
233         ]
234         if combined:
235             handles.insert(0, Line2D([], [], color=colors[-1], label="combined"))
236         axes[0, 1].legend(handles=handles, title="chain")
237 
238     if backend_show(show):
239         plt.show()
240 
241     return axes
242 
243 
244 def _plot_chains_mpl(
245     axes,
246     idx,
247     value,
248     data,
249     colors,
250     combined,
251     xt_labelsize,
252     rug,
253     trace_kwargs,
254     hist_kwargs,
255     plot_kwargs,
256     fill_kwargs,
257     rug_kwargs,
258 ):
259     for chain_idx, row in enumerate(value):
260         axes[idx, 1].plot(data.draw.values, row, color=colors[chain_idx], **trace_kwargs)
261 
262         if not combined:
263             plot_kwargs["color"] = colors[chain_idx]
264             plot_dist(
265                 values=row,
266                 textsize=xt_labelsize,
267                 rug=rug,
268                 ax=axes[idx, 0],
269                 hist_kwargs=hist_kwargs,
270                 plot_kwargs=plot_kwargs,
271                 fill_kwargs=fill_kwargs,
272                 rug_kwargs=rug_kwargs,
273                 backend="matplotlib",
274                 show=False,
275             )
276 
277     if combined:
278         plot_kwargs["color"] = colors[-1]
279         plot_dist(
280             values=value.flatten(),
281             textsize=xt_labelsize,
282             rug=rug,
283             ax=axes[idx, 0],
284             hist_kwargs=hist_kwargs,
285             plot_kwargs=plot_kwargs,
286             fill_kwargs=fill_kwargs,
287             rug_kwargs=rug_kwargs,
288             backend="matplotlib",
289             show=False,
290         )
291
```
--- 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/backends/matplotlib/traceplot.py b/arviz/plots/backends/matplotlib/traceplot.py
--- a/arviz/plots/backends/matplotlib/traceplot.py
+++ b/arviz/plots/backends/matplotlib/traceplot.py
@@ -1,5 +1,6 @@
 """Matplotlib traceplot."""
 
+import warnings
 import matplotlib.pyplot as plt
 from matplotlib.lines import Line2D
 import numpy as np
@@ -48,8 +49,8 @@
     rug : bool
         If True adds a rugplot. Defaults to False. Ignored for 2D KDE. Only affects continuous
         variables.
-    lines : tuple
-        Tuple of (var_name, {'coord': selection}, [line, positions]) to be overplotted as
+    lines : tuple or list
+        list of tuple of (var_name, {'coord': selection}, [line_positions]) to be overplotted as
         vertical lines on the density and horizontal lines on the trace.
     combined : bool
         Flag for combining multiple chains into a single line. If False (default), chains will be
@@ -124,6 +125,21 @@
 
     _, axes = plt.subplots(len(plotters), 2, squeeze=False, figsize=figsize, **backend_kwargs)
 
+    # Check the input for lines
+    if lines is not None:
+        all_var_names = set(plotter[0] for plotter in plotters)
+
+        invalid_var_names = set()
+        for line in lines:
+            if line[0] not in all_var_names:
+                invalid_var_names.add(line[0])
+        if invalid_var_names:
+            warnings.warn(
+                "A valid var_name should be provided, found {} expected from {}".format(
+                    invalid_var_names, all_var_names
+                )
+            )
+
     for idx, (var_name, selection, value) in enumerate(plotters):
         value = np.atleast_2d(value)
 
@@ -219,6 +235,10 @@
                 line_values = [vlines]
             else:
                 line_values = np.atleast_1d(vlines).ravel()
+                if not np.issubdtype(line_values.dtype, np.number):
+                    raise ValueError(
+                        "line-positions should be numeric, found {}".format(line_values)
+                    )
             axes[idx, 0].vlines(line_values, *ylims[0], colors="black", linewidth=1.5, alpha=0.75)
             axes[idx, 1].hlines(
                 line_values, *xlims[1], colors="black", linewidth=1.5, alpha=trace_kwargs["alpha"]

{"golden_diff": "diff --git a/arviz/plots/backends/matplotlib/traceplot.py b/arviz/plots/backends/matplotlib/traceplot.py\n--- a/arviz/plots/backends/matplotlib/traceplot.py\n+++ b/arviz/plots/backends/matplotlib/traceplot.py\n@@ -1,5 +1,6 @@\n \"\"\"Matplotlib traceplot.\"\"\"\n \n+import warnings\n import matplotlib.pyplot as plt\n from matplotlib.lines import Line2D\n import numpy as np\n@@ -48,8 +49,8 @@\n     rug : bool\n         If True adds a rugplot. Defaults to False. Ignored for 2D KDE. Only affects continuous\n         variables.\n-    lines : tuple\n-        Tuple of (var_name, {'coord': selection}, [line, positions]) to be overplotted as\n+    lines : tuple or list\n+        list of tuple of (var_name, {'coord': selection}, [line_positions]) to be overplotted as\n         vertical lines on the density and horizontal lines on the trace.\n     combined : bool\n         Flag for combining multiple chains into a single line. If False (default), chains will be\n@@ -124,6 +125,21 @@\n \n     _, axes = plt.subplots(len(plotters), 2, squeeze=False, figsize=figsize, **backend_kwargs)\n \n+    # Check the input for lines\n+    if lines is not None:\n+        all_var_names = set(plotter[0] for plotter in plotters)\n+\n+        invalid_var_names = set()\n+        for line in lines:\n+            if line[0] not in all_var_names:\n+                invalid_var_names.add(line[0])\n+        if invalid_var_names:\n+            warnings.warn(\n+                \"A valid var_name should be provided, found {} expected from {}\".format(\n+                    invalid_var_names, all_var_names\n+                )\n+            )\n+\n     for idx, (var_name, selection, value) in enumerate(plotters):\n         value = np.atleast_2d(value)\n \n@@ -219,6 +235,10 @@\n                 line_values = [vlines]\n             else:\n                 line_values = np.atleast_1d(vlines).ravel()\n+                if not np.issubdtype(line_values.dtype, np.number):\n+                    raise ValueError(\n+                        \"line-positions should be numeric, found {}\".format(line_values)\n+                    )\n             axes[idx, 0].vlines(line_values, *ylims[0], colors=\"black\", linewidth=1.5, alpha=0.75)\n             axes[idx, 1].hlines(\n                 line_values, *xlims[1], colors=\"black\", linewidth=1.5, alpha=trace_kwargs[\"alpha\"]\n", "issue": "plot_trace lines is unclear and it may yield unexpected results\n**Describe the bug**\r\nThe argument `lines` for the function `plot_trace` can give unexpected results. Moreover, the documentation is a bit nebulous.\r\n \r\n**To Reproduce**\r\nA toy example is defined\r\n```python\r\nimport pymc3 as pm\r\nimport arviz as az\r\nimport numpy as np\r\n\r\n# fake data\r\nmu_real = 0\r\nsigma_real = 1\r\nn_samples = 150\r\n\r\nY = np.random.normal(loc=mu_real, scale=sigma_real, size=n_samples)\r\n\r\nwith pm.Model() as model:\r\n    mu = pm.Normal('mu', mu=0, sigma=10)  \r\n    sigma = pm.HalfNormal('sigma', sigma=10)\r\n    likelihood = pm.Normal('likelihood', mu=mu, sigma=sigma, observed=Y)\r\n    trace = pm.sample()\r\n```\r\nAs per [documentation](https://arviz-devs.github.io/arviz/generated/arviz.plot_trace.html#arviz.plot_trace), the argument `lines` accepts a tuple in the form `(var_name, {\u2018coord\u2019: selection}, [line, positions])`. So, the command \r\n```python\r\naz.plot_trace(trace, lines=(('mu', {}, mu_real),))\r\n```\r\nyields correctly \r\n![image](https://user-images.githubusercontent.com/18400141/69927034-b7327f80-1484-11ea-8f4c-5f52563413be.png)\r\n\r\nI can also pass a list of tuples or a list of tuples and lists and it will work fine:\r\n```\r\naz.plot_trace(trace, lines=[('mu', {}, mu_real)]) # list of tuples\r\naz.plot_trace(trace, lines=[['mu', {}, mu_real]]) # list of lists\r\naz.plot_trace(trace, lines=[['mu', {}, mu_real], ('sigma', {}, sigma_real)]) # list of lists and tuples\r\n```\r\nhowever, I cannot pass a simple tuple because I will get a `KeyError: 0`\r\n```python\r\naz.plot_trace(trace, lines=(['mu', {}, mu_real]))\r\naz.plot_trace(trace, lines=(('mu', {}, mu_real)))\r\n```\r\nAlso, I can pass a variable or coordinate name that do not exist and Arviz will not complain---but not lines will be plotted (here I would expect a warning)\r\n```python\r\naz.plot_trace(trace, lines=[('hey', {}, mu_real)])\r\naz.plot_trace(trace, lines=[('mu', {'hey'}, mu_real)])\r\n```\r\n![image](https://user-images.githubusercontent.com/18400141/69927389-d251bf00-1485-11ea-8d5c-7630a6763728.png)\r\nThe weird behavior happens when I pass a string:\r\n```python\r\naz.plot_trace(trace, lines=[('mu', {}, 'hey')])\r\n```\r\n![image](https://user-images.githubusercontent.com/18400141/69927502-32e0fc00-1486-11ea-8f6a-3f012017e932.png)\r\n\r\n**Expected behavior**\r\nThe [documentation](https://arviz-devs.github.io/arviz/generated/arviz.plot_trace.html#arviz.plot_trace) could be improved and the function could check the inputs. In addition to what described above, the placeholder `[line, positions]` in `(var_name, {\u2018coord\u2019: selection}, [line, positions])` should be something like `[line_positions]` otherwise one may think (like myself :) ) that two values should be inserted (one for `line` and one for `positions`).\r\n\r\n**Additional context**\r\nI am using Win10, fresh conda environment with PyMC3 and Arviz from master.\r\n\r\nPossibly related https://github.com/pymc-devs/pymc3/issues/3495, https://github.com/pymc-devs/pymc3/issues/3497\n", "before_files": [{"content": "\"\"\"Matplotlib traceplot.\"\"\"\n\nimport matplotlib.pyplot as plt\nfrom matplotlib.lines import Line2D\nimport numpy as np\n\nfrom . import backend_kwarg_defaults, backend_show\nfrom ...distplot import plot_dist\nfrom ...plot_utils import _scale_fig_size, get_bins, make_label\n\n\ndef plot_trace(\n    data,\n    var_names,  # pylint: disable=unused-argument\n    divergences,\n    figsize,\n    rug,\n    lines,\n    combined,\n    legend,\n    plot_kwargs,\n    fill_kwargs,\n    rug_kwargs,\n    hist_kwargs,\n    trace_kwargs,\n    plotters,\n    divergence_data,\n    colors,\n    backend_kwargs,\n    show,\n):\n    \"\"\"Plot distribution (histogram or kernel density estimates) and sampled values.\n\n    If `divergences` data is available in `sample_stats`, will plot the location of divergences as\n    dashed vertical lines.\n\n    Parameters\n    ----------\n    data : obj\n        Any object that can be converted to an az.InferenceData object\n        Refer to documentation of az.convert_to_dataset for details\n    var_names : string, or list of strings\n        One or more variables to be plotted.\n    divergences : {\"bottom\", \"top\", None, False}\n        Plot location of divergences on the traceplots. Options are \"bottom\", \"top\", or False-y.\n    figsize : figure size tuple\n        If None, size is (12, variables * 2)\n    rug : bool\n        If True adds a rugplot. Defaults to False. Ignored for 2D KDE. Only affects continuous\n        variables.\n    lines : tuple\n        Tuple of (var_name, {'coord': selection}, [line, positions]) to be overplotted as\n        vertical lines on the density and horizontal lines on the trace.\n    combined : bool\n        Flag for combining multiple chains into a single line. If False (default), chains will be\n        plotted separately.\n    legend : bool\n        Add a legend to the figure with the chain color code.\n    plot_kwargs : dict\n        Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables.\n    fill_kwargs : dict\n        Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables.\n    rug_kwargs : dict\n        Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables.\n    hist_kwargs : dict\n        Extra keyword arguments passed to `arviz.plot_dist`. Only affects discrete variables.\n    trace_kwargs : dict\n        Extra keyword arguments passed to `plt.plot`\n    Returns\n    -------\n    axes : matplotlib axes\n\n\n    Examples\n    --------\n    Plot a subset variables\n\n    .. plot::\n        :context: close-figs\n\n        >>> import arviz as az\n        >>> data = az.load_arviz_data('non_centered_eight')\n        >>> coords = {'school': ['Choate', 'Lawrenceville']}\n        >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords)\n\n    Show all dimensions of multidimensional variables in the same plot\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_trace(data, compact=True)\n\n    Combine all chains into one distribution\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords, combined=True)\n\n\n    Plot reference lines against distribution and trace\n\n    .. plot::\n        :context: close-figs\n\n        >>> lines = (('theta_t',{'school': \"Choate\"}, [-1]),)\n        >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords, lines=lines)\n\n    \"\"\"\n    # Set plot default backend kwargs\n    if backend_kwargs is None:\n        backend_kwargs = {}\n\n    backend_kwargs = {**backend_kwarg_defaults(), **backend_kwargs}\n\n    textsize = plot_kwargs.pop(\"textsize\", 10)\n\n    figsize, _, titlesize, xt_labelsize, linewidth, _ = _scale_fig_size(\n        figsize, textsize, rows=len(plotters), cols=2\n    )\n\n    trace_kwargs.setdefault(\"linewidth\", linewidth)\n    plot_kwargs.setdefault(\"linewidth\", linewidth)\n\n    _, axes = plt.subplots(len(plotters), 2, squeeze=False, figsize=figsize, **backend_kwargs)\n\n    for idx, (var_name, selection, value) in enumerate(plotters):\n        value = np.atleast_2d(value)\n\n        if len(value.shape) == 2:\n            _plot_chains_mpl(\n                axes,\n                idx,\n                value,\n                data,\n                colors,\n                combined,\n                xt_labelsize,\n                rug,\n                trace_kwargs,\n                hist_kwargs,\n                plot_kwargs,\n                fill_kwargs,\n                rug_kwargs,\n            )\n        else:\n            value = value.reshape((value.shape[0], value.shape[1], -1))\n            for sub_idx in range(value.shape[2]):\n                _plot_chains_mpl(\n                    axes,\n                    idx,\n                    value[..., sub_idx],\n                    data,\n                    colors,\n                    combined,\n                    xt_labelsize,\n                    rug,\n                    trace_kwargs,\n                    hist_kwargs,\n                    plot_kwargs,\n                    fill_kwargs,\n                    rug_kwargs,\n                )\n\n        if value[0].dtype.kind == \"i\":\n            xticks = get_bins(value)\n            axes[idx, 0].set_xticks(xticks[:-1])\n        axes[idx, 0].set_yticks([])\n        for col in (0, 1):\n            axes[idx, col].set_title(make_label(var_name, selection), fontsize=titlesize, wrap=True)\n            axes[idx, col].tick_params(labelsize=xt_labelsize)\n\n        xlims = [ax.get_xlim() for ax in axes[idx, :]]\n        ylims = [ax.get_ylim() for ax in axes[idx, :]]\n\n        if divergences:\n            div_selection = {k: v for k, v in selection.items() if k in divergence_data.dims}\n            divs = divergence_data.sel(**div_selection).values\n            # if combined:\n            #     divs = divs.flatten()\n            divs = np.atleast_2d(divs)\n\n            for chain, chain_divs in enumerate(divs):\n                div_draws = data.draw.values[chain_divs]\n                div_idxs = np.arange(len(chain_divs))[chain_divs]\n                if div_idxs.size > 0:\n                    if divergences == \"top\":\n                        ylocs = [ylim[1] for ylim in ylims]\n                    else:\n                        ylocs = [ylim[0] for ylim in ylims]\n                    values = value[chain, div_idxs]\n                    axes[idx, 1].plot(\n                        div_draws,\n                        np.zeros_like(div_idxs) + ylocs[1],\n                        marker=\"|\",\n                        color=\"black\",\n                        markeredgewidth=1.5,\n                        markersize=30,\n                        linestyle=\"None\",\n                        alpha=hist_kwargs[\"alpha\"],\n                        zorder=-5,\n                    )\n                    axes[idx, 1].set_ylim(*ylims[1])\n                    axes[idx, 0].plot(\n                        values,\n                        np.zeros_like(values) + ylocs[0],\n                        marker=\"|\",\n                        color=\"black\",\n                        markeredgewidth=1.5,\n                        markersize=30,\n                        linestyle=\"None\",\n                        alpha=trace_kwargs[\"alpha\"],\n                        zorder=-5,\n                    )\n                    axes[idx, 0].set_ylim(*ylims[0])\n\n        for _, _, vlines in (j for j in lines if j[0] == var_name and j[1] == selection):\n            if isinstance(vlines, (float, int)):\n                line_values = [vlines]\n            else:\n                line_values = np.atleast_1d(vlines).ravel()\n            axes[idx, 0].vlines(line_values, *ylims[0], colors=\"black\", linewidth=1.5, alpha=0.75)\n            axes[idx, 1].hlines(\n                line_values, *xlims[1], colors=\"black\", linewidth=1.5, alpha=trace_kwargs[\"alpha\"]\n            )\n        axes[idx, 0].set_ylim(bottom=0, top=ylims[0][1])\n        axes[idx, 1].set_xlim(left=data.draw.min(), right=data.draw.max())\n        axes[idx, 1].set_ylim(*ylims[1])\n    if legend:\n        handles = [\n            Line2D([], [], color=color, label=chain_id)\n            for chain_id, color in zip(data.chain.values, colors)\n        ]\n        if combined:\n            handles.insert(0, Line2D([], [], color=colors[-1], label=\"combined\"))\n        axes[0, 1].legend(handles=handles, title=\"chain\")\n\n    if backend_show(show):\n        plt.show()\n\n    return axes\n\n\ndef _plot_chains_mpl(\n    axes,\n    idx,\n    value,\n    data,\n    colors,\n    combined,\n    xt_labelsize,\n    rug,\n    trace_kwargs,\n    hist_kwargs,\n    plot_kwargs,\n    fill_kwargs,\n    rug_kwargs,\n):\n    for chain_idx, row in enumerate(value):\n        axes[idx, 1].plot(data.draw.values, row, color=colors[chain_idx], **trace_kwargs)\n\n        if not combined:\n            plot_kwargs[\"color\"] = colors[chain_idx]\n            plot_dist(\n                values=row,\n                textsize=xt_labelsize,\n                rug=rug,\n                ax=axes[idx, 0],\n                hist_kwargs=hist_kwargs,\n                plot_kwargs=plot_kwargs,\n                fill_kwargs=fill_kwargs,\n                rug_kwargs=rug_kwargs,\n                backend=\"matplotlib\",\n                show=False,\n            )\n\n    if combined:\n        plot_kwargs[\"color\"] = colors[-1]\n        plot_dist(\n            values=value.flatten(),\n            textsize=xt_labelsize,\n            rug=rug,\n            ax=axes[idx, 0],\n            hist_kwargs=hist_kwargs,\n            plot_kwargs=plot_kwargs,\n            fill_kwargs=fill_kwargs,\n            rug_kwargs=rug_kwargs,\n            backend=\"matplotlib\",\n            show=False,\n        )\n", "path": "arviz/plots/backends/matplotlib/traceplot.py"}], "after_files": [{"content": "\"\"\"Matplotlib traceplot.\"\"\"\n\nimport warnings\nimport matplotlib.pyplot as plt\nfrom matplotlib.lines import Line2D\nimport numpy as np\n\nfrom . import backend_kwarg_defaults, backend_show\nfrom ...distplot import plot_dist\nfrom ...plot_utils import _scale_fig_size, get_bins, make_label\n\n\ndef plot_trace(\n    data,\n    var_names,  # pylint: disable=unused-argument\n    divergences,\n    figsize,\n    rug,\n    lines,\n    combined,\n    legend,\n    plot_kwargs,\n    fill_kwargs,\n    rug_kwargs,\n    hist_kwargs,\n    trace_kwargs,\n    plotters,\n    divergence_data,\n    colors,\n    backend_kwargs,\n    show,\n):\n    \"\"\"Plot distribution (histogram or kernel density estimates) and sampled values.\n\n    If `divergences` data is available in `sample_stats`, will plot the location of divergences as\n    dashed vertical lines.\n\n    Parameters\n    ----------\n    data : obj\n        Any object that can be converted to an az.InferenceData object\n        Refer to documentation of az.convert_to_dataset for details\n    var_names : string, or list of strings\n        One or more variables to be plotted.\n    divergences : {\"bottom\", \"top\", None, False}\n        Plot location of divergences on the traceplots. Options are \"bottom\", \"top\", or False-y.\n    figsize : figure size tuple\n        If None, size is (12, variables * 2)\n    rug : bool\n        If True adds a rugplot. Defaults to False. Ignored for 2D KDE. Only affects continuous\n        variables.\n    lines : tuple or list\n        list of tuple of (var_name, {'coord': selection}, [line_positions]) to be overplotted as\n        vertical lines on the density and horizontal lines on the trace.\n    combined : bool\n        Flag for combining multiple chains into a single line. If False (default), chains will be\n        plotted separately.\n    legend : bool\n        Add a legend to the figure with the chain color code.\n    plot_kwargs : dict\n        Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables.\n    fill_kwargs : dict\n        Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables.\n    rug_kwargs : dict\n        Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables.\n    hist_kwargs : dict\n        Extra keyword arguments passed to `arviz.plot_dist`. Only affects discrete variables.\n    trace_kwargs : dict\n        Extra keyword arguments passed to `plt.plot`\n    Returns\n    -------\n    axes : matplotlib axes\n\n\n    Examples\n    --------\n    Plot a subset variables\n\n    .. plot::\n        :context: close-figs\n\n        >>> import arviz as az\n        >>> data = az.load_arviz_data('non_centered_eight')\n        >>> coords = {'school': ['Choate', 'Lawrenceville']}\n        >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords)\n\n    Show all dimensions of multidimensional variables in the same plot\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_trace(data, compact=True)\n\n    Combine all chains into one distribution\n\n    .. plot::\n        :context: close-figs\n\n        >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords, combined=True)\n\n\n    Plot reference lines against distribution and trace\n\n    .. plot::\n        :context: close-figs\n\n        >>> lines = (('theta_t',{'school': \"Choate\"}, [-1]),)\n        >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords, lines=lines)\n\n    \"\"\"\n    # Set plot default backend kwargs\n    if backend_kwargs is None:\n        backend_kwargs = {}\n\n    backend_kwargs = {**backend_kwarg_defaults(), **backend_kwargs}\n\n    textsize = plot_kwargs.pop(\"textsize\", 10)\n\n    figsize, _, titlesize, xt_labelsize, linewidth, _ = _scale_fig_size(\n        figsize, textsize, rows=len(plotters), cols=2\n    )\n\n    trace_kwargs.setdefault(\"linewidth\", linewidth)\n    plot_kwargs.setdefault(\"linewidth\", linewidth)\n\n    _, axes = plt.subplots(len(plotters), 2, squeeze=False, figsize=figsize, **backend_kwargs)\n\n    # Check the input for lines\n    if lines is not None:\n        all_var_names = set(plotter[0] for plotter in plotters)\n\n        invalid_var_names = set()\n        for line in lines:\n            if line[0] not in all_var_names:\n                invalid_var_names.add(line[0])\n        if invalid_var_names:\n            warnings.warn(\n                \"A valid var_name should be provided, found {} expected from {}\".format(\n                    invalid_var_names, all_var_names\n                )\n            )\n\n    for idx, (var_name, selection, value) in enumerate(plotters):\n        value = np.atleast_2d(value)\n\n        if len(value.shape) == 2:\n            _plot_chains_mpl(\n                axes,\n                idx,\n                value,\n                data,\n                colors,\n                combined,\n                xt_labelsize,\n                rug,\n                trace_kwargs,\n                hist_kwargs,\n                plot_kwargs,\n                fill_kwargs,\n                rug_kwargs,\n            )\n        else:\n            value = value.reshape((value.shape[0], value.shape[1], -1))\n            for sub_idx in range(value.shape[2]):\n                _plot_chains_mpl(\n                    axes,\n                    idx,\n                    value[..., sub_idx],\n                    data,\n                    colors,\n                    combined,\n                    xt_labelsize,\n                    rug,\n                    trace_kwargs,\n                    hist_kwargs,\n                    plot_kwargs,\n                    fill_kwargs,\n                    rug_kwargs,\n                )\n\n        if value[0].dtype.kind == \"i\":\n            xticks = get_bins(value)\n            axes[idx, 0].set_xticks(xticks[:-1])\n        axes[idx, 0].set_yticks([])\n        for col in (0, 1):\n            axes[idx, col].set_title(make_label(var_name, selection), fontsize=titlesize, wrap=True)\n            axes[idx, col].tick_params(labelsize=xt_labelsize)\n\n        xlims = [ax.get_xlim() for ax in axes[idx, :]]\n        ylims = [ax.get_ylim() for ax in axes[idx, :]]\n\n        if divergences:\n            div_selection = {k: v for k, v in selection.items() if k in divergence_data.dims}\n            divs = divergence_data.sel(**div_selection).values\n            # if combined:\n            #     divs = divs.flatten()\n            divs = np.atleast_2d(divs)\n\n            for chain, chain_divs in enumerate(divs):\n                div_draws = data.draw.values[chain_divs]\n                div_idxs = np.arange(len(chain_divs))[chain_divs]\n                if div_idxs.size > 0:\n                    if divergences == \"top\":\n                        ylocs = [ylim[1] for ylim in ylims]\n                    else:\n                        ylocs = [ylim[0] for ylim in ylims]\n                    values = value[chain, div_idxs]\n                    axes[idx, 1].plot(\n                        div_draws,\n                        np.zeros_like(div_idxs) + ylocs[1],\n                        marker=\"|\",\n                        color=\"black\",\n                        markeredgewidth=1.5,\n                        markersize=30,\n                        linestyle=\"None\",\n                        alpha=hist_kwargs[\"alpha\"],\n                        zorder=-5,\n                    )\n                    axes[idx, 1].set_ylim(*ylims[1])\n                    axes[idx, 0].plot(\n                        values,\n                        np.zeros_like(values) + ylocs[0],\n                        marker=\"|\",\n                        color=\"black\",\n                        markeredgewidth=1.5,\n                        markersize=30,\n                        linestyle=\"None\",\n                        alpha=trace_kwargs[\"alpha\"],\n                        zorder=-5,\n                    )\n                    axes[idx, 0].set_ylim(*ylims[0])\n\n        for _, _, vlines in (j for j in lines if j[0] == var_name and j[1] == selection):\n            if isinstance(vlines, (float, int)):\n                line_values = [vlines]\n            else:\n                line_values = np.atleast_1d(vlines).ravel()\n                if not np.issubdtype(line_values.dtype, np.number):\n                    raise ValueError(\n                        \"line-positions should be numeric, found {}\".format(line_values)\n                    )\n            axes[idx, 0].vlines(line_values, *ylims[0], colors=\"black\", linewidth=1.5, alpha=0.75)\n            axes[idx, 1].hlines(\n                line_values, *xlims[1], colors=\"black\", linewidth=1.5, alpha=trace_kwargs[\"alpha\"]\n            )\n        axes[idx, 0].set_ylim(bottom=0, top=ylims[0][1])\n        axes[idx, 1].set_xlim(left=data.draw.min(), right=data.draw.max())\n        axes[idx, 1].set_ylim(*ylims[1])\n    if legend:\n        handles = [\n            Line2D([], [], color=color, label=chain_id)\n            for chain_id, color in zip(data.chain.values, colors)\n        ]\n        if combined:\n            handles.insert(0, Line2D([], [], color=colors[-1], label=\"combined\"))\n        axes[0, 1].legend(handles=handles, title=\"chain\")\n\n    if backend_show(show):\n        plt.show()\n\n    return axes\n\n\ndef _plot_chains_mpl(\n    axes,\n    idx,\n    value,\n    data,\n    colors,\n    combined,\n    xt_labelsize,\n    rug,\n    trace_kwargs,\n    hist_kwargs,\n    plot_kwargs,\n    fill_kwargs,\n    rug_kwargs,\n):\n    for chain_idx, row in enumerate(value):\n        axes[idx, 1].plot(data.draw.values, row, color=colors[chain_idx], **trace_kwargs)\n\n        if not combined:\n            plot_kwargs[\"color\"] = colors[chain_idx]\n            plot_dist(\n                values=row,\n                textsize=xt_labelsize,\n                rug=rug,\n                ax=axes[idx, 0],\n                hist_kwargs=hist_kwargs,\n                plot_kwargs=plot_kwargs,\n                fill_kwargs=fill_kwargs,\n                rug_kwargs=rug_kwargs,\n                backend=\"matplotlib\",\n                show=False,\n            )\n\n    if combined:\n        plot_kwargs[\"color\"] = colors[-1]\n        plot_dist(\n            values=value.flatten(),\n            textsize=xt_labelsize,\n            rug=rug,\n            ax=axes[idx, 0],\n            hist_kwargs=hist_kwargs,\n            plot_kwargs=plot_kwargs,\n            fill_kwargs=fill_kwargs,\n            rug_kwargs=rug_kwargs,\n            backend=\"matplotlib\",\n            show=False,\n        )\n", "path": "arviz/plots/backends/matplotlib/traceplot.py"}]}