The gmt figure construct for modern node

Added by Paul 5 months ago

To simplify figure creation under GMT Modern, consider the figure construct:

gmt figure [ formats name ]

Scripts that wish to make several figures can issue several gmt figure calls. Each figure call will
  1. Increment the number of figures the current session will make,
  2. Set the desired output format(s) for each figure,
  3. Set the name of each figure.

Then, when gmt end comes along it can complete the half-baked PostScript plots and turn them into the desired products. Users are still allowed to call gmt psconvert to do custom things and will in that case not necessarily use gmt figure at all. However, we expect that vast majority of scripts to use gmt figure. For instance, this simple bash script makes two PDF plots and one PNG:

gmt begin
gmt figure norway pdf,png
gmt pscoast -ENO+r1 -Gred -B -JM6ih -N1/thick
gmt figure sweden pdf
gmt pscoast -ESE+r1 -Gred -B -N1/thick
gmt end

The hidden calls to psconvert that take place will consult the (new) GMT defaults PS_CONVERT which may be used to set things like the -A -E, etc.


Replies (3)

RE: The gmt figure construct for modern node - Added by Leonardo 5 months ago

I can think of a few possible implementations of gmt figure in the Python wrapper.

Straight forward porting of all commands:

gmt.begin()
gmt.figure(fname='norway', format=['pdf', 'png'])
gmt.pscoast(E='NO+r1', G='red', B=True, J='M6ih', N='1/thick')
gmt.figure(fname='sweden.pdf')  # Can guess the format from the file name extension
gmt.pscoast(E='SE+r1', G='red', B=True, N='1/thick')
gmt.end()

Using context managers to get rid of the call to gmt.end() (it will be done automatically when exiting the block of code):

with gmt.begin():
    gmt.figure(fname='norway', format=['pdf', 'png'])
    gmt.pscoast(E='NO+r1', G='red', B=True, J='M6ih', N='1/thick')
    gmt.figure(fname='sweden.pdf')
    gmt.pscoast(E='SE+r1', G='red', B=True, N='1/thick')

Using context managers to get rid of both begin and end.
They will be called automatically for each figure by the context manager machinery in Python.
This is safe because figure is a modern mode exclusive command:

with gmt.figure(fname='norway', format=['pdf', 'png']):
    gmt.pscoast(E='NO+r1', G='red', B=True, J='M6ih', N='1/thick')
with gmt.figure(fname='sweden.pdf'):
    gmt.pscoast(E='SE+r1', G='red', B=True, N='1/thick')

When using the Jupyter notebook, one usually wants to see the figure inlined in the notebook.
Exiting the gmt.figure context manager can trigger a call to gmt.psconvert to get a PNG in a temporary file (could it be returned as a binary through a virtual file instead?).
The PNG can be embedded in the notebook using IPython.display.Image and then deleted.

Paul, would it be possible to use gmt figure without any arguments to just start a new .ps file?
In this case, gmt end wouldn't do anything to this figure.
That wouldn't be very useful for the command-line interface but in Python one does not always want the figure in a file (when using Jupyter notebooks, for example).
When no arguments are given, getting the figure file would be done through a standard gmt psconvert.

So if you don't want a figure file, just a preview in the notebook, you could write:

with gmt.figure():
    gmt.pscoast(E='NO+r1', G='red', B=True, J='M6ih', N='1/thick')
with gmt.figure():
    gmt.pscoast(E='SE+r1', G='red', B=True, N='1/thick')

That is a lot less code.

RE: The gmt figure construct for modern node - Added by Paul 5 months ago

Sure, I think anything is possible. We will need to define what gmt figure can do and then implement it. We do have ways to return images via virtual files and in the gmtmex we are receiving images from psconvert in memory. The only thing we do not have reliably working is having psconvert (actually ghostscript) uses pipes instead of files for its input/output).

RE: The gmt figure construct for modern node - Added by Paul 5 months ago

The gmt figure construct has been implemented in trunk and seems to work. Here are some notes regarding the implementation and things that changed in order to make it word as advertised:

  1. The hidden half-baked PS files now have extension *.ps- instead of *.ps0
  2. When psconvert completes these plot files the extension changes to *.ps+ to prevent any repeated conversions.
  3. When gmt figure is used the hidden plots are numbered from 1, 2, etc, while if gmt figure is not used then there is only a single hidden plot numbered 0.
  4. The default plot format for command line use is PDF.

There remains some inefficiencies when many formats are requested as psconvert does not yet allow for multiple outputs (other than EPS plus one raster). This will be implemented at some point.

(1-3/3)