Repository: regionmask/regionmask

Issue:
Conflicting sizes for region and dataset when trying to create mask
Hi! I've been trying to create a mask for a dataset:

```python
basins = regionmask.defined_regions.natural_earth.ocean_basins_50
mask = basins.mask(cmip6_compiled['CMIP.MPI-M.MPI-ESM1-2-HR.historical.Omon.gn'], lon_name='longitude', lat_name='latitude')
```
but this error appears:
```python-traceback

ValueError                                Traceback (most recent call last)
/tmp/ipykernel_1285/730184074.py in <module>
      1 basins = regionmask.defined_regions.natural_earth.ocean_basins_50
----> 2 mask = basins.mask(cmip6_compiled['CMIP.MPI-M.MPI-ESM1-2-HR.historical.Omon.gn'], lon_name='longitude', lat_name='latitude')

/srv/conda/envs/notebook/lib/python3.9/site-packages/regionmask/core/regions.py in mask(self, lon_or_obj, lat, lon_name, lat_name, method, wrap_lon)
    282     ):
    283 
--> 284         return _mask_2D(
    285             outlines=self.polygons,
    286             lon_bounds=self.bounds_global[::2],

/srv/conda/envs/notebook/lib/python3.9/site-packages/regionmask/core/mask.py in _mask_2D(outlines, lon_bounds, numbers, lon_or_obj, lat, lon_name, lat_name, method, wrap_lon)
    198 ):
    199 
--> 200     mask = _mask(
    201         outlines=outlines,
    202         lon_bounds=lon_bounds,

/srv/conda/envs/notebook/lib/python3.9/site-packages/regionmask/core/mask.py in _mask(outlines, lon_bounds, numbers, lon_or_obj, lat, lon_name, lat_name, method, wrap_lon)
    183         )
    184 
--> 185     return mask_to_dataarray(mask, lon_or_obj, lat_orig, lon_name, lat_name)
    186 
    187 

/srv/conda/envs/notebook/lib/python3.9/site-packages/regionmask/core/mask.py in mask_to_dataarray(mask, lon_or_obj, lat, lon_name, lat_name)
    323         dims = ds.dims.keys()
    324 
--> 325     return ds.assign(region=(dims, mask)).region
    326 
    327 

/srv/conda/envs/notebook/lib/python3.9/site-packages/xarray/core/dataset.py in assign(self, variables, **variables_kwargs)
   5226         results = data._calc_assign_results(variables)
   5227         # ... and then assign
-> 5228         data.update(results)
   5229         return data
   5230 

/srv/conda/envs/notebook/lib/python3.9/site-packages/xarray/core/dataset.py in update(self, other)
   4206         Dataset.merge
   4207         """
-> 4208         merge_result = dataset_update_method(self, other)
   4209         return self._replace(inplace=True, **merge_result._asdict())
   4210 

/srv/conda/envs/notebook/lib/python3.9/site-packages/xarray/core/merge.py in dataset_update_method(dataset, other)
    982     # TODO: benbovy - flexible indexes: fix this (it only works with pandas indexes)
    983     indexes = {key: PandasIndex(dataset.coords[key]) for key in dataset.xindexes.keys()}
--> 984     return merge_core(
    985         [dataset, other],
    986         priority_arg=1,

/srv/conda/envs/notebook/lib/python3.9/site-packages/xarray/core/merge.py in merge_core(objects, compat, join, combine_attrs, priority_arg, explicit_coords, indexes, fill_value)
    638     assert_unique_multiindex_level_names(variables)
    639 
--> 640     dims = calculate_dimensions(variables)
    641 
    642     coord_names, noncoord_names = determine_coords(coerced)

/srv/conda/envs/notebook/lib/python3.9/site-packages/xarray/core/dataset.py in calculate_dimensions(variables)
    206                 last_used[dim] = k
    207             elif dims[dim] != size:
--> 208                 raise ValueError(
    209                     f"conflicting sizes for dimension {dim!r}: "
    210                     f"length {size} on {k!r} and length {dims[dim]} on {last_used!r}"

ValueError: conflicting sizes for dimension 'i': length 404 on 'region' and length 802 on {'i': 'i', 'j': 'j'}
```

