Building a Water Forecaster

Web Development by Jacob Emerick

Hiking, backpacking, or spending any amount of time in the backcountry of Arizona has one important limitation: you need water. I mean, water is important to live no matter where you’re at, but it’s particularly hard to find in this arid state. A handful of rivers run reliably year round, and they’re all so silty and concentrated that it’s darn hard to filter water from. Planning a multi-day trip involves researching little seeps and springs, hoping for recent water reports, as well as having a gut feeling about the recent weather. That gut feeling, though… why depend on your gut when you can use math?

Knowing my limitations with Python, I asked a friendly AI agent to help me out. The ask started simple: given a collection of historic water reports and past weather reports, is there a correlation, and could I use that correlation to predict if a water source was running today? Turns out that mathematical modeling in Python was the first of my limitations. I ended up learning way too much about weather models, geographic pooling, and statistics.

Weather Models

I started with Open-Meteo’s ERA5, which is free, keyless, global, and goes all the way back to 2007. Then I learned that their grid is about ~9-11km, compared to Arizona’s small monsoon convection cells, which are frequently a few km in diameter. I tried switching between PRISM (4km) and MRMS radar (1km) from the Iowa Environmental Mesonet’s API. This resulted in a really interesting finding: the higher-resolution models weren’t actually resulting in better data. I scanned east -> west, iterating only a few kms, and all three models were showing the same results.

offset    ~km   iemre_i   prism_i   data
 -0.06   -5.5      116      1619
 -0.02   -1.8      116      1619    same
  0.00    0.0      116      1619    same
  0.02    1.8      116      1619    same
  0.03    2.8      117      1630    CHANGED

Next I decided to stay with the PRISM model, since at least it claimed to be the most detailed. PRISM depends on actual measured gauges, and interpolates other locations between those known measurements. This resulted in another interesting discovery that makes sense in retrospect: if the precipitation is sparse, most gauges are gonna get missed. MRMS radar was showing way more detail over the wilderness areas I was looking at. In fact, several concentrated, significant summer storms had less than a half-inch of rain on both ERA5 and PRISM, while MRMS had over three inches! That sounds like it contradicts the scan above, but the two tests were asking different questions. The scan asked whether moving a few kms changed the number. This one asked whether the model saw the storm at all… and a finer grid interpolated from the same sparse gauges is the same information, just diced smaller.

After that, I tried playing with the windows of time. Some water sources are more “flashy” (like rock tanks) while others depend on long-term water tables. It would only make sense that some weather models (like MRMS radar) would help predict the flashier springs, while other models (gauge-based) could predict ground-fed springs. This turned out to be a dead end, at least for the springs I tested. The problem is that the weather models just aren’t dependable enough for this. Maybe if Arizona had more rain gauges, especially in the backcountry, this would be a viable variable. For now, though, MRMS radar seems to be the best source.

Pooling

With the precipitation side figured out, I could then switch to aggregating water reports. I had pulled reports from three water sources, all from the Mazatzal Wilderness, about 3km apart. While they shared the same precipitation cell, maybe the geology would result in some interesting findings.

  • Big Kahuna Falls - a tributary draining the rocky Mazatzal Peak area, flashy
  • Castersen Seep - rock tanks along a creek, intermediate
  • Chilson Spring - hillside seep with a spring box, groundwater-fed

The inversion was the interesting thing here - the more reliable a source was, the weaker the correlation with precipitation. I didn’t want to depend on domain knowledge for this. I knew these things from hiking in the area… I wanted this engine to be able to deduce it from the correlation. And it did! Water sources with high correlation are inherently flashy, and then I added geographic pooling and depended on those sources less. Water sources with low correlation are more dependable, and are both more reliable for water and are more reliable indicators for other nearby areas.

Statistics

This is when I really started to trust the agent, because this level of statistics was beyond my math degree. Or, perhaps, twenty years passing has dimmed some of my statistics knowledge. I decided to use Spearman over Pearson, because the “flow” depends on a non-linear scale from 0.0 -> 1.0 (0.2 dripping, 0.6 qt per minute, 1.0 raging). Also, leaning on the weather models, I was able to fit a seasonal curve to find outliers, which turned out to be really indicative of strong spring flow. Current precipitation fitting the expected seasonal patterns is a signal… precipitation outpacing the pattern? Stronger signal. Last interesting thing was using log-sum-exp to stabilize before the likelihood grid, and also making sure that each source had its own control before geographic pooling. Math!

Where it’s At

I wanted to make this thing as accessible as possible, so the Python engine is open-sourced, and I added a Claude skill to that repo because why not. Some users may want to feed in CSVs directly to a Python prompt, others might want to ask Claude to do it (plus, the Claude path is a lot more forgiving about the source format). That wasn’t enough. I like websites, so I also built backcountrywateroracle.com. The inputs for water reports are still a bit finicky, but the best thing about this is the postgres database behind the scenes collecting and de-duping water reports. The more people leverage the site, the more water reports accumulate, and the more geographic pooling can happen based on other people’s entries.

Backcountry Water Oracle on Github

There’s a few things I’ve thought about adding, like “upload a route, and all water sources along your path get printed out” or a “report-back” nudge. For now, though, you can throw water reports at it and it will determine correlation. Shoot, there’s even a “no report” mode, where the engine tries to guess based only on precipitation records. This is risky and not recommended. From someone who’s made this mistake before: just because there’s a little mark on a map doesn’t mean that anything is there.

Comments

No comments yet — be the first.