Skip to content

Commit

Permalink
Special no-data handling
Browse files Browse the repository at this point in the history
  • Loading branch information
m-mohr committed Dec 14, 2023
1 parent 377e367 commit d572913
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 36 deletions.
2 changes: 1 addition & 1 deletion assets/processes
Submodule processes updated 74 files
+15 −6 tests/README.md
+2 −2 tests/absolute.json5
+11 −11 tests/add.json5
+8 −8 tests/all.json5
+9 −9 tests/and.json5
+8 −8 tests/any.json5
+2 −2 tests/arccos.json5
+2 −2 tests/arcosh.json5
+2 −2 tests/arctan.json5
+7 −7 tests/arctan2.json5
+17 −17 tests/array_interpolate_linear.json5
+2 −2 tests/arsinh.json5
+2 −2 tests/artanh.json5
+2 −2 tests/between.json5
+2 −2 tests/ceil.json5
+2 −2 tests/clip.json5
+4 −4 tests/constant.json5
+2 −2 tests/cos.json5
+2 −2 tests/cosh.json5
+4 −4 tests/count.json5
+6 −6 tests/cummax.json5
+6 −6 tests/cummin.json5
+6 −6 tests/cumproduct.json5
+6 −6 tests/cumsum.json5
+2 −2 tests/divide.json5
+5 −5 tests/eq.json5
+2 −2 tests/exp.json5
+7 −7 tests/extrema.json5
+16 −1 tests/filter_bbox.json5
+11 −11 tests/first.json5
+2 −2 tests/floor.json5
+5 −5 tests/gt.json5
+5 −5 tests/gte.json5
+3 −3 tests/int.json5
+1 −1 tests/is_infinite.json5
+1 −1 tests/is_nan.json5
+3 −5 tests/is_nodata.json5
+3 −3 tests/is_valid.json5
+11 −11 tests/last.json5
+2 −2 tests/linear_scale_range.json5
+2 −2 tests/ln.json5
+2 −2 tests/log.json5
+5 −5 tests/lt.json5
+5 −5 tests/lte.json5
+5 −5 tests/max.json5
+12 −12 tests/mean.json5
+9 −9 tests/median.json5
+5 −5 tests/min.json5
+11 −11 tests/mod.json5
+11 −11 tests/multiply.json5
+5 −5 tests/neq.json5
+2 −2 tests/normalized_difference.json5
+2 −2 tests/not.json5
+9 −9 tests/or.json5
+8 −8 tests/order.json5
+4 −4 tests/power.json5
+6 −6 tests/product.json5
+7 −7 tests/quantiles.json5
+2 −2 tests/round.json5
+5 −5 tests/sd.json5
+2 −2 tests/sgn.json5
+2 −2 tests/sin.json5
+2 −2 tests/sinh.json5
+6 −6 tests/sort.json5
+2 −2 tests/sqrt.json5
+8 −8 tests/subtract.json5
+6 −6 tests/sum.json5
+2 −2 tests/tan.json5
+2 −2 tests/tanh.json5
+2 −2 tests/text_begins.json5
+2 −2 tests/text_contains.json5
+2 −2 tests/text_ends.json5
+5 −5 tests/variance.json5
+11 −11 tests/xor.json5
6 changes: 6 additions & 0 deletions src/openeo_test_suite/lib/process_runner/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,9 @@ def is_json_only(self) -> bool:
If True, the runner will skip all tests that contain non JSON values such as infinity and NaN.
"""
return False

def get_nodata_value(self) -> Any:
"""
Returns the nodata value of the backend.
"""
return None
7 changes: 7 additions & 0 deletions src/openeo_test_suite/lib/process_runner/dask.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import importlib
import inspect
import math

from openeo_pg_parser_networkx import OpenEOProcessGraph, ProcessRegistry
from openeo_pg_parser_networkx.process_registry import Process
Expand Down Expand Up @@ -65,3 +66,9 @@ def decode_data(self, data, expected):
data = numpy_to_native(data, expected)
data = xarray_to_datacube(data)
return data

def get_nodata_value(self):
"""
Returns the nodata value of the backend.
"""
return float('nan')
84 changes: 49 additions & 35 deletions src/openeo_test_suite/tests/processes/processing/test_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,63 +98,77 @@ def test_process(connection, process_levels, processes, id, example, file, level
elif returns:
check_return_value(example, result, connection)
else:
pytest.skip("Test doesn't provide an expected result")
pytest.skip("Test for process {} doesn't provide an expected result for arguments: {}".format(id, example["arguments"]))


def prepare_arguments(arguments, process_id, connection, file):
for name in arguments:
arg = arguments[name]

# handle external references to files
if isinstance(arg, dict) and "$ref" in arg:
arg = load_ref(arg["$ref"], file)
arguments[name] = prepare_argument(arguments[name], process_id, name, connection, file)

return arguments

# handle custom types of data
if isinstance(arg, dict):
if "type" in arg:
# labeled arrays
if arg["type"] == "labeled-array":
arg = connection.encode_labeled_array(arg)
# datacubes
elif arg["type"] == "datacube":
arg = connection.encode_datacube(arg)
elif "process_graph" in arg:
arg = connection.encode_process_graph(arg, process_id, name)
def prepare_argument(arg, process_id, name, connection, file):
# handle external references to files
if isinstance(arg, dict) and "$ref" in arg:
arg = load_ref(arg["$ref"], file)

arg = connection.encode_data(arg)
# handle custom types of data
if isinstance(arg, dict):
if "type" in arg:
# labeled arrays
if arg["type"] == "labeled-array":
arg = connection.encode_labeled_array(arg)
# datacubes
elif arg["type"] == "datacube":
arg = connection.encode_datacube(arg)
# nodata-values
elif arg["type"] == "nodata":
arg = connection.get_nodata_value()
elif "process_graph" in arg:
arg = connection.encode_process_graph(arg, process_id, name)
else:
for key in arg:
arg[key] = prepare_argument(arg[key], process_id, name, connection, file)

elif isinstance(arg, list):
for i in range(len(arg)):
arg[i] = prepare_argument(arg[i], process_id, name, connection, file)

if connection.is_json_only():
check_non_json_values(arg)
arg = connection.encode_data(arg)

arguments[name] = arg
if connection.is_json_only():
check_non_json_values(arg)

return arguments
return arg


def prepare_results(example, result = None):
def prepare_results(connection, example, result = None):
# go through the example and result recursively and convert datetimes to iso strings
# could be used for more conversions in the future...

if isinstance(example, dict):
if "type" in example and example["type"] == "datetime":
example = isostr_to_datetime(example["value"])
try:
result = isostr_to_datetime(result)
except:
pass
if "type" in example:
if example["type"] == "datetime":
example = isostr_to_datetime(example["value"])
try:
result = isostr_to_datetime(result)
except:
pass
elif example["type"] == "nodata":
example = connection.get_nodata_value()
else:
for key in example:
if key not in result:
(example[key],) = prepare_results(example[key])
(example[key],) = prepare_results(connection, example[key])
else:
(example[key], result[key]) = prepare_results(example[key], result[key])
(example[key], result[key]) = prepare_results(connection, example[key], result[key])

elif isinstance(example, list):
for i in range(len(example)):
if i >= len(result):
(example[i],) = prepare_results(example[i])
(example[i],) = prepare_results(connection, example[i])
else:
(example[i], result[i]) = prepare_results(example[i], result[i])
(example[i], result[i]) = prepare_results(connection, example[i], result[i])

return (example, result)

Expand Down Expand Up @@ -206,8 +220,8 @@ def check_return_value(example, result, connection):
# handle custom types of data
result = connection.decode_data(result, example["returns"])

# decode special types (currently mostly datetimes)
(example["returns"], result) = prepare_results(example["returns"], result)
# decode special types (currently mostly datetimes and nodata)
(example["returns"], result) = prepare_results(connection, example["returns"], result)

delta = example["delta"] if "delta" in example else 0.0000000001

Expand Down

0 comments on commit d572913

Please sign in to comment.