Skip to content

Commit

Permalink
Feature/issue 100 Add option to 'compact' GeoJSON result into single …
Browse files Browse the repository at this point in the history
…feature (#177)

* Reorganize timeseries code to  prep for Accept header

* Enable Accept header to return response of specific content-type

* Fix whitespace and string continuation

* Make error handling consistent and add an additional test where a reach can't be found

* Update changelog with issue for unreleased version

* Add 415 status code to API definition

* Few minor cleanup items

* Few minor cleanup items

* Update to [email protected]

* Fix dependencies

* Update required query parameters based on current API functionality

* Enable return of 'compact' GeoJSON response

* Fix linting and add test data

* Update documentation for API accept headers and compact GeoJSON response

* Fix references to incorrect Accept header examples

---------

Co-authored-by: Frank Greguska <[email protected]>
  • Loading branch information
nikki-t and frankinspace authored May 14, 2024
1 parent e4bacfb commit 46f65f1
Show file tree
Hide file tree
Showing 6 changed files with 1,635 additions and 50 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- Issue 102 - Enable compression for API Responses
- Issue 100 - Add option to 'compact' GeoJSON result into single feature
- Issue 101 - Add support for HTTP Accept header
- Issue 102 - Enable compression for API Responses
### Deprecated
### Removed
### Fixed
Expand Down
315 changes: 313 additions & 2 deletions docs/timeseries.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,78 @@

Retrieve time series data from SWOT observations for reaches and nodes.

## Request Headers

### Accept

Accept headers: `application/json`, `text/csv`, `application/geo+json`

Possible header and request parameter combinations:

- If the Accept header is `text/csv` or `applicatin/geo+json`, the raw CSV or GeoJSON response is returned.
- If the Accept header is `application/json` with an output field of `geojson`, the entire JSON object with metadata including GeoJSON response is returned.
- If the Accept header is `application/json` with an output field of `csv`, the entire JSON object with metadata including CSV response is returned.
- If the Accept header is `application/json` without an output field, the entire JSON object with metadata including GeoJSON response is returned.
- If the Accept header is none of the accepted types then a 415 Unsupported is returned.

Example GeoJSON request and response:

```bash
curl -v --header "Accept: application/geo+json" --location 'https://soto.podaac.sit.earthdatacloud.nasa.gov/hydrocron/v1/timeseries?feature=Reach&feature_id=63470800171&start_time=2024-02-01T00:00:00%2b00:00&end_time=2024-10-30T00:00:00%2b00:00&fields=reach_id,time_str,wse'
```

Content-Type: 'application/geo+json'

```json
{
"type": "FeatureCollection",
"features": [
{
"id": "0",
"type": "Feature",
"properties": {
"reach_id": "63470800171",
"time_str": "2024-02-01T02:26:50Z",
"wse": "3386.9332",
"wse_units": "m"
},
"geometry": {
"type": "LineString",
"coordinates": []
}
},
{
"id": "1",
"type": "Feature",
"properties": {
"reach_id": "63470800171",
"time_str": "2024-02-08T13:48:41Z",
"wse": "1453.4136",
"wse_units": "m"
},
"geometry": {
"type": "LineString",
"coordinates": []
}
}
]
}
```

*Coordinates removed

Example CSV request and response:

```bash
curl -v --header "Accept: text/csv" --location 'https://soto.podaac.sit.earthdatacloud.nasa.gov/hydrocron/v1/timeseries?feature=Reach&feature_id=63470800171&start_time=2024-02-01T00:00:00%2b00:00&end_time=2024-10-30T00:00:00%2b00:00&fields=reach_id,time_str,wse'
```

Content-Type: text/csv

```json
"reach_id,time_str,wse,wse_units\n63470800171,2024-02-01T02:26:50Z,3386.9332,m\n63470800171,2024-02-08T13:48:41Z,1453.4136,m\n"
```

## Request Parameters

### feature : string, required: yes
Expand Down Expand Up @@ -41,10 +113,16 @@ Example:

`/timeseries?feature=Reach&feature_id=78340600051&output=geojson&start_time=2024-01-25T00:00:00%2b00:00&end_time=2024-03-29T00:00:00%2b00:00&fields=reach_id,time_str,wse,slope`

### output : string, required: yes
### output : string, required: no

Format of the data returned. Either: "csv" or "geojson"

### compact: string, required: no

Whether to return a 'compact' GeoJSON response. Either: "true" or "false"

The default for header `Accept: application/geo+json` is to set compact to `true` if it is not provided. The default header for `application/json` is to set compact to `false` if it is not provided. See "Response" section for details on the returned compact response.

### fields : string, required: yes

The SWOT data fields to return in the request.
Expand Down Expand Up @@ -143,7 +221,239 @@ Hydrocron includes additional fields beyond the source data shapefile attributes

## Returns

CSV or GEOJSON file containing the data for the selected feature and time period.
### Default

This includes cases where Accept header is not included or equals `*/*` or `application/json`.

Returns a JSON response that contains CSV or GeoJSON in `results` object with a Content-Type set to 'application/json'.

If the user sends a request parameter of `output=csv` then the `results` object will contain CSV data of the requested fields.

Example CSV response:

```json
{
"status": "200 OK",
"time": 806.886,
"hits": 4,
"results": {
"csv": "reach_id,time_str,wse,geometry,wse_units\n72390300011,2024-01-29T15:06:46Z,41.2087,\"LINESTRING (-62.159497 50.285927)\",m\n",
"geojson": {}
}
}
```

If the user sends a request parameter of `output=geojson` then the `results` object will contain GeoJSON data of the requested fields.

Example JSON response:

```json
{
"status": "200 OK",
"time": 723.004,
"hits": 2,
"results": {
"csv": "",
"geojson": {
"type": "FeatureCollection",
"features": [
{
"id": "0",
"type": "Feature",
"properties": {
"reach_id": "63470800171",
"time_str": "2024-02-01T02:26:50Z",
"wse": "3386.9332",
"wse_units": "m"
},
"geometry": {
"type": "LineString",
"coordinates": [
[
-45.845445,
-16.166559
]
]
}
},
{
"id": "1",
"type": "Feature",
"properties": {
"reach_id": "63470800171",
"time_str": "2024-02-08T13:48:41Z",
"wse": "1453.4136",
"wse_units": "m"
},
"geometry": {
"type": "LineString",
"coordinates": [
[
-45.845445,
-16.166559
]
]
}
}
]
}
}
}
```

If the user sends a request parameter of `compact=true` and the request parameter `output=geojson`, the response will be compacted. The compacted response appends time series data into a single list for each requested field and is stored under the `properties` object in the `results` object.

Only one Feature is ever returned as the data is aggregated under a single "Feature". The geometry for the data is included in the response's `geometry` object which is listed once as there is only one Feature represented in the response.

Example compacted JSON response:

```json
{
"status": "200 OK",
"time": 2175.824,
"hits": 2,
"results": {
"csv": "",
"geojson": {
"type": "FeatureCollection",
"features": [
{
"id": "0",
"type": "Feature",
"properties": {
"reach_id": [
"63470800171",
"63470800171"
],
"time_str": [
"2024-02-01T02:26:50Z",
"2024-02-08T13:48:41Z"
],
"wse": [
"3386.9332",
"1453.4136"
],
"wse_units": [
"m",
"m"
]
},
"geometry": {
"type": "LineString",
"coordinates": [
-45.845445,
-16.166559
]
}
}
]
}
}
}
```

*Coordinates removed

### application/geo+json

When the `Accept` header is set to `application/geo+json` and there is no `output` request parameter, a GeoJSON response is returned with a Content-Type set to 'application/geo+json'.

The default behavior is to compact the response into a single "Feature". The compacted response appends time series data into a single list for each requested field and includes a single geometry object for the data.

Example compacted GeoJSON response:

```json
{
"type": "FeatureCollection",
"features": [
{
"id": "0",
"type": "Feature",
"properties": {
"reach_id": [
"63470800171",
"63470800171"
],
"time_str": [
"2024-02-01T02:26:50Z",
"2024-02-08T13:48:41Z"
],
"wse": [
"3386.9332",
"1453.4136"
],
"wse_units": [
"m",
"m"
]
},
"geometry": {
"type": "LineString",
"coordinates": [
[
-45.845445,
-16.166559
]
]
}
}
]
}
```

*Coordinates removed

If the user sends a request parameter of `compact=false` then the GeoJSON response will not be compacted and there will be one "Feature" per time step.

Example GeoJSON response that is not compacted:

```json
{
"type": "FeatureCollection",
"features": [
{
"id": "0",
"type": "Feature",
"properties": {
"reach_id": "63470800171",
"time_str": "2024-02-01T02:26:50Z",
"wse": "3386.9332",
"wse_units": "m"
},
"geometry": {
"type": "LineString",
"coordinates": []
}
},
{
"id": "1",
"type": "Feature",
"properties": {
"reach_id": "63470800171",
"time_str": "2024-02-08T13:48:41Z",
"wse": "1453.4136",
"wse_units": "m"
},
"geometry": {
"type": "LineString",
"coordinates": []
}
}
]
}
```

*Coordinates removed

### text/csv

When the `Accept` header is set to `text/csv` and there is no `output` request parameter, a CSV response is returned with Content-Type set to 'text/csv'.

Example CSV response:

```bash
"reach_id,time_str,wse,wse_units\n63470800171,2024-02-01T02:26:50Z,3386.9332,m\n63470800171,2024-02-08T13:48:41Z,1453.4136,m\n"
```

## Response Codes

Expand All @@ -153,5 +463,6 @@ CSV or GEOJSON file containing the data for the selected feature and time period
| 400* | 'Bad Request': This indicates that the end user entered the parameters incorrectly in their query or time series data could not be located for the feature ID. The API attempts to send a response as to which parameter was incorrect. |
| 413 | 'Payload Too Large': The user attempted to retrieve a response that was too large. This is triggered for queries that exceed 6mb. |
| 500 | 'Internal Server Error': Internal API error. |
| 415 | 'Unsupported Media Type': The user send an invalid `Accept` header. |

*The 400 code is also currently returned for queries where no time series data could be located for the request specified feature ID. The message returned with the response indicates this and it can be helpful to adjust the date ranges you are searching.
Loading

0 comments on commit 46f65f1

Please sign in to comment.