diff --git a/doc/api/index.rst b/doc/api/index.rst index 3b2a4aeab6d..28fdc140448 100644 --- a/doc/api/index.rst +++ b/doc/api/index.rst @@ -32,6 +32,13 @@ Plotting data and laying out the map: Figure.image Figure.shift_origin +Color palette table generation: + +.. autosummary:: + :toctree: generated + + makecpt + Saving and displaying the figure: .. autosummary:: diff --git a/pygmt/__init__.py b/pygmt/__init__.py index 3698c0c2264..b886a267acf 100644 --- a/pygmt/__init__.py +++ b/pygmt/__init__.py @@ -15,6 +15,7 @@ from .session_management import begin as _begin, end as _end from .figure import Figure from .gridding import surface +from .mathops import makecpt from .modules import info, grdinfo, which from . import datasets diff --git a/pygmt/mathops.py b/pygmt/mathops.py new file mode 100644 index 00000000000..dab216a0cb0 --- /dev/null +++ b/pygmt/mathops.py @@ -0,0 +1,65 @@ +""" +GMT modules for Mathematical operations on tables or grids +""" +from .clib import Session +from .exceptions import GMTInvalidInput +from .helpers import build_arg_string, fmt_docstring, kwargs_to_strings, use_alias + + +@fmt_docstring +@use_alias(C="cmap", T="series", G="truncate", H="output", I="reverse", Z="continuous") +@kwargs_to_strings(T="sequence", G="sequence") +def makecpt(**kwargs): + """ + Creates a static color palette table (CPT). + + Full option list at :gmt-docs:`makecpt.html` + + Parameters + ---------- + cmap (C) : str + Selects the master color palette table (CPT) to use in the interpolation. + Full list of built-in color palette tables can be found at + :gmt-docs:`cookbook/cpts.html#built-in-color-palette-tables-cpt`. + + series (T) : list or str + ``[min/max/inc[+b|l|n]|file|list]``. + Defines the range of the new CPT by giving the lowest and highest z-value (and + optionally an interval). If this is not given, the existing range in the master + CPT will be used intact. + + truncate (G) : list or str + ``zlo/zhi``. + Truncate the incoming CPT so that the lowest and highest z-levels are to zlo and + zhi. If one of these equal NaN then we leave that end of the CPT alone. The + truncation takes place before any resampling. See also + :gmt-docs:`cookbook/features.html#manipulating-cpts`. + + output (H) : str + Optional. The file name with extension .cpt to store the generated CPT file. + If not given or False (default), saves the CPT as the session current CPT. + + reverse (I) : str + Set this to True or c [Default] to reverse the sense of color progression in the + master CPT. Set this to z to reverse the sign of z-values in the color table. + Note that this change of z-direction happens before -G and -T values are used so + the latter must be compatible with the changed z-range. See also + :gmt-docs:`cookbook/features.html#manipulating-cpts`. + + continuous (Z) : bool + Creates a continuous CPT [Default is discontinuous, i.e., constant colors for + each interval]. This option has no effect when no -T is used, or when using + -Tz_min/z_max; in the first case the input CPT remains untouched, in the second + case it is only scaled to match the range z_min/z_max. + + {aliases} + """ + with Session() as lib: + if "H" not in kwargs.keys(): # if no output is set + arg_str = build_arg_string(kwargs) + elif "H" in kwargs.keys(): # if output is set + outfile = kwargs.pop("H") + if not outfile or not isinstance(outfile, str): + raise GMTInvalidInput("'output' should be a proper file name.") + arg_str = " ".join([build_arg_string(kwargs), f"-H > {outfile}"]) + lib.call_module(module="makecpt", args=arg_str) diff --git a/pygmt/tests/baseline/test_makecpt_continuous.png b/pygmt/tests/baseline/test_makecpt_continuous.png new file mode 100644 index 00000000000..97d59a9fc8b Binary files /dev/null and b/pygmt/tests/baseline/test_makecpt_continuous.png differ diff --git a/pygmt/tests/baseline/test_makecpt_reverse_color_and_zsign.png b/pygmt/tests/baseline/test_makecpt_reverse_color_and_zsign.png new file mode 100644 index 00000000000..99cc79ba638 Binary files /dev/null and b/pygmt/tests/baseline/test_makecpt_reverse_color_and_zsign.png differ diff --git a/pygmt/tests/baseline/test_makecpt_reverse_color_only.png b/pygmt/tests/baseline/test_makecpt_reverse_color_only.png new file mode 100644 index 00000000000..3ed3aee1025 Binary files /dev/null and b/pygmt/tests/baseline/test_makecpt_reverse_color_only.png differ diff --git a/pygmt/tests/baseline/test_makecpt_reverse_zsign_only.png b/pygmt/tests/baseline/test_makecpt_reverse_zsign_only.png new file mode 100644 index 00000000000..cd89bde4d49 Binary files /dev/null and b/pygmt/tests/baseline/test_makecpt_reverse_zsign_only.png differ diff --git a/pygmt/tests/baseline/test_makecpt_to_plot_grid.png b/pygmt/tests/baseline/test_makecpt_to_plot_grid.png new file mode 100644 index 00000000000..e72226d52c7 Binary files /dev/null and b/pygmt/tests/baseline/test_makecpt_to_plot_grid.png differ diff --git a/pygmt/tests/baseline/test_makecpt_to_plot_grid_scaled_with_series.png b/pygmt/tests/baseline/test_makecpt_to_plot_grid_scaled_with_series.png new file mode 100644 index 00000000000..f83941ee2ee Binary files /dev/null and b/pygmt/tests/baseline/test_makecpt_to_plot_grid_scaled_with_series.png differ diff --git a/pygmt/tests/baseline/test_makecpt_to_plot_points.png b/pygmt/tests/baseline/test_makecpt_to_plot_points.png new file mode 100644 index 00000000000..727e75726ae Binary files /dev/null and b/pygmt/tests/baseline/test_makecpt_to_plot_points.png differ diff --git a/pygmt/tests/baseline/test_makecpt_truncated_at_zhigh_only.png b/pygmt/tests/baseline/test_makecpt_truncated_at_zhigh_only.png new file mode 100644 index 00000000000..ede5d670a95 Binary files /dev/null and b/pygmt/tests/baseline/test_makecpt_truncated_at_zhigh_only.png differ diff --git a/pygmt/tests/baseline/test_makecpt_truncated_at_zlow_only.png b/pygmt/tests/baseline/test_makecpt_truncated_at_zlow_only.png new file mode 100644 index 00000000000..7701bf45034 Binary files /dev/null and b/pygmt/tests/baseline/test_makecpt_truncated_at_zlow_only.png differ diff --git a/pygmt/tests/baseline/test_makecpt_truncated_to_zlow_zhigh.png b/pygmt/tests/baseline/test_makecpt_truncated_to_zlow_zhigh.png new file mode 100644 index 00000000000..1c5355ac25e Binary files /dev/null and b/pygmt/tests/baseline/test_makecpt_truncated_to_zlow_zhigh.png differ diff --git a/pygmt/tests/test_makecpt.py b/pygmt/tests/test_makecpt.py new file mode 100644 index 00000000000..7a557a79ace --- /dev/null +++ b/pygmt/tests/test_makecpt.py @@ -0,0 +1,177 @@ +# pylint: disable=redefined-outer-name +""" +Tests for makecpt +""" +import os + +import numpy as np +import pytest + +from .. import Figure, makecpt +from ..datasets import load_earth_relief +from ..exceptions import GMTInvalidInput +from ..helpers import GMTTempFile + +TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data") +POINTS_DATA = os.path.join(TEST_DATA_DIR, "points.txt") + + +@pytest.fixture(scope="module") +def points(): + "Load the points data from the test file" + return np.loadtxt(POINTS_DATA) + + +@pytest.fixture(scope="module") +def region(): + "The data region" + return [10, 70, -5, 10] + + +@pytest.fixture(scope="module") +def grid(): + "Load the grid data from the sample earth_relief file" + return load_earth_relief() + + +@pytest.mark.mpl_image_compare +def test_makecpt_to_plot_points(points, region): + """ + Use static color palette table to change color of points + """ + fig = Figure() + makecpt(cmap="rainbow") + fig.plot( + x=points[:, 0], + y=points[:, 1], + color=points[:, 2], + region=region, + style="c1c", + cmap=True, + ) + return fig + + +@pytest.mark.mpl_image_compare +def test_makecpt_to_plot_grid(grid): + """ + Use static color palette table to change color of grid + """ + fig = Figure() + makecpt(cmap="relief") + fig.grdimage(grid, projection="W0/6i") + return fig + + +@pytest.mark.mpl_image_compare +def test_makecpt_to_plot_grid_scaled_with_series(grid): + """ + Use static color palette table scaled to a min/max series to change color of grid + """ + fig = Figure() + makecpt(cmap="oleron", series="-4500/4500") + fig.grdimage(grid, projection="W0/6i") + return fig + + +def test_makecpt_output_to_cpt_file(): + """ + Save the generated static color palette table to a .cpt file + """ + with GMTTempFile(suffix=".cpt") as cptfile: + makecpt(output=cptfile.name) + assert os.path.exists(cptfile.name) + + +def test_makecpt_blank_output(): + """ + Use incorrect setting by passing in blank file name to output parameter + """ + with pytest.raises(GMTInvalidInput): + makecpt(output="") + + +def test_makecpt_invalid_output(): + """ + Use incorrect setting by passing in invalid type to output parameter + """ + with pytest.raises(GMTInvalidInput): + makecpt(output=["some.cpt"]) + + +@pytest.mark.mpl_image_compare +def test_makecpt_truncated_to_zlow_zhigh(grid): + """ + Use static color palette table that is truncated to z-low and z-high + """ + fig = Figure() + makecpt(cmap="rainbow", truncate=[0.15, 0.85], series=[-4500, 4500]) + fig.grdimage(grid, projection="W0/6i") + return fig + + +@pytest.mark.mpl_image_compare +def test_makecpt_truncated_at_zlow_only(grid): + """ + Use static color palette table that is truncated at z-low only + """ + fig = Figure() + makecpt(cmap="rainbow", truncate=[0.5, None], series=[-4500, 4500]) + fig.grdimage(grid, projection="W0/6i") + return fig + + +@pytest.mark.mpl_image_compare +def test_makecpt_truncated_at_zhigh_only(grid): + """ + Use static color palette table that is truncated at z-high only + """ + fig = Figure() + makecpt(cmap="rainbow", truncate=[None, 0.5], series=[-4500, 4500]) + fig.grdimage(grid, projection="W0/6i") + return fig + + +@pytest.mark.mpl_image_compare +def test_makecpt_reverse_color_only(grid): + """ + Use static color palette table with its colors reversed + """ + fig = Figure() + makecpt(cmap="earth", reverse=True) + fig.grdimage(grid, projection="W0/6i") + return fig + + +@pytest.mark.mpl_image_compare +def test_makecpt_reverse_zsign_only(grid): + """ + Use static color palette table with its z-value sign reversed + """ + fig = Figure() + makecpt(cmap="earth", reverse="z") + fig.grdimage(grid, projection="W0/6i") + return fig + + +@pytest.mark.mpl_image_compare +def test_makecpt_reverse_color_and_zsign(grid): + """ + Use static color palette table with both its colors and z-value sign reversed + """ + fig = Figure() + makecpt(cmap="earth", reverse="cz") + fig.grdimage(grid, projection="W0/6i") + return fig + + +@pytest.mark.mpl_image_compare +def test_makecpt_continuous(grid): + """ + Use static color palette table that is continuous from blue to white and scaled from + -4500 to 4500m. + """ + fig = Figure() + makecpt(cmap="blue,white", continuous=True, series="-4500,4500") + fig.grdimage(grid, projection="W0/6i") + return fig