Skip to content

Fix figure generation on GMT 6.5+#13

Merged
lispandfound merged 10 commits intomainfrom
topo_fix
Aug 27, 2025
Merged

Fix figure generation on GMT 6.5+#13
lispandfound merged 10 commits intomainfrom
topo_fix

Conversation

@lispandfound
Copy link
Contributor

This PR fixes transparency issues for the latest versions of GMT (6.5.0 and the new 6.6.0). Currently, pygmt-helper uses the nan_transparent (gmt option -Q) option to plot topography over water. Unfortunately, this is a buggy option in recent versions of GMT. This PR switches to using the COLOR_NAN and frame arguments to set water colour behind the topography. Because it doesn't use transparency, new versions of GMT work just fine with it.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @lispandfound, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a transparency issue in pygmt-helper when used with GMT versions 6.5 and newer. It resolves the problem by replacing the problematic nan_transparent option with a more robust approach that utilizes GMT's COLOR_NAN configuration and frame arguments to define the water background color, ensuring proper rendering of topography over water.

Highlights

  • Fixes Transparency Issues: Resolves rendering problems with topography over water in pygmt-helper when using GMT versions 6.5.0 and 6.6.0.
  • Switches Water Background Method: Replaces the buggy nan_transparent option with COLOR_NAN and +g frame arguments for setting water color.
  • Ensures GMT Compatibility: Improves compatibility and stability with newer GMT releases by avoiding a known buggy feature.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@lispandfound lispandfound requested a review from Copilot August 25, 2025 23:52

This comment was marked as outdated.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This PR fixes a transparency issue in recent GMT versions by replacing the buggy nan_transparent option with COLOR_NAN and a frame background color. The changes are logical and effectively address the problem. My review includes one suggestion to improve code robustness by scoping the GMT configuration changes to avoid side effects.

]

config_options = {'COLOR_NAN': plot_kwargs['water_color']} | (config_options or {})
pygmt.config(**config_options)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Modifying the global GMT configuration directly can lead to unexpected side effects in other parts of the code that might use pygmt. It is safer to use a context manager (with pygmt.config(...)) to temporarily apply these settings only for the duration of this function's execution. This will prevent the configuration from 'leaking' and affecting other plots.

This would require some restructuring. For example:

def gen_region_fig(...):
    # ... (setup code before config)

    config_options = {'COLOR_NAN': plot_kwargs['water_color']} | (config_options or {})
    
    if fig is None:
        fig = pygmt.Figure()

    with pygmt.config(**config_options):
        # ... (all plotting logic using fig and pygmt)
    
    return fig

This change would make the function more robust and self-contained.

Copy link
Contributor Author

@lispandfound lispandfound Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I tossed up using this in a with context before making the PR. In my opinion, this is not a good idea because many of the config options are set in gen_region_fig with the expectation that they persist outside the invocation of the function. For example, fonts. I also thought about just setting the COLOR_NAN locally and everything else globally. @claudio525 what do you think? Would the user be surprised if the NaN colour is the ocean? Maybe it will make them think something is wrong?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine as is for now, it matches with the current implementation. If this turns out to be an issue down the line, then I think we do a refactor, and change all config_options to be applied using a context manager, but don't think there is a good reason to do this now.

Copy link
Contributor

@claudio525 claudio525 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great, nice one!

Can you also update the plot_grid function to not use nan_transparent (

nan_transparent=True,
).
Since the gen_region_fig happens before, and COLOR_NAN will be set, this should just work (I hope). The only exception is when the nan is used for masking something other than water, but I think thats a bridge we can cross when we get to it. Should be easy to check with the ratio.py example.

]

config_options = {'COLOR_NAN': plot_kwargs['water_color']} | (config_options or {})
pygmt.config(**config_options)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine as is for now, it matches with the current implementation. If this turns out to be an issue down the line, then I think we do a refactor, and change all config_options to be applied using a context manager, but don't think there is a good reason to do this now.

@lispandfound
Copy link
Contributor Author

lispandfound commented Aug 26, 2025

I don't necessarily know if disabling nan_transparent is a good idea for plot_grid because I have used that before for non-water settings and I think it's not that uncommon in general. The old ratio.py script works fine. I made a couple of tweaks to it because it generates a very large PNG, takes a long time to run, and is hard to see with contours enabled. But you can see that nan_transparent=True works fine with the latest version.

ratio

I suspect nan_transparent always works fine for GMT 6.6.0 (not 6.5.0) when you have a defined background colour with +g. If it doesn't it will fallback to COLOR_NAN over the background which is 128 = #FF0000 = red. Accordingly, I think we should keep it for plot_grid because it is essential to it working correctly, but use the background and COLOR_NAN settings for gen_region_fig because:

  • We won't have to tell researchers to avoid 6.5.0 because gen_region_fig will just work for all versions.
  • It is a technically cleaner way to set the background colour because it doesn't require GMT to sample with transparency.

I have also gone with the half-way approach I outlined earlier regarding pygmt.config, where the config_options are applied globally, but COLOR_NAN is set locally. I think this is a good trade-off between requiring researchers to update their scripts, and setting a COLOR_NAN value they might not expect to change and causing weird "water on my grid" issues for researchers.

@lispandfound lispandfound requested a review from Copilot August 26, 2025 04:47
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes transparency issues in pygmt-helper for GMT versions 6.5+ by replacing the buggy nan_transparent option with a more robust approach using COLOR_NAN and frame arguments to set water color behind topography.

  • Replaces nan_transparent=True with COLOR_NAN configuration for handling water areas
  • Simplifies water background plotting by using frame background color instead of geometric shapes
  • Updates example code to use improved grid spacing and output format

Reviewed Changes

Copilot reviewed 2 out of 5 changed files in this pull request and generated 5 comments.

File Description
pygmt_helper/plotting.py Core fix implementing COLOR_NAN approach and simplifying water background rendering
pygmt_helper/examples/ratio.py Example updates demonstrating improved grid spacing and output format changes

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

if subtitle:
title_args.append(f"+s{subtitle}")

if title:
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition if title: is checked twice (lines 307 and 312), but the second check should be if title_args: to avoid calling basemap with empty frame args when only subtitle is provided.

Suggested change
if title:
if title_args:

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I knew the AI would flag this. Nope it is intentional. See the GMT docs

+ttitle to place the string given in title centered above the plot frame [default is no title].
+ssubtitle (requires +ttitle) to place the string given in subtitle beneath the title [default is no subtitle].

Note that +s requires +t, ergo subtitle= requires title=. Thus checking if title_args is non-empty leaves open the subtle bug that a user might call subtitle= and not title=. Hence, we check if title is not None. In that case, title_args is also not None. Likewise, if title is None then we should ignore the values in title_args even if subtitle is set.

@lispandfound lispandfound merged commit b1e3297 into main Aug 27, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants