<jupyter_start><jupyter_text>Explore the Global Forecast System (GFS) with hvplot [Hvplot](https://hvplot.holoviz.org) is part of the [HoloViz tool suite](holoviz.org) 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!<jupyter_code>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)<jupyter_output><empty_output><jupyter_text>hvplot likes longitudes in the range [-180,180], not [0, 360]<jupyter_code>ds = ds.assign_coords(lon=(((ds.lon + 180) % 360) - 180)).sortby('lon')
ds['u-component_of_wind_height_above_ground']<jupyter_output><empty_output><jupyter_text>Visualize the GFS in the CONUS region in geographic coordinates 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.<jupyter_code>ds_conus = ds.sel(lon=slice(-130,-60), lat=slice(50,20))<jupyter_output><empty_output><jupyter_text>We need to tell hvplot which coordinates to use as axes, and `geo=True` says that these are geographic (lon,lat) coordinates<jupyter_code>var = 'u-component_of_wind_height_above_ground'
forecast = ds_conus[var].hvplot(x='lon', y='lat', geo=True, coastline=True, rasterize=True)
forecast<jupyter_output><empty_output><jupyter_text>Add State outlines<jupyter_code>import geoviews.feature as gvf
from geoviews import opts
forecast * gvf.states(fill_alpha=0)<jupyter_output><empty_output><jupyter_text>Visualize the GFS globally using an Orthographic projection and a Panel layout<jupyter_code>import panel as pn
import cartopy.crs as ccrs
crs = ccrs.Orthographic(central_longitude=-70, central_latitude=30)
import datetime
now = datetime.datetime.utcnow()<jupyter_output><empty_output><jupyter_text>Select from now to furthest forecast, and specify a selection widget for time values<jupyter_code>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')<jupyter_output><empty_output><jupyter_text>Specify an animation widget ("scrubber") for time values<jupyter_code>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')<jupyter_output><empty_output><jupyter_text>Display the time value closest to current time (time=now)<jupyter_code>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')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12314225053078556, 'fraction_numerical': 0.013345465574764938, 'mean_word_length': 5.772073921971253, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '316369', 'license': 'MIT', 'n_tokens_mistral': 1188, 'n_tokens_neox': 1118, 'n_words': 257, 'path': 'GFS/hvplot_gfs_demo.ipynb', 'repo_name': 'rsignell-usgs/qhub-notebooks', 'size': '3297'}