What is GeoMakie.jl?
masterGeoAxis type, which handles Coordinate Reference Systems (CRS) and projections. GeoAxis is designed to be a drop-in replacement for Makie.Axis and works seamlessly with standard Makie plotting functions.repository·master·Indexed 42 days ago
https://github.com/makieorg/geomakie.jlA Julia package for plotting geospatial data on map projections within the Makie.jl ecosystem. It provides GeoAxis for handling Coordinate Reference Systems (CRS) via PROJ-strings and includes utilities for plotting coastlines, landmasses, and earth images using standard Makie plotting functions.
GeoAxis type, which handles Coordinate Reference Systems (CRS) and projections. GeoAxis is designed to be a drop-in replacement for Makie.Axis and works seamlessly with standard Makie plotting functions.GeoMakie uses a custom @cardmeta block to generate metadata for the documentation gallery. This metadata is used to render cover images, titles, and descriptions in the HTML grid.
To ensure Documenter.jl processes this correctly, you must wrap the @cardmeta block in a Julia comment block (#= ... =#). This prevents Documenter.jl from attempting to execute the metadata as code while allowing the custom GeoMakie build stage to parse it.
Place this block at the bottom of your Julia file.
#=
```@cardmeta
Cover = fig
Description = "A very short description of the example"
Title = "Some title, optional"=#
When working with geographic data in GeoMakie, you must choose the appropriate plotting method based on whether your data is vector or raster:
Vector data uses points and line segments to identify locations. It is typically plotted using:
linesscatterpolyRaster data uses a series of cells to represent locations. It is typically plotted using:
surfacemeshimageheatmapimage (specifically for GeoMakie.earth)GeoMakie distinguishes between different types of coordinate transformations to manage how data is mapped to the screen. Understanding these helps in predicting how shapes, lines, and bounding boxes will behave.
log or log10 scale to axes). The $x$ transformation does not affect $y$.GeoAxis) are the primary example of this.When using surface or contour plots, the longitudinal dimension may "wrap" around the planet, causing errors because each data point is transformed individually.
To resolve this, you should:
lon_0 parameter in the dest PROJ-string.circshift to shift your data (lons and the field) so they align with the new central longitude.Below is a recommended implementation for a cshift helper function to perform this adjustment.
# Helper to shift data to a new central longitude
function cshift(lons, field, lon_0)
shift = @. lons - lon_0 > 180
nn = sum(shift)
(circshift(lons - 360shift, nn), circshift(field, (nn, 0)))
end
# Usage example:
lons = -180:180
lats = -90:90
field = [exp(cosd(l)) + 3(y/90) for l in lons, y in lats]
lon_0 = -160
(lons_shift, field_shift) = cshift(lons, field, lon_0)
fig = Figure()
ax = GeoAxis(fig[1,1]; dest = "+proj=eqearth +lon_0=$(lon_0)")
surface!(ax, lons_shift, lats, field_shift, colormap=:balance)
lines!(ax, GeoMakie.coastlines(ax), color=:black, overdraw = true)
figGeoMakie extends the Makie.jl plotting ecosystem with three primary capabilities for geographic data visualization:
Proj.jl to define and use various geographic projections.GeoMakie provides GeoAxis, a specialized axis for plotting geospatial data on map projections. It integrates with the Makie.jl ecosystem, allowing you to use standard plotting functions like surface!, scatter!, poly!, and contour! on a geographic coordinate system.
using GeoMakie, CairoMakie
lons = -180:180
lats = -90:90
field = [exp(cosd(l)) + 3(y/90) for l in lons, y in lats]
fig = Figure()
ax = GeoAxis(fig[1,1])
surface!(ax, lons, lats, field; shading = NoShading)
figIn certain projections (like orthographic), the valid range of data in transformed space does not map to a simple rectangle in input space. To find which input points (e.g., lon/lat) are actually visible/valid in the transformed space, you can use Makie.apply_transform on the axis's transform_func and check for finite results.
Warning: Standard bounding boxes in input space may be either too small (missing parts of the data) or too large (including invalid/infinite regions) when dealing with these projections.
# Example: Checking validity of points in an orthographic projection
# ga is a GeoAxis instance
lons = LinRange(-180, 180, 500)
lats = LinRange(-90, 90, 500)
valid_points = [isfinite(Makie.apply_transform(ga.transform_func[], Point2f(lon, lat))) for lon in lons, lat in lats]
# valid_points can then be used in a heatmap to visualize the valid domain
heatmap(lons, lats, valid_points)You can install GeoMakie via the Julia REPL using the add command. Note that the package is currently in development and the interface may change.
]add GeoMakieTo add a new demo or example to the GeoMakie documentation, follow these steps:
examples/ directory.docs/src/examples.md.docs/src/make.jl.Requirements for the Julia file:
# Title) as the title.FigureLike object.@cardmeta block at the bottom of the page (see metadata requirements below).The primary entry point is GeoAxis(fig[i, j]; kw_args...). It creates an axis that accepts nonlinear projections via PROJ-strings. By default, the source CRS is "+proj=longlat +datum=WGS84". You can specify the destination projection using the dest keyword argument.
To plot data, use standard Makie functions like lines!, scatter!, surface!, etc., passing the GeoAxis instance as the first argument.
using CairoMakie, GeoMakie
fig = Figure()
ga = GeoAxis(
fig[1, 1]; # any cell of the figure's layout
dest = "+proj=wintri", # the CRS in which you want to plot
)
# plot coastlines from Natural Earth as a reference
lines!(ga, GeoMakie.coastlines())
# Plot data using standard Makie syntax
scatter!(ga, -120:15:120, -60:7.5:60; color = -60:7.5:60, strokecolor = (:black, 0.2))
figThe recommended way to plot data depends on your Makie backend:
Use image!(ax, ...) or heatmap!(ax, ...) for images or scalar fields.
image! and heatmap! do not work in GLMakie and will result in an empty axis. Instead, use surface! with an interval range to sample the grid:
img:
surface!(ga, lonmin..lonmax, latmin..latmax, ones(size(img)...); color = img, shading = NoShading)surface!(ga, lonmin..lonmax, latmin..latmax, field)Note: The .. notation creates a Makie interval that is automatically sampled to provide the x and y points.