Repository: scikit-image/scikit-image

Issue:
regionprops.moments_weighted_central is broken with AttributeError, likely due to the renaming of centroid_weighted_local
## Description

All's in the title.

## Way to reproduce
```python
import numpy as np, skimage.measure as m
rp = m.regionprops(np.random.randint(0, 2, size=(256, 256)))[0]
print(rp.moments_weighted_central)
```
This raises an AttributeError, but this is actually because an inner access to rp.centroid_weighted_local fails, as revealed by manually calling the property getter:
```python
import numpy as np, skimage.measure as m
rp = m.regionprops(np.random.randint(0, 2, size=(256, 256)))[0]
print(type(rp).moments_weighted_central.fget(rp))
```

## Version information
```python
# Paste the output of the following python commands
from __future__ import print_function
import sys; print(sys.version)
import platform; print(platform.platform())
import skimage; print(f'scikit-image version: {skimage.__version__}')
import numpy; print(f'numpy version: {numpy.__version__}')
```

```
3.10.6 | packaged by conda-forge | (main, Aug 22 2022, 20:36:39) [GCC 10.4.0]
Linux-5.19.14-300.fc37.x86_64-x86_64-with-glibc2.36
scikit-image version: 0.19.3
numpy version: 1.23.3
```



Discussion:
Hi @anntzer, in this case it is expected that `moments_weighted_central` will not be available because it requires specifying `intensity_image` in the call to `regionprops`. I would consider this not having a more helpful error message to that effect a bug, though!

i.e. running your example I see
```
AttributeError: '<class 'skimage.measure._regionprops.RegionProperties'>' object has no attribute 'moments_weighted_central'
```
While a more useful error would be an error with a custom message such as 
```
The "moments_weighted_central" property requires specifying the `intensity_image` in the call to `regionprops`.`
```

The same issue should apply to any of the properties in this list (or any of their former, deprecated names)

https://github.com/scikit-image/scikit-image/blob/d77159024b0ea5fe68854850f17479c734cd6a6d/skimage/measure/_regionprops.py#L681-L691


Resolving patch:
diff --git a/skimage/measure/_regionprops.py b/skimage/measure/_regionprops.py
--- a/skimage/measure/_regionprops.py
+++ b/skimage/measure/_regionprops.py
@@ -136,6 +136,19 @@
 
 PROP_VALS = set(PROPS.values())
 
+_require_intensity_image = (
+    'image_intensity',
+    'intensity_max',
+    'intensity_mean',
+    'intensity_min',
+    'moments_weighted',
+    'moments_weighted_central',
+    'centroid_weighted',
+    'centroid_weighted_local',
+    'moments_weighted_hu',
+    'moments_weighted_normalized',
+)
+
 
 def _infer_number_of_required_args(func):
     """Infer the number of required arguments for a function
@@ -320,6 +333,11 @@ def __init__(self, slice, label, label_image, intensity_image,
             }
 
     def __getattr__(self, attr):
+        if self._intensity_image is None and attr in _require_intensity_image:
+            raise AttributeError(
+                f"Attribute '{attr}' unavailable when `intensity_image` "
+                f"has not been specified."
+            )
         if attr in self._extra_properties:
             func = self._extra_properties[attr]
             n_args = _infer_number_of_required_args(func)
@@ -346,6 +364,14 @@ def __getattr__(self, attr):
                     f'be 1 or 2, but {attr} takes {n_args} arguments.'
                 )
         elif attr in PROPS and attr.lower() == attr:
+            if (
+                self._intensity_image is None
+                and PROPS[attr] in _require_intensity_image
+            ):
+                raise AttributeError(
+                    f"Attribute '{attr}' unavailable when `intensity_image` "
+                    f"has not been specified."
+            )
             # retrieve deprecated property (excluding old CamelCase ones)
             return getattr(self, PROPS[attr])
         else:
@@ -679,17 +705,7 @@ def __iter__(self):
         props = PROP_VALS
 
         if self._intensity_image is None:
-            unavailable_props = ('image_intensity',
-                                 'intensity_max',
-                                 'intensity_mean',
-                                 'intensity_min',
-                                 'moments_weighted',
-                                 'moments_weighted_central',
-                                 'centroid_weighted',
-                                 'centroid_weighted_local',
-                                 'moments_weighted_hu',
-                                 'moments_weighted_normalized')
-
+            unavailable_props = _require_intensity_image
             props = props.difference(unavailable_props)
 
         return iter(sorted(props))


Test patch:
diff --git a/skimage/measure/tests/test_regionprops.py b/skimage/measure/tests/test_regionprops.py
--- a/skimage/measure/tests/test_regionprops.py
+++ b/skimage/measure/tests/test_regionprops.py
@@ -13,6 +13,7 @@
 from skimage.measure._regionprops import (COL_DTYPES, OBJECT_COLUMNS, PROPS,
                                           _inertia_eigvals_to_axes_lengths_3D,
                                           _parse_docs, _props_to_dict,
+                                          _require_intensity_image,
                                           euler_number, perimeter,
                                           perimeter_crofton, regionprops,
                                           regionprops_table)
@@ -1122,6 +1123,18 @@ def test_extra_properties_intensity():
     assert region.intensity_median == np.median(INTENSITY_SAMPLE[SAMPLE == 1])
 
 
+@pytest.mark.parametrize('intensity_prop', _require_intensity_image)
+def test_intensity_image_required(intensity_prop):
+    region = regionprops(SAMPLE)[0]
+    with pytest.raises(AttributeError) as e:
+        getattr(region, intensity_prop)
+    expected_error = (
+        f"Attribute '{intensity_prop}' unavailable when `intensity_image` has "
+        f"not been specified."
+    )
+    assert expected_error == str(e.value)
+
+
 def test_extra_properties_no_intensity_provided():
     with pytest.raises(AttributeError):
         region = regionprops(SAMPLE, extra_properties=(intensity_median,))[0]