GenericMappingTools / pygmt

A Python interface for the Generic Mapping Tools.
https://www.pygmt.org
BSD 3-Clause "New" or "Revised" License
754 stars 218 forks source link

Colorbar annotation size does not change #3041

Closed bjmarfito closed 7 months ago

bjmarfito commented 8 months ago

Description of the problem

I set the FONT_ANNOT_PRIMARY and FONT_LABEL to 20 but the annotation on the colorbar does not change

Minimal Complete Verifiable Example

import pygmt

pygmt.config(FONT_LABEL = 20)
pygmt.config(FONT_ANNOT_PRIMARY = 20)

fig = pygmt.Figure()
fig.colorbar(position="x+3.68i/0.38i+w1.9i/0.090i+ef+mul+h", frame="a100f50", cmap=cptFileSlip)
fig.show()

Full error message

No response

System information

PyGMT information:
  version: v0.10.0
System information:
  python: 3.11.7 (main, Dec 10 2023, 14:13:07) [Clang 15.0.0 (clang-1500.0.40.1)]
  executable: /opt/local/bin/python
  machine: macOS-14.3-arm64-arm-64bit
Dependency information:
  numpy: 1.26.2
  pandas: 2.1.1
  xarray: 2022.12.0
  netCDF4: 1.6.5
  packaging: 23.2
  contextily: None
  geopandas: None
  IPython: 8.14.0
  rioxarray: None
  ghostscript: 10.02.1
GMT library information:
  binary version: 6.5.0
  cores: 10
  grid layout: rows
  image layout: 
  library path: /opt/local/lib/gmt6/lib/libgmt.dylib
  padding: 2
  plugin dir: /opt/local/lib/gmt6/lib/gmt/plugins
  share dir: /opt/local/lib/gmt6/share/gmt
  version: 6.5.0
welcome[bot] commented 8 months ago

👋 Thanks for opening your first issue here! Please make sure you filled out the template with as much detail as possible. You might also want to take a look at our contributing guidelines and code of conduct.

weiji14 commented 8 months ago

Hmm, not very well documented at https://docs.generic-mapping-tools.org/6.5/gmt.conf.html#term-FONT_LABEL, but could you try adding p (for the unit 'point') and see if it works? E.g.:

with pygmt.config(FONT_LABEL="20p", FONT_ANNOT_PRIMARY="20p"):
    fig = pygmt.Figure()
    fig.colorbar(position="x+3.68i/0.38i+w1.9i/0.090i+ef+mul+h", frame="a100f50", cmap=cptFileSlip)
    fig.show()
bjmarfito commented 8 months ago

Hi @weiji14, your proposed fix did not work on my side.

yvonnefroehlich commented 8 months ago

Can you please try to see if it works when config is called after initializing the Figure instance:

import pygmt

size = 5

# pygmt.config(FONT_LABEL = 20)
# pygmt.config(FONT_ANNOT_PRIMARY = 20)

fig = pygmt.Figure()

pygmt.config(FONT_LABEL=20)
pygmt.config(FONT_ANNOT_PRIMARY=20)

fig.basemap(region=[-size, size, -size, size], projection=f"X{size}c", frame=True)
fig.colorbar(cmap="jet", position="jMC", frame=True)

fig.show()
# fig.savefig(fname="config_font.png")

Output figure: config_font

weiji14 commented 8 months ago

Oh yeah, I just remembered #733, the pygmt.config call needs to be placed below fig = pygmt.Figure(). E.g.:

fig = pygmt.Figure()
with pygmt.config(
    FONT_LABEL="30p,Helvetica,red", FONT_ANNOT_PRIMARY="30p,Helvetica,red"
):
    fig.colorbar(
        position="x+3.68i/0.38i+w1.9i/0.090i+ef+mul+h",
        frame="a0.2f50",
        cmap="batlow",
    )
    fig.savefig("temp30.png")
    fig.show()

produces:

temp30

bjmarfito commented 8 months ago

