Skip to content
PeterYousefiPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

🔥 WildfireGIS — Prescribed Burn Jurisdiction & Civic Notification Tool

IBM AI Builders Challenge — Wildcard Theme: Future of Work An AI co-worker for land managers and emergency responders — not a replacement.

.NET IBM watsonx.ai License: MIT


One-Line Pitch

WildfireGIS replaces hours of manual GIS lookups, government-portal searching, and email drafting with a single automated pipeline: draw a burn boundary → get the intersecting municipality, the Mayor's contact, the Fire Chief's contact, and a professionally drafted civic notification email — in under 90 seconds.


Table of Contents

  1. Problem Statement
  2. Architecture Overview
  3. Technical Execution
  4. Innovation
  5. Feasibility
  6. Challenge Fit — Future of Work
  7. Setup Instructions
  8. Demo Script (60–90 seconds)
  9. Known Limitations / Future Work

Problem Statement

The Real Operational Pain

Every prescribed burn in Ontario — and across Canada — requires the burn boss or land manager to:

  1. Manually identify jurisdiction. A burn polygon may cross municipal, county, First Nations, and provincial boundaries simultaneously. Determining which municipality's fire department and elected officials must be notified requires either expensive GIS software, time-consuming ArcGIS portal lookups, or a phone call to a regional office.

  2. Hunt for civic contacts. Municipal websites vary wildly in quality. The Mayor's email may be buried under three navigation levels; the Fire Chief's contact may only exist in a 2-year-old PDF staff directory. There is no single authoritative source.

  3. Draft a professional notification from scratch. Each notification must be factual, calm, and calibrated for a non-technical audience (elected officials, not foresters). A poorly worded email can cause public alarm, media escalation, or strained municipal relationships. Drafting and reviewing takes 30–60 minutes per municipality per burn.

  4. Repeat for every affected municipality. A 500-hectare burn near a township boundary may require notifying 3–5 separate contacts across 2–3 municipalities.

This is a solved problem for AI. The jurisdictional data is public (Ontario LIO). The contact data is partially structured (OpenNorth Represent API, CKAN open data). The notification content follows a well-defined professional template. What was previously a 2–4 hour manual workflow per burn event can become a 90-second automated pipeline.

Real-World Impact

  • Ontario alone runs hundreds of prescribed burns annually through the Ministry of Natural Resources and Forestry (MNRF) and licensed contractors.
  • Canada-wide, the Canadian Forest Service and provincial agencies conduct thousands of prescribed burn operations per year.
  • Delays in civic notification have historically caused public 911 call spikes, unnecessary emergency response mobilisation, and reputational damage to forestry agencies.
  • Faster, consistent notification builds trust between land management agencies and local governments — a critical relationship during wildfire season.

Architecture Overview

┌─────────────────────────────────────────────────────────────────────┐
│                         WildfireGIS                                 │
│                                                                     │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  Blazor Server UI  (BurnDashboard.razor)                     │   │
│  │  ┌──────────────┐  ┌──────────────────┐  ┌───────────────┐  │   │
│  │  │ Coordinate   │  │ Contact Cards    │  │ AI Email      │  │   │
│  │  │ Input Panel  │  │ (Mayor, Fire     │  │ Draft Panel   │  │   │
│  │  │              │  │  Chief, warn     │  │ (editable +   │  │   │
│  │  │ Centroid     │  │  badges)         │  │  mailto/      │  │   │
│  │  │ Area (ha)    │  │                  │  │  clipboard)   │  │   │
│  │  └──────┬───────┘  └────────┬─────────┘  └──────┬────────┘  │   │
│  └─────────┼───────────────────┼────────────────────┼───────────┘   │
│            │ DI (Blazor Server │ same-process calls)│               │
│  ┌─────────▼───────┐  ┌────────▼──────────┐  ┌─────▼──────────┐   │
│  │ SpatialService   │  │ CivicContactSvc   │  │ EmailDraftSvc  │   │
│  │ (NTS + ProjNet)  │  │                   │  │                │   │
│  │ • Polygon build  │  │ Source 1:         │  │ • Llama chat   │   │
│  │ • Winding fix    │  │  Represent API    │  │   template     │   │
│  │ • UTM ha calc    │  │  (Mayor/Reeve)    │  │ • Prompt       │   │
│  │ • GeoJSON serial.│  │                   │  │   injection    │   │
│  └─────────┬───────┘  │ Source 2:         │  │   hardening    │   │
│            │          │  CKAN open data   │  │                │   │
│  ┌─────────▼───────┐  │  (Fire Chief)     │  └──────┬─────────┘   │
│  │ LioMunicipalSvc  │  │                   │         │              │
│  │ (ArcGIS REST)    │  │ Graceful degrad.  │  ┌──────▼─────────┐   │
│  │ POST /query      │  │ + ContactCard     │  │ WatsonxClient  │   │
│  │ Polly retry      │  │   normalisation   │  │ IAM token +    │   │
│  └─────────┬───────┘  └────────┬──────────┘  │ cache          │   │
│            │                   │              │ meta-llama/    │   │
│  ┌─────────▼───────────────────▼──────────────▼────────────────┐   │
│  │  External APIs                                               │   │
│  │  • Ontario LIO ArcGIS REST  (ws.lioservices.lrc.gov.on.ca)  │   │
│  │  • OpenNorth Represent API  (represent.opennorth.ca)         │   │
│  │  • Ontario CKAN open data   (data.ontario.ca)                │   │
│  │  • IBM Cloud IAM            (iam.cloud.ibm.com)              │   │
│  │  • IBM watsonx.ai           (us-south.ml.cloud.ibm.com)      │   │
│  └──────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────┘

