Accessing USGS data

This notebook does the following:

  • Load a single USGS point

  • Look at the metadata

  • Get multiple radiation datasets

  • Calculate albedo from the datasets

  • Plot the albedo evolution

[1]:
# imports
from datetime import datetime
import pandas as pd
import numpy as np

from metloom.pointdata import USGSPointData

# For rendering in readthedocs
import plotly.offline as py
py.init_notebook_mode(connected=True)
[2]:
# Define a point known to have solar measurements
pt = USGSPointData("395709105582701", "Blue Ridge Meteorological Station NR Fraser")

# start data and end date
start_date = datetime(2024, 1, 1)
end_date = datetime(2024, 7, 1)
# Define a list of variables we want
incoming_sw = pt.ALLOWED_VARIABLES.DOWNSHORTWAVE
outgoing_sw = pt.ALLOWED_VARIABLES.UPSHORTWAVE
depth = pt.ALLOWED_VARIABLES.SNOWDEPTH
variables = [incoming_sw, outgoing_sw, depth]


[3]:
# LETS GET THAT DATA
df = pt.get_hourly_data(start_date, end_date, variables)
df.head(10)
/home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages/metloom/pointdata/usgs.py:216: FutureWarning:

In a future version of pandas, parsing datetimes with mixed time zones will raise an error unless `utc=True`. Please specify `utc=True` to opt in to the new behaviour and silence this warning. To create a `Series` with mixed offsets and `object` dtype, please use `apply` and `datetime.datetime.strptime`

/home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages/metloom/pointdata/usgs.py:216: FutureWarning:

In a future version of pandas, parsing datetimes with mixed time zones will raise an error unless `utc=True`. Please specify `utc=True` to opt in to the new behaviour and silence this warning. To create a `Series` with mixed offsets and `object` dtype, please use `apply` and `datetime.datetime.strptime`

/home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages/metloom/pointdata/usgs.py:216: FutureWarning:

In a future version of pandas, parsing datetimes with mixed time zones will raise an error unless `utc=True`. Please specify `utc=True` to opt in to the new behaviour and silence this warning. To create a `Series` with mixed offsets and `object` dtype, please use `apply` and `datetime.datetime.strptime`

[3]:
geometry DOWNWARD SHORTWAVE RADIATION DOWNWARD SHORTWAVE RADIATION_units UPWARD SHORTWAVE RADIATION UPWARD SHORTWAVE RADIATION_units SNOWDEPTH SNOWDEPTH_units datasource
datetime site
2024-01-01 07:00:00+00:00 395709105582701 POINT Z (-105.97408 39.95258 10657) -5.64 W/m2 -0.021 W/m2 0.616 m USGS
2024-01-01 08:00:00+00:00 395709105582701 POINT Z (-105.97408 39.95258 10657) -9.91 W/m2 -0.040 W/m2 0.620 m USGS
2024-01-01 09:00:00+00:00 395709105582701 POINT Z (-105.97408 39.95258 10657) -10.80 W/m2 -0.039 W/m2 0.618 m USGS
2024-01-01 10:00:00+00:00 395709105582701 POINT Z (-105.97408 39.95258 10657) -10.30 W/m2 -0.041 W/m2 0.619 m USGS
2024-01-01 11:00:00+00:00 395709105582701 POINT Z (-105.97408 39.95258 10657) -9.89 W/m2 -0.041 W/m2 0.620 m USGS
2024-01-01 12:00:00+00:00 395709105582701 POINT Z (-105.97408 39.95258 10657) -10.00 W/m2 -0.041 W/m2 0.618 m USGS
2024-01-01 13:00:00+00:00 395709105582701 POINT Z (-105.97408 39.95258 10657) -9.92 W/m2 -0.042 W/m2 0.619 m USGS
2024-01-01 14:00:00+00:00 395709105582701 POINT Z (-105.97408 39.95258 10657) -9.87 W/m2 -0.041 W/m2 0.618 m USGS
2024-01-01 15:00:00+00:00 395709105582701 POINT Z (-105.97408 39.95258 10657) -1.92 W/m2 3.020 W/m2 0.616 m USGS
2024-01-01 16:00:00+00:00 395709105582701 POINT Z (-105.97408 39.95258 10657) 122.00 W/m2 55.000 W/m2 0.614 m USGS
[4]:
# Check out this data!
df = df.reset_index().set_index("datetime")
var_names = [v.name for v in variables]

# Sample to just the vars
df_rad = df.loc[:, var_names]

df_rad.loc[:, [incoming_sw.name, outgoing_sw.name]].plot()


[4]:
<Axes: xlabel='datetime'>
../_images/gallery_usgs_dataaccess_example_4_1.png
[5]:
# Let's get the data in a more usable state
sw_thresh = 10

# mask the SW to decent values
df_rad[incoming_sw.name] = df_rad[incoming_sw.name].mask(df_rad[incoming_sw.name] < sw_thresh, np.nan)
df_rad[outgoing_sw.name] = df_rad[outgoing_sw.name].mask(df_rad[outgoing_sw.name] < sw_thresh, np.nan)

# Resample to daily, based on mean values
df_rad = df_rad.resample("D").mean()

# Plot again
df_rad.loc[:, [incoming_sw.name, outgoing_sw.name]].plot()

[5]:
<Axes: xlabel='datetime'>
../_images/gallery_usgs_dataaccess_example_5_1.png

Now we can think Albedo

The daily data plot looks much better. Now we can start to think about albedo. We can use the SW to calcaulate albedo next

[6]:
# Calculate albedo
albedo_var = "ALBEDO"
df_rad[albedo_var] = df_rad[outgoing_sw.name] / df_rad[incoming_sw.name]
df_rad[albedo_var] = df_rad[albedo_var].mask(df_rad[albedo_var] < 0.1, np.nan)
df_rad[albedo_var] = df_rad[albedo_var].mask(df_rad[albedo_var] > 1, np.nan)
df_rad[albedo_var].plot()
[6]:
<Axes: xlabel='datetime'>
../_images/gallery_usgs_dataaccess_example_7_1.png

Better plotting

Awesome - now we have albedo. We haven’t used snowdepth yet, so let’s create a better plot that shows how the two relate

[7]:
# Get plotly for a nicer plot
# !pip install plotly
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
[8]:
# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])

# Add traces
fig.add_trace(
    go.Scatter(x=df_rad.index, y=df_rad[albedo_var], name=albedo_var),
    secondary_y=False,
)

fig.add_trace(
    go.Scatter(
        x=df_rad.index, y=df_rad[depth.name].diff(), name=f"{depth.name} signal", mode="lines+markers"
    ), secondary_y=True,
)

fig.add_trace(
    go.Scatter(
        x=df_rad.index, y=df_rad[depth.name], name=f"{depth.name}", opacity=0.3,
    ), secondary_y=True,
)

fig.update_layout(
    # template='plotly_dark',
    title=f'{pt.name}',
    xaxis=dict(title='Date'),
    yaxis=dict(
        title=f'Unitless',
        titlefont=dict(color='blue'),
        tickfont=dict(color='blue'),
        tickvals=[.25, .5, .75, 1.0],
        range=[.25, 1]
    ),
    yaxis2=dict(
        title=f'[m]',
        titlefont=dict(color='red'),
        tickfont=dict(color='red'), overlaying='y', side='right'
    )
)

# Show the plot
fig.show()

Summary

  • We started with a point that we knew had shortwave measurements.

  • Next, we pulled all the necessary data, cleaned it, and resampled to daily.

  • We calculated albedo, and plotted it to see how the snow

[ ]: