Skip to content

Reconcile coordinate systems before extracting, and say what got nothing - #20

Merged
chross22 merged 1 commit into
masterfrom
crs-checks
Aug 7, 2026
Merged

Reconcile coordinate systems before extracting, and say what got nothing#20
chross22 merged 1 commit into
masterfrom
crs-checks

Conversation

@chross22

@chross22 chross22 commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Diagnosing "areas with observations but no depth".

The bug

attach_bathymetry() passed st_coordinates(dat) straight to terra::extract(). Those coordinates are in whatever system the object carries, and extract() reads them as the raster's own. Observations in a projected CRS were read as though their metres were degrees — every point landed outside a lon/lat grid and came back NA.

Three points, identical but for their CRS:

EPSG:4326     DEPTH: 100  150  200
EPSG:32619    DEPTH:  NA   NA   NA      coords sent to extract: 500000, 4649776

That is exactly "observations with no depth in an area that plainly has depth", with nothing said about it.

sf input is now reprojected to the raster's CRS first. No CRS at all warns rather than being assumed correct.

A plain data frame carries no CRS to check, so magnitude is the only available signal — an unambiguous one, since a longitude cannot exceed 180. Those are refused, with the conversion to make.

NA depths now say why

The two causes have different remedies, and neither is guessable from a column of NAs:

2 of 40 point(s) got no bathymetry.
  1 fall outside the grid, which spans -70 to -66 lon and 41 to 44 lat.
    Widen `bounding_box` in fetch_bathymetry() to cover them.
  1 fall inside the grid on cells with no depth, which ETOPO treats as land.
    Inshore stations do this: a cell is land if most of it is, so a station in
    a narrow bay can sit in one. A finer `resolution` reduces it.

That second cause may well be what you are seeing if the missing points are coastal — it is not a bug, and no CRS fix will move it. A finer resolution will.

matchData

Already reprojected correctly — verified projected and geographic observations match the same cells. But a missing CRS failed with sf's "crs not found: is it missing?", which is true and says neither which object nor what to do. It now names both sides.

Verification

  • 6 new tests: reprojection gives identical depths, missing CRS warns, projected data frames are refused, both NA causes are reported distinctly, a fully-matched set stays silent, and matchData names whichever side lacks a CRS.
  • R CMD checkStatus: OK. Full suite green. Installed into both R 4.6.1 and 4.3.2.

🤖 Generated with Claude Code

attach_bathymetry() passed st_coordinates(dat) straight to
terra::extract(). Those coordinates are in whatever system the object
carries, and extract() reads them as the raster's own. Observations in a
projected CRS were therefore read as though their metres were degrees:
every point landed outside a lon/lat grid and came back NA.

Demonstrated on three points, identical but for their CRS:

  EPSG:4326    DEPTH: 100  150  200
  EPSG:32619   DEPTH:  NA   NA   NA     coords sent: 500000, 4649776

That is observations with no depth in an area that plainly has depth,
with nothing said about it. sf input is now reprojected to the raster's
CRS first, and no CRS at all warns rather than being assumed right.

A plain data frame carries no CRS to check, so the only available signal
is magnitude - and it is unambiguous, since a longitude cannot exceed
180. Those are refused with the conversion to make.

NA depths are now also reported with their cause, because the two causes
have different remedies and neither is guessable from a column of NAs.
Outside the grid means the bounding box was drawn too small. Inside it
means ETOPO calls that cell land, which at 4 arc-minutes happens readily
to inshore stations, since a cell roughly 7 km across is land if most of
it is. That second one is easy to mistake for a bug and is not.

matchData() already reprojected correctly, but failed on a missing CRS
with sf's "crs not found: is it missing?" - true, and silent about which
object and what to do. It now names both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chross22
chross22 merged commit 4528fcc into master Aug 7, 2026
5 checks passed
@chross22
chross22 deleted the crs-checks branch August 7, 2026 17:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant