diff --git a/.github/ISSUE_TEMPLATE/release_checklist.md b/.github/ISSUE_TEMPLATE/release_checklist.md
index d9c9b2de597..0043fa7006c 100644
--- a/.github/ISSUE_TEMPLATE/release_checklist.md
+++ b/.github/ISSUE_TEMPLATE/release_checklist.md
@@ -13,6 +13,7 @@ assignees: ''
**Before release**:
- [ ] Reserve a DOI on [Zenodo](https://zenodo.org) by clicking on "New Version"
- [ ] Update Changelog
+- [ ] Add a new entry in `doc/_static/version_switch.js` for documentation switcher
**Release**:
- [ ] Go to [GitHub Release](https://github.com/GenericMappingTools/pygmt/releases) and make a release, this will automatically create a tag too
diff --git a/.github/workflows/ci_tests_dev.yaml b/.github/workflows/ci_tests_dev.yaml
index 8e08e5cf836..e73021b00bd 100644
--- a/.github/workflows/ci_tests_dev.yaml
+++ b/.github/workflows/ci_tests_dev.yaml
@@ -21,7 +21,7 @@ jobs:
matrix:
python-version: [3.8]
os: [ubuntu-20.04, macOS-10.15]
- gmt_git_ref: [6.1, master]
+ gmt_git_ref: [master]
env:
# LD_LIBRARY_PATH: ${{ github.workspace }}/gmt/lib:$LD_LIBRARY_PATH
GMT_INSTALL_DIR: ${{ github.workspace }}/gmt-install-dir
diff --git a/Makefile b/Makefile
index 82dd1d560aa..d6672c19f5e 100644
--- a/Makefile
+++ b/Makefile
@@ -6,8 +6,8 @@ PYTEST_ARGS=--cov=$(PROJECT) --cov-config=../.coveragerc \
--doctest-modules -v --mpl --mpl-results-path=results \
--pyargs ${PYTEST_EXTRA}
BLACK_FILES=$(PROJECT) setup.py doc/conf.py examples
-FLAKE8_FILES=$(PROJECT) setup.py
-LINT_FILES=$(PROJECT) setup.py
+FLAKE8_FILES=$(PROJECT) setup.py doc/conf.py
+LINT_FILES=$(PROJECT) setup.py doc/conf.py
help:
@echo "Commands:"
@@ -47,7 +47,8 @@ lint:
clean:
find . -name "*.pyc" -exec rm -v {} \;
find . -name "*~" -exec rm -v {} \;
- rm -rvf build dist MANIFEST *.egg-info __pycache__ .coverage .cache htmlcov coverage.xml
+ find . -type d -name "__pycache__" -exec rm -rv {} +
+ rm -rvf build dist MANIFEST *.egg-info .coverage .cache htmlcov coverage.xml
rm -rvf $(TESTDIR)
rm -rvf baseline
rm -rvf result_images
diff --git a/README.rst b/README.rst
index 4d12c74e9f7..d0c04e6e224 100644
--- a/README.rst
+++ b/README.rst
@@ -73,7 +73,7 @@ Project goals
* Build a Pythonic API for GMT.
* Interface with the GMT C API directly using ctypes (no system calls).
* Support for rich display in the Jupyter notebook.
-* Integration with the Scipy stack: numpy.ndarray or pandas.DataFrame for data tables
+* Integration with the PyData Ecosystem: numpy.ndarray or pandas.DataFrame for data tables
and xarray.DataArray for grids.
diff --git a/doc/Makefile b/doc/Makefile
index d310fc02cbb..ce8dc86f764 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -21,7 +21,7 @@ help:
@echo " doctest run all doctests embedded in the documentation (if enabled)"
clean:
- rm -rf $(BUILDDIR)/html/*
+ rm -rf $(BUILDDIR)/html
rm -rf $(BUILDDIR)/doctrees
rm -rf $(BUILDDIR)/linkcheck
rm -rf modules
diff --git a/doc/_static/version_switch.js b/doc/_static/version_switch.js
new file mode 100644
index 00000000000..b61756ae60f
--- /dev/null
+++ b/doc/_static/version_switch.js
@@ -0,0 +1,79 @@
+// Copyright 2013 PSF. Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+// File originates from the cpython source found in Doc/tools/sphinxext/static/version_switch.js
+
+(function() {
+ 'use strict';
+
+ var doc_url = "www.pygmt.org";
+ //var doc_url = "0.0.0.0:8000"; // for local testing only
+ var url_re = new RegExp(doc_url + "\\/(dev|latest|(v\\d+\\.\\d+\\.\\d+))\\/");
+ // List all versions.
+ // Add one entry "version: title" for any minor releases
+ var all_versions = {
+ 'latest': 'latest',
+ 'dev': 'dev',
+ 'v0.2.0': 'v0.2.0',
+ 'v0.1.2': 'v0.1.2',
+ 'v0.1.1': 'v0.1.1',
+ 'v0.1.0': 'v0.1.0',
+ '0.0.1a0': 'v0.0.1a0',
+ };
+
+ function build_select(current_version, current_release) {
+ var buf = ['');
+ return buf.join('');
+ }
+
+ function patch_url(url, new_version) {
+ return url.replace(url_re, doc_url + '/' + new_version + '/');
+ }
+
+ function on_switch() {
+ var selected = $(this).children('option:selected').attr('value');
+
+ var url = window.location.href,
+ new_url = patch_url(url, selected);
+
+ if (new_url != url) {
+ // check beforehand if url exists, else redirect to version's start page
+ $.ajax({
+ url: new_url,
+ success: function() {
+ window.location.href = new_url;
+ },
+ error: function() {
+ window.location.href = 'http://' + doc_url + '/' + selected;
+ }
+ });
+ }
+ }
+
+ $(document).ready(function() {
+ var match = url_re.exec(window.location.href);
+ if (match) {
+ var release = DOCUMENTATION_OPTIONS.VERSION;
+ var version = match[1];
+ var select = build_select(version, release);
+ $('.version_switch_note').html('Or, select a version from the drop-down menu above.');
+ $('.version').html(select);
+ $('.version select').bind('change', on_switch);
+ }
+ });
+})();
diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html
index 3de7b40dee3..eb0656de46a 100644
--- a/doc/_templates/layout.html
+++ b/doc/_templates/layout.html
@@ -15,6 +15,10 @@
ga('set', 'anonymizeIp', true);
ga('send', 'pageview');
+
+
+
+
{% endblock %}
diff --git a/doc/conf.py b/doc/conf.py
index c3a9e6ef388..6b61ac02008 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
-import sys
-import os
-import glob
-import shutil
+"""
+Sphinx documentation configuration file.
+"""
+# pylint: disable=invalid-name
+
import datetime
-import sphinx_rtd_theme
-import sphinx_gallery
-from sphinx_gallery.sorting import FileNameSortKey, ExplicitOrder
+from sphinx_gallery.sorting import ( # pylint: disable=no-name-in-module
+ FileNameSortKey,
+ ExplicitOrder,
+)
from pygmt import __version__, __commit__
from pygmt.sphinx_gallery import PyGMTScraper
@@ -60,6 +62,7 @@
"gallery_dirs": ["gallery", "tutorials", "projections"],
"subsection_order": ExplicitOrder(
[
+ "../examples/gallery/line",
"../examples/gallery/coast",
"../examples/gallery/plot",
"../examples/gallery/grid",
@@ -90,6 +93,7 @@
templates_path = ["_templates"]
exclude_patterns = ["_build", "**.ipynb_checkpoints"]
source_suffix = ".rst"
+needs_sphinx = "1.8"
# The encoding of source files.
source_encoding = "utf-8-sig"
master_doc = "index"
@@ -97,11 +101,12 @@
# General information about the project
year = datetime.date.today().year
project = "PyGMT"
-copyright = "2017-{}, The PyGMT Developers.".format(year)
+copyright = f"2017-{year}, The PyGMT Developers." # pylint: disable=redefined-builtin
if len(__version__.split("+")) > 1 or __version__ == "unknown":
version = "dev"
else:
version = __version__
+release = __version__
# These enable substitutions using |variable| in the rst files
rst_epilog = """
@@ -116,6 +121,7 @@
html_logo = ""
html_favicon = "_static/favicon.png"
html_static_path = ["_static"]
+html_css_files = ["style.css"]
html_extra_path = []
pygments_style = "default"
add_function_parentheses = False
@@ -127,20 +133,21 @@
html_theme = "sphinx_rtd_theme"
html_theme_options = {}
repository = "GenericMappingTools/pygmt"
-commit_link = f'{ __commit__[:7] }'
+repository_url = "https://github.com/GenericMappingTools/pygmt"
+commit_link = f'{ __commit__[:7] }'
html_context = {
"menu_links": [
(
' Contributing',
- "https://github.com/GenericMappingTools/pygmt/blob/master/CONTRIBUTING.md",
+ f"{repository_url}/blob/master/CONTRIBUTING.md",
),
(
' Code of Conduct',
- "https://github.com/GenericMappingTools/pygmt/blob/master/CODE_OF_CONDUCT.md",
+ f"{repository_url}/blob/master/CODE_OF_CONDUCT.md",
),
(
' License',
- "https://github.com/GenericMappingTools/pygmt/blob/master/LICENSE.txt",
+ f"{repository_url}/blob/master/LICENSE.txt",
),
(
' Contact',
@@ -148,7 +155,7 @@
),
(
' Source Code',
- "https://github.com/GenericMappingTools/pygmt",
+ repository_url,
),
],
# Custom variables to enable "Improve this page"" and "Download notebook"
@@ -162,8 +169,3 @@
"github_version": "master",
"commit": commit_link,
}
-
-
-# Load the custom CSS files (needs sphinx >= 1.6 for this to work)
-def setup(app):
- app.add_stylesheet("style.css")
diff --git a/doc/overview.rst b/doc/overview.rst
index 53ffd321749..7296bb8a19d 100644
--- a/doc/overview.rst
+++ b/doc/overview.rst
@@ -49,13 +49,13 @@ These are conference presentations about the development of PyGMT (previously
* "Building an object-oriented Python interface for the Generic Mapping Tools".
2018.
Leonardo Uieda and Paul Wessel.
- Presented at *Scipy 2018*.
+ Presented at *SciPy 2018*.
doi:`10.6084/m9.figshare.6814052 `__
.. figure:: _static/scipy2018-youtube-thumbnail.png
:target: https://www.youtube.com/watch?v=6wMtfZXfTRM
:align: center
- :alt: Scipy youtube video
+ :alt: SciPy youtube video
* "Integrating the Generic Mapping Tools with the Scientific Python Ecosystem".
2018.
@@ -71,13 +71,13 @@ These are conference presentations about the development of PyGMT (previously
* "Bringing the Generic Mapping Tools to Python".
2017.
Leonardo Uieda and Paul Wessel.
- Presented at *Scipy 2017*.
+ Presented at *SciPy 2017*.
doi:`10.6084/m9.figshare.7635833 `__
.. figure:: _static/scipy2017-youtube-thumbnail.png
:target: https://www.youtube.com/watch?v=93M4How7R24
:align: center
- :alt: Scipy youtube video
+ :alt: SciPy youtube video
* "A modern Python interface for the Generic Mapping Tools".
2017.
diff --git a/examples/gallery/line/README.txt b/examples/gallery/line/README.txt
new file mode 100644
index 00000000000..043f6ca6a79
--- /dev/null
+++ b/examples/gallery/line/README.txt
@@ -0,0 +1,2 @@
+Lines
+-----
diff --git a/examples/gallery/line/linestyles.py b/examples/gallery/line/linestyles.py
new file mode 100644
index 00000000000..d0a1f1daa52
--- /dev/null
+++ b/examples/gallery/line/linestyles.py
@@ -0,0 +1,42 @@
+"""
+Line styles
+-----------
+
+The :meth:`pygmt.Figure.plot` method can plot lines in different styles.
+The default line style is a 0.25-point wide, black, solid line, and can be
+customized via the ``pen`` argument.
+
+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
+dot-dashed line, are allowed.
+
+For more advanced *pen* attributes, see the GMT cookbook
+:gmt-docs:`cookbook/features.html#wpen-attrib`.
+
+"""
+
+import numpy as np
+import pygmt
+
+# Generate a sample line for plotting
+x = np.linspace(0, 10, 500)
+y = np.sin(x)
+
+fig = pygmt.Figure()
+fig.basemap(region=[0, 10, -3, 3], projection="X15c/8c", frame=["xaf", "yaf", "WSrt"])
+
+# Plot the line using the default line style
+fig.plot(x=x, y=y)
+
+# Plot the lines using different line styles
+fig.plot(x=x, y=y + 1.5, pen="1p,red,-")
+fig.plot(x=x, y=y + 1.0, pen="2p,blue,.")
+fig.plot(x=x, y=y + 0.5, pen="1p,red,-.")
+
+fig.plot(x=x, y=y - 0.5, pen="2p,blue,..-")
+fig.plot(x=x, y=y - 1.0, pen="3p,tomato,--.")
+fig.plot(x=x, y=y - 1.5, pen="3p,tomato,4_2:2p")
+
+fig.show()
diff --git a/examples/gallery/plot/colorbar.py b/examples/gallery/plot/colorbar.py
index 195198cfdac..beb4a160362 100644
--- a/examples/gallery/plot/colorbar.py
+++ b/examples/gallery/plot/colorbar.py
@@ -2,50 +2,57 @@
Colorbar
--------
-The :meth:`pygmt.Figure.colorbar` method creates a color scalebar. We must specify the
-colormap via the ``cmap`` argument, and set the placement via the ``position`` argument.
-The full list of color paletted tables can be found at :gmt-docs:`cookbook/cpts.html`.
-You can set the `position` of the colorbar using the following options:
-
-- j/J: justified inside/outside the mapframe using any 2 character combination of
- vertical (**T** op, **M** iddle, **B** ottom) and horizontal (**L** eft, **C** enter,
- **R** ight) alignment codes, e.g. `position="jTR"` for top 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 point.
+The :meth:`pygmt.Figure.colorbar` method creates a color scalebar. We must
+specify the colormap via the ``cmap`` argument, and optionally set the
+placement via the ``position`` argument. The full list of color palette tables
+can be found at :gmt-docs:`cookbook/cpts.html`. You can set the `position` of
+the colorbar using the following options:
+
+- j/J: justified inside/outside the map frame using any 2 character combination
+ of vertical (**T** op, **M** iddle, **B** ottom) and horizontal (**L** eft,
+ **C** enter, **R** ight) alignment codes, e.g. `position="jTR"` for top
+ 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
+ point.
- n: using normalized (0-1) coordinates, e.g. `position="n0.4/0.8"`.
-Note that the anchor point defaults to the bottom left (BL). Append +h to ``position``
-to get a horizontal colorbar instead of a vertical one. For more advanced styling
-options, see the full option list at :gmt-docs:`colorbar.html`.
+Note that the anchor point defaults to the bottom left (BL). Append +h to
+``position`` to get a horizontal colorbar instead of a vertical one. For more
+advanced styling options, see the full option list at
+:gmt-docs:`colorbar.html`.
"""
import pygmt
fig = pygmt.Figure()
-fig.basemap(region=[0, 3, 6, 9], projection="t0/3c", frame=True)
+fig.basemap(region=[0, 3, 6, 9], projection="x3c", frame=["af", 'WSne+t"Colorbars"'])
-# Create a colorbar suitable for surface topography- oleron
+## Create a colorbar designed for seismic tomography - roma
+# Colorbar is placed at bottom center (BC) by default if no position is given
+fig.colorbar(cmap="roma", frame=["x+lVelocity", "y+lm/s"])
+## Create a colorbar showing the scientific rainbow - batlow
fig.colorbar(
- cmap="oleron",
- position="jTC+w6c/1c+h", # justified inside map frame (j) at Top Center (TC)
- box=True,
- frame=["+Loleron", "xaf", "y+lm"],
- scale=10,
-)
-# Create a colorbar designed for seismic tomography- roma
-fig.colorbar(
- cmap="roma",
- position="x1.2c/4.75c+w6c/1c+h", # plot using paper coordinates (x) at 1.2cm,4.75cm
+ 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)
+ position="g0.3/8.7+w4c/0.5c+h",
box=True,
- frame=["+Lroma", "xaf", "y+lm/s"],
- scale=10,
+ frame=["x+lTemperature", r"y+l\260C"],
+ scale=100,
)
-# Create a colorbar showing the scientific rainbow - batlow
+
+## Create a colorbar suitable for surface topography - oleron
fig.colorbar(
- cmap="batlow",
- position="g0.45/6.6+w6c/1c+h", # plot using map coordinates (g) at lon/lat 0.45/6.6
- box=True,
- frame=["+Lbatlow", "xaf", r"y+l\260C"],
+ 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)
+ 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 argument above
+ frame=["x+lElevation", "y+lm"],
scale=10,
)
diff --git a/examples/gallery/plot/scatter.py b/examples/gallery/plot/scatter.py
new file mode 100644
index 00000000000..2d3199b35c8
--- /dev/null
+++ b/examples/gallery/plot/scatter.py
@@ -0,0 +1,41 @@
+"""
+Scatter plots with a legend
+---------------------------
+
+To create a scatter plot with a legend one may use a loop and create one scatter
+plot per item to appear in the legend and set the label accordingly.
+
+Modified from the matplotlib example:
+https://matplotlib.org/gallery/lines_bars_and_markers/scatter_with_legend.html
+"""
+
+import numpy as np
+import pygmt
+
+np.random.seed(19680801)
+n = 200 # number of random data points
+
+fig = pygmt.Figure()
+fig.basemap(
+ region=[-0.1, 1.1, -0.1, 1.1],
+ projection="X10c/10c",
+ frame=["xa0.2fg", "ya0.2fg", "WSrt"],
+)
+for color in ["blue", "orange", "green"]:
+ 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
+ # plot data points as circles (style="c"), with different sizes
+ fig.plot(
+ x=x,
+ y=y,
+ style="c",
+ sizes=sizes,
+ color=color,
+ # Set the legend label,
+ # and set the circle size to be 0.25 cm (+S0.25c) in legend
+ label=f"{color}+S0.25c",
+ transparency=70, # set transparency level for all symbols
+ )
+
+fig.legend(transparency=30) # set transparency level for legends
+fig.show()
diff --git a/examples/tutorials/first-figure.py b/examples/tutorials/first-figure.py
index 752f010ab5e..40dce53a050 100644
--- a/examples/tutorials/first-figure.py
+++ b/examples/tutorials/first-figure.py
@@ -27,7 +27,7 @@
########################################################################################
# Add elements to the figure using its methods. For example, let's start a map with an
# automatic frame and ticks around a given longitude and latitude bound, set the
-# projection to Mercator (``M``), and the figure width to 8 inches:
+# projection to Mercator (``M``), and the map width to 8 inches:
fig.basemap(region=[-90, -70, 0, 20], projection="M8i", frame=True)
diff --git a/pygmt/base_plotting.py b/pygmt/base_plotting.py
index a3f682bebf9..e02eb03d310 100644
--- a/pygmt/base_plotting.py
+++ b/pygmt/base_plotting.py
@@ -68,8 +68,12 @@ def _preprocess(self, **kwargs): # pylint: disable=no-self-use
G="land",
S="water",
U="timestamp",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
)
- @kwargs_to_strings(R="sequence")
+ @kwargs_to_strings(R="sequence", p="sequence")
def coast(self, **kwargs):
"""
Plot continents, shorelines, rivers, and borders on maps
@@ -128,6 +132,9 @@ def coast(self, **kwargs):
shorelines : str
``'[level/]pen'``
Draw shorelines [Default is no shorelines]. Append pen attributes.
+ {XY}
+ {p}
+ {t}
"""
kwargs = self._preprocess(**kwargs)
@@ -144,8 +151,12 @@ def coast(self, **kwargs):
F="box",
G="truncate",
W="scale",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
)
- @kwargs_to_strings(R="sequence", G="sequence")
+ @kwargs_to_strings(R="sequence", G="sequence", p="sequence")
def colorbar(self, **kwargs):
"""
Plot a gray or color scale-bar on maps.
@@ -205,6 +216,9 @@ def colorbar(self, **kwargs):
scale : float
Multiply all z-values in the CPT by the provided scale. By default
the CPT is used as is.
+ {XY}
+ {p}
+ {t}
"""
kwargs = self._preprocess(**kwargs)
@@ -225,8 +239,12 @@ def colorbar(self, **kwargs):
U="timestamp",
W="pen",
l="label",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
)
- @kwargs_to_strings(R="sequence", L="sequence", A="sequence_plus")
+ @kwargs_to_strings(R="sequence", L="sequence", A="sequence_plus", p="sequence")
def grdcontour(self, grid, **kwargs):
"""
Convert grids or images to contours and plot them on maps
@@ -274,6 +292,7 @@ def grdcontour(self, grid, **kwargs):
{G}
{U}
{W}
+ {XY}
label : str
Add a legend entry for the contour being plotted. Normally, the
annotated contour is selected for the legend. You can select the
@@ -281,6 +300,8 @@ def grdcontour(self, grid, **kwargs):
to be of the format [*annotcontlabel*][/*contlabel*]. If either
label contains a slash (/) character then use ``|`` as the
separator for the two labels instead.
+ {p}
+ {t}
"""
kwargs = self._preprocess(**kwargs)
kind = data_kind(grid, None, None)
@@ -296,13 +317,60 @@ def grdcontour(self, grid, **kwargs):
lib.call_module("grdcontour", arg_str)
@fmt_docstring
- @use_alias(R="region", J="projection", W="pen", B="frame", I="shading", C="cmap")
- @kwargs_to_strings(R="sequence")
+ @use_alias(
+ A="img_out",
+ B="frame",
+ C="cmap",
+ D="img_in",
+ E="dpi",
+ G="bit_color",
+ I="shading",
+ J="projection",
+ M="monochrome",
+ N="no_clip",
+ Q="nan_transparent",
+ R="region",
+ U="timestamp",
+ V="verbose",
+ X="xshift",
+ Y="yshift",
+ n="interpolation",
+ p="perspective",
+ t="transparency",
+ x="cores",
+ )
+ @kwargs_to_strings(R="sequence", p="sequence")
def grdimage(self, grid, **kwargs):
"""
- Project grids or images and plot them on maps.
-
- Takes a grid file name or an xarray.DataArray object as input.
+ Project and plot grids or images.
+
+ Reads a 2-D grid file and produces a gray-shaded (or colored) map by
+ building a rectangular image and assigning pixels a gray-shade (or
+ color) based on the z-value and the CPT file. Optionally, illumination
+ may be added by providing a file with intensities in the (-1,+1) range
+ or instructions to derive intensities from the input data grid. Values
+ outside this range will be clipped. Such intensity files can be created
+ from the grid using `grdgradient` and, optionally, modified by
+ `grdmath` or `grdhisteq`. If GMT is built with GDAL support, *grid* can
+ be an image file (geo-referenced or not). In this case the image can
+ optionally be illuminated with the file provided via the *shading*
+ option. Here, if image has no coordinates then those of the intensity
+ file will be used.
+
+ When using map projections, the grid is first resampled on a new
+ rectangular grid with the same dimensions. Higher resolution images can
+ be obtained by using the *dpi* option. To obtain the resampled value
+ (and hence shade or color) of each map pixel, its location is inversely
+ projected back onto the input grid after which a value is interpolated
+ between the surrounding input grid values. By default bi-cubic
+ interpolation is used. Aliasing is avoided by also forward projecting
+ the input grid nodes. If two or more nodes are projected onto the same
+ pixel, their average will dominate in the calculation of the pixel
+ value. Interpolation and aliasing is controlled with the
+ *interpolation* option.
+
+ The *region* option can be used to select a map region larger or
+ smaller than that implied by the extent of the grid.
Full option list at :gmt-docs:`grdimage.html`
@@ -311,7 +379,85 @@ def grdimage(self, grid, **kwargs):
Parameters
----------
grid : str or xarray.DataArray
- The file name of the input grid or the grid loaded as a DataArray.
+ The file name or a DataArray containing the input 2-D gridded data
+ set or image to be plotted (See GRID FILE FORMATS at
+ :gmt-docs:`grdimage.html#grid-file-formats`).
+ img_out : str
+ ``out_img[=driver]``.
+ Save an image in a raster format instead of PostScript. Use
+ extension .ppm for a Portable Pixel Map format which is the only
+ raster format GMT can natively write. For GMT installations
+ configured with GDAL support there are more choices: Append
+ *out_img* to select the image file name and extension. If the
+ extension is one of .bmp, .gif, .jpg, .png, or .tif then no driver
+ information is required. For other output formats you must append
+ the required GDAL driver. The *driver* is the driver code name used
+ by GDAL; see your GDAL installation's documentation for available
+ drivers. Append a **+c**\\ *options* string where options is a list
+ of one or more concatenated number of GDAL **-co** options. For
+ example, to write a GeoPDF with the TerraGo format use
+ ``=PDF+cGEO_ENCODING=OGC_BP``. Notes: (1) If a tiff file (.tif) is
+ selected then we will write a GeoTiff image if the GMT projection
+ syntax translates into a PROJ syntax, otherwise a plain tiff file
+ is produced. (2) Any vector elements will be lost.
+ {B}
+ {CPT}
+ img_in : str
+ ``[r]``
+ GMT will automatically detect standard image files (Geotiff, TIFF,
+ JPG, PNG, GIF, etc.) and will read those via GDAL. For very obscure
+ image formats you may need to explicitly set *img_in*, which
+ specifies that the grid is in fact an image file to be read via
+ GDAL. Append **r** to assign the region specified by *region*
+ to the image. For example, if you have used ``region='d'`` then the
+ image will be assigned a global domain. This mode allows you to
+ project a raw image (an image without referencing coordinates).
+ dpi : int
+ ``[i|dpi]``.
+ Sets the resolution of the projected grid that will be created if a
+ map projection other than Linear or Mercator was selected [100]. By
+ default, the projected grid will be of the same size (rows and
+ columns) as the input file. Specify **i** to use the PostScript
+ image operator to interpolate the image at the device resolution.
+ bit_color : str
+ ``color[+b|f]``.
+ This option only applies when a resulting 1-bit image otherwise
+ would consist of only two colors: black (0) and white (255). If so,
+ this option will instead use the image as a transparent mask and
+ paint the mask with the given color. Append **+b** to paint the
+ background pixels (1) or **+f** for the foreground pixels
+ [Default].
+ shading : str
+ ``[intensfile|intensity|modifiers]``.
+ Give the name of a grid file with intensities in the (-1,+1) range,
+ or a constant intensity to apply everywhere (affects the ambient
+ light). Alternatively, derive an intensity grid from the input data
+ grid via a call to `grdgradient`; append **+a**\\ *azimuth*,
+ **+n**\\ *args*, and **+m**\\ *ambient* to specify azimuth,
+ intensity, and ambient arguments for that module, or just give
+ **+d** to select the default arguments (``+a-45+nt1+m0``). If you
+ want a more specific intensity scenario then run `grdgradient`
+ separately first. If we should derive intensities from another file
+ than grid, specify the file with suitable modifiers [Default is no
+ illumination].
+ {J}
+ monochrome : bool
+ Force conversion to monochrome image using the (television) YIQ
+ transformation. Cannot be used with *nan_transparent*.
+ no_clip : bool
+ Do not clip the image at the map boundary (only relevant for
+ non-rectangular maps).
+ nan_transparent : bool
+ Make grid nodes with z = NaN transparent, using the color-masking
+ feature in PostScript Level 3 (the PS device must support PS Level
+ 3).
+ {R}
+ {V}
+ {XY}
+ {n}
+ {p}
+ {t}
+ {x}
"""
kwargs = self._preprocess(**kwargs)
@@ -341,8 +487,11 @@ def grdimage(self, grid, **kwargs):
Wc="contourpen",
Wm="meshpen",
Wf="facadepen",
- p="perspective",
I="shading",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
)
@kwargs_to_strings(R="sequence", p="sequence")
def grdview(self, grid, **kwargs):
@@ -406,10 +555,6 @@ def grdview(self, grid, **kwargs):
Sets the pen attributes used for the facade. You must also select
-N for the facade outline to be drawn.
- perspective : list or str
- ``'[x|y|z]azim[/elev[/zlevel]][+wlon0/lat0[/z0]][+vx0/y0]'``.
- Select perspective view.
-
shading : str
Provide the name of a grid file with intensities in the (-1,+1)
range, or a constant intensity to apply everywhere (affects the
@@ -419,6 +564,10 @@ def grdview(self, grid, **kwargs):
intensity, and ambient arguments for that module, or just give
``+d`` to select the default arguments (``+a-45+nt1+m0``).
+ {XY}
+ {p}
+ {t}
+
"""
kwargs = self._preprocess(**kwargs)
kind = data_kind(grid, None, None)
@@ -458,8 +607,12 @@ def grdview(self, grid, **kwargs):
l="label",
C="cmap",
U="timestamp",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
)
- @kwargs_to_strings(R="sequence", i="sequence_comma")
+ @kwargs_to_strings(R="sequence", i="sequence_comma", p="sequence")
def plot(self, x=None, y=None, data=None, sizes=None, direction=None, **kwargs):
"""
Plot lines, polygons, and symbols on maps.
@@ -525,8 +678,12 @@ def plot(self, x=None, y=None, data=None, sizes=None, direction=None, **kwargs):
quoted lines).
{W}
{U}
+ {XY}
label : str
Add a legend entry for the symbol or line being plotted.
+
+ {p}
+ {t}
"""
kwargs = self._preprocess(**kwargs)
@@ -576,8 +733,12 @@ def plot(self, x=None, y=None, data=None, sizes=None, direction=None, **kwargs):
i="columns",
l="label",
C="levels",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
)
- @kwargs_to_strings(R="sequence", i="sequence_comma")
+ @kwargs_to_strings(R="sequence", i="sequence_comma", p="sequence")
def contour(self, x=None, y=None, z=None, data=None, **kwargs):
"""
Contour table data by direct triangulation.
@@ -633,6 +794,9 @@ def contour(self, x=None, y=None, z=None, data=None, **kwargs):
to be of the format [*annotcontlabel*][/*contlabel*]. If either
label contains a slash (/) character then use ``|`` as the
separator for the two labels instead.
+ {XY}
+ {p}
+ {t}
"""
kwargs = self._preprocess(**kwargs)
@@ -663,8 +827,12 @@ def contour(self, x=None, y=None, z=None, data=None, **kwargs):
Td="rose",
Tm="compass",
U="timestamp",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
)
- @kwargs_to_strings(R="sequence")
+ @kwargs_to_strings(R="sequence", p="sequence")
def basemap(self, **kwargs):
"""
Produce a basemap for the figure.
@@ -696,6 +864,9 @@ def basemap(self, **kwargs):
Draws a map magnetic rose on the map at the location defined by the
reference and anchor points
{U}
+ {XY}
+ {p}
+ {t}
"""
kwargs = self._preprocess(**kwargs)
@@ -705,8 +876,18 @@ def basemap(self, **kwargs):
lib.call_module("basemap", build_arg_string(kwargs))
@fmt_docstring
- @use_alias(R="region", J="projection", U="timestamp", D="position", F="box")
- @kwargs_to_strings(R="sequence")
+ @use_alias(
+ R="region",
+ J="projection",
+ U="timestamp",
+ D="position",
+ F="box",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
+ )
+ @kwargs_to_strings(R="sequence", p="sequence")
def logo(self, **kwargs):
"""
Place the GMT graphics logo on a map.
@@ -731,6 +912,9 @@ def logo(self, **kwargs):
Without further options, draws a rectangular border around the
GMT logo.
{U}
+ {XY}
+ {p}
+ {t}
"""
kwargs = self._preprocess(**kwargs)
@@ -740,8 +924,18 @@ def logo(self, **kwargs):
lib.call_module("logo", build_arg_string(kwargs))
@fmt_docstring
- @use_alias(R="region", J="projection", D="position", F="box", M="monochrome")
- @kwargs_to_strings(R="sequence")
+ @use_alias(
+ R="region",
+ J="projection",
+ D="position",
+ F="box",
+ M="monochrome",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
+ )
+ @kwargs_to_strings(R="sequence", p="sequence")
def image(self, imagefile, **kwargs):
"""
Place images or EPS files on maps.
@@ -774,6 +968,9 @@ def image(self, imagefile, **kwargs):
monochrome : bool
Convert color image to monochrome grayshades using the (television)
YIQ-transformation.
+ {XY}
+ {p}
+ {t}
"""
kwargs = self._preprocess(**kwargs)
with Session() as lib:
@@ -781,8 +978,17 @@ def image(self, imagefile, **kwargs):
lib.call_module("image", arg_str)
@fmt_docstring
- @use_alias(R="region", J="projection", D="position", F="box")
- @kwargs_to_strings(R="sequence")
+ @use_alias(
+ R="region",
+ J="projection",
+ D="position",
+ F="box",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
+ )
+ @kwargs_to_strings(R="sequence", p="sequence")
def legend(self, spec=None, position="JTR+jTR+o0.2c", box="+gwhite+p1p", **kwargs):
"""
Plot legends on maps.
@@ -816,6 +1022,9 @@ def legend(self, spec=None, position="JTR+jTR+o0.2c", box="+gwhite+p1p", **kwarg
rectangular border around the legend using **MAP_FRAME_PEN**. By
default, uses '+gwhite+p1p' which draws a box around the legend
using a 1 point black pen and adds a white background.
+ {XY}
+ {p}
+ {t}
"""
kwargs = self._preprocess(**kwargs)
@@ -844,6 +1053,10 @@ def legend(self, spec=None, position="JTR+jTR+o0.2c", box="+gwhite+p1p", **kwarg
D="offset",
G="fill",
W="pen",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
)
@kwargs_to_strings(
R="sequence",
@@ -851,6 +1064,7 @@ def legend(self, spec=None, position="JTR+jTR+o0.2c", box="+gwhite+p1p", **kwarg
angle="sequence_comma",
font="sequence_comma",
justify="sequence_comma",
+ p="sequence",
)
def text(
self,
@@ -949,6 +1163,9 @@ def text(
Sets the pen used to draw a rectangle around the text string
(see *clearance*) [Default is width = default, color = black,
style = solid].
+ {XY}
+ {p}
+ {t}
"""
kwargs = self._preprocess(**kwargs)
@@ -998,8 +1215,17 @@ def text(
lib.call_module("text", arg_str)
@fmt_docstring
- @use_alias(R="region", J="projection", B="frame", C="offset")
- @kwargs_to_strings(R="sequence")
+ @use_alias(
+ R="region",
+ J="projection",
+ B="frame",
+ C="offset",
+ X="xshift",
+ Y="yshift",
+ p="perspective",
+ t="transparency",
+ )
+ @kwargs_to_strings(R="sequence", p="sequence")
def meca(
self,
spec,
@@ -1094,6 +1320,9 @@ def meca(
{J}
{R}
{B}
+ {XY}
+ {p}
+ {t}
"""
# pylint warnings that need to be fixed
diff --git a/pygmt/helpers/decorators.py b/pygmt/helpers/decorators.py
index 0a11c37277c..376952891b4 100644
--- a/pygmt/helpers/decorators.py
+++ b/pygmt/helpers/decorators.py
@@ -53,6 +53,15 @@
"W": """\
pen : str
Set pen attributes for lines or the outline of symbols.""",
+ "XY": """\
+ xshift : str
+ ``[a|c|f|r][xshift]``.
+ Shift plot origin in x-direction.
+ yshift : str
+ ``[a|c|f|r][yshift]``.
+ Shift plot origin in y-direction. Full documentation is at
+ :gmt-docs:`gmt.html#xy-full`.
+ """,
"j": """\
distcalc : str
``e|f|g``.
@@ -77,11 +86,35 @@
- 'c' for bicubic [Default]
- 'l' for bilinear
- 'n' for nearest-neighbor""",
+ "p": """\
+ perspective : list or str
+ ``'[x|y|z]azim[/elev[/zlevel]][+wlon0/lat0[/z0]][+vx0/y0]'``.
+ Select perspective view and set the azimuth and elevation angle of
+ the viewpoint. Default is [180, 90]. Full documentation is at
+ :gmt-docs:`gmt.html#perspective-full`.
+ """,
"registration": """\
registration : str
``[g|p]``
Force output grid to be gridline (g) or pixel (p) node registered.
Default is gridline (g).""",
+ "t": """\
+ transparency : float
+ Set transparency level, in [0-100] percent range.
+ Default is 0, i.e., opaque.
+ Only visible when PDF or raster format output is selected.
+ Only the PNG format selection adds a transparency layer
+ in the image (for further processing). """,
+ "x": """\
+ cores : int
+ ``[[-]n]``.
+ Limit the number of cores to be used in any OpenMP-enabled
+ multi-threaded algorithms. By default we try to use all available
+ cores. Set a number *n* to only use n cores (if too large it will
+ be truncated to the maximum cores available). Finally, give a
+ negative number *-n* to select (all - n) cores (or at least 1 if
+ n equals or exceeds all).
+ """,
}
diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py
index 5b4bb731baa..5004e1b24cf 100644
--- a/pygmt/helpers/utils.py
+++ b/pygmt/helpers/utils.py
@@ -172,6 +172,11 @@ def is_nonstr_iter(value):
True
>>> is_nonstr_iter((1, 2, 3))
True
+ >>> import numpy as np
+ >>> is_nonstr_iter(np.array([1.0, 2.0, 3.0]))
+ True
+ >>> is_nonstr_iter(np.array(["abc", "def", "ghi"]))
+ True
"""
return isinstance(value, Iterable) and not isinstance(value, str)
diff --git a/pygmt/modules.py b/pygmt/modules.py
index 1cacf67d6df..477bc99221b 100644
--- a/pygmt/modules.py
+++ b/pygmt/modules.py
@@ -78,9 +78,10 @@ def info(table, **kwargs):
Parameters
----------
- table : pandas.DataFrame or np.ndarray or str
- Either a pandas dataframe, a 1D/2D numpy.ndarray or a file name to an
- ASCII data table.
+ table : str or np.ndarray or pandas.DataFrame or xarray.Dataset
+ Pass in either a file name to an ASCII data table, a 1D/2D numpy array,
+ a pandas dataframe, or an xarray dataset made up of 1D xarray.DataArray
+ data variables.
per_column : bool
Report the min/max values per column in separate columns.
spacing : str
@@ -107,10 +108,13 @@ def info(table, **kwargs):
if kind == "file":
file_context = dummy_context(table)
elif kind == "matrix":
- _table = np.asanyarray(table)
- if table.ndim == 1: # 1D arrays need to be 2D and transposed
- _table = np.transpose(np.atleast_2d(_table))
- file_context = lib.virtualfile_from_matrix(_table)
+ try:
+ # pandas.DataFrame and xarray.Dataset types
+ arrays = [array for _, array in table.items()]
+ except AttributeError:
+ # Python lists, tuples, and numpy ndarray types
+ arrays = np.atleast_2d(np.asanyarray(table).T)
+ file_context = lib.virtualfile_from_vectors(*arrays)
else:
raise GMTInvalidInput(f"Unrecognized data type: {type(table)}")
diff --git a/pygmt/tests/test_grdcontour.py b/pygmt/tests/test_grdcontour.py
index 2b45f2622d6..1ff3b3a2cb3 100644
--- a/pygmt/tests/test_grdcontour.py
+++ b/pygmt/tests/test_grdcontour.py
@@ -9,6 +9,7 @@
from .. import Figure
from ..exceptions import GMTInvalidInput
from ..datasets import load_earth_relief
+from ..helpers.testing import check_figures_equal
TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
@@ -21,49 +22,49 @@ def fixture_grid():
return load_earth_relief(registration="gridline")
-@pytest.mark.xfail(
- reason="Baseline image not updated to use earth relief grid in GMT 6.1.0",
-)
-@pytest.mark.mpl_image_compare
+@check_figures_equal()
def test_grdcontour(grid):
"""Plot a contour image using an xarray grid
with fixed contour interval
"""
- fig = Figure()
- fig.grdcontour(grid, interval="1000", projection="W0/6i")
- return fig
+ 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
-@pytest.mark.xfail(
- reason="Baseline image not updated to use earth relief grid in GMT 6.1.0",
-)
-@pytest.mark.mpl_image_compare
+@check_figures_equal()
def test_grdcontour_labels(grid):
"""Plot a contour image using a xarray grid
with contour labels and alternate colors
"""
- fig = Figure()
- fig.grdcontour(
- grid,
+ fig_ref, fig_test = Figure(), Figure()
+ kwargs = dict(
interval="1000",
annotation="5000",
projection="W0/6i",
pen=["a1p,red", "c0.5p,black"],
label_placement="d3i",
)
- return fig
+ fig_ref.grdcontour("@earth_relief_01d_g", **kwargs)
+ fig_test.grdcontour(grid, **kwargs)
+ return fig_ref, fig_test
-@pytest.mark.xfail(
- reason="Baseline image not updated to use earth relief grid in GMT 6.1.0",
-)
-@pytest.mark.mpl_image_compare
+@check_figures_equal()
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))
- fig = Figure()
- fig.grdcontour(grid_, interval="1000", projection="M6i")
- return fig
+ 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
@pytest.mark.mpl_image_compare
diff --git a/pygmt/tests/test_grdimage.py b/pygmt/tests/test_grdimage.py
index d86798178f3..8b9fac9acd8 100644
--- a/pygmt/tests/test_grdimage.py
+++ b/pygmt/tests/test_grdimage.py
@@ -71,7 +71,7 @@ def test_grdimage_file():
@pytest.mark.xfail(reason="Upstream bug in GMT 6.1.1")
@check_figures_equal()
-def test_grdimage_xarray_shading(grid, fig_ref, fig_test):
+def test_grdimage_xarray_shading(grid):
"""
Test that shading works well for xarray.
See https://github.com/GenericMappingTools/pygmt/issues/364
diff --git a/pygmt/tests/test_info.py b/pygmt/tests/test_info.py
index 142b56dce8e..92e7616adc6 100644
--- a/pygmt/tests/test_info.py
+++ b/pygmt/tests/test_info.py
@@ -8,13 +8,17 @@
import pandas as pd
import pytest
import xarray as xr
+from packaging.version import Version
-from .. import info
+from .. import clib, info
from ..exceptions import GMTInvalidInput
TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
POINTS_DATA = os.path.join(TEST_DATA_DIR, "points.txt")
+with clib.Session() as _lib:
+ gmt_version = Version(_lib.info["version"])
+
def test_info():
"Make sure info works on file name inputs"
@@ -33,7 +37,48 @@ def test_info_dataframe():
table = pd.read_csv(POINTS_DATA, sep=" ", header=None)
output = info(table=table)
expected_output = (
- ": N = 20 <11.5309/61.7074> <-2.9289/7.8648> <0.1412/0.9338>\n"
+ ": N = 20 <11.5309/61.7074> <-2.9289/7.8648> <0.1412/0.9338>\n"
+ )
+ assert output == expected_output
+
+
+@pytest.mark.xfail(
+ condition=gmt_version <= Version("6.1.1"),
+ 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"
+ table = pd.DataFrame(
+ data={
+ "z": [10, 13, 12, 15, 14],
+ "time": pd.date_range(start="2020-01-01", periods=5),
+ }
+ )
+ output = info(table=table)
+ expected_output = (
+ ": N = 5 <10/15> <2020-01-01T00:00:00/2020-01-05T00:00:00>\n"
+ )
+ assert output == expected_output
+
+
+@pytest.mark.xfail(
+ condition=gmt_version <= Version("6.1.1"),
+ 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"
+ table = xr.Dataset(
+ coords={"index": [0, 1, 2, 3, 4]},
+ data_vars={
+ "z": ("index", [10, 13, 12, 15, 14]),
+ "time": ("index", pd.date_range(start="2020-01-01", periods=5)),
+ },
+ )
+ output = info(table=table)
+ expected_output = (
+ ": N = 5 <10/15> <2020-01-01T00:00:00/2020-01-05T00:00:00>\n"
)
assert output == expected_output
@@ -43,7 +88,7 @@ def test_info_2d_array():
table = np.loadtxt(POINTS_DATA)
output = info(table=table)
expected_output = (
- ": N = 20 <11.5309/61.7074> <-2.9289/7.8648> <0.1412/0.9338>\n"
+ ": N = 20 <11.5309/61.7074> <-2.9289/7.8648> <0.1412/0.9338>\n"
)
assert output == expected_output
@@ -51,7 +96,7 @@ def test_info_2d_array():
def test_info_1d_array():
"Make sure info works on 1D numpy.ndarray inputs"
output = info(table=np.arange(20))
- expected_output = ": N = 20 <0/19>\n"
+ expected_output = ": N = 20 <0/19>\n"
assert output == expected_output
diff --git a/pygmt/x2sys.py b/pygmt/x2sys.py
index 22294c3e791..e3803ba7806 100644
--- a/pygmt/x2sys.py
+++ b/pygmt/x2sys.py
@@ -206,8 +206,8 @@ def x2sys_cross(tracks=None, outfile=None, **kwargs):
in the current directory and second in all directories listed in
$X2SYS_HOME/TAG/TAG_paths.txt (if it exists). [If $X2SYS_HOME is not
set it will default to $GMT_SHAREDIR/x2sys]. (Note: MGD77 files will
- also be looked for via $MGD77_HOME/mgd77_paths.txt and *.gmt files will
- be searched for via $GMT_SHAREDIR/mgg/gmtfile_paths).
+ also be looked for via $MGD77_HOME/mgd77_paths.txt and \\*.gmt files
+ will be searched for via $GMT_SHAREDIR/mgg/gmtfile_paths).
outfile : str
Optional. The file name for the output ASCII txt file to store the
@@ -271,7 +271,7 @@ def x2sys_cross(tracks=None, outfile=None, **kwargs):
headings will not be computed (i.e., set to NaN) [Default calculates \
headings regardless of speed].
- For example, you can use ``speed=["l0", "u10", "h5"] to set a lower
+ For example, you can use ``speed=["l0", "u10", "h5"]`` to set a lower
speed of 0, upper speed of 10, and disable heading calculations for
speeds below 5.