Skip to content

Commit

Permalink
Point extent bug (#12734)
Browse files Browse the repository at this point in the history
GitOrigin-RevId: 5cfa9553f9c813c5cbae3b1bea4f9c7042a17c00
  • Loading branch information
mat-savage authored and Descartes Labs Build committed Nov 27, 2024
1 parent bcd512e commit 1e550c7
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 32 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Changelog

## Unreleased

## Catalog

- Fixed a bug where some geometries weren't supported by blob geometry properties

## [3.2.2] - 2024-11-14

## Catalog
Expand Down
138 changes: 117 additions & 21 deletions descarteslabs/core/catalog/tests/test_blob.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def _blob_do_download(_, dest=None, range=None):


class TestBlob(ClientTestCase):
geometry = {
polygon_geometry = {
"type": "Polygon",
"coordinates": [
[
Expand All @@ -87,6 +87,96 @@ class TestBlob(ClientTestCase):
]
],
}
multipolygon_geometry = {
"type": "MultiPolygon",
"coordinates": [
[
[
[-95.2989209, 42.7999878],
[-93.1167728, 42.3858464],
[-93.7138666, 40.703737],
[-95.8364984, 41.1150618],
[-95.2989209, 42.7999878],
]
],
[
[
[-95.3989209, 42.7999878],
[-93.4167728, 42.3858464],
[-93.7138666, 40.703737],
[-95.6364984, 41.1150618],
[-95.3989209, 42.7999878],
]
],
],
}
point_geometry = {
"type": "Point",
"coordinates": [-95.2989209, 42.7999878],
}
multipoint_geometry = {
"type": "MultiPoint",
"coordinates": [
[-95.2989209, 42.7999878],
[-96.2989209, 43.7999878],
],
}
multipoint_all_coincident_geometry = {
"type": "MultiPoint",
"coordinates": [
[-95.2989209, 42.7999878],
[-95.2989209, 42.7999878],
],
}
line_geometry = {
"type": "LineString",
"coordinates": [
[-122.17523623224433, 47.90651694142758],
[-122.13437682048007, 47.88564432387702],
],
}
horizontal_line_geometry = {
"type": "LineString",
"coordinates": [
[-122.17523623224433, 47.88564432387702],
[-122.13437682048007, 47.88564432387702],
],
}
vertical_line_geometry = {
"type": "LineString",
"coordinates": [
[-122.17523623224433, 47.90651694142758],
[-122.17523623224433, 47.88564432387702],
],
}
multiline_geometry = {
"type": "MultiLineString",
"coordinates": [
[
[-122.13826819210863, 47.90599522815964],
[-122.12931803524592, 47.91303790851427],
],
[
[-122.13865732936327, 47.920340416616256],
[-122.12892889799097, 47.912777085591244],
],
[
[-122.17601450675424, 47.91277722269507],
[-122.1293180361663, 47.91277722269507],
],
],
}

test_geometries = [
polygon_geometry,
multipolygon_geometry,
point_geometry,
multipoint_geometry,
line_geometry,
horizontal_line_geometry,
vertical_line_geometry,
multiline_geometry,
]

test_combinations = [
{"value": b"This is mock download data. It can be any binary data."},
Expand Down Expand Up @@ -133,13 +223,15 @@ def test_repr(self):
assert b_repr.strip("\n") == textwrap.dedent(match_str)

def test_set_geometry(self):
shape = shapely.geometry.shape(self.geometry)
b = Blob(id="data/descarteslabs:test/test-blob", name="test-blob")
b.geometry = self.geometry
assert shape == b.geometry
for test_geometry in self.test_geometries:
shape = shapely.geometry.shape(test_geometry)

b.geometry = test_geometry
assert shape == b.geometry

b.geometry = shape
assert shape == b.geometry
b.geometry = shape
assert shape == b.geometry

with pytest.raises(AttributeValidationError):
b.geometry = {"type": "Lollipop"}
Expand All @@ -160,19 +252,23 @@ def test_storage_type_new(self):
StorageType("nodata")

def test_search_intersects(self):
search = Blob.search().intersects(self.geometry).filter(Properties().id == "b1")
search = (
Blob.search()
.intersects(self.polygon_geometry)
.filter(Properties().id == "b1")
)
_, request_params = search._to_request()
assert self.geometry == json.loads(request_params["intersects"])
assert self.polygon_geometry == json.loads(request_params["intersects"])
assert "intersects_none" not in request_params

def test_search_intersects_none(self):
search = (
Blob.search()
.intersects(self.geometry, match_null_geometry=True)
.intersects(self.polygon_geometry, match_null_geometry=True)
.filter(Properties().id == "b1")
)
_, request_params = search._to_request()
assert self.geometry == json.loads(request_params["intersects"])
assert self.polygon_geometry == json.loads(request_params["intersects"])
assert request_params["intersects_none"] is True

@responses.activate
Expand All @@ -186,7 +282,7 @@ def test_get(self):
"description": "a generic description",
"expires": None,
"extra_properties": {},
"geometry": self.geometry,
"geometry": self.polygon_geometry,
"hash": "28495fde1c101c01f2d3ae92d1af85a5",
"href": "s3://super/long/uri/data/descarteslabs:test-namespace/test-blob",
"modified": "2023-09-29T15:54:37.006769Z",
Expand All @@ -213,7 +309,7 @@ def test_get(self):
assert isinstance(b.created, datetime)
assert b.description == "a generic description"
assert b.expires is None
assert b.geometry == shapely.geometry.shape(self.geometry)
assert b.geometry == shapely.geometry.shape(self.polygon_geometry)
assert b.hash == "28495fde1c101c01f2d3ae92d1af85a5"
assert (
b.href == "s3://super/long/uri/data/descarteslabs:test-namespace/test-blob"
Expand All @@ -239,7 +335,7 @@ def test_get_unknown_attribute(self):
"description": "a generic description",
"expires": None,
"extra_properties": {},
"geometry": self.geometry,
"geometry": self.polygon_geometry,
"hash": "28495fde1c101c01f2d3ae92d1af85a5",
"href": "s3://super/long/uri/data/descarteslabs:test-namespace/test-blob",
"modified": "2023-09-29T15:54:37.006769Z",
Expand Down Expand Up @@ -278,7 +374,7 @@ def test_get_many(self):
"description": "a generic description",
"expires": None,
"extra_properties": {},
"geometry": self.geometry,
"geometry": self.polygon_geometry,
"hash": "28495fde1c101c01f2d3ae92d1af85a5",
"href": "s3://super/long/uri/data/descarteslabs:test-namespace/test-blob-1",
"modified": "2023-09-29T15:54:37.006769Z",
Expand All @@ -301,7 +397,7 @@ def test_get_many(self):
"description": "a generic description",
"expires": None,
"extra_properties": {},
"geometry": self.geometry,
"geometry": self.polygon_geometry,
"hash": "28495fde1c101c01f2d3ae92d1af85a5",
"href": "s3://super/long/uri/data/descarteslabs:test-namespace/test-blob-2",
"modified": "2023-09-29T15:54:37.006769Z",
Expand Down Expand Up @@ -346,7 +442,7 @@ def test_get_or_create(self):
"description": "a generic description",
"expires": None,
"extra_properties": {},
"geometry": self.geometry,
"geometry": self.polygon_geometry,
"hash": "28495fde1c101c01f2d3ae92d1af85a5",
"href": "s3://super/long/uri/data/descarteslabs:test-namespace/test-blob",
"modified": "2023-09-29T15:54:37.006769Z",
Expand Down Expand Up @@ -386,7 +482,7 @@ def test_list(self):
"description": "a generic description",
"expires": None,
"extra_properties": {},
"geometry": self.geometry,
"geometry": self.polygon_geometry,
"hash": "28495fde1c101c01f2d3ae92d1af85a5",
"href": "s3://super/long/uri/data/descarteslabs:test-namespace/test-blob-1",
"modified": "2023-09-29T15:54:37.006769Z",
Expand All @@ -409,7 +505,7 @@ def test_list(self):
"description": "a generic description",
"expires": None,
"extra_properties": {},
"geometry": self.geometry,
"geometry": self.polygon_geometry,
"hash": "28495fde1c101c01f2d3ae92d1af85a5",
"href": "s3://super/long/uri/data/descarteslabs:test-namespace/test-blob-2",
"modified": "2023-09-29T15:54:37.006769Z",
Expand Down Expand Up @@ -461,7 +557,7 @@ def test_save(self):
"description": "a generic description",
"expires": None,
"extra_properties": {},
"geometry": self.geometry,
"geometry": self.polygon_geometry,
"hash": "28495fde1c101c01f2d3ae92d1af85a5",
"href": "s3://super/long/uri/data/descarteslabs:test-namespace/test-blob",
"modified": "2023-09-29T15:54:37.006769Z",
Expand Down Expand Up @@ -546,7 +642,7 @@ def test_update(self):
"owners": ["org:descarteslabs"],
"name": "test-blob",
"namespace": "descarteslabs:test-namespace",
"geometry": self.geometry,
"geometry": self.polygon_geometry,
"storage_type": "data",
"storage_state": "available",
"readers": [],
Expand Down Expand Up @@ -600,7 +696,7 @@ def test_reload(self):
"owners": ["org:descarteslabs"],
"name": "test-blob",
"namespace": "descarteslabs:test-namespace",
"geometry": self.geometry,
"geometry": self.polygon_geometry,
"storage_type": "data",
"storage_state": "available",
"readers": [],
Expand Down
31 changes: 21 additions & 10 deletions descarteslabs/core/common/shapely_support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def geometry_like_to_shapely(geometry):
)

# test that geometry is in WGS84
check_valid_bounds(shape.bounds)
check_valid_bounds(shape.bounds, shape.geom_type)
return shape


Expand Down Expand Up @@ -107,7 +107,7 @@ def _parse_geojson_safe(geojson_dict):
return geoj


def check_valid_bounds(bounds):
def check_valid_bounds(bounds, geom_type=None):
"""
Test given bounds are correct type and in correct order.
Expand All @@ -133,11 +133,22 @@ def check_valid_bounds(bounds):
)
) from None

if bounds[0] >= bounds[2]:
raise ValueError(
"minx >= maxx in given bounds, should be (minx, miny, maxx, maxy)"
)
if bounds[1] >= bounds[3]:
raise ValueError(
"miny >= maxy in given bounds, should be (minx, miny, maxx, maxy)"
)
# Only check polygons and multipolygons here
if geom_type and geom_type.endswith("Polygon"):
if bounds[0] >= bounds[2]:
raise ValueError(
"minx >= maxx in given bounds, should be (minx, miny, maxx, maxy)"
)
if bounds[1] >= bounds[3]:
raise ValueError(
"miny >= maxy in given bounds, should be (minx, miny, maxx, maxy)"
)
else:
if bounds[0] > bounds[2]:
raise ValueError(
"minx > maxx in given bounds, should be (minx, miny, maxx, maxy)"
)
if bounds[1] > bounds[3]:
raise ValueError(
"miny > maxy in given bounds, should be (minx, miny, maxx, maxy)"
)
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,14 @@ def test_check_valid_bounds(self):

with pytest.raises(ValueError):
check_valid_bounds(bounds_wrong_order)
with pytest.raises(ValueError):
check_valid_bounds(bounds_wrong_order, "Polygon")
with pytest.raises(ValueError):
check_valid_bounds(bounds_wrong_number)
with pytest.raises(TypeError):
check_valid_bounds(bounds_wrong_type)
with pytest.raises(ValueError):
check_valid_bounds(bounds_point)
check_valid_bounds(bounds_point, "Polygon")

def test_as_geojson_geometry(self):
geoj = as_geojson_geometry(self.feature["geometry"])
Expand Down

0 comments on commit 1e550c7

Please sign in to comment.