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.
Try out https://coming-soon-near-you.streamlit.app/. I'm very happy with the interface here.
Exploratory notebooks are under notebooks/exploratory/ and are not treated as stable public entrypoints.
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.get_observation_rows(...): project/place/date-scoped observation rows for exploratory analyses.annotate_taxon_nativity(...): add Virginia-or-place nativity labels to observation/taxon tables.summarize_time_series(...): period-based counts and summary metrics for observation dataframes.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,
)
obs = get_observation_rows(
project_id="virginia-physiographic-regions-piedmont",
d1="2024-01-01",
per_page=100,
max_pages=5,
)
monthly_obs = summarize_time_series(obs, date_col="observed_on", freq="M")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.
The default API version is v1. You can trial v2 in two ways:
- Environment default for the process:
set INAT_API_VERSION=v2
uv run --extra dev pytest -q- Per-call override in helper functions:
from helpers import coming_soon, get_park_data, get_observation_rows
df = coming_soon("birds", loc=(37.66, -77.88, 25), api_version="v2")
parks = get_park_data((37.66, -77.88, 5), "plants", limit=20, api_version="v2")
obs = get_observation_rows(project_id="some-project", per_page=50, max_pages=2, api_version="v2")Notes:
- Keep tests mocked for API behavior; avoid relying on live API responses.
- Roll out v2 incrementally and compare output schema where notebook/dataframe stability matters.
Exploratory notebook prototypes:
notebooks/exploratory/va_piedmont_native_phenology.ipynb: native Lepidoptera prevalence and life-stage exploration for the Virginia Piedmont project.notebooks/exploratory/va_piedmont_identification_timing.ipynb: observation volume, first non-owner identification volume, and delay summaries over time.
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.