Repository: arviz-devs/arviz

Issue:
Non np.array coords cause hard to diagnose shape error
**Describe the bug**
When one of the `coords` has a `tuple` as its values, the conversion to an xarray variable fails.

**To Reproduce**
A simple PyMC3 model that someone might write:
```python
coords = {
    "d1": ("A", "B", "C")
}
with pymc3.Model(coords=coords):
    pymc3.Normal("n", dims=("d1",))
    pymc3.sample(return_inferencedata=True)
```

The underlying problem is in `base.py/numpy_to_data_array`:
```python
arviz.numpy_to_data_array(
    ary=numpy.random.uniform(size=(3, 7, 11)),
    coords={
        "d1": tuple(numpy.arange(11)),
    },
    dims=["d1",]
)
```

Unhelpful traceback:

```
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-79-67777b4f3e94> in <module>
      4         "d1": tuple(numpy.arange(11)),
      5     },
----> 6     dims=["d1",]
      7 )

~\AppData\Local\Continuum\miniconda3\envs\pm3-dev\lib\site-packages\arviz\data\base.py in numpy_to_data_array(ary, var_name, coords, dims)
    170 
    171     # filter coords based on the dims
--> 172     coords = {key: xr.IndexVariable((key,), data=coords[key]) for key in dims}
    173     return xr.DataArray(ary, coords=coords, dims=dims)
    174 

~\AppData\Local\Continuum\miniconda3\envs\pm3-dev\lib\site-packages\arviz\data\base.py in <dictcomp>(.0)
    170 
    171     # filter coords based on the dims
--> 172     coords = {key: xr.IndexVariable((key,), data=coords[key]) for key in dims}
    173     return xr.DataArray(ary, coords=coords, dims=dims)
    174 

~\AppData\Local\Continuum\miniconda3\envs\pm3-dev\lib\site-packages\xarray\core\variable.py in __init__(self, dims, data, attrs, encoding, fastpath)
   2339 
   2340     def __init__(self, dims, data, attrs=None, encoding=None, fastpath=False):
-> 2341         super().__init__(dims, data, attrs, encoding, fastpath)
   2342         if self.ndim != 1:
   2343             raise ValueError("%s objects must be 1-dimensional" % type(self).__name__)

~\AppData\Local\Continuum\miniconda3\envs\pm3-dev\lib\site-packages\xarray\core\variable.py in __init__(self, dims, data, attrs, encoding, fastpath)
    325         """
    326         self._data = as_compatible_data(data, fastpath=fastpath)
--> 327         self._dims = self._parse_dimensions(dims)
    328         self._attrs = None
    329         self._encoding = None

~\AppData\Local\Continuum\miniconda3\envs\pm3-dev\lib\site-packages\xarray\core\variable.py in _parse_dimensions(self, dims)
    559             raise ValueError(
    560                 "dimensions %s must have the same length as the "
--> 561                 "number of data dimensions, ndim=%s" % (dims, self.ndim)
    562             )
    563         return dims

ValueError: dimensions ('d1',) must have the same length as the number of data dimensions, ndim=0
```

**Expected behavior**
I think all kinds of iterables (arrays, lists, tuples) are perfectly valid inputs for `coords`.

**Additional context**
ArviZ `0.10.0`
xarray `0.16.1`

Maybe this issue should also be raised at xarray. But from the ArviZ perspective, a simple `np.array()` call should fix it.


Discussion:

Resolving patch:
diff --git a/arviz/data/base.py b/arviz/data/base.py
--- a/arviz/data/base.py
+++ b/arviz/data/base.py
@@ -245,7 +245,7 @@ def numpy_to_data_array(
         coords["draw"] = np.arange(index_origin, n_samples + index_origin)
 
     # filter coords based on the dims
-    coords = {key: xr.IndexVariable((key,), data=coords[key]) for key in dims}
+    coords = {key: xr.IndexVariable((key,), data=np.asarray(coords[key])) for key in dims}
     return xr.DataArray(ary, coords=coords, dims=dims)
 
 


Test patch:
diff --git a/arviz/tests/base_tests/test_data.py b/arviz/tests/base_tests/test_data.py
--- a/arviz/tests/base_tests/test_data.py
+++ b/arviz/tests/base_tests/test_data.py
@@ -921,6 +921,16 @@ def test_dict_to_dataset_event_dims_error():
         convert_to_dataset(datadict, coords=coords, dims={"a": ["b", "c"]})
 
 
+def test_dict_to_dataset_with_tuple_coord():
+    datadict = {"a": np.random.randn(100), "b": np.random.randn(1, 100, 10)}
+    dataset = convert_to_dataset(datadict, coords={"c": tuple(range(10))}, dims={"b": ["c"]})
+    assert set(dataset.data_vars) == {"a", "b"}
+    assert set(dataset.coords) == {"chain", "draw", "c"}
+
+    assert set(dataset.a.coords) == {"chain", "draw"}
+    assert set(dataset.b.coords) == {"chain", "draw", "c"}
+
+
 def test_convert_to_dataset_idempotent():
     first = convert_to_dataset(np.random.randn(100))
     second = convert_to_dataset(first)