Hvplot is part of the HoloViz tool suite and has awesome capabilities for visualizing Xarray and Pandas data. Here we access the GFS weather forecast data from the Unidata THREDDS Server and visualize it in just a few lines. We also deal with a couple of problems that people commonly encounter!
import xarray as xr
import hvplot.xarray
url = 'https://thredds-jumbo.unidata.ucar.edu/thredds/dodsC/grib/NCEP/GFS/Global_0p25deg/Best'
ds = xr.open_dataset(url)
hvplot likes longitudes in the range [-180,180], not [0, 360]
ds = ds.assign_coords(lon=(((ds.lon + 180) % 360) - 180)).sortby('lon')
ds['u-component_of_wind_height_above_ground']
<xarray.DataArray 'u-component_of_wind_height_above_ground' (time: 119, height_above_ground4: 7, lat: 721, lon: 1440)> [864853920 values with dtype=float32] Coordinates: * lat (lat) float32 90.0 89.75 89.5 ... -89.5 -89.75 -90.0 * lon (lon) float32 -180.0 -179.8 -179.5 ... 179.5 179.8 * time (time) datetime64[ns] 2021-01-10 ... 2021-01-29T06:... reftime (time) datetime64[ns] 2021-01-10 ... 2021-01-13T06:... * height_above_ground4 (height_above_ground4) float32 10.0 20.0 ... 100.0 Attributes: long_name: u-component of wind @ Specified height le... units: m/s abbreviation: UGRD grid_mapping: LatLon_Projection Grib_Variable_Id: VAR_0-2-2_L103 Grib2_Parameter: [0 2 2] Grib2_Parameter_Discipline: Meteorological products Grib2_Parameter_Category: Momentum Grib2_Parameter_Name: u-component of wind Grib2_Level_Type: 103 Grib2_Level_Desc: Specified height level above ground Grib2_Generating_Process_Type: Forecast
[864853920 values with dtype=float32]
array([ 90. , 89.75, 89.5 , ..., -89.5 , -89.75, -90. ], dtype=float32)
array([-180. , -179.75, -179.5 , ..., 179.25, 179.5 , 179.75], dtype=float32)
array(['2021-01-10T00:00:00.000000000', '2021-01-10T03:00:00.000000000', '2021-01-10T06:00:00.000000000', '2021-01-10T09:00:00.000000000', '2021-01-10T12:00:00.000000000', '2021-01-10T15:00:00.000000000', '2021-01-10T18:00:00.000000000', '2021-01-10T21:00:00.000000000', '2021-01-11T00:00:00.000000000', '2021-01-11T03:00:00.000000000', '2021-01-11T06:00:00.000000000', '2021-01-11T09:00:00.000000000', '2021-01-11T12:00:00.000000000', '2021-01-11T15:00:00.000000000', '2021-01-11T18:00:00.000000000', '2021-01-11T21:00:00.000000000', '2021-01-12T00:00:00.000000000', '2021-01-12T03:00:00.000000000', '2021-01-12T06:00:00.000000000', '2021-01-12T09:00:00.000000000', '2021-01-12T12:00:00.000000000', '2021-01-12T15:00:00.000000000', '2021-01-12T18:00:00.000000000', '2021-01-12T21:00:00.000000000', '2021-01-13T00:00:00.000000000', '2021-01-13T03:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T09:00:00.000000000', '2021-01-13T12:00:00.000000000', '2021-01-13T15:00:00.000000000', '2021-01-13T18:00:00.000000000', '2021-01-13T21:00:00.000000000', '2021-01-14T00:00:00.000000000', '2021-01-14T03:00:00.000000000', '2021-01-14T06:00:00.000000000', '2021-01-14T09:00:00.000000000', '2021-01-14T12:00:00.000000000', '2021-01-14T15:00:00.000000000', '2021-01-14T18:00:00.000000000', '2021-01-14T21:00:00.000000000', '2021-01-15T00:00:00.000000000', '2021-01-15T03:00:00.000000000', '2021-01-15T06:00:00.000000000', '2021-01-15T09:00:00.000000000', '2021-01-15T12:00:00.000000000', '2021-01-15T15:00:00.000000000', '2021-01-15T18:00:00.000000000', '2021-01-15T21:00:00.000000000', '2021-01-16T00:00:00.000000000', '2021-01-16T03:00:00.000000000', '2021-01-16T06:00:00.000000000', '2021-01-16T09:00:00.000000000', '2021-01-16T12:00:00.000000000', '2021-01-16T15:00:00.000000000', '2021-01-16T18:00:00.000000000', '2021-01-16T21:00:00.000000000', '2021-01-17T00:00:00.000000000', '2021-01-17T03:00:00.000000000', '2021-01-17T06:00:00.000000000', '2021-01-17T09:00:00.000000000', '2021-01-17T12:00:00.000000000', '2021-01-17T15:00:00.000000000', '2021-01-17T18:00:00.000000000', '2021-01-17T21:00:00.000000000', '2021-01-18T00:00:00.000000000', '2021-01-18T03:00:00.000000000', '2021-01-18T06:00:00.000000000', '2021-01-18T09:00:00.000000000', '2021-01-18T12:00:00.000000000', '2021-01-18T15:00:00.000000000', '2021-01-18T18:00:00.000000000', '2021-01-18T21:00:00.000000000', '2021-01-19T00:00:00.000000000', '2021-01-19T03:00:00.000000000', '2021-01-19T06:00:00.000000000', '2021-01-19T09:00:00.000000000', '2021-01-19T12:00:00.000000000', '2021-01-19T15:00:00.000000000', '2021-01-19T18:00:00.000000000', '2021-01-19T21:00:00.000000000', '2021-01-20T00:00:00.000000000', '2021-01-20T03:00:00.000000000', '2021-01-20T06:00:00.000000000', '2021-01-20T09:00:00.000000000', '2021-01-20T12:00:00.000000000', '2021-01-20T15:00:00.000000000', '2021-01-20T18:00:00.000000000', '2021-01-20T21:00:00.000000000', '2021-01-21T00:00:00.000000000', '2021-01-21T03:00:00.000000000', '2021-01-21T06:00:00.000000000', '2021-01-21T09:00:00.000000000', '2021-01-21T12:00:00.000000000', '2021-01-21T15:00:00.000000000', '2021-01-21T18:00:00.000000000', '2021-01-21T21:00:00.000000000', '2021-01-22T00:00:00.000000000', '2021-01-22T03:00:00.000000000', '2021-01-22T06:00:00.000000000', '2021-01-22T09:00:00.000000000', '2021-01-22T12:00:00.000000000', '2021-01-22T15:00:00.000000000', '2021-01-22T18:00:00.000000000', '2021-01-22T21:00:00.000000000', '2021-01-23T00:00:00.000000000', '2021-01-23T03:00:00.000000000', '2021-01-23T06:00:00.000000000', '2021-01-23T18:00:00.000000000', '2021-01-24T06:00:00.000000000', '2021-01-24T18:00:00.000000000', '2021-01-25T06:00:00.000000000', '2021-01-25T18:00:00.000000000', '2021-01-26T06:00:00.000000000', '2021-01-26T18:00:00.000000000', '2021-01-27T06:00:00.000000000', '2021-01-27T18:00:00.000000000', '2021-01-28T06:00:00.000000000', '2021-01-28T18:00:00.000000000', '2021-01-29T06:00:00.000000000'], dtype='datetime64[ns]')
array(['2021-01-10T00:00:00.000000000', '2021-01-10T00:00:00.000000000', '2021-01-10T06:00:00.000000000', '2021-01-10T06:00:00.000000000', '2021-01-10T12:00:00.000000000', '2021-01-10T12:00:00.000000000', '2021-01-10T18:00:00.000000000', '2021-01-10T18:00:00.000000000', '2021-01-11T00:00:00.000000000', '2021-01-11T00:00:00.000000000', '2021-01-11T06:00:00.000000000', '2021-01-11T06:00:00.000000000', '2021-01-11T12:00:00.000000000', '2021-01-11T12:00:00.000000000', '2021-01-11T18:00:00.000000000', '2021-01-11T18:00:00.000000000', '2021-01-12T00:00:00.000000000', '2021-01-12T00:00:00.000000000', '2021-01-12T06:00:00.000000000', '2021-01-12T06:00:00.000000000', '2021-01-12T12:00:00.000000000', '2021-01-12T12:00:00.000000000', '2021-01-12T18:00:00.000000000', '2021-01-12T18:00:00.000000000', '2021-01-13T00:00:00.000000000', '2021-01-13T00:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000', '2021-01-13T06:00:00.000000000'], dtype='datetime64[ns]')
array([ 10., 20., 30., 40., 50., 80., 100.], dtype=float32)
We want to select the CONUS, but we see from the previous cell that latitude values are decreasing, so we slice 50 to 20 instead of 20 to 50.
ds_conus = ds.sel(lon=slice(-130,-60), lat=slice(50,20))
We need to tell hvplot which coordinates to use as axes, and geo=True
says that these are geographic (lon,lat) coordinates
var = 'u-component_of_wind_height_above_ground'
forecast = ds_conus[var].hvplot(x='lon', y='lat', geo=True, coastline=True, rasterize=True)
forecast
Add State outlines
import geoviews.feature as gvf
from geoviews import opts
forecast * gvf.states(fill_alpha=0)
import panel as pn
import cartopy.crs as ccrs
crs = ccrs.Orthographic(central_longitude=-70, central_latitude=30)
import datetime
now = datetime.datetime.utcnow()
Select from now to furthest forecast, and specify a selection widget for time values
viz = ds[var].sel(time=slice(now,None))[:,:].hvplot(x='lon', y='lat',
cmap='rainbow', rasterize=True, projection=crs, coastline=True,
title='GFS Explorer', hover=False)
viz = pn.panel(viz, widgets={'time': pn.widgets.Select} )
pn.Column(viz).servable('GFS Explorer')
Specify an animation widget ("scrubber") for time values
viz = ds[var].sel(time=slice(now,None))[:,:].hvplot(x='lon', y='lat',
cmap='rainbow', rasterize=True, projection=crs, coastline=True, hover=False,
widget_type='scrubber', title='GFS Explorer', widget_location='bottom')
pn.Column(viz).servable('GFS Explorer')
Display the time value closest to current time (time=now)
viz = ds[var].sel(time=now, method='nearest')[:,:].hvplot(x='lon', y='lat',
cmap='rainbow', rasterize=True, projection=crs, coastline=True,
title='GFS Explorer', hover=False)
viz = pn.panel(viz, widgets={'time': pn.widgets.Select} )
pn.Column(viz).servable('GFS Explorer')