Horizontal Legend

Hi Everyone,

I am trying to create a legend, but instead of the default (as shown here) - I want to make it so that it looks like this https://docs.generic-mapping-tools.org/6.3/legend.html (so the magnitudes are horizontal).

Here is my code for the vertical legend:


import pygmt

pygmt.config(FORMAT_GEO_MAP="ddd.x", MAP_FRAME_TYPE="plain")
pr_reg = [-120,-105,45,55]
gridfile = pygmt.datasets.load_earth_relief(resolution="15s", region=pr_reg)

fig = pygmt.Figure()

fig.grdimage(region=pr_reg, grid=gridfile, projection="M10c", 
             cmap="gray", frame=['WSen', "xa5.0f1.0", "ya2.0f1.0"],
             transparency=20)

fig.coast(region=pr_reg, projection="T-117/10c", shorelines=True,
          map_scale="-119/45.97/1/50+lkm")

## Mw scaled by size ##
mw1=0.04*(2**1)
mw1s='c'+str(mw1)+'c'
mw2=0.04*(2**2)
mw2s='c'+str(mw2)+'c'
mw3=0.04*(2**3)
mw3s='c'+str(mw3)+'c'
mw4=0.04*(2**4)
mw4s='c'+str(mw4)+'c'
mw5=0.04*(2**5)
mw5s='c'+str(mw5)+'c'

fig.plot(x=-110, y=50, style=mw1s,
          color='white', pen='black', label='"Mw 1"')
fig.plot(x=-115, y=48, style=mw2s,
          color='white', pen='black', label='"Mw 2"')
fig.plot(x=-118, y=51, style=mw3s,
          color='white', pen='black', label='"Mw 3"')
fig.plot(x=-117.5, y=49, style=mw4s,
          color='white', pen='black', label='"Mw 4"')
fig.plot(x=-107, y=52.5, style=mw5s,
          color='white', pen='black', label='"Mw 5"')

fig.legend(position="x+6.5/0.1+o0.2c", box='+gwhite+p1p')

fig.show()

Any ideas on how to make the legend horizontal would be great :slight_smile:

Thank you!

Hello @beckysalvage,

unfortunately, for auto-legends in GMT, the number of columns cannot be specified and it is always 1.

For a legend with multiple columns, users have to write a specific input file instead of using the label parameter of the single plotting methods. For details on the Legend Codes, please see the upstream GMT documentation at https://docs.generic-mapping-tools.org/6.4/legend.html#legend-codes. To get multiple columns, add N number_of_columns at the top of the file.

This was also an issue discussed at the PyGMT GitHub repository (please see https://github.com/GenericMappingTools/pygmt/issues/2603). There I posted an example based on a gallery example showing how to set up such an input file (please see comment (https://github.com/GenericMappingTools/pygmt/issues/2603#issuecomment-1632664981).

Modifier +Nncols to -l allows setting the number of columns. Perhaps not available in PyGMT?

1 Like

It’s available in PyGMT, but I did not know this! Thanks a lot @pwessel. That’s great, was really missing this possibility. I though there should be a modifier for legend to force multi-column legends, but the specifications has to be made together with the argument passed to the label parameter of plot.

# Based on Gallery example: https://www.pygmt.org/latest/gallery/embellishments/legend.html#sphx-glr-gallery-embellishments-legend-py
# Last acces: 2023/10/20

import pygmt

fig = pygmt.Figure()

# -----------------------------------------------------------------------------
# Left: Vertical (one column) legend
fig.basemap(projection="x2c", region=[0, 7, 3, 7], frame=True)

fig.plot(
    data="@Table_5_11.txt",
    style="c0.40c",
    fill="lightgreen",
    pen="faint",
    label="Apples",
)
fig.plot(data="@Table_5_11.txt", pen="1.5p,gray", label="My lines")
fig.plot(data="@Table_5_11.txt", style="t0.40c", fill="orange", label="Oranges")

fig.legend(position="JTR+jTR+o0.2c", box=True)

fig.shift_origin(xshift="+w1c")

# -----------------------------------------------------------------------------
# Right: Horizontal (three columns) legend
fig.basemap(projection="x2c", region=[0, 7, 3, 7], frame=True)

fig.plot(
    data="@Table_5_11.txt",
    style="c0.40c",
    fill="lightgreen",
    pen="faint",
    # +N sets columns of the legend corresponding to the given number
    label="Apples+N3",
)
fig.plot(data="@Table_5_11.txt", pen="1.5p,gray", label="My lines")
fig.plot(data="@Table_5_11.txt", style="t0.40c", fill="orange", label="Oranges")

# For multi-column legends users have to provide the width via +w
fig.legend(position="JTR+jTR+w7c+o0.2c", box=True)

fig.show()

# fig.savefig(fname="multi_col_legend.png")

Output:

1 Like

It goes with -l since you may not want a fixed number of columns for the entire legend.

@pwessel and @yvonnefroehlich - Thank you so much, this is exactly what I was after! :slight_smile:

Thanks @pwessel for this background information regarding the implementation.