Projecting onto a Model Frame
Geophysical datasets come in a variety of coordinate systems: catalogs in lon/lat with depth in kilometers, surface meshes in meters, rasters in geographic or projected CRSs. Finite-element models live in a local cartesian frame for convenience.
The project job bridges the two. It takes a georeferenced input —
catalog, mesh, or GeoTIFF raster — and transforms it into a local model
frame (or a model with a different real-world CRS).
Every input is translated and rotated using a real-world anchor point that lands at a chosen local-frame point. The anchor is a known point whose coordinates you have in both frames. The rotation is optional. An intermediate azimuthal equidistant projection centered on the anchor is used automatically.
Input data types
The input kind is declared as a sub-block under data::
catalogfor.csvpoint setsmeshfor.vtp/.vtu/.vtksurface or volumetric meshesrasterfor.tif/.tiffGeoTIFF rasters
This tutorial walks through three configurations from tutorials/7_data_to_fem_space/, one
for each input type.
Projecting a catalog
Catalogs are CSV files with one point per row. The configuration declares which columns hold the coordinates:
job: project
data:
catalog:
file: ../data/catalog_interface.csv
columns: [longitude, latitude, depth]
src:
crs: epsg:4326
xy_units: deg
z_units: km
z_positive: down
bbox:
lon: [-73.0, -69.0]
lat: [-21.5, -18.0]
depth_km: [0, 70]
dst:
units: km
anchor:
data:
lon: -71.1
lat: -20.17
depth_km: 16
model: [0, 0, -12.8]
rotation_deg: -10
output:
dir: results/
file: catalog_fem_space.vtp
Run it with:
$ fem2geo project_catalog.yaml
In this example:
data.catalog.columnslists the column names holding longitude, latitude, and depth, in that order. All other numeric columns in the CSV become point-data arrays on the output.srcdescribes the coordinates already in the file: geographic CRS, degrees for XY, kilometers for depth, positive downward.src.bboxdrops points outside the region before projection. Bboxes are always in lon/lat/depth_km, regardless of the source CRS.dst.anchorpins the point(lon=-71.07, lat=-20.09, 15.6 km deep)to the local-frame coordinate(0, 0, -14).dst.anchor.rotation_deg: -20rotates the model frame 20° clockwise around the vertical axis through the anchor (a negative value is clockwise; positive is counter-clockwise).
The output is a .vtp file with one point per catalog entry and every
numeric column preserved as point data.
TODO: ADD FIGURE Earthquake catalog projected into the local model frame.
Projecting a mesh
Surface meshes (e.g., slab interfaces) are read directly
from VTK formats. The mesh: sub-block carries the file path:
job: project
data:
mesh:
file: ../data/slab_interface.vtu
src:
crs: epsg:32719
xy_units: m
bbox:
lon: [-73.0, -69.0]
lat: [-21.5, -18.0]
depth_km: [0, 70]
dst:
units: km
anchor:
data:
lon: -70.929
lat: -20.17
depth_km: 18
model: [0, 0, -12.8]
rotation_deg: -10
output:
dir: results/
file: slab_fem_space.vtu
Run it with:
$ fem2geo project_slab.yaml
Points of note:
The slab mesh was stored in UTM zone 19S (
epsg:32719), with XY and Z both in meters.Meshes are assumed to be ENU (Z positive up) with a single unit for all three components, so
src.z_unitsandsrc.z_positiveare not needed and can be omitted.Because the bbox is specified in lon/lat/depth_km, it works identically whether the mesh is in UTM meters or any other CRS.
The output keeps the mesh topology and all original point data, written as
.vtu.
TODO: ADD FIGURE Slab interface projected into the local model frame.
Projecting a raster
GeoTIFF rasters are triangulated into a surface mesh with one point per pixel, then projected. The elevation comes from whichever band the config selects:
job: project
data:
raster:
file: ../data/topo_chile.tif
z_band: 1
src:
crs: epsg:4326
xy_units: deg
z_units: m
z_positive: up
bbox:
lon: [-73.0, -69.0]
lat: [-21.5, -18.0]
dst:
units: km
anchor:
data:
lon: -70.929
lat: -20.17
depth_km: 18
model: [0, 0, -12.8]
rotation_deg: -10
output:
dir: results/
file: topo_fem_space.vtp
Run it with:
$ fem2geo project_topo.yaml
A few raster-specific details:
data.raster.z_bandpicks the band (1-indexed) that drives the z coordinate. Omit it for a flat grid positioned at the anchor.All raster bands become point-data arrays on the output, so additional layers (e.g. slope, classification) ride along with the elevation.
src.xy_unitsdescribes the GeoTIFF’s CRS units (degfor a geographic raster,morkmfor a projected one), whilesrc.z_unitsdescribes the band value. The two are independent — a lon/lat DEM with elevations in meters is a normal case.The output is a
.vtpsurface mesh ready to visualize in ParaView alongside the model, and the slab and catalog outputs.
TODO: ADD FIGURE Topography raster projected into the local model frame.
Understanding the configuration
Every project configuration has four blocks: data, src, dst,
and output. They describe, in order, what to process, how the data
is currently georeferenced, where the model frame lives, and where to
write the result.
The data block
Pick exactly one of catalog, mesh, or raster as a sub-block.
Each carries its own file and any kind-specific options.
data:
mesh:
file: path/to/input.vtu
For catalogs, declare the coordinate columns:
data:
catalog:
file: data/cat.csv
columns: [longitude, latitude, depth]
For rasters, optionally pick the elevation band:
data:
raster:
file: data/dem.tif
z_band: 1
The file extension must match the declared kind: .csv for catalog,
.vtp/.vtu/.vtk for mesh, .tif/.tiff for raster.
The src block
Describes the coordinates inside the input file:
src:
crs: epsg:32719
xy_units: m
z_units: m
z_positive: up
bbox:
lon: [-72.5, -68.0]
lat: [-22.0, -18.0]
depth_km: [-10, 60]
crsaccepts any formatpyprojunderstands:epsg:32719,EPSG:4326, proj strings, WKT, and so on.xy_unitsisdegfor a geographic CRS,morkmfor a projected CRS.z_unitsismorkm, independent ofxy_units.z_positivelets the file use either convention:upfor elevations (negative underground) ordownfor depths (positive underground). The tool handles the flip internally.bboxis always specified in lon/lat/depth_km regardless of the source CRS, so configs stay comparable across datasets. Any axis left out is unconstrained.depth_kmis always positive-down.
Note
Mesh inputs are assumed to be ENU: Z positive up, with XY and Z in the same unit.
The dst block
Describes the destination model frame:
dst:
units: km
anchor:
data:
lon: -71.07
lat: -20.09
depth_km: 15.6
model: [0, 0, -21]
rotation_deg: -10
unitsapplies to both XY and Z of the output,morkm.anchor.datais where the anchor sits in the input coordinate system. Uselon/latwhen the anchor is naturally a geographic point; usex/ywhen the anchor is given in the same projected CRS assrc.crs.depth_kmis always positive-down.anchor.modelis where that same point lands in the output frame, indst.unitswith z positive up.rotation_degrotates the model frame around the vertical (z) axis through the anchor. Positive values rotate counter-clockwise as seen from above, negative values clockwise. Defaults to zero.
The output block
output:
dir: results/
file: topo_fem.vtu
Catalogs are always written as .vtp. Meshes and rasters are written
as .vtu or .vtp depending on the geometry type; if the requested
extension doesn’t match, the tool warns and corrects it.