Hi @weiji14 , the fix still does not work on my side. The annotation font on the colorbar is still smaller compare to the grid annotation.

Screenshot 2024-02-07 at 9 55 58 AM
weiji14 commented 8 months ago

Hmm, could you post your full code, at least the part including fig.basemap? Are you plotting the colorbar in a subplot, inset or just a single figure?

bjmarfito commented 8 months ago

Hi @weiji14, here it is.

import pygmt
import os
import numpy as np

# Define the working directory and change to it
workDirectory = "/Volumes/jupiter/EQ/gmt_plot"
os.chdir(workDirectory)
currentDir = "Current working directory: " + os.getcwd()
print(currentDir)

# Referenced to epicenter
hypocenterReferenced = "y"

# Directory for slip distribution color palette
cptSlip = "/Users/bryan/tools/ScientificColourMaps8/lajolla/lajolla.cpt"
cptFileSlip = "slip.cpt"

# Directory for LOS color palette
cptLos = "/Users/bryan/tools/ScientificColourMaps8/vik/vik.cpt"
cpFileLos = "los.cpt"

# Contour color
contourColor = "white"

# Slip vector color
slipVectorColor = "white"

# Define the font size and other parameters
fontSize = 20
experimentNo = 1
slip = "/Volumes/jupiter/EQ/modelling/distributed_rectangular_slip_model/linear1/output/inverse_okada_slip_vertical_plane_linear1_exp{}.txt"\
    .format(experimentNo)
slipVector = "/Volumes/jupiter/EQ/modelling/distributed_rectangular_slip_model/linear1/output/inverse_okada_slip_vector_vertical_plane_linear1_exp{}.txt"\
    .format(experimentNo)

corner = "/Volumes/jupiter/EQ/modelling/distributed_rectangular_slip_model/linear1/output/inverse_okada_fault_corner_coords_linear1_exp{}.txt"\
    .format(experimentNo)

# Set global PyGMT parameters
pygmt.config(MAP_ANNOT_OBLIQUE = "lat_parallel")
pygmt.config(MAP_FRAME_TYPE = "plain")
pygmt.config(MAP_VECTOR_SHAPE = 0)
pygmt.config(FORMAT_GEO_MAP = "D")
pygmt.config(FONT_ANNOT_PRIMARY = 20)
pygmt.config(FONT_LABEL = 20)

# Extract the local coordinates of the epicenter
xData = np.loadtxt(slip, comments="#", delimiter=" ", unpack=False\
                   , usecols=(0))
x = xData[2]

# Extract the local coordinates of the fault corners
slipCoordinates = np.loadtxt(slip, comments="#", delimiter=" ",\
                          max_rows=1, unpack=False)

hypocenterReferenced.lower()
if hypocenterReferenced == "y":
    slipCoordinates[0] = slipCoordinates[0] - x
    slipCoordinates[1] = slipCoordinates[1] - x
else:
    pass

xmin  = slipCoordinates[0]
xmax  = slipCoordinates[1]
ymin  = slipCoordinates[2]
ymax  = slipCoordinates[3]

regslip= [xmin, xmax, ymin, ymax]

slipValue = np.loadtxt(slip, comments="#", delimiter=" ", skiprows=6)
slipValue[:,0] = slipValue[:,0] - x

slipxyz= "slip.xyz"
np.savetxt(slipxyz, slipValue, fmt="%f", delimiter=" ")

# Use gmtconvert to translate the slip file to a grid file
commandScript = "gmt gmtconvert {} -bo > slip.b".format(slipxyz)
os.system(commandScript)

# Smoothened slip distribution using a median filter
incx = "5m"
incy = "5m"
slipgrd = "slip.grd"
filteredSlipDist = pygmt.blockmedian("slip.b", binary = "i" , spacing = incx + "/" + incy, region = regslip)
pygmt.surface(filteredSlipDist,region = regslip, binary ="i3" , spacing = incx + "/" + incy, outgrid = slipgrd)

