Interactive visualization of NYSM data: Geoviews

Overview:

  1. Create an interactive visualization of NYSM data using the Holoviz ecosystem

Imports

from datetime import datetime
import pandas as pd
import geoviews as gv
import geoviews.feature as gf
from geoviews import opts
import geoviews.tile_sources as gts
from cartopy import crs as ccrs

Create an interactive visualization of NYSM data using the Holoviz ecosystem

Holoviz is a suite of open-source Python libraries designed for interactive data analysis and visualization via the browser (including the Jupyter notebook). In this notebook, we will use the GeoViews package, which is part of Holoviz.

Another part of the Holoviz ecosystem is bokeh. Bokeh leverages Javascript in order to accomplish interactivity via the browser. GeoViews makes available Bokeh as well as Matplotlib via an extenstion.

gv.extension('bokeh', 'matplotlib')

Use Pandas to read in the file containing the most recent NYSM data. Since this file has latitude and longitude, we can pass the dataframe directly to GeoViews (i.e. no need to use Geopandas).

# First define the format and then define the function
timeFormat = "%Y-%m-%d %H:%M:%S"
# This function will iterate over each string in a 1-d array
# and use Pandas' implementation of strptime to convert the string into a datetime object.
parseTime = lambda x: datetime.strptime(x, timeFormat)

df = pd.read_csv('https://www.atmos.albany.edu/products/nysm/nysm_latest.csv',parse_dates=['time'], date_parser=parseTime)
/tmp/ipykernel_975078/163799367.py:7: FutureWarning: The argument 'date_parser' is deprecated and will be removed in a future version. Please use 'date_format' instead, or read your data in as 'object' dtype and then call 'to_datetime'.
  df = pd.read_csv('https://www.atmos.albany.edu/products/nysm/nysm_latest.csv',parse_dates=['time'], date_parser=parseTime)
df.columns
Index(['station', 'time', 'temp_2m [degC]', 'temp_9m [degC]',
       'relative_humidity [percent]', 'precip_incremental [mm]',
       'precip_local [mm]', 'precip_max_intensity [mm/min]',
       'avg_wind_speed_prop [m/s]', 'max_wind_speed_prop [m/s]',
       'wind_speed_stddev_prop [m/s]', 'wind_direction_prop [degrees]',
       'wind_direction_stddev_prop [degrees]', 'avg_wind_speed_sonic [m/s]',
       'max_wind_speed_sonic [m/s]', 'wind_speed_stddev_sonic [m/s]',
       'wind_direction_sonic [degrees]',
       'wind_direction_stddev_sonic [degrees]', 'solar_insolation [W/m^2]',
       'station_pressure [mbar]', 'snow_depth [cm]', 'frozen_soil_05cm [bit]',
       'frozen_soil_25cm [bit]', 'frozen_soil_50cm [bit]',
       'soil_temp_05cm [degC]', 'soil_temp_25cm [degC]',
       'soil_temp_50cm [degC]', 'soil_moisture_05cm [m^3/m^3]',
       'soil_moisture_25cm [m^3/m^3]', 'soil_moisture_50cm [m^3/m^3]', 'lat',
       'lon', 'elevation', 'name'],
      dtype='object')

First, we wlll create a set of GeoViews Points objects. We pass it three arguments:

  1. The Pandas dataframe

  2. A list containing the lons and lats

  3. A list containing the columns we want to include

df_points = gv.Points(df, ['lon','lat'],['name','temp_2m [degC]','station_pressure [mbar]','max_wind_speed_sonic [m/s]'])

Visualize the GeoViews Points object

df_points

Notice that the x and y-axes correspond to the range of lons and lats in the dataframe. Also notice the Toolbar to the right of the plot. You can mouse over each tool to see its function. By default, it is in Pan mode … click and drag to move around.

Next, activate the Box Zoom tool (the single magnifying glass). Click and drag from upper left to lower right to create a box. The plot will automatically adjust to the new zoomed-in view.

If you have a mouse, you can also try the Wheel Zoom tool, which is just below the Box Zoom tool.

The bottom tool resets the plot to the full domain.

Geo-reference the image via a background raster image.

The Holoviz suite uses the * character as an operator to add layers to the same plot. Here, we first specify the Open Street Maps tile source. Then, we add our Points dataframe to it. We also specify options that accomplish the following:

  1. Specify the width and height of the plot

  2. Set the size of the points

  3. Color each point by a variable: in this case, 2 m temperature in Celsius

  4. Add a colorbar

  5. Add the hover tool to the Toolbar

(gv.tile_sources.OSM * df_points).opts(
    opts.Points(frame_width=800, frame_height=600, size=8, color='temp_2m [degC]',cmap='coolwarm',colorbar=True,tools=['hover']))

Note that hover tool is active and appears as the tool icon just below the reset tool. Mouse over any of the points and you will see a readout of the data from all the columns that we included in the creation of the df_points GeoViews object.

Next, let’s plot a map that instead of the point locations, outputs the values of a particular column from the dataset. To do this, we create a GeoViews Labels object. It takes arguments similar to Points.

df_labels = gv.Labels(df, ['lon','lat'],['temp_2m [degC]'])

Plot just the labels.

df_labels

Now layer on the background map tile, as we did for Points. Specify the color and size of the text labels.

figure = (gv.tile_sources.OSM * df_labels).opts(
    opts.Labels(frame_height=800,frame_width=800,text_color='purple',text_font_size='10pt'))
figure

What basemaps do we have available “built-in” in Geoviews?

gv.Layout([ts.relabel(name) for name, ts in
    gts.tile_sources.items()]).opts(
        'WMTS', xaxis=None, yaxis=None, width=225, height=225).cols(6)
NOTE: if you are running this via Jupyterhub, some of the maps above will be *blank*. This is related to the fact that while the notebook is being displayed on your local computing device, the request to the tile server is coming from the Jupyterhub server, whose IP address is different from your local device. Some tile servers are configured in a way that forbids this type of web request, in order to guard against cross-site request forgery. Future releases of Jupyterhub should have some methods to deal with this issue.

In the next notebook, we will use GeoViews to interactively browse worldwide METAR data.