Dynamic Visualization#

Read in Datasets#

  1. WAS 2020 Data

  2. Subset of an AVIRIS image

import pandas as pd
import numpy as np
import rasterio
# Import example WAS data
was_2020_filepath = "./data/SARP 2020 final.xlsx"
was_2020 = pd.read_excel(was_2020_filepath, "INPUT", skipfooter=7)
# Clean temperature column
was_2020['Temp. Celsius'] = pd.to_numeric(was_2020['Temp. Celsius'], errors='coerce')
was_2020['Temp. Celsius'].mask(was_2020['Temp. Celsius'] > 100, np.nan, inplace=True)
/tmp/ipykernel_799/4192276673.py:6: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.
The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.

For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.


  was_2020['Temp. Celsius'].mask(was_2020['Temp. Celsius'] > 100, np.nan, inplace=True)
# Import example AVIRIS data
with rasterio.open('./data/subset_f180628t01p00r02_corr_v1k1_img') as src:
    metadata = src.meta
    bands = src.read()

Interactive Plotting with bokeh#

conda install -c conda-forge -n lessons bokeh

Quick take: Designed for the web, so not always going to look good enough for publications. But the interactivity is great for exploring your data.

Example 1: Line (AVIRIS)#

Step 1: Organize our data#

For our example let’s make a spectral plot for a pixel of our AVIRIS image.

import numpy as np
y = bands[:, 100, 150]  # z profile
x = np.arange(1, 225)  # band number

Step 2: Make our graph#

If you run the following cell of code the plot will show up directly in your jupyter notebook. Choosing not to run this code will open plots in a new tab.

from bokeh.io import output_notebook
output_notebook()
Loading BokehJS ...
from bokeh.plotting import figure, show
# create a new plot with a title and axis labels
p = figure()
p.line(x, y)  # add a line renderer with legend and line thickness to the plot
show(p)

Customizing the graph#

There are a variety of additional arguments we can use to customize the graph.

Tooltips#

The default hovertext includes:

  • index - the index number of your original array of data

  • data - the data values

  • screen - the pixel number of your computer screen that the line is rendered on (I just ignore this one)

You are able to change the default hovertext.

# create a new plot with a title and axis labels
p = figure(title="Spectral Plot", x_axis_label='band number', y_axis_label='reflectance')
# add a line renderer with legend and line thickness to the plot
p.line(x, y, legend_label="pixel100_150", line_width=2)
show(p)

Adding multiple lines#

# get the z profiles
y1 = bands[:, 100, 150]
y2 = bands[:, 145, 302]
y3 = bands[:, 100, 350]

# set unreal numbers to nan 
# (don't do this in your own data unless you've confirmed that it makes scientific sense)
y2[np.where(y2>1)] = np.nan
y3[np.where(y3>1)] = np.nan
# create a new plot with a title, axis labels, and plot tools
p = figure(title="Spectral Plot", x_axis_label='band number', y_axis_label='reflectance', 
           tools='pan,box_zoom,crosshair,hover,wheel_zoom,reset,save')

# add lines
p.line(x, y1, legend_label="pixel100_150", line_color="blue", line_width=2)
p.line(x, y2, legend_label="pixel145_302", line_color="red", line_width=2)
p.line(x, y3, legend_label="pixel100_350", line_color="green", line_width=2)

# show the results
show(p)

Example 2: Scatter plot (WAS data)#

Tooltips#

The default hovertext includes:

  • index - the index number of your original array of data

  • data - the data values

  • screen - the pixel number of your computer screen that the line is rendered on (I just ignore this one)

You are able to change the default hovertext but I had a rough time getting it to work with the default WAS data because bokeh struggles with spaces and parenthesis in column names.

from bokeh.plotting import ColumnDataSource
# create a new plot with a title, axis labels, and plot tools
p = figure(title="CO vs. Temp.", x_axis_label="Temp", y_axis_label="pollutants", 
           tools='pan,box_zoom,crosshair,hover,wheel_zoom,reset,save')

# add data points
p.scatter(was_2020['Temp. Celsius'], was_2020['CO (ppbv)'], alpha=0.4, color='red')
p.scatter(was_2020['Temp. Celsius'], was_2020['CO2 (ppmv)'], alpha=0.4)

# show the results
show(p)

Peruse for futher interactivity examples: https://malouche.github.io/notebooks/scatter_bokeh2.html

Example 3: 3D viz with plotly (WAS data)#

Plotly is a library that does interactive visualization in 2D like bokeh, but it also has some libraries fo 3D viz. The biggest downside I’ve found with plotly is that it doesn’t easily do basemaps handle polygons of data, but it is really nice for 3D data viewing.

conda install -c conda-forge plotly_express -n lessons

Example with WAS#

import numpy as np
import pandas as pd
import plotly.express as px
# Read in WAS data
was_data = pd.read_excel('./data/Copy of WAS merge.xlsx', 'original', nrows=189)
# Remove nans
was_data = was_data.replace(-999999, np.NaN)
fig = px.scatter_3d(was_data, x=' Longitude_YANG', y=' Latitude_YANG', z=' Radar_Altitude_YANG',
              color=' O3_CL_RYERSON')
fig.show()