Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pygmt.config: pen settings are not reverted correctly when set in a context manager #3252

Open
seisman opened this issue May 15, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@seisman
Copy link
Member

seisman commented May 15, 2024

Haven't found time to see why it doesn't work.

Here is the minimal example:

import pygmt

fig = pygmt.Figure()

fig.basemap(region=[0, 10, 0, 10], projection="X10c", frame=True)

fig.shift_origin(xshift="w+1")
with pygmt.config(MAP_FRAME_PEN="4p,blue"):
    fig.basemap(region=[0, 10, 0, 10], projection="X10c", frame=True)

fig.shift_origin(xshift="w+1")
fig.basemap(region=[0, 10, 0, 10], projection="X10c", frame=True)
fig.show()

The 3rd basemap is expected to have the default frame pen setting. Now the pen color is correct, but the pen thickness is incorrect:

Actual Expected
map map

The expected image is produced by:

gmt begin map
    gmt basemap -R0/10/0/10 -JX10c -Baf
    gmt basemap -R0/10/0/10 -JX10c -Baf -Xw+1c --MAP_FRAME_PEN=3p,blue
    gmt basemap -R0/10/0/10 -JX10c -Baf -Xw+1c
gmt end show
@seisman seisman added the bug Something isn't working label May 15, 2024
@seisman
Copy link
Member Author

seisman commented May 15, 2024