I'm not sure, but maybe the i and j variables are getting switched? Here are the dimensions for the dataset:
```python
xarray.Dataset
Dimensions: i: 802 j: 404 lev: 40 bnds: 2 member_id: 1 time: 1980 vertices: 4
```

And these are the package versions that I used:
```python
regionmask='0.8.1.dev11+g3fab767'
xarray='0.19.0'
```


Discussion:
codecov-commenter: # [Codecov](https://codecov.io/gh/regionmask/regionmask/pull/296?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) Report
> Merging [#296](https://codecov.io/gh/regionmask/regionmask/pull/296?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) (2db9e1f) into [master](https://codecov.io/gh/regionmask/regionmask/commit/3fab767a13bbafa7a8b720bc32ed58cec9040eb6?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) (3fab767) will **decrease** coverage by `1.90%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/regionmask/regionmask/pull/296/graphs/tree.svg?width=650&height=150&src=pr&token=WI9PSJZIB7&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask)](https://codecov.io/gh/regionmask/regionmask/pull/296?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask)

```diff
@@            Coverage Diff             @@
##           master     #296      +/-   ##
==========================================
- Coverage   99.00%   97.10%   -1.91%     
==========================================
  Files          15       15              
  Lines        1105     1069      -36     
==========================================
- Hits         1094     1038      -56     
- Misses         11       31      +20     
```

| Flag | Coverage Δ | |
|---|---|---|
| bare-minimum | `?` | |
| min-all-deps | `97.10% <100.00%> (+0.08%)` | :arrow_up: |
| unittests | `97.10% <100.00%> (-1.91%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/regionmask/regionmask/pull/296?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | Coverage Δ | |
|---|---|---|
| [regionmask/core/mask.py](https://codecov.io/gh/regionmask/regionmask/pull/296/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#diff-cmVnaW9ubWFzay9jb3JlL21hc2sucHk=) | `97.83% <100.00%> (-1.74%)` | :arrow_down: |
| [regionmask/core/formatting.py](https://codecov.io/gh/regionmask/regionmask/pull/296/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#diff-cmVnaW9ubWFzay9jb3JlL2Zvcm1hdHRpbmcucHk=) | `65.62% <0.00%> (-31.25%)` | :arrow_down: |
| [regionmask/defined\_regions/natural\_earth.py](https://codecov.io/gh/regionmask/regionmask/pull/296/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#diff-cmVnaW9ubWFzay9kZWZpbmVkX3JlZ2lvbnMvbmF0dXJhbF9lYXJ0aC5weQ==) | `96.03% <0.00%> (-3.05%)` | :arrow_down: |
| [regionmask/core/plot.py](https://codecov.io/gh/regionmask/regionmask/pull/296/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#diff-cmVnaW9ubWFzay9jb3JlL3Bsb3QucHk=) | `98.67% <0.00%> (-1.33%)` | :arrow_down: |
| [regionmask/core/regions.py](https://codecov.io/gh/regionmask/regionmask/pull/296/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#diff-cmVnaW9ubWFzay9jb3JlL3JlZ2lvbnMucHk=) | `96.52% <0.00%> (-0.95%)` | :arrow_down: |
| [regionmask/core/utils.py](https://codecov.io/gh/regionmask/regionmask/pull/296/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#diff-cmVnaW9ubWFzay9jb3JlL3V0aWxzLnB5) | `100.00% <0.00%> (ø)` | |
| [regionmask/defined\_regions/\_ar6.py](https://codecov.io/gh/regionmask/regionmask/pull/296/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#diff-cmVnaW9ubWFzay9kZWZpbmVkX3JlZ2lvbnMvX2FyNi5weQ==) | `100.00% <0.00%> (ø)` | |
| [regionmask/defined\_regions/\_ar6\_pre\_revisions.py](https://codecov.io/gh/regionmask/regionmask/pull/296/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#diff-cmVnaW9ubWFzay9kZWZpbmVkX3JlZ2lvbnMvX2FyNl9wcmVfcmV2aXNpb25zLnB5) | `100.00% <0.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/regionmask/regionmask/pull/296?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/regionmask/regionmask/pull/296?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask). Last update [3fab767...2db9e1f](https://codecov.io/gh/regionmask/regionmask/pull/296?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask).


Patch:
diff --git a/docs/whats_new.rst b/docs/whats_new.rst
index bf653e1..ac13527 100644
--- a/docs/whats_new.rst
+++ b/docs/whats_new.rst
@@ -19,9 +19,9 @@ Breaking Changes
 - Removed support for Python 3.6.
 - Passing coordinates with different type to :py:meth:`Regions.mask` and :py:meth:`Regions.mask_3D`
   is no longer supported, i.e. can no longer pass lon as numpy array and lat as
-  DataArray (:pull:`293`).
+  DataArray (:pull:`294`).
 - The mask no longer has dimension coordinates when 2D numpy arrays are passed as lat and
-  lon coords (:pull:`293`).
+  lon coords (:pull:`294`).
 
 Enhancements
 ~~~~~~~~~~~~
@@ -59,7 +59,8 @@ Bug Fixes
 
 - The name of lon and lat coordinates when passed as single elements is now repected when
   creating masks i.e. for ``region.mask(ds.longitude, ds.longitude)`` (:issue:`129`,
-  :pull:`293`).
+  :pull:`294`).
+
 
 Docs
 ~~~~
