Plot is getting cutoff

Not a PyGMT problem per se, but after an update to the newest versions of pygmt and gmt (and probably ghostscript), my plots are now being cutoff. I have tried setting PS_MEDIA with no change, I’ve also tried changing the PS_PAGE_ORIENTATION with no change. When I pull the resulting file into illustrator, there is nothing being plotted outside of what is shown in preview. Should I fallback to a previous version or is there a command or flag that I’m missing?

Here is a code snippet to recreate the problem:

import pygmt
region = [-155.72,-155.62,19.45,19.55]
proj = 'M8i'
fig = pygmt.Figure()
fig.coast(region=region, projection=proj, land='gray', water='skyblue', frame=True)
fig.show()

Here is the output of pygmt.show_versions()

PyGMT information:
  version: v0.15.0
System information:
  python: 3.12.3 | packaged by conda-forge | (main, Apr 15 2024, 18:35:20) [Clang 16.0.6 ]
  executable: /opt/miniconda3/envs/pygmt/bin/python
  machine: macOS-14.7.5-arm64-arm-64bit
Dependency information:
  numpy: 1.26.4
  pandas: 2.2.3
  xarray: 2024.10.0
  netCDF4: 1.6.5
  packaging: 24.1
  contextily: None
  geopandas: 1.0.1
  IPython: 8.29.0
  pyarrow: None
  rioxarray: None
  gdal: 3.9.1
  ghostscript: 10.04.0
GMT library information:
  version: 6.5.0
  padding: 2
  share dir: /opt/miniconda3/envs/pygmt/share/gmt
  plugin dir: /opt/miniconda3/envs/pygmt/lib/gmt/plugins
  library path: /opt/miniconda3/envs/pygmt/lib/libgmt.dylib
  cores: 16
  grid layout: rows
  image layout: 
  binary version: 6.5.0

Thanks @wthelen for this report.

Hm, I am wondering if this problem is the same as the one reported in Why the subplot second panel is getting cut? - #5 by geodacharya.

If I run your code with a PyGMT dev version + GMT 6.5.0 and ghostscript 10.03.0. The map isn’t cut off. However, in both topics, higher gs versions are used. So, maybe there is a problem with higher gs versions. I have to make an environment with gs higher than 10.03.0 and test on my own.

Maybe share the PS file. PyGMT uses only modern mode and in it the paper size is wall sized (11 meters) so it’s difficult to imagine how this happens and even more that it’s ghostscript issue (but something is).

So, I installed gs 10.04.0 and I do not face to problem of cut off maps in PyGMT.

Thank you for your rapid response.

Downgraded to 10.04.0. There are some changes.

  1. No change to what is displayed with fig.show() (figure still cutoff)
  2. When saved as eps, the file is rotated 90 degrees with the whole figure frame rendered
  3. When saved as pdf, it looks the same as fig.show() (figure still cutoff)

Attached .pdf. Can’t save as .ps in pygmt and I can’t upload the .eps.

test.pdf (5.5 KB)

Here is the new output of show_versions for completeness:
PyGMT information:
version: v0.15.0
System information:
python: 3.12.3 | packaged by conda-forge | (main, Apr 15 2024, 18:35:20) [Clang 16.0.6 ]
executable: /opt/miniconda3/envs/pygmt/bin/python
machine: macOS-14.7.6-arm64-arm-64bit
Dependency information:
numpy: 1.26.4
pandas: 2.2.3
xarray: 2024.10.0
netCDF4: 1.7.2
packaging: 24.1
contextily: None
geopandas: 1.0.1
IPython: 8.29.0
pyarrow: None
rioxarray: None
gdal: 3.11.0
ghostscript: 10.04.0
GMT library information:
version: 6.5.0
padding: 2
share dir: /opt/miniconda3/envs/pygmt/share/gmt
plugin dir: /opt/miniconda3/envs/pygmt/lib/gmt/plugins
library path: /opt/miniconda3/envs/pygmt/lib/libgmt.dylib
cores: 16
grid layout: rows
image layout:
binary version: 6.5.0

The pdf is no good (too late). You can zip the eps and attached here. But what I would like is the ps. Sure is not possible? Others?

I can report the exact same issues as @wthelen with a slightly different configuration (see below). Have played a bit with width/height ratios and it seems that in my case the maps with a N-S:E-W ratio of >1.5 seem to be ok, although there the inset map is getting cut off (only if the map title is wider than map width + inset map, the map is not cut off in width). Maps with a height:width ratio < 1.5 are all getting cut off at the top.

EPS and PDF attached, pygmt doesn’t want to write out *.ps:

File "/Users/christian/Library/Python/3.12/lib/python/site-packages/pygmt/figure.py", line 228, in savefig
    raise GMTInvalidInput(msg)
pygmt.exceptions.GMTInvalidInput: Extension '.ps' is not supported. Use '.eps' or '.pdf' instead.

Cheers,
Christian

PyGMT information:
  version: v0.14.2
System information:
  python: 3.12.9 (main, Feb  8 2025, 10:24:47) [Clang 16.0.0 (clang-1600.0.26.6)]
  executable: /opt/local/bin/python3
  machine: macOS-15.3.2-arm64-arm-64bit
Dependency information:
  numpy: 1.26.4
  pandas: 2.2.3
  xarray: 2025.3.0
  netCDF4: 1.7.2
  packaging: 24.2
  contextily: None
  geopandas: 1.0.1
  IPython: 8.31.0
  pyarrow: None
  rioxarray: None
  gdal: 3.10.2
  ghostscript: 10.05.0