Currently, pygmt.config is implemented (in PR #293) like a context manager. When entering the context manager, we first get the current values of GMT configurations, store them in a dictionary, and then call gmt set to set the GMT configurations to new values. When exiting the context manager, we then restore the old values of GMT configurations by using gmt set again.

THe current values of GMT configurations are obtained by calling the GMT API function GMT_Get_Default (or the Session.get_default wrapper), but this function doesn't work as we expected.

The following test explains what's happening:

In [1]: from pygmt.clib import Session

# Get the current value
In [2]: with Session() as lib:
   ...:     print(lib.get_default("MAP_FRAME_PEN"))
   ...:
black   

# Set to a new value
In [3]: with Session() as lib:
   ...:     lib.call_module("set", "MAP_FRAME_PEN=4p,blue")
   ...:

# Get the current value
In [4]: with Session() as lib:
   ...:     print(lib.get_default("MAP_FRAME_PEN"))
   ...:
4p,blue

# Restore to the old value
In [5]: with Session() as lib:
   ...:     lib.call_module("set", "MAP_FRAME_PEN=black")
   ...:

# Check the current value
In [6]: with Session() as lib:
   ...:     print(lib.get_default("MAP_FRAME_PEN"))
   ...:
4p,black

The main issue is that Session.get_default("MAP_FRAME_PEN") returns black, but we expect a string like thicker,black. The string is returned from the gmt_putpen function (https://github.com/GenericMappingTools/gmt/blob/master/src/gmt_support.c#L7555). I think this is the desired behavior of the function, and it's not an upstream bug.

@seisman
Copy link
Member Author

seisman commented May 19, 2024

Here is the output from gmt defaults in modern mode. It seems that, all PEN related configurations have the value black, rather than something like default,black. So, I expect all other PEN-related configurations have the same issue.

>>> from pygmt.clib import Session
>>> with Session() as lib:
...    lib.call_module("defaults", "")
#
# GMT 6.5.0 Defaults file
#
# COLOR Parameters
#
COLOR_BACKGROUND               = black
COLOR_FOREGROUND               = white
COLOR_CPT                      = turbo
COLOR_NAN                      = 128
COLOR_MODEL                    = none
COLOR_HSV_MIN_S                = 1
COLOR_HSV_MAX_S                = 0.1
COLOR_HSV_MIN_V                = 0.3
COLOR_HSV_MAX_V                = 1
COLOR_SET                      = #0072BD,#D95319,#EDB120,#7E2F8E,#77AC30,#4DBEEE,#A2142F
#
# DIR Parameters
#
DIR_CACHE                      = /home/seisman/.gmt/cache
DIR_DATA                       = 
DIR_DCW                        = /home/seisman/opt/miniforge/envs/pygmt/share/dcw-gmt
DIR_GSHHG                      = /home/seisman/opt/miniforge/envs/pygmt/share/gshhg-gmt
#
# FONT Parameters
#
FONT_ANNOT_PRIMARY             = auto,Helvetica,black
FONT_ANNOT_SECONDARY           = auto,Helvetica,black
FONT_HEADING                   = auto,Helvetica-Bold,black
FONT_LABEL                     = auto,Helvetica,black
FONT_LOGO                      = 8p,Helvetica,black
FONT_SUBTITLE                  = auto,Helvetica-Bold,black
FONT_TAG                       = auto,Helvetica,black
FONT_TITLE                     = auto,Helvetica-Bold,black
#
# FORMAT Parameters
#
FORMAT_CLOCK_IN                = hh:mm:ss
FORMAT_CLOCK_OUT               = hh:mm:ss
FORMAT_CLOCK_MAP               = hh:mm:ss
FORMAT_DATE_IN                 = yyyy-mm-dd
FORMAT_DATE_OUT                = yyyy-mm-dd
FORMAT_DATE_MAP                = yyyy-mm-dd
FORMAT_GEO_OUT                 = D
FORMAT_GEO_MAP                 = ddd:mm:ssF
FORMAT_FLOAT_OUT               = %.12g
FORMAT_FLOAT_MAP               = %.12g
FORMAT_TIME_PRIMARY_MAP        = full
FORMAT_TIME_SECONDARY_MAP      = full
FORMAT_TIME_STAMP              = %Y %b %d %H:%M:%S
#
# GMT Miscellaneous Parameters
#
GMT_DATA_SERVER                = oceania
GMT_DATA_SERVER_LIMIT          = unlimited
GMT_DATA_UPDATE_INTERVAL       = 1d
GMT_COMPATIBILITY              = 6
GMT_CUSTOM_LIBS                = 
GMT_EXPORT_TYPE                = double
GMT_EXTRAPOLATE_VAL            = NaN
GMT_FFT                        = auto
GMT_GRAPHICS_DPU               = 300i
GMT_GRAPHICS_FORMAT            = pdf
GMT_HISTORY                    = true
GMT_INTERPOLANT                = akima
GMT_LANGUAGE                   = us
GMT_MAX_CORES                  = 0
GMT_THEME                      = modern
GMT_TRIANGULATE                = Shewchuk
GMT_VERBOSE                    = warning
#
# I/O Parameters
#
IO_COL_SEPARATOR               = tab
IO_FIRST_HEADER                = maybe
IO_GRIDFILE_FORMAT             = nf
IO_GRIDFILE_SHORTHAND          = false
IO_HEADER                      = false
IO_HEADER_MARKER               = #%!;"',#
IO_N_HEADER_RECS               = 0
IO_NAN_RECORDS                 = pass
IO_NC4_CHUNK_SIZE              = auto
IO_NC4_DEFLATION_LEVEL         = 3
IO_LONLAT_TOGGLE               = false
IO_SEGMENT_BINARY              = 2
IO_SEGMENT_MARKER              = >
#
# MAP Parameters
#
MAP_ANNOT_MIN_ANGLE            = 20
MAP_ANNOT_MIN_SPACING          = auto
MAP_ANNOT_OBLIQUE              = separate,lon_horizontal,lat_horizontal,tick_extend
MAP_ANNOT_OFFSET_PRIMARY       = auto
MAP_ANNOT_OFFSET_SECONDARY     = auto
MAP_ANNOT_ORTHO                = we
MAP_DEFAULT_PEN                = default,black
MAP_DEGREE_SYMBOL              = degree
MAP_EMBELLISHMENT_MODE         = auto
MAP_FRAME_AXES                 = auto
MAP_FRAME_PEN                  = black
MAP_FRAME_PERCENT              = 100
MAP_FRAME_TYPE                 = fancy
MAP_FRAME_WIDTH                = auto
MAP_GRID_CROSS_SIZE_PRIMARY    = 0p
MAP_GRID_CROSS_SIZE_SECONDARY  = 0p
MAP_GRID_PEN_PRIMARY           = black
MAP_GRID_PEN_SECONDARY         = black
MAP_HEADING_OFFSET             = auto
MAP_LABEL_MODE                 = annot
MAP_LABEL_OFFSET               = auto
MAP_LINE_STEP                  = 0.75p
MAP_LOGO                       = false
MAP_LOGO_POS                   = BL/-54p/-54p
MAP_ORIGIN_X                   = 72p
MAP_ORIGIN_Y                   = 72p
MAP_POLAR_CAP                  = auto
MAP_SCALE_HEIGHT               = 5p
MAP_SYMBOL_PEN_SCALE           = 15%
MAP_TICK_LENGTH_PRIMARY        = auto
MAP_TICK_LENGTH_SECONDARY      = auto
MAP_TICK_PEN_PRIMARY           = black
MAP_TICK_PEN_SECONDARY         = black
MAP_TITLE_OFFSET               = auto
MAP_VECTOR_SHAPE               = 0.5
#
# Projection Parameters
#
PROJ_AUX_LATITUDE              = authalic
PROJ_DATUM                     = 
PROJ_ELLIPSOID                 = WGS-84
PROJ_GEODESIC                  = Vincenty
PROJ_LENGTH_UNIT               = cm
PROJ_MEAN_RADIUS               = authalic
PROJ_SCALE_FACTOR              = default
#
# PostScript Parameters
#
PS_CHAR_ENCODING               = ISOLatin1+
PS_COLOR_MODEL                 = rgb
PS_COMMENTS                    = false
PS_CONVERT                     = A
PS_IMAGE_COMPRESS              = deflate,5
PS_LINE_CAP                    = butt
PS_LINE_JOIN                   = miter
PS_MITER_LIMIT                 = 35
PS_MEDIA                       = 32767x32767
PS_PAGE_COLOR                  = white
PS_PAGE_ORIENTATION            = portrait
PS_SCALE_X                     = 1
PS_SCALE_Y                     = 1
PS_TRANSPARENCY                = Normal
#
# Calendar/Time Parameters
#
TIME_EPOCH                     = 1970-01-01T00:00:00
TIME_IS_INTERVAL               = off
TIME_INTERVAL_FRACTION         = 0.5
TIME_LEAP_SECONDS              = false
TIME_REPORT                    = none
TIME_UNIT                      = s
TIME_WEEK_START                = Monday
TIME_Y2K_OFFSET_YEAR           = 1950

Calling gmt get directly also doesn't work:

>>> with Session() as lib:
...    lib.call_module("get", "MAP_FRAME_PEN")
black

@seisman seisman changed the title pygmt.config: Some settings are not reverted correctly even pygmt.config is used as a context manager pygmt.config: pen settings are not reverted correctly when set in a context manager May 19, 2024
@yvonnefroehlich
Copy link
Member

Here is the output from gmt defaults in modern mode. It seems that, all PEN related configurations have the value black, rather than something like default,black. So, I expect all other PEN-related configurations have the same issue.

Yes, the same issue occurs with MAP_GRID_PEN and MAP_TICK_PEN. Also, reverting the line style does not work.

import pygmt

size = 5
region = [-size, size, -size, size]
projection = "X3c"
frame = "afg"

fig = pygmt.Figure()

# Left
fig.basemap(region=region, projection=projection, frame=frame)

# Middle
fig.shift_origin(xshift="w+1")
with pygmt.config(
        MAP_FRAME_PEN="darkred,dashed",
        MAP_GRID_PEN="blue,dashed",
        MAP_TICK_PEN="2p,magenta",
):
    fig.basemap(region=region, projection=projection, frame=frame)

# Right
fig.shift_origin(xshift="w+1")
fig.basemap(region=region, projection=projection, frame=frame)

fig.show()

config_local_revert_pen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants