diff --git a/api/routers/edr.py b/api/routers/edr.py index d0426fa1..956d1701 100644 --- a/api/routers/edr.py +++ b/api/routers/edr.py @@ -33,7 +33,9 @@ async def get_locations(bbox: str = Query(..., example="5.0,52.0,6.0,52.1")) -> poly = geometry.Polygon([(left, bottom), (right, bottom), (right, top), (left, top)]) ts_request = dstore.GetObsRequest( instruments=["tn"], # Hack - inside=dstore.Polygon(points=[dstore.Point(lat=coord[1], lon=coord[0]) for coord in poly.exterior.coords]), + spatial_area=dstore.Polygon( + points=[dstore.Point(lat=coord[1], lon=coord[0]) for coord in poly.exterior.coords] + ), ) ts_response = await getObsRequest(ts_request) @@ -70,7 +72,7 @@ async def get_data_location_id( get_obs_request = dstore.GetObsRequest( platforms=[location_id], instruments=list(map(str.strip, parameter_name.split(","))), - interval=dstore.TimeInterval(start=range[0], end=range[1]) if range else None, + temporal_interval=dstore.TimeInterval(start=range[0], end=range[1]) if range else None, ) response = await getObsRequest(get_obs_request) return edr_formatter[f].convert(response) @@ -111,8 +113,10 @@ async def get_data_area( range = get_datetime_range(datetime) get_obs_request = dstore.GetObsRequest( instruments=list(map(str.strip, parameter_name.split(","))), - inside=dstore.Polygon(points=[dstore.Point(lat=coord[1], lon=coord[0]) for coord in poly.exterior.coords]), - interval=dstore.TimeInterval(start=range[0], end=range[1]) if range else None, + spatial_area=dstore.Polygon( + points=[dstore.Point(lat=coord[1], lon=coord[0]) for coord in poly.exterior.coords] + ), + temporal_interval=dstore.TimeInterval(start=range[0], end=range[1]) if range else None, ) coverages = await getObsRequest(get_obs_request) coverages = edr_formatter[f].convert(coverages) diff --git a/datastore/datastore/README.md b/datastore/datastore/README.md index 3b2d8f9f..c9e7d2bc 100644 --- a/datastore/datastore/README.md +++ b/datastore/datastore/README.md @@ -215,28 +215,28 @@ $ grpcurl -plaintext -proto protobuf/datastore.proto 127.0.0.1:50050 datastore.D ### Retrieve observations in a time range ```text -$ grpcurl -d '{"interval": {"start": "2023-01-01T00:00:00Z", "end": "2023-01-01T00:00:10Z"}}' -plaintext -proto protobuf/datastore.proto 127.0.0.1:50050 datastore.Datastore.GetObservations +$ grpcurl -d '{"temporal_interval": {"start": "2023-01-01T00:00:00Z", "end": "2023-01-01T00:00:10Z"}}' -plaintext -proto protobuf/datastore.proto 127.0.0.1:50050 datastore.Datastore.GetObservations ... ``` ### Retrieve observations in a polygon ```text -$ grpcurl -d '{"inside": {"points": [{"lat": 59.90, "lon": 10.70}, {"lat": 59.90, "lon": 10.80}, {"lat": 60, "lon": 10.80}, {"lat": 60, "lon": 10.70}]}}' -plaintext -proto protobuf/datastore.proto 127.0.0.1:50050 datastore.Datastore.GetObservations +$ grpcurl -d '{"spatial_area": {"points": [{"lat": 59.90, "lon": 10.70}, {"lat": 59.90, "lon": 10.80}, {"lat": 60, "lon": 10.80}, {"lat": 60, "lon": 10.70}]}}' -plaintext -proto protobuf/datastore.proto 127.0.0.1:50050 datastore.Datastore.GetObservations ... ``` ### Retrieve observations in both a time range and a polygon ```text -$ grpcurl -d '{"interval": {"start": "2023-01-01T00:00:00Z", "end": "2023-01-01T00:00:10Z"}, "inside": {"points": [{"lat": 59.90, "lon": 10.70}, {"lat": 59.90, "lon": 10.80}, {"lat": 60, "lon": 10.80}, {"lat": 60, "lon": 10.70}]}}' -plaintext -proto protobuf/datastore.proto 127.0.0.1:50050 datastore.Datastore.GetObservations +$ grpcurl -d '{"temporal_interval": {"start": "2023-01-01T00:00:00Z", "end": "2023-01-01T00:00:10Z"}, "spatial_area": {"points": [{"lat": 59.90, "lon": 10.70}, {"lat": 59.90, "lon": 10.80}, {"lat": 60, "lon": 10.80}, {"lat": 60, "lon": 10.70}]}}' -plaintext -proto protobuf/datastore.proto 127.0.0.1:50050 datastore.Datastore.GetObservations ... ``` ### Retrieve wind speed and air temperature observations in a time range and a polygon ```text -$ grpcurl -d '{"standard_names": ["wind_speed", "air_temperature"], "interval": {"start": "2023-01-01T00:00:00Z", "end": "2023-01-01T00:00:10Z"}, "inside": {"points": [{"lat": 59.90, "lon": 10.70}, {"lat": 59.90, "lon": 10.80}, {"lat": 60, "lon": 10.80}, {"lat": 60, "lon": 10.70}]}}' -plaintext -proto protobuf/datastore.proto 127.0.0.1:50050 datastore.Datastore.GetObservations +$ grpcurl -d '{"standard_names": ["wind_speed", "air_temperature"], "temporal_interval": {"start": "2023-01-01T00:00:00Z", "end": "2023-01-01T00:00:10Z"}, "spatial_area": {"points": [{"lat": 59.90, "lon": 10.70}, {"lat": 59.90, "lon": 10.80}, {"lat": 60, "lon": 10.80}, {"lat": 60, "lon": 10.70}]}}' -plaintext -proto protobuf/datastore.proto 127.0.0.1:50050 datastore.Datastore.GetObservations ... ``` diff --git a/datastore/datastore/dsimpl/getobservations.go b/datastore/datastore/dsimpl/getobservations.go index 5aea6fae..824801e4 100644 --- a/datastore/datastore/dsimpl/getobservations.go +++ b/datastore/datastore/dsimpl/getobservations.go @@ -12,7 +12,7 @@ func (svcInfo *ServiceInfo) GetObservations( *datastore.GetObsResponse, error) { // do general validation of any obs time interval - if ti := request.Interval; ti != nil { + if ti := request.TemporalInterval; ti != nil { if ti.Start != nil && ti.End != nil { if ti.End.AsTime().Before(ti.Start.AsTime()) { return nil, fmt.Errorf("end(%v) < start(%v)", ti.End, ti.Start) diff --git a/datastore/datastore/storagebackend/postgresql/getobservations.go b/datastore/datastore/storagebackend/postgresql/getobservations.go index 2e01a494..5bb063f3 100644 --- a/datastore/datastore/storagebackend/postgresql/getobservations.go +++ b/datastore/datastore/storagebackend/postgresql/getobservations.go @@ -225,7 +225,7 @@ func getObs(db *sql.DB, request *datastore.GetObsRequest, obs *[]*datastore.Meta phVals := []interface{}{} // placeholder values - timeExpr := getTimeFilter(request.GetInterval()) + timeExpr := getTimeFilter(request.GetTemporalInterval()) tsMdataExpr := getMdataFilter([]filterInfo{ {"platform", request.GetPlatforms()}, @@ -239,7 +239,7 @@ func getObs(db *sql.DB, request *datastore.GetObsRequest, obs *[]*datastore.Meta // TODO: add search filters for more columns in table 'observation' }, &phVals) - geoExpr, err := getGeoFilter(request.Inside, &phVals) + geoExpr, err := getGeoFilter(request.GetSpatialArea(), &phVals) if err != nil { return fmt.Errorf("getGeoFilter() failed: %v", err) } diff --git a/datastore/datastore/storagebackend/postgresql/putobservations.go b/datastore/datastore/storagebackend/postgresql/putobservations.go index 183ac795..5d209da4 100644 --- a/datastore/datastore/storagebackend/postgresql/putobservations.go +++ b/datastore/datastore/storagebackend/postgresql/putobservations.go @@ -192,7 +192,7 @@ func getObsTime(obsMdata *datastore.ObsMetadata) (*timestamppb.Timestamp, error) return nil, fmt.Errorf("obsMdata.GetObstimeInstant()is nil") } -// --- BEGIN a variant of getObsTime that also supports intervals --------------------------------- +// --- BEGIN a variant of getObsTime that also supports temporal intervals ------------------------ // getObsTime extracts the obs time from obsMdata as either an instant time or the end of // an interval. // Returns (obs time, nil) upon success, otherwise (..., error). @@ -201,13 +201,14 @@ func getObsTime(obsMdata *datastore.ObsMetadata) (*timestamppb.Timestamp, error) if obsTime := obsMdata.GetInstant(); obsTime != nil { return obsTime, nil } - if obsTime := obsMdata.GetInterval().GetEnd(); obsTime != nil { + if obsTime := obsMdata.GetTemporalInterval().GetEnd(); obsTime != nil { return obsTime, nil } - return nil, fmt.Errorf("obsMdata.GetInstant() and obsMdata.GetInterval().GetEnd() are both nil") + return nil, fmt.Errorf( + "obsMdata.GetInstant() and obsMdata.GetTemporalInterval().GetEnd() are both nil") } */ -// --- END a variant of getObsTime that also supports intervals --------------------------------- +// --- END a variant of getObsTime that also supports temporal intervals -------------------------- // getGeoPointID retrieves the ID of the row in table geo_point that matches point, // inserting a new row if necessary. The ID is first looked up in a cache in order to save diff --git a/datastore/examples/clients/python/client.py b/datastore/examples/clients/python/client.py index 427cf6c1..0e718ac5 100755 --- a/datastore/examples/clients/python/client.py +++ b/datastore/examples/clients/python/client.py @@ -58,7 +58,7 @@ def call_put_obs(stub, version, type, standard_name, unit, value): # obs time range. def call_get_obs_in_time_range(stub): request = dstore.GetObsRequest( - interval=dstore.TimeInterval( + temporal_interval=dstore.TimeInterval( start=dtime2tstamp(datetime(2023, 1, 1, 0, 0, 0, 0, tzinfo=timezone.utc)), end=dtime2tstamp(datetime(2023, 1, 2, 0, 0, 0, 0, tzinfo=timezone.utc)), ) @@ -77,7 +77,7 @@ def call_get_obs_in_polygon(stub): points.append(dstore.Point(lat=60, lon=10.80)) points.append(dstore.Point(lat=60, lon=10.70)) - request = dstore.GetObsRequest(inside=dstore.Polygon(points=points)) + request = dstore.GetObsRequest(spatial_area=dstore.Polygon(points=points)) response = stub.GetObservations(request) return response diff --git a/datastore/integration-test/test_knmi.py b/datastore/integration-test/test_knmi.py index b7419d37..748e9412 100644 --- a/datastore/integration-test/test_knmi.py +++ b/datastore/integration-test/test_knmi.py @@ -59,7 +59,9 @@ def test_get_values_single_station_single_parameter_one_hour(grpc_stub): end_datetime.FromDatetime(datetime(2022, 12, 31, 12)) ts_request = dstore.GetObsRequest( - platforms=["06260"], instruments=["rh"], interval=dstore.TimeInterval(start=start_datetime, end=end_datetime) + platforms=["06260"], + instruments=["rh"], + temporal_interval=dstore.TimeInterval(start=start_datetime, end=end_datetime), ) response = grpc_stub.GetObservations(ts_request) @@ -147,7 +149,7 @@ def test_get_values_single_station_single_parameter_one_hour(grpc_stub): @pytest.mark.parametrize("coords,param_ids,expected_station_ids", input_params_polygon) def test_get_observations_with_polygon(grpc_stub, coords, param_ids, expected_station_ids): polygon = dstore.Polygon(points=[dstore.Point(lat=lat, lon=lon) for lat, lon in coords]) - get_obs_request = dstore.GetObsRequest(inside=polygon, instruments=param_ids) + get_obs_request = dstore.GetObsRequest(spatial_area=polygon, instruments=param_ids) get_obs_response = grpc_stub.GetObservations(get_obs_request) actual_station_ids = sorted({ts.ts_mdata.platform for ts in get_obs_response.observations}) diff --git a/datastore/load-test/locustfile_read.py b/datastore/load-test/locustfile_read.py index 81e966f8..ce3ec975 100644 --- a/datastore/load-test/locustfile_read.py +++ b/datastore/load-test/locustfile_read.py @@ -43,7 +43,7 @@ def get_data_for_single_timeserie(self): to_time.FromDatetime(datetime(2023, 1, 1)) request = dstore.GetObsRequest( - interval=dstore.TimeInterval(start=from_time, end=to_time), + temporal_interval=dstore.TimeInterval(start=from_time, end=to_time), platforms=[random.choice(stations)], instruments=[random.choice(parameters)], ) @@ -62,9 +62,11 @@ def get_data_single_station_through_bbox(self): poly = buffer(point, 0.0001, quad_segs=1) # Roughly 10 meters around the point request = dstore.GetObsRequest( - interval=dstore.TimeInterval(start=from_time, end=to_time), + temporal_interval=dstore.TimeInterval(start=from_time, end=to_time), instruments=[random.choice(parameters)], - inside=dstore.Polygon(points=[dstore.Point(lat=coord[1], lon=coord[0]) for coord in poly.exterior.coords]), + spatial_area=dstore.Polygon( + points=[dstore.Point(lat=coord[1], lon=coord[0]) for coord in poly.exterior.coords] + ), ) response = self.stub.GetObservations(request) assert len(response.observations) == 1 diff --git a/protobuf/datastore.proto b/protobuf/datastore.proto index 4fe56f08..b6feb9ea 100644 --- a/protobuf/datastore.proto +++ b/protobuf/datastore.proto @@ -140,8 +140,8 @@ message PutObsResponse { //--------------------------------------------------------------------------- message GetObsRequest { - TimeInterval interval = 1; // only return observations in this time range - Polygon inside = 2; // if specified, only return observations in this area + TimeInterval temporal_interval = 1; // only return observations in this time range + Polygon spatial_area = 2; // if specified, only return observations inside this area repeated string platforms = 3; // if specified, only return observations matching any of these platform patterns repeated string standard_names = 4 [json_name = "standard_names"]; // if specified, only return observations matching any of these standard names repeated string instruments = 5; // if specified, only return observations matching any of these instruments