In [ ]:
import netCDF4
In [ ]:
f = netCDF4.Dataset('data/rtofs_glo_3dz_f006_6hrly_reg3.nc')
print f
In [ ]:
print f.variables.keys() # get all variable names
temp = f.variables['temperature'] # temperature variable
print temp
In [ ]:
for d in f.dimensions.items():
print d
Each variable has a dimensions
and a shape
attribute.
In [ ]:
temp.dimensions
In [ ]:
temp.shape
In [ ]:
mt = f.variables['MT']
depth = f.variables['Depth']
x,y = f.variables['X'], f.variables['Y']
print mt
print x
In [ ]:
time = mt[:] # Reads the netCDF variable MT, array of one element
print time
In [ ]:
dpth = depth[:] # examine depth array
print dpth
In [ ]:
xx,yy = x[:],y[:]
print 'shape of temp variable:',temp.shape
tempslice = temp[0, dpth > 400, xx > xx.max()/2, yy < yy.max()/2]
print 'shape of temp slice:',tempslice.shape
In [ ]:
lat, lon = f.variables['Latitude'], f.variables['Longitude']
print lat
Aha! So we need to find array indices iy
and ix
such that Latitude[iy, ix]
is close to 50.0 and Longitude[iy, ix]
is close to -140.0 ...
In [ ]:
latvals = lat[:]; lonvals = lon[:] # extract lat/lon values (in degrees) to numpy arrays
import numpy as np
# a function to find the index of the point closest (in squared distance) to give lat/lon value.
def getclosest_ij(lats,lons,latpt,lonpt):
dist_sq = (lats-latpt)**2 + (lons-lonpt)**2 # find squared distance of every point on grid
minindex_flattened = dist_sq.argmin() # 1D index of minimum dist_sq element
# Get 2D index for latvals and lonvals arrays from 1D index
return np.unravel_index(minindex_flattened, latvals.shape)
iy_min, ix_min = getclosest_ij(latvals, lonvals, 50., -140)
|----------+--------|
| Variable | Index |
|----------+--------|
| MT | 0 |
| Depth | 0 |
| Y | iy_min |
| X | ix_min |
|----------+--------|
In [ ]:
sal = f.variables['salinity']
# Read values out of the netCDF file for temperature and salinity
print temp[0,0,iy_min,ix_min], temp.units
print sal[0,0,iy_min,ix_min], sal.units
The following example showcases some nice netCDF features:
In [ ]:
# import pyUDL
from pyudl.tds import get_latest_dods_url
# specify URL for TDS data catalog
gfs_catalog_url = "http://thredds.ucar.edu/thredds/catalog/grib/NCEP/GFS/Global_0p5deg/catalog.xml"
# get latest forecast time available from catalog
latest = get_latest_dods_url(gfs_catalog_url)
print latest
# open the remote dataset
gfs = netCDF4.Dataset(latest)
In [ ]:
# Look at metadata for a specific variable
# gfs.variables.keys() will show all available variables.
sfctmp = gfs.variables['Temperature_surface']
print sfctmp
for dname in sfctmp.dimensions: # print dimensions associated with this variable
print gfs.variables[dname]
In [ ]:
soilmvar = gfs.variables['Volumetric_Soil_Moisture_Content_depth_below_surface_layer']
soilm = soilmvar[0,0,::-1,:] # flip the data in latitude so North Hemisphere is up on the plot
print soilm.shape, type(soilm), soilmvar.missing_value
import matplotlib.pyplot as plt
%matplotlib inline
cs = plt.contourf(soilm)
hours since YY:MM:DD hh-mm-ss
.num2date
and date2num
convenience functions provided to convert between these numeric time coordinates and handy python datetime instances. date2index
finds the time index corresponding to a datetime instance.
In [ ]:
from netCDF4 import num2date, date2num, date2index
timedim = sfctmp.dimensions[0]
print timedim
times = gfs.variables[timedim]
print times.units, times[:]
In [ ]:
dates = num2date(times[:], times.units)
print [date.strftime('%Y%m%d%H') for date in dates]
In [ ]:
from datetime import datetime, timedelta
date = datetime.now() + timedelta(days=3)
print date
ntime = date2index(date,times,select='nearest')
print ntime, dates[ntime]
In [ ]:
lats, lons = gfs.variables['lat'][:], gfs.variables['lon'][:]
# lats, lons are 1-d. Make them 2-d using numpy.meshgrid.
lons, lats = np.meshgrid(lons,lats)
j, i = getclosest_ij(lats,lons,40,-105)
fcst_temp = sfctmp[ntime,j,i]
print 'Boulder forecast valid at %s UTC = %5.1f %s' % (dates[ntime],fcst_temp,sfctmp.units)
Get probability of precip (3 hour accumulation > 0.25mm) at Boulder for tomorrow from SREF.
(catalog URL = 'http://thredds.ucar.edu/thredds/catalog/grib/NCEP/SREF/CONUS_40km/ensprod/catalog.html')
In [ ]:
!ls -l data/prmsl*nc
MFDataset
uses file globbing to patch together all the files into one big Dataset.
You can also pass it a list of specific files.
Limitations:
NETCDF3
, or NETCDF4_CLASSIC
formatted files.
In [ ]:
mf = netCDF4.MFDataset('data/prmsl*nc')
times = mf.variables['time']
dates = num2date(times[:],times.units)
print 'starting date = ',dates[0]
print 'ending date = ',dates[-1]
prmsl = mf.variables['prmsl']
print times.shape, prmsl.dimensions, prmsl.shape
In [ ]:
f.close()
gfs.close()