Data flow:

  1. User inputs polygon coordinates in the left panel
  2. SpatialService builds NTS polygon, corrects winding order, computes centroid + hectares in UTM, serialises to GeoJSON
  3. LioMunicipalService POSTs the Esri polygon to Ontario's LIO ArcGIS server → returns municipal name(s)
  4. CivicContactService queries Represent API (Mayor) + Ontario CKAN (Fire Chief) → normalises to ContactCard list
  5. EmailDraftService builds a Llama 3.3 chat-template prompt, calls WatsonxClient.GenerateWithMetadataAsync → parses Subject + Body
  6. Blazor UI renders all results in real-time; user edits draft → clicks "Open in Mail Client" (mailto:) or "Copy to Clipboard"

Technical Execution

Spatial Engine — NetTopologySuite

Winding-order correction is implemented explicitly rather than assumed. Input coordinates arrive in arbitrary order from a GIS tool or manual entry. The signed shoelace formula detects CW vs CCW orientation, and Array.Reverse() corrects CW → CCW in-place. This matters because GeoJSON RFC 7946 mandates CCW for exterior rings and several ArcGIS REST endpoints silently misinterpret CW rings.

Accurate hectare calculation via UTM reprojection. WGS84 Polygon.Area returns square-degrees — a meaningless unit (a 1°×1° cell spans ~12,000 km² at the equator but only ~3,000 km² at 60°N). The UTM zone is auto-selected from the centroid longitude (zone = floor((lon + 180) / 6) + 1), a ProjNet WKT CRS string is built on-the-fly (no EPSG database file required), and the polygon is reprojected before area calculation. Accuracy: <0.04% for polygons under 50 km wide.

ArcGIS REST Integration — LioMunicipalService

  • Uses POST (not GET) because burn polygons easily exceed the ~2,000-char safe GET URL limit; the LIO server returns HTTP 414 for large GET queries
  • Esri JSON geometry format ("rings" key, not GeoJSON "coordinates") is built by re-wrapping the GeoJSON coordinates array — no re-encoding required
  • Polly exponential back-off (2s → 4s → 8s + jitter) handles the LIO server's known instability during peak hours
  • Soft-error detection: ArcGIS returns HTTP 200 even on failure; the response "error" object is always checked before accessing "features"

IAM Token Management — IamTokenProvider

  • IBM-specific grant type: urn:ibm:params:oauth:grant-type:apikey (not standard client_credentials)
  • Token TTL is 3,600 s; the cache expires 300 s early to prevent race conditions between validity-check and HTTP dispatch
  • SemaphoreSlim(1,1) + double-checked locking prevents stampede under concurrent Blazor circuit requests

Civic Contact Graceful Degradation

Every possible failure mode returns a ContactCard with NeedsManualLookup=true and a LookupNote containing the exact URL to search manually. The pipeline never returns empty — the email draft is always generated with whatever contact information was found, and unverified recipients trigger a [VERIFY CONTACTS BEFORE SENDING] prefix on the subject line. This is a deliberate design choice: a partial notification with a clear warning is more useful than a failed one.