# Create a color palette for slip distribution
pygmt.makecpt(cmap=cptSlip, series=[0,300,1] , output=cptFileSlip,\
              background=True, continuous=True, reverse=True)

# Create a color palette for LOS
pygmt.makecpt(cmap=cptLos, series=[-30,30,1], background=True,\
              continuous=True, output=cpFileLos)

# Initialize the figure
fig = pygmt.Figure()
# Plot basemap
fig.basemap(projection = "X5.85i/3.58125i", region = regslip,\
                    frame = ["xa5f5+lDistance from the epicenter (km)", \
                             "y5f2.5+lDepth (km)", "WSne"], xshift = "c", yshift = "c")

# Plot the slip distribution
fig.grdimage(slipgrd, cmap = cptFileSlip)

#Plot the slip vector
slipVectorData = np.loadtxt(slipVector, comments="#", delimiter=" ", unpack=False)
slipVectorData[:,0] = slipVectorData[:,0] - x
slipVectorData[:,3] = slipVectorData[:,3] /400

# Plot the slip vector
fig.plot(data = slipVectorData, style= "v0.07i+e", fill = slipVectorColor, pen = "thin,{}".format(slipVectorColor))

# Plot the contour interval
fig.grdcontour(slipgrd, interval = 50, limit = [10, 150], \
               pen="thinnest,{}".format(contourColor), \
                annotation =(50,"f{}".format(fontSize),"r2"), \
                label_placement = "d3.1i"
                )

fig.grdcontour(slipgrd, interval = 50, limit = [170, 250], \
               pen="thinnest,{}".format(contourColor), \
                annotation =(50,"f{}".format(fontSize),"r2"), \
                label_placement = "d3.1i"
                )

# Extract epicenter value and plot it
epicenterValue = np.loadtxt(slip, comments="#", delimiter=" ", skiprows=5, max_rows=1)
epicenterValue = epicenterValue[0:2]
epicenterValue[0] = epicenterValue[0] - x
epicenterValue[1] = -1 * epicenterValue[1]
fig.plot(x=epicenterValue[0],y=epicenterValue[1], style = "a0.3i", fill="red", pen="1,black")

# Save the figure
fig.savefig("slip.pdf", dpi=300)
#fig.show()
weiji14 commented 8 months ago

Hmm, I don't see where you are calling fig.colorbar, and all your pygmt.config calls are still above the fig = pygmt.Figure() line. Is this the correct modified version?

bjmarfito commented 8 months ago

Hi @weiji14, this is the modified version. Still does not work on my side. Sorry about the wrong code I posted.

import pygmt
import os
import numpy as np

# Define the working directory and change to it
workDirectory = "/Volumes/jupiter/EQ/modelling/inversion_kaj"
os.chdir(workDirectory)
currentDir = "Current working directory: " + os.getcwd()
print(currentDir)

# Referenced to epicenter
hypocenterReferenced = "y"

# Directory for slip distribution color palette
cptSlip = "/Users/bryan/tools/ScientificColourMaps8/lajolla/lajolla.cpt"
cptFileSlip = "slip.cpt"

# Directory for LOS color palette
cptLos = "/Users/bryan/tools/ScientificColourMaps8/vik/vik.cpt"
cpFileLos = "los.cpt"

# Contour color
contourColor = "white"

# Slip vector color
slipVectorColor = "white"

# Shoreline style
shorelineStyle = "2"

# Subsurface slip projection
subslipProjection  = "X5.85i/3.58125i"

# Surface deformation projection
surfaceDefProjection = "M3i"

# Satellite data region
satRegion =[69.2,69.9,32.8,33.3]

# Define the font size and other parameters
fontSize = 20
experimentNo = 1
slip = "/Volumes/jupiter/EQ/modelling/inversion_kaj/slipData_GMTplot.txt"
slipVector = "/Volumes/jupiter/EQ/modelling/distributed_rectangular_slip_model/linear1/output/inverse_okada_slip_vector_vertical_plane_linear1_exp{}.txt"\
    .format(experimentNo)

