Skip to content

Commit

Permalink
Simplify process logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Zeitsperre committed Feb 3, 2021
1 parent 8f9054f commit dc7da3b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 92 deletions.
106 changes: 36 additions & 70 deletions emu/processes/wps_geospatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ def __init__(self):
"raster",
"Raster grid of a general region.",
abstract="A Well-Known-Test definition for a region.",
min_occurs=0,
min_occurs=1,
max_occurs=1,
supported_formats=[FORMATS.GEOTIFF],
),
ComplexInput(
"vector",
"Region definition in GeoJSON format",
abstract="A polygon defining a region.",
min_occurs=0,
min_occurs=1,
max_occurs=1,
supported_formats=[
FORMATS.GEOJSON,
Expand Down Expand Up @@ -77,74 +77,48 @@ def __init__(self):
)

def _handler(self, request, response):
from collections import namedtuple
import json
import tempfile

from shapely.geometry import box, mapping, shape
from shapely.geometry import mapping, shape
import fiona
import rasterio as rio
from rasterio.mask import mask

response.update_status("PyWPS Process started.", 0)

vec_file = request.inputs["vector"][0].file
ras_file = request.inputs["raster"][0].file

response.update_status("Reading Vector file", 10)
try:
vec_file = request.inputs["vector"][0].file
except KeyError:
vec_file = None
try:
ras_file = request.inputs["raster"][0].file
except KeyError:
ras_file = None

if vec_file is None and ras_file is None:
raise Exception("You need to provide at least one dataset.")

Centroid = namedtuple("Centroid", "x y")
centroid = Centroid(0, 0)

polygon = None
bounds = ""
buffered_geojson = None
if vec_file is not None:
response.update_status("Reading Vector file", 10)
try:
with fiona.open(vec_file, mode='r') as f:
feature = next(iter(f))
polygon = shape(feature["geometry"])
bounds = [*polygon.bounds]
centroid = polygon.centroid

buffered = polygon.buffer(5)
buffered_geojson = tempfile.NamedTemporaryFile(
prefix="out_", suffix=".geojson", delete=False, dir=self.workdir
).name
with open(buffered_geojson, "w") as bf:
output = {"type": "FeatureCollection", "features": []}
feature["geometry"] = mapping(buffered)
output["features"].append(feature)
bf.write(f"{json.dumps(output)}")

except Exception as e:
msg = f"{e}: unable to read vector file."
logging.warning(msg=msg)
raise

subset_geotiff = None
if ras_file:
response.update_status("Reading Raster file", 30)
with rio.open(ras_file, mode="r") as data:
if not polygon:
# Clip the raster to a quadrant
w, s, e, n = data.bounds
x_0, y_0 = (e + w) / 2, (n + s) / 2
b = box(w, s, x_0, y_0)
bounds = [*b.bounds]
masked, _ = mask(dataset=data, shapes=[b], crop=True)
else:
# Clip the raster with the found shape
masked, _ = mask(dataset=data, shapes=[polygon], crop=True)
output_meta = data.meta.copy()
with fiona.open(vec_file, mode='r') as f:
feature = next(iter(f))
polygon = shape(feature["geometry"])
bounds = [*polygon.bounds]
centroid = polygon.centroid

buffered = polygon.buffer(5)
buffered_geojson = tempfile.NamedTemporaryFile(
prefix="out_", suffix=".geojson", delete=False, dir=self.workdir
).name
response.update_status("Writing Vector file", 10)
with open(buffered_geojson, "w") as bf:
output = {"type": "FeatureCollection", "features": []}
feature["geometry"] = mapping(buffered)
output["features"].append(feature)
bf.write(f"{json.dumps(output)}")

except Exception as e:
msg = f"{e}: unable to read vector file."
logging.warning(msg=msg)
raise

response.update_status("Reading Raster file", 30)
with rio.open(ras_file, mode="r") as data:
# Clip the raster with the found shape
masked, _ = mask(dataset=data, shapes=[polygon], crop=True)
output_meta = data.meta.copy()
output_meta.update(
dict(driver="GTiff", height=masked.shape[1], width=masked.shape[2])
)
Expand All @@ -161,16 +135,8 @@ def _handler(self, request, response):
centroid.x, centroid.y
)
response.outputs["bounds"].data = bounds

if subset_geotiff is not None:
response.outputs["raster"].file = subset_geotiff
else:
response.outputs["raster"].data = ""

if buffered_geojson is not None:
response.outputs["vector"].file = buffered_geojson
else:
response.outputs["vector"].data = ""
response.outputs["raster"].file = subset_geotiff
response.outputs["vector"].file = buffered_geojson

response.update_status("PyWPS Process completed.", 100)

Expand Down
30 changes: 8 additions & 22 deletions tests/test_wps_geospatial.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import pytest

from pywps import Service
from pywps.tests import assert_response_success
from emu.processes.wps_geospatial import GeoData
Expand All @@ -7,38 +9,22 @@
def test_wps_geodata():

client = client_for(Service(processes=[GeoData()], cfgfiles=CFG_FILE))

datainputs = f"vector=@xlink:href=file://{resource_file('Olympus_Mons.json')};" \
f"raster=@xlink:href=file://{resource_file('Olympus.tif')}"

resp = client.get(
service='wps', request='execute', version='1.0.0',
identifier='geodata', datainputs=datainputs)

assert_response_success(resp)


def test_wps_geodata_novector():
def test_wps_geodata_novector_fails():

client = client_for(Service(processes=[GeoData()], cfgfiles=CFG_FILE))

datainputs = f"raster=@xlink:href=file://{resource_file('Olympus.tif')}"

resp = client.get(
service='wps', request='execute', version='1.0.0',
identifier='geodata', datainputs=datainputs)

assert_response_success(resp)


def test_wps_geodata_noraster():

client = client_for(Service(processes=[GeoData()], cfgfiles=CFG_FILE))

datainputs = f"vector=@xlink:href=file://{resource_file('Olympus_Mons.json')};"

resp = client.get(
service='wps', request='execute', version='1.0.0',
identifier='geodata', datainputs=datainputs)

assert_response_success(resp)
with pytest.raises(AssertionError):
resp = client.get(
service='wps', request='execute', version='1.0.0',
identifier='geodata', datainputs=datainputs)
assert_response_success(resp)

0 comments on commit dc7da3b

Please sign in to comment.