-
Notifications
You must be signed in to change notification settings - Fork 225
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new modules to plot horizontal and vertical lines
As discussed in #670 here's a new module (**hlines**) to plot a single or a set of horizontal lines with only defining the desired y-value(s). For discussion I only add the module for horizontal lines at the moment, however, the adjustments to prepare the same for vertical lines is done very quickly.
- Loading branch information
1 parent
87cb403
commit 7ed3b49
Showing
1 changed file
with
155 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
""" | ||
hlines - Plot horizontal lines. | ||
""" | ||
import numpy as np | ||
from pygmt.clib import Session | ||
from pygmt.exceptions import GMTInvalidInput | ||
from pygmt.helpers import build_arg_string, fmt_docstring, use_alias, kwargs_to_strings, data_kind | ||
|
||
@fmt_docstring | ||
@use_alias( | ||
B="frame", | ||
C="cmap", | ||
D="offset", | ||
J="projection", | ||
N="no_clip", | ||
R="region", | ||
U="timestamp", | ||
V="verbose", | ||
W="pen", | ||
X="xshift", | ||
Y="yshift", | ||
Z="zvalue", | ||
l="label", | ||
p="perspective", | ||
t="transparency", | ||
) | ||
@kwargs_to_strings(R="sequence", p="sequence") | ||
def hlines(self, y=None, xmin=None, xmax=None, pen=None, label=None, **kwargs): | ||
"""" | ||
Plot one or a collection of horizontal lines | ||
Takes a single y value or a list of individual y values and optionally | ||
lower and upper x value limits as input. | ||
Must provide *y*. | ||
If y values are given without x limits then the current map boundaries are | ||
used as lower and upper limits. If only a single set of x limits is given then | ||
all lines will have the same length, otherwise give x limits for each individual | ||
line. If only a single label is given then all lines are grouped under this label | ||
in the legend (if shown). If each line should appear as a single entry in the | ||
legend, give corresponding labels for all lines (same for **pen**). | ||
Parameters | ||
---------- | ||
y : float or 1d array | ||
The y coordinates or an array of y coordinates of the | ||
horizontal lines to plot. | ||
{J} | ||
{R} | ||
{B} | ||
{CPT} | ||
offset : str | ||
``dx/dy``. | ||
Offset the line locations by the given amounts | ||
*dx/dy* [Default is no offset]. If *dy* is not given it is set | ||
equal to *dx*. | ||
no_clip : bool or str | ||
``'[c|r]'``. | ||
Do NOT clip lines that fall outside map border [Default plots | ||
lines whose coordinates are strictly inside the map border only]. | ||
The option does not apply to lines which are always | ||
clipped to the map region. For periodic (360-longitude) maps we | ||
must plot all lines twice in case they are clipped by the | ||
repeating boundary. ``no_clip=True`` will turn off clipping and not | ||
plot repeating lines. Use ``no_clip="r"`` to turn off clipping | ||
but retain the plotting of such repeating lines, or use | ||
``no_clip="c"`` to retain clipping but turn off plotting of | ||
repeating lines. | ||
{W} | ||
{U} | ||
{V} | ||
{XY} | ||
zvalue : str or float | ||
``value``. | ||
Instead of specifying a line color via **pen**, give it a *value* | ||
via **zvalue** and a color lookup table via **cmap**. Requires appending | ||
**+z** to **pen** (e.g. ``pen = "5p,+z"``, ``zvalue = 0.8``, | ||
* ``cmap = "viridis"``). | ||
label : str | ||
Add a legend entry for the line being plotted. | ||
{p} | ||
{t} | ||
*transparency* can also be a 1d array to set varying transparency | ||
for lines. | ||
""" | ||
|
||
kwargs = self._preprocess(**kwargs) | ||
|
||
list_length = len(np.atleast_1d(y)) | ||
|
||
# prepare x vals | ||
if xmin is None and xmax is None: | ||
# get limits from current map boundings if not given via xmin, xmax | ||
with Session() as lib: | ||
mapbnds = lib.extract_region() | ||
x = np.array([[mapbnds[0]], [mapbnds[1]]]) | ||
x = np.repeat(x, list_length, axis=1) | ||
elif xmin is None or xmax is None: | ||
raise GMTInvalidInput("Must provide both, xmin and xmax if limits are not set automatically.") | ||
|
||
else: | ||
# if only a single xmin and xmax without [], repeat to fit size of y | ||
if isinstance(xmin, int) or isinstance(xmin, float): | ||
x = np.array([[xmin], [xmax]]) | ||
x = np.repeat(x, list_length, axis=1) | ||
else: | ||
if len(xmin) != len(xmax): | ||
GMTInvalidInput("Must provide same length for xmin and xmax.") | ||
else: | ||
x = np.array([xmin, xmax]) | ||
|
||
# prepare labels | ||
if "l" in kwargs: | ||
# if several lines belong to the same label, first take the label, | ||
# then set all to None and reset the first entry to the given label | ||
if not isinstance(kwargs["l"], list): | ||
label2use = kwargs["l"] | ||
kwargs["l"] = np.repeat(None, list_length) | ||
kwargs["l"][0] = label2use | ||
else: | ||
kwargs["l"] = np.repeat(None, list_length) | ||
|
||
|
||
# prepare pens | ||
if "W" in kwargs: | ||
# select pen, no series | ||
if not isinstance(kwargs["W"], list): | ||
pen2use = kwargs["W"] | ||
kwargs["W"] = np.repeat(pen2use, list_length) | ||
else: # use as default if no pen is given (neither single nor series) | ||
kwargs["W"] = np.repeat("1p,black", list_length) | ||
|
||
# loop over entries | ||
kwargs_copy = kwargs.copy() | ||
|
||
for index in range(list_length): | ||
y2plt = [np.atleast_1d(y)[index], np.atleast_1d(y)[index]] | ||
x2plt = [np.atleast_1d(x)[0][index], np.atleast_1d(x)[1][index]] | ||
kind = data_kind(None, x2plt, y2plt) | ||
|
||
with Session() as lib: | ||
if kind == "vectors": | ||
file_context = lib.virtualfile_from_vectors( | ||
np.atleast_1d(x2plt), np.atleast_1d(y2plt)) | ||
else: | ||
raise GMTInvalidInput("Unrecognized data type.") | ||
|
||
kwargs["l"] = kwargs_copy["l"][index] | ||
kwargs["W"] = kwargs_copy["W"][index] | ||
|
||
with file_context as fname: | ||
arg_str = " ".join([fname, build_arg_string(kwargs)]) | ||
lib.call_module("plot", arg_str) |