Plans a day of water sampling on a boat: it maps the water across the bay, works out an efficient route between the stations, and prints the plan and a safety checklist the crew can carry.
Before anyone collects data, someone has to plan the trip. Which stations, in what order, how long will it take, when is the tide right, and is the weather safe to go out. This project does that planning from a station list and a set of recent readings. It draws a map of how a measurement (say salinity) varies across the bay, orders the stations so the boat covers the least distance, and writes a one-page plan plus a pre-departure safety checklist.
I built it because the logistics side of field work interested me: the map, the route, and the checklist that all happen before the science starts.
Salinity across the bay, worked out from the readings at each station. Fresh near the river at the top left, salty near the sea at the bottom right.
The suggested route: start at the launch, visit all ten stations in an efficient order, and return. About 57 nautical miles and six and a half hours.
pip install -e ".[dev]"
# Make example readings, then produce the maps, route, plan, and checklist
./run.shOr run the parts:
python sample_data/generate_samples.py # example readings
field-planner -c config.yaml all sample_data/wq_snapshot.csv # everything
field-planner -c config.yaml route # just the route
field-planner -c config.yaml interpolate sample_data/wq_snapshot.csv # just the map
field-planner -c config.yaml checklist # just the checklist| File | What it is |
|---|---|
interpolation_sal_psu.png |
A map of the measurement across the bay, with stations and the launch marked |
route_map.png |
The suggested boat route drawn over the stations |
interactive_map.html |
A clickable map (station details, the surface, the numbered route) that opens in any browser |
SAMPLING_PLAN.pdf and .md |
The plan the crew carries: stations in order, coordinates, the route legs, and the gear list |
FIELD_SAFETY_CHECKLIST.md |
A checklist to run before leaving: weather limits, tide timing, a float plan, gear, and a sensor calibration log |
route.json |
The route summary in machine-readable form |
A sample plan and checklist are checked in.
This is the part that keeps people safe, so it is generated fresh for each trip rather than typed by hand. It covers:
- A weather go or no-go check, with wind and wave limits from the config.
- The best window to be on the water around the tide, in daylight.
- A float plan (who on shore knows the route and return time).
- The full gear list, split into safety, sampling, and boat gear.
- A sensor calibration table to fill in before launch.
- Emergency contacts and a checklist for when you get back.
Example tide line (a simple stand-in tide; for a real trip you would check the nearest NOAA tide station):
Recommended on-water window: 11:00-15:00 (around high water at 13:00, +0.70 ft)
- The map. Each point on the map is a weighted average of the station readings, with nearer stations counting more. This is a standard method called inverse distance weighting. It is simple, it never invents values outside the measured range, and it is easy to explain.
- The route. Finding the shortest round trip through many stops is a classic hard problem. This uses a quick two-step method: start from the launch and keep hopping to the nearest station you have not visited yet, then tidy up the route by reversing any segment that shortens it. Distances are real great-circle distances, and the time estimate adds travel time to a fixed time at each station.
- The tide. By default it builds a simple tide curve so it works offline, and picks a good sampling window around slack water in daylight. The code shows how to swap in real NOAA predictions.
More detail is in docs/METHODS.md. Stations, the boat, gear,
and tide settings all live in config.yaml.
estuary-field-planner/
├── field_planner/
│ ├── geo.py # distances and the map grid
│ ├── interpolate.py # the bay-wide surface
│ ├── route.py # the route optimiser
│ ├── tides.py # tide curve and best window
│ ├── maps.py # the maps (interactive and static)
│ ├── plan.py # the sampling plan (PDF and text)
│ ├── checklist.py # the safety checklist
│ └── __main__.py # the command-line tool
├── sample_data/ # the example-readings generator
├── tests/ # 8 tests
├── config.yaml # stations, boat, gear, tide settings
└── docs/ # methods, sample plan and checklist, preview images
Python, NumPy, SciPy, matplotlib, folium, reportlab. Tests with pytest.
Routes are straight lines between stations, so a real deployment would follow the navigable channels. The tide here is a simple model, not a real prediction. Both are noted in the methods and are easy to swap out.
MIT. See LICENSE.
Ranjith Guggilla

