Skip to content

Commit

Permalink
Serve flooded buildings data to terria without styling
Browse files Browse the repository at this point in the history
  • Loading branch information
LukeParky committed Feb 3, 2025
1 parent 23039f0 commit 7e85b4b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 16 deletions.
35 changes: 28 additions & 7 deletions floodresilience/flood_model/flood_scenario_process_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@

"""Defines PyWPS WebProcessingService process for creating a flooding scenario."""

import json

from geopandas import GeoDataFrame
from pywps import BoundingBoxInput, Process, LiteralInput, LiteralOutput, WPSRequest
from pywps import BoundingBoxInput, ComplexOutput, Format, LiteralInput, LiteralOutput, Process, WPSRequest
from pywps.inout.literaltypes import AnyValue
from pywps.response.execute import ExecuteResponse
from shapely import box

from floodresilience import tasks
from src.config import cast_str_to_bool
from src.config import cast_str_to_bool, EnvVariable as EnvVar


class FloodScenarioProcessService(Process):
Expand All @@ -49,7 +51,8 @@ def __init__(self) -> None:
]
# Create area WPS outputs
outputs = [
LiteralOutput("area", "Area", data_type="string")
ComplexOutput("floodedBuildings", "Flooded Buildings",
supported_formats=[Format("application/vnd.terriajs.catalog-member+json")]),
]

# Initialise the process
Expand Down Expand Up @@ -89,8 +92,26 @@ def _handler(request: WPSRequest, response: ExecuteResponse) -> None:
}

modelling_task = tasks.create_model_for_area(bounding_box.wkt, scenario_options)
modelling_task.get()
scenario_id = modelling_task.get()

gs_building_workspace = f"{EnvVar.POSTGRES_DB}-buildings"
gs_building_url = f"{EnvVar.GEOSERVER_HOST}:{EnvVar.GEOSERVER_PORT}/geoserver/{gs_building_workspace}/ows"

# Calculate area in square metres
area = "unknown"
response.outputs['area'].data = area
# Add Geoserver JSON Catalog entries to WPS response for use by Terria
response.outputs['floodedBuildings'].data = json.dumps({
"type": "wfs",
"name": "Building Flood Status",
"url": gs_building_url,
"typeNames": f"{gs_building_workspace}:building_flood_status",
"parameters": {
"viewparams": f"scenario:{scenario_id}",
},
"maxFeatures": 300000,
"defaultStyle": {
"outline": {
"null": {
"width": 0
}
}
}
})
21 changes: 12 additions & 9 deletions floodresilience/flood_model/serve_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import logging
import os
import pathlib
from xml.sax import saxutils

import xarray as xr

Expand Down Expand Up @@ -82,21 +83,23 @@ def create_building_layers(workspace_name: str, data_store_name: str) -> None:

# More complex layer that has to do dynamic sql queries against model output ID to fetch
flood_status_layer_name = "building_flood_status"
flooded_buildings_sql_query = """
SELECT *,
building_flood_status.is_flooded::int AS is_flooded_int
FROM nz_building_outlines
LEFT OUTER JOIN building_flood_status USING (building_outline_id)
WHERE building_outline_lifecycle ILIKE 'current'
AND flood_model_id=%scenario%
"""
xml_escaped_sql = saxutils.escape(flooded_buildings_sql_query, entities={r"'": "'", "\n": "
"})

flood_status_xml_query = rf"""
<metadata>
<entry key="JDBC_VIRTUAL_TABLE">
<virtualTable>
<name>{flood_status_layer_name}</name>
<sql>
SELECT * &#xd;
FROM nz_building_outlines&#xd;
LEFT OUTER JOIN (&#xd;
SELECT *&#xd;
FROM building_flood_status&#xd;
WHERE flood_model_id=%scenario%&#xd;
) AS flood_statuses&#xd;
USING (building_outline_id)&#xd;
WHERE building_outline_lifecycle ILIKE &apos;current&apos;
{xml_escaped_sql}
</sql>
<escapeSql>false</escapeSql>
<geometry>
Expand Down

0 comments on commit 7e85b4b

Please sign in to comment.