from netCDF4 import Dataset, num2date
import matplotlib.pyplot as plt
import cartopy
import cartopy.crs as ccrs
import os
import datetime
import pandas as pd
import numpy as np
'data_dir'] = os.getenv('CARTOPY_DIR', cartopy.config.get('data_dir')) cartopy.config[
Plotting eReefs data
Times series plots
Learn how to create time series plots of eReefs data in python.
In this notebook we use OpeNDAP to extract time series data at a single location of interest, then plot this data. This extraction process can also be done with the AIMS eReefs data extraction tool. If you which to perform bigger extractions then we recommend using this tool instead of this process outlined in this example.
Note: This script has no error checking and so changing the date ranges or locations might result in out of bounds errors.
Load the required Python libraries
Choose OPeNDAP end point
The first part of the process is to choose the OPeNDAP end point on the AIMS eReefs THREDDS server. You can view the products here. At this stage there is no grouped OPeNDAP service for the entire time series and so this script only works for looking at a single month of data. Hopefully this can be improved in the future.
# Connect to the OpeNDAP endpoint for the specified month.
= 3
month = 2020
year = str(year)+'-'+format(month, '02')
netCDF_datestr netCDF_datestr
'2020-03'
# OPeNDAP URL to file "EREEFS_AIMS-CSIRO_gbr4_v2_hydro_daily-monthly-YYYY-MM.nc". Hydrodynamic 4km model, daily data for the month specified
= "https://thredds.ereefs.aims.gov.au/thredds/dodsC/ereefs/gbr4_v2/daily-monthly/EREEFS_AIMS-CSIRO_gbr4_v2_hydro_daily-monthly-"+netCDF_datestr+".nc"
inputFile
= Dataset(inputFile, 'r')
nc_data print(nc_data.title)
# To find a list of the variables uncomment the next line:
nc_data.variables
eReefs AIMS-CSIRO GBR4 Hydrodynamic v2 daily aggregation
{'mean_cur': <class 'netCDF4._netCDF4.Variable'>
float32 mean_cur(time, k, latitude, longitude)
coordinates: time zc latitude longitude
substanceOrTaxon_id: http://environment.data.gov.au/def/feature/ocean_current
units: ms-1
puv__parameter: http://vocab.nerc.ac.uk/collection/P01/current/LCEWMP01/
medium_id: http://environment.data.gov.au/def/feature/ocean
unit_id: http://qudt.org/vocab/unit#MeterPerSecond
short_name: mean_cur
aggregation: mean_speed
standard_name: mean_current_speed
long_name: mean_current_speed
_ChunkSizes: [ 1 1 133 491]
unlimited dimensions: time
current shape = (31, 17, 723, 491)
filling off,
'salt': <class 'netCDF4._netCDF4.Variable'>
float32 salt(time, k, latitude, longitude)
qudt__unit: http://qudt.org/vocab/unit/PSU
puv__parameter: http://vocab.nerc.ac.uk/collection/P01/current/PSLTMP01/
coordinates: time zc latitude longitude
substanceOrTaxon_id: http://sweet.jpl.nasa.gov/2.2/matrWater.owl#SaltWater
scaledQuantityKind_id: http://environment.data.gov.au/def/property/practical_salinity
short_name: salt
aggregation: Daily
units: PSU
medium_id: http://environment.data.gov.au/def/feature/ocean
unit_id: http://environment.data.gov.au/water/quality/def/unit/PSU
long_name: Salinity
_ChunkSizes: [ 1 1 133 491]
unlimited dimensions: time
current shape = (31, 17, 723, 491)
filling off,
'temp': <class 'netCDF4._netCDF4.Variable'>
float32 temp(time, k, latitude, longitude)
puv__parameter: https://vocab.nerc.ac.uk/collection/P01/current/TEMPMP01/
coordinates: time zc latitude longitude
substanceOrTaxon_id: http://sweet.jpl.nasa.gov/2.2/matrWater.owl#SaltWater
scaledQuantityKind_id: http://environment.data.gov.au/def/property/sea_water_temperature
short_name: temp
aggregation: Daily
units: degrees C
medium_id: http://environment.data.gov.au/def/feature/ocean
unit_id: http://qudt.org/vocab/unit#DegreeCelsius
long_name: Temperature
_ChunkSizes: [ 1 1 133 491]
unlimited dimensions: time
current shape = (31, 17, 723, 491)
filling off,
'u': <class 'netCDF4._netCDF4.Variable'>
float32 u(time, k, latitude, longitude)
vector_components: u v
coordinates: time zc latitude longitude
substanceOrTaxon_id: http://environment.data.gov.au/def/feature/ocean_current
vector_name: Currents
aggregation: Daily
units: ms-1
long_name: Eastward current
puv__parameter: http://vocab.nerc.ac.uk/collection/P01/current/LCEWMP01/
scaledQuantityKind_id: http://environment.data.gov.au/def/property/sea_water_velocity_eastward
short_name: u
standard_name: eastward_sea_water_velocity
medium_id: http://environment.data.gov.au/def/feature/ocean
unit_id: http://qudt.org/vocab/unit#MeterPerSecond
_ChunkSizes: [ 1 1 133 491]
unlimited dimensions: time
current shape = (31, 17, 723, 491)
filling off,
'v': <class 'netCDF4._netCDF4.Variable'>
float32 v(time, k, latitude, longitude)
vector_components: u v
coordinates: time zc latitude longitude
substanceOrTaxon_id: http://environment.data.gov.au/def/feature/ocean_current
vector_name: Currents
aggregation: Daily
units: ms-1
long_name: Northward current
puv__parameter: http://vocab.nerc.ac.uk/collection/P01/current/LCNSMP01/
scaledQuantityKind_id: http://environment.data.gov.au/def/property/sea_water_velocity_northward
short_name: v
standard_name: northward_sea_water_velocity
medium_id: http://environment.data.gov.au/def/feature/ocean
unit_id: http://qudt.org/vocab/unit#MeterPerSecond
_ChunkSizes: [ 1 1 133 491]
unlimited dimensions: time
current shape = (31, 17, 723, 491)
filling off,
'zc': <class 'netCDF4._netCDF4.Variable'>
float64 zc(k)
positive: up
coordinate_type: Z
units: m
long_name: Z coordinate
axis: Z
_CoordinateAxisType: Height
_CoordinateZisPositive: up
unlimited dimensions:
current shape = (17,)
filling off,
'time': <class 'netCDF4._netCDF4.Variable'>
float64 time(time)
units: days since 1990-01-01 00:00:00 +10
long_name: Time
standard_name: time
coordinate_type: time
puv__uom: http://vocab.nerc.ac.uk/collection/P06/current/UTAA/
calendar: gregorian
_CoordinateAxisType: Time
_ChunkSizes: 1024
unlimited dimensions: time
current shape = (31,)
filling off,
'latitude': <class 'netCDF4._netCDF4.Variable'>
float64 latitude(latitude)
long_name: Latitude
standard_name: latitude
units: degrees_north
coordinate_type: latitude
projection: geographic
puv__ofProperty: http://vocab.nerc.ac.uk/collection/S06/current/S0600045/
puv__uom: http://vocab.nerc.ac.uk/collection/P06/current/DEGN/
_CoordinateAxisType: Lat
unlimited dimensions:
current shape = (723,)
filling off,
'longitude': <class 'netCDF4._netCDF4.Variable'>
float64 longitude(longitude)
standard_name: longitude
long_name: Longitude
units: degrees_east
puv__uom: http://vocab.nerc.ac.uk/collection/P06/current/DEGE/
coordinate_type: longitude
projection: geographic
_CoordinateAxisType: Lon
unlimited dimensions:
current shape = (491,)
filling off,
'mean_wspeed': <class 'netCDF4._netCDF4.Variable'>
float32 mean_wspeed(time, latitude, longitude)
puv__parameter: http://vocab.nerc.ac.uk/collection/P01/current/ESEWMPXX/
coordinates: time latitude longitude
units: ms-1
short_name: mean_wspeed
aggregation: mean_speed
standard_name: mean_wind_speed
long_name: mean_wind_speed
_ChunkSizes: [ 1 133 491]
unlimited dimensions: time
current shape = (31, 723, 491)
filling off,
'eta': <class 'netCDF4._netCDF4.Variable'>
float32 eta(time, latitude, longitude)
puv__parameter: https://vocab.nerc.ac.uk/collection/P01/current/ASLVMP01/
coordinates: time latitude longitude
substanceOrTaxon_id: http://environment.data.gov.au/def/feature/ocean_near_surface
scaledQuantityKind_id: http://environment.data.gov.au/def/property/sea_surface_elevation
short_name: eta
standard_name: sea_surface_height_above_sea_level
aggregation: Daily
units: metre
positive: up
medium_id: http://environment.data.gov.au/def/feature/ocean
unit_id: http://qudt.org/vocab/unit#Meter
long_name: Surface elevation
_ChunkSizes: [ 1 133 491]
unlimited dimensions: time
current shape = (31, 723, 491)
filling off,
'wspeed_u': <class 'netCDF4._netCDF4.Variable'>
float32 wspeed_u(time, latitude, longitude)
puv__parameter: http://vocab.nerc.ac.uk/collection/P01/current/ESEWMPXX/
coordinates: time latitude longitude
short_name: wspeed_u
aggregation: Daily
units: ms-1
long_name: eastward_wind
_ChunkSizes: [ 1 133 491]
unlimited dimensions: time
current shape = (31, 723, 491)
filling off,
'wspeed_v': <class 'netCDF4._netCDF4.Variable'>
float32 wspeed_v(time, latitude, longitude)
puv__parameter: http://vocab.nerc.ac.uk/collection/P01/current/ESNSMPXX/
coordinates: time latitude longitude
short_name: wspeed_v
aggregation: Daily
units: ms-1
long_name: northward_wind
_ChunkSizes: [ 1 133 491]
unlimited dimensions: time
current shape = (31, 723, 491)
filling off}
Select the point location
Work out the bounds of the gridded data. We can then use this to find out which grid cell best matches our location of interest.
Note: This only works because the AIMS eReefs aggregate datasets are regridded onto a regularly spaced grid. The original raw model data is on a curvilinear grid and this approach would not work for that data.
= nc_data.variables['longitude'][:]
lons = max(lons)
max_lon = min(lons)
min_lon = nc_data.variables['latitude'][:]
lats = max(lats)
max_lat = min(lats)
min_lat = lons.size
grid_lon = lats.size
grid_lat print("Grid bounds, Lon: "+str(min_lon)+" - "+str(max_lon)+" Lat:"+str(min_lat)+" - "+str(max_lat))
print("Grid size is: "+str(grid_lon)+" x "+str(grid_lat))
Grid bounds, Lon: 142.168788 - 156.868788 Lat:-28.696022 - -7.036022
Grid size is: 491 x 723
Find the closest index to the location of interest.
# Davies reef
= -18.82
lat = 147.64
lon = round((lat-min_lat)/(max_lat-min_lat)*grid_lat)
selectedLatIndex = round((lon-min_lon)/(max_lon-min_lon)*grid_lon)
selectedLonIndex print("Grid position of location: "+str(selectedLatIndex)+", "+str(selectedLonIndex))
Grid position of location: 330, 183
Extract values
Extract the values over time at this location. Note that because we are access the underlying data here this results in an OpeNDAP call to get the data from the remote server. As a result this call can take a while (~10 sec).
= 15 # -1.5m
selectedDepthIndex = 10 # -17.75m
selectedDepthIndex2
# Time, Depth, Lat, Lon
= nc_data.variables['temp'][:,[selectedDepthIndex,selectedDepthIndex2], selectedLatIndex, selectedLonIndex]
dailyTemp1 print(dailyTemp1[0:5])
[[29.586527 27.764503]
[29.513176 27.867159]
[29.505758 28.179167]
[29.782936 28.216429]
[30.008278 28.062304]]
Let’s get the wind for the same location. The wind variable doesn’t have any depth dimension and so our indexing into the data is different. The wind is a vector measurement, with an x and y component.
= nc_data.variables['wspeed_v'][:, selectedLatIndex, selectedLonIndex]
wspeed_v = nc_data.variables['wspeed_v'][:, selectedLatIndex, selectedLonIndex] wspeed_u
To get the wind speed we need to calculate the magnitude of this vector.
= np.sqrt(wspeed_v**2 + wspeed_u**2) wspeed
Get the time series. Note that the time values are stored as the number of days since 1990-01-01 00:00:00 +10.
= nc_data.variables['time'][:]
times print(times[0:5])
[11017. 11018. 11019. 11020. 11021.]
Plot the time series
# Convert the days since the 1990 origin into Pandas dates for plotting
= pd.to_datetime(times,unit='D',origin=pd.Timestamp('1990-01-01'))
t
= plt.subplots()
fig, ax1 8, 7)
fig.set_size_inches(
'Date')
ax1.set_xlabel('Temperature (deg C)')
ax1.set_ylabel(0], color='tab:red', label='Temp (-1.5 m)')
ax1.plot(t, dailyTemp1[:,1], color='tab:orange', label='Temp (-17.75 m)')
ax1.plot(t, dailyTemp1[:,#ax1.tick_params(axis='y', labelcolor=color)
= ax1.twinx() # instantiate a second axes that shares the same x-axis
ax2
= 'tab:blue'
color 'Wind speed (m/s)', color=color) # we already handled the x-label with ax1
ax2.set_ylabel(=color, label='Wind')
ax2.plot(t, wspeed, color='y', labelcolor=color)
ax2.tick_params(axis
fig.legend()# Set the axes formating to show the dates on an angle on the current figure (gcf)
plt.gcf().autofmt_xdate()
#fig.tight_layout() # otherwise the right y-label is slightly clipped
From this graph we can see that the surface water at Davies Reef was very warm during March 2020. There was a strong stratification of the temperature profile with cool water at -18 m. Around the 10th March the wind picked up for a few days, mixing the water, cooling the surface down rapidly.