diff --git a/climada/entity/exposures/base.py b/climada/entity/exposures/base.py index 0c62af1b5..9575e746b 100644 --- a/climada/entity/exposures/base.py +++ b/climada/entity/exposures/base.py @@ -132,12 +132,40 @@ def gdf(self): @property def latitude(self): """Latitude array of exposures""" - return self.data.geometry.y.values + try: + return self.data.geometry.y.values + except ValueError as valerr: + nonpoints = list( + self.data[ + self.data.geometry.type != "Point" + ].geometry.type.drop_duplicates() + ) + if nonpoints: + raise ValueError( + "Can only calculate latitude from Points." + f" GeoDataFrame contains {', '.join(nonpoints)}." + " Please see the lines_polygons module tutorial." + ) from valerr + raise @property def longitude(self): """Longitude array of exposures""" - return self.data.geometry.x.values + try: + return self.data.geometry.x.values + except ValueError as valerr: + nonpoints = list( + self.data[ + self.data.geometry.type != "Point" + ].geometry.type.drop_duplicates() + ) + if nonpoints: + raise ValueError( + "Can only calculate longitude from Points." + f" GeoDataFrame contains {', '.join(nonpoints)}." + " Please see the lines_polygons module tutorial." + ) from valerr + raise @property def geometry(self): diff --git a/climada/entity/exposures/test/test_base.py b/climada/entity/exposures/test/test_base.py index 7c79f4a22..66e921cd4 100644 --- a/climada/entity/exposures/test/test_base.py +++ b/climada/entity/exposures/test/test_base.py @@ -27,7 +27,7 @@ import rasterio import scipy as sp from rasterio.windows import Window -from shapely.geometry import Point +from shapely.geometry import MultiPolygon, Point, Polygon from sklearn.metrics import DistanceMetric import climada.util.coordinates as u_coord @@ -652,6 +652,39 @@ def test_to_crs_epsg_crs(self): Exposures.to_crs(self, crs="GCS", epsg=26915) self.assertEqual("one of crs or epsg must be None", str(cm.exception)) + def test_latlon_with_polygons(self): + """Check for proper error message if the data frame contains non-Point shapes""" + poly = Polygon( + [(10.0, 0.0), (10.0, 1.0), (11.0, 1.0), (11.0, 0.0), (10.0, 0.0)] + ) + point = Point((1, -1)) + multi = MultiPolygon( + [ + ( + ((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)), + [((0.1, 1.1), (0.1, 1.2), (0.2, 1.2), (0.2, 1.1))], + ) + ] + ) + poly = Polygon() + exp = Exposures(geometry=[poly, point, multi, poly]) + with self.assertRaises(ValueError) as valer: + exp.latitude + self.assertEqual( + "Can only calculate latitude from Points." + " GeoDataFrame contains Polygon, MultiPolygon." + " Please see the lines_polygons module tutorial.", + str(valer.exception), + ) + with self.assertRaises(ValueError) as valer: + exp.longitude + self.assertEqual( + "Can only calculate longitude from Points." + " GeoDataFrame contains Polygon, MultiPolygon." + " Please see the lines_polygons module tutorial.", + str(valer.exception), + ) + class TestImpactFunctions(unittest.TestCase): """Test impact function handling"""