Repository navigation
Make the station selection mean what the config says: radius, and one instrument per station - #45
Merged
Merged
Conversation
…m too `max_radius_km` reached `get_stations` and could never reach the waveform call: FDSN dataselect takes no geographic parameters, so repeating the config's wildcards asked the archive for the whole network however the stations had been selected. Found on a live fetch. A Magna smoke test with `max_radius_km = 50` came back with three BH channels from a station 225 km out, absent from the archived `inventory.xml` — an artefact holding waveforms with no metadata beside them, and a config whose stated spatial restriction the download did not honour. The waveform request is now built from the inventory the station query returned: one bulk line per channel, epochs collapsed. That makes the radius apply to both halves and makes the orphan case unreachable by construction — what was asked for is exactly what has metadata. An empty station query now says so rather than sending a bulk request with no lines, which FDSN rejects with a message about syntax. `min_radius_km` had the same hole and is fixed by the same change. The four new tests fail against the previous implementation. The fake client drops `get_waveforms` entirely, so a return to the wildcard path cannot pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…etres Two ways the thin wrapper handed the caller a trap that `MassDownloader` closes for free. `channel = "HH*,BH*,HN*,EN*"` returns every instrument at every station that has them — 507 channels for Magna's 88 stations. The waveform request is built from that answer, so all of them are downloaded, and a station with a broadband beside an accelerometer contributes the same ground motion twice: two entries in a `SpectrumSet`, weighted as two stations by anything that averages over them. `channel_priorities` and `location_priorities` rank them instead, first-match-wins per station, in ObsPy's order — channels within a location, then locations — so a list carried over from `Restrictions` selects the same instrument. The inventory is pruned to match, keeping the archive describing exactly what it holds. With no list set, the fetch warns and names the stations; `["*"]` is how a config says it wants all of them and means it. `max_radius_km` was converted with a single 111.195 km/degree. A degree of arc is not a fixed distance: measured on WGS84 across latitude and azimuth it runs 110.574 km at the equator to 111.691 km at the poles, a 1.01% spread, so one constant moves the boundary by -0.44% to +0.56% — 0.3 km on a 50 km radius, 2 km on Magna's 400 km. The station query is now sent at the loose end of that bracket, deliberately wide, and the cut made against the true epicentral distance from `gps2dist_azimuth`. The bracketing constants are asserted against the geodetics rather than trusted. Also fixed: `min_radius_km` was only sent alongside `max_radius_km`, so on its own it did nothing. A non-positive radius and an inverted annulus are now refused rather than silently selecting nothing, which is the failure mode of a metres-for-kilometres typo on a local array. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
sgjholt
marked this pull request as ready for review
September 17, 2026 22:48
sgjholt
pushed a commit
that referenced
this pull request
Sep 18, 2026
…ersion The code shipped in 2af57e8, the squash merge of #45. Squashing replaced the two commit subjects — `fix(acquire): ask for waveforms by name, so the radius applies to them too` and `feat(acquire): rank co-sited instruments, and cut the radius in kilometres` — with the pull request's title, which is not a conventional commit. release-please could not parse it: commit could not be parsed: 2af57e8 Make the station selection mean what the config says: radius, and one instrument per station (#45) error message: Error: unexpected token ' ' at 1:5 Considering: 0 commits No commits for path: ., skipping So the work is invisible to the release machinery: no bump, and no changelog entry for a release that contains it. That is the failure `AGENTS.md` means by load-bearing commit messages, and it cannot be repaired in the commit itself — the message on `main` is what it is. This restores the record where release-please will read it, and pays the documentation the change owed either way: `docs/upgrading.md` had no entry for a radius that now cuts against WGS84 rather than a fixed 111.195 km/degree, for `min_radius_km` beginning to work on its own, for the three config errors that now raise, or for the new priority lists. The same section was missing for 0.3 to 0.4, where `[smoothing] method` began being applied — the same shape of break, where the call is unchanged and the numbers move. `Release-As` pins the version rather than leaving it to the type, so the bump is right whichever way this lands: squashed, the subject is the title of this pull request and the footer still parses. Release-As: 0.5.0 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
sgjholt
pushed a commit
that referenced
this pull request
Sep 19, 2026
release-please generated the 0.5.0 section from the commits it could parse, and the one that carries this release's behaviour changes is not among them: 2af57e8, the squash merge of #45, has a subject that is not a Conventional Commit, so the generated Features line described b460d19 — the commit that restored the record — which is documentation about the change rather than the change. Left alone, the 0.5.0 changelog and the GitHub Release minted from it would say a radius fix, a WGS84 cut and two new config fields were "documentation". This names them and points at the commit that carries them. `docs/releasing.md` makes reading the changelog the review step for exactly this. Hand-edited, like the 0.2.0 heading above it, with a comment saying why. release-please only prepends to the file, so it survives the next release. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three bugs of one class, found by a live smoke fetch against IRIS rather than by the suite: the config promised a selection the download did not honour.
Each is a property ObsPy's
MassDownloadersupplies for free and the thin wrapper had to build by hand —sanitize,CircularDomain,channel_priorities.1. The radius never reached the waveforms
max_radius_kmwas converted to degrees and passed toget_stations. The waveform call repeated the config's wildcards:FDSN dataselect takes no geographic parameters, so this is not a missing argument — a wildcard waveform request is unbounded however the stations were selected.
On a Magna fetch with
max_radius_km = 50, that returned three BH channels from UU.SRU, 225 km out. SRU is absent from the archivedinventory.xml, which was radius-filtered, so the artefact held waveforms with no metadata beside them.min_radius_kmhad the identical hole.Fix: the waveform request is built from the inventory the station query returned — one bulk line per channel, epochs collapsed,
--for a blank location code. The request is the metadata, so a trace without a station entry cannot be asked for.2. A degree is not 111.195 km
The conversion was
max_radius_km / 111.195. A degree of arc is not a fixed distance; measured on WGS84 across latitude and azimuth:So one constant moves the boundary by −0.44% to +0.56% — ±0.3 km on a 50 km radius, ±2 km on Magna's 400 km.
Fix: the station query is sent at the loose end of that bracket, deliberately wide so the server cannot clip what the exact cut would keep, and the cut is made locally against the true epicentral distance from
gps2dist_azimuth.max_radius_km = 50now means 50 km wherever the event is. The two bracketing constants are asserted against the geodetics rather than trusted, so tightening them back toward 111.195 fails.Verified down to sub-kilometre arrays: at a 500 m radius the cut resolves a 2 m difference in station position, and the widening is 3.1 m.
Also fixed here:
min_radius_kmwas only sent alongsidemax_radius_km, so on its own it did nothing. A non-positive radius and an inverted annulus are now refused rather than silently selecting nothing — the failure mode of a metres-for-kilometres typo on a local array.3. Every instrument at every station
channel = "HH*,BH*,HN*,EN*"returns all of them wherever they are installed — 507 channels for Magna's 88 stations. Since the request is built from that answer, all 507 are downloaded, and a station carrying a broadband beside an accelerometer contributes the same ground motion twice: two entries in aSpectrumSet, weighted as two stations by anything that averages over them.Fix:
channel_prioritiesandlocation_prioritieson[stations], first-match-wins per station:channelsays what the data centre may offer; the priorities say which of what it offers to keep. Applied in ObsPy's order — channels within a location, then locations across the station — so a list carried over fromRestrictionsselects the same instrument. A station matching no pattern is dropped, and the writteninventory.xmlis pruned to match.With no list set the fetch warns and names the stations;
["*"]keeps everything and says so deliberately.datasets/magna_2020.tomlstays unranked on purpose — the near-source broadbands are the ones that clip, and the accelerometer beside them is why the paper covers that distance range — and now records why.The manifest gains
channels_availableandchannels_requestedbesidechannels, so what the query offered, what was asked for and what arrived are three separate numbers.Tests
26 new tests. Those for §1 fail against the previous implementation; the fake client no longer offers
get_waveformsat all, so a return to the wildcard path cannot pass.Verification
Not covered: a live re-fetch confirming the radius and the priorities hold on the wire. This sandbox has no FDSN egress, so that check is the reporter's to repeat — the channel count should drop and
inventory.xmlshould account for every waveform file.🤖 Generated with Claude Code