A subplot proposal for GMT modern mode

Added by Paul 3 months ago

Background

Many environments, such as MATLAB and Python (matplotlib), have commands that simplify the plotting of multiple panels on the same figure. GMT can also do this but it falls on the user to compute sensible values for panel dimensions, offsets, margins, etc., and to navigate among the slots, do the plotting, and perhaps add labels like a), b) to each panel. Perhaps a main title is desired as well and plotted with pstext separately. In GMT classic mode, doing this successfully is considered a rite of passage and young GMT warriors will paint a small triangle on their forehead to announce their prowess. In GMT modern, we aim to simplify this process, hence this proposal.

The subplot command

The subplot command comes in two modes: 1) To initialize a new sub-divided figure, and 2) to finalize the figure. Between these two we are plotting subplots. We discuss these modes separately.

1. Initializing a new subplot figure

gmt subplot begin nrows x columns [ -Aa|1[)][+cdx/dy][+j|Jrefpoint][+gfill][+odx/dy][+ppen][+r|R]][+v] ] [-Fwidth/height] [ -Llayout ] [-Mm|p margins ] [ -Ttitle ] [-V ]

The various required and optional arguments are:

  1. begin indicates that this is the start of a new sub-divided figure.
  2. The required nrows x columns argument sets the layout and total number of subplots to make space for.
  3. The -A option optionally allows automatic tagging of the panels. The first character is either a letter or a number and determines what type of label will be placed for each panel. For instance, -Ac) will place the tags c), d), e), ... since we started at c. The order is normally increased horizontally following rows but you can append +v to use a vertical column order instead. Note the use of the parenthesis in -A to indicate we want to typeset the tag using that format. The default if just giving -A is -Aa). The tags are placed in the TL corner but can be changed with +j or +J. Standard offset (+o), clearance (+c) and justifications of that tag apply (as for scales and legends). Can also do roman numerals via +r (+R for upper case). Place a filled/outline rectangle behind the tag is optional. The tag is typeset using the new FONT_TAG setting.
  4. The optional -F option sets the dimensions of the entire set of subplots [the current media dimension].
  5. The optional -L option determines the layout and may be set for both rows (-LR) and columns (-LC). The -LC option states that each column of panels share the same x-range and only the first (above) and last (below) rows will have x annotations. Append t or b to select only one of those two rows. Append +l to indicate these annotated x-axes will have an axis label [none]. If the axis label is constant then you can supply the label here. Similarly, the -LR option states that each row of panels share the same y-range and only the first (left) and last (right) column will have y-annotations. Append l or r to select only one of those two columns. Append +l to indicate these annotated y-axes will have an axis label [none]. If the axis label is constant then you can supply the label here.
  6. The -M option can specify two separate types of margins: The -Mm option sets the media margins. These apply to printed media where the printer may not be capable of plotting close to the paper edge. If preparing illustrations where you want to maximize plot space you will need to set these to avoid clipping on the printer (or auto-shrinking) [0/0]. The -Mp option sets the margins for each panel and ensures there is space around each plotted panel [1c/1c]. You can give, one, two, or four number to get a constant, x/y, or individual side margins.
  7. The optional -T sets the figure title. It will be typeset centered and above the matrix of subplots, using font and offset settings from the new FONT_HEADING and MAP_HEADING_OFFSET defaults.

2. Setting the current subplot focus

