Automated spatial analysis and data sync that the two web applications within Utah Division of Emergency Management's (DEM) Utah Natural Hazard Inventory web page.
- Community Explorer - Tool that summarizes natural hazard exposure at four geography levels (State / County / Census Tract / CDP). Scripts read source feature services, compute summaries, and write the results back to the Community Explorer feature services.
- Hazard Explorer — Tool that displays the raw hazard data layers. Scripts pull external sources (UGS WFS, USGS earthquake API, avalanche.org GeoJSON) and republish them as AGOL hosted feature services so the ExB app can consume them (ExB cannot currently read WFS / GeoJSON / public APIs directly).
- Avalanche
- Dam Incident
- Drought
- Earthquake
- Flooding
- Geologic Hazards
- Wildfire
Each script follows the same ETL pattern:
CONFIG -> EXTRACT -> TRANSFORM -> LOAD -> CLEANUP
- Extract — Pull source data and geography layers into an in-memory workspace, project everything to UTM 12N.
- Transform — Run spatial analysis (intersections, zonal statistics, presence checks, etc.) to produce a
{GEOID: value}dictionary for each field. - Load — Write results back to the feature service using batch updates via the
arcgisAPI.
See Automation_Code/scripting_framework.md for the full architecture documentation, analysis patterns, and conventions.
Each script follows the same source-sync pattern:
FETCH -> VALIDATE COUNT -> VALIDATE SCHEMA -> WIPE + RELOAD TARGET
- Fetch — Pull the external source (WFS GetFeature, REST API call, etc.) with exponential-backoff retry.
- Validate count — If the source returned fewer features than
MIN_FEATURE_COUNT, email an alert and abort. Prevents "upstream returned empty → target gets nuked." - Validate schema — Compare source field names to the target layer's fields. Any drift (added / removed / renamed) emails an alert and aborts. Forces a conscious schema update on the target before resuming.
- Wipe + reload — Delete existing features and re-add the new ones in 1000-feature chunks.
Shared helpers for the source-sync pattern live in shared/source_sync.py.
- ArcGIS Pro with an active portal session (signed into the portal that hosts the target feature services)
- Python environment:
arcgispro_clone(ships with ArcGIS Pro) - Required packages:
arcpy,arcgis,requests(all included with ArcGIS Pro — no extra installs needed)
-
Clone the repository:
git clone https://github.com/Austin-Beck/NHI_Repo.git -
Copy the environment template and fill in your SMTP credentials:
cd NHI_Repo/Automation_Code copy .env.example .envEdit
.envwith your SMTP username, password, sender address, and recipient list. -
Copy the local config template and set the path to your ArcGIS Pro python:
copy config.local.bat.example config.local.batEdit
config.local.batand setPYTHONto thepython.exeof the ArcGIS Pro env that hasarcpyinstalled. The default for a stock Pro install is:set PYTHON="c:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro_clone\python.exe"config.local.batis gitignored so each machine keeps its own path.run_all.batwill fail with a clear message if this file is missing. -
Ensure ArcGIS Pro is signed into the portal that hosts the Community Explorer + Hazard Explorer feature services.
Run everything in sequence (Task Scheduler entry point):
Automation_Code\run_all.bat
run_all.bat runs the Hazard Explorer source-sync scripts first (so the Community Explorer scripts see fresh source data), then the Community Explorer hazard analysis scripts, reporting pass/fail status per script. Logs older than 7 days are cleaned up first.
Run a single script:
Use the same python.exe you set in config.local.bat. Default location:
"c:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro_clone\python.exe" Automation_Code\community_explorer\flooding.py
"c:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro_clone\python.exe" Automation_Code\hazard_explorer\wfs_update.py
Logs land in Automation_Code/logs/ with the naming convention {script}_{date}.log. Each log captures start/end time, feature counts, update counts, and full stack traces on failure.
- Copy
Automation_Code/community_explorer/_template.pytoAutomation_Code/community_explorer/{your_hazard}.py. - Fill in the
SOURCESdictionary with feature service URLs. - Fill in
FIELDS_TO_POPULATEwith the target field names. - Write your
run()function using the shared analysis helpers fromshared/transform.py. - Test against one geography level first, then enable the rest.
- Add an entry to
run_all.batunder the Community Explorer block. - Review the log file for correct counts and timing.
Refer to Automation_Code/scripting_framework.md for detailed guidance.
- Copy
Automation_Code/hazard_explorer/_template.pytoAutomation_Code/hazard_explorer/{your_source}.py. - Fill in
SOURCE_URL,SOURCE_PARAMS,TARGET_ITEM_ID, andMIN_FEATURE_COUNT. - Confirm the target AGOL hosted layer's schema matches the source's field names exactly (the strict schema check will abort otherwise).
- Add an entry to
run_all.batunder the Hazard Explorer block. - Test by running the script once and confirming the target layer was populated.
Both pipelines use the same SMTP config in .env. Two notification types:
- Failure email — Sent when a script crashes with an unhandled exception.
- Alert email — Sent by Hazard Explorer source-sync guardrails when a source returned too few features or the source schema has drifted. The script aborts before any destructive operation.
Set NOTIFY_ENABLED = False in Automation_Code/shared/config.py to disable notifications entirely.