corner = "/Volumes/jupiter/EQ/modelling/distributed_rectangular_slip_model/linear1/output/inverse_okada_fault_corner_coords_linear1_exp{}.txt"\
    .format(experimentNo)

# Set global PyGMT parameters
pygmt.config(MAP_ANNOT_OBLIQUE = "lat_parallel")
pygmt.config(MAP_FRAME_TYPE = "plain")
pygmt.config(MAP_VECTOR_SHAPE = 0)
pygmt.config(FORMAT_GEO_MAP = "D")
pygmt.config(FONT_ANNOT_PRIMARY = "20p,Helvetica")
pygmt.config(FONT_LABEL = "20p,Helvetica")

# Extract the local coordinates of the epicenter
xData = np.loadtxt(slip, comments="#", delimiter=" ", unpack=False\
                   , usecols=(0))
x = xData[2]

# Extract the local coordinates of the fault corners
slipCoordinates = np.loadtxt(slip, comments="#", delimiter=" ",\
                          max_rows=1, unpack=False)

hypocenterReferenced.lower()
if hypocenterReferenced == "y":
    slipCoordinates[0] = slipCoordinates[0] - x
    slipCoordinates[1] = slipCoordinates[1] - x
else:
    pass

xmin  = slipCoordinates[0]
xmax  = slipCoordinates[1]
ymin  = slipCoordinates[2]
ymax  = slipCoordinates[3]

regslip= [xmin, xmax, ymin, ymax]

slipValue = np.loadtxt(slip, comments="#", delimiter=" ", skiprows=6)
slipValue[:,0] = slipValue[:,0] - x

slipxyz= "slip.xyz"
np.savetxt(slipxyz, slipValue, fmt="%f", delimiter=" ")

# Use GMT convert to convert the slip file to a grid file
commandScript = "gmt gmtconvert {} -bo > slip.b".format(slipxyz)
os.system(commandScript)

# Smoothened slip distribution using a median filter
incx = "5m"
incy = "5m"
slipgrd = "slip.grd"
filteredSlipDist = pygmt.blockmedian("slip.b", binary = "i" , spacing = incx + "/" + incy, region = regslip)
pygmt.surface(filteredSlipDist,region = regslip, binary ="i3" , spacing = incx + "/" + incy, outgrid = slipgrd)

# Create a color palette for slip distribution
pygmt.makecpt(cmap=cptSlip, series=[0,300,1] , output=cptFileSlip,\
              background=True, continuous=True, reverse=True)

# Create a color palette for LOS
pygmt.makecpt(cmap=cptLos, series=[-30,30,1], background=True,\
              continuous=True, output=cpFileLos)