Prompt Engineering — EmailDraftService

  • Uses the Llama 3.3 Instruct chat template (Meta special tokens: <|begin_of_text|>, <|start_header_id|>, <|eot_id|>) directly in the input field — activates the model's instruction-following mode
  • System prompt is fully static (zero interpolation). All user data flows through the user turn only. Sanitise() strips \n, \r, and Llama special-token delimiters from all user-supplied strings before prompt assembly — prevents multi-line prompt injection via a crafted municipal name
  • stop_sequences: ["<|eot_id|>", "###"] terminates generation cleanly at end-of-assistant-turn, preventing phantom next-user-turn hallucinations
  • Temperature 0.4 / top_k 50 / repetition_penalty 1.1 — tuned for professional prose, not creative output

RFC 6068 mailto: URI Builder — MailtoUriBuilder

  • Standalone static class with no UI dependency — independently testable
  • Line breaks encoded as %0D%0A (CRLF), not bare %0A — required by Outlook on Windows
  • Conservative character encoding set (encodes all non-unreserved chars) for maximum mail-client compatibility
  • URI length check against 1,900-char limit triggers automatic clipboard fallback — documented and tested
  • Primary → To:, secondary → CC: pattern mirrors real notification practice (transparent to all parties)

Innovation

The novel contribution is the automated end-to-end pipeline that no existing tool provides:

Manual workflow today WildfireGIS
Open ArcGIS Desktop or ArcGIS Online → upload boundary → run spatial query → write down municipal names Paste coordinates → instant result
Search municipal website / provincial directory for Mayor contact Represent API query → structured ContactCard
Search fire department registry / CKAN for Fire Chief CKAN package_search + datastore_search + heuristic field extraction
Draft notification email in Word → review → copy-paste into Outlook Llama 3.3 70B generates a professional, regulation-appropriate draft in seconds
Repeat for each of 3 municipalities Single pipeline, parallel municipality lookup

The chaining is the innovation: no individual component is novel in isolation. The novelty is that a land manager with no GIS expertise, no knowledge of ArcGIS REST APIs, no familiarity with CKAN, and no time to draft a careful email can get from "polygon coordinates" to "reviewed, ready-to-send civic notifications" in a single browser session.

This is classic AI augmentation of professional workflow — the tool handles the mechanical steps (spatial query, contact lookup, draft generation) while the land manager applies domain judgment (reviewing the draft, adding operational notes, deciding the send time).


Feasibility

Demo-Ready ✅

Feature Status
Polygon input → centroid + hectares ✅ Full NTS implementation with UTM reprojection
LIO municipal intersection query ✅ ArcGIS REST POST with Polly retry
Mayor contact via Represent API ✅ Live API integration with graceful degradation
CKAN Fire Chief lookup ✅ 3-step package_search → datastore_search pattern
AI email draft via watsonx.ai ✅ Llama 3.3 70B with chat-template prompt
Blazor Server UI with mailto/clipboard ✅ RFC 6068 compliant with JS interop fallback

Production Hardening Needed ⚠️

Gap Description Mitigation path
CKAN endpoint variability Each of Ontario's 440+ municipalities publishes data on a different CKAN instance with different field names. The current heuristic field-matching covers ~70% of cases. Build a curated municipality → CKAN endpoint mapping table; contribute upstream to Open511/OpenNorth
Represent API coverage ~85% of Ontario municipalities are in the Represent database; rural townships and First Nations bands may be missing Supplement with a manually maintained fallback CSV for known gaps
First Nations jurisdictions Burns on Crown land near reserve boundaries may require notification to band councils not in Represent Integrate FNMIS (First Nations Map) or manual contact list
Production secret management .env file is appropriate for hackathon; production needs Azure Key Vault, AWS Secrets Manager, or IBM Secrets Manager DI-ready: swap SettingsLoader for a secrets provider without touching services
Multi-burn session state Current Blazor Server circuit holds one burn at a time Add a BurnSession list component and EF Core / SQLite persistence
Actual email delivery mailto: URI opens the user's default mail client; does not send programmatically Add SMTP/SendGrid service for fully automated delivery (requires additional approval workflow)

Challenge Fit — Future of Work

Wildcard Theme: Future of Work — Decision intelligence and the AI co-worker.

WildfireGIS is a concrete demonstration of how AI reshapes professional workflows in critical infrastructure, not knowledge work. The "Future of Work" conversation is often dominated by knowledge-worker examples (code generation, document summarisation). WildfireGIS targets a different population: land managers, prescribed burn bosses, and emergency responders — professionals whose work is spatially grounded, time-sensitive, and carries real public safety consequences.

The AI co-worker framing is literal here:

  • The spatial analysis (centroid, hectares, jurisdiction lookup) is work the AI replaces entirely — it is mechanical, error-prone, and takes hours; a computer does it better in seconds
  • The civic notification draft is work the AI assists with — it produces a professional starting point that the operator reviews, edits, and takes responsibility for before sending
  • The operator retains full authority: every email is editable, every [VERIFY CONTACTS] flag is visible, and the send action is always a human gesture

This models the correct relationship between AI tools and high-stakes professional work: AI handles the mechanical and informational, humans handle the judgmental and relational.

The pipeline also directly addresses the Future of Work theme's equity dimension: a small municipality or underfunded forestry contractor without a dedicated GIS analyst gets the same spatial intelligence and civic communication support as a large provincial agency with a full ArcGIS team. AI democratises access to expert-level analytical workflows.


Setup Instructions

Prerequisites

  • .NET 8 SDK
  • An IBM Cloud account with:
    • An IBM Cloud IAM API key
    • A watsonx.ai project with Watson Machine Learning service associated
    • Access to the meta-llama/llama-3-3-70b-instruct foundation model in your region

1. Clone and configure

git clone https://github.com/your-org/WildfireGIS.git
cd WildfireGIS/WildfireGIS

cp .env.example .env
# Open .env and fill in the four required values:
#   API_KEY     — IBM Cloud IAM API key
#   PROJECT_ID  — watsonx.ai project GUID
#   CLOUD_URL   — e.g. https://us-south.ml.cloud.ibm.com
#   LLM_NAME    — meta-llama/llama-3-3-70b-instruct

2. Where to find each credential

Variable Location in IBM Cloud
API_KEY cloud.ibm.com → Manage → Access (IAM) → API keys → Create
PROJECT_ID dataplatform.cloud.ibm.com → Projects → [your project] → Manage → General → Project ID
CLOUD_URL Match to region: us-south / eu-de / eu-gb / jp-tok
LLM_NAME meta-llama/llama-3-3-70b-instruct (verify via GET {CLOUD_URL}/ml/v1/foundation_model_specs?version=2024-05-31)

3. Run

dotnet restore
dotnet run

Open http://localhost:5000 in a browser. The Blazor Server dashboard loads immediately; no build step required.

4. Environment variables (CI/production)

The .env file is for local development only. In CI/CD, set the four variables as process environment variables. SettingsLoader uses LoadOptions.NoClobber — real environment variables always shadow .env values.


Demo Script (60–90 seconds)

Goal: show judges the full pipeline from coordinate input to a ready-to-send email, emphasising that the operator stays in control at every step.

0:00 — Context (15 s)

"A prescribed burn boss just received approval for a 280-hectare burn near Parry Sound, Ontario. Before ignition, they need to notify the Mayor and Fire Chief of every municipality the burn boundary touches. Normally this takes 2–4 hours. Let's do it in 90 seconds."

0:15 — Input (10 s)

Paste the four coordinates into the Coordinate Input panel (pre-populated as defaults). Set Fuel Types to "Mixed boreal forest, Jack pine". Click Analyse Burn Boundary.

0:25 — Spatial result (10 s)

While the spinner runs, explain: "The backend is running winding-order correction, reprojecting to UTM for accurate hectare math, and querying Ontario's LIO ArcGIS server for municipal boundaries." Results appear: Centroid, 279.3 ha, Municipality: PARRY SOUND

0:35 — Contact cards (15 s)

The centre panel populates with contact cards. Point out:

  • The Mayor card with green source badge ("represent.opennorth.ca") and visible email/phone
  • The Fire Chief card with the amber ⚠ warning ("CKAN returned no results — verify manually") "The system found the Mayor automatically. It couldn't find the Fire Chief in the open data — it flags that card so the operator knows to verify before sending, rather than silently failing."

0:50 — AI email draft (20 s)

The right panel shows the generated email. Read the subject line and first paragraph. Point out:

  • The tone: professional, calm, no alarming language
  • The [VERIFY CONTACTS BEFORE SENDING] prefix on the subject (because Fire Chief is unverified)
  • The editable text areas: "The operator can edit any part of this before sending"

1:10 — Send action (10 s)

Click Open in Mail Client on the Mayor's contact card. The OS mail client opens with the address, subject, and body pre-filled. Click Copy to Clipboard for the Fire Chief card to show the fallback path.

1:20 — Closing (10 s)

"2–4 hours of manual GIS lookups, government portal searching, and email drafting — automated to 90 seconds, with the operator reviewing and approving every step. That's the AI co-worker for the future of land management."


Known Limitations / Future Work

