Plot multiple triangles/mesh with single call to fig.plot?

Hi! I’m new to pygmt (it’s amazing!) and have a quick question. What is the preferred way to plot multiple triangles (e.g., from a triangulated mesh) with a single fig.plot call? I’m asking because I’d like to plot 100-100k of these and looping is too slow.

A MWE of a sequential two triangle (one red and one blue) example is below. I thought a first thing to do would be to learn how to plot both of these with a single call to fig.plot.

Thoughts and guidance much appreciated!

import pygmt

fig = pygmt.Figure()
fig.plot(x=[-130, -125, -127], y=[35, 40, 39], color="red", pen="1.0p,black")
fig.plot(x=[-126, -125, -127], y=[35, 38, 37], color="blue", pen="1.0p,black")
fig.show()

I believe you want to color your triangles based on numerical values, right? If so, you can simply create a CPT file, and pass a 2D list or 2D numpy array to color.

Here are two examples that may help you:

Thanks for the CPT file suggestion. I still have a more basic question: How to structure the triangle vertex data so that I can plot these with a single call to fig.plot. Right now I do it with multiple calls but this gets too slow for thousands of triangles. Is there a way to structure the vertices so that for multiple triangles I can call like:

fig.plot(x_vertices_for_all_triangles, y_vertices_for_all_triangles, …)

I’m still looking to learn how to package the vertices for multiple triangles to work this way. Guidance much appreciated!

I thought you want to plot triangle symbols at data points, but actually what you want is plotting triangular mesh grids.

To plot multiple triangle meshes, you need to pass a multi-segments file to GMT. Unfortunately, PyGMT still lacks the Pythonic support of multi-segment files. So you have to prepare the multi-segment file manually and then pass the file name to Figure.plot().

Here is an exmaple script. > -Z1 marks the start of a new segment, and -Z1 controls the zvalue (i.e., the color) for the current polygon (i.e., triangle in this example):

import pygmt
fig = pygmt.Figure()
with open("mesh.dat", "w") as fp:
    fp.write("> -Z1\n")
    fp.write("-130 35\n")
    fp.write("-125 40\n")
    fp.write("-127 39\n")
    fp.write("> -Z2\n")
    fp.write("-126 35\n")
    fp.write("-125 38\n")
    fp.write("-127 37\n")
pygmt.makecpt(cmap="inferno", series=(0, 5, 1))
fig.basemap(region=[-135, -120, 30, 45], projection="H10c", frame=True)
fig.plot(data="mesh.dat", pen="1p", close=True, color="+z", cmap=True)
fig.colorbar()
fig.show()

Here is the output:

1 Like

Thank you so much for this response. This makes total sense and is a very cool way to do this. Thanks!

I am glad I found this Forum posting. I was trying to figure out how to get PyGMT to read a GMT multi-segment file and I could not find it in the documentation. It is so easy to just pass the filename of the file. I was thinking I would need to do my own parsing to get it into the X and Y arrays, but it is already in there.