Repository: xgcm/xhistogram

Issue:
Opaque error when a non-xarray object is passed to xhist
Currently when passing, say, an ndarray to `xhist`, the error that comes back is as follows:

```python
import numpy as np
from xhistogram.xarray import histogram as xhist

# Demo data
A = np.arange(100)
xhist(A, bins=[np.linspace(0, 100, 11)])
```

```python-traceback
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-75-0c14fe219de4> in <module>
----> 1 xhist(A, bins=[np.linspace(0, 100, 11)])

~/miniconda3/envs/analysis/lib/python3.6/site-packages/xhistogram/xarray.py in histogram(bins, dim, weights, density, block_size, bin_dim_suffix, bin_edge_suffix, *args)
     78     for a in args:
     79         # TODO: make this a more robust check
---> 80         assert a.name is not None, 'all arrays must have a name'
     81 
     82     # we drop coords to simplify alignment

AttributeError: 'numpy.ndarray' object has no attribute 'name'
```

This is minor, but it would be good to have a quick check that sees whether the object is an `xarray.DataArray` and if not, throw a clear error that that's the issue.

Discussion:

Patch:
diff --git a/doc/contributing.rst b/doc/contributing.rst
index e2a8407..5dac01f 100644
--- a/doc/contributing.rst
+++ b/doc/contributing.rst
@@ -146,6 +146,9 @@ v0.2.1 (not yet released)
   xhistogram that mimic the numpy histogram API. This included
   adding a range argument to the xhistogram API :issue:`13`.
   By `Dougie Squire <https://github.com/dougiesquire>`_.
+- Added a function to check if the object passed to xhist() is an
+  xarray.DataArray and if not, throw an error. :issue:`14`.
+  By `Yang Yunyi <https://github.com/Badboy-16>`_.
 
 v0.2.0
 ~~~~~~
diff --git a/xhistogram/xarray.py b/xhistogram/xarray.py
index aea7a1f..a587abc 100644
--- a/xhistogram/xarray.py
+++ b/xhistogram/xarray.py
@@ -19,7 +19,7 @@ def histogram(
     density=False,
     block_size="auto",
     keep_coords=False,
-    bin_dim_suffix="_bin"
+    bin_dim_suffix="_bin",
 ):
     """Histogram applied along specified dimensions.
 
@@ -106,7 +106,13 @@ def histogram(
     N_weights = 1 if weights is not None else 0
 
     for a in args:
-        # TODO: make this a more robust check
+        if not isinstance(a, xr.DataArray):
+            raise TypeError(
+                "xhistogram.xarray.histogram accepts only xarray.DataArray "
+                + f"objects but a {type(a).__name__} was provided"
+            )
+
+    for a in args:
         assert a.name is not None, "all arrays must have a name"
 
     # we drop coords to simplify alignment
@@ -161,7 +167,7 @@ def histogram(
         range=range,
         axis=axis,
         density=density,
-        block_size=block_size
+        block_size=block_size,
     )
 
     # create output dims


Test patch:
diff --git a/xhistogram/test/test_xarray.py b/xhistogram/test/test_xarray.py
index f64857a..7170537 100644
--- a/xhistogram/test/test_xarray.py
+++ b/xhistogram/test/test_xarray.py
@@ -199,3 +199,10 @@ def test_carry_coords(keep_coords, number_of_inputs):
         assert "lon" in result.coords
     else:
         assert "lon" not in result.coords
+
+
+# test for issue #14
+def test_input_type_check():
+    np_array = np.arange(100)
+    with pytest.raises(TypeError):
+        histogram(np_array)