From 1fd9d4a8b66ffb0282360247ad7d697ffa0e1ccf Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sun, 7 Sep 2025 23:22:48 +0800 Subject: [PATCH 01/24] Implement the Pattern class for specifying pattern as fills --- doc/api/index.rst | 1 + pygmt/params/__init__.py | 1 + pygmt/params/pattern.py | 88 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 pygmt/params/pattern.py diff --git a/doc/api/index.rst b/doc/api/index.rst index ccb049f996a..a8cad413095 100644 --- a/doc/api/index.rst +++ b/doc/api/index.rst @@ -212,6 +212,7 @@ Class-style Parameters :toctree: generated Box + Pattern Enums ----- diff --git a/pygmt/params/__init__.py b/pygmt/params/__init__.py index f2904afba94..b80b921407a 100644 --- a/pygmt/params/__init__.py +++ b/pygmt/params/__init__.py @@ -3,3 +3,4 @@ """ from pygmt.params.box import Box +from pygmt.params.pattern import Pattern diff --git a/pygmt/params/pattern.py b/pygmt/params/pattern.py new file mode 100644 index 00000000000..1b389463c81 --- /dev/null +++ b/pygmt/params/pattern.py @@ -0,0 +1,88 @@ +""" +The Pattern class for specifying GMT filling patterns. +""" + +import dataclasses + +from pygmt.alias import Alias +from pygmt.exceptions import GMTValueError +from pygmt.params.base import BaseParam + +__doctest_skip__ = ["Pattern"] + + +@dataclasses.dataclass(repr=False) +class Pattern(BaseParam): + """ + Class for GMT filling patterns. + + Parameters + ---------- + id + The pattern identifier. It can be in two forms: + + - An integer in the range 1-90, corresponding to one of + :doc:`the 90 predefined 64x64 bit-patterns ` provided with + GMT. + - The name of a 1-, 8-, or 24-bit image raster file, to create customized, + repeating images using image raster files. + dpi + Resolution of the pattern in dots per inch (DPI) [Default is 1200]. + bgcolor/fgcolor + The background/foreground color for predefined bit-patterns or 1-bit images. + [Default is white for background and black for foreground]. Setting either to + an empty string will yield a transparent background/foreground where only the + foreground or background pixels will be painted. + reversed + If True, the pattern will be bit-reversed, i.e., white and black areas will be + interchanged (only applies to 1-bit images or predefined bit-image patterns). + + Examples + -------- + Draw a global map with land areas filled with pattern 15 in a light red background + and 300 dpi resolution: + + >>> import pygmt + >>> from pygmt.params import Pattern + >>> fig = pygmt.Figure() + >>> fig.coast( + ... region="g", + ... projection="H10c", + ... frame=True, + ... land=Pattern(15, bgcolor="lightred", dpi=300), + ... shorelines=True, + ... ) + >>> fig.show() + """ + + id: int | str + dpi: int | None = None + bgcolor: str | None = None + fgcolor: str | None = None + reversed: bool = False + + def _validate(self): + """ + Validate the parameters. + """ + if isinstance(self.id, int) and not (1 <= self.id <= 90): + raise GMTValueError( + self.id, + description="pattern id", + reason=( + "Pattern id must be an integer in the range 1-90 " + "or the name of a 1-, 8-, or 24-bit image raster file." + ), + ) + + @property + def _aliases(self): + """ + Aliases for the Pattern class. + """ + return [ + Alias(self.id, name="id", prefix="P" if self.reversed else "p"), + Alias(self.bgcolor, name="bgcolor", prefix="+b"), + Alias(self.fgcolor, name="fgcolor", prefix="+f"), + Alias(self.dpi, name="dpi", prefix="+r"), + ] From 30d6b92717e6d85c555398f267516cd103ab1119 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sun, 7 Sep 2025 23:22:59 +0800 Subject: [PATCH 02/24] Add tests for the Pattern class --- pygmt/tests/test_params_pattern.py | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 pygmt/tests/test_params_pattern.py diff --git a/pygmt/tests/test_params_pattern.py b/pygmt/tests/test_params_pattern.py new file mode 100644 index 00000000000..41ec4468859 --- /dev/null +++ b/pygmt/tests/test_params_pattern.py @@ -0,0 +1,43 @@ +""" +Test the Pattern class. +""" + +import pytest +from pygmt.exceptions import GMTValueError +from pygmt.params import Pattern + + +def test_pattern(): + """ + Test the Pattern class. + """ + assert str(Pattern(1)) == "p1" + assert str(Pattern(id=1)) == "p1" + + assert str(Pattern("pattern.png")) == "ppattern.png" + + assert str(Pattern(10, bgcolor="red")) == "p10+bred" + assert str(Pattern(20, fgcolor="blue")) == "p20+fblue" + assert str(Pattern(30, bgcolor="red", fgcolor="blue")) == "p30+bred+fblue" + assert str(Pattern(30, fgcolor="blue", bgcolor="")) == "p30+b+fblue" + assert str(Pattern(30, fgcolor="", bgcolor="red")) == "p30+bred+f" + + assert str(Pattern(40, dpi=300)) == "p40+r300" + + assert str(Pattern(50, reversed=True)) == "P50" + + pattern = Pattern(90, reversed=True, bgcolor="red", fgcolor="blue", dpi=300) + assert str(pattern) == "P90+bred+fblue+r300" + + pattern = Pattern("pattern.png", bgcolor="red", fgcolor="blue", dpi=300) + assert str(pattern) == "ppattern.png+bred+fblue+r300" + + +def test_pattern_invalid_id(): + """ + Test that an invalid pattern id raises a GMTValueError. + """ + with pytest.raises(GMTValueError): + _ = str(Pattern(91)) + with pytest.raises(GMTValueError): + _ = str(Pattern(0)) From db82469121a241d634fc2a77dff00b34bbac47bb Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sun, 7 Sep 2025 23:24:55 +0800 Subject: [PATCH 03/24] Use the Pattern class in examples --- examples/tutorials/advanced/cartesian_histograms.py | 7 +++---- examples/tutorials/advanced/focal_mechanisms.py | 5 +++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/tutorials/advanced/cartesian_histograms.py b/examples/tutorials/advanced/cartesian_histograms.py index ad32abfc6e2..5f089227bc5 100644 --- a/examples/tutorials/advanced/cartesian_histograms.py +++ b/examples/tutorials/advanced/cartesian_histograms.py @@ -18,6 +18,7 @@ # Import the required packages import numpy as np import pygmt +from pygmt.params import Pattern # %% # Generate random data from a normal distribution: @@ -204,10 +205,8 @@ frame=["wSnE", "xaf10", "ya5f1+lCumulative counts"], data=data01, series=10, - # Use pattern ("p") number 8 as fill for the bars - # Set the background ("+b") to white [Default] - # Set the foreground ("+f") to black [Default] - fill="p8+bwhite+fblack", + # Fill bars with GMT pattern 8, with white background and black foreground. + fill=Pattern(8, bgcolor="white", fgcolor="black"), pen="1p,darkgray,solid", histtype=0, # Show cumulative counts diff --git a/examples/tutorials/advanced/focal_mechanisms.py b/examples/tutorials/advanced/focal_mechanisms.py index b44286b6397..9c9eaa45145 100644 --- a/examples/tutorials/advanced/focal_mechanisms.py +++ b/examples/tutorials/advanced/focal_mechanisms.py @@ -18,6 +18,7 @@ # %% import pandas as pd import pygmt +from pygmt.params import Pattern # Set up arguments for basemap region = [-5, 5, -5, 5] @@ -122,8 +123,8 @@ longitude=2, latitude=0, depth=0, - compressionfill="p8", - extensionfill="p31", + compressionfill=Pattern(8), + extensionfill=Pattern(31), outline=True, ) From 3031c59aca9501ebd4d4f3d2712f5158be5e51e8 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sun, 7 Sep 2025 23:30:57 +0800 Subject: [PATCH 04/24] Improve the gallery example for patterns --- examples/gallery/symbols/patterns.py | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/examples/gallery/symbols/patterns.py b/examples/gallery/symbols/patterns.py index a518ac7f034..adff7c35034 100644 --- a/examples/gallery/symbols/patterns.py +++ b/examples/gallery/symbols/patterns.py @@ -2,8 +2,8 @@ Bit and hachure patterns ======================== -In addition to colors, PyGMT also allows using bit and hachure patterns to fill -symbols, polygons, and other areas, via the ``fill`` parameter or similar parameters. +In addition to colors, PyGMT also allows using bit and hachure patterns to fill symbols, +polygons, and other areas, via the ``fill`` parameter or similar parameters. Example method parameters that support bit and hachure patterns include: @@ -20,33 +20,33 @@ - :meth:`pygmt.Figure.wiggle`: Anomalies via ``fillpositive`` and ``fillnegative`` GMT provides 90 predefined patterns that can be used in PyGMT. The patterns are numbered -from 1 to 90, and can be colored and inverted. The resolution of the pattern -can be changed, and the background and foreground colors can be set. For a complete list -of available patterns and the full syntax to specify a pattern, refer to the +from 1 to 90. For a complete list of available patterns refer to the :doc:`/techref/patterns`. + +In PyGMT, patterns can be specified via the {class}`pygmt.params.Pattern` class. The +patterns can be customized with different resolution and different foreground and +background colors. The foreground and background colors can also be reversed. """ # %% import pygmt +from pygmt.params import Pattern # A list of patterns that will be demonstrated. -# To use a pattern as fill append "p" and the number of the desired pattern. -# By default, the pattern is plotted in black and white with a resolution of 300 dpi. +# By default, a pattern is plotted in black and white with a resolution of 1200 dpi. patterns = [ - # Plot a hachted pattern via pattern number 8 - "p8", - # Plot a dotted pattern via pattern number 19 - "p19", - # Set the background color ("+b") to "red3" and the foreground color ("+f") to - # "lightgray" - "p19+bred3+flightbrown", - # Invert the pattern by using a capitalized "P" - "P19+bred3+flightbrown", - # Change the resolution ("+r") to 100 dpi - "p19+bred3+flightbrown+r100", - # Make the background transparent by not giving a color after "+b"; - # works analogous for the foreground - "p19+b+flightbrown+r100", + # Predefined 1-bit pattern 8. + Pattern(8), + # Predefined 1-bit pattern 19. + Pattern(19), + # Pattern 19 with custom backgroud ("red3") and foreground ("lightbrown"). + Pattern(19, bgcolor="red3", fgcolor="lightbrown"), + # Reverse the background and foreground. + Pattern(19, reversed=True, bgcolor="red3", fgcolor="lightbrown"), + # Same as above, but with a 100 dpi resolution. + Pattern(19, bgcolor="red3", fgcolor="lightbrown", dpi=100), + # Same as above, but with a transparent background by setting bgcolor to "". + Pattern(19, bgcolor="", fgcolor="lightbrown", dpi=100), ] fig = pygmt.Figure() From ed1ba89e7512ab62fd3db1d74422d3cb2c2be7fb Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sun, 7 Sep 2025 23:31:25 +0800 Subject: [PATCH 05/24] Remove unnecessary content from the techref for patterns --- doc/techref/patterns.md | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/doc/techref/patterns.md b/doc/techref/patterns.md index ee53a5c87ee..bbbc6f8b0f4 100644 --- a/doc/techref/patterns.md +++ b/doc/techref/patterns.md @@ -1,24 +1,7 @@ -# Bit and Hachure Patterns +# 90 Predefined Bit and Hachure Patterns PyGMT supports a variety of bit and hachure patterns that can be used to fill polygons. - -These patterns can be defined using the following syntax: - -**P**|**p**_pattern_[**+b**_color_][**+f**_color_][**+r**_dpi_] - -*pattern* can either be a number in the range 1-90 or the name of a 1-, 8-, or 24-bit -image raster file. The former will result in one of the 90 predefined 64x64 bit-patterns -provided by GMT (see the figure below). The latter allows the user to create customized, -repeating images using image raster files. - -By specifying uppercase **P** instead of **p** the image will be bit-reversed, i.e., -white and black areas will be interchanged (only applies to 1-bit images or predefined -bit-image patterns). For these patterns and other 1-bit images one may specify -alternative **b**ackground and **f**oreground colors (by appending **+b**_color_ and/or -**+f**_color_) that will replace the default white and black pixels, respectively. -Excluding *color* from a fore- or background specification yields a transparent image -where only the back- or foreground pixels will be painted. The **+r**_dpi_ modifier sets -the resolution in dpi. +These patterns can be specified via the {class}`pygmt.params.Pattern` class. The image below shows the 90 predefined bit patterns that can be used in PyGMT. From 57e9c4ede99b5cb1b9ad9c72b02403ec5efd6b0e Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 8 Sep 2025 18:36:20 +0800 Subject: [PATCH 06/24] Improve docstrings --- pygmt/params/pattern.py | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/pygmt/params/pattern.py b/pygmt/params/pattern.py index 1b389463c81..adad492a1f5 100644 --- a/pygmt/params/pattern.py +++ b/pygmt/params/pattern.py @@ -1,9 +1,10 @@ """ -The Pattern class for specifying GMT filling patterns. +The Pattern class for specifying bit and hachure patterns. """ import dataclasses +from pygmt._typing import PathLike from pygmt.alias import Alias from pygmt.exceptions import GMTValueError from pygmt.params.base import BaseParam @@ -14,18 +15,29 @@ @dataclasses.dataclass(repr=False) class Pattern(BaseParam): """ - Class for GMT filling patterns. + Class for specifying bit and hachure patterns. + + This class allows users to specify predefined bit-patterns or custom 1-, 8-, or + 24-bit image raster files to fill symbols and polygons in various PyGMT plotting + methods. The patterns can be customized with different resolution and different + foreground and background colors. The foreground and background colors can also be + reversed. + + GMT provides 90 predefined patterns that can be used in PyGMT. The patterns are + numbered from 1 to 90, and shown below: + + .. image:: https://docs.generic-mapping-tools.org/6.5/_images/GMT_App_D.png + :alt: The 90 predefined bit-patterns provided with GMT Parameters ---------- id - The pattern identifier. It can be in two forms: + The pattern ID. It can be specified in two forms: - - An integer in the range 1-90, corresponding to one of - :doc:`the 90 predefined 64x64 bit-patterns ` provided with - GMT. - - The name of a 1-, 8-, or 24-bit image raster file, to create customized, - repeating images using image raster files. + - An integer in the range of 1-90, corresponding to one of 90 predefined 64x64 + bit-patterns + - Name of a 1-, 8-, or 24-bit image raster file, to create customized, repeating + images using image raster files. dpi Resolution of the pattern in dots per inch (DPI) [Default is 1200]. bgcolor/fgcolor @@ -35,7 +47,7 @@ class Pattern(BaseParam): foreground or background pixels will be painted. reversed If True, the pattern will be bit-reversed, i.e., white and black areas will be - interchanged (only applies to 1-bit images or predefined bit-image patterns). + interchanged (only applies to predefined bit-patterns or 1-bit images). Examples -------- @@ -55,7 +67,7 @@ class Pattern(BaseParam): >>> fig.show() """ - id: int | str + id: int | PathLike dpi: int | None = None bgcolor: str | None = None fgcolor: str | None = None @@ -65,6 +77,7 @@ def _validate(self): """ Validate the parameters. """ + # Integer pattern id must be in the range 1-90. if isinstance(self.id, int) and not (1 <= self.id <= 90): raise GMTValueError( self.id, From 3ba200654c0e9974e97bb94c918cf54937536102 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 8 Sep 2025 18:44:32 +0800 Subject: [PATCH 07/24] Remove the doc/techref/patterns.md doc --- doc/techref/index.md | 1 - doc/techref/patterns.md | 8 -------- examples/gallery/symbols/patterns.py | 9 ++++----- examples/tutorials/advanced/focal_mechanisms.py | 5 +---- examples/tutorials/basics/polygons.py | 4 ++-- 5 files changed, 7 insertions(+), 20 deletions(-) delete mode 100644 doc/techref/patterns.md diff --git a/doc/techref/index.md b/doc/techref/index.md index 0380c229290..a17c19f868e 100644 --- a/doc/techref/index.md +++ b/doc/techref/index.md @@ -12,7 +12,6 @@ common_parameters.md projections.md fonts.md text_formatting.md -patterns.md encodings.md justification_codes.md environment_variables.md diff --git a/doc/techref/patterns.md b/doc/techref/patterns.md deleted file mode 100644 index bbbc6f8b0f4..00000000000 --- a/doc/techref/patterns.md +++ /dev/null @@ -1,8 +0,0 @@ -# 90 Predefined Bit and Hachure Patterns - -PyGMT supports a variety of bit and hachure patterns that can be used to fill polygons. -These patterns can be specified via the {class}`pygmt.params.Pattern` class. - -The image below shows the 90 predefined bit patterns that can be used in PyGMT. - -![](https://docs.generic-mapping-tools.org/6.5/_images/GMT_App_E.png) diff --git a/examples/gallery/symbols/patterns.py b/examples/gallery/symbols/patterns.py index adff7c35034..c2951c0c64a 100644 --- a/examples/gallery/symbols/patterns.py +++ b/examples/gallery/symbols/patterns.py @@ -19,12 +19,11 @@ ``uncertaintyfill`` - :meth:`pygmt.Figure.wiggle`: Anomalies via ``fillpositive`` and ``fillnegative`` -GMT provides 90 predefined patterns that can be used in PyGMT. The patterns are numbered -from 1 to 90. For a complete list of available patterns refer to the -:doc:`/techref/patterns`. +GMT provides 90 predefined 1-bit patterns, which are numbered from 1 to 90. Theses +patterns can be specified via the {class}`pygmt.params.Pattern` class. In addition, +custom 1-, 8-, or 24-bit image raster files can also be used as patterns. -In PyGMT, patterns can be specified via the {class}`pygmt.params.Pattern` class. The -patterns can be customized with different resolution and different foreground and +The patterns can be customized with different resolution and different foreground and background colors. The foreground and background colors can also be reversed. """ diff --git a/examples/tutorials/advanced/focal_mechanisms.py b/examples/tutorials/advanced/focal_mechanisms.py index 9c9eaa45145..c9ba743e904 100644 --- a/examples/tutorials/advanced/focal_mechanisms.py +++ b/examples/tutorials/advanced/focal_mechanisms.py @@ -100,10 +100,7 @@ # --------------------- # # Use the parameters ``compressionfill`` and ``extensionfill`` to fill the quadrants -# with different colors or patterns. Regarding patterns see the gallery example -# :doc:`Bit and hachure patterns ` and the Technical -# Reference :doc:`Bit and hachure patterns `. - +# with different colors or :class:`patterns `. fig = pygmt.Figure() fig.basemap(region=region, projection=projection, frame=frame) diff --git a/examples/tutorials/basics/polygons.py b/examples/tutorials/basics/polygons.py index 67144fdc680..dbd13775bdb 100644 --- a/examples/tutorials/basics/polygons.py +++ b/examples/tutorials/basics/polygons.py @@ -50,8 +50,8 @@ # %% # Use the ``fill`` parameter to fill the polygon with a color or -# :doc:`pattern `. Note, that there are no lines drawn between the -# data points by default if ``fill`` is used. Use the ``pen`` parameter to add an +# :class:`pattern `. Note, that there are no lines drawn between +# the data points by default if ``fill`` is used. Use the ``pen`` parameter to add an # outline around the polygon. fig = pygmt.Figure() From 5dfa0d2435557c2f04584f31fd60e82bd8b2db15 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 8 Sep 2025 18:51:00 +0800 Subject: [PATCH 08/24] Fix a typo in URL --- pygmt/params/pattern.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pygmt/params/pattern.py b/pygmt/params/pattern.py index adad492a1f5..3ded245cbfa 100644 --- a/pygmt/params/pattern.py +++ b/pygmt/params/pattern.py @@ -26,8 +26,8 @@ class Pattern(BaseParam): GMT provides 90 predefined patterns that can be used in PyGMT. The patterns are numbered from 1 to 90, and shown below: - .. image:: https://docs.generic-mapping-tools.org/6.5/_images/GMT_App_D.png - :alt: The 90 predefined bit-patterns provided with GMT + .. image:: https://docs.generic-mapping-tools.org/6.5/_images/GMT_App_E.png + :alt: The 90 predefined bit-patterns provided with GMT Parameters ---------- From 0ca48c6d5ce809b9f9642e1480255ad0e344f7cd Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 8 Sep 2025 21:37:34 +0800 Subject: [PATCH 09/24] Smaller image size --- pygmt/params/pattern.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pygmt/params/pattern.py b/pygmt/params/pattern.py index 3ded245cbfa..3acbac5ad17 100644 --- a/pygmt/params/pattern.py +++ b/pygmt/params/pattern.py @@ -28,6 +28,7 @@ class Pattern(BaseParam): .. image:: https://docs.generic-mapping-tools.org/6.5/_images/GMT_App_E.png :alt: The 90 predefined bit-patterns provided with GMT + :width: 75% Parameters ---------- From 43bf9ff007e3282f0c6d4009934ea019db545976 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 8 Sep 2025 21:59:10 +0800 Subject: [PATCH 10/24] Fix a typo in examples/gallery/symbols/patterns.py --- examples/gallery/symbols/patterns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gallery/symbols/patterns.py b/examples/gallery/symbols/patterns.py index c2951c0c64a..f5b1fefa233 100644 --- a/examples/gallery/symbols/patterns.py +++ b/examples/gallery/symbols/patterns.py @@ -20,7 +20,7 @@ - :meth:`pygmt.Figure.wiggle`: Anomalies via ``fillpositive`` and ``fillnegative`` GMT provides 90 predefined 1-bit patterns, which are numbered from 1 to 90. Theses -patterns can be specified via the {class}`pygmt.params.Pattern` class. In addition, +patterns can be specified via the :class:`pygmt.params.Pattern` class. In addition, custom 1-, 8-, or 24-bit image raster files can also be used as patterns. The patterns can be customized with different resolution and different foreground and From 2a18366e2197c0082c8ebc3cc7b2ccfe2d088aa6 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 8 Sep 2025 22:03:23 +0800 Subject: [PATCH 11/24] Use the figure directive --- pygmt/params/pattern.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pygmt/params/pattern.py b/pygmt/params/pattern.py index 3acbac5ad17..ab6ea6b6014 100644 --- a/pygmt/params/pattern.py +++ b/pygmt/params/pattern.py @@ -26,9 +26,10 @@ class Pattern(BaseParam): GMT provides 90 predefined patterns that can be used in PyGMT. The patterns are numbered from 1 to 90, and shown below: - .. image:: https://docs.generic-mapping-tools.org/6.5/_images/GMT_App_E.png + .. figure:: https://docs.generic-mapping-tools.org/6.5/_images/GMT_App_E.png :alt: The 90 predefined bit-patterns provided with GMT :width: 75% + :align: center Parameters ---------- From 5cda812c7f196c4940b91db35b0efae97edcb6a2 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 8 Sep 2025 23:01:21 +0800 Subject: [PATCH 12/24] Polish examples/gallery/symbols/patterns.py --- examples/gallery/symbols/patterns.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/gallery/symbols/patterns.py b/examples/gallery/symbols/patterns.py index f5b1fefa233..05971fc3335 100644 --- a/examples/gallery/symbols/patterns.py +++ b/examples/gallery/symbols/patterns.py @@ -19,11 +19,11 @@ ``uncertaintyfill`` - :meth:`pygmt.Figure.wiggle`: Anomalies via ``fillpositive`` and ``fillnegative`` -GMT provides 90 predefined 1-bit patterns, which are numbered from 1 to 90. Theses -patterns can be specified via the :class:`pygmt.params.Pattern` class. In addition, +GMT provides 90 predefined 1-bit patterns, which are numbered from 1 to 90. In addition, custom 1-, 8-, or 24-bit image raster files can also be used as patterns. -The patterns can be customized with different resolution and different foreground and +Theses patterns can be specified via the :class:`pygmt.params.Pattern` class. The +patterns can be customized with different resolution and different foreground and background colors. The foreground and background colors can also be reversed. """ From dcbcaa8b1061f31eacda8fb6375cc21e4510e544 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 8 Sep 2025 23:04:31 +0800 Subject: [PATCH 13/24] Fix the text for each pattern --- examples/gallery/symbols/patterns.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/gallery/symbols/patterns.py b/examples/gallery/symbols/patterns.py index 05971fc3335..26f2fe51486 100644 --- a/examples/gallery/symbols/patterns.py +++ b/examples/gallery/symbols/patterns.py @@ -54,13 +54,12 @@ projection="X10c", frame="rlbt+glightgray+tBit and Hachure Patterns", ) - y = 11 for pattern in patterns: # Plot a square with the pattern as fill. # The square has a size of 2 centimeters with a 1 point thick, black outline. fig.plot(x=2, y=y, style="s2c", pen="1p,black", fill=pattern) # Add a description of the pattern. - fig.text(x=4, y=y, text=pattern, font="Courier-Bold", justify="ML") + fig.text(x=4, y=y, text=str(repr(pattern)), font="Courier-Bold", justify="ML") y -= 2 fig.show() From ff3419c803863c5a36840f55137a08931457844e Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 8 Sep 2025 23:15:44 +0800 Subject: [PATCH 14/24] Fix the image width to show the pattern string --- examples/gallery/symbols/patterns.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/gallery/symbols/patterns.py b/examples/gallery/symbols/patterns.py index 26f2fe51486..901f3944043 100644 --- a/examples/gallery/symbols/patterns.py +++ b/examples/gallery/symbols/patterns.py @@ -51,15 +51,15 @@ fig = pygmt.Figure() fig.basemap( region=[0, 10, 0, 12], - projection="X10c", + projection="X18c/10c", frame="rlbt+glightgray+tBit and Hachure Patterns", ) y = 11 for pattern in patterns: # Plot a square with the pattern as fill. # The square has a size of 2 centimeters with a 1 point thick, black outline. - fig.plot(x=2, y=y, style="s2c", pen="1p,black", fill=pattern) + fig.plot(x=1, y=y, style="s2c", pen="1p,black", fill=pattern) # Add a description of the pattern. - fig.text(x=4, y=y, text=str(repr(pattern)), font="Courier-Bold", justify="ML") + fig.text(x=2, y=y, text=str(repr(pattern)), font="Courier-Bold", justify="ML") y -= 2 fig.show() From 1b17ab05448a15aaa030799bd5a7cac4c5badc2f Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 8 Sep 2025 23:23:16 +0800 Subject: [PATCH 15/24] Validate that fgcolor and fgcolor cannot both be empty --- pygmt/params/pattern.py | 12 ++++++++++-- pygmt/tests/test_params_pattern.py | 8 ++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pygmt/params/pattern.py b/pygmt/params/pattern.py index ab6ea6b6014..bd89fd6f83a 100644 --- a/pygmt/params/pattern.py +++ b/pygmt/params/pattern.py @@ -48,8 +48,8 @@ class Pattern(BaseParam): an empty string will yield a transparent background/foreground where only the foreground or background pixels will be painted. reversed - If True, the pattern will be bit-reversed, i.e., white and black areas will be - interchanged (only applies to predefined bit-patterns or 1-bit images). + If ``True``, the pattern will be bit-reversed, i.e., white and black areas will + be interchanged (only applies to predefined bit-patterns or 1-bit images). Examples -------- @@ -89,6 +89,14 @@ def _validate(self): "or the name of a 1-, 8-, or 24-bit image raster file." ), ) + # fgcolor and bgcolor cannot both be empty. + if self.fgcolor == "" and self.bgcolor == "": + _value = f"{self.fgcolor=}, {self.bgcolor=}" + raise GMTValueError( + _value, + description="fgcolor/", + reason="fgcolor and bgcolor cannot both be empty.", + ) @property def _aliases(self): diff --git a/pygmt/tests/test_params_pattern.py b/pygmt/tests/test_params_pattern.py index 41ec4468859..c72c70f1e10 100644 --- a/pygmt/tests/test_params_pattern.py +++ b/pygmt/tests/test_params_pattern.py @@ -41,3 +41,11 @@ def test_pattern_invalid_id(): _ = str(Pattern(91)) with pytest.raises(GMTValueError): _ = str(Pattern(0)) + + +def test_pattern_invalid_colors(): + """ + Test that both fgcolor and bgcolor cannot be empty strings. + """ + with pytest.raises(GMTValueError): + _ = str(Pattern(10, fgcolor="", bgcolor="")) \ No newline at end of file From 994c3beb53ef6ee66a50b7ae7d3947e74ae048fb Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 8 Sep 2025 23:32:32 +0800 Subject: [PATCH 16/24] Fix styling --- pygmt/tests/test_params_pattern.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/tests/test_params_pattern.py b/pygmt/tests/test_params_pattern.py index c72c70f1e10..419270a9c2f 100644 --- a/pygmt/tests/test_params_pattern.py +++ b/pygmt/tests/test_params_pattern.py @@ -48,4 +48,4 @@ def test_pattern_invalid_colors(): Test that both fgcolor and bgcolor cannot be empty strings. """ with pytest.raises(GMTValueError): - _ = str(Pattern(10, fgcolor="", bgcolor="")) \ No newline at end of file + _ = str(Pattern(10, fgcolor="", bgcolor="")) From 8e560c3a0ff758d9aadb5cebfa6bf7c7a7dee19d Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Tue, 9 Sep 2025 10:42:09 +0800 Subject: [PATCH 17/24] Fix typos Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- examples/gallery/symbols/patterns.py | 2 +- pygmt/params/pattern.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gallery/symbols/patterns.py b/examples/gallery/symbols/patterns.py index 901f3944043..62ae6b7470a 100644 --- a/examples/gallery/symbols/patterns.py +++ b/examples/gallery/symbols/patterns.py @@ -38,7 +38,7 @@ Pattern(8), # Predefined 1-bit pattern 19. Pattern(19), - # Pattern 19 with custom backgroud ("red3") and foreground ("lightbrown"). + # Pattern 19 with custom background ("red3") and foreground ("lightbrown"). Pattern(19, bgcolor="red3", fgcolor="lightbrown"), # Reverse the background and foreground. Pattern(19, reversed=True, bgcolor="red3", fgcolor="lightbrown"), diff --git a/pygmt/params/pattern.py b/pygmt/params/pattern.py index bd89fd6f83a..03ca15aed67 100644 --- a/pygmt/params/pattern.py +++ b/pygmt/params/pattern.py @@ -94,7 +94,7 @@ def _validate(self): _value = f"{self.fgcolor=}, {self.bgcolor=}" raise GMTValueError( _value, - description="fgcolor/", + description="fgcolor and bgcolor", reason="fgcolor and bgcolor cannot both be empty.", ) From f627d2881cd263bd26d4b29a638f8e3c3fa172b9 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Tue, 9 Sep 2025 17:09:05 +0800 Subject: [PATCH 18/24] Rename id to pattern --- pygmt/params/pattern.py | 18 +++++++++--------- pygmt/tests/test_params_pattern.py | 11 +++++------ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/pygmt/params/pattern.py b/pygmt/params/pattern.py index 03ca15aed67..4d65d32c0be 100644 --- a/pygmt/params/pattern.py +++ b/pygmt/params/pattern.py @@ -33,8 +33,8 @@ class Pattern(BaseParam): Parameters ---------- - id - The pattern ID. It can be specified in two forms: + pattern + The pattern to use. It can be specified in two forms: - An integer in the range of 1-90, corresponding to one of 90 predefined 64x64 bit-patterns @@ -69,7 +69,7 @@ class Pattern(BaseParam): >>> fig.show() """ - id: int | PathLike + pattern: int | PathLike dpi: int | None = None bgcolor: str | None = None fgcolor: str | None = None @@ -79,13 +79,13 @@ def _validate(self): """ Validate the parameters. """ - # Integer pattern id must be in the range 1-90. - if isinstance(self.id, int) and not (1 <= self.id <= 90): + # Integer pattern number must be in the range 1-90. + if isinstance(self.pattern, int) and not (1 <= self.pattern <= 90): raise GMTValueError( - self.id, - description="pattern id", + self.pattern, + description="pattern number", reason=( - "Pattern id must be an integer in the range 1-90 " + "Parameter 'pattern' must be an integer in the range 1-90 " "or the name of a 1-, 8-, or 24-bit image raster file." ), ) @@ -104,7 +104,7 @@ def _aliases(self): Aliases for the Pattern class. """ return [ - Alias(self.id, name="id", prefix="P" if self.reversed else "p"), + Alias(self.pattern, name="pattern", prefix="P" if self.reversed else "p"), Alias(self.bgcolor, name="bgcolor", prefix="+b"), Alias(self.fgcolor, name="fgcolor", prefix="+f"), Alias(self.dpi, name="dpi", prefix="+r"), diff --git a/pygmt/tests/test_params_pattern.py b/pygmt/tests/test_params_pattern.py index 419270a9c2f..c848ec9275a 100644 --- a/pygmt/tests/test_params_pattern.py +++ b/pygmt/tests/test_params_pattern.py @@ -12,7 +12,7 @@ def test_pattern(): Test the Pattern class. """ assert str(Pattern(1)) == "p1" - assert str(Pattern(id=1)) == "p1" + assert str(Pattern(pattern=1)) == "p1" assert str(Pattern("pattern.png")) == "ppattern.png" @@ -33,15 +33,14 @@ def test_pattern(): assert str(pattern) == "ppattern.png+bred+fblue+r300" -def test_pattern_invalid_id(): +def test_pattern_invalid_pattern(): """ - Test that an invalid pattern id raises a GMTValueError. + Test that an invalid pattern number raises a GMTValueError. """ - with pytest.raises(GMTValueError): - _ = str(Pattern(91)) with pytest.raises(GMTValueError): _ = str(Pattern(0)) - + with pytest.raises(GMTValueError): + _ = str(Pattern(91)) def test_pattern_invalid_colors(): """ From 28be12399e667d63610071405ab4491f2927fb5c Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Tue, 9 Sep 2025 17:12:11 +0800 Subject: [PATCH 19/24] Rename reversed to invert --- examples/gallery/symbols/patterns.py | 4 ++-- pygmt/params/pattern.py | 10 +++++----- pygmt/tests/test_params_pattern.py | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/gallery/symbols/patterns.py b/examples/gallery/symbols/patterns.py index 62ae6b7470a..81de7d80ef6 100644 --- a/examples/gallery/symbols/patterns.py +++ b/examples/gallery/symbols/patterns.py @@ -24,7 +24,7 @@ Theses patterns can be specified via the :class:`pygmt.params.Pattern` class. The patterns can be customized with different resolution and different foreground and -background colors. The foreground and background colors can also be reversed. +background colors. The foreground and background colors can also be inverted. """ # %% @@ -41,7 +41,7 @@ # Pattern 19 with custom background ("red3") and foreground ("lightbrown"). Pattern(19, bgcolor="red3", fgcolor="lightbrown"), # Reverse the background and foreground. - Pattern(19, reversed=True, bgcolor="red3", fgcolor="lightbrown"), + Pattern(19, invert=True, bgcolor="red3", fgcolor="lightbrown"), # Same as above, but with a 100 dpi resolution. Pattern(19, bgcolor="red3", fgcolor="lightbrown", dpi=100), # Same as above, but with a transparent background by setting bgcolor to "". diff --git a/pygmt/params/pattern.py b/pygmt/params/pattern.py index 4d65d32c0be..a97768de826 100644 --- a/pygmt/params/pattern.py +++ b/pygmt/params/pattern.py @@ -21,7 +21,7 @@ class Pattern(BaseParam): 24-bit image raster files to fill symbols and polygons in various PyGMT plotting methods. The patterns can be customized with different resolution and different foreground and background colors. The foreground and background colors can also be - reversed. + inverted. GMT provides 90 predefined patterns that can be used in PyGMT. The patterns are numbered from 1 to 90, and shown below: @@ -47,8 +47,8 @@ class Pattern(BaseParam): [Default is white for background and black for foreground]. Setting either to an empty string will yield a transparent background/foreground where only the foreground or background pixels will be painted. - reversed - If ``True``, the pattern will be bit-reversed, i.e., white and black areas will + invert + If ``True``, the pattern will be bit-inverted, i.e., white and black areas will be interchanged (only applies to predefined bit-patterns or 1-bit images). Examples @@ -73,7 +73,7 @@ class Pattern(BaseParam): dpi: int | None = None bgcolor: str | None = None fgcolor: str | None = None - reversed: bool = False + invert: bool = False def _validate(self): """ @@ -104,7 +104,7 @@ def _aliases(self): Aliases for the Pattern class. """ return [ - Alias(self.pattern, name="pattern", prefix="P" if self.reversed else "p"), + Alias(self.pattern, name="pattern", prefix="P" if self.invert else "p"), Alias(self.bgcolor, name="bgcolor", prefix="+b"), Alias(self.fgcolor, name="fgcolor", prefix="+f"), Alias(self.dpi, name="dpi", prefix="+r"), diff --git a/pygmt/tests/test_params_pattern.py b/pygmt/tests/test_params_pattern.py index c848ec9275a..713503bb008 100644 --- a/pygmt/tests/test_params_pattern.py +++ b/pygmt/tests/test_params_pattern.py @@ -24,9 +24,9 @@ def test_pattern(): assert str(Pattern(40, dpi=300)) == "p40+r300" - assert str(Pattern(50, reversed=True)) == "P50" + assert str(Pattern(50, invert=True)) == "P50" - pattern = Pattern(90, reversed=True, bgcolor="red", fgcolor="blue", dpi=300) + pattern = Pattern(90, invert=True, bgcolor="red", fgcolor="blue", dpi=300) assert str(pattern) == "P90+bred+fblue+r300" pattern = Pattern("pattern.png", bgcolor="red", fgcolor="blue", dpi=300) @@ -42,6 +42,7 @@ def test_pattern_invalid_pattern(): with pytest.raises(GMTValueError): _ = str(Pattern(91)) + def test_pattern_invalid_colors(): """ Test that both fgcolor and bgcolor cannot be empty strings. From a8af0e7d5d3624d43e41304f922f7ee3c4da70ca Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Tue, 9 Sep 2025 17:20:25 +0800 Subject: [PATCH 20/24] One more fix for reverse->invert --- examples/gallery/symbols/patterns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gallery/symbols/patterns.py b/examples/gallery/symbols/patterns.py index 81de7d80ef6..c595f4ef011 100644 --- a/examples/gallery/symbols/patterns.py +++ b/examples/gallery/symbols/patterns.py @@ -40,7 +40,7 @@ Pattern(19), # Pattern 19 with custom background ("red3") and foreground ("lightbrown"). Pattern(19, bgcolor="red3", fgcolor="lightbrown"), - # Reverse the background and foreground. + # Invert the background and foreground. Pattern(19, invert=True, bgcolor="red3", fgcolor="lightbrown"), # Same as above, but with a 100 dpi resolution. Pattern(19, bgcolor="red3", fgcolor="lightbrown", dpi=100), From 74da7a823231a86a7f56ea189c2eebfdedf4bc73 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Tue, 9 Sep 2025 20:53:46 +0800 Subject: [PATCH 21/24] Fix a typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Yvonne Fröhlich <94163266+yvonnefroehlich@users.noreply.github.com> --- examples/gallery/symbols/patterns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gallery/symbols/patterns.py b/examples/gallery/symbols/patterns.py index c595f4ef011..2ef6516d9f5 100644 --- a/examples/gallery/symbols/patterns.py +++ b/examples/gallery/symbols/patterns.py @@ -22,7 +22,7 @@ GMT provides 90 predefined 1-bit patterns, which are numbered from 1 to 90. In addition, custom 1-, 8-, or 24-bit image raster files can also be used as patterns. -Theses patterns can be specified via the :class:`pygmt.params.Pattern` class. The +These patterns can be specified via the :class:`pygmt.params.Pattern` class. The patterns can be customized with different resolution and different foreground and background colors. The foreground and background colors can also be inverted. """ From e9eca8ee0b5327ce8e3819a36d0691d8c8afd8a7 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Tue, 9 Sep 2025 21:17:33 +0800 Subject: [PATCH 22/24] DOC: Fix the default resolution from 1200 to 300 for patterns --- examples/gallery/symbols/patterns.py | 2 +- pygmt/params/pattern.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/gallery/symbols/patterns.py b/examples/gallery/symbols/patterns.py index 2ef6516d9f5..f9896a9ee47 100644 --- a/examples/gallery/symbols/patterns.py +++ b/examples/gallery/symbols/patterns.py @@ -32,7 +32,7 @@ from pygmt.params import Pattern # A list of patterns that will be demonstrated. -# By default, a pattern is plotted in black and white with a resolution of 1200 dpi. +# By default, a pattern is plotted in black and white with a resolution of 300 dpi. patterns = [ # Predefined 1-bit pattern 8. Pattern(8), diff --git a/pygmt/params/pattern.py b/pygmt/params/pattern.py index a97768de826..55f72369faa 100644 --- a/pygmt/params/pattern.py +++ b/pygmt/params/pattern.py @@ -41,7 +41,7 @@ class Pattern(BaseParam): - Name of a 1-, 8-, or 24-bit image raster file, to create customized, repeating images using image raster files. dpi - Resolution of the pattern in dots per inch (DPI) [Default is 1200]. + Resolution of the pattern in dots per inch (DPI) [Default is 300]. bgcolor/fgcolor The background/foreground color for predefined bit-patterns or 1-bit images. [Default is white for background and black for foreground]. Setting either to @@ -54,7 +54,7 @@ class Pattern(BaseParam): Examples -------- Draw a global map with land areas filled with pattern 15 in a light red background - and 300 dpi resolution: + and 200 dpi resolution: >>> import pygmt >>> from pygmt.params import Pattern @@ -63,7 +63,7 @@ class Pattern(BaseParam): ... region="g", ... projection="H10c", ... frame=True, - ... land=Pattern(15, bgcolor="lightred", dpi=300), + ... land=Pattern(15, bgcolor="lightred", dpi=200), ... shorelines=True, ... ) >>> fig.show() From 43036c54080606ca7c1799b71168d047e8ac4308 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Tue, 9 Sep 2025 22:17:51 +0800 Subject: [PATCH 23/24] Polish docstrings --- pygmt/params/pattern.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pygmt/params/pattern.py b/pygmt/params/pattern.py index 55f72369faa..33c83a569cd 100644 --- a/pygmt/params/pattern.py +++ b/pygmt/params/pattern.py @@ -44,9 +44,9 @@ class Pattern(BaseParam): Resolution of the pattern in dots per inch (DPI) [Default is 300]. bgcolor/fgcolor The background/foreground color for predefined bit-patterns or 1-bit images. - [Default is white for background and black for foreground]. Setting either to - an empty string will yield a transparent background/foreground where only the - foreground or background pixels will be painted. + Setting either to an empty string will yield a transparent background/foreground + where only the foreground/background pixels will be painted. [Default is white + for background and black for foreground]. invert If ``True``, the pattern will be bit-inverted, i.e., white and black areas will be interchanged (only applies to predefined bit-patterns or 1-bit images). From 5774b35254e9447539bd9b38a3d8df84bc461de4 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Thu, 25 Sep 2025 07:44:42 +0800 Subject: [PATCH 24/24] Add intersphinx link to Pattern --- examples/tutorials/advanced/cartesian_histograms.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/tutorials/advanced/cartesian_histograms.py b/examples/tutorials/advanced/cartesian_histograms.py index 5f089227bc5..c4ee692f41b 100644 --- a/examples/tutorials/advanced/cartesian_histograms.py +++ b/examples/tutorials/advanced/cartesian_histograms.py @@ -175,10 +175,10 @@ # Cumulative values # ----------------- # -# To create a histogram showing the cumulative values set ``cumulative=True``. Here, -# the bars of the cumulative histogram are filled with a pattern via the ``fill`` -# parameter. Annotate each bar with the counts it represents using the ``annotate`` -# parameter. +# To create a histogram showing the cumulative values set ``cumulative=True``. Here, the +# bars of the cumulative histogram are filled with a :class:`pygmt.params.Pattern` via +# the ``fill`` parameter. Annotate each bar with the counts it represents using the +# ``annotate`` parameter. fig = pygmt.Figure()