diff --git a/.github/workflows/cache_data.yaml b/.github/workflows/cache_data.yaml index 892608e2700..969198e4ef1 100644 --- a/.github/workflows/cache_data.yaml +++ b/.github/workflows/cache_data.yaml @@ -19,7 +19,7 @@ jobs: steps: # Setup Miniconda - name: Setup Miniconda - uses: conda-incubator/setup-miniconda@v2.1.0 + uses: conda-incubator/setup-miniconda@v2.1.1 with: channels: conda-forge miniconda-version: "latest" diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml index 59859ff62c0..752e87ff51f 100644 --- a/.github/workflows/check-links.yml +++ b/.github/workflows/check-links.yml @@ -26,7 +26,7 @@ jobs: path: documentation - name: Link Checker - uses: lycheeverse/lychee-action@v1.0.6 + uses: lycheeverse/lychee-action@v1.0.8 with: # 429: Too many requests args: > @@ -52,7 +52,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Create Issue From File - uses: peter-evans/create-issue-from-file@v2.3.2 + uses: peter-evans/create-issue-from-file@v3 with: title: Link Checker Report content-filepath: ./lychee/out.md diff --git a/.github/workflows/ci_docs.yml b/.github/workflows/ci_docs.yml index 69aca102a72..f20663b89d7 100644 --- a/.github/workflows/ci_docs.yml +++ b/.github/workflows/ci_docs.yml @@ -43,7 +43,7 @@ jobs: steps: # Cancel previous runs that are not completed - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.8.0 + uses: styfle/cancel-workflow-action@0.9.0 with: access_token: ${{ github.token }} @@ -56,7 +56,7 @@ jobs: # Setup Miniconda - name: Setup Miniconda - uses: conda-incubator/setup-miniconda@v2.1.0 + uses: conda-incubator/setup-miniconda@v2.1.1 with: activate-environment: pygmt python-version: ${{ matrix.python-version }} @@ -66,9 +66,10 @@ jobs: # Install GMT and other required dependencies from conda-forge - name: Install dependencies run: | - conda install gmt=6.1.1 numpy pandas xarray netCDF4 packaging \ + conda install -c conda-forge/label/dev gmt=6.2.0rc1 + conda install numpy pandas xarray netCDF4 packaging \ ipython make myst-parser \ - sphinx sphinx-copybutton sphinx-gallery sphinx_rtd_theme=0.5.1 + sphinx sphinx-copybutton sphinx-gallery sphinx_rtd_theme # Show installed pkg information for postmortem diagnostic - name: List installed packages @@ -76,7 +77,7 @@ jobs: # Download cached remote files (artifacts) from GitHub - name: Download remote data from GitHub - uses: dawidd6/action-download-artifact@v2.13.0 + uses: dawidd6/action-download-artifact@v2.14.0 with: workflow: cache_data.yaml workflow_conclusion: success diff --git a/.github/workflows/ci_tests.yaml b/.github/workflows/ci_tests.yaml index 328de2ced94..dbacd83b6c8 100644 --- a/.github/workflows/ci_tests.yaml +++ b/.github/workflows/ci_tests.yaml @@ -63,7 +63,7 @@ jobs: steps: # Cancel previous runs that are not completed - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.8.0 + uses: styfle/cancel-workflow-action@0.9.0 with: access_token: ${{ github.token }} @@ -76,7 +76,7 @@ jobs: # Setup Miniconda - name: Setup Miniconda - uses: conda-incubator/setup-miniconda@v2.1.0 + uses: conda-incubator/setup-miniconda@v2.1.1 with: activate-environment: pygmt python-version: ${{ matrix.python-version }} @@ -86,7 +86,8 @@ jobs: # Install GMT and other required dependencies from conda-forge - name: Install dependencies run: | - conda install gmt=6.1.1 numpy=${{ matrix.numpy-version }} \ + conda install -c conda-forge/label/dev gmt=6.2.0rc1 + conda install numpy=${{ matrix.numpy-version }} \ pandas xarray netCDF4 packaging \ codecov coverage[toml] dvc ipython make \ pytest-cov pytest-mpl pytest>=6.0 \ @@ -98,7 +99,7 @@ jobs: # Download cached remote files (artifacts) from GitHub - name: Download remote data from GitHub - uses: dawidd6/action-download-artifact@v2.13.0 + uses: dawidd6/action-download-artifact@v2.14.0 with: workflow: cache_data.yaml workflow_conclusion: success @@ -140,7 +141,7 @@ jobs: # Upload coverage to Codecov - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1.3.1 + uses: codecov/codecov-action@v1.5.0 with: file: ./coverage.xml # optional env_vars: OS,PYTHON,NUMPY diff --git a/.github/workflows/ci_tests_dev.yaml b/.github/workflows/ci_tests_dev.yaml index ff2daae118e..c2728dfbb0b 100644 --- a/.github/workflows/ci_tests_dev.yaml +++ b/.github/workflows/ci_tests_dev.yaml @@ -39,7 +39,7 @@ jobs: steps: # Cancel previous runs that are not completed - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.8.0 + uses: styfle/cancel-workflow-action@0.9.0 with: access_token: ${{ github.token }} @@ -73,7 +73,7 @@ jobs: # Setup Miniconda - name: Setup Miniconda - uses: conda-incubator/setup-miniconda@v2.1.0 + uses: conda-incubator/setup-miniconda@v2.1.1 with: activate-environment: pygmt python-version: ${{ matrix.python-version }} @@ -102,7 +102,7 @@ jobs: # Download cached remote files (artifacts) from GitHub - name: Download remote data from GitHub - uses: dawidd6/action-download-artifact@v2.13.0 + uses: dawidd6/action-download-artifact@v2.14.0 with: workflow: cache_data.yaml workflow_conclusion: success diff --git a/.github/workflows/dvc-diff.yml b/.github/workflows/dvc-diff.yml index 07da75674fd..c6f214f3981 100644 --- a/.github/workflows/dvc-diff.yml +++ b/.github/workflows/dvc-diff.yml @@ -24,6 +24,9 @@ jobs: - name: Setup continuous machine learning (CML) uses: iterative/setup-cml@v1.0.0 + - name: Pull image data from cloud storage + run: dvc pull --remote upstream + # Produce the markdown diff report, which should look like: # ## Summary of changed images # @@ -32,32 +35,52 @@ jobs: # | Status | Path | # |----------|-------------------------------------| # | added | pygmt/tests/baseline/test_image.png | - - name: Put list of images that were added or changed into report + # | deleted | pygmt/tests/baseline/test_image2.png | + # | modified | pygmt/tests/baseline/test_image3.png | + - name: Generate the image diff report + env: + repo_token: ${{ secrets.GITHUB_TOKEN }} + id: image-diff run: | echo -e "## Summary of changed images\n" > report.md echo -e "This is an auto-generated report of images that have changed on the DVC remote\n" >> report.md dvc diff --show-md master HEAD >> report.md - cat report.md - - name: Pull image data from cloud storage - run: dvc pull --remote upstream - - - name: Put image diff(s) into report - env: - repo_token: ${{ secrets.GITHUB_TOKEN }} - id: image-diff - run: | - # Get just the filename of the changed image from the report - awk 'NF==5 && NR>=7 {print $4}' report.md > diff_files.txt + # Get just the filename of the added and modified image from the report + awk 'NF==5 && NR>=7 && $2=="added" {print $4}' report.md > added_files.txt + awk 'NF==5 && NR>=7 && $2=="modified" {print $4}' report.md > modified_files.txt # Append each image to the markdown report echo -e "## Image diff(s)\n" >> report.md echo -e "
\n" >> report.md + # Added images + echo -e "### Added images\n" >> report.md while IFS= read -r line; do echo -e "- $line \n" >> report.md cml-publish --title $line --md "$line" >> report.md < /dev/null - done < diff_files.txt + done < added_files.txt + + # Modified images + echo -e "### Modified images\n" >> report.md + # Upload new images + while IFS= read -r line; do + cml-publish --title $line --md "$line" >> modified_images_new.md < /dev/null + done < modified_files.txt + + # Pull images in the master branch from cloud storage + git checkout master + dvc pull --remote upstream + # Upload old images + while IFS= read -r line; do + cml-publish --title $line --md "$line" >> modified_images_old.md < /dev/null + done < modified_files.txt + + # Append image report for modified images + echo -e "| Path | Old | New |" >> report.md + echo -e "|---|---|---|" >> report.md + paste modified_files.txt modified_images_old.md modified_images_new.md -d"|" | + awk -F"|" 'function basename(file) {sub(".*/", "", file); return file} {printf("| %s | %s | %s |\n", basename($1), $2, $3)}' >> report.md echo -e "
\n" >> report.md diff --git a/.github/workflows/format-command.yml b/.github/workflows/format-command.yml index e9ec1b82233..b23f7aa2c4e 100644 --- a/.github/workflows/format-command.yml +++ b/.github/workflows/format-command.yml @@ -21,7 +21,7 @@ jobs: ref: ${{ github.event.client_payload.pull_request.head.ref }} # Setup Python environment - - uses: actions/setup-python@v2.2.1 + - uses: actions/setup-python@v2.2.2 # Install formatting tools - name: Install formatting tools diff --git a/.github/workflows/publish-to-pypi.yml b/.github/workflows/publish-to-pypi.yml index d65461db1d0..73e09f92f83 100644 --- a/.github/workflows/publish-to-pypi.yml +++ b/.github/workflows/publish-to-pypi.yml @@ -29,7 +29,7 @@ jobs: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v2.2.2 with: python-version: 3.9 diff --git a/.github/workflows/slash-command-dispatch.yml b/.github/workflows/slash-command-dispatch.yml index 918597888e1..0637c0f3fb6 100644 --- a/.github/workflows/slash-command-dispatch.yml +++ b/.github/workflows/slash-command-dispatch.yml @@ -6,6 +6,7 @@ on: # types: [created, edited] jobs: slashCommandDispatch: + if: ${{ github.event.issue.pull_request }} runs-on: ubuntu-latest steps: # Generate token from GenericMappingTools bot diff --git a/.github/workflows/style_checks.yaml b/.github/workflows/style_checks.yaml index 3ad07f0e10a..0f6d3ed9b60 100644 --- a/.github/workflows/style_checks.yaml +++ b/.github/workflows/style_checks.yaml @@ -20,7 +20,7 @@ jobs: # Setup Miniconda - name: Set up Python - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v2.2.2 with: python-version: 3.9 diff --git a/AUTHORS.md b/AUTHORS.md index 6597cef7b35..b959a88ae72 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -8,6 +8,7 @@ Manoa. The following people have contributed code and/or documentation to the project (alphabetical by name) and are considered to be "PyGMT Developers": +* [Abhishek Anant](https://twitter.com/itsabhianant) | [0000-0002-5751-2010](https://orcid.org/0000-0002-5751-2010) | Unaffiliated * [Dongdong Tian](https://seisman.info/) | [0000-0001-7967-1197](https://orcid.org/0000-0001-7967-1197) | Michigan State University * [Jiayuan Yao](https://github.com/core-man) | [0000-0001-7036-4238](https://orcid.org/0000-0001-7036-4238) | Nanyang Technological University * [Kathryn Materna](https://github.com/kmaterna) | [0000-0002-6687-980X](https://orcid.org/0000-0002-6687-980X) | US Geological Survey diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 23c75b934d1..94fad78206d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -181,13 +181,17 @@ When editing documentation, use the following standards to demonstrate the examp 1. Python arguments, such as import statements, Boolean expressions, and function arguments should be wrapped as ``code`` by using \`\` on both sides of the code. - Example: \`\`import pygmt\`\` results in ``import pygmt``. + Examples: \`\`import pygmt\`\` results in ``import pygmt``, \`\`True\`\` results in `True`, + \`\`style="v"\`\` results in `style="v"`. 2. Literal GMT arguments should be **bold** by wrapping the arguments with \*\* (two asterisks) on both sides. The argument description should be in *italicized* with \* (single asterisk) on both sides. - Example: `**+l**\ *label*` results in **+l***label*. -3. Optional arguments are placed wrapped with [ ] (square brackets). + Examples: `**+l**\ *label*` results in **+l***label*, `**05m**` results in **05m**. +3. Optional arguments are wrapped with [ ] (square brackets). 4. Arguments that are mutually exclusive are separated with a | (bar) to denote "or". +5. Default arguments for parameters and configuration settings are wrapped + with [ ] (square brackers) with the prefix "Default is". Example: [Default is + **p**]. ## Contributing Code @@ -215,7 +219,7 @@ General guidelines for pull requests (PRs): do. * Each pull request should consist of a **small** and logical collection of changes. * Larger changes should be broken down into smaller components and integrated - separately. + separately. For example, break the wrapping of aliases into multiple pull requests. * Bug fixes should be submitted in separate PRs. * Use underscores for all Python (*.py) files as per [PEP8](https://www.python.org/dev/peps/pep-0008/), not hyphens. Directory names should also use underscores instead of hyphens. @@ -299,6 +303,12 @@ warn us and you can make a new commit with the formatted code. Even better, you can just write `/format` in the first line of any comment in a Pull Request to lint the code automatically. +When wrapping a new alias, use an underscore to separate words bridged by vowels +(aeiou), such as `no_skip` and `z_only`. Do not use an underscore to separate +words bridged only by consonants, such as `distcalc`, and `crossprofile`. This +convention is not applied by the code checking tools, but the PyGMT maintainers +will comment on any pull requests as needed. + We also use [flake8](http://flake8.pycqa.org/en/latest/) and [pylint](https://www.pylint.org/) to check the quality of the code and quickly catch common errors. diff --git a/MANIFEST.in b/MANIFEST.in index 8a50c80900c..7be2555ff30 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,7 +7,6 @@ exclude .gitignore exclude .pylintrc exclude AUTHORSHIP.md exclude CONTRIBUTING.md -exclude MAINTENANCE.md exclude Makefile exclude environment.yml exclude package.json diff --git a/Makefile b/Makefile index e5cae667ecd..a5342aa800d 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ test: @echo "" @cd $(TESTDIR); python -c "import $(PROJECT); $(PROJECT).show_versions()" @echo "" - cd $(TESTDIR); pytest $(PYTEST_COV_ARGS) $(PROJECT) + cd $(TESTDIR); PYGMT_USE_EXTERNAL_DISPLAY="false" pytest $(PYTEST_COV_ARGS) $(PROJECT) cp $(TESTDIR)/coverage.xml . cp -r $(TESTDIR)/htmlcov . rm -r $(TESTDIR) diff --git a/doc/Makefile b/doc/Makefile index 81b3a53fcd2..6c4d7ab31ff 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -31,7 +31,8 @@ html: api @echo @echo "Building HTML files." @echo - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + # Set PYGMT_USE_EXTERNAL_DISPLAY to "false" to disable external display + PYGMT_USE_EXTERNAL_DISPLAY="false" $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." diff --git a/doc/_static/style.css b/doc/_static/style.css index 66b20538c06..d8171f6ffee 100644 --- a/doc/_static/style.css +++ b/doc/_static/style.css @@ -89,6 +89,32 @@ p { max-width: 1000px; } +/* Format parameters section similar to sphinx_rtd_theme v4.x.x (not a grid) */ +html.writer-html5 .rst-content dl.field-list { + display: initial; +} + +/* Add a grey box around parameters similar to sphinx_rtd_theme v4.x.x) */ +.rst-content dl:not(.docutils) dl dt { + margin-bottom: 4px; + border: none; + border-left: solid 3px #ccc; + background: #f0f0f0; + color: #555; +} + +.rst-content dl:not(.docutils) dt { + display: table; + margin: 6px 0; + font-size: 90%; + line-height: normal; + background: #e7f2fa; + color: #2980B9; + border-top: solid 3px #6ab0de; + padding: 6px; + position: relative; +} + /* Remove the padding from the Parameters table */ .rst-content table.field-list .field-name { padding-left: 0px; diff --git a/doc/api/index.rst b/doc/api/index.rst index 3b4220b7e7d..b6cb79a26d6 100644 --- a/doc/api/index.rst +++ b/doc/api/index.rst @@ -29,6 +29,7 @@ Plotting data and laying out the map: Figure.grdcontour Figure.grdimage Figure.grdview + Figure.histogram Figure.image Figure.inset Figure.legend @@ -42,6 +43,8 @@ Plotting data and laying out the map: Figure.solar Figure.subplot Figure.text + Figure.velo + Figure.wiggle Color palette table generation: @@ -60,6 +63,13 @@ Saving and displaying the figure: Figure.show Figure.psconvert +Configuring the display settings: + +.. autosummary:: + :toctree: generated + + set_display + Data Processing --------------- @@ -217,6 +227,7 @@ Low level access (these are mostly used by the :mod:`pygmt.clib` package): clib.Session.get_default clib.Session.create_data clib.Session.put_matrix + clib.Session.put_strings clib.Session.put_vector clib.Session.write_data clib.Session.open_virtual_file diff --git a/doc/conf.py b/doc/conf.py index fb47eab1d19..e43193f4060 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -78,6 +78,7 @@ "../examples/gallery/3d_plots", "../examples/gallery/seismology", "../examples/gallery/basemaps", + "../examples/gallery/histograms", "../examples/gallery/embellishments", "../examples/projections/azim", "../examples/projections/conic", @@ -150,7 +151,14 @@ html_theme_options = {} repository = "GenericMappingTools/pygmt" repository_url = "https://github.com/GenericMappingTools/pygmt" -commit_link = f'{ __commit__[:8] }' +if __commit__: + commit_link = ( + f'{ __commit__[:8] }' + ) +else: + commit_link = ( + f'{ __version__ }' + ) html_context = { "menu_links": [ ( diff --git a/doc/external_resources.md b/doc/external_resources.md new file mode 100644 index 00000000000..600ab1bafc7 --- /dev/null +++ b/doc/external_resources.md @@ -0,0 +1,21 @@ +# External Resources + +Below is a curated collection of external PyGMT resources. + +*To add your contribution to this collection, follow [these instructions](https://github.com/GenericMappingTools/pygmt/blob/master/CONTRIBUTING.md#editing-the-documentation) +to submit a pull request with your recommended addition to the +[External Resources file](https://github.com/GenericMappingTools/pygmt/blob/master/doc/external_resources.md).* + +--- + +## Tutorials + +- [2021 PyGMT course at the UAF Geophysical Institute](https://github.com/liamtoney/gi-pygmt-2021) by Liam Toney +- [Remote Online Sessions for Emerging Seismologists (ROSES): Unit 8 - PyGMT](https://www.iris.edu/hq/inclass/lesson/728) by Liam Toney +- [PyGMT Tutorial in 2021](https://github.com/MIGG-NTU/PyGMT2021) by MIGG-NTU +- [PyGMT Workshop at FOSS4G Oceania 2019](https://github.com/GenericMappingTools/foss4g2019oceania) by Wei Ji Leong + +## Examples from Publications and Posters + +- [GMT and PyGMT plotting examples](https://github.com/michaelgrund/GMT-plotting) by Michael Grund +- [NZ Antarctic Science Conference 2021 poster](https://github.com/weiji14/nzasc2021) by Wei Ji Leong diff --git a/doc/index.rst b/doc/index.rst index 0bb9b4d24f5..ca611820d23 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -21,7 +21,14 @@ overview.rst install.rst tutorials/first_figure.rst + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Examples + gallery/index.rst + external_resources.md .. toctree:: :maxdepth: 2 @@ -34,6 +41,7 @@ tutorials/regions.rst tutorials/plot.rst tutorials/lines.rst + tutorials/vectors.rst tutorials/text.rst tutorials/contour_map.rst tutorials/earth_relief.rst @@ -48,4 +56,5 @@ :caption: Reference documentation api/index.rst - changes.rst + changes.md + maintenance.md diff --git a/doc/install.rst b/doc/install.rst index b3a000b1143..75e9995331c 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -159,35 +159,17 @@ from Python. Testing your install -------------------- -Quick check -~~~~~~~~~~~ - To ensure that PyGMT and its dependencies are installed correctly, run the following in your Python interpreter:: import pygmt pygmt.show_versions() -Or run this in the command line:: - - python -c "import pygmt; pygmt.show_versions()" - - -Full test (optional) -~~~~~~~~~~~~~~~~~~~~ - -PyGMT ships with a full test suite. -You can run our tests after you install it but you will need a few extra -dependencies as well (be sure to have your conda environment activated):: + fig = pygmt.Figure() + fig.coast(region="g", frame=True, shorelines=1) + fig.show() - conda install pytest pytest-mpl ipython - -Test your installation by running the following inside a Python interpreter -(note that it may take a few minutes):: - - import pygmt - pygmt.show_versions() - pygmt.test() +If you see a global map with shorelines, then you're all set. Finding the GMT shared library diff --git a/MAINTENANCE.md b/doc/maintenance.md similarity index 79% rename from MAINTENANCE.md rename to doc/maintenance.md index f493eda2b39..dabf808d76e 100644 --- a/MAINTENANCE.md +++ b/doc/maintenance.md @@ -4,30 +4,17 @@ This page contains instructions for project maintainers about how our setup work making releases, creating packages, etc. If you want to make a contribution to the project, see the -[Contributing Guide](CONTRIBUTING.md) instead. - -## Table of Contents -* [Onboarding Access Checklist](#onboarding-access-checklist) -* [Branches](#branches) -* [Reviewing and Merging Pull Requests](#reviewing-and-merging-pull-requests) -* [Continuous Integration](#continuous-integration) -* [Continuous Documentation](#continuous-documentation) -* [Dependencies Policy](#dependencies-policy) -* [Making a Release](#making-a-release) - - [Updating the Changelog](#updating-the-changelog) - - [Check the README Syntax](#check-the-readme-syntax) - - [Pushing to PyPI and Updating the Documentation](#pushing-to-pypi-and-updating-the-documentation) - - [Archiving on Zenodo](#archiving-on-zenodo) - - [Updating the Conda Package](#updating-the-conda-package) +[Contributing Guide](https://github.com/GenericMappingTools/pygmt/blob/master/CONTRIBUTING.md) +instead. ## Onboarding Access Checklist -- [ ] Added to [python-maintainers](https://github.com/orgs/GenericMappingTools/teams/python-maintainers) team in the [GenericMappingTools](https://github.com/orgs/GenericMappingTools/teams/) organization on GitHub (gives 'maintain' permissions) -- [ ] Added as collaborator on [DAGsHub](https://dagshub.com/GenericMappingTools/pygmt/settings/collaboration) (gives 'write' permission to dvc remote storage) -- [ ] Added as moderator on [GMT forum](https://forum.generic-mapping-tools.org) (to see mod-only discussions) -- [ ] Added as member on the [PyGMT devs Slack channel](https://pygmtdevs.slack.com) (for casual conversations) -- [ ] Added as maintainer on [PyPI](https://pypi.org/project/pygmt/) and [Test PyPI](https://test.pypi.org/project/pygmt) [optional] -- [ ] Added as member on [HackMD](https://hackmd.io/@pygmt) [optional] +- Added to [python-maintainers](https://github.com/orgs/GenericMappingTools/teams/python-maintainers) team in the [GenericMappingTools](https://github.com/orgs/GenericMappingTools/teams/) organization on GitHub (gives 'maintain' permissions) +- Added as collaborator on [DAGsHub](https://dagshub.com/GenericMappingTools/pygmt/settings/collaboration) (gives 'write' permission to dvc remote storage) +- Added as moderator on [GMT forum](https://forum.generic-mapping-tools.org) (to see mod-only discussions) +- Added as member on the [PyGMT devs Slack channel](https://pygmtdevs.slack.com) (for casual conversations) +- Added as maintainer on [PyPI](https://pypi.org/project/pygmt/) and [Test PyPI](https://test.pypi.org/project/pygmt) [optional] +- Added as member on [HackMD](https://hackmd.io/@pygmt) [optional] ## Branches @@ -159,6 +146,47 @@ supported version of Python. Minimum Python and NumPy version support should be adjusted upward on every major and minor release, but never on a patch release. +## Backwards compatibility and deprecation policy + +PyGMT is still undergoing rapid developement. All of the API is subject to change +until the v1.0.0 release. + +Basic policy for backwards compatibility: + +- Any incompatible changes should go through the deprecation process below. +- Incompatible changes are only allowed in major and minor releases, not in + patch releases. +- Incompatible changes should be documented in the release notes. + +When making incompatible changes, we should follow the process: + +- Discuss whether the incompatible changes are necessary on GitHub. +- Make the changes in a backwards compatible way, and raise a `FutureWarning` + warning for old usage. At least one test using the old usage should be added. +- The warning message should clearly explain the changes and include the versions + in which the old usage is deprecated and is expected to be removed. +- The `FutureWarning` warning should appear for 2-4 minor versions, depending on + the impact of the changes. It means the deprecation period usually lasts + 3-12 months. +- Remove the old usage and warning when reaching the declared version. + +To rename a function parameter, add the `@deprecated_parameter` decorator +before the function definition (but after the `@use_alias` decorator if it exists). +Here is an example: + +``` +@fmt_docstring +@use_alias(J="projection", R="region", V="verbose") +@kwargs_to_strings(R="sequence") +@deprecate_parameter("sizes", "size", "v0.4.0", remove_version="v0.6.0") +def plot(self, x=None, y=None, data=None, size=None, direction=None, **kwargs): + pass +``` + +In this case, the old parameter name `sizes` is deprecated since v0.4.0, and will be +fully removed in v0.6.0. The new parameter name is `size`. + + ## Making a Release We try to automate the release process as much as possible. diff --git a/environment.yml b/environment.yml index cc70941f715..d44c2ff2fb8 100644 --- a/environment.yml +++ b/environment.yml @@ -1,11 +1,12 @@ name: pygmt channels: + - conda-forge/label/dev - conda-forge - defaults dependencies: # Required dependencies - pip - - gmt=6.1.1 + - gmt=6.2.0rc1 - numpy>=1.17 - pandas - xarray @@ -32,4 +33,4 @@ dependencies: - sphinx - sphinx-copybutton - sphinx-gallery - - sphinx_rtd_theme=0.5.1 + - sphinx_rtd_theme diff --git a/examples/gallery/3d_plots/scatter3d.py b/examples/gallery/3d_plots/scatter3d.py index 568c2de7cbd..0c70581fe32 100644 --- a/examples/gallery/3d_plots/scatter3d.py +++ b/examples/gallery/3d_plots/scatter3d.py @@ -47,7 +47,7 @@ y=df.sepal_length, z=df.petal_length, # Vary each symbol size according to another feature (sepal width, scaled by 0.1) - sizes=0.1 * df.sepal_width, + size=0.1 * df.sepal_width, # Use 3D cubes ("u") as symbols, with size in centimeter units ("c") style="uc", # Points colored by categorical number code diff --git a/examples/gallery/embellishments/colorbar.py b/examples/gallery/embellishments/colorbar.py index eb9994191ab..e8e633f3deb 100644 --- a/examples/gallery/embellishments/colorbar.py +++ b/examples/gallery/embellishments/colorbar.py @@ -14,7 +14,7 @@ right. - **g**: using map coordinates, e.g. ``position="g170/-45"`` for longitude 170E, latitude 45S. -- **x**: using paper coordinates, e.g. ``position="x5c/7c"`` for 5cm,7cm from anchor +- **x**: using paper coordinates, e.g. ``position="x5c/7c"`` for 5 cm,7 cm from anchor point. - **n**: using normalized (0-1) coordinates, e.g. ``position="n0.4/0.8"``. @@ -34,7 +34,7 @@ fig.colorbar( cmap="batlow", # Colorbar positioned at map coordinates (g) longitude/latitude 0.3/8.7, - # with a length/width (+w) of 4cm by 0.5cm, and plotted horizontally (+h) + # with a length/width (+w) of 4 cm by 0.5 cm, and plotted horizontally (+h) position="g0.3/8.7+w4c/0.5c+h", box=True, frame=["x+lTemperature", r"y+l\260C"], @@ -45,8 +45,8 @@ fig.colorbar( cmap="oleron", # Colorbar position justified outside map frame (J) at Middle Right (MR), - # offset (+o) by 1cm horizontally and 0cm vertically from anchor point, - # with a length/width (+w) of 7cm by 0.5cm and a box for NaN values (+n) + # offset (+o) by 1 cm horizontally and 0 cm vertically from anchor point, + # with a length/width (+w) of 7 cm by 0.5 cm and a box for NaN values (+n) position="JMR+o1c/0c+w7c/0.5c+n+mc", # Note that the label 'Elevation' is moved to the opposite side and plotted # vertically as a column of text using '+mc' in the position parameter diff --git a/examples/gallery/embellishments/inset.py b/examples/gallery/embellishments/inset.py index a8c5490e8ff..cd835aacbb0 100644 --- a/examples/gallery/embellishments/inset.py +++ b/examples/gallery/embellishments/inset.py @@ -3,9 +3,9 @@ ----- The :meth:`pygmt.Figure.inset` method adds an inset figure inside a larger -figure. The function is called using a ``with`` statement, and its position, -box, offset, and margin parameters are set. Plotting methods called within the -``with`` statement are applied to the inset figure. +figure. The function is called using a ``with`` statement, and its ``position``, +``box``, ``offset``, and ``margin`` parameters are set. Plotting methods called +within the ``with`` statement are applied to the inset figure. """ import pygmt @@ -14,10 +14,10 @@ # "brown", the water to "lightblue", the shorelines width to "thin", and adding a frame fig.coast(region="MG+r2", land="brown", water="lightblue", shorelines="thin", frame="a") # Create an inset, setting the position to top left, the width to 3.5 centimeters, and -# the x- and y-offsets to 0.2 centimeters. The margin is set to 0, and the border is "green". -with fig.inset(position="jTL+w3.5c+o0.2c", margin=0, box="+pgreen"): +# the x- and y-offsets to 0.2 centimeters. The margin is set to 0, and the border is "gold". +with fig.inset(position="jTL+w3.5c+o0.2c", margin=0, box="+pgold"): # Create a figure in the inset using coast. This example uses the azimuthal - # orthogonal projection centered at 47E, 20S. The land is set to "gray" and + # orthogonal projection centered at 47E, 20S. The land color is set to "gray" and # Madagascar is highlighted in "red". fig.coast( region="g", projection="G47/-20/3.5c", land="gray", water="white", dcw="MG+gred" diff --git a/examples/gallery/embellishments/inset_rectangle_region.py b/examples/gallery/embellishments/inset_rectangle_region.py index 89000501afb..264139775e0 100644 --- a/examples/gallery/embellishments/inset_rectangle_region.py +++ b/examples/gallery/embellishments/inset_rectangle_region.py @@ -3,9 +3,9 @@ -------------------------------------- The :meth:`pygmt.Figure.inset` method adds an inset figure inside a larger -figure. The function is called using a ``with`` statement, and its position, -box, offset, and margin can be customized. Plotting methods called within the -``with`` statement plot into the inset figure. +figure. The function is called using a ``with`` statement, and its ``position``, +``box``, ``offset``, and ``margin`` can be customized. Plotting methods called +within the ``with`` statement plot into the inset figure. """ import pygmt diff --git a/examples/gallery/embellishments/logo.py b/examples/gallery/embellishments/logo.py index e9edc4512fe..a246a0e6e52 100644 --- a/examples/gallery/embellishments/logo.py +++ b/examples/gallery/embellishments/logo.py @@ -2,7 +2,7 @@ Logo ---- -The :meth:`pygmt.Figure.logo` method allows to place the GMT logo on a map. +The :meth:`pygmt.Figure.logo` method allows to place the GMT logo on a map. """ import pygmt diff --git a/examples/gallery/histograms/README.txt b/examples/gallery/histograms/README.txt new file mode 100644 index 00000000000..4e68998cd33 --- /dev/null +++ b/examples/gallery/histograms/README.txt @@ -0,0 +1,2 @@ +Histograms +---------- diff --git a/examples/gallery/embellishments/rose.py b/examples/gallery/histograms/rose.py similarity index 100% rename from examples/gallery/embellishments/rose.py rename to examples/gallery/histograms/rose.py diff --git a/examples/gallery/images/track_sampling.py b/examples/gallery/images/track_sampling.py index 8d17987ca69..dfaae26e03d 100644 --- a/examples/gallery/images/track_sampling.py +++ b/examples/gallery/images/track_sampling.py @@ -27,7 +27,7 @@ fig.basemap(region="g", projection="Cyl_stere/150/-20/15c", frame=True) fig.grdimage(grid=grid, cmap="gray") fig.coast(land="#666666") -# Plot the sampled bathymetry points using circles (c) of 0.15 cm +# Plot the sampled bathymetry points using circles (c) of 0.15 cm size # Points are colored using elevation values (normalized for visual purposes) fig.plot( x=track.longitude, diff --git a/examples/gallery/lines/line_custom_cpt.py b/examples/gallery/lines/line_custom_cpt.py index 4406c69f697..bb42c9e54e3 100644 --- a/examples/gallery/lines/line_custom_cpt.py +++ b/examples/gallery/lines/line_custom_cpt.py @@ -15,7 +15,7 @@ import numpy as np import pygmt -# Create a list of values between 20 and 30 with at 0.2 intervals +# Create a list of values between 20 and 30 with 0.2 intervals x = np.arange(start=20, stop=30, step=0.2) fig = pygmt.Figure() diff --git a/examples/gallery/lines/linestyles.py b/examples/gallery/lines/linestyles.py index 1bd563b876b..eb68c165e29 100644 --- a/examples/gallery/lines/linestyles.py +++ b/examples/gallery/lines/linestyles.py @@ -8,8 +8,8 @@ A *pen* in GMT has three attributes: *width*, *color*, and *style*. The *style* attribute controls the appearance of the line. -Giving “dotted” or “.” yields a dotted line, whereas a dashed pen is requested -with “dashed” or “-”. Also combinations of dots and dashes, like “.-” for a +Giving "dotted" or "." yields a dotted line, whereas a dashed pen is requested +with "dashed" or "-". Also combinations of dots and dashes, like ".-" for a dot-dashed line, are allowed. For more advanced *pen* attributes, see the GMT cookbook @@ -38,7 +38,7 @@ "1p,lightblue,-.", # dash-dotted line "2p,blue,..-", # dot-dot-dashed line "2p,tomato,--.", # dash-dash-dotted line - # A pattern of 4-point-long line segment and 2-point-gap between segment, + # A pattern of 4-point-long line segments and 2-point-long gaps between segments, # with pattern offset by 2 points from the origin "2p,tomato,4_2:2p", ]: diff --git a/examples/gallery/lines/vector_heads_tails.py b/examples/gallery/lines/vector_heads_tails.py index 7c213f73006..231aabdc96c 100644 --- a/examples/gallery/lines/vector_heads_tails.py +++ b/examples/gallery/lines/vector_heads_tails.py @@ -26,7 +26,7 @@ In the following we use the :meth:`pygmt.Figure.plot` method to plot vectors with individual heads and tails. We must specify the modifiers (together with the vector type, here ``v``, see also -:doc:`Vector types documentation `) +:doc:`Vector types documentation `) by passing the corresponding shortcuts to the ``style`` parameter. """ diff --git a/examples/gallery/lines/vectors.py b/examples/gallery/lines/vector_styles.py similarity index 100% rename from examples/gallery/lines/vectors.py rename to examples/gallery/lines/vector_styles.py diff --git a/examples/gallery/lines/wiggle.py b/examples/gallery/lines/wiggle.py new file mode 100644 index 00000000000..48ea5140cd0 --- /dev/null +++ b/examples/gallery/lines/wiggle.py @@ -0,0 +1,38 @@ +""" +Wiggle along tracks +------------------- + +The :meth:`pygmt.Figure.wiggle` method can plot z = f(x,y) anomalies along +tracks. ``x``, ``y``, ``z`` can be specified as 1d arrays or within a specified +file. The ``scale`` parameter can be used to set the scale of the anomaly in +data/distance units. The positive and/or negative areas can be filled with +color by setting the ``color`` parameter. +""" + +import numpy as np +import pygmt + +# Create (x, y, z) triplets +x = np.arange(-7, 7, 0.1) +y = np.zeros(x.size) +z = 50 * np.exp(-((x / 3) ** 2)) * np.cos(2 * np.pi * x) + +fig = pygmt.Figure() +fig.basemap(region=[-8, 12, -1, 1], projection="X10c", frame=["Snlr", "xa2f1"]) +fig.wiggle( + x=x, + y=y, + z=z, + # Set anomaly scale to "20c" + scale="20c", + # Fill positive and negative areas red and gray, respectively + color=["red+p", "gray+n"], + # Set the outline width to "1.0p" + pen="1.0p", + # Draw a blue track with a width of 0.5 points + track="0.5p,blue", + # Plot a vertical scale bar at the right middle. The bar length is 100 in + # data (z) units. Set the z unit label to "nT". + position="jRM+w100+lnT", +) +fig.show() diff --git a/examples/gallery/maps/borders.py b/examples/gallery/maps/borders.py index a5944814a85..85445517e06 100644 --- a/examples/gallery/maps/borders.py +++ b/examples/gallery/maps/borders.py @@ -11,8 +11,8 @@ * **3** = Marine boundaries * **a** = All boundaries (1-3) -For example, to draw national boundaries with a line thickness of 1p and black line -color use ``borders="1/1p,black"``. You can draw multiple boundaries by passing in +For example, to draw national boundaries with a line thickness of 1p and black line +color use ``borders="1/1p,black"``. You can draw multiple boundaries by passing in a list to ``borders``. """ import pygmt diff --git a/examples/gallery/maps/land_and_water.py b/examples/gallery/maps/land_and_water.py index 207ae1d5f2d..919604f58f6 100644 --- a/examples/gallery/maps/land_and_water.py +++ b/examples/gallery/maps/land_and_water.py @@ -2,7 +2,7 @@ Color land and water -------------------- -The ``land`` and ``water`` parameters of :meth:`pygmt.Figure.coast` specify +The ``land`` and ``water`` parameters of :meth:`pygmt.Figure.coast` specify a color to fill in the land and water masses, respectively. There are many :gmt-docs:`color codes in GMT `, including standard GMT color names (like ``skyblue``), R/G/B levels (like ``0/0/255``), a hex value (like diff --git a/examples/gallery/seismology/velo_arrow_ellipse.py b/examples/gallery/seismology/velo_arrow_ellipse.py new file mode 100644 index 00000000000..3d7018aca33 --- /dev/null +++ b/examples/gallery/seismology/velo_arrow_ellipse.py @@ -0,0 +1,41 @@ +""" +Velocity arrows and confidence ellipses +--------------------------------------- + +The :meth:`pygmt.Figure.velo` method can be used to plot mean velocity arrows +and confidence ellipses. The example below plots red velocity arrows with +light-blue confidence ellipses outlined in red with the east_velocity x +north_velocity used for the station names. Note that the velocity arrows are +scaled by 0.2 and the 39% confidence limit will give an ellipse which fits +inside a rectangle of dimension east_sigma by north_sigma. +""" + +import pandas as pd +import pygmt + +fig = pygmt.Figure() +df = pd.DataFrame( + data={ + "x": [0, -8, 0, -5, 5, 0], + "y": [-8, 5, 0, -5, 0, -5], + "east_velocity": [0, 3, 4, 6, -6, 6], + "north_velocity": [0, 3, 6, 4, 4, -4], + "east_sigma": [4, 0, 4, 6, 6, 6], + "north_sigma": [6, 0, 6, 4, 4, 4], + "correlation_EN": [0.5, 0.5, 0.5, 0.5, -0.5, -0.5], + "SITE": ["0x0", "3x3", "4x6", "6x4", "-6x4", "6x-4"], + } +) +fig.velo( + data=df, + region=[-10, 8, -10, 6], + pen="0.6p,red", + uncertaintycolor="lightblue1", + line=True, + spec="e0.2/0.39/18", + frame=["WSne", "2g2f"], + projection="x0.8c", + vector="0.3c+p1p+e+gred", +) + +fig.show() diff --git a/examples/gallery/symbols/basic_symbols.py b/examples/gallery/symbols/basic_symbols.py new file mode 100644 index 00000000000..7d78c114060 --- /dev/null +++ b/examples/gallery/symbols/basic_symbols.py @@ -0,0 +1,108 @@ +""" +Basic geometric symbols +----------------------- + +The :meth:`pygmt.Figure.plot` method can plot individual geometric symbols +by passing the corresponding shortcuts to the ``style`` parameter. The 14 basic +geometric symbols are shown underneath their corresponding shortcut codes. +Four symbols (**-**, **+**, **x** and **y**) are line-symbols only for which we +can adjust the linewidth via the ``pen`` parameter. The point symbol (**p**) +only takes a color fill which we can define via the ``color`` parameter. For the +remaining symbols we may define a linewidth as well as a color fill. + +""" + +import pygmt + +fig = pygmt.Figure() +fig.basemap(region=[0, 8, 0, 3], projection="X12c/4c", frame=True) + +# define fontstlye for annotations +font = "15p,Helvetica-Bold" + +# upper row +y = 2 + +# use a dash in x direction (-) with a size of 0.9 cm, +# linewidth is set to 2p and the linecolor to "gray40" +fig.plot(x=1, y=y, style="-0.9c", pen="2p,gray40") +fig.text(x=1, y=y + 0.6, text="-", font=font) + +# use a plus (+) with a size of 0.9 cm, +# linewidth is set to 2p and the linecolor to "gray40" +fig.plot(x=2, y=y, style="+0.9c", pen="2p,gray40") +fig.text(x=2, y=y + 0.6, text="+", font=font) + +# use a star (a) with a size of 0.9 cm, +# linewidth is set to 1p, the linecolor to "black" (default) and the +# color fill to "darkorange" +fig.plot(x=3, y=y, style="a0.9c", pen="1p,black", color="darkorange") +fig.text(x=3, y=y + 0.6, text="a", font=font) + +# use a circle (c) with a size of 0.9 cm, +# linewidth is set to 1p, the linecolor to "black" and the +# color fill to "darkred" +fig.plot(x=4, y=y, style="c0.9c", pen="1p,black", color="darkred") +fig.text(x=4, y=y + 0.6, text="c", font=font) + +# use a diamond (d) with a size of 0.9 cm, +# linewidth is set to 1p, the linecolor to "black" and the +# color fill to "seagreen" +fig.plot(x=5, y=y, style="d0.9c", pen="1p,black", color="seagreen") +fig.text(x=5, y=y + 0.6, text="d", font=font) + +# use a octagon (g) with a size of 0.9 cm, +# linewidth is set to 1p, the linecolor to "black" and the +# color fill to "dodgerblue4" +fig.plot(x=6, y=y, style="g0.9c", pen="1p,black", color="dodgerblue4") +fig.text(x=6, y=y + 0.6, text="g", font=font) + +# use a hexagon (h) with a size of 0.9 cm, +# linewidth is set to 1p, the linecolor to "black" and the +# color fill to "lightgray" +fig.plot(x=7, y=y, style="h0.9c", pen="1p,black", color="lightgray") +fig.text(x=7, y=y + 0.6, text="h", font=font) + +# lower row +y = 0.5 + +# use an inverted triangle (i) with a size of 0.9 cm, +# linewidth is set to 1p, the linecolor to "black" and the +# color fill to "tomato" +fig.plot(x=1, y=y, style="i0.9c", pen="1p,black", color="tomato") +fig.text(x=1, y=y + 0.6, text="i", font=font) + +# use pentagon (n) with a size of 0.9 cm, +# linewidth is set to 1p, the linecolor to "black" and the +# color fill to "lightseagreen" +fig.plot(x=2, y=y, style="n0.9c", pen="1p,black", color="lightseagreen") +fig.text(x=2, y=y + 0.6, text="n", font=font) + +# use a point (p) with a size of 0.9 cm, +# color fill is set to "lightseagreen" +fig.plot(x=3, y=y, style="p0.9c", color="slateblue") +fig.text(x=3, y=y + 0.6, text="p", font=font) + +# use square (s) with a size of 0.9 cm, +# linewidth is set to 1p, the linecolor to "black" and the +# color fill to "gold2" +fig.plot(x=4, y=y, style="s0.9c", pen="1p,black", color="gold2") +fig.text(x=4, y=y + 0.6, text="s", font=font) + +# use triangle (t) with a size of 0.9 cm, +# linewidth is set to 1p, the linecolor to "black" and the +# color fill to "magenta4" +fig.plot(x=5, y=y, style="t0.9c", pen="1p,black", color="magenta4") +fig.text(x=5, y=y + 0.6, text="t", font=font) + +# use cross (x) with a size of 0.9 cm, +# linewidth is set to 2p and the linecolor to "gray40" +fig.plot(x=6, y=y, style="x0.9c", pen="2p,gray40") +fig.text(x=6, y=y + 0.6, text="x", font=font) + +# use a dash in y direction (y) with a size of 0.9 cm, +# linewidth is set to 2p and the linecolor to "gray40" +fig.plot(x=7, y=y, style="y0.9c", pen="2p,gray40") +fig.text(x=7, y=y + 0.6, text="y", font=font) + +fig.show() diff --git a/examples/gallery/symbols/datetime_inputs.py b/examples/gallery/symbols/datetime_inputs.py index 4851b337484..49a0b51c18d 100644 --- a/examples/gallery/symbols/datetime_inputs.py +++ b/examples/gallery/symbols/datetime_inputs.py @@ -8,14 +8,14 @@ - :class:`pandas.DatetimeIndex` - :class:`xarray.DataArray`: datetimes included in a *xarray.DataArray* - raw datetime strings in `ISO format `__ - (e.g. ``"YYYY-MM-DD"``, ``"YYYY-MM-DDTHH"``, and ``"YYYY-MM-DDTHH:MM:SS"``) + (e.g. ``"YYYY-MM-DD"``, ``"YYYY-MM-DDTHH"``, and ``"YYYY-MM-DDTHH:MM:SS"``) - Python built-in :class:`datetime.datetime` and :class:`datetime.date` -We can pass datetime inputs based on one of the types listed above directly to +We can pass datetime inputs based on one of the types listed above directly to the ``x`` and ``y`` parameters of e.g. the :meth:`pygmt.Figure.plot` method. -The ``region`` parameter has to include the :math:`x` and :math:`y` axis limits -in the form [*date_min*, *date_max*, *ymin*, *ymax*]. Here *date_min* and +The ``region`` parameter has to include the :math:`x` and :math:`y` axis limits +in the form [*date_min*, *date_max*, *ymin*, *ymax*]. Here *date_min* and *date_max* can be directly defined as datetime input. """ diff --git a/examples/gallery/symbols/points.py b/examples/gallery/symbols/points.py index be159269414..386eb818f8f 100644 --- a/examples/gallery/symbols/points.py +++ b/examples/gallery/symbols/points.py @@ -15,8 +15,8 @@ y = np.random.uniform(region[2], region[3], 100) fig = pygmt.Figure() -# Create a 15x15 cm basemap with a Cartesian projection (X) using the data region +# Create a 15 cm x 15 cm basemap with a Cartesian projection (X) using the data region fig.basemap(region=region, projection="X15c", frame=True) -# Plot using triangles (i) of 0.5 cm +# Plot using inverted triangles (i) of 0.5 cm size fig.plot(x, y, style="i0.5c", color="black") fig.show() diff --git a/examples/gallery/symbols/points_categorical.py b/examples/gallery/symbols/points_categorical.py index 9a2a302939a..3abf829e7ff 100644 --- a/examples/gallery/symbols/points_categorical.py +++ b/examples/gallery/symbols/points_categorical.py @@ -53,7 +53,7 @@ x=df.bill_length_mm, y=df.bill_depth_mm, # Vary each symbol size according to another feature (body mass, scaled by 7.5*10e-5) - sizes=df.body_mass_g * 7.5e-5, + size=df.body_mass_g * 7.5e-5, # Points colored by categorical number code color=df.species.cat.codes.astype(int), # Use colormap created by makecpt diff --git a/examples/gallery/symbols/scatter.py b/examples/gallery/symbols/scatter.py index 2d3199b35c8..2009b4945fc 100644 --- a/examples/gallery/symbols/scatter.py +++ b/examples/gallery/symbols/scatter.py @@ -21,20 +21,20 @@ projection="X10c/10c", frame=["xa0.2fg", "ya0.2fg", "WSrt"], ) -for color in ["blue", "orange", "green"]: +for color in ["gray73", "darkorange", "slateblue"]: x, y = np.random.rand(2, n) # random X and Y data in [0,1] - sizes = np.random.rand(n) * 0.5 # random size [0,0.5], in cm + size = np.random.rand(n) * 0.5 # random size [0,0.5], in cm # plot data points as circles (style="c"), with different sizes fig.plot( x=x, y=y, style="c", - sizes=sizes, + size=size, color=color, # Set the legend label, - # and set the circle size to be 0.25 cm (+S0.25c) in legend + # and set the symbol size to be 0.25 cm (+S0.25c) in legend label=f"{color}+S0.25c", - transparency=70, # set transparency level for all symbols + transparency=50, # set transparency level for all symbols ) fig.legend(transparency=30) # set transparency level for legends diff --git a/examples/projections/cyl/cyl_oblique_mercator_1.py b/examples/projections/cyl/cyl_oblique_mercator_1.py new file mode 100644 index 00000000000..70bf818f297 --- /dev/null +++ b/examples/projections/cyl/cyl_oblique_mercator_1.py @@ -0,0 +1,32 @@ +""" +Oblique Mercator +================ + +Oblique configurations of the cylinder give rise to the oblique Mercator +projection. It is particularly useful when mapping regions of large lateral +extent in an oblique direction. Both parallels and meridians are complex +curves. The projection was developed in the early 1900s by several workers. + +**oa**\|\ **oA**\ *lon0/lat0/azimuth/scale*\[**+v**] or +**Oa**\|\ **OA**\ *lon0/lat0/azimuth/width*\[**+v**] + +The projection is set with **o** or **O**. The pole is set in the +northern hemisphere with **a** or the southern hemisphere +with **A**. The central meridian is set by *lon0/lat0*. The oblique equator +is set by *azimuth*. Align the y-axis +with the optional **+v**. The figure size is set with *scale* or *width*. +""" +import pygmt + +fig = pygmt.Figure() +# Using the origin and azimuth +fig.coast( + projection="Oa-120/25/-30/6c+v", + # Set bottom left and top right coordinates of the figure with "+r" + region="-122/35/-107/22+r", + frame="afg", + land="gray", + shorelines="1/thin", + water="lightblue", +) +fig.show() diff --git a/examples/projections/cyl/cyl_oblique_mercator_2.py b/examples/projections/cyl/cyl_oblique_mercator_2.py new file mode 100644 index 00000000000..afe889863b6 --- /dev/null +++ b/examples/projections/cyl/cyl_oblique_mercator_2.py @@ -0,0 +1,32 @@ +""" +Oblique Mercator +================ + +Oblique configurations of the cylinder give rise to the oblique Mercator +projection. It is particularly useful when mapping regions of large lateral +extent in an oblique direction. Both parallels and meridians are complex +curves. The projection was developed in the early 1900s by several workers. + +**ob**\|\ **oB**\ *lon0/lat0/lon1/lat1/scale*\ [**+v**] or +**Ob**\|\ **OB**\ *lon0/lat0/lon1/lat1/width*\ [**+v**] + +The projection is set with **o** or **O**. The pole is set in the +northern hemisphere with **b** or the southern hemisphere +with **B**. The central meridian is set by *lon0/lat0*. The oblique +equator is set by *lon1/lat1*. Align the y-axis +with the optional **+v**. The figure size is set with *scale* or *width*. +""" +import pygmt + +fig = pygmt.Figure() +# Using the origin and two points +fig.coast( + projection="Ob130/35/25/35/6c", + # Set bottom left and top right coordinates of the figure with "+r" + region="130/35/145/40+r", + frame="afg", + land="gray", + shorelines="1/thin", + water="lightblue", +) +fig.show() diff --git a/examples/projections/cyl/cyl_oblique_mercator_3.py b/examples/projections/cyl/cyl_oblique_mercator_3.py new file mode 100644 index 00000000000..399dd33de89 --- /dev/null +++ b/examples/projections/cyl/cyl_oblique_mercator_3.py @@ -0,0 +1,31 @@ +""" +Oblique Mercator +================ + +Oblique configurations of the cylinder give rise to the oblique Mercator +projection. It is particularly useful when mapping regions of large lateral +extent in an oblique direction. Both parallels and meridians are complex +curves. The projection was developed in the early 1900s by several workers. + +**oc**\|\ **oC**\ *lon0/lat0/lonp/latp/scale*\ [**+v**] or +**Oc**\|\ **OC**\ *lon0/lat0/lonp/latp/width*\ [**+v**] + +The projection is set with **o** or **O**. The central meridian is set +by *lon0/lat0*. The projection pole is set by *lonp/latp* in option three. +Align the y-axis with the optional **+v**. The figure size is set +with *scale* or *width*. +""" +import pygmt + +fig = pygmt.Figure() +# Using the origin projection pole +fig.coast( + projection="Oc280/25.5/22/69/12c", + # Set bottom left and top right coordinates of the figure with "+r" + region="270/20/305/25+r", + frame="afg", + land="gray", + shorelines="1/thin", + water="lightblue", +) +fig.show() diff --git a/examples/projections/misc/misc_robinson.py b/examples/projections/misc/misc_robinson.py index f2c6b0b0136..f73fd7272fa 100644 --- a/examples/projections/misc/misc_robinson.py +++ b/examples/projections/misc/misc_robinson.py @@ -6,7 +6,7 @@ Arthur H. Robinson in 1963, is a modified cylindrical projection that is neither conformal nor equal-area. Central meridian and all parallels are straight lines; other meridians are curved. It uses lookup tables rather than analytic expressions to make -the world map “look” right 22. The scale is true along latitudes 38. The projection was +the world map "look" right 22. The scale is true along latitudes 38. The projection was originally developed for use by Rand McNally and is currently used by the National Geographic Society. diff --git a/examples/projections/misc/misc_sinusoidal.py b/examples/projections/misc/misc_sinusoidal.py index 93bac1a9938..439108a1c54 100644 --- a/examples/projections/misc/misc_sinusoidal.py +++ b/examples/projections/misc/misc_sinusoidal.py @@ -4,7 +4,7 @@ The sinusoidal projection is one of the oldest known projections, is equal-area, and has been used since the mid-16th century. It has also been called the -“Equal-area Mercator” projection. The central meridian is a straight line; all other +"Equal-area Mercator" projection. The central meridian is a straight line; all other meridians are sinusoidal curves. Parallels are all equally spaced straight lines, with scale being true along all parallels (and central meridian). diff --git a/examples/projections/misc/misc_winkel_tripel.py b/examples/projections/misc/misc_winkel_tripel.py index adbc238172f..7d2629ca879 100644 --- a/examples/projections/misc/misc_winkel_tripel.py +++ b/examples/projections/misc/misc_winkel_tripel.py @@ -4,9 +4,9 @@ In 1921, the German mathematician Oswald Winkel a projection that was to strike a compromise between the properties of three elements (area, angle and distance). The -German word “tripel” refers to this junction of where each of these elements are least +German word "tripel" refers to this junction of where each of these elements are least distorted when plotting global maps. The projection was popularized when Bartholomew -and Son started to use it in its world-renowned “The Times Atlas of the World” in the +and Son started to use it in its world-renowned "The Times Atlas of the World" in the mid-20th century. In 1998, the National Geographic Society made the Winkel Tripel as its map projection of choice for global maps. diff --git a/examples/projections/nongeo/polar.py b/examples/projections/nongeo/polar.py index 156dc952daa..a09cbf7ff1e 100644 --- a/examples/projections/nongeo/polar.py +++ b/examples/projections/nongeo/polar.py @@ -3,7 +3,7 @@ ===== Polar projections allow plotting polar coordinate data (e.g. angle -:math:`\theta` and radius *r*). +:math:`\theta` and radius *r*). The full syntax for polar projections is: diff --git a/examples/projections/table/README.txt b/examples/projections/table/README.txt index e0a821ed9cc..b5a84f7d6f8 100644 --- a/examples/projections/table/README.txt +++ b/examples/projections/table/README.txt @@ -53,11 +53,11 @@ The below table shows the projection codes for the 31 GMT projections. * - **N**\ [|lon0|/]\ *width* - :doc:`Robinson ` * - **Oa**\ |lon0|/|lat0|/\ *azim*/*width*\ [**+v**] - - Oblique Mercator, 1: origin and azim + - :doc:`Oblique Mercator, 1: origin and azim ` * - **Ob**\ |lon0|/|lat0|/|lon1|/|lat1|/\ *width*\ [**+v**] - - Oblique Mercator, 2: two points + - :doc:`Oblique Mercator, 2: two points ` * - **Oc**\ |lon0|/|lat0|/|lonp|/|latp|/\ *width*\ [**+v**] - - Oblique Mercator, 3: origin and pole + - :doc:`Oblique Mercator, 3: origin and pole ` * - **P**\ *width*\ [**+a**]\ [**+f**\ [**e**\|\ **p**\|\ *radius*]]\ [**+r**\ *offset*][**+t**\ *origin*][**+z**\ [**p**\|\ *radius*]] - :doc:`Polar ` [azimuthal] diff --git a/examples/tutorials/3d_perspective_image.py b/examples/tutorials/3d_perspective_image.py index 61236cca7be..d8377bf0921 100644 --- a/examples/tutorials/3d_perspective_image.py +++ b/examples/tutorials/3d_perspective_image.py @@ -4,15 +4,6 @@ Create 3-D perspective image or surface mesh from a grid using :meth:`pygmt.Figure.grdview`. - -.. note:: - - This tutorial assumes the use of a Python notebook, such as IPython or Jupyter Notebook. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ # sphinx_gallery_thumbnail_number = 4 diff --git a/examples/tutorials/coastlines.py b/examples/tutorials/coastlines.py index b110e946a68..0163f1d24bf 100644 --- a/examples/tutorials/coastlines.py +++ b/examples/tutorials/coastlines.py @@ -3,15 +3,6 @@ ====================== Plotting coastlines and borders is handled by :meth:`pygmt.Figure.coast`. - -.. note:: - - This tutorial assumes the use of a Python notebook, such as IPython or Jupyter Notebook. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ # sphinx_gallery_thumbnail_number = 5 diff --git a/examples/tutorials/configuration.py b/examples/tutorials/configuration.py index acbaa1bd0aa..4a205abf571 100644 --- a/examples/tutorials/configuration.py +++ b/examples/tutorials/configuration.py @@ -3,15 +3,6 @@ ========================== Default GMT parameters can be set globally or locally using :class:`pygmt.config`. - -.. note:: - - This tutorial assumes the use of a Python notebook, such as IPython or Jupyter Notebook. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ # sphinx_gallery_thumbnail_number = 3 diff --git a/examples/tutorials/contour_map.py b/examples/tutorials/contour_map.py index e13c1aa6efa..6cb83eba7cb 100644 --- a/examples/tutorials/contour_map.py +++ b/examples/tutorials/contour_map.py @@ -3,15 +3,6 @@ ================================= Plotting a contour map is handled by :meth:`pygmt.Figure.grdcontour`. - -.. note:: - - This tutorial assumes the use of a Python notebook, such as IPython or Jupyter Notebook. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ # sphinx_gallery_thumbnail_number = 5 diff --git a/examples/tutorials/earth_relief.py b/examples/tutorials/earth_relief.py index f7dc1aaf6b6..b762c19e47b 100644 --- a/examples/tutorials/earth_relief.py +++ b/examples/tutorials/earth_relief.py @@ -5,15 +5,6 @@ Plotting a map of Earth relief can use the data accessed by the :meth:`pygmt.datasets.load_earth_relief` method. The data can then be plotted using the :meth:`pygmt.Figure.grdimage` method. - -.. note:: - - This tutorial assumes the use of a Python notebook, such as IPython or Jupyter Notebook. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ # sphinx_gallery_thumbnail_number = 5 diff --git a/examples/tutorials/first_figure.py b/examples/tutorials/first_figure.py index 78f731e6f59..f245889a4be 100644 --- a/examples/tutorials/first_figure.py +++ b/examples/tutorials/first_figure.py @@ -4,16 +4,6 @@ Welcome to PyGMT! Here we'll cover some of basic concepts, like creating simple figures and naming conventions. - -.. note:: - - This tutorial assumes the use of a Python notebook, such as `IPython `__ - or `JupyterLab `__. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ ######################################################################################## diff --git a/examples/tutorials/frames.py b/examples/tutorials/frames.py index e3cb9869c2a..27253c56981 100644 --- a/examples/tutorials/frames.py +++ b/examples/tutorials/frames.py @@ -4,15 +4,6 @@ Setting the style of the map frames, ticks, etc, is handled by the ``frame`` parameter that all plotting methods of :class:`pygmt.Figure`. - -.. note:: - - This tutorial assumes the use of a Python notebook, such as IPython or Jupyter Notebook. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ # sphinx_gallery_thumbnail_number = 4 diff --git a/examples/tutorials/insets.py b/examples/tutorials/insets.py index 9d892e5755b..a49fc25390a 100644 --- a/examples/tutorials/insets.py +++ b/examples/tutorials/insets.py @@ -6,15 +6,6 @@ :meth:`pygmt.Figure.inset` method. After a large figure has been created, call ``inset`` using a ``with`` statement, and new plot elements will be added to the inset figure instead of the larger figure. - -.. note:: - - This tutorial assumes the use of a Python notebook, such as IPython or Jupyter Notebook. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ # sphinx_gallery_thumbnail_number = 4 diff --git a/examples/tutorials/lines.py b/examples/tutorials/lines.py index 76eae9fa455..10db8309269 100644 --- a/examples/tutorials/lines.py +++ b/examples/tutorials/lines.py @@ -3,15 +3,6 @@ ============== Plotting lines is handled by :meth:`pygmt.Figure.plot`. - -.. note:: - - This tutorial assumes the use of a Python notebook, such as IPython or Jupyter Notebook. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ # sphinx_gallery_thumbnail_number = 3 diff --git a/examples/tutorials/plot.py b/examples/tutorials/plot.py index 1de7bf77f57..cead5c55afb 100644 --- a/examples/tutorials/plot.py +++ b/examples/tutorials/plot.py @@ -7,15 +7,6 @@ :mod:`pygmt.datasets` package. If you don't have the data files already, they are automatically downloaded and saved to a cache directory the first time you use them (usually ``~/.gmt/cache``). - -.. note:: - - This tutorial assumes the use of a Python notebook, such as IPython or Jupyter Notebook. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ # sphinx_gallery_thumbnail_number = 3 @@ -54,7 +45,7 @@ # parameter controls the outline of the symbols and the ``color`` parameter controls the fill. # # We can map the size of the circles to the earthquake magnitude by passing an array to -# the ``sizes`` parameter. Because the magnitude is on a logarithmic scale, it helps to +# the ``size`` parameter. Because the magnitude is on a logarithmic scale, it helps to # show the differences by scaling the values using a power law. fig = pygmt.Figure() @@ -63,7 +54,7 @@ fig.plot( x=data.longitude, y=data.latitude, - sizes=0.02 * (2 ** data.magnitude), + size=0.02 * (2 ** data.magnitude), style="cc", color="white", pen="black", @@ -72,7 +63,7 @@ ######################################################################################## # Notice that we didn't include the size in the ``style`` parameter this time, just the -# symbol ``c`` (circles) and the unit ``c`` (centimeter). So in this case, the sizes +# symbol ``c`` (circles) and the unit ``c`` (centimeter). So in this case, the size # will be interpreted as being in centimeters. # # We can also map the colors of the markers to the depths by passing an array to the @@ -91,7 +82,7 @@ fig.plot( x=data.longitude, y=data.latitude, - sizes=0.02 * 2 ** data.magnitude, + size=0.02 * 2 ** data.magnitude, color=data.depth_km, cmap=True, style="cc", diff --git a/examples/tutorials/regions.py b/examples/tutorials/regions.py index 532af0e8b53..01169f305c2 100644 --- a/examples/tutorials/regions.py +++ b/examples/tutorials/regions.py @@ -5,15 +5,6 @@ Many of the plotting functions take the ``region`` parameter, which sets the area that will be shown in the figure. This tutorial covers the different types of inputs that it can accept. - -.. note:: - - This tutorial assumes the use of a Python notebook, such as IPython or Jupyter Notebook. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ import pygmt diff --git a/examples/tutorials/text.py b/examples/tutorials/text.py index 90f03e5e7a6..b0a3ec12514 100644 --- a/examples/tutorials/text.py +++ b/examples/tutorials/text.py @@ -4,15 +4,6 @@ It is often useful to add annotations to a map plot. This is handled by :meth:`pygmt.Figure.text`. - -.. note:: - - This tutorial assumes the use of a Python notebook, such as IPython or Jupyter Notebook. - To see the figures while using a Python script instead, use - ``fig.show(method="external")`` to display the figure in the default PDF viewer. - - To save the figure, use ``fig.savefig("figname.pdf")`` where ``"figname.pdf"`` - is the desired name and file extension for the saved figure. """ # sphinx_gallery_thumbnail_number = 3 diff --git a/examples/tutorials/vectors.py b/examples/tutorials/vectors.py new file mode 100644 index 00000000000..64f3e3ec543 --- /dev/null +++ b/examples/tutorials/vectors.py @@ -0,0 +1,443 @@ +""" +Plotting vectors +================ + +Plotting vectors is handled by :meth:`pygmt.Figure.plot`. +""" +# sphinx_gallery_thumbnail_number = 6 + +import numpy as np +import pygmt + +######################################################################################## +# Plot Cartesian Vectors +# ---------------------- +# +# Create a simple Cartesian vector using a starting point through +# ``x``, ``y``, and ``direction`` parameters. +# On the shown figure, the plot is projected on a 10cm X 10cm region, +# which is specified by the ``projection`` parameter. +# The direction is specified +# by a list of two 1d arrays structured as ``[[angle_in_degrees], [length]]``. +# The angle is measured in degrees and moves counter-clockwise from the +# horizontal. +# The length of the vector uses centimeters by default but +# could be changed using :meth:`pygmt.config` +# (Check the next examples for unit changes). +# +# Notice that the ``v`` in the ``style`` parameter stands for +# vector; it distinguishes it from regular lines and allows for +# different customization. ``0c`` is used to specify the size +# of the arrow head which explains why there is no arrow on either +# side of the vector. + +fig = pygmt.Figure() +fig.plot( + region=[0, 10, 0, 10], + projection="X10c/10c", + frame="ag", + x=2, + y=8, + style="v0c", + direction=[[-45], [6]], +) +fig.show() + +######################################################################################## +# In this example, we apply the same concept shown previously to plot multiple +# vectors. Notice that instead of passing int/float to ``x`` and ``y``, a list +# of all x and y coordinates will be passed. Similarly, the length of direction +# list will increase accordingly. +# +# Additionally, we change the style of the vector to include a red +# arrow head at the end (**+e**) of the vector and increase the +# thickness (``pen="2p"``) of the vector stem. A list of different +# styling attributes can be found in +# :doc:`Vector heads and tails `. + +fig = pygmt.Figure() +fig.plot( + region=[0, 10, 0, 10], + projection="X10c/10c", + frame="ag", + x=[2, 4], + y=[8, 1], + style="v0.6c+e", + direction=[[-45, 23], [6, 3]], + pen="2p", + color="red3", +) +fig.show() + +######################################################################################## +# The default unit of vector length is centimeters, +# however, this can be changed to inches or points. Note that, in PyGMT, +# one point is defined as 1/72 inch. +# +# In this example, the graphed region is 5in X 5in, but +# the length of the first vector is still graphed in centimeters. +# Using ``pygmt.config(PROJ_LENGTH_UNIT="i")``, the default unit +# can be changed to inches in the second plotted vector. + +fig = pygmt.Figure() +# Vector 1 with default unit as cm +fig.plot( + region=[0, 10, 0, 10], + projection="X5i/5i", + frame="ag", + x=2, + y=8, + style="v1c+e", + direction=[[0], [3]], + pen="2p", + color="red3", +) +# Vector 2 after changing default unit to inch +with pygmt.config(PROJ_LENGTH_UNIT="i"): + fig.plot( + x=2, + y=7, + direction=[[0], [3]], + style="v1c+e", + pen="2p", + color="red3", + ) +fig.show() + +######################################################################################## +# Vectors can also be plotted by including all the information +# about a vector in a single list. However, this requires creating +# a 2D list or numpy array containing all vectors. +# Each vector list contains the information structured as: +# ``[x_start, y_start, direction_degrees, length]``. +# +# If this approach is chosen, the ``data`` parameter must be +# used instead of ``x``, ``y`` and ``direction``. + +# Create a list of lists that include each vector information +vectors = [[2, 3, 45, 4]] + +fig = pygmt.Figure() +fig.plot( + region=[0, 10, 0, 10], + projection="X10c/10c", + frame="ag", + data=vectors, + style="v0.6c+e", + pen="2p", + color="red3", +) +fig.show() + +######################################################################################## +# Using the functionality mentioned in the previous example, +# multiple vectors can be plotted at the same time. Another +# vector could be simply added to the 2D list or numpy +# array object and passed using ``data`` parameter. + +# Vector specifications structured as: [x_start, y_start, direction_degrees, length] +vector_1 = [2, 3, 45, 4] +vector_2 = [7.5, 8.3, -120.5, 7.2] +# Create a list of lists that include each vector information +vectors = [vector_1, vector_2] +# Vectors structure: [[2, 3, 45, 4], [7.5, 8.3, -120.5, 7.2]] + +fig = pygmt.Figure() +fig.plot( + region=[0, 10, 0, 10], + projection="X10c/10c", + frame="ag", + data=vectors, + style="v0.6c+e", + pen="2p", + color="red3", +) +fig.show() + +######################################################################################## +# In this example, cartesian vectors are plotted over a Mercator +# projection of the continental US. The x values represent the +# longitude and y values represent the latitude where the vector starts. +# +# This example also shows some of the styles a vector supports. +# The beginning point of the vector (**+b**) +# should take the shape of a circle (**c**). Similarly, the end +# point of the vector (**+e**) should have an arrow shape (**a**) +# (to draw a plain arrow, use **A** instead). Lastly, the **+a** +# specifies the angle of the vector head apex (30 degrees in +# this example). + +# Create a plot with coast, Mercator projection (M) over the continental US +fig = pygmt.Figure() +fig.coast( + region=[-127, -64, 24, 53], + projection="M10c", + frame="ag", + borders=1, + shorelines="0.25p,black", + area_thresh=4000, + land="grey", + water="lightblue", +) + +# Plot a vector using the x, y, direction parameters +style = "v0.4c+bc+ea+a30" +fig.plot( + x=-110, + y=40, + style=style, + direction=[[-25], [3]], + pen="1p", + color="red3", +) + +# vector specifications structured as: [x_start, y_start, direction_degrees, length] +vector_2 = [-82, 40.5, 138, 2.5] +vector_3 = [-71.2, 45, -115.7, 4] +# Create a list of lists that include each vector information +vectors = [vector_2, vector_3] + +# Plot vectors using the data parameter. +fig.plot( + data=vectors, + style=style, + pen="1p", + color="yellow", +) +fig.show() + +######################################################################################## +# Another example of plotting cartesian vectors over a coast plot. This time +# a Transverse Mercator projection is used. Additionally, :func:`numpy.linspace` +# is used to create 5 vectors with equal stops. + +x = np.linspace(36, 42, 5) # x values = [36. 37.5 39. 40.5 42. ] +y = np.linspace(39, 39, 5) # y values = [39. 39. 39. 39.] +direction = np.linspace(-90, -90, 5) # direction values = [-90. -90. -90. -90.] +length = np.linspace(1.5, 1.5, 5) # length values = [1.5 1.5 1.5 1.5] + +# Create a plot with coast, Mercator projection (M) over the continental US +fig = pygmt.Figure() +fig.coast( + region=[20, 50, 30, 45], + projection="T35/10c", + frame=True, + borders=1, + shorelines="0.25p,black", + area_thresh=4000, + land="lightbrown", + water="lightblue", +) + +fig.plot( + x=x, + y=y, + style="v0.4c+ea+bc", + direction=[direction, length], + pen="0.6p", + color="red3", +) + +fig.show() + +######################################################################################## +# Plot Circular Vectors +# --------------------- +# +# When plotting circular vectors, all of the information for a single vector is +# to be stored in a list. Each circular vector list is structured as: +# ``[x_start, y_start, radius, degree_start, degree_stop]``. The first two values in +# the vector list represent the origin of the circle that will be plotted. +# The next value is the radius which is represented on the plot in centimeters. +# +# The last two values in the vector list represent the degree at which the plot +# will start and stop. These values are measured counter-clockwise from the horizontal +# axis. In this example, the result show is the left half of a circle as the +# plot starts at 90 degrees and goes until 270. Notice that the ``m`` in the +# ``style`` parameter stands for circular vectors. + +fig = pygmt.Figure() + +circular_vector_1 = [0, 0, 2, 90, 270] +data = [circular_vector_1] +fig.plot( + region=[-5, 5, -5, 5], + projection="X10c", + frame="ag", + data=data, + style="m0.5c+ea", + pen="2p", + color="red3", +) + +# Another example using np.array() +circular_vector_2 = [0, 0, 4, -90, 90] +data = np.array([circular_vector_2]) + +fig.plot( + data=data, + style="m0.5c+ea", + pen="2p", + color="red3", +) +fig.show() + +######################################################################################## +# When plotting multiple circular vectors, a two dimensional array or numpy array +# object should be passed as the ``data`` parameter. In this example, :func:`numpy.column_stack` +# is used to generate this two dimensional array. Other numpy objects are used to +# generate linear values for the ``radius`` parameter and random values for +# the ``degree_stop`` parameter discussed in the previous example. This is +# the reason in which each vector has +# a different appearance on the projection. + +vector_num = 5 +radius = 3 - (0.5 * np.arange(0, vector_num)) +startdir = np.full(vector_num, 90) +stopdir = 180 + (50 * np.arange(0, vector_num)) +data = np.column_stack( + [np.full(vector_num, 0), np.full(vector_num, 0), radius, startdir, stopdir] +) + +fig = pygmt.Figure() +fig.plot( + region=[-5, 5, -5, 5], + projection="X10c", + frame="ag", + data=data, + style="m0.5c+ea", + pen="2p", + color="red3", +) +fig.show() + +######################################################################################## +# Much like when plotting Cartesian vectors, the default unit used is centimeters. +# When this is changed to inches, the size of the plot appears larger when the +# projection units do not change. Below is an example of two circular vectors. +# One is plotted using the default unit, and the second is plotted using inches. +# Despite using the same list to plot the vectors, a different measurement unit +# causes one to be larger than the other. + +circular_vector = [6, 5, 1, 90, 270] + +fig = pygmt.Figure() +fig.plot( + region=[0, 10, 0, 10], + projection="X10c", + frame="ag", + data=[circular_vector], + style="m0.5c+ea", + pen="2p", + color="red3", +) + +with pygmt.config(PROJ_LENGTH_UNIT="i"): + fig.plot( + data=[circular_vector], + style="m0.5c+ea", + pen="2p", + color="red3", + ) +fig.show() + +######################################################################################## +# Plot Geographic Vectors +# ----------------------- +# On this map, +# ``point_1`` and ``point_2`` are coordinate pairs used to set the +# start and end points of the geographic vector. +# The geographical vector is going from Idaho to +# Chicago. To style geographic +# vectors, use ``=`` at the begining of the ``style`` parameter. +# Other styling features such as vector stem thickness and head color +# can be passed into the ``pen`` and ``color`` parameters. +# +# Note that the **+s** is added to use a startpoint and an endpoint +# to represent the vector instead of input angle and length. + +point_1 = [-114.7420, 44.0682] +point_2 = [-87.6298, 41.8781] +data = np.array([point_1 + point_2]) + +fig = pygmt.Figure() +fig.coast( + region=[-127, -64, 24, 53], + projection="M10c", + frame=True, + borders=1, + shorelines="0.25p,black", + area_thresh=4000, +) +fig.plot( + data=data, + style="=0.5c+ea+s", + pen="2p", + color="red3", +) +fig.show() + +######################################################################################## +# Using the same technique shown in the previous example, +# multiple vectors can be plotted in a chain where the endpoint +# of one is the starting point of another. This can be done +# by adding the coordinate lists together to create this structure: +# ``[[start_latitude, start_longitude, end_latitude, end_longitude]]``. +# Each list within the 2D list contains the start and end information +# for each vector. + +# Coordinate pairs for all the locations used +ME = [-69.4455, 45.2538] +CHI = [-87.6298, 41.8781] +SEA = [-122.3321, 47.6062] +NO = [-90.0715, 29.9511] +KC = [-94.5786, 39.0997] +CA = [-119.4179, 36.7783] + +# Add array to piece together the vectors +data = [ME + CHI, CHI + SEA, SEA + KC, KC + NO, NO + CA] + +fig = pygmt.Figure() +fig.coast( + region=[-127, -64, 24, 53], + projection="M10c", + frame=True, + borders=1, + shorelines="0.25p,black", + area_thresh=4000, +) +fig.plot( + data=data, + style="=0.5c+ea+s", + pen="2p", + color="red3", +) +fig.show() + +################################################################################ +# This example plots vectors over a Mercator projection. The starting points are +# located at SA which is South Africa and going to four different +# locations. + +SA = [22.9375, -30.5595] +EUR = [15.2551, 54.5260] +ME = [-69.4455, 45.2538] +AS = [100.6197, 34.0479] +NM = [-105.8701, 34.5199] +data = np.array([SA + EUR, SA + ME, SA + AS, SA + NM]) + +fig = pygmt.Figure() +fig.coast( + region=[-180, 180, -80, 80], + projection="M0/0/12c", + frame="afg", + land="lightbrown", + water="lightblue", +) +fig.plot( + data=data, + style="=0.5c+ea+s", + pen="2p", + color="red3", +) +fig.show() diff --git a/pygmt/__init__.py b/pygmt/__init__.py index 2aeb76d10a6..1dc2ed79ac4 100644 --- a/pygmt/__init__.py +++ b/pygmt/__init__.py @@ -25,7 +25,7 @@ # Import modules to make the high-level GMT Python API from pygmt import datasets from pygmt.accessors import GMTDataArrayAccessor -from pygmt.figure import Figure +from pygmt.figure import Figure, set_display from pygmt.session_management import begin as _begin from pygmt.session_management import end as _end from pygmt.src import ( @@ -47,7 +47,7 @@ # Get semantic version through setuptools-scm __version__ = f'v{get_distribution("pygmt").version}' # e.g. v0.1.2.dev3+g0ab3cd78 -__commit__ = __version__.split("+g")[-1] # 0ab3cd78 +__commit__ = __version__.split("+g")[-1] if "+g" in __version__ else "" # 0ab3cd78 # Start our global modern mode session _begin() diff --git a/pygmt/clib/session.py b/pygmt/clib/session.py index 3e79f558a8a..d13cb911091 100644 --- a/pygmt/clib/session.py +++ b/pygmt/clib/session.py @@ -60,6 +60,7 @@ np.uint64: "GMT_ULONG", np.uint32: "GMT_UINT", np.datetime64: "GMT_DATETIME", + np.str_: "GMT_TEXT", } @@ -719,9 +720,7 @@ def _check_dtype_and_dim(self, array, ndim): """ # check the array has the given dimension if array.ndim != ndim: - raise GMTInvalidInput( - "Expected a numpy 1d array, got {}d.".format(array.ndim) - ) + raise GMTInvalidInput(f"Expected a numpy 1d array, got {array.ndim}d.") # check the array has a valid/known data type if array.dtype.type not in DTYPES: @@ -745,7 +744,7 @@ def put_vector(self, dataset, column, vector): first. Use ``family='GMT_IS_DATASET|GMT_VIA_VECTOR'``. Not at all numpy dtypes are supported, only: float64, float32, int64, - int32, uint64, and uint32. + int32, uint64, uint32, datetime64 and str_. .. warning:: The numpy array must be C contiguous in memory. If it comes from a @@ -777,11 +776,14 @@ def put_vector(self, dataset, column, vector): ) gmt_type = self._check_dtype_and_dim(vector, ndim=1) - if gmt_type == self["GMT_DATETIME"]: + if gmt_type in (self["GMT_TEXT"], self["GMT_DATETIME"]): vector_pointer = (ctp.c_char_p * len(vector))() - vector_pointer[:] = np.char.encode( - np.datetime_as_string(array_to_datetime(vector)) - ) + if gmt_type == self["GMT_DATETIME"]: + vector_pointer[:] = np.char.encode( + np.datetime_as_string(array_to_datetime(vector)) + ) + else: + vector_pointer[:] = np.char.encode(vector) else: vector_pointer = vector.ctypes.data_as(ctp.c_void_p) status = c_put_vector( @@ -789,11 +791,9 @@ def put_vector(self, dataset, column, vector): ) if status != 0: raise GMTCLibError( - " ".join( - [ - "Failed to put vector of type {}".format(vector.dtype), - "in column {} of dataset.".format(column), - ] + ( + f"Failed to put vector of type {vector.dtype} " + f"in column {column} of dataset." ) ) diff --git a/pygmt/datasets/earth_relief.py b/pygmt/datasets/earth_relief.py index 1a949cc38f4..9c248989f57 100644 --- a/pygmt/datasets/earth_relief.py +++ b/pygmt/datasets/earth_relief.py @@ -10,7 +10,7 @@ from pygmt.src import grdcut, which -@kwargs_to_strings(convert_bools=False, region="sequence") +@kwargs_to_strings(region="sequence") def load_earth_relief(resolution="01d", region=None, registration=None, use_srtm=False): r""" Load Earth relief grids (topography and bathymetry) in various resolutions. @@ -133,7 +133,7 @@ def load_earth_relief(resolution="01d", region=None, registration=None, use_srtm f"'region' is required for Earth relief resolution '{resolution}'." ) fname = which(f"@earth_relief_{resolution}{reg}", download="a") - with xr.open_dataarray(fname) as dataarray: + with xr.open_dataarray(fname, engine="netcdf4") as dataarray: grid = dataarray.load() _ = grid.gmt # load GMTDataArray accessor information else: diff --git a/pygmt/figure.py b/pygmt/figure.py index b6b4289e3a3..b3f58c3f156 100644 --- a/pygmt/figure.py +++ b/pygmt/figure.py @@ -6,9 +6,10 @@ from tempfile import TemporaryDirectory try: - from IPython.display import Image -except ImportError: - Image = None + import IPython +except ModuleNotFoundError: + IPython = None # pylint: disable=invalid-name + from pygmt.clib import Session from pygmt.exceptions import GMTError, GMTInvalidInput @@ -25,6 +26,23 @@ # This is needed for the sphinx-gallery scraper in pygmt/sphinx_gallery.py SHOWED_FIGURES = [] +# Configurations for figure display +SHOW_CONFIG = { + "method": "external", # Open in an external viewer by default +} + +# Show figures in Jupyter notebooks if available +if IPython: + get_ipython = IPython.get_ipython() # pylint: disable=invalid-name + if get_ipython and "IPKernelApp" in get_ipython.config: # Jupyter Notebook enabled + SHOW_CONFIG["method"] = "notebook" + +# Set environment variable PYGMT_USE_EXTERNAL_DISPLAY to 'false' to disable +# external display. Use it when running the tests and building the docs to +# avoid popping up windows. +if os.environ.get("PYGMT_USE_EXTERNAL_DISPLAY", "true").lower() == "false": + SHOW_CONFIG["method"] = "none" + class Figure: """ @@ -61,7 +79,9 @@ class Figure: def __init__(self): self._name = unique_name() - self._preview_dir = TemporaryDirectory(prefix=self._name + "-preview-") + self._preview_dir = TemporaryDirectory( # pylint: disable=consider-using-with + prefix=f"{self._name}-preview-" + ) self._activate_figure() def __del__(self): @@ -237,62 +257,72 @@ def savefig( if show: launch_external_viewer(fname) - def show(self, dpi=300, width=500, method="static"): + def show(self, dpi=300, width=500, method=None): """ Display a preview of the figure. - Inserts the preview in the Jupyter notebook output. You will need to - have IPython installed for this to work. You should have it if you are - using the notebook. + Inserts the preview in the Jupyter notebook output if available, + otherwise opens it in the default viewer for your operating system + (falls back to the default web browser). + + :func:`pygmt.set_display` can select the default display method + (**notebook**, **external**, or **none**). + + The ``method`` parameter can also override the default display method + for the current figure. Parameters ``dpi`` and ``width`` can be used + to control the resolution and dimension of the figure in the notebook. + + Note: The external viewer can be disabled by setting the + PYGMT_USE_EXTERNAL_DISPLAY environment variable to **false**. + This is useful when running unit tests and building the documentation + in consoles without a Graphical User Interface. - If ``method='external'``, makes PDF preview instead and opens it in the - default viewer for your operating system (falls back to the default web - browser). Note that the external viewer does not block the current - process, so this won't work in a script. + Note that the external viewer does not block the current process. Parameters ---------- dpi : int - The image resolution (dots per inch). + The image resolution (dots per inch) in Jupyter notebooks. width : int - Width of the figure shown in the notebook in pixels. Ignored if - ``method='external'``. + The image width (in pixels) in Jupyter notebooks. method : str - How the figure will be displayed. Options are (1) ``'static'``: PNG - preview (default); (2) ``'external'``: PDF preview in an external - program. + How the current figure will be displayed. Options are - Returns - ------- - img : IPython.display.Image - Only if ``method != 'external'``. + - **external**: PDF preview in an external program [default] + - **notebook**: PNG preview [default in Jupyter notebooks] + - **none**: Disable image preview """ # Module level variable to know which figures had their show method # called. Needed for the sphinx-gallery scraper. SHOWED_FIGURES.append(self) - if method not in ["static", "external"]: - raise GMTInvalidInput("Invalid show method '{}'.".format(method)) - if method == "external": - pdf = self._preview(fmt="pdf", dpi=dpi, anti_alias=False, as_bytes=False) - launch_external_viewer(pdf) - img = None - elif method == "static": - png = self._preview( - fmt="png", dpi=dpi, anti_alias=True, as_bytes=True, transparent=True + # Set the display method + if method is None: + method = SHOW_CONFIG["method"] + + if method not in ["external", "notebook", "none"]: + raise GMTInvalidInput( + ( + f"Invalid display method '{method}', " + "should be either 'notebook', 'external', or 'none'." + ) ) - if Image is None: + + if method in ["notebook", "none"]: + if IPython is None: raise GMTError( - " ".join( - [ - "Cannot find IPython.", - "Make sure you have it installed", - "or use 'method=\"external\"' to open in an external viewer.", - ] + ( + "Notebook display is selected, but IPython is not available. " + "Make sure you have IPython installed, " + "or run the script in a Jupyter notebook." ) ) - img = Image(data=png, width=width) - return img + png = self._preview(fmt="png", dpi=dpi, anti_alias=True, as_bytes=True) + IPython.display.display(IPython.display.Image(data=png, width=width)) + + if method == "external": + pdf = self._preview(fmt="pdf", dpi=dpi, anti_alias=False, as_bytes=False) + launch_external_viewer(pdf) def shift_origin(self, xshift=None, yshift=None): """ @@ -349,7 +379,7 @@ def _preview(self, fmt, dpi, as_bytes=False, **kwargs): If ``as_bytes=False``, this is the file name of the preview image file. Else, it is the file content loaded as a bytes string. """ - fname = os.path.join(self._preview_dir.name, "{}.{}".format(self._name, fmt)) + fname = os.path.join(self._preview_dir.name, f"{self._name}.{fmt}") self.savefig(fname, dpi=dpi, **kwargs) if as_bytes: with open(fname, "rb") as image: @@ -385,6 +415,7 @@ def _repr_html_(self): grdcontour, grdimage, grdview, + histogram, image, inset, legend, @@ -397,4 +428,30 @@ def _repr_html_(self): solar, subplot, text, + velo, + wiggle, ) + + +def set_display(method=None): + """ + Set the display method. + + Parameters + ---------- + method : str or None + The method to display an image. Choose from: + + - **external**: PDF preview in an external program [default] + - **notebook**: PNG preview [default in Jupyter notebooks] + - **none**: Disable image preview + """ + if method in ["notebook", "external", "none"]: + SHOW_CONFIG["method"] = method + elif method is not None: + raise GMTInvalidInput( + ( + f"Invalid display mode '{method}', " + "should be either 'notebook', 'external' or 'none'." + ) + ) diff --git a/pygmt/helpers/__init__.py b/pygmt/helpers/__init__.py index 84aaad0fb9a..2b372c59aa1 100644 --- a/pygmt/helpers/__init__.py +++ b/pygmt/helpers/__init__.py @@ -1,7 +1,12 @@ """ Functions, classes, decorators, and context managers to help wrap GMT modules. """ -from pygmt.helpers.decorators import fmt_docstring, kwargs_to_strings, use_alias +from pygmt.helpers.decorators import ( + deprecate_parameter, + fmt_docstring, + kwargs_to_strings, + use_alias, +) from pygmt.helpers.tempfile import GMTTempFile, unique_name from pygmt.helpers.utils import ( args_in_kwargs, diff --git a/pygmt/helpers/decorators.py b/pygmt/helpers/decorators.py index d050cf96ffb..e020f010d3b 100644 --- a/pygmt/helpers/decorators.py +++ b/pygmt/helpers/decorators.py @@ -7,6 +7,7 @@ """ import functools import textwrap +import warnings import numpy as np from pygmt.exceptions import GMTInvalidInput @@ -36,7 +37,7 @@ (e.g., *color1*,\ *color2*,\ *color3*) to build a linear continuous CPT from those colors automatically.""", "G": """\ - color : str + color : str or 1d array Select color or pattern for filling of symbols or polygons. Default is no fill.""", "V": """\ @@ -302,14 +303,14 @@ def new_module(*args, **kwargs): return alias_decorator -def kwargs_to_strings(convert_bools=True, **conversions): +def kwargs_to_strings(**conversions): """ Decorator to convert given keyword arguments to strings. The strings are what GMT expects from command line arguments. - Converts all boolean arguments by default. Transforms ``True`` into ``''`` - (empty string) and removes the argument from ``kwargs`` if ``False``. + Boolean arguments and None are not converted and will be processed in the + ``build_arg_string`` function. You can also specify other conversions to specific arguments. @@ -323,9 +324,6 @@ def kwargs_to_strings(convert_bools=True, **conversions): Parameters ---------- - convert_bools : bool - If ``True``, convert all boolean arguments to strings using the rules - specified above. If ``False``, leave them as they are. conversions : keyword arguments Keyword arguments specifying other kinds of conversions that should be performed. The keyword is the name of the argument and the value is the @@ -356,16 +354,18 @@ def kwargs_to_strings(convert_bools=True, **conversions): >>> module(R="5/6/7/8") {'R': '5/6/7/8'} >>> module(P=True) - {'P': ''} + {'P': True} >>> module(P=False) - {} + {'P': False} + >>> module(P=None) + {'P': None} >>> module(i=[1, 2]) {'i': '1,2'} >>> module(files=["data1.txt", "data2.txt"]) {'files': 'data1.txt data2.txt'} >>> # Other non-boolean arguments are passed along as they are >>> module(123, bla=(1, 2, 3), foo=True, A=False, i=(5, 6)) - {'bla': (1, 2, 3), 'foo': '', 'i': '5,6'} + {'A': False, 'bla': (1, 2, 3), 'foo': True, 'i': '5,6'} args: 123 >>> import datetime >>> module( @@ -416,8 +416,6 @@ def new_module(*args, **kwargs): """ New module instance that converts the arguments first. """ - if convert_bools: - kwargs = remove_bools(kwargs) for arg, fmt in conversions.items(): if arg in kwargs: value = kwargs[arg] @@ -444,28 +442,80 @@ def new_module(*args, **kwargs): return converter -def remove_bools(kwargs): +def deprecate_parameter(oldname, newname, deprecate_version, remove_version): """ - Remove booleans from arguments. + Decorator to deprecate a parameter. - If ``True``, replace it with an empty string. If ``False``, completely - remove the entry from the argument list. + The old parameter name will be automatically swapped to the new parameter + name, and users will receive a FutureWarning to inform them of the pending + deprecation. + + Use this decorator below the ``use_alias`` decorator. Parameters ---------- - kwargs : dict - Dictionary with the keyword arguments. + oldname : str + The old, deprecated parameter name. + newname : str + The new parameter name. + deprecate_version : str + The PyGMT version when the old parameter starts to be deprecated. + remove_version : str + The PyGMT version when the old parameter will be fully removed. - Returns - ------- - new_kwargs : dict - A copy of `kwargs` with the booleans parsed. + Examples + -------- + >>> @deprecate_parameter("sizes", "size", "v0.0.0", "v9.9.9") + ... @deprecate_parameter("colors", "color", "v0.0.0", "v9.9.9") + ... @deprecate_parameter("infile", "data", "v0.0.0", "v9.9.9") + ... def module(data, size=0, **kwargs): + ... "A module that prints the arguments it received" + ... print(f"data={data}, size={size}, color={kwargs['color']}") + >>> # new names are supported + >>> module(data="table.txt", size=5.0, color="red") + data=table.txt, size=5.0, color=red + >>> # old names are supported, FutureWarning warnings are reported + >>> with warnings.catch_warnings(record=True) as w: + ... module(infile="table.txt", sizes=5.0, colors="red") + ... # check the number of warnings + ... assert len(w) == 3 + ... for i in range(len(w)): + ... assert issubclass(w[i].category, FutureWarning) + ... assert "deprecated" in str(w[i].message) + ... + data=table.txt, size=5.0, color=red + >>> # using both old and new names will raise an GMTInvalidInput exception + >>> import pytest + >>> with pytest.raises(GMTInvalidInput): + ... module(data="table.txt", size=5.0, sizes=4.0) + ... """ - new_kwargs = {} - for arg, value in kwargs.items(): - if isinstance(value, bool): - if value: - new_kwargs[arg] = "" - else: - new_kwargs[arg] = value - return new_kwargs + + def deprecator(module_func): + """ + The decorator that creates the new function to work with both old and + new parameters. + """ + + @functools.wraps(module_func) + def new_module(*args, **kwargs): + """ + New module instance that converts old parameters to new parameters. + """ + if oldname in kwargs: + if newname in kwargs: + raise GMTInvalidInput( + f"Can't provide both '{newname}' and '{oldname}'." + ) + msg = ( + f"The '{oldname}' parameter has been deprecated since {deprecate_version}" + f" and will be removed in {remove_version}." + f" Please use '{newname}' instead." + ) + warnings.warn(msg, category=FutureWarning, stacklevel=2) + kwargs[newname] = kwargs.pop(oldname) + return module_func(*args, **kwargs) + + return new_module + + return deprecator diff --git a/pygmt/helpers/testing.py b/pygmt/helpers/testing.py index 364faa532b5..1192d0f23fa 100644 --- a/pygmt/helpers/testing.py +++ b/pygmt/helpers/testing.py @@ -42,7 +42,9 @@ def check_figures_equal(*, extensions=("png",), tol=0.0, result_dir="result_imag ... fig_ref = Figure() ... fig_ref.basemap(projection="X5c", region=[0, 5, 0, 5], frame=True) ... fig_test = Figure() - ... fig_test.basemap(projection="X5c", region=[0, 5, 0, 5], frame="af") + ... fig_test.basemap( + ... projection="X5c", region=[0, 5, 0, 5], frame=["WrStZ", "af"] + ... ) ... return fig_ref, fig_test >>> test_check_figures_equal() >>> assert len(os.listdir("tmp_result_images")) == 0 @@ -51,7 +53,7 @@ def check_figures_equal(*, extensions=("png",), tol=0.0, result_dir="result_imag >>> @check_figures_equal(result_dir="tmp_result_images") ... def test_check_figures_unequal(): ... fig_ref = Figure() - ... fig_ref.basemap(projection="X5c", region=[0, 5, 0, 5], frame=True) + ... fig_ref.basemap(projection="X5c", region=[0, 6, 0, 6], frame=True) ... fig_test = Figure() ... fig_test.basemap(projection="X5c", region=[0, 3, 0, 3], frame=True) ... return fig_ref, fig_test diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index 749ebe63e5b..36a957e83f9 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -5,6 +5,7 @@ import shutil import subprocess import sys +import time import webbrowser from collections.abc import Iterable from contextlib import contextmanager @@ -106,7 +107,8 @@ def build_arg_string(kwargs): Transform keyword arguments into a GMT argument string. Make sure all arguments have been previously converted to a string - representation using the ``kwargs_to_strings`` decorator. + representation using the ``kwargs_to_strings`` decorator. The only + exceptions are True, False and None. Any lists or tuples left will be interpreted as multiple entries for the same command line argument. For example, the kwargs entry ``'B': ['xa', @@ -128,10 +130,20 @@ def build_arg_string(kwargs): >>> print( ... build_arg_string( - ... dict(R="1/2/3/4", J="X4i", P="", E=200, X=None, Y=None) + ... dict( + ... A=True, + ... B=False, + ... E=200, + ... J="X4c", + ... P="", + ... R="1/2/3/4", + ... X=None, + ... Y=None, + ... Z=0, + ... ) ... ) ... ) - -E200 -JX4i -P -R1/2/3/4 + -A -E200 -JX4c -P -R1/2/3/4 -Z0 >>> print( ... build_arg_string( ... dict( @@ -142,20 +154,22 @@ def build_arg_string(kwargs): ... ) ... ) ... ) - -Bxaf -Byaf -BWSen -I1/1p,blue -I2/0.25p,blue -JX4i -R1/2/3/4 + -BWSen -Bxaf -Byaf -I1/1p,blue -I2/0.25p,blue -JX4i -R1/2/3/4 """ - sorted_args = [] - for key in sorted(kwargs): + gmt_args = [] + # Exclude arguments that are None and False + filtered_kwargs = { + k: v for k, v in kwargs.items() if (v is not None and v is not False) + } + for key in filtered_kwargs: if is_nonstr_iter(kwargs[key]): for value in kwargs[key]: - sorted_args.append("-{}{}".format(key, value)) - elif kwargs[key] is None: # arguments like -XNone are invalid - continue + gmt_args.append(f"-{key}{value}") + elif kwargs[key] is True: + gmt_args.append(f"-{key}") else: - sorted_args.append("-{}{}".format(key, kwargs[key])) - - arg_str = " ".join(sorted_args) - return arg_str + gmt_args.append(f"-{key}{kwargs[key]}") + return " ".join(sorted(gmt_args)) def is_nonstr_iter(value): @@ -220,6 +234,9 @@ def launch_external_viewer(fname): os.startfile(fname) # pylint: disable=no-member else: webbrowser.open_new_tab(f"file://{fname}") + # suspend the execution for 0.5 s to avoid the images being deleted + # when a Python script exits + time.sleep(0.5) def args_in_kwargs(args, kwargs): diff --git a/pygmt/src/__init__.py b/pygmt/src/__init__.py index 7911195bf57..083a2970109 100644 --- a/pygmt/src/__init__.py +++ b/pygmt/src/__init__.py @@ -17,6 +17,7 @@ from pygmt.src.grdinfo import grdinfo from pygmt.src.grdtrack import grdtrack from pygmt.src.grdview import grdview +from pygmt.src.histogram import histogram from pygmt.src.image import image from pygmt.src.info import info from pygmt.src.inset import inset @@ -31,6 +32,8 @@ from pygmt.src.subplot import set_panel, subplot from pygmt.src.surface import surface from pygmt.src.text import text_ as text # "text" is an argument within "text_" +from pygmt.src.velo import velo from pygmt.src.which import which +from pygmt.src.wiggle import wiggle from pygmt.src.x2sys_cross import x2sys_cross from pygmt.src.x2sys_init import x2sys_init diff --git a/pygmt/src/coast.py b/pygmt/src/coast.py index 6155651cc68..f3e1b70c343 100644 --- a/pygmt/src/coast.py +++ b/pygmt/src/coast.py @@ -85,7 +85,7 @@ def coast(self, **kwargs): (**h**\ )igh, (**i**\ )ntermediate, (**l**\ )ow, and (**c**\ )rude. land : str - Select filling or clipping of “dry” areas. + Select filling or clipping of "dry" areas. rivers : int or str or list *river*\ [/*pen*]. Draw rivers. Specify the type of rivers and [optionally] append @@ -151,7 +151,7 @@ def coast(self, **kwargs): a = All boundaries (1-3) water : str - Select filling or clipping of “wet” areas. + Select filling or clipping of "wet" areas. {U} shorelines : int or str or list [*level*\ /]\ *pen*. diff --git a/pygmt/src/grdtrack.py b/pygmt/src/grdtrack.py index f67cc842ba7..366506a5922 100644 --- a/pygmt/src/grdtrack.py +++ b/pygmt/src/grdtrack.py @@ -8,7 +8,6 @@ GMTTempFile, build_arg_string, data_kind, - dummy_context, fmt_docstring, use_alias, ) @@ -26,7 +25,7 @@ def grdtrack(points, grid, newcolname=None, outfile=None, **kwargs): table with the interpolated values added as (one or more) new columns. A bicubic [Default], bilinear, B-spline or nearest-neighbor interpolation is used, requiring boundary conditions at the limits of the region (see - ``interpolation``; Default uses “natural” conditions (second partial + ``interpolation``; Default uses "natural" conditions (second partial derivative normal to edge is zero) unless the grid is automatically recognized as periodic.) @@ -51,8 +50,7 @@ def grdtrack(points, grid, newcolname=None, outfile=None, **kwargs): sampled values will be placed. outfile : str - Required if ``points`` is a file. The file name for the output ASCII - file. + The file name for the output ASCII file. {V} {f} @@ -68,21 +66,13 @@ def grdtrack(points, grid, newcolname=None, outfile=None, **kwargs): - None if ``outfile`` is set (track output will be stored in file set by ``outfile``) """ + if data_kind(points) == "matrix" and newcolname is None: + raise GMTInvalidInput("Please pass in a str to 'newcolname'") with GMTTempFile(suffix=".csv") as tmpfile: with Session() as lib: - # Store the pandas.DataFrame points table in virtualfile - if data_kind(points) == "matrix": - if newcolname is None: - raise GMTInvalidInput("Please pass in a str to 'newcolname'") - table_context = lib.virtualfile_from_matrix(points.values) - elif data_kind(points) == "file": - if outfile is None: - raise GMTInvalidInput("Please pass in a str to 'outfile'") - table_context = dummy_context(points) - else: - raise GMTInvalidInput(f"Unrecognized data type {type(points)}") - + # Choose how data will be passed into the module + table_context = lib.virtualfile_from_data(check_kind="vector", data=points) # Store the xarray.DataArray grid in virtualfile grid_context = lib.virtualfile_from_data(check_kind="raster", data=grid) @@ -100,8 +90,11 @@ def grdtrack(points, grid, newcolname=None, outfile=None, **kwargs): # Read temporary csv output to a pandas table if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame - column_names = points.columns.to_list() + [newcolname] - result = pd.read_csv(tmpfile.name, sep="\t", names=column_names) + try: + column_names = points.columns.to_list() + [newcolname] + result = pd.read_csv(tmpfile.name, sep="\t", names=column_names) + except AttributeError: # 'str' object has no attribute 'columns' + result = pd.read_csv(tmpfile.name, sep="\t", header=None, comment=">") elif outfile != tmpfile.name: # return None if outfile set, output in outfile result = None diff --git a/pygmt/src/histogram.py b/pygmt/src/histogram.py new file mode 100644 index 00000000000..3759a27061e --- /dev/null +++ b/pygmt/src/histogram.py @@ -0,0 +1,59 @@ +""" +Histogram - Create a histogram +""" +from pygmt.clib import Session +from pygmt.helpers import build_arg_string, fmt_docstring, kwargs_to_strings, use_alias + + +@fmt_docstring +@use_alias( + A="horizontal", + B="frame", + C="cmap", + G="fill", + J="projection", + R="region", + T="series", + W="pen", + c="panel", + l="label", + p="perspective", +) +@kwargs_to_strings(R="sequence", T="sequence") +def histogram(self, table, **kwargs): + r""" + Plots a histogram, and can read data from a file or + list, array, or dataframe. + + Full option list at :gmt-docs:`histogram.html` + + {aliases} + + Parameters + ---------- + table : str, list, or 1d array + A data file name, list, or 1d numpy array. This is a required argument. + {J} + {R} + {B} + {CPT} + {G} + {W} + {c} + label : str + Add a legend entry for the symbol or line being plotted. + {p} + horizontal : bool + Plot the histogram using horizonal bars instead of the + default vertical bars. + series : int or str or list + [*min*\ /*max*\ /]\ *inc*\ [**+n**\ ] + Set the interval for the width of each bar in the histogram. + + """ + kwargs = self._preprocess(**kwargs) # pylint: disable=protected-access + with Session() as lib: + file_context = lib.virtualfile_from_data(check_kind="vector", data=table) + with file_context as infile: + arg_str = " ".join([infile, build_arg_string(kwargs)]) + lib.call_module("histogram", arg_str) diff --git a/pygmt/src/meca.py b/pygmt/src/meca.py index e73f95b35ea..cde18474165 100644 --- a/pygmt/src/meca.py +++ b/pygmt/src/meca.py @@ -98,8 +98,8 @@ def data_format_code(convention, component="full"): @use_alias( R="region", J="projection", + A="offset", B="frame", - C="offset", N="no_clip", V="verbose", X="xshift", @@ -334,8 +334,8 @@ def update_pointers(data_pointers): if arg is None: spec.append(0) else: - if "C" not in kwargs: - kwargs["C"] = True + if "A" not in kwargs: + kwargs["A"] = True spec.append(arg) # or assemble the 2D array for the case of lists as values @@ -389,8 +389,8 @@ def update_pointers(data_pointers): if arg is None: row.append(0) else: - if "C" not in kwargs: - kwargs["C"] = True + if "A" not in kwargs: + kwargs["A"] = True row.append(arg[index]) spec_array.append(row) spec = spec_array @@ -435,8 +435,8 @@ def update_pointers(data_pointers): if arg is None: row.append(0) else: - if "C" not in kwargs: - kwargs["C"] = True + if "A" not in kwargs: + kwargs["A"] = True row.append(arg[index]) spec_array.append(row) spec = spec_array diff --git a/pygmt/src/plot.py b/pygmt/src/plot.py index f3be49b598b..deac3f833ae 100644 --- a/pygmt/src/plot.py +++ b/pygmt/src/plot.py @@ -6,6 +6,7 @@ from pygmt.helpers import ( build_arg_string, data_kind, + deprecate_parameter, fmt_docstring, is_nonstr_iter, kwargs_to_strings, @@ -43,7 +44,8 @@ t="transparency", ) @kwargs_to_strings(R="sequence", c="sequence_comma", i="sequence_comma", p="sequence") -def plot(self, x=None, y=None, data=None, sizes=None, direction=None, **kwargs): +@deprecate_parameter("sizes", "size", "v0.4.0", remove_version="v0.6.0") +def plot(self, x=None, y=None, data=None, size=None, direction=None, **kwargs): r""" Plot lines, polygons, and symbols in 2-D. @@ -78,8 +80,8 @@ def plot(self, x=None, y=None, data=None, sizes=None, direction=None, **kwargs): Either a data file name or a 2d numpy array with the tabular data. Use parameter ``columns`` to choose which columns are x, y, color, and size, respectively. - sizes : 1d array - The sizes of the data points in units specified using ``style``. + size : 1d array + The size of the data points in units specified using ``style``. Only valid if using ``x``/``y``. direction : list of two 1d arrays If plotting vectors (using ``style='V'`` or ``style='v'``), then @@ -144,6 +146,8 @@ def plot(self, x=None, y=None, data=None, sizes=None, direction=None, **kwargs): the coordinates of a *refpoint* which will serve as a fixed external reference point for all groups. {G} + *color* can be a 1d array, but it is only valid if using ``x``/``y`` + and ``cmap=True`` is also required. intensity : float or bool or 1d array Provide an *intensity* value (nominally in the -1 to +1 range) to modulate the fill color by simulating illumination. If using @@ -215,12 +219,12 @@ def plot(self, x=None, y=None, data=None, sizes=None, direction=None, **kwargs): ) extra_arrays.append(kwargs["G"]) del kwargs["G"] - if sizes is not None: + if size is not None: if kind != "vectors": raise GMTInvalidInput( - "Can't use arrays for sizes if data is matrix or file." + "Can't use arrays for 'size' if data is a matrix or file." ) - extra_arrays.append(sizes) + extra_arrays.append(size) for flag in ["I", "t"]: if flag in kwargs and is_nonstr_iter(kwargs[flag]): diff --git a/pygmt/src/plot3d.py b/pygmt/src/plot3d.py index 85b4826cae4..42687165787 100644 --- a/pygmt/src/plot3d.py +++ b/pygmt/src/plot3d.py @@ -6,6 +6,7 @@ from pygmt.helpers import ( build_arg_string, data_kind, + deprecate_parameter, fmt_docstring, is_nonstr_iter, kwargs_to_strings, @@ -43,8 +44,9 @@ t="transparency", ) @kwargs_to_strings(R="sequence", c="sequence_comma", i="sequence_comma", p="sequence") +@deprecate_parameter("sizes", "size", "v0.4.0", remove_version="v0.6.0") def plot3d( - self, x=None, y=None, z=None, data=None, sizes=None, direction=None, **kwargs + self, x=None, y=None, z=None, data=None, size=None, direction=None, **kwargs ): r""" Plot lines, polygons, and symbols in 3-D. @@ -80,8 +82,8 @@ def plot3d( Either a data file name or a 2d numpy array with the tabular data. Use parameter ``columns`` to choose which columns are x, y, z, color, and size, respectively. - sizes : 1d array - The sizes of the data points in units specified in ``style``. + size : 1d array + The size of the data points in units specified in ``style``. Only valid if using ``x``/``y``/``z``. direction : list of two 1d arrays If plotting vectors (using ``style='V'`` or ``style='v'``), then @@ -111,6 +113,8 @@ def plot3d( Offset the plot symbol or line locations by the given amounts *dx*/*dy*\ [/*dz*] [Default is no offset]. {G} + *color* can be a 1d array, but it is only valid if using ``x``/``y`` + and ``cmap=True`` is also required. intensity : float or bool or 1d array Provide an *intensity* value (nominally in the -1 to +1 range) to modulate the fill color by simulating illumination. If using @@ -179,12 +183,12 @@ def plot3d( ) extra_arrays.append(kwargs["G"]) del kwargs["G"] - if sizes is not None: + if size is not None: if kind != "vectors": raise GMTInvalidInput( - "Can't use arrays for sizes if data is matrix or file." + "Can't use arrays for 'size' if data is a matrix or a file." ) - extra_arrays.append(sizes) + extra_arrays.append(size) for flag in ["I", "t"]: if flag in kwargs and is_nonstr_iter(kwargs[flag]): diff --git a/pygmt/src/subplot.py b/pygmt/src/subplot.py index fdf11856bf1..1e713afb189 100644 --- a/pygmt/src/subplot.py +++ b/pygmt/src/subplot.py @@ -22,7 +22,7 @@ A="autolabel", B="frame", C="clearance", - J="projecton", + J="projection", M="margins", R="region", SC="sharex", @@ -148,8 +148,9 @@ def subplot(self, nrows=1, ncols=1, **kwargs): {XY} """ kwargs = self._preprocess(**kwargs) # pylint: disable=protected-access - # allow for spaces in string with needing double quotes - kwargs["A"] = f'"{kwargs.get("A")}"' if kwargs.get("A") is not None else None + # allow for spaces in string without needing double quotes + if isinstance(kwargs.get("A"), str): + kwargs["A"] = f'"{kwargs.get("A")}"' kwargs["T"] = f'"{kwargs.get("T")}"' if kwargs.get("T") else None if nrows < 1 or ncols < 1: diff --git a/pygmt/src/text.py b/pygmt/src/text.py index 4c7b5421410..9db7d35bac4 100644 --- a/pygmt/src/text.py +++ b/pygmt/src/text.py @@ -177,13 +177,23 @@ def text_( ) ): kwargs.update({"F": ""}) - if angle is not None and isinstance(angle, (int, float, str)): + + if angle is True: + kwargs["F"] += "+a" + elif isinstance(angle, (int, float, str)): kwargs["F"] += f"+a{str(angle)}" - if font is not None and isinstance(font, str): + + if font is True: + kwargs["F"] += "+f" + elif isinstance(font, str): kwargs["F"] += f"+f{font}" - if justify is not None and isinstance(justify, str): + + if justify is True: + kwargs["F"] += "+j" + elif isinstance(justify, str): kwargs["F"] += f"+j{justify}" - if position is not None and isinstance(position, str): + + if isinstance(position, str): kwargs["F"] += f'+c{position}+t"{text}"' extra_arrays = [] diff --git a/pygmt/src/velo.py b/pygmt/src/velo.py new file mode 100644 index 00000000000..5db2544e83b --- /dev/null +++ b/pygmt/src/velo.py @@ -0,0 +1,247 @@ +""" +velo - Plot velocity vectors, crosses, anisotropy bars, and wedges. +""" +import numpy as np +import pandas as pd +from pygmt.clib import Session +from pygmt.exceptions import GMTInvalidInput +from pygmt.helpers import build_arg_string, fmt_docstring, kwargs_to_strings, use_alias + + +@fmt_docstring +@use_alias( + A="vector", + B="frame", + C="cmap", + D="rescale", + E="uncertaintycolor", + G="color", + H="scale", + I="shading", + J="projection", + L="line", + N="no_clip", + R="region", + S="spec", + U="timestamp", + V="verbose", + W="pen", + X="xshift", + Y="yshift", + Z="zvalue", + c="panel", + p="perspective", + t="transparency", +) +@kwargs_to_strings(R="sequence", c="sequence_comma", i="sequence_comma", p="sequence") +def velo(self, data=None, **kwargs): + r""" + Plot velocity vectors, crosses, anisotropy bars, and wedges. + + Reads data values from files, :class:`numpy.ndarray` or + :class:`pandas.DataFrame` and plots the selected geodesy symbol on a map. + You may choose from velocity vectors and their uncertainties, rotational + wedges and their uncertainties, anisotropy bars, or strain crosses. Symbol + fills or their outlines may be colored based on constant parameters or via + color lookup tables. + + Must provide ``data`` and ``spec``. + + Full option list at :gmt-docs:`supplements/geodesy/velo.html` + + {aliases} + + Parameters + ---------- + data : str or numpy.ndarray or pandas.DataFrame + Either a file name, a 2D :class:`numpy.ndarray` or a + :class:`pandas.DataFrame` with the tabular data. Note that text columns + are only supported with file or pandas DataFrame inputs. + + spec: str + Selects the meaning of the columns in the data file and the figure to + be plotted. In all cases, the scales are in data units per length unit + and sizes are in length units (default length unit is controlled by + :gmt-term:`PROJ_LENGTH_UNIT` unless **c**, **i**, or **p** is + appended). + + - **e**\ [*velscale*/]\ *confidence*\ [**+f**\ *font*] + + Velocity ellipses in (N,E) convention. The *velscale* sets the + scaling of the velocity arrows. If *velscale* is not given then we + read it from the data file as an extra column. The *confidence* sets + the 2-dimensional confidence limit for the ellipse, e.g. 0.95 for 95% + confidence ellipse. Use **+f** to set the font and size of the text + [Default is 9p,Helvetica,black]; give **+f**\ 0 to deactivate + labeling. The arrow will be drawn with the pen attributes specified + by the ``pen`` option and the arrow-head can be colored via + ``color``. The ellipse will be filled with the color or shade + specified by the ``uncertaintycolor`` option [Default is + transparent], and its outline will be drawn if ``line`` is selected + using the pen selected (by ``pen`` if not given by ``line``). + Parameters are expected to be in the following columns: + + - **1**,\ **2**: longitude, latitude of station + - **3**,\ **4**: eastward, northward velocity + - **5**,\ **6**: uncertainty of eastward, northward velocities + (1-sigma) + - **7**: correlation between eastward and northward components + - **Trailing text**: name of station (optional) + + - **n**\ [*barscale*] + + Anisotropy bars. *barscale* sets the scaling of the bars. If + *barscale* is not given then we read it from the data file as an + extra column. Parameters are expected to be in the following columns: + + - **1**,\ **2**: longitude, latitude of station + - **3**,\ **4**: eastward, northward components of anisotropy + vector + + - **r**\ [*velscale*/]\ *confidence*\ [**+f**\ *font*] + + Velocity ellipses in rotated convention. The *velscale* sets the + scaling of the velocity arrows. If *velscale* is not given then we + read it from the data file as an extra column. The *confidence* sets + the 2-dimensional confidence limit for the ellipse, e.g. 0.95 for 95% + confidence ellipse. Use **+f** to set the font and size of the text + [Default is 9p,Helvetica,black]; give **+f**\ 0 to deactivate + labeling. The arrow will be drawn with the pen attributes specified + by the ``pen`` option and the arrow-head can be colored via + ``color``. The ellipse will be filled with the color or shade + specified by the ``uncertaintycolor`` option [Default is + transparent], and its outline will be drawn if ``line`` is selected + using the pen selected (by ``pen`` if not given by ``line``). + Parameters are expected to be in the following columns: + + - **1**,\ **2**: longitude, latitude of station + - **3**,\ **4**: eastward, northward velocity + - **5**,\ **6**: semi-major, semi-minor axes + - **7**: counter-clockwise angle, in degrees, from horizontal axis + to major axis of ellipse. + - **Trailing text**: name of station (optional) + + - **w**\ [*wedgescale*/]\ *wedgemag* + + Rotational wedges. The *wedgescale* sets the size of the wedges. If + *wedgescale* is not given then we read it from the data file as an + extra column. Rotation values are multiplied by *wedgemag* before + plotting. For example, setting *wedgemag* to 1.e7 works well for + rotations of the order of 100 nanoradians/yr. Use ``color`` to set + the fill color or shade for the wedge, and ``uncertaintycolor`` to + set the color or shade for the uncertainty. Parameters are expected + to be in the following columns: + + - **1**,\ **2**: longitude, latitude of station + - **3**: rotation in radians + - **4**: rotation uncertainty in radians + + - **x**\ [*cross_scale*] + + Strain crosses. The *cross_scale* sets the size of the cross. If + *cross_scale* is not given then we read it from the data file as an + extra column. Parameters are expected to be in the following columns: + + - **1**,\ **2**: longitude, latitude of station + - **3**: eps1, the most extensional eigenvalue of strain tensor, + with extension taken positive. + - **4**: eps2, the most compressional eigenvalue of strain tensor, + with extension taken positive. + - **5**: azimuth of eps2 in degrees CW from North. + + {J} + {R} + vector : bool or str + Modify vector parameters. For vector heads, append vector head *size* + [Default is 9p]. See + :gmt-docs:`supplements/geodesy/velo.html#vector-attributes` for + specifying additional attributes. + {B} + {CPT} + rescale : str + can be used to rescale the uncertainties of velocities (``spec='e'`` + and ``spec='r'``) and rotations (``spec='w'``). Can be combined with + the ``confidence`` variable. + uncertaintycolor : str + Sets the color or shade used for filling uncertainty wedges + (``spec='w'``) or velocity error ellipses (``spec='e'`` or + ``spec='r'``). If ``uncertaintycolor`` is not specified, the + uncertainty regions will be transparent. **Note**: Using ``cmap`` and + ``zvalue='+e'`` will update the uncertainty fill color based on the + selected measure in ``zvalue`` [magnitude error]. More details at + :gmt-docs:`cookbook/features.html#gfill-attrib`. + color : str + Select color or pattern for filling of symbols [Default is no fill]. + **Note**: Using ``cmap`` (and optionally ``zvalue``) will update the + symbol fill color based on the selected measure in ``zvalue`` + [magnitude]. More details at + :gmt-docs:`cookbook/features.html#gfill-attrib`. + scale : float or bool + [*scale*]. + Scale symbol sizes and pen widths on a per-record basis using the + *scale* read from the data set, given as the first column after the + (optional) *z* and *size* columns [Default is no scaling]. The symbol + size is either provided by ``spec`` or via the input *size* column. + Alternatively, append a constant *scale* that should be used instead of + reading a scale column. + shading : float or bool + *intens*. + Use the supplied *intens* value (nominally in the -1 to +1 range) to + modulate the symbol fill color by simulating illumination [Default is + none]. If *intens* is not provided we will instead read the intensity + from an extra data column after the required input columns determined + by ``spec``. + line: str + [*pen*\ [**+c**\ [**f**\|\ **l**]]]. + Draw lines. Ellipses and rotational wedges will have their outlines + drawn using the current pen (see ``pen``). Alternatively, append a + separate pen to use for the error outlines. If the modifier **+cl** is + appended then the color of the pen is updated from the CPT (see + ``cmap``). If instead modifier **+cf** is appended then the color from + the cpt file is applied to error fill only [Default]. Use just **+c** + to set both pen and fill color. + no_clip: bool or str + Do NOT skip symbols that fall outside the frame boundary specified + by ``region``. [Default plots symbols inside frame only]. + {U} + {V} + pen : str + [*pen*][**+c**\ [**f**\|\ **l**]]. + Set pen attributes for velocity arrows, ellipse circumference and fault + plane edges. [Defaults: width = default, color = black, style = solid]. + If the modifier **+cl** is appended then the color of the pen is + updated from the CPT (see ``cmap``). If instead modifier **+cf** is + appended then the color from the cpt file is applied to symbol fill + only [Default]. Use just **+c** to set both pen and fill color. + {XY} + zvalue : str + [**m**\|\ **e**\|\ **n**\|\ **u**\ ][**+e**]. + Select the quantity that will be used with the CPT given via ``cmap`` + to set the fill color. Choose from **m**\ agnitude (vector magnitude + or rotation magnitude), **e**\ ast-west velocity, **n**\ orth-south + velocity, or **u**\ ser-supplied data column (supplied after the + required columns). To instead use the corresponding error estimates + (i.e., vector or rotation uncertainty) to lookup the color and paint + the error ellipse or wedge instead, append **+e**. + {c} + {p} + {t} + """ + kwargs = self._preprocess(**kwargs) # pylint: disable=protected-access + + if "S" not in kwargs or ("S" in kwargs and not isinstance(kwargs["S"], str)): + raise GMTInvalidInput("Spec is a required argument and has to be a string.") + + if isinstance(data, np.ndarray) and not pd.api.types.is_numeric_dtype(data): + raise GMTInvalidInput( + "Text columns are not supported with numpy.ndarray type inputs. " + "They are only supported with file or pandas.DataFrame inputs." + ) + + with Session() as lib: + # Choose how data will be passed in to the module + file_context = lib.virtualfile_from_data(check_kind="vector", data=data) + + with file_context as fname: + arg_str = " ".join([fname, build_arg_string(kwargs)]) + lib.call_module("velo", arg_str) diff --git a/pygmt/src/wiggle.py b/pygmt/src/wiggle.py new file mode 100644 index 00000000000..2e3235e9b64 --- /dev/null +++ b/pygmt/src/wiggle.py @@ -0,0 +1,95 @@ +""" +wiggle - Plot z=f(x,y) anomalies along tracks. +""" +from pygmt.clib import Session +from pygmt.helpers import build_arg_string, fmt_docstring, kwargs_to_strings, use_alias + + +@fmt_docstring +@use_alias( + B="frame", + D="position", + G="color", + J="projection", + R="region", + T="track", + U="timestamp", + V="verbose", + W="pen", + X="xshift", + Y="yshift", + Z="scale", + c="panel", + i="columns", + p="perspective", +) +@kwargs_to_strings(R="sequence", c="sequence_comma", i="sequence_comma", p="sequence") +def wiggle(self, x=None, y=None, z=None, data=None, **kwargs): + r""" + Plot z=f(x,y) anomalies along tracks. + + Takes a matrix, (x,y,z) triplets, or a file name as input and plots z as a + function of distance along track. + + Must provide either ``data`` or ``x``/``y``/``z``. + + Full parameter list at :gmt-docs:`wiggle.html` + + {aliases} + + Parameters + ---------- + x/y/z : 1d arrays + The arrays of x and y coordinates and z data points. + data : str or 2d array + Either a data file name or a 2d numpy array with the tabular data. + Use parameter ``columns`` to choose which columns are x, y, z, + respectively. + {J} + {R} + scale : str or float + Gives anomaly scale in data-units/distance-unit. Append **c**, **i**, + or **p** to indicate the distance unit (cm, inch, or point); if no unit + is given we use the default unit that is controlled by + :gmt-term:`PROJ_LENGTH_UNIT`. + {B} + position : str + [**g**\|\ **j**\|\ **J**\|\ **n**\|\ **x**]\ *refpoint*\ + **+w**\ *length*\ [**+j**\ *justify*]\ [**+al**\ |\ **r**]\ + [**+o**\ *dx*\ [/*dy*]][**+l**\ [*label*]]. + Defines the reference point on the map for the vertical scale bar. + color : str + Set fill shade, color or pattern for positive and/or negative wiggles + [Default is no fill]. Optionally, append **+p** to fill positive areas + (this is the default behavior). Append **+n** to fill negative areas. + Append **+n+p** to fill both positive and negative areas with the same + fill. Note: You will need to repeat the color parameter to select + different fills for the positive and negative wiggles. + + track : str + Draw track [Default is no track]. Append pen attributes to use + [Default is **0.25p,black,solid**]. + {U} + {V} + pen : str + Specify outline pen attributes [Default is no outline]. + {XY} + {c} + columns : str or 1d array + Choose which columns are x, y, and z, respectively if input is provided + via *data*. E.g. ``columns = [0, 1, 2]`` or ``columns = "0,1,2"`` if + the *x* values are stored in the first column, *y* values in the second + one and *z* values in the third one. Note: zero-based indexing is used. + {p} + """ + kwargs = self._preprocess(**kwargs) # pylint: disable=protected-access + + with Session() as lib: + # Choose how data will be passed in to the module + file_context = lib.virtualfile_from_data( + check_kind="vector", data=data, x=x, y=y, z=z + ) + + with file_context as fname: + arg_str = " ".join([fname, build_arg_string(kwargs)]) + lib.call_module("wiggle", arg_str) diff --git a/pygmt/tests/baseline/test_basemap.png.dvc b/pygmt/tests/baseline/test_basemap.png.dvc index a2b69e9f802..b59133e7071 100644 --- a/pygmt/tests/baseline/test_basemap.png.dvc +++ b/pygmt/tests/baseline/test_basemap.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 61986bbf1ea20c418cbce50456d1d4f7 - size: 9281 +- md5: 3cf01816fa5dd3fbc1adc602557bb032 + size: 6187 path: test_basemap.png diff --git a/pygmt/tests/baseline/test_basemap_compass.png.dvc b/pygmt/tests/baseline/test_basemap_compass.png.dvc index 13c48fad715..f67e592a2c8 100644 --- a/pygmt/tests/baseline/test_basemap_compass.png.dvc +++ b/pygmt/tests/baseline/test_basemap_compass.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 5ecccc4123b28636b62e01f642006ae4 - size: 90778 +- md5: 77dc6e9b11b2fa1cf79c7de525704fca + size: 76593 path: test_basemap_compass.png diff --git a/pygmt/tests/baseline/test_basemap_loglog.png.dvc b/pygmt/tests/baseline/test_basemap_loglog.png.dvc index f828504dc4f..115ee699591 100644 --- a/pygmt/tests/baseline/test_basemap_loglog.png.dvc +++ b/pygmt/tests/baseline/test_basemap_loglog.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 04df0757105b810a647f545f4f7371fb - size: 28235 +- md5: 37c36d4fa4524260ea43c6757a3140a1 + size: 24475 path: test_basemap_loglog.png diff --git a/pygmt/tests/baseline/test_basemap_map_scale.png.dvc b/pygmt/tests/baseline/test_basemap_map_scale.png.dvc index b952b792c59..ad000a365ea 100644 --- a/pygmt/tests/baseline/test_basemap_map_scale.png.dvc +++ b/pygmt/tests/baseline/test_basemap_map_scale.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: f1ff6ede343ce3d2fc42cbe9ef0ba96b - size: 40128 +- md5: e88925c5053369eb516757ec963d691d + size: 31044 path: test_basemap_map_scale.png diff --git a/pygmt/tests/baseline/test_basemap_power_axis.png.dvc b/pygmt/tests/baseline/test_basemap_power_axis.png.dvc index 534ae1df77d..6b08bfc89a9 100644 --- a/pygmt/tests/baseline/test_basemap_power_axis.png.dvc +++ b/pygmt/tests/baseline/test_basemap_power_axis.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 6d9dd0086ab8226f180c6aae5ec3e4a6 - size: 31288 +- md5: d42769c9b2a802788ac3b3fd0c193c26 + size: 16446 path: test_basemap_power_axis.png diff --git a/pygmt/tests/baseline/test_basemap_rose.png.dvc b/pygmt/tests/baseline/test_basemap_rose.png.dvc index 886802038dc..335502b2345 100644 --- a/pygmt/tests/baseline/test_basemap_rose.png.dvc +++ b/pygmt/tests/baseline/test_basemap_rose.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: ede2912205feff80db261b54ff8d5bec - size: 41421 +- md5: 50267f9329529a279a1846185b78f0ef + size: 32476 path: test_basemap_rose.png diff --git a/pygmt/tests/baseline/test_basemap_winkel_tripel.png.dvc b/pygmt/tests/baseline/test_basemap_winkel_tripel.png.dvc index da1060955f1..442bc6f1c49 100644 --- a/pygmt/tests/baseline/test_basemap_winkel_tripel.png.dvc +++ b/pygmt/tests/baseline/test_basemap_winkel_tripel.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: d0d2c680e9e6e1b546566d9aa2aaf830 - size: 70487 +- md5: b32f987475dee83c219df916a7ffb687 + size: 62786 path: test_basemap_winkel_tripel.png diff --git a/pygmt/tests/baseline/test_coast_dcw_list.png.dvc b/pygmt/tests/baseline/test_coast_dcw_list.png.dvc index 28c7e8d07b3..2aeef5d7875 100644 --- a/pygmt/tests/baseline/test_coast_dcw_list.png.dvc +++ b/pygmt/tests/baseline/test_coast_dcw_list.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 30c3f4c90ba740b7d9edae97d9d3b853 - size: 93411 +- md5: f2b5e260c880ee65c1da003715a48985 + size: 89438 path: test_coast_dcw_list.png diff --git a/pygmt/tests/baseline/test_coast_dcw_single.png.dvc b/pygmt/tests/baseline/test_coast_dcw_single.png.dvc index 38a0b2b1a5d..713e151367c 100644 --- a/pygmt/tests/baseline/test_coast_dcw_single.png.dvc +++ b/pygmt/tests/baseline/test_coast_dcw_single.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 40fcf70e1f73ba2be60cbf9e3f15794d - size: 83794 +- md5: 4ac010bb7791c4d972fdf7d22deef73f + size: 79609 path: test_coast_dcw_single.png diff --git a/pygmt/tests/baseline/test_coast_region.png.dvc b/pygmt/tests/baseline/test_coast_region.png.dvc index 1caeef93884..3f81279e64a 100644 --- a/pygmt/tests/baseline/test_coast_region.png.dvc +++ b/pygmt/tests/baseline/test_coast_region.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 6aecb1529eb8c9535a392f918fc30c38 - size: 82728 +- md5: 211a3f5d1a3f84db2ca592f501d9066b + size: 77711 path: test_coast_region.png diff --git a/pygmt/tests/baseline/test_coast_world_mercator.png.dvc b/pygmt/tests/baseline/test_coast_world_mercator.png.dvc index 7d363abe813..20eb24b5237 100644 --- a/pygmt/tests/baseline/test_coast_world_mercator.png.dvc +++ b/pygmt/tests/baseline/test_coast_world_mercator.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 6da57e19a2de4ca60299094139ea6cb0 - size: 119081 +- md5: 2b78b937f6d799908bd9425b332d2244 + size: 114193 path: test_coast_world_mercator.png diff --git a/pygmt/tests/baseline/test_colorbar_box.png b/pygmt/tests/baseline/test_colorbar_box.png deleted file mode 100644 index 895ac1031f7..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_box.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_box.png.dvc b/pygmt/tests/baseline/test_colorbar_box.png.dvc new file mode 100644 index 00000000000..790404fe32e --- /dev/null +++ b/pygmt/tests/baseline/test_colorbar_box.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 5bd7bba7139b23c1c63dd7ed053a5b88 + size: 1388 + path: test_colorbar_box.png diff --git a/pygmt/tests/baseline/test_colorbar_box_with_clearance.png b/pygmt/tests/baseline/test_colorbar_box_with_clearance.png deleted file mode 100644 index 1511a8d7231..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_box_with_clearance.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_box_with_fill.png b/pygmt/tests/baseline/test_colorbar_box_with_fill.png deleted file mode 100644 index 3c52057604c..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_box_with_fill.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_box_with_fill.png.dvc b/pygmt/tests/baseline/test_colorbar_box_with_fill.png.dvc new file mode 100644 index 00000000000..ac6a259686b --- /dev/null +++ b/pygmt/tests/baseline/test_colorbar_box_with_fill.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 92aeb730de6db02fb2cf488f37d799cc + size: 1394 + path: test_colorbar_box_with_fill.png diff --git a/pygmt/tests/baseline/test_colorbar_box_with_offset_background.png b/pygmt/tests/baseline/test_colorbar_box_with_offset_background.png deleted file mode 100644 index 273540f0c79..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_box_with_offset_background.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_box_with_pen.png b/pygmt/tests/baseline/test_colorbar_box_with_pen.png deleted file mode 100644 index 3ca2b1855c5..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_box_with_pen.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_box_with_rounded_corners.png b/pygmt/tests/baseline/test_colorbar_box_with_rounded_corners.png deleted file mode 100644 index 88cef9fd49e..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_box_with_rounded_corners.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_box_with_secondary_border.png b/pygmt/tests/baseline/test_colorbar_box_with_secondary_border.png deleted file mode 100644 index 7e88ab113b4..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_box_with_secondary_border.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_positioned_using_justification_code.png b/pygmt/tests/baseline/test_colorbar_positioned_using_justification_code.png deleted file mode 100644 index 7f26712d622..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_positioned_using_justification_code.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_positioned_using_map_coordinates.png b/pygmt/tests/baseline/test_colorbar_positioned_using_map_coordinates.png deleted file mode 100644 index b7ccbfb9f3b..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_positioned_using_map_coordinates.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_positioned_using_normalized_coords.png b/pygmt/tests/baseline/test_colorbar_positioned_using_normalized_coords.png deleted file mode 100644 index efcc94dfbbc..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_positioned_using_normalized_coords.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_scaled_z_values.png b/pygmt/tests/baseline/test_colorbar_scaled_z_values.png deleted file mode 100644 index 7fc3170c818..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_scaled_z_values.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_scaled_z_values.png.dvc b/pygmt/tests/baseline/test_colorbar_scaled_z_values.png.dvc new file mode 100644 index 00000000000..ac071994083 --- /dev/null +++ b/pygmt/tests/baseline/test_colorbar_scaled_z_values.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: e337c879b0db02a0ea5312d306ce7a32 + size: 1826 + path: test_colorbar_scaled_z_values.png diff --git a/pygmt/tests/baseline/test_colorbar_shading_boolean.png.dvc b/pygmt/tests/baseline/test_colorbar_shading_boolean.png.dvc new file mode 100644 index 00000000000..734f1b4ffa2 --- /dev/null +++ b/pygmt/tests/baseline/test_colorbar_shading_boolean.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 4ee03ad49ec7264348e4d9c7d642bc37 + size: 51318 + path: test_colorbar_shading_boolean.png diff --git a/pygmt/tests/baseline/test_colorbar_shading_list.png.dvc b/pygmt/tests/baseline/test_colorbar_shading_list.png.dvc new file mode 100644 index 00000000000..565dbed17cc --- /dev/null +++ b/pygmt/tests/baseline/test_colorbar_shading_list.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 823a04eb5398f1b101cb7ebc4af006f1 + size: 56049 + path: test_colorbar_shading_list.png diff --git a/pygmt/tests/baseline/test_colorbar_truncated_to_zlow_zhigh.png b/pygmt/tests/baseline/test_colorbar_truncated_to_zlow_zhigh.png deleted file mode 100644 index 1a8f80a90c8..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_truncated_to_zlow_zhigh.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_truncated_to_zlow_zhigh.png.dvc b/pygmt/tests/baseline/test_colorbar_truncated_to_zlow_zhigh.png.dvc new file mode 100644 index 00000000000..84d61f7a7b1 --- /dev/null +++ b/pygmt/tests/baseline/test_colorbar_truncated_to_zlow_zhigh.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: e2f5d695f6f7a0d385a8d988e7ecdf37 + size: 2319 + path: test_colorbar_truncated_to_zlow_zhigh.png diff --git a/pygmt/tests/baseline/test_colorbar_using_paper_coordinates.png b/pygmt/tests/baseline/test_colorbar_using_paper_coordinates.png deleted file mode 100644 index f7f8b99d407..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_using_paper_coordinates.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_colorbar_using_paper_coordinates_horizontal.png b/pygmt/tests/baseline/test_colorbar_using_paper_coordinates_horizontal.png deleted file mode 100644 index dced4c597bc..00000000000 Binary files a/pygmt/tests/baseline/test_colorbar_using_paper_coordinates_horizontal.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_config.png b/pygmt/tests/baseline/test_config.png deleted file mode 100644 index d234eb2684c..00000000000 Binary files a/pygmt/tests/baseline/test_config.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_config.png.dvc b/pygmt/tests/baseline/test_config.png.dvc new file mode 100644 index 00000000000..a13600efec1 --- /dev/null +++ b/pygmt/tests/baseline/test_config.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 1f6d2bb449a5329d0208627dc293fd42 + size: 19614 + path: test_config.png diff --git a/pygmt/tests/baseline/test_config_font_annot.png.dvc b/pygmt/tests/baseline/test_config_font_annot.png.dvc new file mode 100644 index 00000000000..fe2b5b62b60 --- /dev/null +++ b/pygmt/tests/baseline/test_config_font_annot.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 5db66e9f22ef896d1689513026036ec1 + size: 69927 + path: test_config_font_annot.png diff --git a/pygmt/tests/baseline/test_config_font_one.png.dvc b/pygmt/tests/baseline/test_config_font_one.png.dvc new file mode 100644 index 00000000000..e602ac1e310 --- /dev/null +++ b/pygmt/tests/baseline/test_config_font_one.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 6969208b1b1852a0b08cd67263966fdc + size: 83228 + path: test_config_font_one.png diff --git a/pygmt/tests/baseline/test_config_format_time_map.png b/pygmt/tests/baseline/test_config_format_time_map.png deleted file mode 100644 index 0b96d80fdb4..00000000000 Binary files a/pygmt/tests/baseline/test_config_format_time_map.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_config_format_time_map.png.dvc b/pygmt/tests/baseline/test_config_format_time_map.png.dvc new file mode 100644 index 00000000000..5bc084480df --- /dev/null +++ b/pygmt/tests/baseline/test_config_format_time_map.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: d95be055306d25aa619e816a9a4b147e + size: 7550 + path: test_config_format_time_map.png diff --git a/pygmt/tests/baseline/test_config_map_annot_offset.png b/pygmt/tests/baseline/test_config_map_annot_offset.png deleted file mode 100644 index 71cb475d5af..00000000000 Binary files a/pygmt/tests/baseline/test_config_map_annot_offset.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_config_map_annot_offset.png.dvc b/pygmt/tests/baseline/test_config_map_annot_offset.png.dvc new file mode 100644 index 00000000000..73cb7b23fba --- /dev/null +++ b/pygmt/tests/baseline/test_config_map_annot_offset.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 9d9b668163b3d0118199a5bbca7a92b9 + size: 6858 + path: test_config_map_annot_offset.png diff --git a/pygmt/tests/baseline/test_config_map_grid_cross_size.png b/pygmt/tests/baseline/test_config_map_grid_cross_size.png deleted file mode 100644 index 2f4d1425721..00000000000 Binary files a/pygmt/tests/baseline/test_config_map_grid_cross_size.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_config_map_grid_cross_size.png.dvc b/pygmt/tests/baseline/test_config_map_grid_cross_size.png.dvc new file mode 100644 index 00000000000..e472243eda2 --- /dev/null +++ b/pygmt/tests/baseline/test_config_map_grid_cross_size.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: cd5aec2937c08cf7d94f80eb6894609a + size: 13246 + path: test_config_map_grid_cross_size.png diff --git a/pygmt/tests/baseline/test_config_map_grid_pen.png b/pygmt/tests/baseline/test_config_map_grid_pen.png deleted file mode 100644 index 31cd1d84bcd..00000000000 Binary files a/pygmt/tests/baseline/test_config_map_grid_pen.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_config_map_grid_pen.png.dvc b/pygmt/tests/baseline/test_config_map_grid_pen.png.dvc new file mode 100644 index 00000000000..ec8babcd439 --- /dev/null +++ b/pygmt/tests/baseline/test_config_map_grid_pen.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: eb591a3581ad0cc82ff08fd4aa763b8c + size: 13506 + path: test_config_map_grid_pen.png diff --git a/pygmt/tests/baseline/test_config_map_tick_length.png b/pygmt/tests/baseline/test_config_map_tick_length.png deleted file mode 100644 index 5a795cd646a..00000000000 Binary files a/pygmt/tests/baseline/test_config_map_tick_length.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_config_map_tick_length.png.dvc b/pygmt/tests/baseline/test_config_map_tick_length.png.dvc new file mode 100644 index 00000000000..3f54ddbb011 --- /dev/null +++ b/pygmt/tests/baseline/test_config_map_tick_length.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 2fdbc52afba87ecf8c434e4b62232455 + size: 12664 + path: test_config_map_tick_length.png diff --git a/pygmt/tests/baseline/test_config_map_tick_pen.png b/pygmt/tests/baseline/test_config_map_tick_pen.png deleted file mode 100644 index 305ee595f81..00000000000 Binary files a/pygmt/tests/baseline/test_config_map_tick_pen.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_config_map_tick_pen.png.dvc b/pygmt/tests/baseline/test_config_map_tick_pen.png.dvc new file mode 100644 index 00000000000..86b9ec7f9f6 --- /dev/null +++ b/pygmt/tests/baseline/test_config_map_tick_pen.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 380b4c6fb0245a393aeb76b5c1f6ee91 + size: 13085 + path: test_config_map_tick_pen.png diff --git a/pygmt/tests/baseline/test_contour_from_file.png.dvc b/pygmt/tests/baseline/test_contour_from_file.png.dvc index 31e63dc1965..d812ded2d22 100644 --- a/pygmt/tests/baseline/test_contour_from_file.png.dvc +++ b/pygmt/tests/baseline/test_contour_from_file.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 68c12988f1bb0dbc67da560fe4d51ea2 - size: 64936 +- md5: f8bd9e2347bf29bd2d47745d347dc643 + size: 60272 path: test_contour_from_file.png diff --git a/pygmt/tests/baseline/test_contour_matrix.png.dvc b/pygmt/tests/baseline/test_contour_matrix.png.dvc index 1f9e7976953..b6203821f64 100644 --- a/pygmt/tests/baseline/test_contour_matrix.png.dvc +++ b/pygmt/tests/baseline/test_contour_matrix.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 7a8e0d23ce325cef3be12da033ab2602 - size: 75839 +- md5: 41e82af65514b8a977c5b0ef56c3c923 + size: 74943 path: test_contour_matrix.png diff --git a/pygmt/tests/baseline/test_contour_vec.png.dvc b/pygmt/tests/baseline/test_contour_vec.png.dvc index 5c234915b32..ce91ed9af2f 100644 --- a/pygmt/tests/baseline/test_contour_vec.png.dvc +++ b/pygmt/tests/baseline/test_contour_vec.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 8bae58cc9d84de9ff9c30f3d45792dc5 - size: 87570 +- md5: 521386238fd3dd23bcaff147d7b4e0b7 + size: 82236 path: test_contour_vec.png diff --git a/pygmt/tests/baseline/test_figure_shift_origin.png.dvc b/pygmt/tests/baseline/test_figure_shift_origin.png.dvc index 9c12eaad58b..072b81d1f73 100644 --- a/pygmt/tests/baseline/test_figure_shift_origin.png.dvc +++ b/pygmt/tests/baseline/test_figure_shift_origin.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 07df92baab0051531f6c8023f4108332 - size: 9876 +- md5: 85e88836e6d32cded37f792de6439fb9 + size: 9896 path: test_figure_shift_origin.png diff --git a/pygmt/tests/baseline/test_grd2cpt.png.dvc b/pygmt/tests/baseline/test_grd2cpt.png.dvc new file mode 100644 index 00000000000..f55edee9848 --- /dev/null +++ b/pygmt/tests/baseline/test_grd2cpt.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 305e3650aa4ed9a56bec58be3a0d752b + size: 22460 + path: test_grd2cpt.png diff --git a/pygmt/tests/baseline/test_grdcontour.png b/pygmt/tests/baseline/test_grdcontour.png deleted file mode 100644 index f48340f9b91..00000000000 Binary files a/pygmt/tests/baseline/test_grdcontour.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_grdcontour.png.dvc b/pygmt/tests/baseline/test_grdcontour.png.dvc new file mode 100644 index 00000000000..dea1f734b46 --- /dev/null +++ b/pygmt/tests/baseline/test_grdcontour.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 9366e405a1be22b4c2515f24a3acae69 + size: 217638 + path: test_grdcontour.png diff --git a/pygmt/tests/baseline/test_grdcontour_file.png b/pygmt/tests/baseline/test_grdcontour_file.png deleted file mode 100644 index 444f1d1eba0..00000000000 Binary files a/pygmt/tests/baseline/test_grdcontour_file.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_grdcontour_file.png.dvc b/pygmt/tests/baseline/test_grdcontour_file.png.dvc new file mode 100644 index 00000000000..c044a33f0ac --- /dev/null +++ b/pygmt/tests/baseline/test_grdcontour_file.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 717b9f9123c7bb2bfb197a419d459288 + size: 97067 + path: test_grdcontour_file.png diff --git a/pygmt/tests/baseline/test_grdcontour_interval_file_full_opts.png b/pygmt/tests/baseline/test_grdcontour_interval_file_full_opts.png deleted file mode 100644 index 41bb07b6e21..00000000000 Binary files a/pygmt/tests/baseline/test_grdcontour_interval_file_full_opts.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_grdcontour_interval_file_full_opts.png.dvc b/pygmt/tests/baseline/test_grdcontour_interval_file_full_opts.png.dvc new file mode 100644 index 00000000000..f3e40cd1fe6 --- /dev/null +++ b/pygmt/tests/baseline/test_grdcontour_interval_file_full_opts.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 25125246f541652071fac1771e5d7e88 + size: 33966 + path: test_grdcontour_interval_file_full_opts.png diff --git a/pygmt/tests/baseline/test_grdcontour_labels.png b/pygmt/tests/baseline/test_grdcontour_labels.png deleted file mode 100644 index 7a0c9557ff4..00000000000 Binary files a/pygmt/tests/baseline/test_grdcontour_labels.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_grdcontour_labels.png.dvc b/pygmt/tests/baseline/test_grdcontour_labels.png.dvc new file mode 100644 index 00000000000..c7cd373037d --- /dev/null +++ b/pygmt/tests/baseline/test_grdcontour_labels.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 03a7cc6dea35f9383cbfb2683d7b7c1b + size: 223421 + path: test_grdcontour_labels.png diff --git a/pygmt/tests/baseline/test_grdcontour_slice.png b/pygmt/tests/baseline/test_grdcontour_slice.png deleted file mode 100644 index 427ce5a5f1f..00000000000 Binary files a/pygmt/tests/baseline/test_grdcontour_slice.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_grdcontour_slice.png.dvc b/pygmt/tests/baseline/test_grdcontour_slice.png.dvc new file mode 100644 index 00000000000..b28d837a160 --- /dev/null +++ b/pygmt/tests/baseline/test_grdcontour_slice.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 48070d23c538d26eb96b5caaf440513a + size: 97314 + path: test_grdcontour_slice.png diff --git a/pygmt/tests/baseline/test_grdimage.png b/pygmt/tests/baseline/test_grdimage.png deleted file mode 100644 index 7237245de06..00000000000 Binary files a/pygmt/tests/baseline/test_grdimage.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_grdimage.png.dvc b/pygmt/tests/baseline/test_grdimage.png.dvc new file mode 100644 index 00000000000..391496690a5 --- /dev/null +++ b/pygmt/tests/baseline/test_grdimage.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 1540b29b9469db19bd65abd479cabb30 + size: 172480 + path: test_grdimage.png diff --git a/pygmt/tests/baseline/test_grdimage_file.png b/pygmt/tests/baseline/test_grdimage_file.png deleted file mode 100644 index f4a719422fd..00000000000 Binary files a/pygmt/tests/baseline/test_grdimage_file.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_grdimage_file.png.dvc b/pygmt/tests/baseline/test_grdimage_file.png.dvc new file mode 100644 index 00000000000..3137f4a5428 --- /dev/null +++ b/pygmt/tests/baseline/test_grdimage_file.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 0f1c4cc2bc2207c32cc5fb04fd75fcb7 + size: 194595 + path: test_grdimage_file.png diff --git a/pygmt/tests/baseline/test_grdimage_over_dateline.png b/pygmt/tests/baseline/test_grdimage_over_dateline.png deleted file mode 100644 index 34b909c2beb..00000000000 Binary files a/pygmt/tests/baseline/test_grdimage_over_dateline.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_grdimage_over_dateline.png.dvc b/pygmt/tests/baseline/test_grdimage_over_dateline.png.dvc new file mode 100644 index 00000000000..88657c3b19e --- /dev/null +++ b/pygmt/tests/baseline/test_grdimage_over_dateline.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 9fde25c97659e17430eff8f6f66a9412 + size: 10988 + path: test_grdimage_over_dateline.png diff --git a/pygmt/tests/baseline/test_grdimage_slice.png b/pygmt/tests/baseline/test_grdimage_slice.png deleted file mode 100644 index 89f91e4ff6f..00000000000 Binary files a/pygmt/tests/baseline/test_grdimage_slice.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_grdimage_slice.png.dvc b/pygmt/tests/baseline/test_grdimage_slice.png.dvc new file mode 100644 index 00000000000..f320344c3a4 --- /dev/null +++ b/pygmt/tests/baseline/test_grdimage_slice.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: ea59acb8c1de63d6caba7df897c8f3ba + size: 67726 + path: test_grdimage_slice.png diff --git a/pygmt/tests/baseline/test_histogram.png.dvc b/pygmt/tests/baseline/test_histogram.png.dvc new file mode 100644 index 00000000000..33b740d0fb4 --- /dev/null +++ b/pygmt/tests/baseline/test_histogram.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 8499f1d0ef232ece53300c6aaf611607 + size: 10794 + path: test_histogram.png diff --git a/pygmt/tests/baseline/test_image.png.dvc b/pygmt/tests/baseline/test_image.png.dvc index 7fdec067301..e9bfe6e74e2 100644 --- a/pygmt/tests/baseline/test_image.png.dvc +++ b/pygmt/tests/baseline/test_image.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: de86468aa453b14912c8362c67e51064 - size: 10403 +- md5: 765c70d1a8ac23327329046a94f9a9d5 + size: 10014 path: test_image.png diff --git a/pygmt/tests/baseline/test_inset_aliases.png.dvc b/pygmt/tests/baseline/test_inset_aliases.png.dvc new file mode 100644 index 00000000000..1fd51109769 --- /dev/null +++ b/pygmt/tests/baseline/test_inset_aliases.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 62d6aec510780889e6f1d25a8c564ff0 + size: 29626 + path: test_inset_aliases.png diff --git a/pygmt/tests/baseline/test_inset_context_manager.png.dvc b/pygmt/tests/baseline/test_inset_context_manager.png.dvc new file mode 100644 index 00000000000..83530f16b5c --- /dev/null +++ b/pygmt/tests/baseline/test_inset_context_manager.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 43c2c1d0c58d4fd2b24d3ca059cc5e35 + size: 10477 + path: test_inset_context_manager.png diff --git a/pygmt/tests/baseline/test_legend_default_position.png b/pygmt/tests/baseline/test_legend_default_position.png deleted file mode 100644 index 67bd7f2adc2..00000000000 Binary files a/pygmt/tests/baseline/test_legend_default_position.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_legend_default_position.png.dvc b/pygmt/tests/baseline/test_legend_default_position.png.dvc new file mode 100644 index 00000000000..157ae4d0e6e --- /dev/null +++ b/pygmt/tests/baseline/test_legend_default_position.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: f62e18d2a678273594c3fc8e3ac0e4bd + size: 20380 + path: test_legend_default_position.png diff --git a/pygmt/tests/baseline/test_legend_entries.png.dvc b/pygmt/tests/baseline/test_legend_entries.png.dvc index 8d1ed261703..e3a34821ae5 100644 --- a/pygmt/tests/baseline/test_legend_entries.png.dvc +++ b/pygmt/tests/baseline/test_legend_entries.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 4d1ed417fd2625d0b2fa5c17dafd32fd - size: 73728 +- md5: fb617517ff07cd45eb26dda6e7b2eb23 + size: 68296 path: test_legend_entries.png diff --git a/pygmt/tests/baseline/test_legend_position.png b/pygmt/tests/baseline/test_legend_position.png deleted file mode 100644 index 403388e119a..00000000000 Binary files a/pygmt/tests/baseline/test_legend_position.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_legend_position.png.dvc b/pygmt/tests/baseline/test_legend_position.png.dvc new file mode 100644 index 00000000000..bcfddaedb99 --- /dev/null +++ b/pygmt/tests/baseline/test_legend_position.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 4306da978112fb27dde184d63ec440ee + size: 24826 + path: test_legend_position.png diff --git a/pygmt/tests/baseline/test_legend_specfile.png b/pygmt/tests/baseline/test_legend_specfile.png deleted file mode 100644 index 9541a119319..00000000000 Binary files a/pygmt/tests/baseline/test_legend_specfile.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_legend_specfile.png.dvc b/pygmt/tests/baseline/test_legend_specfile.png.dvc new file mode 100644 index 00000000000..323b349ceb8 --- /dev/null +++ b/pygmt/tests/baseline/test_legend_specfile.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 331f8fcdf2a864fb840ec48b865327bc + size: 52216 + path: test_legend_specfile.png diff --git a/pygmt/tests/baseline/test_logo.png.dvc b/pygmt/tests/baseline/test_logo.png.dvc index 152712be479..24eaf83a44b 100644 --- a/pygmt/tests/baseline/test_logo.png.dvc +++ b/pygmt/tests/baseline/test_logo.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 905d5b9f0f8d8b809899dfe9e87d0e91 - size: 33347 +- md5: 61be9b262729e0a6b739e814d1aa4655 + size: 32065 path: test_logo.png diff --git a/pygmt/tests/baseline/test_logo_on_a_map.png.dvc b/pygmt/tests/baseline/test_logo_on_a_map.png.dvc index 69db157d065..39528bdb41c 100644 --- a/pygmt/tests/baseline/test_logo_on_a_map.png.dvc +++ b/pygmt/tests/baseline/test_logo_on_a_map.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 409119aeeec2680d106e32527009c255 - size: 77366 +- md5: 57c3747cb7d2ed978e473d0f161ca3a6 + size: 70993 path: test_logo_on_a_map.png diff --git a/pygmt/tests/baseline/test_makecpt_categorical.png.dvc b/pygmt/tests/baseline/test_makecpt_categorical.png.dvc new file mode 100644 index 00000000000..9eabc67f273 --- /dev/null +++ b/pygmt/tests/baseline/test_makecpt_categorical.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 9a8c5ecec5f8962987635057f577a01c + size: 6029 + path: test_makecpt_categorical.png diff --git a/pygmt/tests/baseline/test_makecpt_continuous.png b/pygmt/tests/baseline/test_makecpt_continuous.png deleted file mode 100644 index 56d5d243a58..00000000000 Binary files a/pygmt/tests/baseline/test_makecpt_continuous.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_makecpt_continuous.png.dvc b/pygmt/tests/baseline/test_makecpt_continuous.png.dvc new file mode 100644 index 00000000000..847aa561557 --- /dev/null +++ b/pygmt/tests/baseline/test_makecpt_continuous.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 9a18c81caa92725aa9de5c2dd7d74e46 + size: 75856 + path: test_makecpt_continuous.png diff --git a/pygmt/tests/baseline/test_makecpt_cyclic.png.dvc b/pygmt/tests/baseline/test_makecpt_cyclic.png.dvc new file mode 100644 index 00000000000..a21292f4af9 --- /dev/null +++ b/pygmt/tests/baseline/test_makecpt_cyclic.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 4ad410eb2843b3b47818121563c79254 + size: 4628 + path: test_makecpt_cyclic.png diff --git a/pygmt/tests/baseline/test_makecpt_plot_grid.png.dvc b/pygmt/tests/baseline/test_makecpt_plot_grid.png.dvc new file mode 100644 index 00000000000..8892a9285ff --- /dev/null +++ b/pygmt/tests/baseline/test_makecpt_plot_grid.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 690415b96990c3b1d1388bf263e40a0d + size: 150867 + path: test_makecpt_plot_grid.png diff --git a/pygmt/tests/baseline/test_makecpt_plot_grid_scaled_with_series.png.dvc b/pygmt/tests/baseline/test_makecpt_plot_grid_scaled_with_series.png.dvc new file mode 100644 index 00000000000..02553625436 --- /dev/null +++ b/pygmt/tests/baseline/test_makecpt_plot_grid_scaled_with_series.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: aea39948ca2ea6924618a0e09b0020b3 + size: 118302 + path: test_makecpt_plot_grid_scaled_with_series.png diff --git a/pygmt/tests/baseline/test_makecpt_plot_points.png.dvc b/pygmt/tests/baseline/test_makecpt_plot_points.png.dvc new file mode 100644 index 00000000000..1375bbae583 --- /dev/null +++ b/pygmt/tests/baseline/test_makecpt_plot_points.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: b28ff0dad316d0b6a860b8af7e402a56 + size: 26601 + path: test_makecpt_plot_points.png diff --git a/pygmt/tests/baseline/test_makecpt_reverse_color_and_zsign.png b/pygmt/tests/baseline/test_makecpt_reverse_color_and_zsign.png deleted file mode 100644 index cd9c7ee3345..00000000000 Binary files a/pygmt/tests/baseline/test_makecpt_reverse_color_and_zsign.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_makecpt_reverse_color_and_zsign.png.dvc b/pygmt/tests/baseline/test_makecpt_reverse_color_and_zsign.png.dvc new file mode 100644 index 00000000000..3f321c178ec --- /dev/null +++ b/pygmt/tests/baseline/test_makecpt_reverse_color_and_zsign.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 6a5ca01aebcc23b00dc884fcd9c927d8 + size: 141567 + path: test_makecpt_reverse_color_and_zsign.png diff --git a/pygmt/tests/baseline/test_makecpt_reverse_color_only.png b/pygmt/tests/baseline/test_makecpt_reverse_color_only.png deleted file mode 100644 index 81ae1a44350..00000000000 Binary files a/pygmt/tests/baseline/test_makecpt_reverse_color_only.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_makecpt_reverse_color_only.png.dvc b/pygmt/tests/baseline/test_makecpt_reverse_color_only.png.dvc new file mode 100644 index 00000000000..1b6124cde6d --- /dev/null +++ b/pygmt/tests/baseline/test_makecpt_reverse_color_only.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 5ad9b6aab72e45be8a1adc20f9e1c0e9 + size: 71377 + path: test_makecpt_reverse_color_only.png diff --git a/pygmt/tests/baseline/test_makecpt_reverse_zsign_only.png b/pygmt/tests/baseline/test_makecpt_reverse_zsign_only.png deleted file mode 100644 index 54ecee7ce92..00000000000 Binary files a/pygmt/tests/baseline/test_makecpt_reverse_zsign_only.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_makecpt_to_plot_grid.png b/pygmt/tests/baseline/test_makecpt_to_plot_grid.png deleted file mode 100644 index b7e848f4cbb..00000000000 Binary files a/pygmt/tests/baseline/test_makecpt_to_plot_grid.png and /dev/null 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 deleted file mode 100644 index 735e8379227..00000000000 Binary files a/pygmt/tests/baseline/test_makecpt_to_plot_grid_scaled_with_series.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_makecpt_to_plot_points.png b/pygmt/tests/baseline/test_makecpt_to_plot_points.png deleted file mode 100644 index 727e75726ae..00000000000 Binary files a/pygmt/tests/baseline/test_makecpt_to_plot_points.png and /dev/null 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 deleted file mode 100644 index e7d2f03a6d0..00000000000 Binary files a/pygmt/tests/baseline/test_makecpt_truncated_at_zhigh_only.png and /dev/null 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 deleted file mode 100644 index 533b8b70f38..00000000000 Binary files a/pygmt/tests/baseline/test_makecpt_truncated_at_zlow_only.png and /dev/null 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 deleted file mode 100644 index 14d800d4aab..00000000000 Binary files a/pygmt/tests/baseline/test_makecpt_truncated_to_zlow_zhigh.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_makecpt_truncated_zlow_zhigh.png.dvc b/pygmt/tests/baseline/test_makecpt_truncated_zlow_zhigh.png.dvc new file mode 100644 index 00000000000..e1aec7c6f47 --- /dev/null +++ b/pygmt/tests/baseline/test_makecpt_truncated_zlow_zhigh.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 26f3d0d95a68799ddd4eb8a130bc1445 + size: 97790 + path: test_makecpt_truncated_zlow_zhigh.png diff --git a/pygmt/tests/baseline/test_meca_loc_array.png b/pygmt/tests/baseline/test_meca_loc_array.png deleted file mode 100644 index 73c9675c1d7..00000000000 Binary files a/pygmt/tests/baseline/test_meca_loc_array.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_meca_loc_array.png.dvc b/pygmt/tests/baseline/test_meca_loc_array.png.dvc new file mode 100644 index 00000000000..31612381e84 --- /dev/null +++ b/pygmt/tests/baseline/test_meca_loc_array.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 7500fa67c18f4e307497e05fbc6857e3 + size: 4903 + path: test_meca_loc_array.png diff --git a/pygmt/tests/baseline/test_meca_spec_1d_array.png b/pygmt/tests/baseline/test_meca_spec_1d_array.png deleted file mode 100644 index e6c1f0c25c2..00000000000 Binary files a/pygmt/tests/baseline/test_meca_spec_1d_array.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_meca_spec_1d_array.png.dvc b/pygmt/tests/baseline/test_meca_spec_1d_array.png.dvc new file mode 100644 index 00000000000..def65f4334c --- /dev/null +++ b/pygmt/tests/baseline/test_meca_spec_1d_array.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 05610aeb221699698eac9d74012b5c0b + size: 3212 + path: test_meca_spec_1d_array.png diff --git a/pygmt/tests/baseline/test_meca_spec_2d_array.png b/pygmt/tests/baseline/test_meca_spec_2d_array.png deleted file mode 100644 index 51c62146df3..00000000000 Binary files a/pygmt/tests/baseline/test_meca_spec_2d_array.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_meca_spec_2d_array.png.dvc b/pygmt/tests/baseline/test_meca_spec_2d_array.png.dvc new file mode 100644 index 00000000000..d0a8f4fc2b2 --- /dev/null +++ b/pygmt/tests/baseline/test_meca_spec_2d_array.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: b3e49cd999ed234d679f359d7b4fac28 + size: 5424 + path: test_meca_spec_2d_array.png diff --git a/pygmt/tests/baseline/test_meca_spec_dataframe.png b/pygmt/tests/baseline/test_meca_spec_dataframe.png deleted file mode 100644 index 45a2efda1b4..00000000000 Binary files a/pygmt/tests/baseline/test_meca_spec_dataframe.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_meca_spec_dataframe.png.dvc b/pygmt/tests/baseline/test_meca_spec_dataframe.png.dvc new file mode 100644 index 00000000000..6fca9e8556b --- /dev/null +++ b/pygmt/tests/baseline/test_meca_spec_dataframe.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 7b7024b143d6b0ec2a339e58db4d7c78 + size: 4575 + path: test_meca_spec_dataframe.png diff --git a/pygmt/tests/baseline/test_meca_spec_dict_list.png b/pygmt/tests/baseline/test_meca_spec_dict_list.png deleted file mode 100644 index c4b54723c7b..00000000000 Binary files a/pygmt/tests/baseline/test_meca_spec_dict_list.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_meca_spec_dict_list.png.dvc b/pygmt/tests/baseline/test_meca_spec_dict_list.png.dvc new file mode 100644 index 00000000000..c889888a2b1 --- /dev/null +++ b/pygmt/tests/baseline/test_meca_spec_dict_list.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: a0abe33fb3dc4a67444cabe82cad92ba + size: 3074 + path: test_meca_spec_dict_list.png diff --git a/pygmt/tests/baseline/test_meca_spec_dictionary.png b/pygmt/tests/baseline/test_meca_spec_dictionary.png deleted file mode 100644 index 9663b3a9c1d..00000000000 Binary files a/pygmt/tests/baseline/test_meca_spec_dictionary.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_meca_spec_dictionary.png.dvc b/pygmt/tests/baseline/test_meca_spec_dictionary.png.dvc new file mode 100644 index 00000000000..a98a6a549e9 --- /dev/null +++ b/pygmt/tests/baseline/test_meca_spec_dictionary.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 8581943564134f58b295ec633acb8d1e + size: 17901 + path: test_meca_spec_dictionary.png diff --git a/pygmt/tests/baseline/test_meca_spec_file.png b/pygmt/tests/baseline/test_meca_spec_file.png deleted file mode 100644 index d3a57997080..00000000000 Binary files a/pygmt/tests/baseline/test_meca_spec_file.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_meca_spec_file.png.dvc b/pygmt/tests/baseline/test_meca_spec_file.png.dvc new file mode 100644 index 00000000000..1693cb3f82d --- /dev/null +++ b/pygmt/tests/baseline/test_meca_spec_file.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: ad602355748d74a76edfa5cef4100b13 + size: 3179 + path: test_meca_spec_file.png diff --git a/pygmt/tests/baseline/test_plot3d_colors.png.dvc b/pygmt/tests/baseline/test_plot3d_colors.png.dvc new file mode 100644 index 00000000000..8cb4355c043 --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_colors.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 6ff032c45486e738b8d42c24e6333c64 + size: 35434 + path: test_plot3d_colors.png diff --git a/pygmt/tests/baseline/test_plot3d_colors_sizes.png.dvc b/pygmt/tests/baseline/test_plot3d_colors_sizes.png.dvc new file mode 100644 index 00000000000..6013b9a3fc2 --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_colors_sizes.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 33186d037bfc92b1edfdc21141000ed7 + size: 23817 + path: test_plot3d_colors_sizes.png diff --git a/pygmt/tests/baseline/test_plot3d_colors_sizes_proj.png.dvc b/pygmt/tests/baseline/test_plot3d_colors_sizes_proj.png.dvc new file mode 100644 index 00000000000..2f9428b695e --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_colors_sizes_proj.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 36f4fd42ad4da34e28dcc49e7295e1de + size: 46095 + path: test_plot3d_colors_sizes_proj.png diff --git a/pygmt/tests/baseline/test_plot3d_from_file.png.dvc b/pygmt/tests/baseline/test_plot3d_from_file.png.dvc new file mode 100644 index 00000000000..b9441c30394 --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_from_file.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: cb66a8d11e211fcc8c58a35e1bb3a957 + size: 40754 + path: test_plot3d_from_file.png diff --git a/pygmt/tests/baseline/test_plot3d_matrix.png.dvc b/pygmt/tests/baseline/test_plot3d_matrix.png.dvc new file mode 100644 index 00000000000..5fe22f98b6e --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_matrix.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: e06a251a3eb5559215998a1fbbb5b8a1 + size: 33878 + path: test_plot3d_matrix.png diff --git a/pygmt/tests/baseline/test_plot3d_matrix_color.png.dvc b/pygmt/tests/baseline/test_plot3d_matrix_color.png.dvc new file mode 100644 index 00000000000..05539e55540 --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_matrix_color.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 9b1e94da314923794dca11d20ae3e5df + size: 24071 + path: test_plot3d_matrix_color.png diff --git a/pygmt/tests/baseline/test_plot3d_projection.png.dvc b/pygmt/tests/baseline/test_plot3d_projection.png.dvc new file mode 100644 index 00000000000..ddd6f850202 --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_projection.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 7cb09c736bc05fd7a8f0259b818c7190 + size: 37747 + path: test_plot3d_projection.png diff --git a/pygmt/tests/baseline/test_plot3d_red_circles_zscale.png.dvc b/pygmt/tests/baseline/test_plot3d_red_circles_zscale.png.dvc new file mode 100644 index 00000000000..afaef205cac --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_red_circles_zscale.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 616ef96dbb160d3173710ef2fb77eb6f + size: 46624 + path: test_plot3d_red_circles_zscale.png diff --git a/pygmt/tests/baseline/test_plot3d_red_circles_zsize.png.dvc b/pygmt/tests/baseline/test_plot3d_red_circles_zsize.png.dvc new file mode 100644 index 00000000000..f8d14977fb1 --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_red_circles_zsize.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 183b7625f59a7c6d624f80ed8aa2114a + size: 45948 + path: test_plot3d_red_circles_zsize.png diff --git a/pygmt/tests/baseline/test_plot3d_scalar_xyz.png.dvc b/pygmt/tests/baseline/test_plot3d_scalar_xyz.png.dvc new file mode 100644 index 00000000000..46f776c638b --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_scalar_xyz.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: ff132fccbeb5304eb230d64eb2c57792 + size: 30890 + path: test_plot3d_scalar_xyz.png diff --git a/pygmt/tests/baseline/test_plot3d_sizes.png.dvc b/pygmt/tests/baseline/test_plot3d_sizes.png.dvc new file mode 100644 index 00000000000..1108d08d3b6 --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_sizes.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 89e45c0906d1ee9f15139a339b9da86d + size: 31246 + path: test_plot3d_sizes.png diff --git a/pygmt/tests/baseline/test_plot3d_sizes_colors_transparencies.png.dvc b/pygmt/tests/baseline/test_plot3d_sizes_colors_transparencies.png.dvc new file mode 100644 index 00000000000..4cc49b7fd24 --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_sizes_colors_transparencies.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 231b040215ab669ada480cd31770c14a + size: 25486 + path: test_plot3d_sizes_colors_transparencies.png diff --git a/pygmt/tests/baseline/test_plot3d_transparency.png.dvc b/pygmt/tests/baseline/test_plot3d_transparency.png.dvc new file mode 100644 index 00000000000..a19e1b4e914 --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_transparency.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: d6c5a7b43189ac32ca098701851703fb + size: 21479 + path: test_plot3d_transparency.png diff --git a/pygmt/tests/baseline/test_plot3d_varying_intensity.png.dvc b/pygmt/tests/baseline/test_plot3d_varying_intensity.png.dvc index 6003814adc7..0038803da13 100644 --- a/pygmt/tests/baseline/test_plot3d_varying_intensity.png.dvc +++ b/pygmt/tests/baseline/test_plot3d_varying_intensity.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 79f7d8062dbb6f29ffa0a3aaa7382f13 - size: 24052 +- md5: cbdb71d2bbf5ec6b0a3846114fc241cf + size: 22129 path: test_plot3d_varying_intensity.png diff --git a/pygmt/tests/baseline/test_plot3d_varying_transparency.png.dvc b/pygmt/tests/baseline/test_plot3d_varying_transparency.png.dvc new file mode 100644 index 00000000000..492360f7f6e --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_varying_transparency.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 7f3cfa3eed29efaac3221c6695990417 + size: 22477 + path: test_plot3d_varying_transparency.png diff --git a/pygmt/tests/baseline/test_plot3d_vectors.png.dvc b/pygmt/tests/baseline/test_plot3d_vectors.png.dvc new file mode 100644 index 00000000000..cf9234d01cf --- /dev/null +++ b/pygmt/tests/baseline/test_plot3d_vectors.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: cbc43a6768b1766494248491b29bd4b1 + size: 22521 + path: test_plot3d_vectors.png diff --git a/pygmt/tests/baseline/test_plot_colors.png.dvc b/pygmt/tests/baseline/test_plot_colors.png.dvc index 9ffe57c0d53..b0b01ac1d27 100644 --- a/pygmt/tests/baseline/test_plot_colors.png.dvc +++ b/pygmt/tests/baseline/test_plot_colors.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: f643f63586e6557e550924e4212c1b83 - size: 26924 +- md5: 669c9cc878f831a3c25b0ecf84077de0 + size: 22867 path: test_plot_colors.png diff --git a/pygmt/tests/baseline/test_plot_colors_sizes.png.dvc b/pygmt/tests/baseline/test_plot_colors_sizes.png.dvc index 690164cb8f8..e0582299dfd 100644 --- a/pygmt/tests/baseline/test_plot_colors_sizes.png.dvc +++ b/pygmt/tests/baseline/test_plot_colors_sizes.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: c883316003595f49e7276ff2feeedc23 - size: 22649 +- md5: dacab23f81227284ba7a54d912afc5d7 + size: 18921 path: test_plot_colors_sizes.png diff --git a/pygmt/tests/baseline/test_plot_colors_sizes_proj.png.dvc b/pygmt/tests/baseline/test_plot_colors_sizes_proj.png.dvc index ded8c7e3ccf..e2b54f92607 100644 --- a/pygmt/tests/baseline/test_plot_colors_sizes_proj.png.dvc +++ b/pygmt/tests/baseline/test_plot_colors_sizes_proj.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 6b83196cfa41d4087565e8e288ec9360 - size: 32579 +- md5: b2d254db59316bfbdf906924c77214cf + size: 28285 path: test_plot_colors_sizes_proj.png diff --git a/pygmt/tests/baseline/test_plot_datetime.png.dvc b/pygmt/tests/baseline/test_plot_datetime.png.dvc index 5f8860250ed..84f0156611a 100644 --- a/pygmt/tests/baseline/test_plot_datetime.png.dvc +++ b/pygmt/tests/baseline/test_plot_datetime.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: e0011db4e7e58fb22a85ea6b1c5fa4eb - size: 18254 +- md5: ed371743977c33b2036f1e88337f7861 + size: 12780 path: test_plot_datetime.png diff --git a/pygmt/tests/baseline/test_plot_from_file.png.dvc b/pygmt/tests/baseline/test_plot_from_file.png.dvc index 14f90e51b4d..ababb3c3932 100644 --- a/pygmt/tests/baseline/test_plot_from_file.png.dvc +++ b/pygmt/tests/baseline/test_plot_from_file.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 395dba88f7816dffd1be8691502616b4 - size: 26578 +- md5: 7f7e2f839a58ae227b381103189b0380 + size: 22558 path: test_plot_from_file.png diff --git a/pygmt/tests/baseline/test_plot_lines_with_arrows.png.dvc b/pygmt/tests/baseline/test_plot_lines_with_arrows.png.dvc index a90826b4552..719a64e1b3d 100644 --- a/pygmt/tests/baseline/test_plot_lines_with_arrows.png.dvc +++ b/pygmt/tests/baseline/test_plot_lines_with_arrows.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 66c5e3755224058e57f5eb4cf8a6c403 - size: 21127 +- md5: df86e4f70b5641624d16358dba6617c3 + size: 22050 path: test_plot_lines_with_arrows.png diff --git a/pygmt/tests/baseline/test_plot_matrix.png.dvc b/pygmt/tests/baseline/test_plot_matrix.png.dvc index c2ea03ee867..b54d3b25515 100644 --- a/pygmt/tests/baseline/test_plot_matrix.png.dvc +++ b/pygmt/tests/baseline/test_plot_matrix.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: f7254b2eef71154aec50f24f3d80e216 - size: 21111 +- md5: 41e2e88122f0a2036943ec8017ac0f4f + size: 17139 path: test_plot_matrix.png diff --git a/pygmt/tests/baseline/test_plot_matrix_color.png.dvc b/pygmt/tests/baseline/test_plot_matrix_color.png.dvc index f0962f32bbb..49c0aa3f709 100644 --- a/pygmt/tests/baseline/test_plot_matrix_color.png.dvc +++ b/pygmt/tests/baseline/test_plot_matrix_color.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: eec194756b15654f98cbe2175ad9774b - size: 25104 +- md5: 09cf372b28e44de6a97e7943ba145e26 + size: 21204 path: test_plot_matrix_color.png diff --git a/pygmt/tests/baseline/test_plot_projection.png.dvc b/pygmt/tests/baseline/test_plot_projection.png.dvc index f3c56c995d4..d8a32e6ae90 100644 --- a/pygmt/tests/baseline/test_plot_projection.png.dvc +++ b/pygmt/tests/baseline/test_plot_projection.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 83866387e8e3b85e61b0b4be68cae3a1 - size: 26574 +- md5: 5fa2e73cc144954960d68108abab8795 + size: 21255 path: test_plot_projection.png diff --git a/pygmt/tests/baseline/test_plot_red_circles.png.dvc b/pygmt/tests/baseline/test_plot_red_circles.png.dvc index 45e225aa752..c4a2af70ad0 100644 --- a/pygmt/tests/baseline/test_plot_red_circles.png.dvc +++ b/pygmt/tests/baseline/test_plot_red_circles.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 28293b887a937fb34be586e0561735de - size: 18600 +- md5: a547afc02dbb426270e2329624b55835 + size: 15307 path: test_plot_red_circles.png diff --git a/pygmt/tests/baseline/test_plot_scalar_xy.png.dvc b/pygmt/tests/baseline/test_plot_scalar_xy.png.dvc index b9f2c05afce..a20055919ef 100644 --- a/pygmt/tests/baseline/test_plot_scalar_xy.png.dvc +++ b/pygmt/tests/baseline/test_plot_scalar_xy.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 5c771f56126a8e0d9edbd50e392bff50 - size: 23593 +- md5: 4837998790cefec43cd89cf93f2a5b74 + size: 24319 path: test_plot_scalar_xy.png diff --git a/pygmt/tests/baseline/test_plot_sizes.png.dvc b/pygmt/tests/baseline/test_plot_sizes.png.dvc index 553db66dd99..0a0631fc818 100644 --- a/pygmt/tests/baseline/test_plot_sizes.png.dvc +++ b/pygmt/tests/baseline/test_plot_sizes.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 8d867d0365a4df9e00fbe0a1d0e59be1 - size: 20748 +- md5: 7d0ca166d73c1461326ea55a2dc7010c + size: 17042 path: test_plot_sizes.png diff --git a/pygmt/tests/baseline/test_plot_sizes_colors_transparencies.png.dvc b/pygmt/tests/baseline/test_plot_sizes_colors_transparencies.png.dvc index 69b062080da..4b91cdd79d3 100644 --- a/pygmt/tests/baseline/test_plot_sizes_colors_transparencies.png.dvc +++ b/pygmt/tests/baseline/test_plot_sizes_colors_transparencies.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: c62218d784b1e005696dd19e8cd72f48 - size: 19260 +- md5: c0c239594e0f54feb334e6bc6cdfade2 + size: 14643 path: test_plot_sizes_colors_transparencies.png diff --git a/pygmt/tests/baseline/test_plot_transparency.png.dvc b/pygmt/tests/baseline/test_plot_transparency.png.dvc index a87962410f8..b7b1ed47f0f 100644 --- a/pygmt/tests/baseline/test_plot_transparency.png.dvc +++ b/pygmt/tests/baseline/test_plot_transparency.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 6cf164155ba82b94cd40d6bbc554b380 - size: 17737 +- md5: ae116eaad0d5c840645c37aed83d2159 + size: 12704 path: test_plot_transparency.png diff --git a/pygmt/tests/baseline/test_plot_varying_intensity.png.dvc b/pygmt/tests/baseline/test_plot_varying_intensity.png.dvc index 816686bdbeb..813921fc1d9 100644 --- a/pygmt/tests/baseline/test_plot_varying_intensity.png.dvc +++ b/pygmt/tests/baseline/test_plot_varying_intensity.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: a7b81503eff617cb3d495f10565ed044 - size: 10693 +- md5: 61159f8ce3f36d2862c39b190291257d + size: 9229 path: test_plot_varying_intensity.png diff --git a/pygmt/tests/baseline/test_plot_varying_transparency.png.dvc b/pygmt/tests/baseline/test_plot_varying_transparency.png.dvc index 6bf79478c12..852db99af4a 100644 --- a/pygmt/tests/baseline/test_plot_varying_transparency.png.dvc +++ b/pygmt/tests/baseline/test_plot_varying_transparency.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: d37f2ba80e8b835db898737fd0fdb7fb - size: 17362 +- md5: 5f429e8dfd8613bf7624b14c7d617f5b + size: 12661 path: test_plot_varying_transparency.png diff --git a/pygmt/tests/baseline/test_plot_vectors.png.dvc b/pygmt/tests/baseline/test_plot_vectors.png.dvc index 64218ec7c70..95d0b319e11 100644 --- a/pygmt/tests/baseline/test_plot_vectors.png.dvc +++ b/pygmt/tests/baseline/test_plot_vectors.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: d1dbd719eb27ead91bcbb2440798d158 - size: 15617 +- md5: 27fbdd97acc54e2008ba09c9bf12debd + size: 12113 path: test_plot_vectors.png diff --git a/pygmt/tests/baseline/test_rose_2d_array_multiple.png.dvc b/pygmt/tests/baseline/test_rose_2d_array_multiple.png.dvc index d2f072536a5..6bb4e2ea258 100644 --- a/pygmt/tests/baseline/test_rose_2d_array_multiple.png.dvc +++ b/pygmt/tests/baseline/test_rose_2d_array_multiple.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 2e440e6db215a619829acb08a0ab55bf - size: 41397 +- md5: a2c0e7fce6907cea54171b1776b7de86 + size: 36494 path: test_rose_2d_array_multiple.png diff --git a/pygmt/tests/baseline/test_rose_2d_array_single.png.dvc b/pygmt/tests/baseline/test_rose_2d_array_single.png.dvc index 886ea8638b3..58afb116de8 100644 --- a/pygmt/tests/baseline/test_rose_2d_array_single.png.dvc +++ b/pygmt/tests/baseline/test_rose_2d_array_single.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: c64abda4022e5e9fcf5592c5c2f6bb44 - size: 37742 +- md5: 7b28e4fb7fdb547a2ec2f8ce3d268736 + size: 34575 path: test_rose_2d_array_single.png diff --git a/pygmt/tests/baseline/test_rose_bools.png.dvc b/pygmt/tests/baseline/test_rose_bools.png.dvc index bf45d701a36..19d771d65aa 100644 --- a/pygmt/tests/baseline/test_rose_bools.png.dvc +++ b/pygmt/tests/baseline/test_rose_bools.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 2b0ba264c2240a6d2da02466d8848d7a - size: 73857 +- md5: 3a2af68ba35cb59b0adfc0ce26d8b0c2 + size: 59435 path: test_rose_bools.png diff --git a/pygmt/tests/baseline/test_rose_data_file.png.dvc b/pygmt/tests/baseline/test_rose_data_file.png.dvc index e2788260503..5f0e95f93f4 100644 --- a/pygmt/tests/baseline/test_rose_data_file.png.dvc +++ b/pygmt/tests/baseline/test_rose_data_file.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: eba3b08913112996eca8b9d01f5709c3 - size: 40610 +- md5: c01637915fe1fd8c36150dfa9ee974f8 + size: 32114 path: test_rose_data_file.png diff --git a/pygmt/tests/baseline/test_rose_no_sectors.png.dvc b/pygmt/tests/baseline/test_rose_no_sectors.png.dvc index 4b9404913cc..0eddeaf6fee 100644 --- a/pygmt/tests/baseline/test_rose_no_sectors.png.dvc +++ b/pygmt/tests/baseline/test_rose_no_sectors.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 67613d130577c8083e1d505155421205 - size: 159974 +- md5: 8e1c47b1cf6001dad3b3c0875af4562e + size: 150390 path: test_rose_no_sectors.png diff --git a/pygmt/tests/baseline/test_rose_plot_data_using_cpt.png.dvc b/pygmt/tests/baseline/test_rose_plot_data_using_cpt.png.dvc index 36c4d8b7fb7..c639ba52f3b 100644 --- a/pygmt/tests/baseline/test_rose_plot_data_using_cpt.png.dvc +++ b/pygmt/tests/baseline/test_rose_plot_data_using_cpt.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 1facbc2eb905197cd6aece39c08c8686 - size: 44793 +- md5: 42314fb23e4a6002e38812f66b316825 + size: 39249 path: test_rose_plot_data_using_cpt.png diff --git a/pygmt/tests/baseline/test_rose_plot_with_transparency.png.dvc b/pygmt/tests/baseline/test_rose_plot_with_transparency.png.dvc index aa0e5c5d1fc..bb8ad0fd898 100644 --- a/pygmt/tests/baseline/test_rose_plot_with_transparency.png.dvc +++ b/pygmt/tests/baseline/test_rose_plot_with_transparency.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 11af5a2d9971898c96f48e0a5215d759 - size: 62490 +- md5: 8d8adbe565623420f7211ecd97b02db2 + size: 58333 path: test_rose_plot_with_transparency.png diff --git a/pygmt/tests/baseline/test_solar_set_terminator_datetime.png.dvc b/pygmt/tests/baseline/test_solar_set_terminator_datetime.png.dvc index caaab7eedce..2bb781a16c8 100644 --- a/pygmt/tests/baseline/test_solar_set_terminator_datetime.png.dvc +++ b/pygmt/tests/baseline/test_solar_set_terminator_datetime.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 0a7f4959b500b6fa3a560a6368db0f90 - size: 25982 +- md5: 0f8baadcf84e0222b6a42a2525277c78 + size: 25000 path: test_solar_set_terminator_datetime.png diff --git a/pygmt/tests/baseline/test_solar_terminators.png.dvc b/pygmt/tests/baseline/test_solar_terminators.png.dvc index c7f3b4f2516..ef0fdad7373 100644 --- a/pygmt/tests/baseline/test_solar_terminators.png.dvc +++ b/pygmt/tests/baseline/test_solar_terminators.png.dvc @@ -1,4 +1,4 @@ outs: -- md5: 54c92bea64e0fc76c62601cb6131f22e - size: 44160 +- md5: 9854a8041fe4c5d8b3832446b77fb482 + size: 41749 path: test_solar_terminators.png diff --git a/pygmt/tests/baseline/test_subplot_autolabel_margins_title.png.dvc b/pygmt/tests/baseline/test_subplot_autolabel_margins_title.png.dvc new file mode 100644 index 00000000000..644df7c2b59 --- /dev/null +++ b/pygmt/tests/baseline/test_subplot_autolabel_margins_title.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 7be1b4ed2ec2eb506d9571e7ea3248ba + size: 28164 + path: test_subplot_autolabel_margins_title.png diff --git a/pygmt/tests/baseline/test_subplot_basic_frame.png.dvc b/pygmt/tests/baseline/test_subplot_basic_frame.png.dvc new file mode 100644 index 00000000000..83ee19173ae --- /dev/null +++ b/pygmt/tests/baseline/test_subplot_basic_frame.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 7149569679bfdef854f8683f30fc3cde + size: 9251 + path: test_subplot_basic_frame.png diff --git a/pygmt/tests/baseline/test_subplot_clearance_and_shared_xy_axis_layout.png.dvc b/pygmt/tests/baseline/test_subplot_clearance_and_shared_xy_axis_layout.png.dvc new file mode 100644 index 00000000000..65b418fed55 --- /dev/null +++ b/pygmt/tests/baseline/test_subplot_clearance_and_shared_xy_axis_layout.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 2a1b33433bd3921113938b8d7c0a4928 + size: 11245 + path: test_subplot_clearance_and_shared_xy_axis_layout.png diff --git a/pygmt/tests/baseline/test_subplot_direct.png.dvc b/pygmt/tests/baseline/test_subplot_direct.png.dvc new file mode 100644 index 00000000000..d9256e41a44 --- /dev/null +++ b/pygmt/tests/baseline/test_subplot_direct.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: d09053a8eaf8a4b32ec087f99004590b + size: 13087 + path: test_subplot_direct.png diff --git a/pygmt/tests/baseline/test_text_angle_30.png b/pygmt/tests/baseline/test_text_angle_30.png deleted file mode 100644 index a859ddd371c..00000000000 Binary files a/pygmt/tests/baseline/test_text_angle_30.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_angle_30.png.dvc b/pygmt/tests/baseline/test_text_angle_30.png.dvc new file mode 100644 index 00000000000..a49dc604574 --- /dev/null +++ b/pygmt/tests/baseline/test_text_angle_30.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: ecd7b400f7421d0f9d65879f798be3aa + size: 5485 + path: test_text_angle_30.png diff --git a/pygmt/tests/baseline/test_text_angle_font_justify_from_textfile.png b/pygmt/tests/baseline/test_text_angle_font_justify_from_textfile.png deleted file mode 100644 index bc244904784..00000000000 Binary files a/pygmt/tests/baseline/test_text_angle_font_justify_from_textfile.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_angle_font_justify_from_textfile.png.dvc b/pygmt/tests/baseline/test_text_angle_font_justify_from_textfile.png.dvc new file mode 100644 index 00000000000..8cc59c370d8 --- /dev/null +++ b/pygmt/tests/baseline/test_text_angle_font_justify_from_textfile.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 67773d5e56bd3d8a9afda23551f24793 + size: 14146 + path: test_text_angle_font_justify_from_textfile.png diff --git a/pygmt/tests/baseline/test_text_fill.png b/pygmt/tests/baseline/test_text_fill.png deleted file mode 100644 index f3f341828aa..00000000000 Binary files a/pygmt/tests/baseline/test_text_fill.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_fill.png.dvc b/pygmt/tests/baseline/test_text_fill.png.dvc new file mode 100644 index 00000000000..2583a8b93e4 --- /dev/null +++ b/pygmt/tests/baseline/test_text_fill.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 81c49d2f653288ac23937a8a91802ff3 + size: 1918 + path: test_text_fill.png diff --git a/pygmt/tests/baseline/test_text_font_bold.png b/pygmt/tests/baseline/test_text_font_bold.png deleted file mode 100644 index 957056ba43c..00000000000 Binary files a/pygmt/tests/baseline/test_text_font_bold.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_font_bold.png.dvc b/pygmt/tests/baseline/test_text_font_bold.png.dvc new file mode 100644 index 00000000000..d480a594ad7 --- /dev/null +++ b/pygmt/tests/baseline/test_text_font_bold.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 55875debfe049cc8b9fed9012ab0cde7 + size: 1346 + path: test_text_font_bold.png diff --git a/pygmt/tests/baseline/test_text_input_multiple_filenames.png b/pygmt/tests/baseline/test_text_input_multiple_filenames.png deleted file mode 100644 index 3589de0bc49..00000000000 Binary files a/pygmt/tests/baseline/test_text_input_multiple_filenames.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_input_multiple_filenames.png.dvc b/pygmt/tests/baseline/test_text_input_multiple_filenames.png.dvc new file mode 100644 index 00000000000..80cd7d67bfd --- /dev/null +++ b/pygmt/tests/baseline/test_text_input_multiple_filenames.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: ad2ebff32ed5559c165767427ad974cb + size: 32675 + path: test_text_input_multiple_filenames.png diff --git a/pygmt/tests/baseline/test_text_input_remote_filename.png b/pygmt/tests/baseline/test_text_input_remote_filename.png deleted file mode 100644 index b0c680568ca..00000000000 Binary files a/pygmt/tests/baseline/test_text_input_remote_filename.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_input_remote_filename.png.dvc b/pygmt/tests/baseline/test_text_input_remote_filename.png.dvc new file mode 100644 index 00000000000..e21b99e85f1 --- /dev/null +++ b/pygmt/tests/baseline/test_text_input_remote_filename.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 3dcfb0403ab740ea59b6633af1d466d3 + size: 48909 + path: test_text_input_remote_filename.png diff --git a/pygmt/tests/baseline/test_text_input_single_filename.png b/pygmt/tests/baseline/test_text_input_single_filename.png deleted file mode 100644 index 65ab36c1221..00000000000 Binary files a/pygmt/tests/baseline/test_text_input_single_filename.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_input_single_filename.png.dvc b/pygmt/tests/baseline/test_text_input_single_filename.png.dvc new file mode 100644 index 00000000000..9faf69dd64c --- /dev/null +++ b/pygmt/tests/baseline/test_text_input_single_filename.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 0d4bb86bb215dc668954cd0f797b0112 + size: 30750 + path: test_text_input_single_filename.png diff --git a/pygmt/tests/baseline/test_text_justify_bottom_right_and_top_left.png b/pygmt/tests/baseline/test_text_justify_bottom_right_and_top_left.png deleted file mode 100644 index 5f10262a4d5..00000000000 Binary files a/pygmt/tests/baseline/test_text_justify_bottom_right_and_top_left.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_justify_bottom_right_and_top_left.png.dvc b/pygmt/tests/baseline/test_text_justify_bottom_right_and_top_left.png.dvc new file mode 100644 index 00000000000..216805c1147 --- /dev/null +++ b/pygmt/tests/baseline/test_text_justify_bottom_right_and_top_left.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: de441a55342a02fd9a72dfb4e26b1e4f + size: 4665 + path: test_text_justify_bottom_right_and_top_left.png diff --git a/pygmt/tests/baseline/test_text_justify_parsed_from_textfile.png b/pygmt/tests/baseline/test_text_justify_parsed_from_textfile.png deleted file mode 100644 index 34b89b39bad..00000000000 Binary files a/pygmt/tests/baseline/test_text_justify_parsed_from_textfile.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_justify_parsed_from_textfile.png.dvc b/pygmt/tests/baseline/test_text_justify_parsed_from_textfile.png.dvc new file mode 100644 index 00000000000..47fbe2a2984 --- /dev/null +++ b/pygmt/tests/baseline/test_text_justify_parsed_from_textfile.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 5933108dbec4e66903180fec744128fb + size: 11229 + path: test_text_justify_parsed_from_textfile.png diff --git a/pygmt/tests/baseline/test_text_multiple_lines_of_text.png b/pygmt/tests/baseline/test_text_multiple_lines_of_text.png deleted file mode 100644 index 0bb344d2c04..00000000000 Binary files a/pygmt/tests/baseline/test_text_multiple_lines_of_text.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_multiple_lines_of_text.png.dvc b/pygmt/tests/baseline/test_text_multiple_lines_of_text.png.dvc new file mode 100644 index 00000000000..d268e5fc104 --- /dev/null +++ b/pygmt/tests/baseline/test_text_multiple_lines_of_text.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 680b7683044d4a4dced2fa7ef6b224f3 + size: 6016 + path: test_text_multiple_lines_of_text.png diff --git a/pygmt/tests/baseline/test_text_nonstr_text.png.dvc b/pygmt/tests/baseline/test_text_nonstr_text.png.dvc new file mode 100644 index 00000000000..3b4ffabf4fd --- /dev/null +++ b/pygmt/tests/baseline/test_text_nonstr_text.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 33281f8b69dabad053c3031e17b0680b + size: 17998 + path: test_text_nonstr_text.png diff --git a/pygmt/tests/baseline/test_text_pen.png b/pygmt/tests/baseline/test_text_pen.png deleted file mode 100644 index 68ce614a7ea..00000000000 Binary files a/pygmt/tests/baseline/test_text_pen.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_pen.png.dvc b/pygmt/tests/baseline/test_text_pen.png.dvc new file mode 100644 index 00000000000..0b44dd4b47e --- /dev/null +++ b/pygmt/tests/baseline/test_text_pen.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 0fa24792c277718f44e6468a699921a0 + size: 2469 + path: test_text_pen.png diff --git a/pygmt/tests/baseline/test_text_position.png b/pygmt/tests/baseline/test_text_position.png deleted file mode 100644 index 165c6c3a157..00000000000 Binary files a/pygmt/tests/baseline/test_text_position.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_position.png.dvc b/pygmt/tests/baseline/test_text_position.png.dvc new file mode 100644 index 00000000000..8eccfbb4ed9 --- /dev/null +++ b/pygmt/tests/baseline/test_text_position.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 3463b1217b0d1aca2913cbcb9b0ca438 + size: 10583 + path: test_text_position.png diff --git a/pygmt/tests/baseline/test_text_position_offset_with_line.png b/pygmt/tests/baseline/test_text_position_offset_with_line.png deleted file mode 100644 index 4e8d438a8f9..00000000000 Binary files a/pygmt/tests/baseline/test_text_position_offset_with_line.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_position_offset_with_line.png.dvc b/pygmt/tests/baseline/test_text_position_offset_with_line.png.dvc new file mode 100644 index 00000000000..c648bbfc38e --- /dev/null +++ b/pygmt/tests/baseline/test_text_position_offset_with_line.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: e5645d25873e31c750e6642a63a6d47d + size: 11577 + path: test_text_position_offset_with_line.png diff --git a/pygmt/tests/baseline/test_text_round_clearance.png b/pygmt/tests/baseline/test_text_round_clearance.png deleted file mode 100644 index c35e44a5d74..00000000000 Binary files a/pygmt/tests/baseline/test_text_round_clearance.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_round_clearance.png.dvc b/pygmt/tests/baseline/test_text_round_clearance.png.dvc new file mode 100644 index 00000000000..ea3e4fece6b --- /dev/null +++ b/pygmt/tests/baseline/test_text_round_clearance.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: ad64e7cba2c3f776a8786fd551063489 + size: 3558 + path: test_text_round_clearance.png diff --git a/pygmt/tests/baseline/test_text_single_line_of_text.png b/pygmt/tests/baseline/test_text_single_line_of_text.png deleted file mode 100644 index 932ac478cfc..00000000000 Binary files a/pygmt/tests/baseline/test_text_single_line_of_text.png and /dev/null differ diff --git a/pygmt/tests/baseline/test_text_single_line_of_text.png.dvc b/pygmt/tests/baseline/test_text_single_line_of_text.png.dvc new file mode 100644 index 00000000000..694bdd95e43 --- /dev/null +++ b/pygmt/tests/baseline/test_text_single_line_of_text.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 3f3874c252ee2cefc3f9a2c29f46b8e3 + size: 1839 + path: test_text_single_line_of_text.png diff --git a/pygmt/tests/baseline/test_text_transparency.png.dvc b/pygmt/tests/baseline/test_text_transparency.png.dvc new file mode 100644 index 00000000000..a57b7a69bc4 --- /dev/null +++ b/pygmt/tests/baseline/test_text_transparency.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: c2fd156325a40e9d875edfd6d236002e + size: 24535 + path: test_text_transparency.png diff --git a/pygmt/tests/baseline/test_text_varying_transparency.png.dvc b/pygmt/tests/baseline/test_text_varying_transparency.png.dvc new file mode 100644 index 00000000000..acdd94997e8 --- /dev/null +++ b/pygmt/tests/baseline/test_text_varying_transparency.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 5e867b4473cd9d1063ad5a08253e031c + size: 24775 + path: test_text_varying_transparency.png diff --git a/pygmt/tests/baseline/test_velo_numpy_array_numeric_only.png.dvc b/pygmt/tests/baseline/test_velo_numpy_array_numeric_only.png.dvc new file mode 100644 index 00000000000..10da6c1a375 --- /dev/null +++ b/pygmt/tests/baseline/test_velo_numpy_array_numeric_only.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 64e45d586112fc131090cfac2c104b63 + size: 45483 + path: test_velo_numpy_array_numeric_only.png diff --git a/pygmt/tests/baseline/test_velo_pandas_dataframe.png.dvc b/pygmt/tests/baseline/test_velo_pandas_dataframe.png.dvc new file mode 100644 index 00000000000..a696a5b2773 --- /dev/null +++ b/pygmt/tests/baseline/test_velo_pandas_dataframe.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 60dff1a72e6d984f095fb4973cecaec7 + size: 42430 + path: test_velo_pandas_dataframe.png diff --git a/pygmt/tests/baseline/test_wiggle.png.dvc b/pygmt/tests/baseline/test_wiggle.png.dvc new file mode 100644 index 00000000000..5f3819fb339 --- /dev/null +++ b/pygmt/tests/baseline/test_wiggle.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: 5ac12f7e91127dae1fa70cec77b84c0b + size: 9144 + path: test_wiggle.png diff --git a/pygmt/tests/test_accessor.py b/pygmt/tests/test_accessor.py index 32fa3e4001b..a3b0dc4fafc 100644 --- a/pygmt/tests/test_accessor.py +++ b/pygmt/tests/test_accessor.py @@ -24,7 +24,7 @@ def test_accessor_pixel_geographic(): and a gtype value of 0 when using Cartesian coordinates. """ fname = which(fname="@earth_relief_01d_p", download="a") - grid = xr.open_dataarray(fname) + grid = xr.open_dataarray(fname, engine="netcdf4") assert grid.gmt.registration == 1 # pixel registration assert grid.gmt.gtype == 1 # geographic coordinate type diff --git a/pygmt/tests/test_basemap.py b/pygmt/tests/test_basemap.py index 726661ab165..6fc2946d55e 100644 --- a/pygmt/tests/test_basemap.py +++ b/pygmt/tests/test_basemap.py @@ -2,9 +2,13 @@ Tests Figure.basemap. """ import pytest -from pygmt import Figure +from packaging.version import Version +from pygmt import Figure, clib from pygmt.exceptions import GMTInvalidInput +with clib.Session() as _lib: + gmt_version = Version(_lib.info["version"]) + def test_basemap_required_args(): """ @@ -53,6 +57,10 @@ def test_basemap_power_axis(): return fig +@pytest.mark.xfail( + condition=gmt_version == Version("6.2.0rc1"), + reason="Upstream bug #5167 in GMT 6.2.0rc1", +) @pytest.mark.mpl_image_compare def test_basemap_polar(): """ diff --git a/pygmt/tests/test_clib_put_matrix.py b/pygmt/tests/test_clib_put_matrix.py index 46e9ebd9d5c..e5c0bfe604c 100644 --- a/pygmt/tests/test_clib_put_matrix.py +++ b/pygmt/tests/test_clib_put_matrix.py @@ -92,7 +92,7 @@ def test_put_matrix_grid(): npt.assert_allclose(newdata, data) # Save the data to a netCDF grid and check that xarray can load it - with GMTTempFile() as tmp_grid: + with GMTTempFile(suffix=".nc") as tmp_grid: lib.write_data( "GMT_IS_MATRIX", "GMT_IS_SURFACE", diff --git a/pygmt/tests/test_clib_put_vector.py b/pygmt/tests/test_clib_put_vector.py index 72a4c858898..1d085eb92ca 100644 --- a/pygmt/tests/test_clib_put_vector.py +++ b/pygmt/tests/test_clib_put_vector.py @@ -2,6 +2,7 @@ Test the functions that put vector data into GMT. """ import itertools +from datetime import datetime import numpy as np import numpy.testing as npt @@ -90,6 +91,75 @@ def test_put_vector_mixed_dtypes(): npt.assert_allclose(newy, y) +def test_put_vector_string_dtype(): + """ + Passing string type vectors to a dataset. + """ + # input string vectors: numbers, longitudes, latitudes, and datetimes + vectors = np.array( + [ + ["10", "20.0", "-30.0", "3.5e1"], + ["10W", "30.50E", "30:30W", "40:30:30.500E"], + ["10N", "30.50S", "30:30N", "40:30:30.500S"], + ["2021-02-03", "2021-02-03T04", "2021-02-03T04:05:06.700", "T04:50:06.700"], + ] + ) + # output vectors in double or string type + # Notes: + # 1. longitudes and latitudes are stored in double in GMT + # 2. The default output format for datetime is YYYY-mm-ddTHH:MM:SS + expected_vectors = [ + [10.0, 20.0, -30.0, 35], + [-10, 30.5, -30.5, 40.508472], + [10, -30.50, 30.5, -40.508472], + [ + "2021-02-03T00:00:00", + "2021-02-03T04:00:00", + "2021-02-03T04:05:06", + f"{datetime.utcnow().strftime('%Y-%m-%d')}T04:50:06", + ], + ] + + # loop over all possible combinations of input types + for i, j in itertools.combinations_with_replacement(range(4), r=2): + with clib.Session() as lib: + dataset = lib.create_data( + family="GMT_IS_DATASET|GMT_VIA_VECTOR", + geometry="GMT_IS_POINT", + mode="GMT_CONTAINER_ONLY", + dim=[2, 4, 1, 0], # columns, rows, layers, dtype + ) + lib.put_vector(dataset, column=lib["GMT_X"], vector=vectors[i]) + lib.put_vector(dataset, column=lib["GMT_Y"], vector=vectors[j]) + # Turns out wesn doesn't matter for Datasets + wesn = [0] * 6 + # Save the data to a file to see if it's being accessed correctly + with GMTTempFile() as tmp_file: + lib.write_data( + "GMT_IS_VECTOR", + "GMT_IS_POINT", + "GMT_WRITE_SET", + wesn, + tmp_file.name, + dataset, + ) + # Load the data + output = np.genfromtxt( + tmp_file.name, dtype=None, names=("x", "y"), encoding=None + ) + # check that the output is correct + # Use npt.assert_allclose for numeric arrays + # and npt.assert_array_equal for string arrays + if i != 3: + npt.assert_allclose(output["x"], expected_vectors[i]) + else: + npt.assert_array_equal(output["x"], expected_vectors[i]) + if j != 3: + npt.assert_allclose(output["y"], expected_vectors[j]) + else: + npt.assert_array_equal(output["y"], expected_vectors[j]) + + def test_put_vector_invalid_dtype(): """ Check that it fails with an exception for invalid data types. diff --git a/pygmt/tests/test_colorbar.py b/pygmt/tests/test_colorbar.py index 865df5d00e8..7b58ad26381 100644 --- a/pygmt/tests/test_colorbar.py +++ b/pygmt/tests/test_colorbar.py @@ -3,65 +3,6 @@ """ import pytest from pygmt import Figure -from pygmt.helpers.testing import check_figures_equal - - -@pytest.mark.mpl_image_compare -def test_colorbar_using_paper_coordinates(): - """ - Create colorbar positioned at 0cm,0cm with length 1cm and width 0.5cm. - """ - fig = Figure() - fig.colorbar(cmap="rainbow", position="x0c/0c+w1c/0.5c") - return fig - - -@pytest.mark.mpl_image_compare -def test_colorbar_using_paper_coordinates_horizontal(): - """ - Create colorbar positioned at 0cm,0cm with length 2cm oriented - horizontally. - """ - fig = Figure() - fig.colorbar(cmap="rainbow", position="x0c/0c+w2c+h") - return fig - - -@pytest.mark.mpl_image_compare -def test_colorbar_positioned_using_map_coordinates(): - """ - Create colorbar positioned at longitude,latitude 3,6 with length 2cm. - """ - fig = Figure() - fig.basemap(region=[2, 4, 6, 8], projection="t0/2c", frame=True) - fig.colorbar(cmap="rainbow", position="g3/6+w2c") - return fig - - -@check_figures_equal() -def test_colorbar_positioned_using_justification_code(): - """ - Create colorbar at Top Center inside the map frame with length 2cm. - """ - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - fig_ref.basemap(R="2/4/6/8", J="t0/2c", B="") - fig_ref.colorbar(C="rainbow", D="jTC+w2c") - - fig_test.basemap(region=[2, 4, 6, 8], projection="t0/2c", frame=True) - fig_test.colorbar(cmap="rainbow", position="jTC+w2c") - return fig_ref, fig_test - - -@pytest.mark.mpl_image_compare -def test_colorbar_positioned_using_normalized_coords(): - """ - Create colorbar at normalized coordinates 0.75,0.25 with length 2cm. - """ - fig = Figure() - fig.basemap(region=[2, 4, 6, 8], projection="t0/2c", frame=True) - fig.colorbar(cmap="rainbow", position="n0.75/0.25+w2c") - return fig @pytest.mark.mpl_image_compare @@ -74,16 +15,6 @@ def test_colorbar_box(): return fig -@pytest.mark.mpl_image_compare -def test_colorbar_box_with_pen(): - """ - Create colorbar with box that has a different colored pen. - """ - fig = Figure() - fig.colorbar(cmap="rainbow", box="+porange", position="x0c/0c+w1c/0.5c") - return fig - - @pytest.mark.mpl_image_compare def test_colorbar_box_with_fill(): """ @@ -94,48 +25,6 @@ def test_colorbar_box_with_fill(): return fig -@pytest.mark.mpl_image_compare -def test_colorbar_box_with_clearance(): - """ - Create colorbar with box that has an x-clearance of 0.8cm and y-clearance - of 0.4cm. - """ - fig = Figure() - fig.colorbar(cmap="rainbow", box="+c0.8c/0.4c+porange", position="x0c/0c+w1c/0.5c") - return fig - - -@pytest.mark.mpl_image_compare -def test_colorbar_box_with_secondary_border(): - """ - Create colorbar with box that has a secondary, inner border in addition to - the main primary, outer border. - """ - fig = Figure() - fig.colorbar(cmap="rainbow", box="+porange+imagenta", position="x0c/0c+w1c/0.5c") - return fig - - -@pytest.mark.mpl_image_compare -def test_colorbar_box_with_rounded_corners(): - """ - Create colorbar with box that has rounded corners. - """ - fig = Figure() - fig.colorbar(cmap="rainbow", box="+porange+r", position="x0c/0c+w1c/0.5c") - return fig - - -@pytest.mark.mpl_image_compare -def test_colorbar_box_with_offset_background(): - """ - Create colorbar with box and an offset background shaded region. - """ - fig = Figure() - fig.colorbar(cmap="rainbow", box="+s5p/-5p", position="x0c/0c+w1c/0.5c") - return fig - - @pytest.mark.mpl_image_compare def test_colorbar_truncated_to_zlow_zhigh(): """ @@ -156,61 +45,23 @@ def test_colorbar_scaled_z_values(): return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_colorbar_shading_boolean(): """ Create colorbar and set shading with a Boolean value. """ - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - fig_ref.basemap(R="0/10/0/10", J="X15c", B="a") - fig_ref.colorbar(C="geo", I="") - - fig_test.basemap(region=[0, 10, 0, 10], projection="X15c", frame="a") - fig_test.colorbar(cmap="geo", shading=True) - return fig_ref, fig_test - - -@check_figures_equal() -def test_colorbar_shading_float(): - """ - Create colorbar and set shading with a single float variable. - """ - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - fig_ref.basemap(R="0/10/0/10", J="X15c", B="a") - fig_ref.colorbar(C="geo", I=0.5) - - fig_test.basemap(region=[0, 10, 0, 10], projection="X15c", frame="a") - fig_test.colorbar(cmap="geo", shading=0.5) - return fig_ref, fig_test - - -@check_figures_equal() -def test_colorbar_shading_string(): - """ - Create colorbar and set shading by passing the low/high values as a string. - """ - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - fig_ref.basemap(R="0/10/0/10", J="X15c", B="a") - fig_ref.colorbar(C="geo", I="-0.7/0.2") - - fig_test.basemap(region=[0, 10, 0, 10], projection="X15c", frame="a") - fig_test.colorbar(cmap="geo", shading="-0.7/0.2") - return fig_ref, fig_test + fig = Figure() + fig.basemap(region=[0, 10, 0, 10], projection="X15c", frame="a") + fig.colorbar(cmap="geo", shading=True, frame=True) + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_colorbar_shading_list(): """ Create colorbar and set shading by passing the high/low values as a list. """ - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - fig_ref.basemap(R="0/10/0/10", J="X15c", B="a") - fig_ref.colorbar(C="geo", I="-0.7/0.2") - - fig_test.basemap(region=[0, 10, 0, 10], projection="X15c", frame="a") - fig_test.colorbar(cmap="geo", shading=[-0.7, 0.2]) - return fig_ref, fig_test + fig = Figure() + fig.basemap(region=[0, 10, 0, 10], projection="X15c", frame="a") + fig.colorbar(cmap="geo", shading=[-0.7, 0.2], frame=True) + return fig diff --git a/pygmt/tests/test_config.py b/pygmt/tests/test_config.py index 63a3005d918..ba39ab53b79 100644 --- a/pygmt/tests/test_config.py +++ b/pygmt/tests/test_config.py @@ -1,9 +1,8 @@ """ -Tests for gmt config. +Tests for pygmt.config. """ import pytest from pygmt import Figure, config -from pygmt.helpers.testing import check_figures_equal @pytest.mark.mpl_image_compare @@ -15,83 +14,61 @@ def test_config(): # Change global settings of current figure config(FONT_ANNOT_PRIMARY="blue") fig.basemap( - region="0/10/0/10", projection="X10c/10c", frame=["af", '+t"Blue Annotation"'] + region=[0, 10, 0, 10], projection="X5c/5c", frame=["af", '+t"Blue Annotation"'] ) with config(FONT_LABEL="red", FONT_ANNOT_PRIMARY="red"): fig.basemap( - region="0/10/0/10", - projection="X10c/10c", + region=[0, 10, 0, 10], + projection="X5c/5c", frame=['xaf+l"red label"', "yaf", '+t"red annotation"'], - X="15c", + xshift="7c", ) fig.basemap( - region="0/10/0/10", - projection="X10c/10c", + region=[0, 10, 0, 10], + projection="X5c/5c", frame=["af", '+t"Blue Annotation"'], - X="15c", + xshift="7c", ) # Revert to default settings in current figure config(FONT_ANNOT_PRIMARY="black") return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_config_font_one(): """ - Test that setting `FONT` config changes all `FONT_*` settings except - `FONT_LOGO`. + Test that setting FONT config changes all FONT_* settings except FONT_LOGO. - Specifically, this test only checks that `FONT_ANNOT_PRIMARY`, - `FONT_ANNOT_SECONDARY`, `FONT_LABEL`, and `FONT_TITLE` are modified. + Specifically, this test only checks that FONT_ANNOT_PRIMARY, + FONT_ANNOT_SECONDARY, FONT_LABEL, and FONT_TITLE are modified. """ - fig_ref = Figure() - with config( - FONT_ANNOT_PRIMARY="8p,red", - FONT_ANNOT_SECONDARY="8p,red", - FONT_LABEL="8p,red", - FONT_TITLE="8p,red", - ): - fig_ref.basemap(R="0/9/0/9", J="C3/3/9c", Tm="jTL+w4c+d4.5+l") - fig_ref.basemap(Tm="jBR+w5c+d-4.5+l") - - fig_test = Figure() + fig = Figure() with config(FONT="8p,red"): - fig_test.basemap( - region=[0, 9, 0, 9], projection="C3/3/9c", compass="jTL+w4c+d4.5+l" - ) - fig_test.basemap(compass="jBR+w5c+d-4.5+l") - - return fig_ref, fig_test + fig.basemap(region=[0, 9, 0, 9], projection="C3/3/9c", compass="jTL+w4c+d4.5+l") + fig.basemap(compass="jBR+w5c+d-4.5+l") + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_config_font_annot(): """ - Test that setting `FONT_ANNOT` config changes both `FONT_ANNOT_PRIMARY` and - `FONT_ANNOT_SECONDARY`. + Test that setting FONT_ANNOT config changes both FONT_ANNOT_PRIMARY and + FONT_ANNOT_SECONDARY. """ - fig_ref = Figure() - with config(FONT_ANNOT_PRIMARY="6p,red", FONT_ANNOT_SECONDARY="6p,red"): - fig_ref.basemap(R="0/9/0/9", J="C3/3/9c", Tm="jTL+w4c+d4.5") - fig_ref.basemap(compass="jBR+w5c+d-4.5") - - fig_test = Figure() + fig = Figure() with config(FONT_ANNOT="6p,red"): - fig_test.basemap( - region=[0, 9, 0, 9], projection="C3/3/9c", compass="jTL+w4c+d4.5" - ) - fig_test.basemap(compass="jBR+w5c+d-4.5") - - return fig_ref, fig_test + fig.basemap(region=[0, 9, 0, 9], projection="C3/3/9c", compass="jTL+w4c+d4.5") + fig.basemap(compass="jBR+w5c+d-4.5") + return fig @pytest.mark.mpl_image_compare def test_config_format_time_map(): """ - Test that setting `FORMAT_TIME_MAP` config changes both - `FORMAT_TIME_PRIMARY_MAP` and `FORMAT_TIME_SECONDARY_MAP`. + Test that setting FORMAT_TIME_MAP config changes both + FORMAT_TIME_PRIMARY_MAP and FORMAT_TIME_SECONDARY_MAP. """ fig = Figure() with config(FORMAT_TIME_MAP="abbreviation"): @@ -107,8 +84,8 @@ def test_config_format_time_map(): @pytest.mark.mpl_image_compare def test_config_map_annot_offset(): """ - Test that setting `MAP_ANNOT_OFFSET` config changes both - `MAP_ANNOT_OFFSET_PRIMARY` and `MAP_ANNOT_OFFSET_SECONDARY`. + Test that setting MAP_ANNOT_OFFSET config changes both + MAP_ANNOT_OFFSET_PRIMARY and MAP_ANNOT_OFFSET_SECONDARY. """ fig = Figure() with config(MAP_ANNOT_OFFSET="15p"): @@ -124,8 +101,8 @@ def test_config_map_annot_offset(): @pytest.mark.mpl_image_compare def test_config_map_grid_cross_size(): """ - Test that setting `MAP_GRID_CROSS_SIZE` config changes both - `MAP_GRID_CROSS_SIZE_PRIMARY` and `MAP_GRID_CROSS_SIZE_SECONDARY`. + Test that setting MAP_GRID_CROSS_SIZE config changes both + MAP_GRID_CROSS_SIZE_PRIMARY and MAP_GRID_CROSS_SIZE_SECONDARY. """ fig = Figure() with config(MAP_GRID_CROSS_SIZE="3p"): @@ -142,8 +119,8 @@ def test_config_map_grid_cross_size(): @pytest.mark.mpl_image_compare def test_config_map_grid_pen(): """ - Test that setting `MAP_GRID_PEN` config changes both `MAP_GRID_PEN_PRIMARY` - and `MAP_GRID_PEN_SECONDARY`. + Test that setting MAP_GRID_PEN config changes both MAP_GRID_PEN_PRIMARY and + MAP_GRID_PEN_SECONDARY. """ fig = Figure() with config(MAP_GRID_PEN="thick,red"): @@ -160,8 +137,8 @@ def test_config_map_grid_pen(): @pytest.mark.mpl_image_compare def test_config_map_tick_length(): """ - Test that setting `MAP_TICK_LENGTH` config changes both - `MAP_TICK_LENGTH_PRIMARY` and `MAP_TICK_LENGTH_SECONDARY`. + Test that setting MAP_TICK_LENGTH config changes both + MAP_TICK_LENGTH_PRIMARY and MAP_TICK_LENGTH_SECONDARY. """ fig = Figure() with config(MAP_TICK_LENGTH="5p"): @@ -178,8 +155,8 @@ def test_config_map_tick_length(): @pytest.mark.mpl_image_compare def test_config_map_tick_pen(): """ - Test that setting `MAP_TICK_PEN` config changes both `MAP_TICK_PEN_PRIMARY` - and `MAP_TICK_PEN_SECONDARY`. + Test that setting MAP_TICK_PEN config changes both MAP_TICK_PEN_PRIMARY and + MAP_TICK_PEN_SECONDARY. """ fig = Figure() with config(MAP_TICK_PEN="thick,red"): diff --git a/pygmt/tests/test_figure.py b/pygmt/tests/test_figure.py index 6ea0a27b21f..fa72d0926af 100644 --- a/pygmt/tests/test_figure.py +++ b/pygmt/tests/test_figure.py @@ -8,7 +8,7 @@ import numpy as np import numpy.testing as npt import pytest -from pygmt import Figure +from pygmt import Figure, set_display from pygmt.exceptions import GMTInvalidInput @@ -154,8 +154,7 @@ def test_figure_show(): """ fig = Figure() fig.basemap(region="10/70/-300/800", projection="X3i/5i", frame="af") - img = fig.show(width=800) - assert img.width == 800 + fig.show() @pytest.mark.mpl_image_compare @@ -187,3 +186,12 @@ def test_figure_show_invalid_method(): fig.basemap(region="10/70/-300/800", projection="X3i/5i", frame="af") with pytest.raises(GMTInvalidInput): fig.show(method="test") + + +def test_figure_set_display_invalid(): + """ + Test to check if an error is raised when an invalid method is passed to + set_display. + """ + with pytest.raises(GMTInvalidInput): + set_display(method="invalid") diff --git a/pygmt/tests/test_grd2cpt.py b/pygmt/tests/test_grd2cpt.py index 26a83cced36..59c1e4b7f42 100644 --- a/pygmt/tests/test_grd2cpt.py +++ b/pygmt/tests/test_grd2cpt.py @@ -4,12 +4,10 @@ import os import pytest -from pygmt import Figure +from pygmt import Figure, grd2cpt from pygmt.datasets import load_earth_relief from pygmt.exceptions import GMTInvalidInput from pygmt.helpers import GMTTempFile -from pygmt.helpers.testing import check_figures_equal -from pygmt.src.grd2cpt import grd2cpt @pytest.fixture(scope="module", name="grid") @@ -20,21 +18,17 @@ def fixture_grid(): return load_earth_relief() -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_grd2cpt(grid): """ Test creating a CPT with grd2cpt to create a CPT based off a grid input and plot it with a color bar. """ - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - fig_ref.basemap(B="a", J="W0/15c", R="d") - grd2cpt(grid="@earth_relief_01d") - fig_ref.colorbar(B="a2000") - fig_test.basemap(frame="a", projection="W0/15c", region="d") + fig = Figure() + fig.basemap(frame="a", projection="W0/15c", region="d") grd2cpt(grid=grid) - fig_test.colorbar(frame="a2000") - return fig_ref, fig_test + fig.colorbar(frame="a2000") + return fig def test_grd2cpt_blank_output(grid): diff --git a/pygmt/tests/test_grdcontour.py b/pygmt/tests/test_grdcontour.py index b208be55d6e..2c759afcca6 100644 --- a/pygmt/tests/test_grdcontour.py +++ b/pygmt/tests/test_grdcontour.py @@ -8,7 +8,6 @@ from pygmt import Figure from pygmt.datasets import load_earth_relief from pygmt.exceptions import GMTInvalidInput -from pygmt.helpers.testing import check_figures_equal TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data") TEST_CONTOUR_FILE = os.path.join(TEST_DATA_DIR, "contours.txt") @@ -22,52 +21,45 @@ def fixture_grid(): return load_earth_relief(registration="gridline") -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_grdcontour(grid): """ Plot a contour image using an xarray grid with fixed contour interval. """ - fig_ref, fig_test = Figure(), Figure() - kwargs = dict(interval="1000", projection="W0/6i") - fig_ref.grdcontour("@earth_relief_01d_g", **kwargs) - fig_test.grdcontour(grid, **kwargs) - return fig_ref, fig_test + fig = Figure() + fig.grdcontour(grid, interval="1000", projection="W0/15c", frame=True) + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_grdcontour_labels(grid): """ Plot a contour image using a xarray grid with contour labels and alternate colors. """ - fig_ref, fig_test = Figure(), Figure() - kwargs = dict( + fig = Figure() + fig.grdcontour( + grid, interval="1000", annotation="5000", - projection="W0/6i", + projection="W0/15c", pen=["a1p,red", "c0.5p,black"], - label_placement="d3i", + label_placement="d6c", + frame=True, ) - fig_ref.grdcontour("@earth_relief_01d_g", **kwargs) - fig_test.grdcontour(grid, **kwargs) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_grdcontour_slice(grid): """ Plot an contour image using an xarray grid that has been sliced. """ - - fig_ref, fig_test = Figure(), Figure() - grid_ = grid.sel(lat=slice(-30, 30)) - kwargs = dict(interval="1000", projection="M6i") - fig_ref.grdcontour( - grid="@earth_relief_01d_g", region=[-180, 180, -30, 30], **kwargs - ) - fig_test.grdcontour(grid=grid_, **kwargs) - return fig_ref, fig_test + + fig = Figure() + fig.grdcontour(grid=grid_, interval="1000", projection="M15c", frame=True) + return fig @pytest.mark.mpl_image_compare @@ -82,43 +74,31 @@ def test_grdcontour_file(): limit="0", pen="0.5p,black", region=[-180, 180, -70, 70], - projection="M10i", + projection="M15c", + frame=True, ) return fig -@check_figures_equal() -def test_grdcontour_interval_file_full_opts(): +@pytest.mark.mpl_image_compare +def test_grdcontour_interval_file_full_opts(grid): """ Plot based on external contour level file. """ - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - comargs_ref = { - "grid": "@earth_relief_10m", - "R": "-161.5/-154/18.5/23", - "C": TEST_CONTOUR_FILE, - "S": 100, - "J": "M6i", - "Q": 10, - } - fig_ref.grdcontour(**comargs_ref, L="-25000/-1", W=["a1p,blue", "c0.5p,blue"]) - fig_ref.grdcontour(**comargs_ref, L="0", W=["a1p,black", "c0.5p,black"]) + fig = Figure() - comargs_test = { + comargs = { "region": [-161.5, -154, 18.5, 23], "interval": TEST_CONTOUR_FILE, - "grid": "@earth_relief_10m", + "grid": grid, "resample": "100", - "projection": "M6i", + "projection": "M10c", "cut": 10, } - fig_test.grdcontour( - **comargs_test, limit=(-25000, -1), pen=["a1p,blue", "c0.5p,blue"] - ) - fig_test.grdcontour(**comargs_test, limit=0, pen=["a1p,black", "c0.5p,black"]) + fig.grdcontour(**comargs, limit=(-25000, -1), pen=["a1p,blue", "c0.5p,blue"]) + fig.grdcontour(**comargs, limit=0, pen=["a1p,black", "c0.5p,black"], frame=True) - return fig_ref, fig_test + return fig def test_grdcontour_fails(): diff --git a/pygmt/tests/test_grdfilter.py b/pygmt/tests/test_grdfilter.py index bb064327223..129f90a8c7a 100644 --- a/pygmt/tests/test_grdfilter.py +++ b/pygmt/tests/test_grdfilter.py @@ -21,7 +21,7 @@ def fixture_grid(): return load_earth_relief(registration="pixel") -def test_grfilter_dataarray_in_dataarray_out(grid): +def test_grdfilter_dataarray_in_dataarray_out(grid): """ grdfilter an input DataArray, and output as DataArray. """ @@ -32,8 +32,8 @@ def test_grfilter_dataarray_in_dataarray_out(grid): assert result.coords["lat"].data.max() == 89.5 assert result.coords["lon"].data.min() == -179.5 assert result.coords["lon"].data.max() == 179.5 - npt.assert_almost_equal(result.data.min(), -6147.47265625, decimal=2) - npt.assert_almost_equal(result.data.max(), 5164.1157, decimal=2) + npt.assert_almost_equal(result.data.min(), -6147.4907, decimal=2) + npt.assert_almost_equal(result.data.max(), 5164.06, decimal=2) assert result.sizes["lat"] == 180 assert result.sizes["lon"] == 360 @@ -47,11 +47,11 @@ def test_grdfilter_dataarray_in_file_out(grid): assert result is None # grdfilter returns None if output to a file result = grdinfo(tmpfile.name, per_column=True) assert ( - result == "-180 180 -90 90 -6147.47265625 5164.11572266 1 1 360 180 1 1\n" + result == "-180 180 -90 90 -6147.49072266 5164.06005859 1 1 360 180 1 1\n" ) -def test_grfilter_file_in_dataarray_out(): +def test_grdfilter_file_in_dataarray_out(): """ grdfilter an input grid file, and output as DataArray. """ diff --git a/pygmt/tests/test_grdtrack.py b/pygmt/tests/test_grdtrack.py index 8ed74adcd47..60c728c53cd 100644 --- a/pygmt/tests/test_grdtrack.py +++ b/pygmt/tests/test_grdtrack.py @@ -36,7 +36,7 @@ def test_grdtrack_input_dataframe_and_dataarray(dataarray): output = grdtrack(points=dataframe, grid=dataarray, newcolname="bathymetry") assert isinstance(output, pd.DataFrame) assert output.columns.to_list() == ["longitude", "latitude", "bathymetry"] - npt.assert_allclose(output.iloc[0], [-110.9536, -42.2489, -2797.394987]) + npt.assert_allclose(output.iloc[0], [-110.9536, -42.2489, -2974.656296]) return output @@ -54,7 +54,7 @@ def test_grdtrack_input_csvfile_and_dataarray(dataarray): assert os.path.exists(path=TEMP_TRACK) # check that outfile exists at path track = pd.read_csv(TEMP_TRACK, sep="\t", header=None, comment=">") - npt.assert_allclose(track.iloc[0], [-110.9536, -42.2489, -2797.394987]) + npt.assert_allclose(track.iloc[0], [-110.9536, -42.2489, -2974.656296]) finally: os.remove(path=TEMP_TRACK) @@ -132,11 +132,14 @@ def test_grdtrack_without_newcolname_setting(dataarray): grdtrack(points=dataframe, grid=dataarray) -def test_grdtrack_without_outfile_setting(dataarray): +def test_grdtrack_without_outfile_setting(): """ Run grdtrack by not passing in outfile parameter setting. """ csvfile = which("@ridge.txt", download="c") + ncfile = which("@earth_relief_01d", download="a") - with pytest.raises(GMTInvalidInput): - grdtrack(points=csvfile, grid=dataarray) + output = grdtrack(points=csvfile, grid=ncfile) + npt.assert_allclose(output.iloc[0], [-32.2971, 37.4118, -1939.748245]) + + return output diff --git a/pygmt/tests/test_helpers.py b/pygmt/tests/test_helpers.py index 5f33291798f..f2ac45c9e35 100644 --- a/pygmt/tests/test_helpers.py +++ b/pygmt/tests/test_helpers.py @@ -50,23 +50,6 @@ def test_kwargs_to_strings_fails(): kwargs_to_strings(bla="blablabla") -def test_kwargs_to_strings_no_bools(): - """ - Test that not converting bools works. - """ - - @kwargs_to_strings(convert_bools=False) - def my_module(**kwargs): - """ - Function that does nothing. - """ - return kwargs - - # The module should return the exact same arguments it was given - args = dict(P=True, A=False, R="1/2/3/4") - assert my_module(**args) == args - - def test_gmttempfile(): """ Check that file is really created and deleted. diff --git a/pygmt/tests/test_histogram.py b/pygmt/tests/test_histogram.py new file mode 100644 index 00000000000..77dd5f03807 --- /dev/null +++ b/pygmt/tests/test_histogram.py @@ -0,0 +1,31 @@ +# pylint: disable=redefined-outer-name +""" +Tests histogram. +""" +import pytest +from pygmt import Figure + + +@pytest.fixture(scope="module") +def table(): + """ + Returns a list of integers to be used in the histogram. + """ + return [1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8] + + +@pytest.mark.mpl_image_compare +def test_histogram(table): + """ + Tests plotting a histogram using a list of integers. + """ + fig = Figure() + fig.histogram( + table=table, + projection="X10c/10c", + region=[0, 9, 0, 6], + series=1, + frame="a", + fill="green", + ) + return fig diff --git a/pygmt/tests/test_info.py b/pygmt/tests/test_info.py index ab1093b29d2..b3a0b4ae78b 100644 --- a/pygmt/tests/test_info.py +++ b/pygmt/tests/test_info.py @@ -55,19 +55,13 @@ def test_info_numpy_array_time_column(): Make sure info works on a numpy.ndarray input with a datetime type. """ table = pd.date_range(start="2020-01-01", periods=5).to_numpy() - # Please remove coltypes="0T" workaround after - # https://github.com/GenericMappingTools/gmt/issues/4241 is resolved - output = info(table=table, coltypes="0T") + output = info(table=table) expected_output = ( ": N = 5 <2020-01-01T00:00:00/2020-01-05T00:00:00>\n" ) assert output == expected_output -@pytest.mark.xfail( - reason="UNIX timestamps returned instead of ISO datetime, should work on GMT 6.2.0 " - "after https://github.com/GenericMappingTools/gmt/issues/4241 is resolved", -) def test_info_pandas_dataframe_time_column(): """ Make sure info works on pandas.DataFrame inputs with a time column. @@ -85,10 +79,6 @@ def test_info_pandas_dataframe_time_column(): assert output == expected_output -@pytest.mark.xfail( - reason="UNIX timestamp returned instead of ISO datetime, should work on GMT 6.2.0 " - "after https://github.com/GenericMappingTools/gmt/issues/4241 is resolved", -) def test_info_xarray_dataset_time_column(): """ Make sure info works on xarray.Dataset 1D inputs with a time column. @@ -143,9 +133,7 @@ def test_info_per_column_with_time_inputs(): Make sure the per_column option works with time inputs. """ table = pd.date_range(start="2020-01-01", periods=5).to_numpy() - # Please remove coltypes="0T" workaround after - # https://github.com/GenericMappingTools/gmt/issues/4241 is resolved - output = info(table=table, per_column=True, coltypes="0T") + output = info(table=table, per_column=True) npt.assert_equal( actual=output, desired=["2020-01-01T00:00:00", "2020-01-05T00:00:00"] ) diff --git a/pygmt/tests/test_inset.py b/pygmt/tests/test_inset.py index 1d87b5a77f5..2891a3f744f 100644 --- a/pygmt/tests/test_inset.py +++ b/pygmt/tests/test_inset.py @@ -1,42 +1,31 @@ """ Tests for the inset function. """ +import pytest from pygmt import Figure -from pygmt.helpers.testing import check_figures_equal -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_inset_aliases(): """ Test the aliases for the inset function. """ - fig_ref, fig_test = Figure(), Figure() - fig_ref.basemap(R="MG+r2", B="afg") - with fig_ref.inset(D="jTL+w3.5c+o0.2c", M=0, F="+pgreen"): - fig_ref.basemap(R="g", J="G47/-20/4c", B="afg") + fig = Figure() + fig.basemap(region="MG+r2", frame="afg") + with fig.inset(position="jTL+w3.5c+o0.2c", margin=0, box="+pgreen"): + fig.basemap(region="g", projection="G47/-20/4c", frame="afg") + return fig - fig_test.basemap(region="MG+r2", frame="afg") - with fig_test.inset(position="jTL+w3.5c+o0.2c", margin=0, box="+pgreen"): - fig_test.basemap(region="g", projection="G47/-20/4c", frame="afg") - return fig_ref, fig_test - -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_inset_context_manager(): """ Test that the inset context manager works and, once closed, plotting elements are added to the larger figure. """ - fig_ref, fig_test = Figure(), Figure() - - fig_ref.basemap(region=[-74, -69.5, 41, 43], projection="M9c", frame=True) - fig_ref.basemap(rose="jTR+w3c") # Pass rose argument with basemap before the inset - with fig_ref.inset(position="jBL+w3c+o0.2c", margin=0, box="+pblack"): - fig_ref.basemap(region=[-80, -65, 35, 50], projection="M3c", frame="afg") - - fig_test.basemap(region=[-74, -69.5, 41, 43], projection="M9c", frame=True) - with fig_test.inset(position="jBL+w3c+o0.2c", margin=0, box="+pblack"): - fig_test.basemap(region=[-80, -65, 35, 50], projection="M3c", frame="afg") - fig_test.basemap(rose="jTR+w3c") # Pass rose argument with basemap after the inset - - return fig_ref, fig_test + fig = Figure() + fig.basemap(region=[-74, -69.5, 41, 43], projection="M9c", frame=True) + with fig.inset(position="jBL+w3c+o0.2c", margin=0, box="+pblack"): + fig.basemap(region=[-80, -65, 35, 50], projection="M3c", frame="afg") + fig.basemap(rose="jTR+w3c") # Pass rose argument with basemap after the inset + return fig diff --git a/pygmt/tests/test_legend.py b/pygmt/tests/test_legend.py index 8e269b62382..7bd2f00948a 100644 --- a/pygmt/tests/test_legend.py +++ b/pygmt/tests/test_legend.py @@ -10,27 +10,22 @@ @pytest.mark.mpl_image_compare def test_legend_position(): """ - Try positioning with each of the four legend coordinate systems. + Test that plots a position with each of the four legend coordinate systems. """ fig = Figure() - fig.basemap(region=[-2, 2, -2, 2], frame=True) - positions = ["jTR+jTR", "g0/1", "n0.2/0.2", "x4i/2i/2i"] - for i, position in enumerate(positions): - fig.plot(x=[0], y=[0], style="p10p", label=i) fig.legend(position=position, box=True) - return fig @pytest.mark.mpl_image_compare def test_legend_default_position(): """ - Try using the default legend position. + Test using the default legend position. """ fig = Figure() @@ -98,15 +93,11 @@ def test_legend_specfile(): """ with GMTTempFile() as specfile: - with open(specfile.name, "w") as file: file.write(specfile_contents) - fig = Figure() - fig.basemap(projection="x6i", region=[0, 1, 0, 1], frame=True) fig.legend(specfile.name, position="JTM+jCM+w5i") - return fig diff --git a/pygmt/tests/test_makecpt.py b/pygmt/tests/test_makecpt.py index 0cb8517ceb5..173cbe315bf 100644 --- a/pygmt/tests/test_makecpt.py +++ b/pygmt/tests/test_makecpt.py @@ -9,7 +9,6 @@ from pygmt.datasets import load_earth_relief from pygmt.exceptions import GMTInvalidInput from pygmt.helpers import GMTTempFile -from pygmt.helpers.testing import check_figures_equal TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data") POINTS_DATA = os.path.join(TEST_DATA_DIR, "points.txt") @@ -40,7 +39,7 @@ def fixture_grid(): @pytest.mark.mpl_image_compare -def test_makecpt_to_plot_points(points, region): +def test_makecpt_plot_points(points, region): """ Use static color palette table to change color of points. """ @@ -58,34 +57,29 @@ def test_makecpt_to_plot_points(points, region): @pytest.mark.mpl_image_compare -def test_makecpt_to_plot_grid(grid): +def test_makecpt_plot_grid(grid): """ Use static color palette table to change color of grid. """ fig = Figure() makecpt(cmap="relief") - fig.grdimage(grid, projection="W0/6i") + fig.grdimage(grid, projection="W0/10c") return fig -@check_figures_equal() -def test_makecpt_to_plot_grid_scaled_with_series(grid): +@pytest.mark.mpl_image_compare +def test_makecpt_plot_grid_scaled_with_series(grid): """ Use static color palette table scaled to a min/max series to change color of grid. """ - # Use single-character arguments for the reference image - fig_ref = Figure() - makecpt(C="oleron", T="-4500/4500") - fig_ref.grdimage(grid, J="W0/6i") - - fig_test = Figure() - makecpt(cmap="oleron", series="-4500/4500") - fig_test.grdimage(grid, projection="W0/6i") - return fig_ref, fig_test + fig = Figure() + makecpt(cmap="oleron", series=[-4500, 4500]) + fig.grdimage(grid, projection="W0/10c") + return fig -def test_makecpt_output_to_cpt_file(): +def test_makecpt_output_cpt_file(): """ Save the generated static color palette table to a .cpt file. """ @@ -111,35 +105,13 @@ def test_makecpt_invalid_output(): @pytest.mark.mpl_image_compare -def test_makecpt_truncated_to_zlow_zhigh(grid): +def test_makecpt_truncated_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") + fig.grdimage(grid, projection="W0/10c") return fig @@ -150,18 +122,7 @@ def test_makecpt_reverse_color_only(grid): """ 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") + fig.grdimage(grid, projection="W0/10c") return fig @@ -173,7 +134,7 @@ def test_makecpt_reverse_color_and_zsign(grid): """ fig = Figure() makecpt(cmap="earth", reverse="cz") - fig.grdimage(grid, projection="W0/6i") + fig.grdimage(grid, projection="W0/10c") return fig @@ -184,39 +145,39 @@ def test_makecpt_continuous(grid): scaled from -4500 to 4500m. """ fig = Figure() - makecpt(cmap="blue,white", continuous=True, series="-4500,4500") - fig.grdimage(grid, projection="W0/6i") + makecpt(cmap="blue,white", continuous=True, series=[-4500, 4500]) + fig.grdimage(grid, projection="W0/10c") return fig -@check_figures_equal() +@pytest.mark.xfail( + reason="Flaky test only passes with pytest on single module" + "See https://github.com/GenericMappingTools/pygmt/issues/1242" +) +@pytest.mark.mpl_image_compare def test_makecpt_categorical(region): """ Use static color palette table that is categorical. """ - fig_ref = Figure() - makecpt(C="categorical", W="") - fig_ref.colorbar(cmap=True, region=region, frame=True, position="JBC") - - fig_test = Figure() + fig = Figure() makecpt(cmap="categorical", categorical=True) - fig_test.colorbar(cmap=True, region=region, frame=True, position="JBC") - return fig_ref, fig_test + fig.colorbar(cmap=True, region=region, frame=True, position="JBC") + return fig -@check_figures_equal() +@pytest.mark.xfail( + reason="Flaky test only passes with pytest on single module" + "See https://github.com/GenericMappingTools/pygmt/issues/1242" +) +@pytest.mark.mpl_image_compare def test_makecpt_cyclic(region): """ Use static color palette table that is cyclic. """ - fig_ref = Figure() - makecpt(C="cork", W="w") - fig_ref.colorbar(cmap=True, region=region, frame=True, position="JBC") - - fig_test = Figure() + fig = Figure() makecpt(cmap="cork", cyclic=True) - fig_test.colorbar(cmap=True, region=region, frame=True, position="JBC") - return fig_ref, fig_test + fig.colorbar(cmap=True, region=region, frame=True, position="JBC") + return fig def test_makecpt_categorical_and_cyclic(): diff --git a/pygmt/tests/test_meca.py b/pygmt/tests/test_meca.py index 24715cd92a2..400ef37570d 100644 --- a/pygmt/tests/test_meca.py +++ b/pygmt/tests/test_meca.py @@ -15,12 +15,10 @@ @pytest.mark.mpl_image_compare def test_meca_spec_dictionary(): """ - Test supplying a dictionary containing a single focal mechanism to the - `spec` argument. + Test supplying a dictionary containing a single focal mechanism to the spec + parameter. """ - fig = Figure() - # Right lateral strike slip focal mechanism fig.meca( dict(strike=0, dip=90, rake=0, magnitude=5), @@ -32,7 +30,6 @@ def test_meca_spec_dictionary(): projection="M14c", frame=2, ) - return fig @@ -40,16 +37,13 @@ def test_meca_spec_dictionary(): def test_meca_spec_dict_list(): """ Test supplying a dictionary containing a list of focal mechanism to the - `spec` argument. + spec parameter. """ - fig = Figure() - # supply focal mechanisms as a dict of lists focal_mechanisms = dict( strike=[330, 350], dip=[30, 50], rake=[90, 90], magnitude=[3, 2] ) - fig.meca( focal_mechanisms, longitude=[-124.3, -124.4], @@ -59,15 +53,14 @@ def test_meca_spec_dict_list(): scale="2c", projection="M14c", ) - return fig @pytest.mark.mpl_image_compare def test_meca_spec_dataframe(): """ - Test supplying a pandas DataFrame containing focal mechanisms and locations - to the `spec` argument. + Test supplying a pandas.DataFrame containing focal mechanisms and locations + to the spec parameter. """ fig = Figure() @@ -83,9 +76,7 @@ def test_meca_spec_dataframe(): depth=[12, 11.0], ) spec_dataframe = pd.DataFrame(data=focal_mechanisms) - fig.meca(spec_dataframe, region=[-125, -122, 47, 49], scale="2c", projection="M14c") - return fig @@ -93,11 +84,9 @@ def test_meca_spec_dataframe(): def test_meca_spec_1d_array(): """ Test supplying a 1D numpy array containing focal mechanisms and locations - to the `spec` argument. + to the spec parameter. """ - fig = Figure() - # supply focal mechanisms to meca as a 1D numpy array, here we are using # the Harvard CMT zero trace convention but the focal mechanism # parameters may be specified any of the available conventions. Since we @@ -118,7 +107,6 @@ def test_meca_spec_1d_array(): 0, # plot_lat, 0 to plot at event location ] focal_mech_array = np.asarray(focal_mechanism) - fig.meca( focal_mech_array, convention="mt", @@ -127,7 +115,6 @@ def test_meca_spec_1d_array(): scale="2c", projection="M14c", ) - return fig @@ -135,11 +122,9 @@ def test_meca_spec_1d_array(): def test_meca_spec_2d_array(): """ Test supplying a 2D numpy array containing focal mechanisms and locations - to the `spec` argument. + to the spec parameter. """ - fig = Figure() - # supply focal mechanisms to meca as a 2D numpy array, here we are using # the GCMT convention but the focal mechanism parameters may be # specified any of the available conventions. Since we are not using a @@ -163,7 +148,6 @@ def test_meca_spec_2d_array(): [-127.50, 40.88, 12.0, 168, 40, -115, 20, 54, -70, 4.0, 23, 0, 0], ] focal_mechs_array = np.asarray(focal_mechanisms) - fig.meca( focal_mechs_array, convention="gcmt", @@ -171,21 +155,18 @@ def test_meca_spec_2d_array(): scale="2c", projection="M14c", ) - return fig @pytest.mark.mpl_image_compare def test_meca_spec_file(): """ - Test supplying a file containing focal mechanisms and locations to the - `spec` argument. + Test supplying a file containing focal mechanisms and locations to the spec + parameter. """ fig = Figure() - focal_mechanism = [-127.43, 40.81, 12, -3.19, 1.16, 3.93, -1.02, -3.93, -1.02, 23] - # writes temp file to pass to gmt with GMTTempFile() as temp: with open(temp.name, mode="w") as temp_file: @@ -199,7 +180,6 @@ def test_meca_spec_file(): scale="2c", projection="M14c", ) - return fig @@ -209,22 +189,17 @@ def test_meca_loc_array(): Test supplying lists and np.ndarrays as the event location (longitude, latitude, and depth). """ - fig = Figure() - # specify focal mechanisms focal_mechanisms = dict( strike=[327, 350], dip=[41, 50], rake=[68, 90], magnitude=[3, 2] ) - # longitude, latitude, and depth may be specified as an int, float, # list, or 1d numpy array longitude = np.array([-123.3, -124.4]) latitude = np.array([48.4, 48.2]) depth = [12.0, 11.0] # to test mixed data types as inputs - scale = "2c" - fig.meca( focal_mechanisms, scale, @@ -234,5 +209,4 @@ def test_meca_loc_array(): region=[-125, -122, 47, 49], projection="M14c", ) - return fig diff --git a/pygmt/tests/test_plot.py b/pygmt/tests/test_plot.py index 7f50fc75219..2fff587d292 100644 --- a/pygmt/tests/test_plot.py +++ b/pygmt/tests/test_plot.py @@ -93,7 +93,7 @@ def test_plot_fail_no_data(data): def test_plot_fail_color_size_intensity(data): """ - Should raise an exception if array color, sizes and intensity are used with + Should raise an exception if array color, size and intensity are used with matrix. """ fig = Figure() @@ -101,7 +101,7 @@ def test_plot_fail_color_size_intensity(data): with pytest.raises(GMTInvalidInput): fig.plot(style="c0.2c", color=data[:, 2], **kwargs) with pytest.raises(GMTInvalidInput): - fig.plot(style="cc", sizes=data[:, 2], color="red", **kwargs) + fig.plot(style="cc", size=data[:, 2], color="red", **kwargs) with pytest.raises(GMTInvalidInput): fig.plot(style="c0.2c", color="red", intensity=data[:, 2], **kwargs) @@ -152,7 +152,7 @@ def test_plot_sizes(data, region): fig.plot( x=data[:, 0], y=data[:, 1], - sizes=0.5 * data[:, 2], + size=0.5 * data[:, 2], region=region, projection="X10c", style="cc", @@ -172,7 +172,7 @@ def test_plot_colors_sizes(data, region): x=data[:, 0], y=data[:, 1], color=data[:, 2], - sizes=0.5 * data[:, 2], + size=0.5 * data[:, 2], region=region, projection="X10c", style="cc", @@ -193,7 +193,7 @@ def test_plot_colors_sizes_proj(data, region): x=data[:, 0], y=data[:, 1], color=data[:, 2], - sizes=0.5 * data[:, 2], + size=0.5 * data[:, 2], style="cc", cmap="copper", ) @@ -288,7 +288,7 @@ def test_plot_sizes_colors_transparencies(): frame=True, style="cc", color=color, - sizes=size, + size=size, cmap="gray", transparency=transparency, ) @@ -446,3 +446,27 @@ def test_plot_datetime(): y = [8.5, 9.5] fig.plot(x, y, style="i0.2c", pen="1p") return fig + + +@pytest.mark.mpl_image_compare(filename="test_plot_sizes.png") +def test_plot_deprecate_sizes_to_size(data, region): + """ + Make sure that the old parameter "sizes" is supported and it reports an + warning. + + Modified from the test_plot_sizes() test. + """ + fig = Figure() + with pytest.warns(expected_warning=FutureWarning) as record: + fig.plot( + x=data[:, 0], + y=data[:, 1], + sizes=0.5 * data[:, 2], + region=region, + projection="X10c", + style="cc", + color="blue", + frame="af", + ) + assert len(record) == 1 # check that only one warning was raised + return fig diff --git a/pygmt/tests/test_plot3d.py b/pygmt/tests/test_plot3d.py index 11ba0707897..05708f7f67a 100644 --- a/pygmt/tests/test_plot3d.py +++ b/pygmt/tests/test_plot3d.py @@ -7,8 +7,6 @@ import pytest from pygmt import Figure from pygmt.exceptions import GMTInvalidInput -from pygmt.helpers import GMTTempFile -from pygmt.helpers.testing import check_figures_equal TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data") POINTS_DATA = os.path.join(TEST_DATA_DIR, "points.txt") @@ -30,62 +28,42 @@ def fixture_region(): return [10, 70, -5, 10, 0, 1] -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_red_circles_zscale(data, region): "Plot the 3D data in red circles passing in vectors and setting zscale = 5" - fig_ref, fig_test = Figure(), Figure() - fig_ref.plot3d( - data=POINTS_DATA, - Jz=5, - p="225/30", - R="/".join(map(str, region)), - J="X4i", - S="c0.2c", - G="red", - B=["afg", "zafg"], - ) - fig_test.plot3d( + fig = Figure() + fig.plot3d( x=data[:, 0], y=data[:, 1], z=data[:, 2], zscale=5, perspective=[225, 30], region=region, - projection="X4i", + projection="X10c", style="c0.2c", color="red", frame=["afg", "zafg"], ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_red_circles_zsize(data, region): - "Plot the 3D data in red circles passing in vectors and setting zsize = 3i" - fig_ref, fig_test = Figure(), Figure() - fig_ref.plot3d( - data=POINTS_DATA, - JZ="3i", - p="225/30", - R="/".join(map(str, region)), - J="X4i", - S="c0.2c", - G="red", - B=["afg", "zafg"], - ) - fig_test.plot3d( + "Plot the 3D data in red circles passing in vectors and setting zsize = 6c" + fig = Figure() + fig.plot3d( x=data[:, 0], y=data[:, 1], z=data[:, 2], - zsize="3i", + zsize="6c", perspective=[225, 30], region=region, - projection="X4i", + projection="X10c", style="c0.2c", color="red", frame=["afg", "zafg"], ) - return fig_ref, fig_test + return fig def test_plot3d_fail_no_data(data, region): @@ -95,13 +73,13 @@ def test_plot3d_fail_no_data(data, region): fig = Figure() with pytest.raises(GMTInvalidInput): fig.plot3d( - region=region, projection="X4i", style="c0.2c", color="red", frame="afg" + region=region, projection="X10c", style="c0.2c", color="red", frame="afg" ) with pytest.raises(GMTInvalidInput): fig.plot3d( x=data[:, 0], region=region, - projection="X4i", + projection="X10c", style="c0.2c", color="red", frame="afg", @@ -110,7 +88,7 @@ def test_plot3d_fail_no_data(data, region): fig.plot3d( y=data[:, 0], region=region, - projection="X4i", + projection="X10c", style="c0.2c", color="red", frame="afg", @@ -123,7 +101,7 @@ def test_plot3d_fail_no_data(data, region): z=data[:, 2], data=data, region=region, - projection="X4i", + projection="X10c", style="c0.2c", color="red", frame="afg", @@ -132,7 +110,7 @@ def test_plot3d_fail_no_data(data, region): def test_plot3d_fail_color_size_intensity(data, region): """ - Should raise an exception if array color, sizes and intensity are used with + Should raise an exception if array color, size and intensity are used with matrix. """ fig = Figure() @@ -140,61 +118,39 @@ def test_plot3d_fail_color_size_intensity(data, region): with pytest.raises(GMTInvalidInput): fig.plot3d(style="c0.2c", color=data[:, 2], **kwargs) with pytest.raises(GMTInvalidInput): - fig.plot3d(style="cc", sizes=data[:, 2], color="red", **kwargs) + fig.plot3d(style="cc", size=data[:, 2], color="red", **kwargs) with pytest.raises(GMTInvalidInput): fig.plot3d(style="cc", intensity=data[:, 2], color="red", **kwargs) -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_projection(data, region): """ Plot the data in green squares with a projection. """ - fig_ref, fig_test = Figure(), Figure() - fig_ref.plot3d( - data=POINTS_DATA, - Jz=5, - p="225/30", - R="/".join(map(str, region)), - J="R270/4i", - S="s1c", - G="green", - B=["ag", "zag"], - ) - fig_test.plot3d( + fig = Figure() + fig.plot3d( x=data[:, 0], y=data[:, 1], z=data[:, 2], zscale=5, perspective=[225, 30], region=region, - projection="R270/4i", + projection="R270/10c", style="s1c", color="green", frame=["ag", "zag"], ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_colors(data, region): """ Plot the data using z as colors. """ - fig_ref, fig_test = Figure(), Figure() - fig_ref.plot3d( - data=POINTS_DATA, - Jz=5, - p="225/30", - G="+z", - R="/".join(map(str, region)), - J="X3i", - S="c0.5c", - C="cubhelix", - B=["afg", "zafg"], - i="0,1,2,2", - ) - fig_test.plot3d( + fig = Figure() + fig.plot3d( x=data[:, 0], y=data[:, 1], z=data[:, 2], @@ -202,120 +158,86 @@ def test_plot3d_colors(data, region): perspective=[225, 30], color=data[:, 2], region=region, - projection="X3i", + projection="X6c", style="c0.5c", cmap="cubhelix", frame=["afg", "zafg"], ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_sizes(data, region): """ Plot the data using z as sizes. """ - fig_ref, fig_test = Figure(), Figure() - fig_ref.plot3d( - data=POINTS_DATA, - Jz=5, - p="225/30", - i="0,1,2,2+s0.5", - R="/".join(map(str, region)), - J="X4i", - S="ui", - G="blue", - B=["af", "zaf"], - ) - fig_test.plot3d( + fig = Figure() + fig.plot3d( x=data[:, 0], y=data[:, 1], z=data[:, 2], zscale=5, perspective=[225, 30], - sizes=0.5 * data[:, 2], + size=0.5 * data[:, 2], region=region, - projection="X4i", + projection="X10c", # Using inches instead of cm because of upstream bug at # https://github.com/GenericMappingTools/gmt/issues/4386 style="ui", color="blue", frame=["af", "zaf"], ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_colors_sizes(data, region): """ Plot the data using z as sizes and colors. """ - fig_ref, fig_test = Figure(), Figure() - fig_ref.plot3d( - data=POINTS_DATA, - Jz=5, - p="225/30", - i="0,1,2,2,2+s0.5", - R="/".join(map(str, region)), - J="X3i", - S="ui", - C="copper", - B=["af", "zaf"], - ) - fig_test.plot3d( + fig = Figure() + fig.plot3d( x=data[:, 0], y=data[:, 1], z=data[:, 2], zscale=5, perspective=[225, 30], color=data[:, 2], - sizes=0.5 * data[:, 2], + size=0.5 * data[:, 2], region=region, - projection="X3i", + projection="X6c", # Using inches instead of cm because of upstream bug at # https://github.com/GenericMappingTools/gmt/issues/4386 style="ui", cmap="copper", frame=["af", "zaf"], ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_colors_sizes_proj(data, region): """ Plot the data using z as sizes and colors with a projection. """ - fig_ref, fig_test = Figure(), Figure() - fig_ref.plot3d( - data=POINTS_DATA, - Jz=5, - p="225/30", - R="/".join(map(str, region)), - J="M10i", - B=["af", "zaf"], - G="+z", - i="0,1,2,2,2+s1", - S="ui", - C="copper", - ) - fig_test.plot3d( + fig = Figure() + fig.plot3d( x=data[:, 0], y=data[:, 1], z=data[:, 2], zscale=5, perspective=[225, 30], region=region, - projection="M10i", + projection="M20c", frame=["af", "zaf"], color=data[:, 2], - sizes=data[:, 2], + size=data[:, 2], # Using inches instead of cm because of upstream bug at # https://github.com/GenericMappingTools/gmt/issues/4386 style="ui", cmap="copper", ) - return fig_ref, fig_test + return fig @pytest.mark.mpl_image_compare @@ -345,7 +267,7 @@ def test_plot3d_varying_intensity(): return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_transparency(): """ Plot the data with a constant transparency. @@ -354,39 +276,24 @@ def test_plot3d_transparency(): y = np.arange(1, 10) z = np.arange(1, 10) * 10 - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - with GMTTempFile() as tmpfile: - np.savetxt(tmpfile.name, np.c_[x, y, z], fmt="%d") - fig_ref.plot3d( - data=tmpfile.name, - S="u0.2c", - G="blue", - R="0/10/0/10/10/90", - J="X4i", - Jz=0.1, - B="", - p="135/30", - t=80.0, - ) - - fig_test.plot3d( + fig = Figure() + fig.plot3d( x=x, y=y, z=z, style="u0.2c", color="blue", region=[0, 10, 0, 10, 10, 90], - projection="X4i", + projection="X10c", zscale=0.1, frame=True, perspective=[135, 30], transparency=80.0, ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_varying_transparency(): """ Plot the data using z as transparency using 3-D column symbols. @@ -395,38 +302,24 @@ def test_plot3d_varying_transparency(): y = np.arange(1, 10) z = np.arange(1, 10) * 10 - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - with GMTTempFile() as tmpfile: - np.savetxt(tmpfile.name, np.c_[x, y, z, z, z], fmt="%d") - fig_ref.plot3d( - data=tmpfile.name, - S="o0.2c+B5", - G="blue", - R="0/10/0/10/10/90", - J="X4i", - Jz=0.1, - B="", - p="135/30", - t="", - ) - fig_test.plot3d( + fig = Figure() + fig.plot3d( x=x, y=y, z=z, style="o0.2c+B5", color="blue", region=[0, 10, 0, 10, 10, 90], - projection="X4i", + projection="X10c", zscale=0.1, frame=True, perspective=[135, 30], transparency=z, ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_sizes_colors_transparencies(): """ Plot the data with varying sizes and colors using z as transparency. @@ -438,133 +331,86 @@ def test_plot3d_sizes_colors_transparencies(): size = np.arange(1, 10) * 0.2 transparency = np.arange(1, 10) * 10 - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - with GMTTempFile() as tmpfile: - np.savetxt(tmpfile.name, np.c_[x, y, z, color, size, transparency]) - fig_ref.plot3d( - data=tmpfile.name, - R="0/10/0/10/10/90", - J="X4i", - Jz=0.1, - p="135/30", - B="", - S="uc", - C="gray", - t="", - ) - fig_test.plot3d( + fig = Figure() + fig.plot3d( x=x, y=y, z=z, region=[0, 10, 0, 10, 10, 90], - projection="X4i", + projection="X10c", zscale=0.1, perspective=[135, 30], frame=True, style="uc", color=color, - sizes=size, + size=size, cmap="gray", transparency=transparency, ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_matrix(data, region): """ Plot the data passing in a matrix and specifying columns. """ - fig_ref, fig_test = Figure(), Figure() - fig_ref.plot3d( - data=POINTS_DATA, - Jz=5, - p="225/30", - R="/".join(map(str, region)), - J="M10i", - S="c1c", - G="#aaaaaa", - B=["a", "za"], - i="0,1,2", - ) - fig_test.plot3d( + fig = Figure() + fig.plot3d( data=data, zscale=5, perspective=[225, 30], region=region, - projection="M10i", + projection="M20c", style="c1c", color="#aaaaaa", frame=["a", "za"], columns="0,1,2", ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_matrix_color(data, region): """ Plot the data passing in a matrix and using a colormap. """ - fig_ref, fig_test = Figure(), Figure() - fig_ref.plot3d( - data=POINTS_DATA, - Jz=5, - p="225/30", - R="/".join(map(str, region)), - J="X5i", - S="c0.5c", - C="rainbow", - i="0,1,2,2", - B=["a", "za"], - ) - fig_test.plot3d( + fig = Figure() + fig.plot3d( data=data, zscale=5, perspective=[225, 30], region=region, - projection="X5i", + projection="X10c", style="c0.5c", cmap="rainbow", columns=[0, 1, 2, 2], frame=["a", "za"], ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_from_file(region): """ Plot using the data file name instead of loaded data. """ - fig_ref, fig_test = Figure(), Figure() - fig_ref.plot3d( - data=POINTS_DATA, - Jz=5, - p="225/30", - R="/".join(map(str, region)), - J="X10i", - S="d1c", - G="yellow", - B=["af", "zaf"], - i="0,1,2", - ) - fig_test.plot3d( + fig = Figure() + fig.plot3d( data=POINTS_DATA, zscale=5, perspective=[225, 30], region=region, - projection="X10i", + projection="X20c", style="d1c", color="yellow", frame=["af", "zaf"], columns=[0, 1, 2], ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_vectors(): """ Plot vectors. @@ -574,20 +420,9 @@ def test_plot3d_vectors(): lon = np.sin(np.deg2rad(azimuth)) lat = np.cos(np.deg2rad(azimuth)) elev = np.tan(np.deg2rad(azimuth)) - fig_ref, fig_test = Figure(), Figure() - with GMTTempFile() as tmpfile: - np.savetxt(tmpfile.name, np.c_[lon, lat, elev, azimuth, lengths]) - fig_ref.plot3d( - data=tmpfile.name, - Jz=2, - p="225/30", - R="-2/2/-2/2/-2/2", - J="X4i", - S="V1c+e", - G="black", - B=["af", "zaf"], - ) - fig_test.plot3d( + + fig = Figure() + fig.plot3d( x=lon, y=lat, z=elev, @@ -595,42 +430,58 @@ def test_plot3d_vectors(): perspective=[225, 30], direction=(azimuth, lengths), region=[-2, 2, -2, 2, -2, 2], - projection="X4i", + projection="X10c", style="V1c+e", color="black", frame=["af", "zaf"], ) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_plot3d_scalar_xyz(): """ Plot symbols given scalar x, y, z coordinates. """ - fig_ref, fig_test = Figure(), Figure() - with GMTTempFile() as tmpfile: - np.savetxt(tmpfile.name, np.c_[[-1.5, 0, 1.5], [1.5, 0, -1.5], [-1.5, 0, 1.5]]) - fig_ref.basemap( - R="-2/2/-2/2/-2/2", B=["xaf+lx", "yaf+ly", "zaf+lz"], Jz=2, p="225/30" - ) - fig_ref.plot3d(data=tmpfile.name, S="c1c", G="red", Jz="", p="", qi=0) - fig_ref.plot3d(data=tmpfile.name, S="t1c", G="green", Jz="", p="", qi=1) - fig_ref.plot3d(data=tmpfile.name, S="s1c", G="blue", Jz="", p="", qi=2) - - fig_test.basemap( + fig = Figure() + fig.basemap( region=[-2, 2, -2, 2, -2, 2], frame=["xaf+lx", "yaf+ly", "zaf+lz"], zscale=2, perspective=[225, 30], ) - fig_test.plot3d( + fig.plot3d( x=-1.5, y=1.5, z=-1.5, style="c1c", color="red", zscale=True, perspective=True ) - fig_test.plot3d( - x=0, y=0, z=0, style="t1c", color="green", zscale=True, perspective=True - ) - fig_test.plot3d( + fig.plot3d(x=0, y=0, z=0, style="t1c", color="green", zscale=True, perspective=True) + fig.plot3d( x=1.5, y=-1.5, z=1.5, style="s1c", color="blue", zscale=True, perspective=True ) - return fig_ref, fig_test + return fig + + +@pytest.mark.mpl_image_compare(filename="test_plot3d_sizes.png") +def test_plot3d_deprecate_sizes_to_size(data, region): + """ + Make sure that the old parameter "sizes" is supported and it reports an + warning. + + Modified from the test_plot3d_sizes() test. + """ + fig = Figure() + with pytest.warns(expected_warning=FutureWarning) as record: + fig.plot3d( + x=data[:, 0], + y=data[:, 1], + z=data[:, 2], + zscale=5, + perspective=[225, 30], + sizes=0.5 * data[:, 2], + region=region, + projection="X10c", + style="ui", + color="blue", + frame=["af", "zaf"], + ) + assert len(record) == 1 # check that only one warning was raised + return fig diff --git a/pygmt/tests/test_solar.py b/pygmt/tests/test_solar.py index d487dc30fc3..043f1ee9053 100644 --- a/pygmt/tests/test_solar.py +++ b/pygmt/tests/test_solar.py @@ -8,6 +8,10 @@ from pygmt.exceptions import GMTInvalidInput +@pytest.mark.xfail( + reason="Flaky test only passes with pytest on single module" + "See https://github.com/GenericMappingTools/pygmt/issues/1242" +) @pytest.mark.mpl_image_compare def test_solar_terminators(): """ @@ -39,6 +43,10 @@ def test_solar_terminators(): return fig +@pytest.mark.xfail( + reason="Flaky test only passes with pytest on single module" + "See https://github.com/GenericMappingTools/pygmt/issues/1242" +) @pytest.mark.mpl_image_compare(filename="test_solar_set_terminator_datetime.png") @pytest.mark.parametrize( "terminator_datetime", @@ -104,6 +112,10 @@ def test_invalid_datetime(): ) +@pytest.mark.xfail( + reason="Flaky test only passes with pytest on single module" + "See https://github.com/GenericMappingTools/pygmt/issues/1242" +) @pytest.mark.mpl_image_compare(filename="test_solar_set_terminator_datetime.png") def test_solar_default_terminator(): """ diff --git a/pygmt/tests/test_subplot.py b/pygmt/tests/test_subplot.py index 44d78a6aa9d..2afd071391d 100644 --- a/pygmt/tests/test_subplot.py +++ b/pygmt/tests/test_subplot.py @@ -4,89 +4,81 @@ import pytest from pygmt import Figure from pygmt.exceptions import GMTInvalidInput -from pygmt.helpers.testing import check_figures_equal -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_subplot_basic_frame(): """ Create a subplot figure with 1 vertical row and 2 horizontal columns, and ensure map frame setting is applied to all subplot figures. """ - fig_ref, fig_test = Figure(), Figure() - with fig_ref.subplot(nrows=1, ncols=2, Ff="6c/3c", B="WSne"): - with fig_ref.set_panel(panel=0): - fig_ref.basemap(region=[0, 3, 0, 3], frame="+tplot0") - with fig_ref.set_panel(panel=1): - fig_ref.basemap(region=[0, 3, 0, 3], frame="+tplot1") - with fig_test.subplot(nrows=1, ncols=2, figsize=("6c", "3c"), frame="WSne"): - with fig_test.set_panel(panel="0,0"): - fig_test.basemap(region=[0, 3, 0, 3], frame="+tplot0") - with fig_test.set_panel(panel=[0, 1]): - fig_test.basemap(region=[0, 3, 0, 3], frame="+tplot1") - return fig_ref, fig_test - - -@check_figures_equal() + fig = Figure() + + with fig.subplot(nrows=1, ncols=2, figsize=("6c", "3c"), frame="WSne"): + with fig.set_panel(panel="0,0"): + fig.basemap(region=[0, 3, 0, 3], frame="+tplot0") + with fig.set_panel(panel=[0, 1]): + fig.basemap(region=[0, 3, 0, 3], frame="+tplot1") + return fig + + +@pytest.mark.mpl_image_compare def test_subplot_direct(): """ Plot map elements to subplot directly using the panel parameter. """ - fig_ref, fig_test = Figure(), Figure() - with fig_ref.subplot(nrows=2, ncols=1, Fs="3c/3c"): - fig_ref.basemap(region=[0, 3, 0, 3], frame="af", panel=0) - fig_ref.basemap(region=[0, 3, 0, 3], frame="af", panel=1) - with fig_test.subplot(nrows=2, ncols=1, subsize=("3c", "3c")): - fig_test.basemap(region=[0, 3, 0, 3], frame="af", panel=[0, 0]) - fig_test.basemap(region=[0, 3, 0, 3], frame="af", panel=[1, 0]) - return fig_ref, fig_test + fig = Figure() + with fig.subplot(nrows=2, ncols=1, subsize=("3c", "3c")): + fig.basemap(region=[0, 3, 0, 3], frame="af", panel=[0, 0]) + fig.basemap(region=[0, 3, 0, 3], frame="af", panel=[1, 0]) + return fig -@check_figures_equal() + +@pytest.mark.mpl_image_compare def test_subplot_autolabel_margins_title(): """ Make subplot figure with autolabels, setting some margins and a title. """ - fig_ref, fig_test = Figure(), Figure() - kwargs = dict(nrows=2, ncols=1, figsize=("15c", "6c")) - - with fig_ref.subplot(A="a)", M="0.3c/0.1c", T="Subplot Title", **kwargs): - fig_ref.basemap(region=[0, 1, 2, 3], frame="WSne", c="0,0") - fig_ref.basemap(region=[4, 5, 6, 7], frame="WSne", c="1,0") + fig = Figure() - with fig_test.subplot( - autolabel=True, margins=["0.3c", "0.1c"], title="Subplot Title", **kwargs + with fig.subplot( + nrows=2, + ncols=1, + figsize=("15c", "6c"), + autolabel=True, + margins=["0.3c", "0.1c"], + title="Subplot Title", ): - fig_test.basemap(region=[0, 1, 2, 3], frame="WSne", panel=[0, 0]) - fig_test.basemap(region=[4, 5, 6, 7], frame="WSne", panel=[1, 0]) + fig.basemap(region=[0, 1, 2, 3], frame="WSne", panel=[0, 0]) + fig.basemap(region=[4, 5, 6, 7], frame="WSne", panel=[1, 0]) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_subplot_clearance_and_shared_xy_axis_layout(): """ Ensure subplot clearance works, and that the layout can be set to use shared X and Y axis labels across columns and rows. """ - fig_ref, fig_test = Figure(), Figure() - kwargs = dict(nrows=2, ncols=2, frame="WSrt", figsize=("5c", "5c")) - - with fig_ref.subplot(C="y0.2c", SC="t", SR="", **kwargs): - fig_ref.basemap(region=[0, 4, 0, 4], projection="X?", panel=True) - fig_ref.basemap(region=[0, 8, 0, 4], projection="X?", panel=True) - fig_ref.basemap(region=[0, 4, 0, 8], projection="X?", panel=True) - fig_ref.basemap(region=[0, 8, 0, 8], projection="X?", panel=True) + fig = Figure() - with fig_test.subplot( - clearance=["s0.2c", "n0.2c"], sharex="t", sharey=True, **kwargs + with fig.subplot( + nrows=2, + ncols=2, + figsize=("5c", "5c"), + frame="WSrt", + clearance=["s0.2c", "n0.2c"], + sharex="t", + sharey=True, ): - fig_test.basemap(region=[0, 4, 0, 4], projection="X?", panel=True) - fig_test.basemap(region=[0, 8, 0, 4], projection="X?", panel=True) - fig_test.basemap(region=[0, 4, 0, 8], projection="X?", panel=True) - fig_test.basemap(region=[0, 8, 0, 8], projection="X?", panel=True) + fig.basemap(region=[0, 4, 0, 4], projection="X?", panel=True) + fig.basemap(region=[0, 8, 0, 4], projection="X?", panel=True) + fig.basemap(region=[0, 4, 0, 8], projection="X?", panel=True) + fig.basemap(region=[0, 8, 0, 8], projection="X?", panel=True) - return fig_ref, fig_test + return fig def test_subplot_figsize_and_subsize_error(): diff --git a/pygmt/tests/test_text.py b/pygmt/tests/test_text.py index 8c3305c5267..fd6817f11ec 100644 --- a/pygmt/tests/test_text.py +++ b/pygmt/tests/test_text.py @@ -9,7 +9,6 @@ from pygmt import Figure from pygmt.exceptions import GMTCLibError, GMTInvalidInput from pygmt.helpers import GMTTempFile -from pygmt.helpers.testing import check_figures_equal TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data") POINTS_DATA = os.path.join(TEST_DATA_DIR, "points.txt") @@ -21,7 +20,7 @@ def projection(): """ The projection system. """ - return "x4i" + return "x10c" @pytest.fixture(scope="module") @@ -304,7 +303,7 @@ def test_text_angle_font_justify_from_textfile(): return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_text_transparency(): """ Add texts with a constant transparency. @@ -313,20 +312,15 @@ def test_text_transparency(): y = np.arange(11, 20) text = [f"TEXT-{i}-{j}" for i, j in zip(x, y)] - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - with GMTTempFile() as tmpfile: - np.savetxt(tmpfile.name, np.c_[x, y, text], fmt="%s") - fig_ref.basemap(R="0/10/10/20", J="X10c", B="") - fig_ref.text(textfiles=tmpfile.name, t=50) + fig = Figure() - fig_test.basemap(region=[0, 10, 10, 20], projection="X10c", frame=True) - fig_test.text(x=x, y=y, text=text, transparency=50) + fig.basemap(region=[0, 10, 10, 20], projection="X10c", frame=True) + fig.text(x=x, y=y, text=text, transparency=50) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_text_varying_transparency(): """ Add texts with varying transparency. @@ -336,33 +330,21 @@ def test_text_varying_transparency(): text = [f"TEXT-{i}-{j}" for i, j in zip(x, y)] transparency = np.arange(10, 100, 10) - fig_ref, fig_test = Figure(), Figure() - # Use single-character arguments for the reference image - with GMTTempFile() as tmpfile: - np.savetxt(tmpfile.name, np.c_[x, y, transparency, text], fmt="%s") - fig_ref.basemap(R="0/10/10/20", J="X10c", B="") - fig_ref.text(textfiles=tmpfile.name, t="") - - fig_test.basemap(region=[0, 10, 10, 20], projection="X10c", frame=True) - fig_test.text(x=x, y=y, text=text, transparency=transparency) + fig = Figure() + fig.basemap(region=[0, 10, 10, 20], projection="X10c", frame=True) + fig.text(x=x, y=y, text=text, transparency=transparency) - return fig_ref, fig_test + return fig -@check_figures_equal() +@pytest.mark.mpl_image_compare def test_text_nonstr_text(): """ Input text is in non-string type (e.g., int, float) """ - fig_ref, fig_test = Figure(), Figure() - - # Use single-character arguments and input files for the reference image - with GMTTempFile(suffix=".txt") as tempfile: - with open(tempfile.name, "w") as tmpfile: - tmpfile.write("1 1 1.0\n2 2 2.0\n3 3 3.0\n4 4 4.0\n") - fig_ref.text(R="0/10/0/10", J="X10c", B="", textfiles=tempfile.name) + fig = Figure() - fig_test.text( + fig.text( region=[0, 10, 0, 10], projection="X10c", frame=True, @@ -371,4 +353,4 @@ def test_text_nonstr_text(): text=[1, 2, 3.0, 4.0], ) - return fig_ref, fig_test + return fig diff --git a/pygmt/tests/test_velo.py b/pygmt/tests/test_velo.py new file mode 100644 index 00000000000..a8517adf62c --- /dev/null +++ b/pygmt/tests/test_velo.py @@ -0,0 +1,91 @@ +""" +Tests velo. +""" +import pandas as pd +import pytest +from pygmt import Figure +from pygmt.exceptions import GMTInvalidInput + + +@pytest.fixture(scope="module", name="dataframe") +def fixture_dataframe(): + """ + Sample pandas.DataFrame for plotting velocity vectors. + """ + return pd.DataFrame( + data={ + "Long.": [0, -8, 0, -5, 5, 0], + "Lat.": [-8, 5, 0, -5, 0, -5], + "Evel": [0, 3, 4, 6, -6, 6], + "Nvel": [0, 3, 6, 4, 4, -4], + "Esig": [4, 0, 4, 6, 6, 6], + "Nsig": [6, 0, 6, 4, 4, 4], + "CorEN": [0.5, 0.5, 0.5, 0.5, -0.5, -0.5], + "SITE": ["4x6", "3x3", "NaN", "6x4", "-6x4", "6x-4"], + } + ) + + +@pytest.mark.xfail( + reason="Flaky test only passes with pytest on single module" + "See https://github.com/GenericMappingTools/pygmt/issues/1242" +) +@pytest.mark.mpl_image_compare +def test_velo_numpy_array_numeric_only(dataframe): + """ + Plot velocity arrow and confidence ellipse from a numpy.ndarray. + """ + fig = Figure() + fig.velo( + data=dataframe.iloc[:, :-1].to_numpy(), + spec="e0.2/0.39/18", + vector="0.3c+p1p+e+gred", + frame="1g1", + ) + return fig + + +def test_velo_numpy_array_text_column(dataframe): + """ + Check that velo fails when plotting a numpy.ndarray with a text column. + """ + fig = Figure() + with pytest.raises(GMTInvalidInput): + fig.velo( + data=dataframe.to_numpy(), + spec="e0.2/0.39/18", + vector="0.3c+p1p+e+gred", + ) + + +def test_velo_without_spec(dataframe): + """ + Check that velo fails when the spec parameter is not given. + """ + fig = Figure() + with pytest.raises(GMTInvalidInput): + fig.velo(data=dataframe) + + +@pytest.mark.xfail( + reason="Flaky test only passes with pytest on single module" + "See https://github.com/GenericMappingTools/pygmt/issues/1242" +) +@pytest.mark.mpl_image_compare +def test_velo_pandas_dataframe(dataframe): + """ + Plot velocity arrow and confidence ellipse from a pandas.DataFrame. + """ + fig = Figure() + fig.velo( + data=dataframe, + spec="e0.2/0.39/18", + vector="0.3c+p1p+e+gred", + frame=["WSne", "2g2f"], + region=[-10, 8, -10, 6], + projection="x0.8c", + pen="0.6p,red", + uncertaintycolor="lightblue1", + line=True, + ) + return fig diff --git a/pygmt/tests/test_wiggle.py b/pygmt/tests/test_wiggle.py new file mode 100644 index 00000000000..7bd92e15bb1 --- /dev/null +++ b/pygmt/tests/test_wiggle.py @@ -0,0 +1,31 @@ +""" +Tests wiggle. +""" +import numpy as np +import pytest +from pygmt import Figure + + +@pytest.mark.mpl_image_compare +def test_wiggle(): + """ + Plot the z=f(x,y) anomalies along tracks. + """ + x = np.arange(-2, 2, 0.02) + y = np.zeros(x.size) + z = np.cos(2 * np.pi * x) + + fig = Figure() + fig.wiggle( + region=[-4, 4, -1, 1], + projection="X8c", + x=x, + y=y, + z=z, + scale="0.5c", + color=["red+p", "gray+n"], + pen="1.0p", + track="0.5p", + position="jRM+w2+lnT", + ) + return fig