I need help making a map with jupyterlab + pygmt +others

106 views Asked by At

I am currently working on a figure and I was recommended to use PyGMT.

However, I have been facing challenges in generating the legend for my plot.

The data provided to me is in an unconventional format, and I had to adjust it, resulting in the need to work with shapefiles instead of simple .txt data.

Despite writing the code along with the assistance of ChatGPT 4, I am still stuck on generating the legend.

Here is the code that plots everything correctly but lacks the legend generation:

import pygmt
import geopandas as gpd

# Create custom color palettes
# Ocean: from deep dark blue to light blue.
ocean_cpt_data = "... (omitted for brevity) ..."

with open("ocean_custom.cpt", "w") as ocpt:
    ocpt.write(ocean_cpt_data)

# Land: from medium gray to dark gray.
land_cpt_data = "... (omitted for brevity) ..."

with open("land_custom.cpt", "w") as lcpt:
    lcpt.write(land_cpt_data)

# Combine the custom color palettes
with open("combined.cpt", "w") as combined:
    with open("ocean_custom.cpt", "r") as ocean:
        for line in ocean:
            combined.write(line)
    with open("land_custom.cpt", "r") as land:
        for line in land:
            combined.write(line)

# Read the shapefile
contours = gpd.read_file("D:/.../1960_contour.shp")

# Main map figure
fig1 = pygmt.Figure()
main_region = [-75.2, -72, -40.5, -38.2]
fig1.basemap(region=main_region, projection="M6i", frame=True)
fig1.grdimage(grid=r"D:/.../gebco.nc", cmap="./combined.cpt")

# Plotting the trench with subduction symbols
trench_shapefile = r"D:/.../trench.shp" # Adjust the path to point to your shapefile
fig1.plot(data=trench_shapefile, pen="3", style="f1c/0.3c+r+t+o0.3c+p", fill="4")

# Plot contour lines and annotate with labels from shapefile's ELEV attribute
for line, value in zip(contours.geometry, contours['ELEV']):
    x, y = line.xy
    # Plot the contour
    fig1.plot(x=x, y=y, pen="0.5p")
    # Annotate the contour
    fig1.text(x=x[len(x)//2], y=y[len(y)//2], text=str(value), font="8p,Helvetica-Bold,black", offset="0/0.2c")

min_elevation = -5500
max_elevation = 4000

legend_entries = [
    "S 0.2i f0.5c/0.3c+r+t+o0.3c+p 0.25p 0.3i black 0.4i Trench",
    "S 0.2i - 0.25p black 0.3i Contours",
    f"G 0.2i - 1i ./combined.cpt 0.4i {min_elevation}/{max_elevation} Elevation (m)"
]

# Create a temporary file to store the legend specifications
with tempfile.NamedTemporaryFile(delete=False, mode="w", suffix=".txt") as legend_file:
    for entry in legend_entries:
        legend_file.write(entry + "\n")
    legend_file_name = legend_file.name

# Add the legend to the figure
fig1.legend(position="JTR+jTR+o0.5i", box="+gwhite+p2p", spec=legend_file_name)

# Show the figure
fig1.show()    

# Inset figure (code omitted for brevity)

I would greatly appreciate any assistance or insights on how to generate the legend for this plot using PyGMT.

Thank you in advance for any help you can provide.

1

There are 1 answers

0
yvonnefroehlich On

It's difficult to help here. The posted code example is not a working example as it is not complete and no input data are provided. Are there any error or warning messages?

I tried to understand how the legend should look like, but the third entry remains unclear to me:

f"G 0.2i - 1i ./combined.cpt 0.4i {min_elevation}/{max_elevation} Elevation (m)"

I reduced your code example. The required external legend file "legend_file.txt" looks like:

# legend in GMT / PyGMT ready format

N 1
S 0.45c f+r+t 0.2i/-3/0.1i black 0.1p,black 0.4i Thrust
G 0.05c
S 0.45c - 0.3i black 1p,black 0.4i Contours
import pygmt

main_region = [-75.2, -72, -40.5, -38.2]

# Main map figure
fig = pygmt.Figure()

fig.basemap(region=main_region, projection="M6i", frame=True)

# Plot trench
fig.plot(
    x=[-74, -73],  # Use some dummy data
    y=[-40, -39],
    pen="3p",
    style="f1c/0.3c+r+t+o0.3c+p",
    fill="black",
)

# Plot contour lines
fig.plot(
    x=[-74.5, -73],
    y=[-40.4, -38.3],
    pen="0.5p",
)

# Annotate the contour lines
fig.text(
    x=-74,
    y=-39.5,
    text="depth",
    font="8p,Helvetica-Bold,black",
    offset="0/0.2c",
)

# Add the legend to the figure
# Create legend file externally
fig.legend(position="JTR+jTR+o0.5i", box="+gwhite+p2p", spec="legend_file.txt")

# Show the figure
fig.show()

# Save figure
#fig.savefig(fname="add_legend_to_plot.png")

The code produces the figure shown below. Does this legend fit to your expectation for the first two entries of your desired legend? enter image description here