@@ -70,7 +71,8 @@ Internal Changes
 - Fix compatibility with shapely 1.8 (:pull:`291`).
 - Fix downloading naturalearth regions part 2 (see :pull:`261`): Monkeypatch the correct
   download URL and catch all ``URLError``, not only timeouts (:pull:`289`).
-- Rewrote the function to create the mask `DataArray` (:issue:`168`, :pull:`293`).
+- Rewrote the function to create the mask `DataArray` (:issue:`168`, :pull:`294`).
+- Follow up to :pull:`294` - fix wrong dimension order for certain conditions (:issue:`295`).
 
 v0.8.0 (08.09.2021)
 -------------------
diff --git a/regionmask/core/mask.py b/regionmask/core/mask.py
index db1c05c..d5b1666 100644
--- a/regionmask/core/mask.py
+++ b/regionmask/core/mask.py
@@ -1,5 +1,4 @@
 import warnings
-from distutils.version import LooseVersion
 
 import numpy as np
 import xarray as xr
@@ -316,11 +315,7 @@ def mask_to_dataarray(mask, lon_or_obj, lat=None, lon_name="lon", lat_name="lat"
 
     ds = lat.coords.merge(lon.coords)
 
-    if LooseVersion(xr.__version__) < LooseVersion("0.19"):
-        # ds.dims were a SortedDict but we rely on the insertion order here
-        dims = ds._dims.keys()
-    else:
-        dims = ds.dims.keys()
+    dims = xr.core.variable.broadcast_variables(lat.variable, lon.variable)[0].dims
 
     return ds.assign(region=(dims, mask)).region
 
@@ -332,11 +327,11 @@ def _numpy_coords_to_dataarray(lon, lat, lon_name, lat_name):
 
     lon = np.asarray(lon)
     dims = dims2D if lon.ndim == 2 else lon_name
-    lon = xr.Dataset(coords={lon_name: (dims, lon)})
+    lon = xr.Dataset(coords={lon_name: (dims, lon)})[lon_name]
 
     lat = np.asarray(lat)
     dims = dims2D if lat.ndim == 2 else lat_name
-    lat = xr.Dataset(coords={lat_name: (dims, lat)})
+    lat = xr.Dataset(coords={lat_name: (dims, lat)})[lat_name]
 
     return lon, lat
 


Test patch:
diff --git a/regionmask/tests/test_create_dataarray.py b/regionmask/tests/test_create_dataarray.py
index 10360c8..969a433 100644
--- a/regionmask/tests/test_create_dataarray.py
+++ b/regionmask/tests/test_create_dataarray.py
@@ -18,28 +18,39 @@ def test_mask_to_dataarray_mixed_types():
 
 def create_test_datasets():
 
-    mask = np.arange(4).reshape(2, 2)
+    mask = np.arange(6).reshape(2, 3)
     mask1D = np.arange(2)
 
-    lon = [0, 1]
+    lon2 = [0, 1]
+    lon3 = [0, 1, 3]
     lat = [2, 3]
 
-    lon_2D = [[0, 1], [0, 1]]
-    lat_2D = [[1, 1], [0, 0]]
+    lon_2D = [[0, 1, 3], [0, 1, 3]]
+    lat_2D = [[1, 1, 1], [0, 0, 0]]
 
-    ds0 = xr.Dataset(coords={"lon": lon, "lat": lat})
-    ds1 = xr.Dataset(coords={"longitude": lon, "latitude": lat})
-    ds2 = xr.Dataset(coords={"lon": ("cells", lon), "lat": ("cells", lat)})
+    ds0 = xr.Dataset(coords={"lon": lon3, "lat": lat})
+    ds1 = xr.Dataset(coords={"longitude": lon3, "latitude": lat})
+    ds2 = xr.Dataset(coords={"lon": ("cells", lon2), "lat": ("cells", lat)})
     ds3 = xr.Dataset(
-        coords={"lon": ("cells", lon), "lat": ("cells", lat), "cells": ["a", "b"]}
+        coords={"lon": ("cells", lon2), "lat": ("cells", lat), "cells": ["a", "b"]}
     )
     ds4 = xr.Dataset(coords={"lon": (("y", "x"), lon_2D), "lat": (("y", "x"), lat_2D)})
     ds5 = xr.Dataset(
         coords={
             "lon": (("y", "x"), lon_2D),
             "lat": (("y", "x"), lat_2D),
-            "x": ["x0", "x1"],
             "y": ["y0", "y1"],
+            "x": ["x0", "x1", "x2"],
+        }
+    )
+
+    # pass x coords before the y coords https://github.com/regionmask/regionmask/issues/295
+    ds6 = xr.Dataset(
+        coords={
+            "x": ["x0", "x1", "x2"],
+            "y": ["y0", "y1"],
+            "lon": (("y", "x"), lon_2D),
+            "lat": (("y", "x"), lat_2D),
         }
     )
 
@@ -50,6 +61,7 @@ def create_test_datasets():
         (ds3, "lon", "lat", mask1D),
         (ds4, "lon", "lat", mask),
         (ds5, "lon", "lat", mask),
+        (ds6, "lon", "lat", mask),
     )
     return DATASETS
 
