"""
plot - Plot in two dimensions.
"""
from pathlib import Path
from pygmt.clib import Session
from pygmt.exceptions import GMTInvalidInput
from pygmt.helpers import (
build_arg_list,
data_kind,
fmt_docstring,
is_nonstr_iter,
kwargs_to_strings,
use_alias,
)
from pygmt.src.which import which
@fmt_docstring
@use_alias(
A="straight_line",
B="frame",
C="cmap",
D="offset",
E="error_bar",
F="connection",
G="fill",
I="intensity",
J="projection",
L="close",
N="no_clip",
R="region",
S="style",
V="verbose",
W="pen",
Z="zvalue",
a="aspatial",
b="binary",
c="panel",
d="nodata",
e="find",
f="coltypes",
g="gap",
h="header",
i="incols",
l="label",
p="perspective",
t="transparency",
w="wrap",
)
@kwargs_to_strings(R="sequence", c="sequence_comma", i="sequence_comma", p="sequence")
def plot( # noqa: PLR0912
self, data=None, x=None, y=None, size=None, direction=None, **kwargs
):
r"""
Plot lines, polygons, and symbols in 2-D.
Takes a matrix, (x,y) pairs, or a file name as input and plots lines,
polygons, or symbols at those locations on a map.
Must provide either ``data`` or ``x``/``y``.
If providing data through ``x``/``y``, ``fill`` can be a 1-D array that
will be mapped to a colormap.
If a symbol is selected and no symbol size given, then plot will
interpret the third column of the input data as symbol size. Symbols
whose size is <= 0 are skipped. If no symbols are specified then the
symbol code (see ``style`` below) must be present as last column in the
input. If ``style`` is not used, a line connecting the data points will
be drawn instead. To explicitly close polygons, use ``close``. Select a
fill with ``fill``. If ``fill`` is set, ``pen`` will control whether the
polygon outline is drawn or not. If a symbol is selected, ``fill`` and
``pen`` determine the fill and outline/no outline, respectively.
Full option list at :gmt-docs:`plot.html`
{aliases}
Parameters
----------
data : str, {table-like}
Pass in either a file name to an ASCII data table, a 2-D
{table-classes}.
Use parameter ``incols`` to choose which columns are x, y, fill, and
size, respectively.
x/y : float or 1-D arrays
The x and y coordinates, or arrays of x and y coordinates of the
data points
size : 1-D array
The size of the data points in units specified using ``style``.
Only valid if using ``x``/``y``.
direction : list of two 1-D arrays
If plotting vectors (using ``style="V"`` or ``style="v"``), then
should be a list of two 1-D arrays with the vector directions. These
can be angle and length, azimuth and length, or x and y components,
depending on the style options chosen.
{projection}
{region}
straight_line : bool or str
[**m**\|\ **p**\|\ **x**\|\ **y**].
By default, geographic line segments are drawn as great circle
arcs. To draw them as straight lines, use
``straight_line=True``.
Alternatively, add **m** to draw the line by first following a
meridian, then a parallel. Or append **p** to start following a
parallel, then a meridian. (This can be practical to draw a line
along parallels, for example). For Cartesian data, points are
simply connected, unless you append **x** or **y** to draw
stair-case curves that whose first move is along *x* or *y*,
respectively.
{frame}
{cmap}
offset : str
*dx*/*dy*.
Offset the plot symbol or line locations by the given amounts
*dx/dy* [Default is no offset]. If *dy* is not given it is set
equal to *dx*.
error_bar : bool or str
[**x**\|\ **y**\|\ **X**\|\ **Y**][**+a**\|\ **A**]\
[**+cl**\|\ **f**][**+n**][**+w**\ *cap*][**+p**\ *pen*].
Draw error bars. Full documentation is at
:gmt-docs:`plot.html#e`.
connection : str
[**c**\|\ **n**\|\ **p**][**a**\|\ **r**\|\ **s**\|\ **t**\|\ *refpoint*].
Alter the way points are connected (by specifying a *scheme*) and data are
grouped (by specifying a *method*). Append one of three line connection schemes:
- **c**: Draw continuous line segments for each group [Default].
- **n**: Draw networks of line segments between all points in each group.
- **p**: Draw line segments from a reference point reset for each group.
Optionally, append the one of four segmentation methods to define the group:
- **a**: Ignore all segment headers, i.e., let all points belong to a single
group, and set group the reference point to the very first point of the first
file.
- **r**: Segment headers are honored so each segment is a group; the group
reference point is reset after each record to the previous point (this method
is only available with the ``connection="p"`` scheme).
- **s**: Same as **r**, but the group reference point is reset to the first
point of each incoming segment [Default].
- **t**: Consider all data in each file to be a single separate group and reset
the group reference point to the first point of each group.
Instead of the codes **a**\|\ **r**\|\ **s**\|\ **t** you may append the
coordinates of a *refpoint* which will serve as a fixed external reference point
for all groups.
{fill}
*fill* can be a 1-D array, but it is only valid if using ``x``/``y``
and ``cmap=True`` is also required.
intensity : float, bool, or 1-D array
Provide an *intensity* value (nominally in the -1 to +1 range) to
modulate the fill color by simulating illumination. If using
``intensity=True``, we will instead read *intensity* from the first
data column after the symbol parameters (if given). *intensity* can
also be a 1-D array to set varying intensity for symbols, but it is
only valid for ``x``/``y`` pairs.
close : str
[**+b**\|\ **d**\|\ **D**][**+xl**\|\ **r**\|\ *x0*]\
[**+yl**\|\ **r**\|\ *y0*][**+p**\ *pen*].
Force closed polygons. Full documentation is at
:gmt-docs:`plot.html#l`.
no_clip : bool or str
[**c**\|\ **r**].
Do **not** clip symbols that fall outside the frame boundaries
[Default plots points whose coordinates are strictly inside the
frame boundaries only].
The parameter does not apply to lines and polygons which are always
clipped to the map region. For periodic (360-longitude) maps we
must plot all symbols twice in case they are clipped by the
repeating boundary. ``no_clip=True`` will turn off clipping and not
plot repeating symbols. Use ``no_clip="r"`` to turn off clipping
but retain the plotting of such repeating symbols, or use
``no_clip="c"`` to retain clipping but turn off plotting of
repeating symbols.
style : str
Plot symbols (including vectors, pie slices, fronts, decorated or
quoted lines).
{pen}
{verbose}
zvalue : str
*value*\|\ *file*.
Instead of specifying a symbol or polygon fill and outline color
via ``fill`` and ``pen``, give both a *value* via ``zvalue`` and a
color lookup table via ``cmap``. Alternatively, give the name of a
*file* with one z-value (read from the last column) for each
polygon in the input data. To apply it to the fill color, use
``fill="+z"``. To apply it to the pen color, append **+z** to
``pen``.
{aspatial}
{binary}
{panel}
{nodata}
{find}
{coltypes}
{gap}
{header}
{incols}
{label}
{perspective}
{transparency}
``transparency`` can also be a 1-D array to set varying
transparency for symbols, but this option is only valid if using
``x``/``y``.
{wrap}
"""
kwargs = self._preprocess(**kwargs)
kind = data_kind(data, x, y)
extra_arrays = []
if kind == "vectors": # Add more columns for vectors input
# Parameters for vector styles
if (
kwargs.get("S") is not None
and kwargs["S"][0] in "vV"
and is_nonstr_iter(direction)
):
extra_arrays.extend(direction)
# Fill
if is_nonstr_iter(kwargs.get("G")):
extra_arrays.append(kwargs.get("G"))
del kwargs["G"]
# Size
if is_nonstr_iter(size):
extra_arrays.append(size)
# Intensity and transparency
for flag in ["I", "t"]:
if is_nonstr_iter(kwargs.get(flag)):
extra_arrays.append(kwargs.get(flag))
kwargs[flag] = ""
else:
for name, value in [
("direction", direction),
("fill", kwargs.get("G")),
("size", size),
("intensity", kwargs.get("I")),
("transparency", kwargs.get("t")),
]:
if is_nonstr_iter(value):
raise GMTInvalidInput(f"'{name}' can't be 1-D array if 'data' is used.")
# Set the default style if data has a geometry of Point or MultiPoint
if kwargs.get("S") is None:
if kind == "geojson" and data.geom_type.isin(["Point", "MultiPoint"]).all():
kwargs["S"] = "s0.2c"
elif kind == "file" and str(data).endswith(".gmt"): # OGR_GMT file
try:
with Path(which(data)).open() as file:
line = file.readline()
if "@GMULTIPOINT" in line or "@GPOINT" in line:
kwargs["S"] = "s0.2c"
except FileNotFoundError:
pass
with Session() as lib:
with lib.virtualfile_in(
check_kind="vector", data=data, x=x, y=y, extra_arrays=extra_arrays
) as vintbl:
lib.call_module(module="plot", args=build_arg_list(kwargs, infile=vintbl))