How to Use the Statistics API¶
The /statistics endpoint can be used to get summary statistics for a geojson Feature or FeatureCollection.
This notebook demonstrates how to use the statistics API using the TROPESS Chemical Reanalysis O3 Monthly 3-dimensional Product dataset.
Setup¶
import json
import os
from datetime import datetime, timezone
import httpx
titiler_endpoint = os.getenv(
"TITILER_CMR_ENDPOINT", "https://openveda.cloud/api/titiler-cmr"
)
Specifiy a geojson dictionary to use in the request.
geojson_dict = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
[
[-20.79973248834736, 83.55979308678764],
[-20.79973248834736, 75.0115425216471],
[14.483337068956956, 75.0115425216471],
[14.483337068956956, 83.55979308678764],
[-20.79973248834736, 83.55979308678764],
]
],
"type": "Polygon",
},
}
],
}
TiTiler-CMR will use one or more sel parameter values to select specific subsets from a multidimensional data granule. The TROPESS dataset consists of monthly granules with daily arrays. To load the values from 2021-10-10 we provide that timestamp to the temporal parameter then provide sel=time=nearest::{datetime} to have TiTiler-CMR interpolate the value you provided to the temporal parameter. For fuzzy matching you can provide the nearest:: prefix to the value.
r = httpx.post(
f"{titiler_endpoint}/xarray/statistics",
params=(
("collection_concept_id", "C2837626477-GES_DISC"),
# Timestamp or temporal range for CMR granule query
("temporal", datetime(2021, 10, 10, tzinfo=timezone.utc).isoformat()),
# xarray backend query parameters
("variables", "o3"),
("sel", "time=nearest::{datetime}"), # gets interpolated
("sel", "lev=1000"),
),
json=geojson_dict,
timeout=None,
).json()
print(json.dumps(r, indent=2))
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-20.79973248834736,
83.55979308678764
],
[
-20.79973248834736,
75.0115425216471
],
[
14.483337068956956,
75.0115425216471
],
[
14.483337068956956,
83.55979308678764
],
[
-20.79973248834736,
83.55979308678764
]
]
]
},
"properties": {
"statistics": {
"b1": {
"min": 12.448402404785156,
"max": 30.638206481933594,
"mean": 25.00276756286621,
"count": 236.0,
"sum": 5900.6533203125,
"std": 3.4685499803764728,
"median": 25.134218215942383,
"majority": 12.448402404785156,
"minority": 12.448402404785156,
"unique": 236.0,
"histogram": [
[
2,
1,
0,
6,
33,
39,
37,
42,
32,
44
],
[
12.448402404785156,
14.267382621765137,
16.086362838745117,
17.905344009399414,
19.724323272705078,
21.543304443359375,
23.362285614013672,
25.18126678466797,
27.000246047973633,
28.81922721862793,
30.638206481933594
]
],
"valid_percent": 95.16,
"masked_pixels": 12.0,
"valid_pixels": 236.0,
"description": "0",
"percentile_2": 18.29606056213379,
"percentile_98": 30.242084503173828
}
},
"used_assets": [
"TRPSCRO3M3D.1:TROPESS_reanalysis_mon_o3_2021.nc"
]
}
}
]
}
You can chose a different time slice from the same granule simply by updating the datetime query parameter.
r = httpx.post(
f"{titiler_endpoint}/xarray/statistics",
params=(
("collection_concept_id", "C2837626477-GES_DISC"),
# Datetime for CMR granule query
("temporal", datetime(2021, 12, 10, tzinfo=timezone.utc).isoformat()),
# xarray backend query parameters
("variables", "o3"),
("sel", "time=nearest::{datetime}"), #
("sel", "lev=1000"),
),
json=geojson_dict,
timeout=None,
).json()
print(json.dumps(r, indent=2))
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-20.79973248834736,
83.55979308678764
],
[
-20.79973248834736,
75.0115425216471
],
[
14.483337068956956,
75.0115425216471
],
[
14.483337068956956,
83.55979308678764
],
[
-20.79973248834736,
83.55979308678764
]
]
]
},
"properties": {
"statistics": {
"b1": {
"min": 18.230709075927734,
"max": 37.22050476074219,
"mean": 27.433626174926758,
"count": 192.0,
"sum": 5267.25634765625,
"std": 4.652167252044063,
"median": 27.250431060791016,
"majority": 18.230709075927734,
"minority": 18.230709075927734,
"unique": 192.0,
"histogram": [
[
1,
23,
39,
21,
16,
16,
30,
26,
12,
8
],
[
18.230709075927734,
20.129688262939453,
22.028667449951172,
23.92764663696289,
25.826627731323242,
27.72560691833496,
29.62458610534668,
31.52356719970703,
33.42254638671875,
35.32152557373047,
37.22050476074219
]
],
"valid_percent": 77.42,
"masked_pixels": 56.0,
"valid_pixels": 192.0,
"description": "0",
"percentile_2": 20.44560432434082,
"percentile_98": 36.73855972290039
}
},
"used_assets": [
"TRPSCRO3M3D.1:TROPESS_reanalysis_mon_o3_2021.nc"
]
}
}
]
}