@@ -111,8 +123,8 @@ def test_numpy_coords_to_dataarray_1D(lon_name, lat_name):
 
     lon_actual, lat_actual = _numpy_coords_to_dataarray(lon, lat, lon_name, lat_name)
 
-    lon_expected = xr.Dataset(coords={lon_name: lon})
-    lat_expected = xr.Dataset(coords={lat_name: lat})
+    lon_expected = xr.Dataset(coords={lon_name: lon})[lon_name]
+    lat_expected = xr.Dataset(coords={lat_name: lat})[lat_name]
 
     xr.testing.assert_equal(lon_expected, lon_actual)
     xr.testing.assert_equal(lat_expected, lat_actual)
@@ -128,8 +140,8 @@ def test_numpy_coords_to_dataarray_2D(lon_name, lat_name):
     lon_actual, lat_actual = _numpy_coords_to_dataarray(lon, lat, lon_name, lat_name)
 
     dims = (f"{lat_name}_idx", f"{lon_name}_idx")
-    lon_expected = xr.Dataset(coords={lon_name: (dims, lon)})
-    lat_expected = xr.Dataset(coords={lat_name: (dims, lat)})
+    lon_expected = xr.Dataset(coords={lon_name: (dims, lon)})[lon_name]
+    lat_expected = xr.Dataset(coords={lat_name: (dims, lat)})[lat_name]
 
     xr.testing.assert_equal(lon_expected, lon_actual)
     xr.testing.assert_equal(lat_expected, lat_actual)