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)
../_images/gallery_2_where_are_the_points_11_1.png

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?

[ ]: