Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added pygmt_helper/examples/ratio.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed pygmt_helper/examples/ratio.png
Binary file not shown.
14 changes: 10 additions & 4 deletions pygmt_helper/examples/ratio.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,22 @@
fig = plotting.gen_region_fig("Ratio")

# Compute the interpolated grid
grid = plotting.create_grid(df, "ratio")
# Use a large grid resolution for the whole country.
grid = plotting.create_grid(df, "ratio", grid_spacing="1000e/1000e")

# Plot the grid
plotting.plot_grid(
fig, grid, "polar", (-0.5, 0.5, 1.0 / 16), ("darkred", "darkblue"), transparency=35
fig,
grid,
"polar",
(-0.5, 0.5, 1.0 / 16),
("darkred", "darkblue"),
transparency=35,
plot_contours=False,
)

# Save the figure
fig.savefig(
output_dir / f"ratio.png",
dpi=900,
output_dir / f"ratio.jpeg",
anti_alias=True,
)
85 changes: 38 additions & 47 deletions pygmt_helper/plotting.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
"""Plotting tools to generate basemaps, grids and contours with PyGMT."""

import itertools
import copy
import itertools
import tempfile
from pathlib import Path
from typing import Any, NamedTuple, Optional, Self, Callable
from typing import Any, Callable, NamedTuple, Optional, Self

import geopandas
import numpy as np
import pandas as pd
import pooch
import pygmt
import xarray as xr
from scipy import interpolate
from shapely import geometry
from qcore import point_in_polygon
from scipy import interpolate

GMT_DATA = pooch.create(
pooch.os_cache("pygmt_helper"),
Expand Down Expand Up @@ -290,41 +289,30 @@ def gen_region_fig(
# Merge with default
plot_kwargs = copy.deepcopy(DEFAULT_PLT_KWARGS) | (plot_kwargs or {})

if title:
plot_kwargs["frame_args"] = plot_kwargs.get("frame_args", []) + [
f"+t{title}".replace(" ", r"\040")
]

if subtitle:
plot_kwargs["frame_args"] = plot_kwargs.get("frame_args", []) + [
f"+s{subtitle}".replace(" ", r"\040")
]
if config_options:
pygmt.config(**config_options)

if fig is None:
fig = pygmt.Figure()

if config_options:
pygmt.config(**config_options)

water_color = plot_kwargs["water_color"]
plot_kwargs["frame_args"] = plot_kwargs.get("frame_args", []) + [f"+g{water_color}"]
fig.basemap(
region=region if region else "NZ",
projection=projection,
frame=plot_kwargs["frame_args"],
)

# Plot coastline and background water
bg_region = region if region else fig.region
water_bg = geopandas.GeoSeries(
geometry.LineString(
[
(bg_region[0], bg_region[2]),
(bg_region[1], bg_region[2]),
(bg_region[1], bg_region[3]),
[bg_region[0], bg_region[3]],
]
)
)
fig.plot(water_bg, fill=plot_kwargs["water_color"], straight_line=True)
title_args = []
if title:
title_args.append(f"+t{title}")
if subtitle:
title_args.append(f"+s{subtitle}")

if title:
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition if title: is checked twice (lines 307 and 312), but the second check should be if title_args: to avoid calling basemap with empty frame args when only subtitle is provided.

Suggested change
if title:
if title_args:

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I knew the AI would flag this. Nope it is intentional. See the GMT docs

+ttitle to place the string given in title centered above the plot frame [default is no title].
+ssubtitle (requires +ttitle) to place the string given in subtitle beneath the title [default is no subtitle].

Note that +s requires +t, ergo subtitle= requires title=. Thus checking if title_args is non-empty leaves open the subtle bug that a user might call subtitle= and not title=. Hence, we check if title is not None. In that case, title_args is also not None. Likewise, if title is None then we should ignore the values in title_args even if subtitle is set.

fig.basemap(frame=title_args)

# Plot coastline
fig.plot(
data=map_data.coastline_df,
pen=f"{plot_kwargs['coastline_pen_width']}p,{plot_kwargs['coastline_pen_color']}",
Expand Down Expand Up @@ -370,24 +358,27 @@ def gen_region_fig(
topo_shading_grid = topo_shading_grid.where(mask, np.nan)

# Create topography colormap
pygmt.makecpt(
series=(
plot_kwargs["topo_cmap_min"],
plot_kwargs["topo_cmap_max"],
plot_kwargs["topo_cmap_inc"],
),
continuous=plot_kwargs["topo_cmap_continous"],
cmap=plot_kwargs["topo_cmap"],
reverse=plot_kwargs["topo_cmap_reverse"],
)
with pygmt.config(COLOR_NAN=plot_kwargs["water_color"]):
pygmt.makecpt(
series=(
plot_kwargs["topo_cmap_min"],
plot_kwargs["topo_cmap_max"],
plot_kwargs["topo_cmap_inc"],
),
continuous=plot_kwargs["topo_cmap_continous"],
cmap=plot_kwargs["topo_cmap"],
reverse=plot_kwargs["topo_cmap_reverse"],
# Some CPTs define their own COLOR_NAN, but we wish to use the
# water colour
no_bg=True,
)

# Plot topography
fig.grdimage(
grid=topo_grid,
shading=topo_shading_grid,
cmap=True,
nan_transparent=True,
)
# Plot topography
fig.grdimage(
grid=topo_grid,
shading=topo_shading_grid,
cmap=True,
)

# Plot inland water
fig.plot(data=map_data.water_df, fill=plot_kwargs["water_color"])
Expand All @@ -413,7 +404,7 @@ def plot_grid(
cmap: str,
cmap_limits: tuple[float, float, float],
cmap_limit_colors: tuple[str, str],
cb_label: str = None,
cb_label: str | None = None,
reverse_cmap: bool = False,
log_cmap: bool = False,
transparency: float = 0.0,
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pyarrow
pygmt
xarray
scipy
shapely
qcore @ git+https://github.com/ucgmsim/qcore.git
pytest
pytest-cov
Expand Down