# Initialize the figure
fig = pygmt.Figure()
with pygmt.config(FONT_LABEL="20p,Helvetica", FONT_ANNOT_PRIMARY="20p,Helvetica"):
# Plot basemap
    fig.basemap(projection = subslipProjection, region = regslip,\
                    frame = ["xa5f5+lDistance from the epicenter (km)", \
                             "y5f2.5+lDepth (km)", "WSne"], xshift = "c", yshift = "c")

    # Plot the slip distribution
    fig.grdimage(slipgrd, cmap = cptFileSlip)

    # Plot the slip vector
    # slipVectorData = np.loadtxt(slipVector, comments="#", delimiter=" ", unpack=False)
    # slipVectorData[:,0] = slipVectorData[:,0] - x
    # slipVectorData[:,3] = slipVectorData[:,3] /400

    # Plot the slip vector
    # fig.plot(data = slipVectorData, style= "v0.07i+e", fill = slipVectorColor, pen = "thin,{}".format(slipVectorColor))

    # Plot the contour interval
    fig.grdcontour(slipgrd, interval = 50, limit = [10, 150], \
               pen="thinnest,{}".format(contourColor), \
                annotation =(50,"f{}".format(fontSize),"r2"), \
                label_placement = "d3.1i"
                )

    fig.grdcontour(slipgrd, interval = 50, limit = [170, 250], \
               pen="thinnest,{}".format(contourColor), \
                annotation =(50,"f{}".format(fontSize),"r2"), \
                label_placement = "d3.1i"
                )

    fig.colorbar(position="x+3.68i/0.38i+w1.9i/0.090i+ef+mul+h", frame="a100f50", \
                 cmap=cptFileSlip)
    fig.text(text="cm", x = 9.0, y= -9.2)
    fig.text(text = "SW", x = 11.2, y= 0.4)
    fig.text(text = "NE", x = -5, y= 0.4)

    # Extract epicenter value and plot it
    epicenterValue = np.loadtxt(slip, comments="#", delimiter=" ", skiprows=5, max_rows=1)
    epicenterValue = epicenterValue[0:2]
    epicenterValue[0] = epicenterValue[0] - x
    epicenterValue[1] = -1 * epicenterValue[1]
    fig.plot(x=epicenterValue[0],y=epicenterValue[1], style = "a0.3i", fill="red", \
             pen="1,black")

    # Plot the data points
    fig.coast(region = satRegion, land=contourColor, resolution="f",\
               shorelines = shorelineStyle, projection = surfaceDefProjection, \
                water = "azure", frame = ["WSne", "xa.3f.3","y.2f.2" ], xshift = -10, yshift = -3)
    # Save the figure
    fig.savefig("slip.pdf", dpi=300)
    #fig.show()
yvonnefroehlich commented 8 months ago

Thanks @bjmarfito for posting your code (if you write ```python at the beginning of your code block your get code highlighting related to python 🙂).

The annotation font on the colorbar is still smaller compare to the grid annotation.

Just to be clear about your question: Is your issue, that the font size does not change via pygmt.config() or that map frame annotations and colorbar annotations do not appear in the same font size?

bjmarfito commented 8 months ago

Hi @yvonnefroehlich, the issue is the first one where the colorbar annotation font size does not change.

seisman commented 8 months ago

@bjmarfito Both @yvonnefroehlich and @weiji14's examples work for me, so I bet there must be something wrong on your side. You need to provide all datasets used in your script or provide a minimal example so that we can reproduce your issue. Otherwise, there will be very little we can do to help you.

seisman commented 7 months ago

I'm closing the issue now.

yvonnefroehlich commented 6 months ago

@bjmarfito I am wondering whether your issue is simliar to the issue reported in this Forum post. Please see the updated GMT documentation at https://docs.generic-mapping-tools.org/dev/colorbar.html#description for details on this change.

bjmarfito commented 6 months ago

Hi @yvonnefroehlich, yes this is the issue. I tried it the example code on the forum post and it worked by adding --FONT_ANNOT_PRIMARY=20 to thegmt colorbar command.

How will I implement this in PyGMT?

yvonnefroehlich commented 5 months ago

@bjmarfito please apologize for my late response; I probably overlooked this issue as it is already closed... 🙁.

You can try changing the font size due to changing the GMT defaults locally. Here is a generall example:

import pygmt

size = 5

# (I)
fig = pygmt.Figure()
fig.basemap(region=[-size, size, -size, size], projection=f"X{size}c", frame=1)
fig.colorbar(cmap="batlow", position="jMC", frame=["x+lquantity", "y+lunit"])
fig.show()

# (II)
fig = pygmt.Figure()
fig.basemap(region=[-size, size, -size, size], projection=f"X{size}c", frame=1)
# local changes of GMT defaults via context manager
with pygmt.config(
    FONT_ANNOT_PRIMARY="17p,blue", 
    FONT_ANNOT_SECONDARY="15p,darkgreen",
    FONT_LABEL="20p,orange",
):
    fig.colorbar(cmap="batlow", position="jMC", frame=["x+lquantity", "y+lunit"])
fig.show()
(I) (II)
colorbar_font_650 colorbar_font_650_locally
bjmarfito commented 5 months ago

It works now. Thank you @yvonnefroehlich!