Having initialized the subplots you can now use the -c option to select the current plot panel by giving a row and column combination, e.g., -c2,1. Alternatively you can use gmt subplot row,col. The latter is the required option if you also need to specify a gap on any of the sides via -G side\ /*gap*.

3. Finalize the subplot

gmt subplot end

Once you have finished plotting all the subplots you wish to plot you stop the figure compositioning with the end command. This exits the subplot mode and resets the current plot origin to what it was prior to the begin command.

Technical comments

  1. The begin command will implicitly set MAP_ANNOT_ORTHO to be empty, meaning both x and y annotations will be plotted parallel to their axes. This avoids wasting too much horizontal space on large y-axis annotations. We also request plain map frame type for geographic maps and let latitude annotation be parallel to the axes.
  2. The settings of fonts and offsets in effect when begin is called will be used to compute dimensions and offsets required by gmt subplot -c.
  3. For Cartesian plots life is simple, since both the width and height of the panel plot are determined exactly. When plotting to the current subplot you do not specify any -J setting as it is already set for you. For geographic maps there is the issue that the subplot height, given a width and a region, may in fact exceed the panel height. The solution we have implemented is to ensure that the plot fits within the given panel dimensions, and if the natural map height exceeds the panel height we reduce the map width proportionally so it fits. This is done by each -c command since there is no requirement that each panel must use the same projection (or region). Only the first plot command for a panel may use -c.
  4. You do not have to plot all of the panels.
  5. If your rows must have different heights then you must consider each row a separate subplot and just plot several subplots with different dimensions (see -F).
  6. The -c was used in GMT 4 for "number of copies but was retired in GMT5. Here, it is resurrected under modern mode. In classic mode it will continue to be processed as before under compatibility mode.
  7. The first plot command for a new panel requires -c while subsequent plot calls will continue to plot in the current panel. The current panel row, col is written to gmt.panel so that subsequent commands will know which is the current panel (unless another -c is given).
  8. Implementation: The subplot.c code will perform all calculations regarding dimensions, offsets, standard frame settings, etc and write this to gmt.subplot as one record per panel. The -c option reads the corresponding information, prepares new options, and inserts them into the option list ahead of the GMT_Parse_Common call. This way the module gets the correct settings and history will be updated for the following modules (until another panel is selected with -c).
  9. The subplot end command exits the subplot mode and removes the gmt.subplot and gmt.panel files.

Example

The attached files shows an example of a 3x2 figure. The figure.pdf shows the final result while figure_lines.pdf shows the same plot with various helper lines indicating margins, etc. The script subplot.sh made the figure. You can play with it and change margins and options like title etc., but the 3x2 is hardwired for this mockup figure. Following the guidelines above, a GMT modern script for making this plot intended for a PDF (so we ignore paper margins) would be written thus. Here all panels share the same region and we set -L accordingly:

gmt begin Figure pdf
  gmt subplot begin 3x2 -A+v -LCb+l”Distance along track (km)” -LRl+l”Elevation (m)” -T”All my profiles" -Mp0.2i -R0/100/0/50
  gmt psbasemap -c1,1 -B
  gmt psbasemap -c1,2 -B
  gmt psbasemap -c2,1 -B -B+glightpink
  gmt psbasemap -c2,2 -B -B+glightpink
  gmt psbasemap -c3,1 -B
  gmt psbasemap -c3,2 -B
gmt subplot end
gmt end

This 10-line script compares very favorably with a classic script where all the dimension and position calculations, as well as labeling, must be done explicitly.

Figure.pdf - Final figure intended for PDF use (7.95 KB)

Figure_lines.pdf - Figure with helper lines and showing grayed out paper edge. (8.08 KB)

subplot.sh Magnifier (4.42 KB)


Replies (2)

RE: A subplot proposal for GMT modern mode - Added by Leonardo 3 months ago

Hi Paul, I really like the idea of having a "subplot" command. I use this a lot in matplotlib for quick figures. This GMT feature will probably be better because matplotlib has a bit of trouble with adjusting the subplots when colorbars and projections are involved. This will be a big selling point for GMT/Python.

One suggestion to the interface based on how matplotlib behaves (I don't know how feasible it would be to implement):

gmt begin
    gmt figure my_figure pdf -T”All my profiles" 
    gmt subplot begin 2x3 -LCb+l”Distance along track (km)” -LRl+l”Elevation (m)” -Mp0.2i -R0/100/0/50
        gmt subplot 1,1 -Aa)
        gmt psbasemap -B
        gmt subplot 1,2 -Ab)
        gmt psbasemap -B
        gmt subplot 1,3 -Ac)
        gmt psbasemap -B -B+glightpink
        gmt subplot 2,1 -A1.
        gmt psbasemap -B -B+glightpink
        gmt subplot 2,2 -A2.
        gmt psbasemap -B
        gmt subplot 2,3 -A3.
        gmt psbasemap -B
    gmt subplot end
gmt end
  • -T is very useful even when no subplots are being made. Since it sets the title for the figure, it makes sense that it should belong to "gmt figure".
  • Using the plain "gmt subplot" command to set the current subplot would free all other modules from "-c". This way, the plotting code doesn't need to know that it's in a subplot and looks the same. It adds lines of code but simplifies getting commands out of subplots or changing subplot order (no need to change all the "-c"s, just reorder the subplot commands).
  • -A is something I had to do manually on matplotlib and it was such a pain. Love it! It's useful that it's auto generated. It would also be good to optionally pass it as part of each subplot command. Then one can use it to set the labels in whatever order, not just alphabetical.

These changes give more weight to the "gmt figure" command and makes it more useful overall. Having "-T" provides an incentive for using it even when making single figure scripts. Otherwise, I can very well imagine seeing people using "subplot begin 1x1" just to have access to -T.

Would it be useful to set "-R" in "gmt figure"? That way all plotting commands can get it from the hidden file instead of having to pass it to the first command.

RE: A subplot proposal for GMT modern mode - Added by Paul 3 months ago

Sorry, forgot to reply to this but we spoke -:). I have also made some changes above to some of the syntax.

  1. As we discussed, no simple mechanism to place that figure title. One would have to keep track of how a figure is built up to know its true height. This is pretty daunting and we decided long ago not to bother knowing the exact dimensions within GMT.
  2. I have implemented gmt subplot row,col but also -c. I certainly will prefer -c since it saves one line per panel.
  3. Letting subplot begin accept -R should be doable. I have not done that yet but should be fairly simple to have it included in the history so that the first panel call will obtain -R that way.

(1-2/2)