diff --git a/requirements.txt b/requirements.txt index a596a0a..08d64bd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -60,4 +60,3 @@ werkzeug==3.1.2 # flask # flask-cors -opengeodeweb-microservice==1.*,>=1.0.13rc1 diff --git a/src/opengeodeweb_back/routes/blueprint_routes.py b/src/opengeodeweb_back/routes/blueprint_routes.py index 570ef41..88ab768 100644 --- a/src/opengeodeweb_back/routes/blueprint_routes.py +++ b/src/opengeodeweb_back/routes/blueprint_routes.py @@ -8,6 +8,7 @@ import flask import werkzeug import zipfile +import opengeode as og import opengeode_io as og_io import opengeode_geosciences as og_geosciences import opengeode_geosciencesio as og_geosciencesio @@ -264,6 +265,30 @@ def texture_coordinates() -> flask.Response: return flask.make_response({"texture_coordinates": texture_coordinates}, 200) +def attributes_metadata(manager: og.AttributeManager) -> dict[str, list[float]]: + metadata: dict[str, list[float]] = {} + for name in manager.attribute_names(): + attribute = manager.find_generic_attribute(name) + if not attribute.is_genericable(): + metadata[name] = [-1.0, -1.0] + continue + min_value = None + max_value = None + nb_items = attribute.nb_items() + for i in range(nb_items): + generic_value = attribute.generic_value(i) + if min_value is None or generic_value < min_value: + min_value = generic_value + if max_value is None or generic_value > max_value: + max_value = generic_value + metadata[name] = ( + [min_value, max_value] + if min_value is not None and max_value is not None + else [-1.0, -1.0] + ) + return metadata + + @routes.route( schemas_dict["vertex_attribute_names"]["route"], methods=schemas_dict["vertex_attribute_names"]["methods"], @@ -276,10 +301,11 @@ def vertex_attribute_names() -> flask.Response: geode_object = geode_functions.load_geode_object(params.id) if not isinstance(geode_object, GeodeMesh): flask.abort(400, f"{params.id} is not a GeodeMesh") - vertex_attribute_names = geode_object.vertex_attribute_manager().attribute_names() + attribute_manager = geode_object.vertex_attribute_manager() return flask.make_response( { - "vertex_attribute_names": vertex_attribute_names, + "vertex_attribute_names": attribute_manager.attribute_names(), + "vertex_attribute_metadata": attributes_metadata(attribute_manager), }, 200, ) @@ -297,10 +323,11 @@ def cell_attribute_names() -> flask.Response: geode_object = geode_functions.load_geode_object(params.id) if not isinstance(geode_object, GeodeGrid2D | GeodeGrid3D): flask.abort(400, f"{params.id} is not a GeodeGrid") - cell_attribute_names = geode_object.cell_attribute_manager().attribute_names() + attribute_manager = geode_object.cell_attribute_manager() return flask.make_response( { - "cell_attribute_names": cell_attribute_names, + "cell_attribute_names": attribute_manager.attribute_names(), + "cell_attribute_metadata": attributes_metadata(attribute_manager), }, 200, ) @@ -318,10 +345,11 @@ def polygon_attribute_names() -> flask.Response: geode_object = geode_functions.load_geode_object(params.id) if not isinstance(geode_object, GeodeSurfaceMesh2D | GeodeSurfaceMesh3D): flask.abort(400, f"{params.id} is not a GeodeSurfaceMesh") - polygon_attribute_names = geode_object.polygon_attribute_manager().attribute_names() + attribute_manager = geode_object.polygon_attribute_manager() return flask.make_response( { - "polygon_attribute_names": polygon_attribute_names, + "polygon_attribute_names": attribute_manager.attribute_names(), + "polygon_attribute_metadata": attributes_metadata(attribute_manager), }, 200, ) @@ -339,12 +367,11 @@ def polyhedron_attribute_names() -> flask.Response: geode_object = geode_functions.load_geode_object(params.id) if not isinstance(geode_object, GeodeSolidMesh3D): flask.abort(400, f"{params.id} is not a GeodeSolidMesh") - polyhedron_attribute_names = ( - geode_object.polyhedron_attribute_manager().attribute_names() - ) + attribute_manager = geode_object.polyhedron_attribute_manager() return flask.make_response( { - "polyhedron_attribute_names": polyhedron_attribute_names, + "polyhedron_attribute_names": attribute_manager.attribute_names(), + "polyhedron_attribute_metadata": attributes_metadata(attribute_manager), }, 200, ) @@ -362,10 +389,11 @@ def edge_attribute_names() -> flask.Response: geode_object = geode_functions.load_geode_object(params.id) if not isinstance(geode_object, GeodeGraph): flask.abort(400, f"{params.id} does not have edges") - edge_attribute_names = geode_object.edge_attribute_manager().attribute_names() + attribute_manager = geode_object.edge_attribute_manager() return flask.make_response( { - "edge_attribute_names": edge_attribute_names, + "edge_attribute_names": attribute_manager.attribute_names(), + "edge_attribute_metadata": attributes_metadata(attribute_manager), }, 200, ) diff --git a/tests/test_routes.py b/tests/test_routes.py index 4c84f32..d40c68a 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -245,9 +245,12 @@ def test_vertex_attribute_names(client: FlaskClient, test_id: str) -> None: response = client.post(route, json={"id": data.id}) assert response.status_code == 200 vertex_attribute_names = response.get_json()["vertex_attribute_names"] + vertex_attribute_metadata = response.get_json()["vertex_attribute_metadata"] assert type(vertex_attribute_names) is list + assert type(vertex_attribute_metadata) is dict for vertex_attribute_name in vertex_attribute_names: assert type(vertex_attribute_name) is str + assert vertex_attribute_name in vertex_attribute_metadata def test_cell_attribute_names(client: FlaskClient, test_id: str) -> None: @@ -271,9 +274,12 @@ def test_cell_attribute_names(client: FlaskClient, test_id: str) -> None: response = client.post(route, json={"id": data.id}) assert response.status_code == 200 cell_attribute_names = response.get_json()["cell_attribute_names"] + cell_attribute_metadata = response.get_json()["cell_attribute_metadata"] assert type(cell_attribute_names) is list + assert type(cell_attribute_metadata) is dict for cell_attribute_name in cell_attribute_names: assert type(cell_attribute_name) is str + assert cell_attribute_name in cell_attribute_metadata def test_polygon_attribute_names(client: FlaskClient, test_id: str) -> None: @@ -297,9 +303,12 @@ def test_polygon_attribute_names(client: FlaskClient, test_id: str) -> None: response = client.post(route, json={"id": data.id}) assert response.status_code == 200 polygon_attribute_names = response.get_json()["polygon_attribute_names"] + polygon_attribute_metadata = response.get_json()["polygon_attribute_metadata"] assert type(polygon_attribute_names) is list + assert type(polygon_attribute_metadata) is dict for polygon_attribute_name in polygon_attribute_names: assert type(polygon_attribute_name) is str + assert polygon_attribute_name in polygon_attribute_metadata def test_polyhedron_attribute_names(client: FlaskClient, test_id: str) -> None: @@ -324,9 +333,15 @@ def test_polyhedron_attribute_names(client: FlaskClient, test_id: str) -> None: print(response.get_json()) assert response.status_code == 200 polyhedron_attribute_names = response.get_json()["polyhedron_attribute_names"] + polyhedron_attribute_metadata = response.get_json()["polyhedron_attribute_metadata"] assert type(polyhedron_attribute_names) is list + assert type(polyhedron_attribute_metadata) is dict for polyhedron_attribute_name in polyhedron_attribute_names: assert type(polyhedron_attribute_name) is str + assert polyhedron_attribute_name in polyhedron_attribute_metadata + + if "Range" in polyhedron_attribute_metadata: + assert polyhedron_attribute_metadata["Range"] == [0.0, 579.0] def test_edge_attribute_names(client: FlaskClient, test_id: str) -> None: @@ -351,9 +366,12 @@ def test_edge_attribute_names(client: FlaskClient, test_id: str) -> None: print(response.get_json()) assert response.status_code == 200 edge_attribute_names = response.get_json()["edge_attribute_names"] + edge_attribute_metadata = response.get_json()["edge_attribute_metadata"] assert type(edge_attribute_names) is list + assert type(edge_attribute_metadata) is dict for edge_attribute_name in edge_attribute_names: assert type(edge_attribute_name) is str + assert edge_attribute_name in edge_attribute_metadata def test_database_uri_path(client: FlaskClient) -> None: