Three deterministic steps, from orbit to owner.
The registry (Phase 1) already knows where every plant is and which company owns it. Phase 2 adds the time dimension: what's actually running hot, tonight. It's a pipeline, not a model.
Pull the detections
NASA's VIIRS instruments (SNPP, NOAA-20, NOAA-21) sweep the whole US twice a night. We pull their thermal-anomaly detections — already a structured table of hotspots, each with a temperature and a radiant-power number.
3 satellites · every ~12 h
Snap each to a plant
A nearest-neighbor search matches each detection to the closest combustion plant within 1 km. Only things that burn fuel emit a persistent heat signature — so a hotspot near a solar farm with no thermal plant nearby is left unmatched.
match radius · 1 km · thermal assets only
Land the time series
Each observation lands with its raw radiometry, when the overpass happened, and — crucially — when we could first know it (the point-in-time stamp that makes an honest backtest possible). Unmatched detections become a discovery queue for plants we don't know yet.
keys · observed_at + available_at (PIT)
Did we run a vision model on satellite imagery? No — and that was the point.
The intuitive version of "AI + satellites" is to point a vision-language model at infrared images and ask what it sees. We rejected that before writing a line of code. Here's the same job, two ways.
A vision model on rendered imagery
- Render satellite tiles to pictures, then ask a model "is this a flare?"
- Needs GPUs, labeled training data, and a fine-tuning loop
- Re-derives a worse version of numbers the satellite already published
- A thermal pixel isn't text — so the model confabulates fluently, and you can't audit why
- Can't tell 1,700 K flare from 800 K wildfire from a picture — that's physics, not perception
Geometry on a radiometric table
- VIIRS already ships each hotspot's temperature (K) and radiant heat (MW), as a table
- A nearest-neighbor join snaps it to the owning plant — pure coordinate math
- $0 of compute, fully deterministic, reproducible bit-for-bit
- Every match is auditable: a distance in metres, not a black box
- Flare-vs-wildfire stays a numeric question (temperature, persistence) for later — answered with data, not vibes
The strongest signal in the country isn't a power plant.
The first live ingest matched 665 detections to 155 plants. Ranked by heat, the top of the list was a surprise — and a useful one.
Steel output is a classic leading indicator of industrial activity, which is exactly what our first consumer wants to nowcast. The register×satellite join surfaced it on night one, for free.
- Mon Valley Works — US Steelpeak 11.8 MW
- Gary Works — US Steelpeak 6.5 MW
- Burns Harbor — ArcelorMittalpeak 5.4 MW
- Cleveland & 4 AC Works — Cleveland-CliffsNYSE: CLF
Night one, in numbers
Unmatched isn't error — a persistent hotspot with no plant nearby is a candidate we don't have yet.
The registry is the hard part. Every sensor is now just another join.
Because Phase 2 is source-agnostic — swap the fetcher, keep the join — the roadmap is mostly a question of which instruments to point at plants we already know the owners of.
Real temperature & footprint
The purpose-built combustion product from EOG gives source temperature and burning-area size directly — turning "something's hot" into "a 1,650 K flare over 900 m²." A one-function swap from today's wildfire-oriented feed.
3-metre thermal, on demand
Taskable high-resolution thermal at known coordinates: count individual units firing, watch a single cooling stack. Paid, so it only earns its cost once the free feed proves the join is worth resolving.
NO₂ & SO₂ plumes
Combustion emits more than heat. Pairing a nitrogen-dioxide or sulfur-dioxide plume with a thermal detection at the same plant cross-confirms it's really running — and adds an emissions dimension of its own.
Steam & cooling plumes
Daytime optical bands catch the water-vapor plume off a cooling tower — a utilization proxy that works for plants whose heat signature is faint, and a daylight complement to the night-only thermal pass.
Confounder normalization
Raw brightness moves with cloud cover, season, and satellite angle — an un-normalized "spike" is often just a clear night. We normalize for all three, then calibrate against reported grid generation. It passes with evidence, or we report the honest negative.
Flare vs wildfire, by physics
A gas flare burns ~1,700 K in the same pixel every night for years; a wildfire is cooler, moves, and dies. Those are two numbers and a time series — a small classifier on radiometric features, never a vision model.
Dark / lit transitions
A plant that goes dark on a date is a tradeable shape — a shutdown or restart. The first, compliance-safe version simply verifies already-disclosed outages against the observed record.
A decade of backtest
The same feed exists back to 2012. Replaying it through the registry builds a decade-long per-plant history — the substrate any signal has to be backtested on before anyone believes it.
Refineries, smelters, data centers
The registry schema already allows non-power thermal assets. Refinery flares, smelters, and the heat plume off a hyperscale data center are all the same pattern: a hot coordinate with a known owner.
Carbon column over a stack
Direct CO₂ column measurements over a point source close the loop from heat to emissions to production — the most demanding fusion, and the most valuable if the earlier layers hold up.