Skip to content

Commit cb3fa1b

Browse files
authored
Merge branch 'main' into no_clip
2 parents 27c17bb + bd71206 commit cb3fa1b

File tree

6 files changed

+79
-25
lines changed

6 files changed

+79
-25
lines changed

pygmt/src/grdimage.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
E="dpi",
2222
G="bitcolor",
2323
I="shading",
24-
M="monochrome",
2524
Q="nan_transparent",
2625
R="region",
2726
n="interpolation",
@@ -32,6 +31,7 @@
3231
def grdimage(
3332
self,
3433
grid: PathLike | xr.DataArray,
34+
monochrome: bool = False,
3535
no_clip: bool = False,
3636
projection=None,
3737
verbose: Literal["quiet", "error", "warning", "timing", "info", "compat", "debug"]
@@ -76,6 +76,7 @@ def grdimage(
7676
7777
{aliases}
7878
- J = projection
79+
- M = monochrome
7980
- N = no_clip
8081
- V = verbose
8182
- c = panel
@@ -129,9 +130,9 @@ def grdimage(
129130
input data represent an *image* then an *intensfile* or constant
130131
*intensity* must be provided.
131132
{projection}
132-
monochrome : bool
133-
Force conversion to monochrome image using the (television) YIQ
134-
transformation. Cannot be used with ``nan_transparent``.
133+
monochrome
134+
Force conversion to monochrome image using the (television) YIQ transformation.
135+
Cannot be used with ``nan_transparent``.
135136
no_clip
136137
Do **not** clip the image at the frame boundaries (only relevant for
137138
non-rectangular maps) [Default is ``False``].
@@ -175,6 +176,7 @@ def grdimage(
175176
raise NotImplementedError(msg)
176177

177178
aliasdict = AliasSystem(
179+
M=Alias(monochrome, name="monochrome"),
178180
N=Alias(no_clip, name="no_clip"),
179181
).add_common(
180182
J=projection,

pygmt/src/image.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212

1313

1414
@fmt_docstring
15-
@use_alias(D="position", G="bitcolor", M="monochrome", R="region", p="perspective")
15+
@use_alias(D="position", G="bitcolor", R="region", p="perspective")
1616
@kwargs_to_strings(R="sequence", p="sequence")
1717
def image(
1818
self,
1919
imagefile: PathLike,
2020
projection=None,
2121
box: Box | bool = False,
22+
monochrome: bool = False,
2223
verbose: Literal["quiet", "error", "warning", "timing", "info", "compat", "debug"]
2324
| bool = False,
2425
panel: int | tuple[int, int] | bool = False,
@@ -28,26 +29,35 @@ def image(
2829
r"""
2930
Plot raster or EPS images.
3031
31-
Reads an Encapsulated PostScript file or a raster image file and plots
32-
it on a map.
32+
Reads Encapsulated PostScript (EPS) or raster image files and plots them. The
33+
image can be scaled arbitrarily, and 1-bit raster images can be:
34+
35+
- inverted, i.e., black pixels (on) becomes white (off) and vice versa.
36+
- colorized, by assigning different foreground and background colors.
37+
- made transparent where either the back- or foreground is painted.
38+
39+
As an option, the user may choose to convert colored raster images to grayscale
40+
using TV's YIQ-transformation. For raster files, the user can select which color is
41+
made transparent. The user may also choose to replicate the image which, when
42+
preceded by appropriate clip paths, may allow larger custom-designed fill patterns
43+
to be implemented.
3344
3445
Full GMT docs at :gmt-docs:`image.html`.
3546
3647
{aliases}
3748
- F = box
3849
- J = projection
50+
- M = monochrome
3951
- V = verbose
4052
- c = panel
4153
- t = transparency
4254
4355
Parameters
4456
----------
45-
imagefile : str
46-
This must be an Encapsulated PostScript (EPS) file or a raster
47-
image. An EPS file must contain an appropriate BoundingBox. A
48-
raster file can have a depth of 1, 8, 24, or 32 bits and is read
49-
via GDAL. **Note**: If GDAL was not configured during GMT installation
50-
then only EPS files are supported.
57+
imagefile
58+
An Encapsulated PostScript (EPS) file or a raster image file. An EPS file must
59+
contain an appropriate BoundingBox. A raster file can have a depth of 1, 8, 24,
60+
or 32 bits and is read via GDAL.
5161
{projection}
5262
{region}
5363
position : str
@@ -68,7 +78,7 @@ def image(
6878
to make those pixels transparent. Can be repeated with different
6979
settings. Alternatively, for color images you can select a single
7080
*color* that should be made transparent instead (**+t**).
71-
monochrome : bool
81+
monochrome
7282
Convert color image to monochrome grayshades using the (television)
7383
YIQ-transformation.
7484
{verbose}
@@ -80,6 +90,7 @@ def image(
8090

8191
aliasdict = AliasSystem(
8292
F=Alias(box, name="box"),
93+
M=Alias(monochrome, name="monochrome"),
8394
).add_common(
8495
J=projection,
8596
V=verbose,

pygmt/src/solar.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ def solar(
3232
r"""
3333
Plot day-night terminators and other sunlight parameters.
3434
35-
This function plots the day-night terminator. Alternatively, it can plot the
35+
This method plots the day-night terminator. Alternatively, it can plot the
3636
terminators for civil twilight, nautical twilight, or astronomical twilight.
3737
3838
Full GMT docs at :gmt-docs:`solar.html`.
3939
4040
{aliases}
4141
- G = fill
4242
- J = projection
43-
- T = terminator, **+d**: terminator_datetime
43+
- T = terminator, **+d**/**+z**: terminator_datetime
4444
- V = verbose
4545
- W = pen
4646
- c = panel
@@ -49,8 +49,7 @@ def solar(
4949
Parameters
5050
----------
5151
terminator
52-
Set the type of terminator displayed, which can be set with either the full name
53-
or the first letter of the name. Available options are:
52+
Set the type of terminator. Choose one of the following:
5453
5554
- ``"astronomical"``: Astronomical twilight
5655
- ``"civil"``: Civil twilight
@@ -60,8 +59,12 @@ def solar(
6059
Refer to https://en.wikipedia.org/wiki/Twilight for the definitions of different
6160
types of twilight.
6261
terminator_datetime : str or datetime object
63-
Set the UTC date and time of the displayed terminator [Default is the current
64-
UTC date and time]. It can be passed as a string or Python datetime object.
62+
Set the date and time for the terminator calculation. It can be provided as a
63+
string or any datetime-like object recognized by :func:`pandas.to_datetime`. The
64+
time can be specified in UTC or using a UTC offset. The offset must be an
65+
integer number of hours (e.g., -8 or +5); fractional hours are truncated
66+
towards zero (e.g., -8.5 becomes -8 and +5.5 becomes +5). [Default is the
67+
current UTC date and time].
6568
{region}
6669
{projection}
6770
{frame}
@@ -102,12 +105,16 @@ def solar(
102105
"""
103106
self._activate_figure()
104107

105-
datetime_string = None
108+
datetime_string, datetime_timezone = None, None
106109
if terminator_datetime:
107110
try:
108-
datetime_string = pd.to_datetime(terminator_datetime).strftime(
109-
"%Y-%m-%dT%H:%M:%S.%f"
110-
)
111+
_datetime = pd.to_datetime(terminator_datetime)
112+
datetime_string = _datetime.strftime("%Y-%m-%dT%H:%M:%S.%f")
113+
# GMT's solar module uses the C 'atoi' function to parse the timezone
114+
# offset. Ensure the offset is an integer number of hours (e.g., -8 or +5).
115+
# Fractional hours (e.g., -8.5 or +5.5) are truncated towards zero.
116+
if utcoffset := _datetime.utcoffset():
117+
datetime_timezone = int(utcoffset.total_seconds() / 3600)
111118
except ValueError as verr:
112119
raise GMTValueError(terminator_datetime, description="datetime") from verr
113120

@@ -125,6 +132,7 @@ def solar(
125132
},
126133
),
127134
Alias(datetime_string, name="terminator_datetime", prefix="+d"),
135+
Alias(datetime_timezone, name="terminator_timezone", prefix="+z"),
128136
],
129137
W=Alias(pen, name="pen"),
130138
).add_common(

pygmt/src/tilemap.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
B="frame",
2222
E="dpi",
2323
I="shading",
24-
M="monochrome",
2524
Q="nan_transparent",
2625
# R="region",
2726
p="perspective",
@@ -36,6 +35,7 @@ def tilemap( # noqa: PLR0913
3635
wait: int = 0,
3736
max_retries: int = 2,
3837
zoom_adjust: int | None = None,
38+
monochrome: bool = False,
3939
no_clip: bool = False,
4040
projection=None,
4141
verbose: Literal["quiet", "error", "warning", "timing", "info", "compat", "debug"]
@@ -59,6 +59,7 @@ def tilemap( # noqa: PLR0913
5959
6060
{aliases}
6161
- J = projection
62+
- M = monochrome
6263
- N = no_clip
6364
- V = verbose
6465
- c = panel
@@ -133,6 +134,7 @@ def tilemap( # noqa: PLR0913
133134
kwargs["R"] = "/".join(str(coordinate) for coordinate in region)
134135

135136
aliasdict = AliasSystem(
137+
M=Alias(monochrome, name="monochrome"),
136138
N=Alias(no_clip, name="no_clip"),
137139
).add_common(
138140
J=projection,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
outs:
2+
- md5: 10c5d3cadeb50764177bf49cbefeecb1
3+
size: 48753
4+
hash: md5
5+
path: test_solar_terminator_datetime_timezone.png

pygmt/tests/test_solar.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,29 @@ def test_solar_default_terminator():
119119
terminator_datetime="1990-02-17 04:25:00",
120120
)
121121
return fig
122+
123+
124+
@pytest.mark.mpl_image_compare
125+
def test_solar_terminator_datetime_timezone():
126+
"""
127+
Test passing the terminator_datetime argument with a time string that includes a
128+
timezone.
129+
"""
130+
fig = Figure()
131+
fig.basemap(region="d", projection="W0/15c", frame=True)
132+
fig.solar(terminator_datetime="2020-01-01T01:02:03", pen="1p,black")
133+
fig.solar(terminator_datetime="2020-01-01T01:02:03+01:00", pen="1p,red")
134+
fig.solar(terminator_datetime="2020-01-01T01:02:03-01:00", pen="1p,blue")
135+
fig.solar(
136+
terminator_datetime=datetime.datetime(
137+
2020, 1, 1, 1, 2, 3, tzinfo=datetime.timezone(datetime.timedelta(hours=2))
138+
),
139+
pen="1p,lightred",
140+
)
141+
fig.solar(
142+
terminator_datetime=datetime.datetime(
143+
2020, 1, 1, 1, 2, 3, tzinfo=datetime.timezone(datetime.timedelta(hours=-2))
144+
),
145+
pen="1p,lightblue",
146+
)
147+
return fig

0 commit comments

Comments
 (0)