Skip to content

Commit 5a6e4df

Browse files
willschlitzerseismanweiji14
authored
Wrap solar (#804)
Co-authored-by: Dongdong Tian <[email protected]> Co-authored-by: Wei Ji <[email protected]>
1 parent 955a55e commit 5a6e4df

File tree

8 files changed

+276
-0
lines changed

8 files changed

+276
-0
lines changed

doc/api/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Plotting data and laying out the map:
3838
Figure.plot3d
3939
Figure.set_panel
4040
Figure.shift_origin
41+
Figure.solar
4142
Figure.subplot
4243
Figure.text
4344

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""
2+
Day-night terminator line and twilights
3+
---------------------------------------
4+
5+
Use :meth:`pygmt.Figure.solar` to show the different transition stages between daytime
6+
and nightime. The parameter ``terminator`` is used to set the twilight stage, and can be
7+
either 'day-night' (brightest), 'civil', 'nautical', or 'astronomical' (darkest). Refer
8+
to https://en.wikipedia.org/wiki/Twilight for more information.
9+
"""
10+
import datetime
11+
12+
import pygmt
13+
14+
fig = pygmt.Figure()
15+
# Create a figure showing the global region on a Mollweide projection
16+
# Land color is set to dark green and water color is set to light blue
17+
fig.coast(region="d", projection="W0/15c", land="darkgreen", water="lightblue")
18+
# Set a time for the day-night terminator and twilights, 1700 UTC on January 1, 2000
19+
terminator_datetime = datetime.datetime(
20+
year=2000, month=1, day=1, hour=17, minute=0, second=0
21+
)
22+
# Set the pen line to be 0.5p thick
23+
# Set the fill for the night area to be navy blue at different transparency levels
24+
fig.solar(
25+
terminator="day_night",
26+
terminator_datetime=terminator_datetime,
27+
fill="navyblue@95",
28+
pen="0.5p",
29+
)
30+
fig.solar(
31+
terminator="civil",
32+
terminator_datetime=terminator_datetime,
33+
fill="navyblue@85",
34+
pen="0.5p",
35+
)
36+
fig.solar(
37+
terminator="nautical",
38+
terminator_datetime=terminator_datetime,
39+
fill="navyblue@80",
40+
pen="0.5p",
41+
)
42+
fig.solar(
43+
terminator="astronomical",
44+
terminator_datetime=terminator_datetime,
45+
fill="navyblue@80",
46+
pen="0.5p",
47+
)
48+
fig.show()

pygmt/figure.py

+1
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ def _repr_html_(self):
391391
plot,
392392
plot3d,
393393
set_panel,
394+
solar,
394395
subplot,
395396
text,
396397
)

pygmt/src/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from pygmt.src.meca import meca
2626
from pygmt.src.plot import plot
2727
from pygmt.src.plot3d import plot3d
28+
from pygmt.src.solar import solar
2829
from pygmt.src.subplot import set_panel, subplot
2930
from pygmt.src.surface import surface
3031
from pygmt.src.text import text_ as text # "text" is an argument within "text_"

pygmt/src/solar.py

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
"""
2+
solar - Plot day-night terminators and twilight.
3+
"""
4+
import pandas as pd
5+
from pygmt.clib import Session
6+
from pygmt.exceptions import GMTInvalidInput
7+
from pygmt.helpers import build_arg_string, fmt_docstring, kwargs_to_strings, use_alias
8+
9+
10+
@fmt_docstring
11+
@use_alias(
12+
B="frame",
13+
G="fill",
14+
J="projection",
15+
R="region",
16+
U="timestamp",
17+
V="verbose",
18+
W="pen",
19+
X="xshift",
20+
Y="yshift",
21+
c="panel",
22+
p="perspective",
23+
t="transparency",
24+
)
25+
@kwargs_to_strings(R="sequence", c="sequence_comma", p="sequence")
26+
def solar(self, terminator="d", terminator_datetime=None, **kwargs):
27+
r"""
28+
Plot day-light terminators or twilights.
29+
30+
This function plots the day-night terminator. Alternatively, it can plot
31+
the terminators for civil twilight, nautical twilight, or astronomical
32+
twilight.
33+
34+
Full parameter list at :gmt-docs:`solar.html`
35+
36+
{aliases}
37+
38+
Parameters
39+
----------
40+
terminator : str
41+
Set the type of terminator displayed. Valid arguments are
42+
**day_night**, **civil**, **nautical**, and **astronomical**, which
43+
can be set with either the full name or the first letter of the name.
44+
[Default is **day_night**]
45+
46+
Refer to https://en.wikipedia.org/wiki/Twilight for the definitions of
47+
different types of twilight.
48+
terminator_datetime : str or datetime object
49+
Set the UTC date and time of the displayed terminator. It can be
50+
passed as a string or Python datetime object.
51+
[Default is the current UTC date and time]
52+
{R}
53+
{J}
54+
{B}
55+
fill : str
56+
Color or pattern for filling of terminators.
57+
pen : str
58+
Set pen attributes for lines. The default pen
59+
is ``default,black,solid``.
60+
{U}
61+
{V}
62+
{XY}
63+
{c}
64+
{p}
65+
{t}
66+
"""
67+
68+
kwargs = self._preprocess(**kwargs) # pylint: disable=protected-access
69+
if "T" in kwargs:
70+
raise GMTInvalidInput(
71+
"Use 'terminator' and 'terminator_datetime' instead of 'T'."
72+
)
73+
if terminator not in [
74+
"day_night",
75+
"civil",
76+
"nautical",
77+
"astronomical",
78+
"d",
79+
"c",
80+
"n",
81+
"a",
82+
]:
83+
raise GMTInvalidInput(
84+
f"Unrecognized solar terminator type '{terminator}'. Valid values "
85+
"are 'day_night', 'civil', 'nautical', and 'astronomical'."
86+
)
87+
kwargs["T"] = terminator[0]
88+
if terminator_datetime:
89+
try:
90+
datetime_string = pd.to_datetime(terminator_datetime).strftime(
91+
"%Y-%m-%dT%H:%M:%S.%f"
92+
)
93+
except ValueError as verr:
94+
raise GMTInvalidInput("Unrecognized datetime format.") from verr
95+
kwargs["T"] += f"+d{datetime_string}"
96+
with Session() as lib:
97+
lib.call_module("solar", build_arg_string(kwargs))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
outs:
2+
- md5: 0a7f4959b500b6fa3a560a6368db0f90
3+
size: 25982
4+
path: test_solar_set_terminator_datetime.png
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
outs:
2+
- md5: 54c92bea64e0fc76c62601cb6131f22e
3+
size: 44160
4+
path: test_solar_terminators.png

pygmt/tests/test_solar.py

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
"""
2+
Tests for solar.
3+
"""
4+
import datetime
5+
6+
import pytest
7+
from pygmt import Figure
8+
from pygmt.exceptions import GMTInvalidInput
9+
10+
11+
@pytest.mark.mpl_image_compare
12+
def test_solar_terminators():
13+
"""
14+
Test passing the solar argument with a time string and no terminator type
15+
to confirm the default terminator type.
16+
"""
17+
fig = Figure()
18+
fig.basemap(region="d", projection="W0/15c", frame="a")
19+
fig.solar(
20+
terminator="d",
21+
pen="1p,blue",
22+
terminator_datetime="1990-02-17 04:25:00",
23+
)
24+
fig.solar(
25+
terminator="a",
26+
pen="1p,red",
27+
terminator_datetime="1990-02-17 04:25:00",
28+
)
29+
fig.solar(
30+
terminator="c",
31+
pen="1p,green",
32+
terminator_datetime="1990-02-17 04:25:00",
33+
)
34+
fig.solar(
35+
terminator="n",
36+
pen="1p,yellow",
37+
terminator_datetime="1990-02-17 04:25:00",
38+
)
39+
return fig
40+
41+
42+
@pytest.mark.mpl_image_compare(filename="test_solar_set_terminator_datetime.png")
43+
@pytest.mark.parametrize(
44+
"terminator_datetime",
45+
[
46+
pytest.param("1990-02-17 04:25:00", id="terminator_datetime_string"),
47+
datetime.datetime(year=1990, month=2, day=17, hour=4, minute=25, second=0),
48+
],
49+
)
50+
def test_solar_set_terminator_datetime(terminator_datetime):
51+
"""
52+
Test passing the solar argument with the day_night terminator and a
53+
datetime string.
54+
"""
55+
fig = Figure()
56+
fig.solar(
57+
region="d",
58+
projection="W0/15c",
59+
frame="a",
60+
terminator="day_night",
61+
terminator_datetime=terminator_datetime,
62+
)
63+
return fig
64+
65+
66+
def test_invalid_terminator_type():
67+
"""
68+
Test if solar fails when it receives an invalid terminator type.
69+
"""
70+
fig = Figure()
71+
with pytest.raises(GMTInvalidInput):
72+
fig.solar(
73+
region="d",
74+
projection="W0/15c",
75+
frame="a",
76+
terminator="invalid",
77+
)
78+
79+
80+
def test_invalid_parameter():
81+
"""
82+
Test if solar fails when it receives a GMT argument for 'T' instead of the
83+
PyGMT arguments for 'terminator' and 'terminator_datetime'.
84+
"""
85+
fig = Figure()
86+
with pytest.raises(GMTInvalidInput):
87+
# Use single-letter option 'T' for testing
88+
fig.solar(
89+
region="d", projection="W0/15c", frame="a", T="d+d1990-02-17T04:25:00"
90+
)
91+
92+
93+
def test_invalid_datetime():
94+
"""
95+
Test if solar fails when it receives an invalid datetime string.
96+
"""
97+
fig = Figure()
98+
with pytest.raises(GMTInvalidInput):
99+
fig.solar(
100+
region="d",
101+
projection="W0/15c",
102+
frame="a",
103+
terminator_datetime="199A-02-17 04:25:00",
104+
)
105+
106+
107+
@pytest.mark.mpl_image_compare(filename="test_solar_set_terminator_datetime.png")
108+
def test_solar_default_terminator():
109+
"""
110+
Test passing the solar argument with a time string and no terminator type
111+
to confirm the default terminator type.
112+
"""
113+
fig = Figure()
114+
fig.solar(
115+
region="d",
116+
projection="W0/15c",
117+
frame="a",
118+
terminator_datetime="1990-02-17 04:25:00",
119+
)
120+
return fig

0 commit comments

Comments
 (0)