COSMOS-UK API - Example Python snippets for accessing data
This notebook aims to provide a basic introduction in how you might interact with the COSMOS-UK API programatically, for example to automate the process of bringing COSMOS-UK data into your workflows.
More information about COSMOS-UK can be found on our website: https://cosmos.ceh.ac.uk/.
A detailed general user guide for COSMOS-UK, including information about sensors, quality control checks and other information about how our data is collected, is available here: https://cosmos.ceh.ac.uk/resources/user_guide.
Imports and helper functions
Here, we are just importing the required Python modules and defining some static helper functions that will be used throughout the rest of the code.
[1]:
from datetime import datetime
import io
import json
import requests
import zipfile
import pandas as pd
[2]:
BASE_URL = 'https://cosmos-api.ceh.ac.uk'
[3]:
def get_api_response(url, csv=False):
""" Helper function to send request to API and get the response
:param str url: The URL of the API request
:param bool csv: Whether this is a CSV request. Default False.
:return: API response
"""
# Send request and read response
print(url)
response = requests.get(url)
if csv:
return response
else:
# Decode from JSON to Python dictionary
return json.loads(response.content)
Data collections
The COSMOS-UK API can provide data for sites at two time steps, known as ‘collections’:
30 minutes (30M)
Daily (1D)
Each collection has their own set of variables (known as ‘parameters’) that data is available for. You can find these parameters by interrogating the collection metadata with a call to the root collection URL. The parameter listing contains various information about each parameter that may be useful.
[4]:
def get_collection_parameter_info(params):
""" A function for wrangling the collection information into a more visually appealing format!
"""
df = pd.DataFrame.from_dict(params)
df = df.T[['label', 'description', 'unit', 'sensorInfo']]
df['unit_symbol'] = df['unit'].apply(lambda x: x['symbol']['value'])
df['unit_label'] = df['unit'].apply(lambda x: x['label'])
df['sensor_depth'] = df['sensorInfo'].apply(lambda x: None if pd.isna(x) else x['sensor_depth']['value'])
df = df.drop(['sensorInfo', 'unit'], axis=1)
return df
30 minute (30M) parameters
[5]:
collection_30M_url = f'{BASE_URL}/collections/30M'
collection_30M_meta = get_api_response(collection_30M_url)
# Get the information about the parameter names from the metadata dictionary
collection_30M_params = collection_30M_meta['parameter_names']
collection_30M_params_df = get_collection_parameter_info(collection_30M_params)
display(collection_30M_params_df)
https://cosmos-api.ceh.ac.uk/collections/30M
label | description | unit_symbol | unit_label | sensor_depth | |
---|---|---|---|---|---|
g1 | Soil Heat Flux 1 | 30 minute soil heat flux from heat flux plate 1 | W m-2 | watts per square metre | None |
g2 | Soil Heat Flux 2 | 30 minute soil heat flux from heat flux plate 2 | W m-2 | watts per square metre | None |
lwin | Longwave Radiation - Incoming | 30 minute incoming longwave radiation | W m-2 | watts per square metre | None |
lwout | Longwave Radiation - Outgoing | 30 minute outgoing longwave radiation | W m-2 | watts per square metre | None |
pa | Atmospheric Pressure | 30 minute atmospheric pressure | hPa | hectopascal | None |
precip | Precipitation (Pluvio) | 30 minute precipitation from pluvio gauge | mm | millimetre | None |
precip_raine | Precipitation (rainE) | 30 minute precipitation from rainE gauge | mm | millimetre | None |
precip_tipping | Precipitation (Tipping Bucket) | 30 minute precipitation from tipping bucket gauge | mm | millimetre | None |
q | Absolute Humidity | 30 minute absolute humidity | g m-3 | gram per cubic metre | None |
rh | Relative Humidity | 30 minute relative humidity | % | percent | None |
rn | Net Radiation | 30 minute net radiation | W m-2 | watts per square metre | None |
snow_depth | Snow Depth | 30 minute snow depth (Only given on snow days) | mm | millimetre | None |
stp_tsoil10 | STP 03 Soil Temperature at 10cm | 30 minute soil temperature at 10cm. STP sensor | °C | degrees Celsius | 10 |
stp_tsoil2 | STP 01 Soil Temperature at 2cm | 30 minute soil temperature at 2cm. STP sensor | °C | degrees Celsius | 2 |
stp_tsoil20 | STP 04 Soil Temperature at 20cm | 30 minute soil temperature at 20cm. STP sensor | °C | degrees Celsius | 20 |
stp_tsoil5 | STP 02 Soil Temperature at 5cm | 30 minute soil temperature at 5cm. STP sensor | °C | degrees Celsius | 5 |
stp_tsoil50 | STP 05 Soil Temperature at 50cm | 30 minute soil temperature at 50cm. STP sensor | °C | degrees Celsius | 50 |
swin | Shortwave Radiation - Incoming | 30 minute incoming shortwave radiation | W m-2 | watts per square metre | None |
swout | Shortwave Radiation - Outgoing | 30 minute outgoing shortwave radiation | W m-2 | watts per square metre | None |
ta | Air Temperature | 30 minute air temperature | °C | degrees Celsius | None |
tdt10_tsoil | TDT 10 - Soil Temperature at 50cm | 30 minute soil temperature at 50cm*. TDT senso... | °C | degrees Celsius | 50 |
tdt10_vwc | TDT 10 - Volumetric Water Content at 50cm | 30 minute volumetric water content at 50cm*. T... | % | percent | 50 |
tdt1_tsoil | TDT 01 - Soil Temperature at 10cm | 30 minute soil temperature at 10cm. TDT sensor 1 | °C | degrees Celsius | 10 |
tdt1_vwc | TDT 01 - Volumetric Water Content at 10cm | 30 minute volumetric water content at 10cm. TD... | % | percent | 10 |
tdt2_tsoil | TDT 02 - Soil Temperature at 10cm | 30 minute soil temperature at 10cm. TDT sensor 2 | °C | degrees Celsius | 10 |
tdt2_vwc | TDT 02 - Volumetric Water Content at 10cm | 30 minute volumetric water content at 10cm. TD... | % | percent | 10 |
tdt3_tsoil | TDT 03 - Soil Temperature at 5cm | 30 minute soil temperature at 5cm. TDT sensor 3 | °C | degrees Celsius | 5 |
tdt3_vwc | TDT 03 - Volumetric Water Content at 5cm | 30 minute volumetric water content at 5cm. TDT... | % | percent | 5 |
tdt4_tsoil | TDT 04 - Soil Temperature at 5cm | 30 minute soil temperature at 5cm. TDT sensor 4 | °C | degrees Celsius | 5 |
tdt4_vwc | TDT 04 - Volumetric Water Content at 5cm | 30 minute volumetric water content at 5cm. TDT... | % | percent | 5 |
tdt5_tsoil | TDT 05 - Soil Temperature at 15cm | 30 minute soil temperature at 15cm. TDT sensor 5 | °C | degrees Celsius | 15 |
tdt5_vwc | TDT 05 - Volumetric Water Content at 15cm | 30 minute volumetric water content at 15cm. TD... | % | percent | 15 |
tdt6_tsoil | TDT 06 - Soil Temperature at 15cm | 30 minute soil temperature at 15cm. TDT sensor 6 | °C | degrees Celsius | 15 |
tdt6_vwc | TDT 06 - Volumetric Water Content at 15cm | 30 minute volumetric water content at 15cm. TD... | % | percent | 15 |
tdt7_tsoil | TDT 07 - Soil Temperature at 25cm | 30 minute soil temperature at 25cm. TDT sensor 7 | °C | degrees Celsius | 25 |
tdt7_vwc | TDT 07 - Volumetric Water Content at 25cm | 30 minute volumetric water content at 25cm. TD... | % | percent | 25 |
tdt8_tsoil | TDT 08 - Soil Temperature at 25cm | 30 minute soil temperature at 25cm. TDT sensor 8 | °C | degrees Celsius | 25 |
tdt8_vwc | TDT 08 - Volumetric Water Content at 25cm | 30 minute volumetric water content at 25cm. TD... | % | percent | 25 |
tdt9_tsoil | TDT 09 - Soil Temperature at 50cm | 30 minute soil temperature at 50cm*. TDT senso... | °C | degrees Celsius | 50 |
tdt9_vwc | TDT 09 - Volumetric Water Content at 50cm | 30 minute volumetric water content at 50cm*. T... | % | percent | 50 |
ux | Wind Speed - X Component | 30 minute x component of wind speed | m/s | metres per second | None |
uy | Wind Speed - Y Component | 30 minute y component of wind speed | m/s | metres per second | None |
uz | Wind Speed - Z Component | 30 minute z component of wind speed | m/s | metres per second | None |
wd | Wind Direction | 30 minute wind direction | ° | degree (angle) | None |
ws | Wind Speed | 30 minute wind speed | m/s | metres per second | None |
Daily (1D) parameters
[6]:
collection_1D_url = f'{BASE_URL}/collections/1D'
collection_1D_meta = get_api_response(collection_1D_url)
# Get the information about the parameter names from the metadata dictionary
collection_1D_params = collection_1D_meta['parameter_names']
collection_1D_params_df = get_collection_parameter_info(collection_1D_params)
display(collection_1D_params_df)
https://cosmos-api.ceh.ac.uk/collections/1D
label | description | unit_symbol | unit_label | sensor_depth | |
---|---|---|---|---|---|
albedo | Albedo | Mean albedo value between 10:00 and 14:00 | 1 | dimensionless | None |
cosmos_vwc | COSMOS Volumetric Water Content | Daily volumetric water content (soil moisture)... | % | percent | None |
cts_mod_corr | COSMOS Neutron Counts (corrected) | Daily corrected counts from CRNS tube | count | count | None |
d86_75m | D86 75M | Daily effective depth of COSMOS VWC measuremen... | cm | centimetre | None |
g1 | Soil Heat Flux 1 | Daily soil heat flux from heat flux plate 1 | W m-2 | watts per square metre | None |
g2 | Soil Heat Flux 2 | Daily soil heat flux from heat flux plate 2 | W m-2 | watts per square metre | None |
lwin | Longwave Radiation - Incoming | Daily incoming longwave radiation | MJ m-2 day-1 | megajoule per square metre per day | None |
lwout | Longwave Radiation - Outgoing | Daily outgoing longwave radiation | MJ m-2 day-1 | megajoule per square metre per day | None |
pa | Atmospheric Pressure | Daily atmospheric pressure | hPa | hectopascal | None |
pe | Potential Evaporation | Daily potential evaporation | mm | millimetre | None |
precip | Precipitation (Pluvio) | Daily precipitation from pluvio gauge | mm | millimetre | None |
precip_raine | Precipitation (rainE) | Daily precipitation from rainE gauge | mm | millimetre | None |
precip_tipping | Precipitation (Tipping Bucket) | Daily precipitation from tipping bucket gauge | mm | millimetre | None |
q | Absolute Humidity | Daily absolute humidity | g m-3 | gram per cubic metre | None |
rh | Relative Humidity | Daily relative humidity | % | percent | None |
rn | Net Radiation | Daily net radiation | MJ m-2 day-1 | megajoule per square metre per day | None |
snow | Snow | Whether or not snow occurred (Daily) | 1 | dimensionless | None |
snow_depth | Snow Depth | Daily snow depth (Only given on snow days) | mm | millimetre | None |
stp_tsoil10 | STP 03 Soil Temperature at 10cm | Daily soil temperature at 10cm. STP sensor | °C | degrees Celsius | 10 |
stp_tsoil2 | STP 01 Soil Temperature at 2cm | Daily soil temperature at 2cm. STP sensor | °C | degrees Celsius | 2 |
stp_tsoil20 | STP 04 Soil Temperature at 20cm | Daily soil temperature at 20cm. STP sensor | °C | degrees Celsius | 20 |
stp_tsoil5 | STP 02 Soil Temperature at 5cm | Daily soil temperature at 5cm. STP sensor | °C | degrees Celsius | 5 |
stp_tsoil50 | STP 05 Soil Temperature at 50cm | Daily soil temperature at 50cm. STP sensor | °C | degrees Celsius | 50 |
swe_crns | Snow Water Equivalent | Daily snow water equivalent (only given on sno... | mm | millimetre | None |
swin | Shortwave Radiation - Incoming | Daily incoming shortwave radiation | MJ m-2 day-1 | megajoule per square metre per day | None |
swout | Shortwave Radiation - Outgoing | Daily outgoing shortwave radiation | MJ m-2 day-1 | megajoule per square metre per day | None |
ta | Air Temperature | Daily air temperature | °C | degrees Celsius | None |
ta_max | Air Temperature - Maximum | Daily maximum air temperature | °C | degrees Celsius | None |
ta_min | Air Temperature - Minimum | Daily minimum air temperature | °C | degrees Celsius | None |
tdt10_tsoil | TDT 10 - Soil Temperature at 50cm | Daily soil temperature at 50cm*. TDT sensor 10... | °C | degrees Celsius | 50 |
tdt10_vwc | TDT 10 - Volumetric Water Content at 50cm | Daily volumetric water content at 50cm*. TDT s... | % | percent | 50 |
tdt1_tsoil | TDT 01 - Soil Temperature at 10cm | Daily soil temperature at 10cm. TDT sensor 1 | °C | degrees Celsius | 10 |
tdt1_vwc | TDT 01 - Volumetric Water Content at 10cm | Daily volumetric water content at 10cm. TDT se... | % | percent | 10 |
tdt2_tsoil | TDT 02 - Soil Temperature at 10cm | Daily soil temperature at 10cm. TDT sensor 2 | °C | degrees Celsius | 10 |
tdt2_vwc | TDT 02 - Volumetric Water Content at 10cm | Daily volumetric water content at 10cm. TDT se... | % | percent | 10 |
tdt3_tsoil | TDT 03 - Soil Temperature at 5cm | Daily soil temperature at 5cm. TDT sensor 3 | °C | degrees Celsius | 5 |
tdt3_vwc | TDT 03 - Volumetric Water Content at 5cm | Daily volumetric water content at 5cm. TDT sen... | % | percent | 5 |
tdt4_tsoil | TDT 04 - Soil Temperature at 5cm | Daily soil temperature at 5cm. TDT sensor 4 | °C | degrees Celsius | 5 |
tdt4_vwc | TDT 04 - Volumetric Water Content at 5cm | Daily volumetric water content at 5cm. TDT sen... | % | percent | 5 |
tdt5_tsoil | TDT 05 - Soil Temperature at 15cm | Daily soil temperature at 15cm. TDT sensor 5 | °C | degrees Celsius | 15 |
tdt5_vwc | TDT 05 - Volumetric Water Content at 15cm | Daily volumetric water content at 15cm. TDT se... | % | percent | 15 |
tdt6_tsoil | TDT 06 - Soil Temperature at 15cm | Daily soil temperature at 15cm. TDT sensor 6 | °C | degrees Celsius | 15 |
tdt6_vwc | TDT 06 - Volumetric Water Content at 15cm | Daily volumetric water content at 15cm. TDT se... | % | percent | 15 |
tdt7_tsoil | TDT 07 - Soil Temperature at 25cm | Daily soil temperature at 25cm. TDT sensor 7 | °C | degrees Celsius | 25 |
tdt7_vwc | TDT 07 - Volumetric Water Content at 25cm | Daily volumetric water content at 25cm. TDT se... | % | percent | 25 |
tdt8_tsoil | TDT 08 - Soil Temperature at 25cm | Daily soil temperature at 25cm. TDT sensor 8 | °C | degrees Celsius | 25 |
tdt8_vwc | TDT 08 - Volumetric Water Content at 25cm | Daily volumetric water content at 25cm. TDT se... | % | percent | 25 |
tdt9_tsoil | TDT 09 - Soil Temperature at 50cm | Daily soil temperature at 50cm*. TDT sensor 9 ... | °C | degrees Celsius | 50 |
tdt9_vwc | TDT 09 - Volumetric Water Content at 50cm | Daily volumetric water content at 50cm*. TDT s... | % | percent | 50 |
wd | Wind Direction | Daily wind direction | ° | degree (angle) | None |
ws | Wind Speed | Daily wind speed | m/s | metres per second | None |
Data flags parameters
Alongside each data parameter (as listed above), there is a corresponding ‘flag’ parameter. The flag parameters mirror the structure of their data parameter data part, and hold information about the data value itself. There are currently three values that the flag parameters can be:
M
: Missing - Where data has been lost and not infilled.
I
: Infilled - Where missing data has been filled in directly using an infill method. The only infilling method currently in use is interpolation, used for gaps smaller than 10 values. More information is available in the supporting documentation of the EIDC data holding.
E
: Estimated - Where the value contains some degree of uncertainty. This can be for one of two reasons:
The value was aggregated with less than a full set of data. For example, a daily mean temperature where some of the sub daily values were missing.
The value was aggregated or derived with some degree of infilled data. For example, if net radiation was calculated using an infilled short wave radiation value.
A null value in the flag parameter indicates a ‘normal’ data value.
Note: The default is not to return the flag parameters alongside the data parameters in order to reduce the size of the request. You can use the query parameter flags=true
to include the flag parameters. See below for examples.
Site list
Both the 30M and 1D data collections contain data for the same set of COSMOS-UK sites. You can get information about the sites from calling to the /locations
endpoint of each collection (shown below for the 1D collection).
Note: ‘End date’ in the table below is the last available date there is data available for each site. For currently open sites, this will be the date this notebook was created. For closed sites, this will be the date the site was closed.
[7]:
site_info_url = f'{BASE_URL}/collections/1D/locations'
site_info_response = get_api_response(site_info_url)
site_info = {}
for site in site_info_response['features']:
site_id = site['id']
site_name = site['properties']['label']
coordinates = site['geometry']['coordinates']
date_range = site['properties']['datetime']
start_date, end_date = date_range.split('/')
other_info = site['properties']['siteInfo']
other_info = {key: d['value'] for key, d in other_info.items()}
site_info[site_id] = {'site_name': site_name,
'coordinates': coordinates,
'start_date': start_date,
'end_date': end_date} | other_info
site_info_df = pd.DataFrame.from_dict(site_info).T
display(site_info_df)
https://cosmos-api.ceh.ac.uk/collections/1D/locations
site_name | coordinates | start_date | end_date | altitude | bulk_density | bulk_density_sd | land_cover | lattice_water | lattice_water_sd | soil_organic_carbon | soil_organic_carbon_sd | soil_type | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ALIC1 | Alice Holt | [51.153551, -0.858232] | 2015-03-06T13:30:00Z | 2023-08-07T00:00:00Z | 80.0 | 0.84 | None | Broadleaf woodland | 0.025 | None | 0.042 | None | Mineral soil |
BALRD | Balruddery | [56.482297, -3.1114881] | 2014-05-15T17:30:00Z | 2023-08-07T00:00:00Z | 130.0 | 1.35 | 0.14 | Arable and horticulture | 0.018 | 0.00066 | 0.023 | 0.00076 | Mineral soil |
BICKL | Bickley Hall | [53.02635, -2.7005297] | 2015-01-28T17:00:00Z | 2023-08-07T00:00:00Z | 78.0 | 1.25 | 0.23 | Grassland | 0.01 | 0.00042 | 0.02 | 0.0036 | Mineral soil |
BUNNY | Bunny Park | [52.86073, -1.12685] | 2015-01-27T00:30:00Z | 2023-08-07T00:00:00Z | 39.0 | 1.53 | 0.11 | Arable and horticulture | 0.008 | 0.0012 | 0.016 | 0.0015 | Mineral soil |
CARDT | Cardington | [52.105601, -0.424644] | 2015-06-24T10:00:00Z | 2023-08-07T00:00:00Z | 29.0 | 1.1 | 0.17 | Improved grassland | 0.016 | 0.0018 | 0.04 | 0.0052 | Mineral soil |
CGARW | Cwm Garw | [51.951295, -4.746634] | 2016-06-29T11:00:00Z | 2023-08-07T00:00:00Z | 299.0 | 0.79 | 0.26 | Improved grassland | 0.022 | 0.00086 | 0.048 | 0.0015 | Mineral soil |
CHIMN | Chimney Meadows | [51.708021, -1.4787658] | 2013-10-02T13:30:00Z | 2023-08-07T00:00:00Z | 65.0 | 1.32 | 0.095 | Improved grassland | 0.011 | 0.0018 | 0.027 | 0.0016 | Calcareous mineral soil |
CHOBH | Chobham Common | [51.367821, -0.597484] | 2015-02-24T14:00:00Z | 2023-08-07T00:00:00Z | 47.0 | 0.73 | 0.37 | Heather grassland | 0.003 | 0.0011 | 0.031 | 0.0084 | Organic soil over mineral soil |
COCHN | Cochno | [55.941421, -4.4035431] | 2017-08-23T00:00:00Z | 2020-11-16T00:00:00Z | 168.0 | 0.76 | 0.21 | Improved grassland | 0.019 | 0.0018 | 0.068 | 0.014 | Mineral soil |
COCLP | Cockle Park | [55.216013, -1.6943736] | 2014-11-21T14:30:00Z | 2023-08-07T00:00:00Z | 87.0 | 1.18 | 0.084 | Arable and horticulture | 0.02 | 0.0015 | 0.033 | 0.0018 | Mineral soil |
CRICH | Crichton | [55.043057, -3.583386] | 2014-12-02T15:00:00Z | 2023-08-07T00:00:00Z | 42.0 | 1.1 | 0.15 | Arable and horticulture | 0.011 | 0.0012 | 0.045 | 0.0068 | Mineral soil |
EASTB | Easter Bush | [55.867392, -3.207115] | 2014-08-13T11:30:00Z | 2023-08-07T00:00:00Z | 208.0 | 1.07 | 0.19 | Improved grassland | 0.019 | 0.0015 | 0.033 | 0.0035 | Mineral soil |
ELMST | Elmsett | [52.094647, 0.9930645] | 2016-08-11T15:30:00Z | 2023-08-07T00:00:00Z | 76.0 | 1.2 | 0.18 | Arable and horticulture | 0.015 | 0.00096 | 0.022 | 0.0041 | Calcareous mineral soil |
EUSTN | Euston | [52.383178, 0.7847112] | 2016-03-31T16:00:00Z | 2023-08-07T00:00:00Z | 18.0 | 1.18 | 0.2 | Improved grassland | 0.003 | 0.00026 | 0.029 | 0.0023 | Mineral soil |
FINCH | Fincham | [52.617773, 0.5107284] | 2017-06-07T11:30:00Z | 2023-08-07T00:00:00Z | 15.0 | 1.26 | 0.13 | Arable and horticulture | 0.007 | 0.00055 | 0.02 | 0.0011 | Calcareous mineral soil |
FIVET | Fivemiletown | [54.298468, -7.291954] | 2018-06-26T15:30:00Z | 2023-08-07T00:00:00Z | 174.0 | 0.86 | 0.24 | Arable and horticulture | 0.014 | 0.0019 | 0.039 | 0.0095 | Mineral soil |
GISBN | Gisburn Forest | [54.023711, -2.384689] | 2014-08-15T12:00:00Z | 2023-08-07T00:00:00Z | 246.0 | 0.71 | 0.29 | Coniferous woodland | 0.021 | 0.0037 | 0.061 | 0.0035 | Mineral soil |
GLENS | Glensaugh | [56.914403, -2.5621547] | 2014-05-14T11:30:00Z | 2023-08-07T00:00:00Z | 399.0 | 0.36 | 0.33 | Heather | 0.014 | 0.0034 | 0.203 | 0.059 | Organic soil |
GLENW | Glenwherry | [54.838087, -6.0045994] | 2016-06-15T15:00:00Z | 2023-08-07T00:00:00Z | 274.0 | 0.58 | 0.24 | Improved grassland | 0.024 | 0.0019 | 0.153 | 0.011 | Organic soil |
HADLW | Hadlow | [51.228582, 0.320276] | 2016-10-27T14:30:00Z | 2023-08-07T00:00:00Z | 33.0 | 1.1 | 0.15 | Improved grassland | 0.028 | 0.0019 | 0.031 | 0.0014 | Mineral soil |
HARTW | Hartwood Home | [55.810254, -3.828995] | 2014-05-20T13:30:00Z | 2023-08-07T00:00:00Z | 225.0 | 1.02 | 0.15 | Improved grassland | 0.033 | 0.0066 | 0.043 | 0.0037 | Mineral soil |
HARWD | Harwood Forest | [55.216677, -2.025488] | 2015-05-22T12:00:00Z | 2022-06-28T09:00:00Z | 300.0 | 0.35 | 0.23 | Coniferous forest | 0.009 | 0.0034 | 0.304 | 0.1 | Organic soil |
HENFS | Henfaes Farm | [53.225198, -4.01255] | 2015-12-17T13:00:00Z | 2023-08-07T00:00:00Z | 287.0 | 0.86 | 0.26 | Acid grassland | 0.022 | 0.001 | 0.077 | 0.0041 | Mineral soil |
HILLB | Hillsborough | [54.446959, -6.068526] | 2016-06-14T17:00:00Z | 2023-08-07T00:00:00Z | 146.0 | 1.11 | 0.18 | Improved grassland | 0.021 | 0.0042 | 0.042 | 0.0052 | Mineral soil |
HLACY | Holme Lacy | [52.02088, -2.6621054] | 2018-04-11T00:00:00Z | 2023-08-07T00:00:00Z | 76.0 | 1.27 | 0.16 | Arable and horticulture | 0.017 | 0.00084 | 0.022 | 0.0013 | Mineral soil |
HOLLN | Hollin Hill | [54.110665, -0.959477] | 2014-03-25T12:30:00Z | 2023-08-07T00:00:00Z | 82.0 | 0.96 | 0.18 | Improved grassland | 0.025 | 0.0034 | 0.032 | 0.012 | Mineral soil |
HYBRY | Heytesbury | [51.20277, -2.079616] | 2017-08-16T12:30:00Z | 2023-08-07T00:00:00Z | 166.0 | 0.78 | 0.27 | Calcareous grassland | 0.006 | 0.0021 | 0.066 | 0.011 | Calcareous mineral soil |
LIZRD | The Lizard | [50.03266, -5.19999] | 2014-10-17T12:00:00Z | 2023-08-07T00:00:00Z | 85.0 | 0.78 | 0.3 | Grassland | 0.014 | 0.0023 | 0.058 | 0.027 | Mineral soil |
LODTN | Loddington | [52.610159, -0.8264188] | 2016-04-26T15:00:00Z | 2023-08-07T00:00:00Z | 186.0 | 1.07 | 0.1 | Arable and horticulture | 0.041 | 0.0023 | 0.036 | 0.0023 | Mineral soil |
LULLN | Lullington Heath | [50.79372, 0.18887] | 2014-12-16T15:30:00Z | 2023-08-07T00:00:00Z | 119.0 | 0.8 | 0.22 | Calcareous grassland | 0.006 | 0.0017 | 0.043 | 0.011 | Calcareous mineral soil |
MOORH | Moor House | [54.659417, -2.4678] | 2014-12-04T11:30:00Z | 2023-08-07T00:00:00Z | 565.0 | 0.61 | 0.38 | Acid grassland | 0.014 | 0.0025 | 0.076 | 0.029 | Mineral soil |
MOREM | Moreton Morrell | [52.199407, -1.563081] | 2018-11-15T00:00:00Z | 2023-08-07T00:00:00Z | 53.0 | 1.09 | 0.23 | Improved grassland | 0.026 | 0.0038 | 0.035 | 0.0053 | Mineral soil |
MORLY | Morley | [52.548146, 1.0342313] | 2014-05-14T05:00:00Z | 2023-08-07T00:00:00Z | 55.0 | 1.48 | 0.2 | Arable and horticulture | 0.016 | 0.002 | 0.017 | 0.0038 | Mineral soil |
NWYKE | North Wyke | [50.773479, -3.905963] | 2014-10-16T09:00:00Z | 2023-08-07T00:00:00Z | 181.0 | 1.16 | 0.15 | Arable and horticulture | 0.02 | 0.0014 | 0.037 | 0.0021 | Mineral soil |
PLYNL | Plynlimon | [52.453337, -3.762572] | 2014-11-05T12:30:00Z | 2023-08-07T00:00:00Z | 542.0 | 0.61 | 0.33 | Acid grassland | 0.02 | 0.0015 | 0.098 | 0.0097 | Organic soil |
PORTN | Porton Down | [51.120071, -1.681482] | 2014-12-18T10:30:00Z | 2023-08-07T00:00:00Z | 146.0 | 0.91 | 0.14 | Improved grassland | 0.004 | 0.0011 | 0.049 | 0.0059 | Calcareous mineral soil |
RDMER | Redmere | [52.44577, 0.42104] | 2015-02-10T10:30:00Z | 2018-09-20T00:00:00Z | 3.0 | 0.59 | 0.097 | Arable and horticulture | 0.056 | 0.0059 | 0.238 | 0.053 | Organic soil |
REDHL | Redhill | [51.26287, 0.4291348] | 2016-02-18T16:00:00Z | 2023-08-07T00:00:00Z | 91.0 | 1.23 | 0.15 | Orchard | 0.011 | 0.00076 | 0.024 | 0.0026 | Calcareous mineral soil |
RISEH | Riseholme | [53.261647, -0.5259074] | 2016-05-04T16:00:00Z | 2023-08-07T00:00:00Z | 53.0 | 1.15 | 0.18 | Improved grassland | 0.022 | 0.0051 | 0.032 | 0.0043 | Calcareous mineral soil |
ROTHD | Rothamsted | [51.813787, -0.378304] | 2014-07-25T08:00:00Z | 2023-08-07T00:00:00Z | 131.0 | 1.32 | 0.15 | Arable and horticulture | 0.018 | 0.0011 | 0.021 | 0.0036 | Mineral soil |
SHEEP | Sheepdrove | [51.530244, -1.481903] | 2013-10-24T14:30:00Z | 2023-08-07T00:00:00Z | 170.0 | 1.03 | 0.14 | Arable and horticulture | 0.027 | 0.006 | 0.059 | 0.0086 | Mineral soil |
SOURH | Sourhope | [55.479876, -2.229989] | 2014-11-19T11:00:00Z | 2023-08-07T00:00:00Z | 487.0 | 0.55 | 0.29 | Acid grassland | 0.021 | 0.0034 | 0.086 | 0.041 | Mineral soil |
SPENF | Spen Farm | [53.86886, -1.31886] | 2016-11-23T10:00:00Z | 2023-08-07T00:00:00Z | 57.0 | 1.49 | 0.19 | Arable and horticulture | 0.011 | 0.0013 | 0.019 | 0.002 | Calcareous mineral soil |
STGHT | Stoughton | [52.601667, -1.047046] | 2015-08-19T06:30:00Z | 2023-08-07T00:00:00Z | 130.0 | 1.35 | 0.14 | Arable and horticulture | 0.018 | 0.0028 | 0.027 | 0.0071 | Mineral soil |
STIPS | Stiperstones | [52.581248, -2.9446865] | 2014-11-06T15:00:00Z | 2023-08-07T00:00:00Z | 432.0 | 0.52 | 0.25 | Improved grassland | 0.016 | 0.004 | 0.104 | 0.036 | Organic soil |
SYDLG | Sydling | [50.828373, -2.527891] | 2018-11-27T00:00:00Z | 2023-08-07T00:00:00Z | 249.0 | 1.05 | 0.19 | Improved grassland | 0.02 | 0.0015 | 0.035 | 0.0029 | Mineral soil |
TADHM | Tadham Moor | [51.207417, -2.82881] | 2014-10-14T12:00:00Z | 2023-08-07T00:00:00Z | 7.0 | 0.31 | 0.093 | Improved grassland | 0.029 | 0.0033 | 0.314 | 0.059 | Organic soil |
WADDN | Waddesdon | [51.839436, -0.948405] | 2013-11-04T18:30:00Z | 2023-08-07T00:00:00Z | 98.0 | 1.01 | 0.16 | Improved grassland | 0.021 | 0.0021 | 0.034 | 0.0023 | Mineral soil |
WIMPL | Wimpole | [52.132078, -0.044411] | 2019-09-10T00:00:00Z | 2023-08-07T00:00:00Z | 30.0 | 1.18 | 0.16 | Arable and horticulture | 0.015 | 0.0039 | 0.035 | 0.0021 | Mineral soil |
WRTTL | Writtle | [51.733896, 0.417923] | 2017-07-04T10:30:00Z | 2023-08-07T00:00:00Z | 44.0 | 1.15 | 0.23 | Improved grassland | 0.019 | 0.0013 | 0.035 | 0.0033 | Mineral soil |
WYTH1 | Wytham Woods | [51.77728, -1.33846] | 2013-11-26T00:30:00Z | 2016-10-01T00:00:00Z | 109.0 | 0.96 | 0.19 | Broadleaf woodland | 0.017 | 0.0047 | 0.028 | 0.0044 | Mineral soil |
Data queries
To get hold of the data for COSMOS-UK sites, there are a number of different ‘queries’ that you can use against each data collection. They are:
Location / site ID
Position
Cube
Radius
JSON response
Data responses can either be in JSON or CSV format. First we will look at the JSON response - this is the default. The JSON response is essentially loaded as a nested Python dictionary. We can access the parts of the dictionary we need to build a dataframe of the COSMOS-UK data. The following is a function that we can re-use to wrangle the dictionary into a Pandas dataframe:
[8]:
def read_json_collection_data(json_response):
""" Wrangle the response JSON from a COSMOS-API data collection request into a more usable format - in this case a Pandas Dataframe
:param dict json_response: The JSON response dictionary returned from a COSMOS-API data collection request
:return: Dataframe of data
:rtype: pd.DataFrame
"""
# The response is a list of dictionaries, one for each requested site
# You can choose how you want to build your dataframes. Here, I'm just loading all stations into one big dataframe.
# But you could modify this for your own use cases. For example you might want to build a dictionary of {site_id: dataframe}
# to keep site data separate, etc.
master_df = pd.DataFrame()
for site_data in resp['coverages']:
# Read the site ID
site_id = site_data['dct:identifier']
# Read the time stamps of each data point
time_values = pd.DatetimeIndex(site_data['domain']['axes']['t']['values'])
# Now read the values for each requested parameter at each of the time stamps
param_values = {param_name: param_data['values'] for param_name, param_data in site_data['ranges'].items()}
# And put everything into a dataframe
site_df = pd.DataFrame.from_dict(param_values)
site_df['datetime'] = time_values
site_df['site_id'] = site_id
site_df = site_df.set_index(['datetime', 'site_id'])
master_df = pd.concat([master_df, site_df])
return master_df
Location (site ID) query
/collections/<collection_id>/locations/<site_id>
The location query fetches data for a given site ID. You can constrain the query by specifing a given date or date range and one or more parameter names (see section below)
The default without additional query parameters is to return data for all parameters, for the latest single timestep available.
Single site ID
[9]:
site_id = 'CHIMN'
query_url = f'{BASE_URL}/collections/1D/locations/{site_id}'
resp = get_api_response(query_url)
df = read_json_collection_data(resp)
display(df)
https://cosmos-api.ceh.ac.uk/collections/1D/locations/CHIMN
albedo | cosmos_vwc | cts_mod_corr | d86_75m | g1 | g2 | lwin | lwout | pa | pe | ... | tdt6_tsoil | tdt6_vwc | tdt7_tsoil | tdt7_vwc | tdt8_tsoil | tdt8_vwc | tdt9_tsoil | tdt9_vwc | wd | ws | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
datetime | site_id | |||||||||||||||||||||
2023-08-07 00:00:00+00:00 | CHIMN | 0.21 | 40.0 | 885.12869 | 14.53812 | -1.2 | -0.8 | 28.2 | 33.7 | 1011.6 | 3.5 | ... | 16.1 | 28.0 | 16.0 | 32.3 | 16.2 | 23.6 | 16.1 | 8.4 | 252.9 | 2.0 |
1 rows × 51 columns
Multiple site IDs
You can also provide a semi-colon separated list of site IDs. This returns data for all sites listed. For example:
[10]:
site_ids = ['CHIMN', 'ROTHD', 'WRTTL']
query_url = f'{BASE_URL}/collections/1D/locations/{";".join(site_ids)}'
resp = get_api_response(query_url)
df = read_json_collection_data(resp)
display(df)
https://cosmos-api.ceh.ac.uk/collections/1D/locations/CHIMN;ROTHD;WRTTL
albedo | cosmos_vwc | cts_mod_corr | d86_75m | g1 | g2 | lwin | lwout | pa | pe | ... | tdt6_tsoil | tdt6_vwc | tdt7_tsoil | tdt7_vwc | tdt8_tsoil | tdt8_vwc | tdt9_tsoil | tdt9_vwc | wd | ws | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
datetime | site_id | |||||||||||||||||||||
2023-08-07 00:00:00+00:00 | CHIMN | 0.210 | 40.0 | 885.12869 | 14.53812 | -1.2 | -0.8 | 28.2 | 33.7 | 1011.6 | 3.5 | ... | 16.1 | 28.0 | 16.0 | 32.3 | 16.2 | 23.6 | 16.1 | 8.4 | 252.9 | 2.0 |
ROTHD | 0.171 | 32.8 | 1661.41515 | 15.84727 | 3.2 | 1.8 | 28.0 | 34.2 | 1003.4 | 3.6 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 281.0 | 2.4 | |
WRTTL | 0.178 | 27.4 | 1730.81202 | 19.37998 | -0.4 | -0.5 | 27.7 | 34.2 | 1014.0 | 3.8 | ... | 15.4 | 29.9 | 15.5 | 30.1 | 15.4 | 29.3 | 15.3 | 11.1 | 277.2 | 2.9 |
3 rows × 51 columns
Constraining the request with query parameters
Date constraints
Lets add some query parameters to select a date range. There are 4 ways to specify a date query parameter:
A single date in the format:
datetime=<date>
A date range in the format:
datetime=<start_date>/<end_date>
A date range with an open end (i.e. fetch all from start date):
datetime=<start_date>..
A date range with an open beginning (i.e. fetch all up to end date):
datetime=..<end_date>
Note that dates always need to be provided in the format: “YYYY-mm-ddTHH:MM:SSZ”, for example: “2023-03-31T10:30:00Z”
[11]:
def format_datetime(dt):
return dt.strftime("%Y-%m-%dT%H:%M:%SZ")
[12]:
# An example of using specific start and end dates
start_date = format_datetime(datetime(2023, 3, 1))
end_date = format_datetime(datetime(2023, 3, 6))
query_date_range = f'{start_date}/{end_date}'
query_url = f'{BASE_URL}/collections/1D/locations/{site_id}?datetime={query_date_range}'
resp = get_api_response(query_url)
df = read_json_collection_data(resp)
display(df)
https://cosmos-api.ceh.ac.uk/collections/1D/locations/CHIMN?datetime=2023-03-01T00:00:00Z/2023-03-06T00:00:00Z
albedo | cosmos_vwc | cts_mod_corr | d86_75m | g1 | g2 | lwin | lwout | pa | pe | ... | tdt6_tsoil | tdt6_vwc | tdt7_tsoil | tdt7_vwc | tdt8_tsoil | tdt8_vwc | tdt9_tsoil | tdt9_vwc | wd | ws | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
datetime | site_id | |||||||||||||||||||||
2023-03-01 00:00:00+00:00 | CHIMN | 0.182 | 43.3 | 870.38390 | 14.04427 | 0.3 | 0.6 | 28.3 | 29.4 | 1021.2 | 0.8 | ... | 5.2 | 31.6 | 5.3 | 34.8 | 5.3 | 35.5 | 6.0 | 11.1 | 33.2 | 3.4 |
2023-03-02 00:00:00+00:00 | CHIMN | 0.209 | 42.6 | 873.54724 | 14.14392 | -1.9 | -2.4 | 24.3 | 29.2 | 1018.3 | 1.3 | ... | 5.4 | 31.5 | 5.5 | 34.8 | 5.6 | 35.4 | 6.1 | 11.2 | 45.5 | 3.4 |
2023-03-03 00:00:00+00:00 | CHIMN | 0.195 | 43.0 | 871.49535 | 14.08666 | -2.3 | -3.4 | 27.9 | 29.2 | 1021.4 | 0.8 | ... | 5.3 | 31.5 | 5.5 | 34.8 | 5.6 | 35.4 | 6.1 | 11.1 | 34.8 | 2.6 |
2023-03-04 00:00:00+00:00 | CHIMN | 0.193 | 41.6 | 877.72452 | 14.29089 | -2.7 | -4.2 | 27.6 | 29.1 | 1021.7 | 0.9 | ... | 5.3 | 31.4 | 5.4 | 34.7 | 5.5 | 35.3 | 6.1 | 11.0 | 9.6 | 2.4 |
2023-03-05 00:00:00+00:00 | CHIMN | 0.194 | 44.3 | 865.99066 | 13.90633 | -3.8 | -6.4 | 26.4 | 28.6 | 1010.8 | 0.7 | ... | 5.1 | 31.4 | 5.3 | 34.7 | 5.4 | 35.3 | 6.0 | 11.1 | 277.0 | 1.7 |
2023-03-06 00:00:00+00:00 | CHIMN | 0.199 | 42.6 | 873.31374 | 14.14392 | -1.0 | -1.7 | 27.9 | 29.3 | 997.4 | 0.9 | ... | 5.0 | 31.3 | 5.2 | 34.7 | 5.3 | 35.4 | 5.9 | 11.1 | 253.4 | 2.5 |
6 rows × 51 columns
Parameter constraints
We can constrain the data response further by providing a list of parameter names:
[13]:
# Specify a subset of paramater names
param_names = ['albedo', 'cosmos_vwc', 'pe']
query_url = f'{BASE_URL}/collections/1D/locations/{site_id}?datetime={query_date_range}¶meter-name={",".join(param_names)}'
resp = get_api_response(query_url)
df = read_json_collection_data(resp)
display(df)
https://cosmos-api.ceh.ac.uk/collections/1D/locations/CHIMN?datetime=2023-03-01T00:00:00Z/2023-03-06T00:00:00Z¶meter-name=albedo,cosmos_vwc,pe
albedo | cosmos_vwc | pe | ||
---|---|---|---|---|
datetime | site_id | |||
2023-03-01 00:00:00+00:00 | CHIMN | 0.182 | 43.3 | 0.8 |
2023-03-02 00:00:00+00:00 | CHIMN | 0.209 | 42.6 | 1.3 |
2023-03-03 00:00:00+00:00 | CHIMN | 0.195 | 43.0 | 0.8 |
2023-03-04 00:00:00+00:00 | CHIMN | 0.193 | 41.6 | 0.9 |
2023-03-05 00:00:00+00:00 | CHIMN | 0.194 | 44.3 | 0.7 |
2023-03-06 00:00:00+00:00 | CHIMN | 0.199 | 42.6 | 0.9 |
By specifying ‘flags=true’, we can return the flag parameters alongside the data parameters:
[14]:
# Add flags=false to the query:
query_url = f'{BASE_URL}/collections/1D/locations/{site_id}?datetime={query_date_range}¶meter-name={",".join(param_names)}&flags=true'
resp = get_api_response(query_url)
df = read_json_collection_data(resp)
display(df)
https://cosmos-api.ceh.ac.uk/collections/1D/locations/CHIMN?datetime=2023-03-01T00:00:00Z/2023-03-06T00:00:00Z¶meter-name=albedo,cosmos_vwc,pe&flags=true
albedo | albedo_flag | cosmos_vwc | cosmos_vwc_flag | pe | pe_flag | ||
---|---|---|---|---|---|---|---|
datetime | site_id | ||||||
2023-03-01 00:00:00+00:00 | CHIMN | 0.182 | None | 43.3 | None | 0.8 | E |
2023-03-02 00:00:00+00:00 | CHIMN | 0.209 | None | 42.6 | None | 1.3 | E |
2023-03-03 00:00:00+00:00 | CHIMN | 0.195 | None | 43.0 | None | 0.8 | E |
2023-03-04 00:00:00+00:00 | CHIMN | 0.193 | None | 41.6 | None | 0.9 | E |
2023-03-05 00:00:00+00:00 | CHIMN | 0.194 | None | 44.3 | None | 0.7 | E |
2023-03-06 00:00:00+00:00 | CHIMN | 0.199 | None | 42.6 | None | 0.9 | E |
Position, cube and radius queries
Other methods are available for requesting multiple sites, however these are potentially less useful than the location query shown above. They have been included in the API for completeness and conformance with the OGC Environmental Data Retrieval API standards.
As with the location query, you can constrain the query further by specifing a given date or date range and one or more parameter names.
Position
/collections/<collection_id>/position?<coord(s)>
The position query fetches data for site(s) nearest to the given coordinate(s). You can specifiy coordinates in 2 ways:
A single POINT coordinate to return just one site
for example:
/collections/1D/position?coords=POINT(-1.12685 52.86073)
A set of MULTIPOINT coordinates to return multiple sites
for example:
/collections/1D/position?coords=MULTIPOINT((-1.4787658 51.708021),(-2.4678 54.659417),(-0.044411 52.132078))
The default coordinate reference system is WGS84 (i.e. specifying latitude and longitude coordinates). Alternatively, you can specify crs=OSGB36
as an additional query parameter to use British National Grid coordinates.
Cube
/collections/<collection_id>/cube?<bbox>
The cube query fetches data for sites within a given bounding box. The bounding box is given in the format: bbox=<min x>,<min y>,<max x>,<max y>
For example: /collections/1D/cube?bbox=-0.8,50,0,53
Radius
/collections/<collection_id>/radius?<coord(s)>
The radius query fetches data for sites within a circle of a given radius, centred at a given point (or points). The radius query parameter can be omitted, in which case this performs as described in the Position query above.
For example: /collections/30M/radius?coords=POINT(-1, 52)&within=10&within-units=km
This fetches data for all sites within a 10km radius of the given point.
CSV response
All of the data collection queries described above can return CSV file(s) instead of JSON if required. Simply add f=csv
as an additional query parameter to the query URL.
A CSV file per site is created and returned within a zip archive.
[20]:
# Create a CSV query URL for multiple sites
site_ids = ['CHIMN', 'MOORH', 'WIMPL']
start_date = format_datetime(datetime(2023, 3, 1))
end_date = format_datetime(datetime(2023, 3, 3))
query_date_range = f'{start_date}/{end_date}'
query_url = f'{BASE_URL}/collections/1D/locations/{";".join(site_ids)}?datetime={query_date_range}&f=csv'
resp = get_api_response(query_url, csv=True)
zip_file = zipfile.ZipFile(io.BytesIO(resp.content))
https://cosmos-api.ceh.ac.uk/collections/1D/locations/CHIMN;MOORH;WIMPL?datetime=2023-03-01T00:00:00Z/2023-03-03T00:00:00Z&f=csv
[21]:
# List files within the returned zip archive
for csv_name in zip_file.namelist():
print(csv_name)
COSMOS_UK_CHIMN_1D_202303010000_202303030000.csv
COSMOS_UK_MOORH_1D_202303010000_202303030000.csv
COSMOS_UK_WIMPL_1D_202303010000_202303030000.csv
[22]:
# The CSV files are formatted with some metadata at the top. You can read the CSV files into a Pandas dataframe with code such as:
csv_file = zip_file.open(csv_name)
df = pd.read_csv(csv_file, index_col=0, skiprows=[0, 1, 2, 3, 4, 6, 7])
display(df)
albedo | cosmos_vwc | cts_mod_corr | d86_75m | g1 | g2 | lwin | lwout | pa | pe | ... | tdt3_vwc | tdt4_vwc | tdt5_vwc | tdt6_vwc | tdt7_vwc | tdt8_vwc | tdt9_vwc | tdt10_vwc | wd | ws | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
parameter-id | |||||||||||||||||||||
2023-03-01T00:00:00Z | 0.181 | 37.4 | 1570.37808 | 16.57967 | 2.2 | 2.2 | 27.6 | 29.5 | 1026.2 | 0.7 | ... | 38.5 | 39.2 | 38.9 | 39.0 | 29.4 | 39.1 | 23.6 | 19.1 | 27.2 | 2.2 |
2023-03-02T00:00:00Z | 0.196 | 40.9 | 1541.40998 | 15.95570 | -0.3 | -1.6 | 24.7 | 29.3 | 1023.5 | 1.3 | ... | 38.5 | 39.0 | 39.0 | 39.0 | 29.4 | 39.1 | 23.6 | 19.1 | 38.5 | 2.6 |
2023-03-03T00:00:00Z | 0.179 | 37.9 | 1565.63872 | 16.48513 | -1.7 | -1.2 | 27.8 | 29.5 | 1026.2 | 0.9 | ... | 38.5 | 38.9 | 38.8 | 39.0 | 29.4 | 39.0 | 23.6 | 19.1 | 20.0 | 2.2 |
3 rows × 51 columns
Request limits
Given the large number of stations, variables, and timesteps, there is potential for data requests to the API to be very large, particularly for the 30 minute time step collection. Therefore, it is necessary for a limit to be set on the size of the data request so that the data can be returned in a timely manner without the API server or your local connection being overwhelmed.
The COSMOS-UK API has a ‘credit’ system to help you manage your data requests in a transparent way. The current credit limit is set to 15,000,000. Credits are calculated by:
(Number of sites) x (number of parameters) x (number of timesteps)
Note: Remember that the default is to always return the flag parameters alongside the data parameters. This will effectively double the number of parameters in the request - so bear that in mind when working about request credit totals.
Example representative credit totals:
1 site, all parameters (including flags), 1 year of 30 minute data = 1 * 50 * 17,520 = 876,000 credits
1 site, all parameters (including flags), 10 years of 30 minute data = 1 * 50 * 175,200 = 8,760,000 credits
All sites, all parameters (including flags), 10 years of daily data = 51 * 68 * 3,650 = 12,658,200 credits
A request that exceeds the credit limit will be returned a 413 error code with a description of how many credits you used in the failed request.
[23]:
# Request 30 minute data for all sites, for all parameters, for all timesteps
query_url = f'{BASE_URL}/collections/30M/cube?bbox=-9,49.75,2,61&datetime=..2023-03-01T00:00:00Z'
resp = get_api_response(query_url)
print(resp)
https://cosmos-api.ceh.ac.uk/collections/30M/cube?bbox=-9,49.75,2,61&datetime=..2023-03-01T00:00:00Z
{'code': 413, 'name': 'Request Entity Too Large', 'description': 'Too much data has been requested for a single request. Maximum request size is 15,000,000 credits. Your request would use 288,564,525 credits. Credits are calculated by (sites x parameters x time steps).'}