Module geodata_harvester.getdata_radiometric
Script to download Radiometric data from NCI’s GSKY Data Server (using WCS) for a given resolution, and bounding box. Final data is saved as geotiff or NetCDF.
A full ist of datasets can be retrieved with get_radiometricdict() or get_capabilities() for a given url An overview of all datasets can be also found here: https://opus.nci.org.au/display/Help/Datasets
For more details of the NCI GSKY WCS, please see here: https://opus.nci.org.au/pages/viewpage.action?pageId=137199852
LIMITATIONS: for some layers the server readout time can occasionally exceed 30s (longer readout time in request seems to be ignored) In case this happens please try later again when the NCI server is less loaded.
This package is part of the Data Harvester project developed for the Agricultural Research Federation (AgReFed).
Copyright 2022 Sydney Informatics Hub (SIH), The University of Sydney
This open-source software is released under the LGPL-3.0 License.
Author: Sebastian Haan
Expand source code
"""
Script to download Radiometric data from NCI’s GSKY Data Server (using WCS) for a given
resolution, and bounding box. Final data is saved as geotiff or NetCDF.
A full ist of datasets can be retrieved with get_radiometricdict() or get_capabilities() for a given url
An overview of all datasets can be also found here:
https://opus.nci.org.au/display/Help/Datasets
For more details of the NCI GSKY WCS, please see here:
https://opus.nci.org.au/pages/viewpage.action?pageId=137199852
LIMITATIONS: for some layers the server readout time can occasionally exceed 30s (longer readout time in request seems to be ignored)
In case this happens please try later again when the NCI server is less loaded.
This package is part of the Data Harvester project developed for the Agricultural Research Federation (AgReFed).
Copyright 2022 Sydney Informatics Hub (SIH), The University of Sydney
This open-source software is released under the LGPL-3.0 License.
Author: Sebastian Haan
"""
import os
from owslib.wcs import WebCoverageService
import rasterio
from rasterio.plot import show
from datetime import datetime, timezone
from termcolor import cprint, colored
from alive_progress import alive_bar, config_handler
from geodata_harvester import utils
from geodata_harvester.utils import spin
def get_radiometricdict():
"""
Returns dictionary of keys and layer titles
To update manually please run get_capabilities() to retrieve all current layer details
"""
rmdict = {
"resolution_arcsec": 3.6,
"layernames": {
"radmap2019_grid_dose_terr_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 unfiltered terrestrial dose rate",
"radmap2019_grid_dose_terr_filtered_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 filtered terrestrial xf",
"radmap2019_grid_k_conc_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 unfiltered pct potassium",
"radmap2019_grid_k_conc_filtered_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 filtered pct potassium grid",
"radmap2019_grid_th_conc_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 unfiltered ppm thorium",
"radmap2019_grid_th_conc_filtered_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 filtered ppm thorium",
"radmap2019_grid_thk_ratio_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 ratio thorium over potassium",
"radmap2019_grid_u2th_ratio_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 ratio uranium squared over thorium",
"radmap2019_grid_u_conc_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 unfiltered ppm uranium",
"radmap2019_grid_u_conc_filtered_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 filtered ppm uranium",
"radmap2019_grid_uk_ratio_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 ratio uranium over potassium",
"radmap2019_grid_uth_ratio_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 ratio uranium over thorium",
},
}
return rmdict
def getdict_license():
"""
Retrieves the Geoscience Australia data license and NCI attribution information as dict
"""
dict = {
"name": "Geoscience Australia National Geophysical Compilation Sub-collection Radiometrics",
"source_url": "https://opus.nci.org.au/display/Help/Datasets",
"license": "CC BY 4.0",
"license_title": "Creative Commons Attribution 4.0 International (CC BY 4.0)",
"license_url": "https://creativecommons.org/licenses/by/4.0/",
"copyright": "© Copyright 2017-2022, Geoscience Australia",
"attribution": "Geoscience Australia. The WCS service relies on GSKY - A Scalable, Distributed Geospatial Data Service \
from the National Centre for Environmental Information (NCI).",
}
return dict
def plot_raster(infname):
"""
Read in raster tif with rasterio and visualise as map.
Parameters
----------
infname : str
"""
data = rasterio.open(infname)
# show image
show(data)
def get_capabilities():
"""
Get capabilities from WCS layer.
Parameters
----------
url : str
layer url
Returns
-------
keys : list
layer identifiers
titles : list of str
layer titles
descriptions : list of str
layer descriptions
bboxs : list of floats
layer bounding boxes
"""
# URL
url = "https://gsky.nci.org.au/ows/national_geophysical_compilations?service=WCS&version=1.0.0&request=GetCapabilities"
# Create WCS object
wcs = WebCoverageService(url, version="1.0.0", timeout=300)
# Get coverages and content dict keys
content = wcs.contents
keys = content.keys()
print("Following data layers are available:")
title_list = []
description_list = []
bbox_list = []
for key in keys:
print(f"key: {key}")
print(f"title: {wcs[key].title}")
title_list.append(wcs[key].title)
print(f"{wcs[key].abstract}")
description_list.append(wcs[key].abstract)
print(f"bounding box: {wcs[key].boundingBoxWGS84}")
bbox_list.append(wcs[key].boundingBoxWGS84)
print("")
return keys, title_list, description_list, bbox_list
def get_radiometric_layers(
outpath, layernames, bbox, resolution=1, crs="EPSG:4326", format_out="GeoTIFF"
):
"""
Wrapper function for downloading radiometric data layers and save geotiffs from WCS layer.
Parameters
----------
outpath: str
output path
layername : list of strings
layer identifiers
bbox : list
layer bounding box
resolution : int
layer resolution in arcsec
url : str
url of wcs server
crs: str
crsm default 'EPSG:4326'
format_out: str
output format, either "GeoTIFF" or "NetCDF"
Return
------
list of output filenames
"""
url = "https://gsky.nci.org.au/ows/national_geophysical_compilations?service=WCS"
if type(layernames) != list:
layernames = [layernames]
if format_out == "GeoTIFF":
fname_end = ".tif"
elif format_out == "NetCDF":
fname_end = ".nc"
else:
print(
f"\u2716 {format_out} not supported. Choose either GeoTIFF or NetCDF.")
return outfnames
# Loop over all layers
fnames_out = []
for layername in layernames:
outfname = os.path.join(
outpath, "radiometric_" + layername + fname_end)
ok = get_radiometric_image(
outfname, layername, bbox, url, resolution=1, crs=crs, format_out=format_out
)
if ok:
fnames_out.append(outfname)
return fnames_out
def get_radiometric_image(
outfname, layername, bbox, url, resolution=1, crs="EPSG:4326", format_out="GeoTIFF"
):
"""
Download radiometric data layer and save geotiff from WCS layer.
Parameters
----------
outfname : str
output file name
layername : str
layer identifier
bbox : list
layer bounding box
resolution : int
layer resolution in arcsec
url : str
url of wcs server
crs: str
crsm default 'EPSG:4326'
format: str
output format, either "GeoTIFF" or "NetCDF"
Return
------
Exited ok: boolean
"""
# If the resolution passed is None, set to native resolution of datasource
if resolution is None:
resolution = get_radiometricdict()["resolution_arcsec"]
# Convert resolution into width and height pixel number
width = abs(bbox[2] - bbox[0])
height = abs(bbox[3] - bbox[1])
nwidth = int(width / resolution * 3600)
nheight = int(height / resolution * 3600)
# Get date
times = get_times(url, layername)
# There is only one time available per layer
date = times[0]
# Get data
if os.path.exists(outfname):
utils.msg_warn(f"{layername}.tif already exists, skipping download")
else:
try:
with spin(f"Downloading {layername}") as s:
wcs = WebCoverageService(url, version="1.0.0", timeout=300)
data = wcs.getCoverage(
identifier=layername,
time=[date],
bbox=bbox,
format=format_out,
crs=crs,
width=nwidth,
height=nheight,
)
s(1)
except:
utils.msg_err("Download failed")
return False
# Save data
with open(outfname, "wb") as f:
f.write(data.read())
# print(f"Layer {layername} saved in {outfname}")
return True
def get_times(url, layername, year=None):
"""
Return available dates for layer.
Parameters
----------
url: str, layer url
layername: str, name of layer id
year: int or str, year of interest (if None, times for all available years are returned)
Return
------
list of dates
"""
wcs = WebCoverageService(url, version="1.0.0", timeout=300)
times = wcs[layername].timepositions
if year is None:
return times
else:
year = int(year)
dates = []
for time in times:
if datetime.fromisoformat(time[:-1]).astimezone(timezone.utc).year == year:
dates.append(time)
return dates
Functions
def get_capabilities()
-
Get capabilities from WCS layer.
Parameters
url
:str
- layer url
Returns
keys : list
- layer identifiers
titles : list
ofstr
- layer titles
descriptions
:list
ofstr
- layer descriptions
bboxs : list
offloats
- layer bounding boxes
Expand source code
def get_capabilities(): """ Get capabilities from WCS layer. Parameters ---------- url : str layer url Returns ------- keys : list layer identifiers titles : list of str layer titles descriptions : list of str layer descriptions bboxs : list of floats layer bounding boxes """ # URL url = "https://gsky.nci.org.au/ows/national_geophysical_compilations?service=WCS&version=1.0.0&request=GetCapabilities" # Create WCS object wcs = WebCoverageService(url, version="1.0.0", timeout=300) # Get coverages and content dict keys content = wcs.contents keys = content.keys() print("Following data layers are available:") title_list = [] description_list = [] bbox_list = [] for key in keys: print(f"key: {key}") print(f"title: {wcs[key].title}") title_list.append(wcs[key].title) print(f"{wcs[key].abstract}") description_list.append(wcs[key].abstract) print(f"bounding box: {wcs[key].boundingBoxWGS84}") bbox_list.append(wcs[key].boundingBoxWGS84) print("") return keys, title_list, description_list, bbox_list
def get_radiometric_image(outfname, layername, bbox, url, resolution=1, crs='EPSG:4326', format_out='GeoTIFF')
-
Download radiometric data layer and save geotiff from WCS layer.
Parameters
outfname
:str
- output file name
layername
:str
- layer identifier
bbox
:list
- layer bounding box
resolution
:int
- layer resolution in arcsec
url
:str
- url of wcs server
crs
:str
- crsm default 'EPSG:4326'
format
:str
- output format, either "GeoTIFF" or "NetCDF"
Return
Exited ok: boolean
Expand source code
def get_radiometric_image( outfname, layername, bbox, url, resolution=1, crs="EPSG:4326", format_out="GeoTIFF" ): """ Download radiometric data layer and save geotiff from WCS layer. Parameters ---------- outfname : str output file name layername : str layer identifier bbox : list layer bounding box resolution : int layer resolution in arcsec url : str url of wcs server crs: str crsm default 'EPSG:4326' format: str output format, either "GeoTIFF" or "NetCDF" Return ------ Exited ok: boolean """ # If the resolution passed is None, set to native resolution of datasource if resolution is None: resolution = get_radiometricdict()["resolution_arcsec"] # Convert resolution into width and height pixel number width = abs(bbox[2] - bbox[0]) height = abs(bbox[3] - bbox[1]) nwidth = int(width / resolution * 3600) nheight = int(height / resolution * 3600) # Get date times = get_times(url, layername) # There is only one time available per layer date = times[0] # Get data if os.path.exists(outfname): utils.msg_warn(f"{layername}.tif already exists, skipping download") else: try: with spin(f"Downloading {layername}") as s: wcs = WebCoverageService(url, version="1.0.0", timeout=300) data = wcs.getCoverage( identifier=layername, time=[date], bbox=bbox, format=format_out, crs=crs, width=nwidth, height=nheight, ) s(1) except: utils.msg_err("Download failed") return False # Save data with open(outfname, "wb") as f: f.write(data.read()) # print(f"Layer {layername} saved in {outfname}") return True
def get_radiometric_layers(outpath, layernames, bbox, resolution=1, crs='EPSG:4326', format_out='GeoTIFF')
-
Wrapper function for downloading radiometric data layers and save geotiffs from WCS layer.
Parameters
outpath
:str
- output path
layername
:list
ofstrings
- layer identifiers
bbox
:list
- layer bounding box
resolution
:int
- layer resolution in arcsec
url
:str
- url of wcs server
crs
:str
- crsm default 'EPSG:4326'
format_out
:str
- output format, either "GeoTIFF" or "NetCDF"
Return
list of output filenames
Expand source code
def get_radiometric_layers( outpath, layernames, bbox, resolution=1, crs="EPSG:4326", format_out="GeoTIFF" ): """ Wrapper function for downloading radiometric data layers and save geotiffs from WCS layer. Parameters ---------- outpath: str output path layername : list of strings layer identifiers bbox : list layer bounding box resolution : int layer resolution in arcsec url : str url of wcs server crs: str crsm default 'EPSG:4326' format_out: str output format, either "GeoTIFF" or "NetCDF" Return ------ list of output filenames """ url = "https://gsky.nci.org.au/ows/national_geophysical_compilations?service=WCS" if type(layernames) != list: layernames = [layernames] if format_out == "GeoTIFF": fname_end = ".tif" elif format_out == "NetCDF": fname_end = ".nc" else: print( f"\u2716 {format_out} not supported. Choose either GeoTIFF or NetCDF.") return outfnames # Loop over all layers fnames_out = [] for layername in layernames: outfname = os.path.join( outpath, "radiometric_" + layername + fname_end) ok = get_radiometric_image( outfname, layername, bbox, url, resolution=1, crs=crs, format_out=format_out ) if ok: fnames_out.append(outfname) return fnames_out
def get_radiometricdict()
-
Returns dictionary of keys and layer titles
To update manually please run get_capabilities() to retrieve all current layer details
Expand source code
def get_radiometricdict(): """ Returns dictionary of keys and layer titles To update manually please run get_capabilities() to retrieve all current layer details """ rmdict = { "resolution_arcsec": 3.6, "layernames": { "radmap2019_grid_dose_terr_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 unfiltered terrestrial dose rate", "radmap2019_grid_dose_terr_filtered_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 filtered terrestrial xf", "radmap2019_grid_k_conc_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 unfiltered pct potassium", "radmap2019_grid_k_conc_filtered_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 filtered pct potassium grid", "radmap2019_grid_th_conc_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 unfiltered ppm thorium", "radmap2019_grid_th_conc_filtered_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 filtered ppm thorium", "radmap2019_grid_thk_ratio_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 ratio thorium over potassium", "radmap2019_grid_u2th_ratio_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 ratio uranium squared over thorium", "radmap2019_grid_u_conc_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 unfiltered ppm uranium", "radmap2019_grid_u_conc_filtered_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 filtered ppm uranium", "radmap2019_grid_uk_ratio_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 ratio uranium over potassium", "radmap2019_grid_uth_ratio_awags_rad_2019": "Radiometric Grid of Australia (Radmap) v4 2019 ratio uranium over thorium", }, } return rmdict
def get_times(url, layername, year=None)
-
Return available dates for layer.
Parameters
url
:str, layer url
layername
:str, name
oflayer id
year
:int
orstr, year
ofinterest (if None, times for all available years are returned)
Return
list of dates
Expand source code
def get_times(url, layername, year=None): """ Return available dates for layer. Parameters ---------- url: str, layer url layername: str, name of layer id year: int or str, year of interest (if None, times for all available years are returned) Return ------ list of dates """ wcs = WebCoverageService(url, version="1.0.0", timeout=300) times = wcs[layername].timepositions if year is None: return times else: year = int(year) dates = [] for time in times: if datetime.fromisoformat(time[:-1]).astimezone(timezone.utc).year == year: dates.append(time) return dates
def getdict_license()
-
Retrieves the Geoscience Australia data license and NCI attribution information as dict
Expand source code
def getdict_license(): """ Retrieves the Geoscience Australia data license and NCI attribution information as dict """ dict = { "name": "Geoscience Australia National Geophysical Compilation Sub-collection Radiometrics", "source_url": "https://opus.nci.org.au/display/Help/Datasets", "license": "CC BY 4.0", "license_title": "Creative Commons Attribution 4.0 International (CC BY 4.0)", "license_url": "https://creativecommons.org/licenses/by/4.0/", "copyright": "© Copyright 2017-2022, Geoscience Australia", "attribution": "Geoscience Australia. The WCS service relies on GSKY - A Scalable, Distributed Geospatial Data Service \ from the National Centre for Environmental Information (NCI).", } return dict
def plot_raster(infname)
-
Read in raster tif with rasterio and visualise as map.
Parameters
infname
:str
Expand source code
def plot_raster(infname): """ Read in raster tif with rasterio and visualise as map. Parameters ---------- infname : str """ data = rasterio.open(infname) # show image show(data)