Repository: regionmask/regionmask

Issue:
bug for unstructured grid and overlap
Masking a unstructured grid for overlapping regions errors:

```python
import regionmask
import xarray as xr

air = xr.tutorial.open_dataset("air_temperature")

stacked = air.stack(gridcell=("lat", "lon"))

ar6_land = regionmask.defined_regions.ar6.land
ar6_land.overlap = True

regionmask.defined_regions.ar6.land.mask_3D(stacked)
```


```python-traceback
...
File ~/.../regionmask/core/mask.py:595, in _mask_shapely_v2(lon, lat, polygons, numbers, fill, is_unstructured, as_3D)
    592     for i, number in enumerate(numbers):
    593         out[b[a == i]] = number
--> 595 return out.reshape(shape)

ValueError: cannot reshape array of size 2803700 into shape (46,1325)
```

seems no one ran into this until now - not sure if that is a good or bad sign... :shrug: 

Discussion:
codecov-commenter: ## [Codecov](https://app.codecov.io/gh/regionmask/regionmask/pull/442?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) Report
> Merging [#442](https://app.codecov.io/gh/regionmask/regionmask/pull/442?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) (500fa11) into [main](https://app.codecov.io/gh/regionmask/regionmask/commit/fcdca1da269a3a597925d6549ef4a22003242140?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) (fcdca1d) will **decrease** coverage by `2.91%`.
> The diff coverage is `100.00%`.

:exclamation: Your organization needs to install the [Codecov GitHub app](https://github.com/apps/codecov/installations/select_target) to enable full functionality.

```diff
@@            Coverage Diff             @@
##             main     #442      +/-   ##
==========================================
- Coverage   98.10%   95.19%   -2.91%     
==========================================
  Files          18       18              
  Lines        1478     1478              
==========================================
- Hits         1450     1407      -43     
- Misses         28       71      +43     
```

| [Flag](https://app.codecov.io/gh/regionmask/regionmask/pull/442/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | Coverage Δ | |
|---|---|---|
| [bare-minimum](https://app.codecov.io/gh/regionmask/regionmask/pull/442/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | `?` | |
| [min-all-deps](https://app.codecov.io/gh/regionmask/regionmask/pull/442/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | `?` | |
| [shapely_lt_2](https://app.codecov.io/gh/regionmask/regionmask/pull/442/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | `?` | |
| [unittests](https://app.codecov.io/gh/regionmask/regionmask/pull/442/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | `95.19% <100.00%> (-2.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.

| [Files Changed](https://app.codecov.io/gh/regionmask/regionmask/pull/442?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://app.codecov.io/gh/regionmask/regionmask/pull/442?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#diff-cmVnaW9ubWFzay9jb3JlL21hc2sucHk=) | `91.35% <100.00%> (-8.03%)` | :arrow_down: |

... and [4 files with indirect coverage changes](https://app.codecov.io/gh/regionmask/regionmask/pull/442/indirect-changes?src=pr&el=tree-more&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 036fbf1..c5fefbe 100644
--- a/docs/whats_new.rst
+++ b/docs/whats_new.rst
@@ -52,6 +52,8 @@ New regions
 Bug Fixes
 ~~~~~~~~~
 
+- Fix a bug which raises an error when trying to creating a mask for overlapping regions
+  and unstructured coordinates (:issue:`438`).
 - Fix the detection of edge points at -180°E or 0°E if longitude values contain ``NA``
   values (:issue:`426`).
 - Fix the wrapping of longitudes that contain ``NA`` values and simplify the ``_wrapAngle``
diff --git a/regionmask/core/mask.py b/regionmask/core/mask.py
index fe1e08a..0edf884 100644
--- a/regionmask/core/mask.py
+++ b/regionmask/core/mask.py
@@ -701,7 +701,7 @@ def _get_LON_LAT_shape(lon, lat, numbers, is_unstructured=False, as_3D=False):
 def _get_out(shape, fill, as_3D):
     # create flattened output variable
     if as_3D:
-        out = np.full(shape[:1] + (np.prod(shape[-2:]).item(),), False, bool)
+        out = np.full(shape[:1] + (np.prod(shape[1:]).item(),), False, bool)
     else:
         out = np.full(np.prod(shape), fill, float)
 


Test patch:
diff --git a/regionmask/tests/test_mask.py b/regionmask/tests/test_mask.py
index d360bef..ed13769 100644
--- a/regionmask/tests/test_mask.py
+++ b/regionmask/tests/test_mask.py
@@ -367,6 +367,24 @@ def test_mask_3D_overlap_empty(method):
     assert not result.any()
 
 
+@pytest.mark.parametrize("drop", [True, False])
+@pytest.mark.parametrize("method", MASK_METHODS_IRREGULAR)
+def test_mask_overlap_unstructured(drop, method):
+    """Test for unstructured output."""
+    lat = [0.5, 0.5, 1.5, 1.5]
+    lon = [0.5, 1.5, 0.5, 1.5]
+
+    coords = {"lon": ("cells", lon), "lat": ("cells", lat)}
+    grid = xr.Dataset(coords=coords)
+
+    result = dummy_region_overlap.mask_3D(grid, drop=drop, method=method)
+
+    expected = expected_mask_3D(drop=drop, overlap=True)
+    expected = expected.stack(cells=("lat", "lon")).reset_index("cells")
+
+    xr.testing.assert_equal(result, expected)
+
+
 def test_mask_flag():
 
     expected = expected_mask_2D()