GMT library information:
  version: 6.6.0
  padding: 2
  share dir: /usr/local/gmt/share
  plugin dir: /usr/local/gmt/lib/gmt/plugins
  library path: /usr/local/gmt/lib/libgmt.dylib
  cores: 12
  grid layout: rows
  image layout:
  binary version: 6.6.0_e1f3593-dirty_2025.03.18

50e7305c-6f31-4fa1-a945-beb501956b9e.eps.zip (22.6 KB)
50e7305c-6f31-4fa1-a945-beb501956b9e.pdf (29.6 KB)

Unfortunately, I cannot figure out what happened. Namely, why the eps is in Landscape when the ps must have been created in Portrait.

@yvonnefroehlich & @Joaquim - here are a *.ps of @wthelen’s script translated to plain GMT. This one get chopped off at the right

#!/usr/bin/env zsh
gmt begin
gmt figure test ps,pdf,png
# region = [-155.72,-155.62,19.45,19.55]
gmt coast -R-155.72/-155.62/19.45/19.55 -JM8i -Ggray -Bafg
gmt end

test.ps (25.5 KB)

and another one which gets cut off at the top:

#!/usr/bin/env zsh
gmt begin
gmt figure test2 ps,pdf,png
gmt basemap -R87/89/27/31 -JD88.0/29.0/31.0/27.0/15c -Bafg
gmt end

test2.ps (26.4 KB)

Hmmm, cannot confirm that. This one-liner (same as your first example) works fine for me.

gmt coast -R-155.72/-155.62/19.45/19.55 -JM8i -Ggray -Bafg -png lixo

On my system -ps lixo gets cut while -png lixo does not. PyGMT example does not get cut either.

I downgraded versions of ghostscript from 10.04 to 10.03,10.02 and 9.56 (No other libraries changed). All had the same behavior (cut off the map).

Returning to gs 10.04, I can recreate the behavior of @Joaquim and @mkononets. I will note that the “-ps lixo” result cuts the plot on the right. It also retains the portrait orientation (unlike the .eps output from .savefig.

Now I tried different things. Overall, I think the issue is related to the “ps” format, and for me, the maps are cutoff also for gs versions lower than 10.4.0.

This works fine for me:

gmt begin
gmt figure test_no_ps pdf,png
gmt basemap -R-155.72/-155.62/19.45/19.55 -JM8i -Bafg
gmt end

but adding “ps”, leads to cutoff maps for all formats:

gmt begin
gmt figure test_with_ps ps,pdf,png
gmt basemap -R-155.72/-155.62/19.45/19.55 -JM8i -Bafg
gmt end

I face the same behaviour here, wherey png (or pdf) work:

gmt basemap -R-155.72/-155.62/19.45/19.55 -JM8i -Bafg -png lixo

but ps (or eps) leads to cutoff maps:

gmt basemap -R-155.72/-155.62/19.45/19.55 -JM8i -Bafg -ps lixo

same here.

OK, so this is what is happening.
In modern mode (PyGMT) only the non-(e)ps formats are plotted in a wall size paper (11 m), which is latter trimmed to the figures BoundingBox. With the (e)ps format, the figure is plotted on a A4 (default) paper size and if the figure overflows it, it get cropped.
Things are more clear on classic mode where we get a warning.

gmt psbasemap -R-155.72/-155.62/19.45/19.55 -JM8i -Bafg -P > lixo.ps
psbasemap [WARNING]: Your plot (WxH = 20.32 x 21.43 cm) placed at (2.54, 2.54 cm) may exceed your PS_MEDIA (WxH = 20.99 x 29.70 cm)

Thanks for tracking that down!

Now I’m trying to figure out how best to solve this issue. Setting the PS_MEDIA doesn’t change the behavior (tried a fixed size, like “B1” and a custom size). Is there a parameter that needs to be passed through the PS_CONVERT config to keep from trimming the BoundingBox? I’ve tried a few different iterations using the I flag (I+m3i, I+sm10i, I+s10i). The results are so similar that I’m not sure its actually doing anything at all.

Not sure this observation is relevant, but both users reporting the issue on PyGMT use macOS-...-arm64-arm-64bit. My Linux x86_64 system does not experience the PyGMT issue.

I have to confess that this issue got over my PostScript knowledge. I did an experiment in Julia where I do always set the wall paper size and asked an eps output … which is also cut. e.g.

basemap(R="-155.72/-155.62/19.45/19.55", J="M8i", B="afg", show=1, fmt=:eps)

Now the bloody crazy thing. Even if I delete the “BoundingBox” and “HiResBoundingBox” lines from the .eps file (attached) it still bloody knows the paper size. How’s that possible?

GMTjl_j.zip (7.0 KB)

I’m not an expert, but I think the .[e]ps viewer software always has some specific paper size pre-set. Like my gv sets A4 by default and GMTjl_j.eps gets cut. If I change paper size to A3 the GMTjl_j.eps gets enough paper to be fully displayed. Another viewer (xreader) sets US Letter paper size by default and does not let me to specify paper size manually.

if I run gmt ps2raster GMTjl_j.eps -A -Tg I get a correctly displayed and cropped png image.

It’s a bit more convoluted than that. If you take the original ps (attached) and do:

gmt psconvert GMTjl_j.ps -Te -A

you get a nice cropped eps. But if we do

gmt psconvert GMTjl_j.ps -Tg -A

than we get a nice full png image. Now the puzzling thing is that the good png was created from the bad(?) eps file (psconvert internals). How can that be?

Note, I loaded the eps file in Inkscape and even if I increase the page width, the right size remains cropped.

GMTjl_j.ps.zip (7.2 KB)