Small iNaturalist helper workflows for exploration and reliability analysis.
This repository currently has two main tracks:
- Observation discovery utilities in
helpers.py(for example, coming-soon seasonal species queries). - Identification reliability analysis in
reliability.py(proposal-level outcomes and taxon-level summaries).
Run these from the repository root:
uv venv
uv sync --extra dev
uv run --extra dev pytest -qNotes:
- The project uses
uvfor environment and dependency management. pytestlives in thedevextra, so include--extra devfor test commands.
Public Binder scope: coming_soon_near_you.ipynb.
Exploratory notebooks are under notebooks/exploratory/ and are not treated as stable public entrypoints.
- Binder (JupyterLab): https://mybinder.org/v2/gh/svshepherd/pynat/main?urlpath=lab/tree/coming_soon_near_you.ipynb
- Binder (classic fallback): https://mybinder.org/v2/gh/svshepherd/pynat/main?filepath=coming_soon_near_you.ipynb
- Voila render (code hidden): https://mybinder.org/v2/gh/svshepherd/pynat/main?urlpath=voila/render/coming_soon_near_you.ipynb
Binder tips:
- Cold starts can take a few minutes.
- For reproducible demos, replace
mainin URLs with a release tag. - Start with low-traffic settings (
per_page=25,max_pages=2,fetch_images=False).
Never commit API tokens or key files.
Runtime key lookup in helpers.load_api_key() uses this order:
- Environment variables (
INAT_TOKEN,INAT_API_KEY,PYINAT_API_KEY,INAT_KEY) - System keyring (if installed)
- Legacy dill fallback file (
pyinaturalistkey.pkd)
Session-only token example:
import os, getpass
token = getpass.getpass("Paste iNaturalist token (optional): ").strip()
if token:
os.environ["INAT_TOKEN"] = tokenImplemented in helpers.py:
coming_soon(...): seasonal/common taxa with optional normalization and nativity filtering.get_park_data(...): park-centered species ranking by relative frequency.coming_soon_notebook(...): notebook UI wrapper used by the public notebook.get_mine(...): fetch and print recent observations for a user.
Quick example:
from helpers import coming_soon, get_park_data
df = coming_soon(
"birds",
loc=(37.6669, -77.8883, 25),
per_page=25,
max_pages=2,
fetch_images=False,
)
parks = get_park_data(
(37.6669, -77.8883, 5),
"plants",
limit=20,
per_page=25,
max_pages=2,
)Fallback behavior:
- When
pyinaturalistis unavailable, helper queries fall back to direct REST calls. - Fallback calls are bounded by
per_pageandmax_pagesto avoid unbounded network fetches.
reliability.py contains an Analyzer class for taxon-scoped reliability analysis.
Primary workflow:
- Use
Analyzer.assess_taxon(...)(or CLIassess-taxon) for one user and one target taxon. - The method builds proposal outcomes and taxonomic overlap summaries in one pass.
Deprecated workflow:
- Legacy cache-first
ingest/summarizecommands are deprecated and kept only for compatibility. - New usage should prefer taxon-scoped assessment.
Minimal programmatic example:
from reliability import Analyzer
an = Analyzer(cache_dir="data")
out = an.assess_taxon(
user_login="your_login",
taxon_id=130953,
start="2024-01-01",
end="2025-12-31",
print_report=False,
)
out["taxon_reliability"].head()Run the test suite with:
uv run --extra dev pytest -qCurrent tests cover helper utilities and core reliability behavior paths.