Known Limitations

  1. CKAN coverage: Ontario's open data portal doesn't have fire department contacts for every municipality. The 3-step CKAN lookup works for ~70% of cases; the remaining 30% return manual-lookup cards.

  2. Represent API completeness: Rural townships, unorganised territories, and First Nations lands may not appear in the Represent database. Coverage is best for cities and towns.

  3. Single-burn session: The current UI holds one burn analysis at a time. Navigating away loses state.

  4. No actual email sending: The tool opens the user's default mail client via mailto:. It does not send email programmatically. This is intentional for the hackathon (avoids needing SMTP credentials) but is a production gap.

  5. Llama 3.3 70B availability: Model availability varies by watsonx.ai region. If the model is unavailable in your region, update LLM_NAME in .env to a supported alternative (e.g. ibm/granite-13b-instruct-v2).

Future Work

  • Interactive map (Leaflet.js or MapLibre GL) replacing the coordinate textarea — draw the burn boundary directly on a basemap
  • Multi-burn session management with SQLite/EF Core persistence
  • First Nations consultation layer — overlay First Nations reserve boundaries and link to band council contacts from the First Nations Major Projects Coalition directory
  • Ontario MNRF fire weather data integration — pull FFMC/BUI/FWI indices for the centroid location to include fire behaviour context in the notification
  • Programmatic email delivery via SendGrid/SMTP with operator approval workflow
  • PDF notification package — generate a complete notification package (email + burn plan summary + GeoJSON map export) for the burn file
  • Multi-province support — parameterise the LIO endpoint and Represent boundary sets to support BC, AB, MB jurisdictions
  • Streaming LLM responses via /ml/v1/text/generation_stream — show the email draft being written in real-time for demo impact

Project Structure

WildfireGIS/
├── .env.example                    ← credential template
├── .gitignore                      ← .env excluded
├── WildfireGIS.csproj
├── Program.cs                      ← ASP.NET Core / Blazor Server host
├── Api/
│   └── BurnApiEndpoints.cs         ← Minimal API REST endpoints
├── Components/
│   ├── App.razor                   ← HTML document shell
│   ├── Routes.razor                ← Blazor router
│   ├── Layout/
│   │   └── MainLayout.razor        ← App chrome (header, footer)
│   └── Pages/
│       └── BurnDashboard.razor     ← Main three-panel UI
├── Config/
│   ├── WatsonxSettings.cs          ← Strongly-typed credential POCO
│   └── SettingsLoader.cs           ← DotNetEnv loader + validation
├── Models/
│   ├── WatsonxModels.cs            ← IAM + generation DTOs
│   ├── SpatialModels.cs            ← LonLat, BurnPolygonInfo, ArcGIS DTOs
│   └── CivicModels.cs              ← ContactCard, EmailDraft, BurnParameters, CKAN/Represent DTOs
├── Services/
│   ├── IamTokenProvider.cs         ← IBM IAM token exchange + caching
│   ├── WatsonxClient.cs            ← watsonx.ai HTTP wrapper
│   ├── SpatialService.cs           ← NTS polygon + UTM area + GeoJSON
│   ├── LioMunicipalService.cs      ← ArcGIS REST + Polly retry
│   ├── CivicContactService.cs      ← Represent API + CKAN lookup
│   └── EmailDraftService.cs        ← Llama prompt builder + output parser
├── Utilities/
│   └── MailtoUriBuilder.cs         ← RFC 6068 mailto: URI + clipboard fallback
└── wwwroot/
    ├── app.css                     ← Flat CSS design system (no framework)
    └── blazor-interop.js           ← window.open mailto + Clipboard API

Dependencies

Package Version Purpose
DotNetEnv 3.1.0 .env file loading with NoClobber precedence
NetTopologySuite 2.5.0 Computational geometry (polygon, algorithms)
NetTopologySuite.IO.GeoJSON4STJ 4.0.0 NTS → GeoJSON via System.Text.Json
ProjNet 2.0.0 WGS84 → UTM reprojection (pure .NET, no GDAL)
Polly 8.4.1 Retry/timeout resilience for external APIs
Polly.Extensions.Http 3.0.0 HTTP transient-error helpers
Microsoft.AspNetCore.Components.Web 8.0.0 Blazor Server presentation layer
Microsoft.Extensions.Logging.Console 8.0.0 Structured console logging

License

MIT — see LICENSE.


Built for the IBM AI Builders Challenge · Wildcard Theme: Future of Work Powered by IBM watsonx.ai · Llama 3.3 70B Instruct · NetTopologySuite · Ontario LIO · OpenNorth Represent API

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages