API reference¶
Auto-generated from docstrings.
Client¶
- class sjvair.client.SJVAirClient(base_url: str | None = None, timeout: int | None = None, max_retries: int | None = None, max_connections: int | None = None, api_key: str | None = None)¶
HTTP client for the SJVAir API.
All resource objects (
monitors,regions,calenviroscreen5,calenviroscreen4,ceidars,hms,pesticides,calheatscore,forecasts,tempo) are attached as attributes and share this client’s session, retry logic, and cooldown gate.- Parameters:
base_url – API base URL. Defaults to
SJVAIR_BASE_URLenv var or the production URL.timeout – Request timeout in seconds. Defaults to
SJVAIR_TIMEOUTenv var or 30.max_retries – Number of retries on 5xx / 429 responses. Defaults to 5.
max_connections – Maximum concurrent requests (semaphore). Defaults to 4.
api_key – Bearer token for authenticated endpoints. Defaults to
SJVAIR_API_KEYenv var.
Can be used as a context manager to ensure the underlying session is closed:
with SJVAirClient() as client: monitors = list(client.monitors.list())
- get(path: str, params: dict[str, Any] | None = None) Any¶
GET
pathrelative tobase_url, with retry and cooldown.Retries on 5xx and transient network errors (connection/timeout) up to
max_retriestimes with exponential backoff. On 429, triggers a shared cooldown that blocks all threads until the wait expires. RaisesNotFoundon 404,RateLimitedafter exhausting retries on 429,ServerErrorafter exhausting retries on 5xx or a persistent network error, andClientErroron other non-retryable 4xx responses.
Resources¶
- class sjvair.resources.monitors.MonitorsResource(client: SJVAirClient)¶
Access air quality monitor data.
Available on
SJVAirClient.monitors.- list(**params: Any) Iterator[dict[str, Any]]¶
Iterate all monitors, optionally filtered by
region_id,is_sjvair, etc.
- get(monitor_id: str) dict[str, Any]¶
Get a single monitor by ID.
- meta() dict[str, Any]¶
Return field metadata for monitor entries (field names, units, etc.).
- entries(monitor_id: str, entry_type: str, **params: Any) Iterator[dict[str, Any]]¶
Iterate paginated entries for one monitor and entry type (e.g.
'PM2.5').
- export(monitor_id: str, start_date: str, end_date: str, scope: str = 'resolved') Iterator[dict[str, Any]]¶
Bulk-export entries for a monitor in a single request.
The server enforces a 180-day maximum window per call. Use
ExportEngineto download longer ranges automatically by splitting into chunks.- Parameters:
monitor_id – Monitor UUID.
start_date – ISO 8601 date string (
YYYY-MM-DD).end_date – ISO 8601 date string (
YYYY-MM-DD).scope –
'resolved'(calibrated) or'expanded'(raw + derived fields).
- summaries(monitor_id: str, entry_type: str, resolution: str, start_date: str, end_date: str) Iterator[dict[str, Any]]¶
Iterate aggregated summaries for a monitor across the given date range.
- Parameters:
monitor_id – Monitor UUID.
entry_type – Sensor field (e.g.
'PM2.5').resolution – One of
'hourly','daily','monthly','quarterly','seasonal','yearly'.start_date – ISO 8601 date string.
end_date – ISO 8601 date string.
- closest(entry_type: str, lat: float, lon: float, **params: Any) list[dict[str, Any]]¶
Return up to 3 nearest active monitors with distance and latest entry.
Pass
deviceto filter by device type (e.g.device='CIMIS').
- current(entry_type: str, **params: Any) Iterator[dict[str, Any]]¶
Iterate all active monitors with their most recent entry for the given type.
Pass
deviceto filter by device type (e.g.device='CIMIS').
- current_at(entry_type: str, timestamp: str, region: list[str] | None = None, bbox: tuple[float, float, float, float] | None = None, **params: Any) Iterator[dict[str, Any]]¶
As
current(), but as-of a historicaltimestamp(ISO 8601).- Parameters:
entry_type – Sensor field (e.g.
'pm25').timestamp – ISO 8601 timestamp to query as-of.
region – One or more region IDs to filter to monitors covered by their boundaries.
bbox –
(west, south, east, north)to filter to monitors within the box.
Pass
deviceto filter by device type (e.g.device='CIMIS').
- class sjvair.resources.regions.RegionsResource(client: SJVAirClient)¶
Access geographic region data (counties, cities, ZIP codes, census tracts).
Available on
SJVAirClient.regions.- list(**params: Any) Iterator[dict[str, Any]]¶
Iterate all regions, optionally filtered by
kind,county, etc.
- get(region_id: str) dict[str, Any]¶
Get a single region by ID.
- search(query: str, **params: Any) list[dict[str, Any]]¶
Search regions by name, returning all high-confidence matches. Pass
type=to scope to a specific region type.
- lookup(query: str, **params: Any) dict[str, Any] | None¶
Resolve a name to the single best-match region. Pass
type=to scope to a specific region type.
- summaries(region_id: str, entry_type: str, resolution: str, start_date: str, end_date: str) Iterator[dict[str, Any]]¶
Iterate aggregated summaries for a region. Same resolution options as
MonitorsResource.summaries().
- class sjvair.resources.calenviroscreen.CalEnviroScreen5Resource(client: SJVAirClient)¶
Access CalEnviroScreen 5.0 census tract cumulative impact scores.
Available on
SJVAirClient.calenviroscreen5.- list(**params: Any) Iterator[dict[str, Any]]¶
Iterate census tract scores.
Single-vintage dataset (2020 census tracts) — no
yearfilter. Filters are applied server-side. Passregion_idto scope to a region,dac_sb535/dac_categoryfor the disadvantaged-community designation, or__gt/__gte/__lt/__ltesuffixes for threshold lookups on any score field.
- get(tract: str) dict[str, Any]¶
Get CalEnviroScreen 5.0 scores for a single census tract (FIPS code).
- class sjvair.resources.calenviroscreen.CalEnviroScreen4Resource(client: SJVAirClient)¶
Access CalEnviroScreen 4.0 census tract cumulative impact scores.
Available on
SJVAirClient.calenviroscreen4.- list(year: int | None = None, **params: Any) Iterator[dict[str, Any]]¶
Iterate census tract scores.
yeardefaults server-side to 2020 if omitted. Filters are applied server-side. Passregion_idto scope to a region,dac_sb535/dac_categoryfor the disadvantaged-community designation, or__gt/__gte/__lt/__ltesuffixes for threshold lookups on any score field (e.g.pollution_p__gte=75).
- get(tract: str, year: int | None = None) dict[str, Any]¶
Get CalEnviroScreen 4.0 scores for a single census tract (FIPS code).
yeardefaults server-side to 2020 if omitted.
- class sjvair.resources.ceidars.CEIDARSResource(client: SJVAirClient)¶
Access CEIDARS (California Emissions Inventory) facility data.
Available on
SJVAirClient.ceidars.- list(**params: Any) Iterator[dict[str, Any]]¶
Iterate all CEIDARS facilities.
- get(facility_id: str) dict[str, Any]¶
Get a single CEIDARS facility by ID.
- years() list[int]¶
Return the list of inventory years available in the dataset.
- class sjvair.resources.hms.HMSResource(client: Any)¶
Access NOAA Hazard Mapping System (HMS) smoke and fire data.
Available on
SJVAirClient.hms. Sub-resources:smoke— smoke plume polygonsfire— fire detection points
- class sjvair.resources.pesticides.PesticidesResource(client: Any)¶
Access California Department of Pesticide Regulation (CDPR) pesticide data.
Available on
SJVAirClient.pesticides. Sub-resources:chemicals— active ingredient lookupcommodities— crop/commodity lookupproducts— registered product lookupuse— pesticide use reportsnotice— pesticide use notices
- region_use(region_id: str, **params: Any) Iterator[dict[str, Any]]¶
Iterate pesticide use reports for a specific region.
- region_notice(region_id: str, **params: Any) Iterator[dict[str, Any]]¶
Iterate pesticide use notices for a specific region.
- region_summary(region_id: str) dict[str, Any]¶
Return an aggregate pesticide use summary for a region.
- class sjvair.resources.calheatscore.CalHeatScoreResource(client: SJVAirClient)¶
Daily ZIP-code-level heat-risk scores (0-4) from CalEPA’s CalHeatScore.
Available on
SJVAirClient.calheatscore.- list(**params: Any) Iterator[dict[str, Any]]¶
Iterate CalHeatScore rows across ZIP codes.
Defaults to today (server-side) if no
datefilter is given. Filters:date/date__gte/date__lte,score/score__gte/score__lte,zipcode,zipcode__in(comma-separated).
- class sjvair.resources.forecasts.ForecastsResource(client: SJVAirClient)¶
SJVAPCD daily air quality forecasts, by SJV county zone.
Available on
SJVAirClient.forecasts.- list(**params: Any) Iterator[dict[str, Any]]¶
Iterate forecasts across zones.
Defaults to current + future forecasts (server-side, forecast_date >= today) if no forecast_date filter is given. Filters: region_id, forecast_date/forecast_date__lt/__lte/__gt/__gte, issued_date/issued_date__lt/__lte/__gt/__gte.
- get(forecast_id: str) dict[str, Any]¶
Get a single forecast record by ID.
- class sjvair.resources.tempo.TempoResource(client: SJVAirClient)¶
NASA TEMPO satellite air-quality data (NO2, O3TOT, HCHO, CLDO4 — hourly gridded column-density measurements).
Available on
SJVAirClient.tempo.- products() list[dict[str, Any]]¶
List TEMPO product metadata: label, units, and legend color stops.
Excludes
cldo4(QA-only, not a toggleable map layer) — it’s still a validproductvalue forgranules()/point()/region().
- granules(product: str, **params: Any) Iterator[dict[str, Any]]¶
Iterate TEMPO granules for one product.
Defaults to today’s granules (America/Los_Angeles, falling back to yesterday if it’s before noon and today’s data isn’t ready) when no
date/timestampfilter is given. Filters:date,timestamp/timestamp__lt/__lte/__gt/__gte,is_final,version/version__iexact.
- latest(product: str) dict[str, Any]¶
Get the single most recent granule for one product.
- point(product: str, latitude: float, longitude: float, start: str | None = None, end: str | None = None) list[dict[str, Any]]¶
Get an hourly point-value series for one product at a coordinate.
start/endare ISO 8601 timestamps; omit both to default to today’s available granules. Max range is 90 days.
Maps¶
Rendering utilities behind sjvair map/sjvair timelapse — requires pip install sjvair[maps] to actually render (importing the module does not).
Standalone static-map rendering for the sjvair map/sjvair timelapse
commands.
Importing this module never requires the maps extra — only calling
render_frame() does, so callers can defer that cost (and the import error,
if the extra isn’t installed) until a map is actually being rendered.
- sjvair.maps.color_for_value(levels: dict[str, Any], value: float) str¶
Pick a marker color for
valuefrom ameta()levels dict.Linearly blends between the matched level and the next one, matching the server’s
LevelSet.get_color().valueis coerced tofloatsince the API serializes some monitors’latest.valueas a JSON string (server-sideDecimalfields aren’t natively JSON-serializable) rather than a number.
- sjvair.maps.shape_for_monitor(monitor: dict[str, Any]) str¶
Marker shape by monitor grade: triangle for regulatory (FEM/FRM) networks, circle for SJVAir low-cost sensors, square for other third-party monitors.
- sjvair.maps.render_frame(monitors: list[dict[str, Any]], levels: dict[str, Any], outlines: list[dict[str, Any]], viewport: tuple[float, float, float, float], timestamp_label: str | None = None, show_legend: bool = True, legend_label: str | None = None, width: int = 1600, height: int = 1200, dpi: int = 100, marker_size: int = 220) bytes¶
Render one map frame to PNG bytes: basemap, region outlines, monitor markers colored by AQI level, and optional legend/timestamp overlays.