Searching for Stations¶
Where in the world are these stations?¶
One common frustration is finding relevant stations for analysis and validation
What are some methods you have used to identify stations that fit your research?
[1]:
# Imports
from datetime import datetime
import pandas as pd
import geopandas as gpd
from pathlib import Path
from metloom.pointdata import SnotelPointData, CDECPointData, MesowestPointData
[2]:
try:
import folium
except Exception as e:
!pip install folium
try:
import mapclassify
except Exception as e:
!pip install mapclassify
Collecting folium
Downloading folium-0.20.0-py2.py3-none-any.whl.metadata (4.2 kB)
Collecting branca>=0.6.0 (from folium)
Downloading branca-0.8.2-py3-none-any.whl.metadata (1.7 kB)
Requirement already satisfied: jinja2>=2.9 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from folium) (3.1.6)
Requirement already satisfied: numpy in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from folium) (2.2.6)
Requirement already satisfied: requests in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from folium) (2.33.1)
Requirement already satisfied: xyzservices in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from folium) (2026.3.0)
Requirement already satisfied: MarkupSafe>=2.0 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from jinja2>=2.9->folium) (2.0.1)
Requirement already satisfied: charset_normalizer<4,>=2 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from requests->folium) (3.4.7)
Requirement already satisfied: idna<4,>=2.5 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from requests->folium) (3.11)
Requirement already satisfied: urllib3<3,>=1.26 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from requests->folium) (2.6.3)
Requirement already satisfied: certifi>=2023.5.7 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from requests->folium) (2026.2.25)
Downloading folium-0.20.0-py2.py3-none-any.whl (113 kB)
Downloading branca-0.8.2-py3-none-any.whl (26 kB)
Installing collected packages: branca, folium
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2/2 [folium]
Successfully installed branca-0.8.2 folium-0.20.0
Collecting mapclassify
Downloading mapclassify-2.8.1-py3-none-any.whl.metadata (2.8 kB)
Collecting networkx>=2.7 (from mapclassify)
Downloading networkx-3.4.2-py3-none-any.whl.metadata (6.3 kB)
Requirement already satisfied: numpy>=1.23 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from mapclassify) (2.2.6)
Requirement already satisfied: pandas!=1.5.0,>=1.4 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from mapclassify) (2.3.3)
Collecting scikit-learn>=1.0 (from mapclassify)
Downloading scikit_learn-1.7.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (11 kB)
Collecting scipy>=1.8 (from mapclassify)
Downloading scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (61 kB)
Requirement already satisfied: python-dateutil>=2.8.2 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from pandas!=1.5.0,>=1.4->mapclassify) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from pandas!=1.5.0,>=1.4->mapclassify) (2026.1.post1)
Requirement already satisfied: tzdata>=2022.7 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from pandas!=1.5.0,>=1.4->mapclassify) (2026.1)
Requirement already satisfied: six>=1.5 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from python-dateutil>=2.8.2->pandas!=1.5.0,>=1.4->mapclassify) (1.17.0)
Requirement already satisfied: joblib>=1.2.0 in /home/docs/checkouts/readthedocs.org/user_builds/metloom/envs/stable/lib/python3.10/site-packages (from scikit-learn>=1.0->mapclassify) (1.5.3)
Collecting threadpoolctl>=3.1.0 (from scikit-learn>=1.0->mapclassify)
Downloading threadpoolctl-3.6.0-py3-none-any.whl.metadata (13 kB)
Downloading mapclassify-2.8.1-py3-none-any.whl (59 kB)
Downloading networkx-3.4.2-py3-none-any.whl (1.7 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.7/1.7 MB 14.0 MB/s 0:00:00
Downloading scikit_learn-1.7.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (9.7 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 9.7/9.7 MB 38.2 MB/s 0:00:00
Downloading scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (37.7 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 37.7/37.7 MB 118.5 MB/s 0:00:00
Downloading threadpoolctl-3.6.0-py3-none-any.whl (18 kB)
Installing collected packages: threadpoolctl, scipy, networkx, scikit-learn, mapclassify
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5/5 [mapclassify]
Successfully installed mapclassify-2.8.1 networkx-3.4.2 scikit-learn-1.7.2 scipy-1.15.3 threadpoolctl-3.6.0
Search for points in an area¶
[3]:
# Find your area
sf_path = Path("./data/outline.shp").expanduser()
sf = gpd.read_file(str(sf_path))
sf["name"] = ["Our outline"]
variables = [SnotelPointData.ALLOWED_VARIABLES.SNOWDEPTH]
[4]:
# What does the area look like
sf.explore()
[4]:
Make this Notebook Trusted to load map: File -> Trust Notebook
[5]:
# Find all the points in the area for our variables
points = SnotelPointData.points_from_geometry(sf, variables)
print(len(points))
# This is an iterator
print(type(points))
# It contains the points in a `points` attribute
print(points.points)
2
<class 'metloom.pointdata.base.PointDataCollection'>
[SnotelPointData('637:ID:SNTL', 'Mores Creek Summit'), SnotelPointData('978:ID:SNTL', 'Bogus Basin')]
What if I want a station nearby?¶
[6]:
# buffer - add buffer (in degrees) to extents
print(SnotelPointData.points_from_geometry(sf, variables, buffer=0.5).points)
# within_geometry - doesn't do anything since our geometry is already a square
print(SnotelPointData.points_from_geometry(sf, variables, within_geometry=False).points)
[SnotelPointData('978:ID:SNTL', 'Bogus Basin'), SnotelPointData('637:ID:SNTL', 'Mores Creek Summit')]
[SnotelPointData('637:ID:SNTL', 'Mores Creek Summit'), SnotelPointData('978:ID:SNTL', 'Bogus Basin')]
[7]:
# imports for a static map
try:
import contextily as ctx
except Exception:
!pip install contextily
import contextily as ctx
import matplotlib.pyplot as plt
from shapely.geometry import Point
[8]:
# Make a static plot of the points
# turn that iterator into a dataframe
df = points.to_dataframe()
# look at what is in the dataframe
df.head(10)
def remove_z(geom):
if geom.is_empty:
return geom
else:
return Point(geom.x, geom.y)
df.geometry = df.geometry.apply(remove_z)
df = df.set_crs("EPSG:4326")
print(df)
ax = sf.to_crs("EPSG:4326").plot(alpha=0.1)
ax = df.plot(ax=ax, color="red")
ctx.add_basemap(
ax,
# source=ctx.providers.OpenStreetMap.Mapnik,
source=ctx.providers.USGS.USTopo,
crs=df.crs,
# zoom=5
)
name id datasource geometry
0 Mores Creek Summit 637:ID:SNTL NRCS POINT (-115.66588 43.932)
1 Bogus Basin 978:ID:SNTL NRCS POINT (-116.09685 43.76377)
Our plot could be more interesting¶
[9]:
# plot the shapefile
m = sf.explore(
tooltip=False, color="grey", highlight=False, style_kwds={"opacity": 0.2}, popup=["name"]
)
# plot the points on top of the shapefile
df.explore(m=m, tooltip=["name", "id"], color="red", marker_kwds={"radius":4})
[9]:
Make this Notebook Trusted to load map: File -> Trust Notebook
Extra¶
How would we get the daily data for the first point from points?
[ ]: