-
Notifications
You must be signed in to change notification settings - Fork 228
Add Figure.hlines for plotting horizontal lines #923
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
77 commits
Select commit
Hold shift + click to select a range
7ed3b49
Add new modules to plot horizontal and vertical lines
michaelgrund 096b9de
added further content
michaelgrund 92fa9c0
added some first tests
michaelgrund 975b305
some formatting
michaelgrund f25a89c
corrected typo
michaelgrund 3cee081
Merge branch 'master' into hlines-module
michaelgrund a0c29fc
Merge branch 'master' into hlines-module
michaelgrund 51dcb6a
Merge branch 'master' into hlines-module
michaelgrund 4fdc984
Merge branch 'master' into hlines-module
michaelgrund 154d05e
Merge branch 'master' into hlines-module
michaelgrund ddd04b4
Merge branch 'master' into hlines-module
michaelgrund d0bc35c
moved gallery example to new subfolder /lines
michaelgrund 450d8de
Merge branch 'master' into hlines-module
michaelgrund f75fbe1
disable pylint warnings
michaelgrund a375a77
replace hyphen by underscore in gallery example file name
michaelgrund 71113dd
disable pylint warnings
michaelgrund 1438d43
formatting
michaelgrund e3a564e
Merge branch 'master' into hlines-module
michaelgrund d6a8fa5
Merge branch 'master' into hlines-module
michaelgrund ff13180
Merge branch 'master' into hlines-module
michaelgrund 1881e95
Merge branch 'master' into hlines-module
michaelgrund 7222e9b
Merge branch 'main' into hlines-module
michaelgrund 65eb85d
update hlines module
michaelgrund 2353587
Merge branch 'hlines-module' of https://github.com/GenericMappingTool…
michaelgrund 49008ed
formatting
michaelgrund 457bf72
adjust docstring
michaelgrund f2c84a7
adjust priliminary tests
michaelgrund 50dccf9
Merge branch 'main' into hlines-module
michaelgrund e7726c0
update
michaelgrund 60d6e55
Merge branch 'hlines-module' of https://github.com/GenericMappingTool…
michaelgrund 46f8702
formatting
michaelgrund 5648778
Merge branch 'main' into hlines-module
michaelgrund d553e28
Merge branch 'main' into hlines-module
michaelgrund d493a1c
Update pygmt/src/hlines.py
michaelgrund 92bfca5
Merge branch 'main' into hlines-module
seisman ed7de94
Fix styling
seisman 1ae727a
Simplify the logic of codes
seisman 8fee6a8
Remove the gallery example
seisman 67b1497
Finalize hlines source code
seisman cd0ce35
Fix hlines
seisman e60b064
Add tests for Figure.hlines
seisman f28dce0
Fix the order in the API docs
seisman 4816dbb
Skip doctest
seisman 49c2e97
Improve type hints
seisman a40ff00
Simplify type hints
seisman d657fe3
Support for horizontal lines in geographic projections
seisman a8bd1a0
Add tests for polar projection
seisman 457e8eb
Fix tests for polar
seisman a2b7223
Add tests for no_clip
seisman 258a64f
Improve docstrings
seisman ad09ece
Merge branch 'main' into hlines-module
seisman 4e26a6f
Merge branch 'main' into hlines-module
seisman 9e17bdf
Use straight_line='p' although it makes no difference
seisman 25cbeb4
Transparency should be set by 'pen' instead
seisman afe7592
Merge branch 'main' into hlines-module
seisman 6556500
Refactor the codes for handling y/xmin/xmax
seisman fc1898c
Simplify the checking
seisman 7ef0406
Fix reference to Figure.plot
seisman 354e090
Merge branch 'main' into hlines-module
seisman 7a20b8c
Merge branch 'main' into hlines-module
seisman 762bf4e
Fix a typo [skip ci]
seisman d88b9c2
Merge branch 'main' into hlines-module
seisman 982112f
Merge branch 'main' into hlines-module
seisman 5440bf8
Fix typos
seisman 00662cf
Merge branch 'main' into hlines-module
seisman 7299827
Merge branch 'main' into hlines-module
seisman 118baf7
Merge branch 'main' into hlines-module
seisman 5c99205
Merge branch 'main' into hlines-module
seisman e2cddd2
Merge branch 'main' into hlines-module
seisman d79c2b6
Merge branch 'main' into hlines-module
seisman 5a0989f
Change straight_line='p' to 'x'
seisman af63f37
Merge branch 'main' into hlines-module
seisman f673b76
Merge branch 'main' into hlines-module
yvonnefroehlich cc6c83f
Apply suggestions from code review
seisman 635d8e6
Update baseline image
seisman edd804e
Merge branch 'main' into hlines-module
seisman 1e643c1
[format-command] fixes
actions-bot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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 |
---|---|---|
|
@@ -417,6 +417,7 @@ def _repr_html_(self) -> str: | |
grdimage, | ||
grdview, | ||
histogram, | ||
hlines, | ||
image, | ||
inset, | ||
legend, | ||
|
This file contains hidden or 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
This file contains hidden or 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,137 @@ | ||
""" | ||
hlines - Plot horizontal lines. | ||
""" | ||
|
||
from collections.abc import Sequence | ||
|
||
import numpy as np | ||
from pygmt.exceptions import GMTInvalidInput | ||
|
||
__doctest_skip__ = ["hlines"] | ||
|
||
|
||
def hlines( | ||
self, | ||
y: float | Sequence[float], | ||
xmin: float | Sequence[float] | None = None, | ||
xmax: float | Sequence[float] | None = None, | ||
pen: str | None = None, | ||
label: str | None = None, | ||
no_clip: bool = False, | ||
perspective: str | bool | None = None, | ||
): | ||
""" | ||
Plot one or multiple horizontal line(s). | ||
|
||
This method is a high-level wrapper around :meth:`pygmt.Figure.plot` that focuses on | ||
plotting horizontal lines at Y-coordinates specified by the ``y`` parameter. The | ||
``y`` parameter can be a single value (for a single horizontal line) or a sequence | ||
of values (for multiple horizontal lines). | ||
|
||
By default, the X-coordinates of the start and end points of the lines are set to | ||
be the X-limits of the current plot, but this can be overridden by specifying the | ||
``xmin`` and ``xmax`` parameters. ``xmin`` and ``xmax`` can be either a single | ||
value or a sequence of values. If a single value is provided, it is applied to all | ||
lines. If a sequence is provided, the length of ``xmin`` and ``xmax`` must match | ||
the length of ``y``. | ||
|
||
The term "horizontal" lines can be interpreted differently in different coordinate | ||
systems: | ||
|
||
- **Cartesian** coordinate system: lines are plotted as straight lines. | ||
- **Polar** projection: lines are plotted as arcs along a constant radius. | ||
- **Geographic** projection: lines are plotted as parallels along constant latitude. | ||
|
||
Parameters | ||
---------- | ||
y | ||
Y-coordinates to plot the lines. It can be a single value (for a single line) | ||
or a sequence of values (for multiple lines). | ||
xmin/xmax | ||
X-coordinates of the start/end point of the line(s). If ``None``, defaults to | ||
the X-limits of the current plot. ``xmin`` and ``xmax`` can be either a single | ||
value or a sequence of values. If a single value is provided, it is applied to | ||
all lines. If a sequence is provided, the length of ``xmin`` and ``xmax`` must | ||
match the length of ``y``. | ||
pen | ||
Pen attributes for the line(s), in the format of *width,color,style*. | ||
label | ||
Label for the line(s), to be displayed in the legend. | ||
no_clip | ||
If ``True``, do not clip lines outside the plot region. Only makes sense in the | ||
Cartesian coordinate system. | ||
perspective | ||
Select perspective view and set the azimuth and elevation angle of the | ||
viewpoint. Refer to :meth:`pygmt.Figure.plot` for details. | ||
|
||
Examples | ||
-------- | ||
>>> import pygmt | ||
>>> fig = pygmt.Figure() | ||
>>> fig.basemap(region=[0, 10, 0, 10], projection="X10c/10c", frame=True) | ||
>>> fig.hlines(y=1, pen="1p,black", label="Line at y=1") | ||
>>> fig.hlines(y=2, xmin=2, xmax=8, pen="1p,red,-", label="Line at y=2") | ||
>>> fig.hlines(y=[3, 4], xmin=3, xmax=7, pen="1p,black,.", label="Lines at y=3,4") | ||
>>> fig.hlines(y=[5, 6], xmin=4, xmax=9, pen="1p,red", label="Lines at y=5,6") | ||
>>> fig.hlines( | ||
... y=[7, 8], xmin=[0, 1], xmax=[7, 8], pen="1p,blue", label="Lines at y=7,8" | ||
... ) | ||
>>> fig.legend() | ||
>>> fig.show() | ||
""" | ||
self._preprocess() | ||
|
||
# Determine the x limits from the current plot region if not specified. | ||
if xmin is None or xmax is None: | ||
xlimits = self.region[:2] | ||
if xmin is None: | ||
xmin = xlimits[0] | ||
if xmax is None: | ||
xmax = xlimits[1] | ||
|
||
# Ensure y/xmin/xmax are 1-D arrays. | ||
_y = np.atleast_1d(y) | ||
_xmin = np.atleast_1d(xmin) | ||
_xmax = np.atleast_1d(xmax) | ||
|
||
nlines = len(_y) # Number of lines to plot. | ||
|
||
# Check if xmin/xmax are scalars or have the expected length. | ||
if _xmin.size not in {1, nlines} or _xmax.size not in {1, nlines}: | ||
msg = ( | ||
f"'xmin' and 'xmax' are expected to be scalars or have lengths '{nlines}', " | ||
f"but lengths '{_xmin.size}' and '{_xmax.size}' are given." | ||
) | ||
raise GMTInvalidInput(msg) | ||
|
||
# Repeat xmin/xmax to match the length of y if they are scalars. | ||
if nlines != 1: | ||
if _xmin.size == 1: | ||
_xmin = np.repeat(_xmin, nlines) | ||
if _xmax.size == 1: | ||
_xmax = np.repeat(_xmax, nlines) | ||
|
||
# Call the Figure.plot method to plot the lines. | ||
for i in range(nlines): | ||
# Special handling for label. | ||
# 1. Only specify a label when plotting the first line. | ||
# 2. The -l option can accept comma-separated labels for labeling multiple lines | ||
# with auto-coloring enabled. We don't need this feature here, so we need to | ||
# replace comma with \054 if the label contains commas. | ||
_label = label.replace(",", "\\054") if label and i == 0 else None | ||
|
||
# By default, points are connected as great circle arcs in geographic coordinate | ||
# systems and straight lines in Cartesian coordinate systems (including polar | ||
# projection). To plot "horizontal" lines along constant latitude (in geographic | ||
# coordinate systems) or constant radius (in polar projection), we need to | ||
# resample the line to at least 4 points. | ||
npoints = 4 # 2 for Cartesian, at least 4 for geographic and polar projections. | ||
self.plot( | ||
x=np.linspace(_xmin[i], _xmax[i], npoints), | ||
y=[_y[i]] * npoints, | ||
pen=pen, | ||
label=_label, | ||
no_clip=no_clip, | ||
perspective=perspective, | ||
straight_line="x", | ||
) |
This file contains hidden or 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,5 @@ | ||
outs: | ||
- md5: e87ea1b80ae5d32d49e9ad94a5c25f96 | ||
size: 7199 | ||
hash: md5 | ||
path: test_hlines_clip.png |
This file contains hidden or 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,5 @@ | ||
outs: | ||
- md5: b7055f03ff5bc152c0f6b72f2d39f32c | ||
size: 29336 | ||
hash: md5 | ||
path: test_hlines_geographic_global_d.png |
This file contains hidden or 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,5 @@ | ||
outs: | ||
- md5: ab2e7717cad6ac4132fd3e3af1fefa89 | ||
size: 29798 | ||
hash: md5 | ||
path: test_hlines_geographic_global_g.png |
This file contains hidden or 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,5 @@ | ||
outs: | ||
- md5: 70c8decbffd37fc48b2eb9ff84442ec0 | ||
size: 14139 | ||
hash: md5 | ||
path: test_hlines_multiple_lines.png |
This file contains hidden or 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,5 @@ | ||
outs: | ||
- md5: 121970f75d34c552e632cacc692f09e9 | ||
size: 13685 | ||
hash: md5 | ||
path: test_hlines_one_line.png |
This file contains hidden or 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,5 @@ | ||
outs: | ||
- md5: 0c0eeb160dd6beb06bb6d3dcc264127a | ||
size: 57789 | ||
hash: md5 | ||
path: test_hlines_polar_projection.png |
This file contains hidden or 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,121 @@ | ||
""" | ||
Tests for Figure.hlines. | ||
""" | ||
|
||
import pytest | ||
from pygmt import Figure | ||
from pygmt.exceptions import GMTInvalidInput | ||
|
||
|
||
@pytest.mark.mpl_image_compare | ||
def test_hlines_one_line(): | ||
""" | ||
Plot one horizontal line. | ||
""" | ||
fig = Figure() | ||
fig.basemap(region=[0, 10, 0, 10], projection="X10c/10c", frame=True) | ||
fig.hlines(1) | ||
fig.hlines(2, xmin=1) | ||
fig.hlines(3, xmax=9) | ||
fig.hlines(4, xmin=3, xmax=8) | ||
fig.hlines(5, xmin=4, xmax=8, pen="1p,blue", label="Line at y=5") | ||
fig.hlines(6, xmin=5, xmax=7, pen="1p,red", label="Line at y=6") | ||
fig.legend() | ||
return fig | ||
|
||
|
||
@pytest.mark.mpl_image_compare | ||
def test_hlines_multiple_lines(): | ||
""" | ||
Plot multiple horizontal lines. | ||
""" | ||
fig = Figure() | ||
fig.basemap(region=[0, 10, 0, 16], projection="X10c/10c", frame=True) | ||
fig.hlines([1, 2]) | ||
fig.hlines([3, 4, 5], xmin=[1, 2, 3]) | ||
fig.hlines([6, 7, 8], xmax=[7, 8, 9]) | ||
fig.hlines([9, 10], xmin=[1, 2], xmax=[9, 10]) | ||
fig.hlines([11, 12], xmin=1, xmax=9, pen="1p,blue", label="Lines at y=11,12") | ||
fig.hlines( | ||
[13, 14], xmin=[3, 4], xmax=[8, 9], pen="1p,red", label="Lines at y=13,14" | ||
) | ||
fig.legend() | ||
return fig | ||
|
||
|
||
@pytest.mark.mpl_image_compare | ||
def test_hlines_clip(): | ||
""" | ||
Plot horizontal lines with clipping or not. | ||
""" | ||
fig = Figure() | ||
fig.basemap(region=[0, 10, 0, 4], projection="X10c/4c", frame=True) | ||
fig.hlines(1, xmin=-2, xmax=12) | ||
fig.hlines(2, xmin=-2, xmax=12, no_clip=True) | ||
return fig | ||
|
||
|
||
@pytest.mark.mpl_image_compare | ||
@pytest.mark.parametrize("region", ["g", "d"]) | ||
def test_hlines_geographic_global(region): | ||
""" | ||
Plot horizontal lines in geographic coordinates. | ||
""" | ||
fig = Figure() | ||
fig.basemap(region=region, projection="R15c", frame=True) | ||
# Plot lines with longitude range of 0 to 360. | ||
fig.hlines(10, pen="1p") | ||
fig.hlines(20, xmin=0, xmax=360, pen="1p") | ||
fig.hlines(30, xmin=0, xmax=180, pen="1p") | ||
fig.hlines(40, xmin=180, xmax=360, pen="1p") | ||
fig.hlines(50, xmin=0, xmax=90, pen="1p") | ||
fig.hlines(60, xmin=90, xmax=180, pen="1p") | ||
fig.hlines(70, xmin=180, xmax=270, pen="1p") | ||
fig.hlines(80, xmin=270, xmax=360, pen="1p") | ||
|
||
# Plot lines with longitude range of -180 to 180. | ||
fig.hlines(-10, pen="1p,red") | ||
fig.hlines(-20, xmin=-180, xmax=180, pen="1p,red") | ||
fig.hlines(-30, xmin=-180, xmax=0, pen="1p,red") | ||
fig.hlines(-40, xmin=0, xmax=180, pen="1p,red") | ||
fig.hlines(-50, xmin=-180, xmax=-90, pen="1p,red") | ||
fig.hlines(-60, xmin=-90, xmax=0, pen="1p,red") | ||
fig.hlines(-70, xmin=0, xmax=90, pen="1p,red") | ||
fig.hlines(-80, xmin=90, xmax=180, pen="1p,red") | ||
return fig | ||
|
||
|
||
@pytest.mark.mpl_image_compare | ||
def test_hlines_polar_projection(): | ||
""" | ||
Plot horizontal lines in polar projection. | ||
""" | ||
fig = Figure() | ||
fig.basemap(region=[0, 360, 0, 1], projection="P15c", frame=True) | ||
fig.hlines(0.1, pen="1p") | ||
fig.hlines(0.2, xmin=0, xmax=360, pen="1p") | ||
fig.hlines(0.3, xmin=0, xmax=180, pen="1p") | ||
fig.hlines(0.4, xmin=180, xmax=360, pen="1p") | ||
fig.hlines(0.5, xmin=0, xmax=90, pen="1p") | ||
fig.hlines(0.6, xmin=90, xmax=180, pen="1p") | ||
fig.hlines(0.7, xmin=180, xmax=270, pen="1p") | ||
fig.hlines(0.8, xmin=270, xmax=360, pen="1p") | ||
return fig | ||
|
||
|
||
def test_hlines_invalid_input(): | ||
""" | ||
Test invalid input for hlines. | ||
""" | ||
fig = Figure() | ||
fig.basemap(region=[0, 10, 0, 6], projection="X10c/6c", frame=True) | ||
with pytest.raises(GMTInvalidInput): | ||
fig.hlines(1, xmin=2, xmax=[3, 4]) | ||
with pytest.raises(GMTInvalidInput): | ||
fig.hlines(1, xmin=[2, 3], xmax=4) | ||
with pytest.raises(GMTInvalidInput): | ||
fig.hlines(1, xmin=[2, 3], xmax=[4, 5]) | ||
with pytest.raises(GMTInvalidInput): | ||
fig.hlines([1, 2], xmin=[2, 3, 4], xmax=3) | ||
with pytest.raises(GMTInvalidInput): | ||
fig.hlines([1, 2], xmin=[2, 3], xmax=[4, 5, 6]) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.