Skip to content

Commit

Permalink
Merge branch 'main' into pyarrow/string
Browse files Browse the repository at this point in the history
  • Loading branch information
weiji14 committed Nov 7, 2024
2 parents 9fd77dc + c50c1ec commit ccf4eff
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 113 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/type_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ jobs:
# 4. other packages that are used somewhere in PyGMT
python -m pip install \
numpy pandas xarray netcdf4 packaging \
contextily geopandas ipython rioxarray \
mypy pandas-stubs \
contextily geopandas ipython pyarrow rioxarray \
mypy pandas-stubs pyarrow-stubs \
matplotlib pytest
python -m pip list
Expand Down
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies:
- contextily
- geopandas
- ipython
- pyarrow
- rioxarray
# Development dependencies (general)
- dvc
Expand Down
130 changes: 50 additions & 80 deletions examples/tutorials/basics/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Plotting lines
==============
Plotting lines is handled by :meth:`pygmt.Figure.plot`.
Plotting lines is handled by the :meth:`pygmt.Figure.plot` method.
"""

# %%
Expand All @@ -12,123 +12,93 @@
# Plot lines
# ----------
#
# Create a Cartesian figure using ``projection`` parameter and set the axis
# scales using ``region`` (in this case, each axis is 0-10). Pass a list of
# ``x`` and ``y`` values to be plotted as a line.
# Create a Cartesian figure using the :meth:`pygmt.Figure.basemap` method. Pass lists
# containing two values to the ``x`` and ``y`` parameters of the
# :meth:`pygmt.Figure.plot` method. By default, a 0.25-points thick, black, solid
# line is drawn between these two data points.

fig = pygmt.Figure()
fig.plot(
region=[0, 10, 0, 10],
projection="X15c/10c",
frame="a",
x=[1, 8],
y=[5, 9],
pen="1p,black",
)
fig.basemap(region=[0, 10, 0, 10], projection="X15c/10c", frame=True)

fig.plot(x=[1, 5], y=[5, 9])

fig.show()

# %%
# Additional line segments can be added by including additional values for
# ``x`` and ``y``.
# Additional line segments can be added by including more data points in the lists
# passed to ``x`` and ``y``.

fig = pygmt.Figure()
fig.plot(
region=[0, 10, 0, 10],
projection="X15c/10c",
frame="a",
x=[1, 6, 9],
y=[5, 7, 4],
pen="1p,black",
)
fig.basemap(region=[0, 10, 0, 10], projection="X15c/10c", frame=True)

fig.plot(x=[1, 5, 8], y=[5, 9, 4])

fig.show()

# %%
# To plot multiple lines, :meth:`pygmt.Figure.plot` needs to be used for each
# additional line. Parameters such as ``region``, ``projection``, and ``frame``
# do not need to be repeated in subsequent uses.
# To plot multiple lines, :meth:`pygmt.Figure.plot` needs to be used for each line
# separately.

fig = pygmt.Figure()
fig.plot(
region=[0, 10, 0, 10],
projection="X15c/10c",
frame="a",
x=[1, 6, 9],
y=[5, 7, 4],
pen="2p,blue",
)
fig.plot(x=[2, 4, 10], y=[3, 8, 9], pen="2p,red")
fig.basemap(region=[0, 10, 0, 10], projection="X15c/10c", frame=True)

fig.plot(x=[1, 5, 8], y=[5, 9, 4])
fig.plot(x=[2, 4, 9], y=[3, 7, 5])

fig.show()


# %%
# Change line attributes
# ----------------------
#
# The line attributes can be set by the ``pen`` parameter. ``pen`` takes a
# string argument with the optional values *width*,\ *color*,\ *style*.
#
# In the example below, the pen width is set to ``5p``, and with ``black`` as
# the default color and ``solid`` as the default style.
# The line attributes can be set by the ``pen`` parameter which takes a string
# argument with the optional values *width*,\ *color*,\ *style*.

fig = pygmt.Figure()
fig.plot(
region=[0, 10, 0, 10],
projection="X15c/10c",
frame="a",
x=[1, 8],
y=[3, 9],
pen="5p",
)
fig.basemap(region=[0, 10, 0, 10], projection="X15c/10c", frame=True)

# Set the pen width to "5p" (5 points), and use the default color "black" and the
# default style "solid"
fig.plot(x=[1, 8], y=[3, 9], pen="5p")

fig.show()

# %%
# The line color can be set and is added after the line width to the ``pen``
# parameter. In the example below, the line color is set to ``red``.
# parameter.

fig = pygmt.Figure()
fig.plot(
region=[0, 10, 0, 10],
projection="X15c/10c",
frame="a",
x=[1, 8],
y=[3, 9],
pen="5p,red",
)
fig.basemap(region=[0, 10, 0, 10], projection="X15c/10c", frame=True)

# Set the line color to "red", use the default style "solid"
fig.plot(x=[1, 8], y=[3, 9], pen="5p,red")

fig.show()

# %%
# The line style can be set and is added after the line width or color to the
# ``pen`` parameter. In the example below, the line style is set to
# ``..-`` (*dot dot dash*), and the default color ``black`` is used.
# ``pen`` parameter.

fig = pygmt.Figure()
fig.plot(
region=[0, 10, 0, 10],
projection="X15c/10c",
frame="a",
x=[1, 8],
y=[3, 9],
pen="5p,..-",
)
fig.basemap(region=[0, 10, 0, 10], projection="X15c/10c", frame=True)

# Set the line style to "..-" (dot dot dash), use the default color "black"
fig.plot(x=[1, 8], y=[3, 9], pen="5p,..-")

fig.show()

# %%
# The line width, color, and style can all be set in the same ``pen``
# parameter. In the example below, the line width is set to ``7p``, the color
# is set to ``green``, and the line style is ``-.-`` (*dash dot dash*).
#
# For a gallery showing other ``pen`` settings, see
# The line width, color, and style can all be set in the same ``pen`` parameter.
# For a gallery example showing other ``pen`` settings, see
# :doc:`/gallery/lines/linestyles`.

fig = pygmt.Figure()
fig.plot(
region=[0, 10, 0, 10],
projection="X15c/10c",
frame="a",
x=[1, 8],
y=[3, 9],
pen="7p,green,-.-",
)
fig.basemap(region=[0, 10, 0, 10], projection="X15c/10c", frame=True)

# Draw a 7-points thick, green line with style "-.-" (dash dot dash)
fig.plot(x=[1, 8], y=[3, 9], pen="7p,green,-.-")

fig.show()

# sphinx_gallery_thumbnail_number = 3
# sphinx_gallery_thumbnail_number = 6
48 changes: 24 additions & 24 deletions pygmt/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import numpy as np
from pygmt.clib import Session
from pygmt.exceptions import GMTError, GMTInvalidInput
from pygmt.exceptions import GMTInvalidInput
from pygmt.helpers import launch_external_viewer, unique_name


Expand Down Expand Up @@ -135,7 +135,7 @@ def region(self) -> np.ndarray:
wesn = lib.extract_region()
return wesn

def savefig( # noqa: PLR0912
def savefig(
self,
fname: str | PurePath,
transparent: bool = False,
Expand Down Expand Up @@ -177,7 +177,8 @@ def savefig( # noqa: PLR0912
The desired figure file name, including the extension. See the list of
supported formats and their extensions above.
transparent
Use a transparent background for the figure. Only valid for PNG format.
Use a transparent background for the figure. Only valid for PNG format and
the PNG file asscoiated with KML format.
crop
Crop the figure canvas (page) to the plot area.
anti_alias
Expand All @@ -203,9 +204,9 @@ def savefig( # noqa: PLR0912
"bmp": "b",
"eps": "e",
"jpg": "j",
"kml": "g",
"kml": "G" if transparent is True else "g",
"pdf": "f",
"png": "g",
"png": "G" if transparent is True else "g",
"ppm": "m",
"tif": "t",
"tiff": None, # GeoTIFF doesn't need the -T option
Expand All @@ -226,14 +227,12 @@ def savefig( # noqa: PLR0912
msg = "Extension '.ps' is not supported. Use '.eps' or '.pdf' instead."
raise GMTInvalidInput(msg)
case ext if ext not in fmts:
raise GMTInvalidInput(f"Unknown extension '.{ext}'.")

fmt = fmts[ext]
if transparent:
if fmt != "g":
msg = f"Transparency unavailable for '{ext}', only for png."
msg = f"Unknown extension '.{ext}'."
raise GMTInvalidInput(msg)
fmt = fmt.upper()

if transparent and ext not in {"kml", "png"}:
msg = f"Transparency unavailable for '{ext}', only for png and kml."
raise GMTInvalidInput(msg)
if anti_alias:
kwargs["Qt"] = 2
kwargs["Qg"] = 2
Expand All @@ -244,18 +243,17 @@ def savefig( # noqa: PLR0912
raise GMTInvalidInput(msg)
kwargs["W"] = True

# pytest-mpl v0.17.0 added the "metadata" parameter to Figure.savefig, which
# is not recognized. So remove it before calling Figure.psconvert.
# pytest-mpl v0.17.0 added the "metadata" parameter to Figure.savefig, which is
# not recognized. So remove it before calling Figure.psconvert.
kwargs.pop("metadata", None)
self.psconvert(prefix=prefix, fmt=fmt, crop=crop, **kwargs)
self.psconvert(prefix=prefix, fmt=fmts[ext], crop=crop, **kwargs)

# Remove the .pgw world file if exists.
# Not necessary after GMT 6.5.0.
# Remove the .pgw world file if exists. Not necessary after GMT 6.5.0.
# See upstream fix https://github.com/GenericMappingTools/gmt/pull/7865
if ext == "tiff":
fname.with_suffix(".pgw").unlink(missing_ok=True)

# Rename if file extension doesn't match the input file suffix
# Rename if file extension doesn't match the input file suffix.
if ext != suffix[1:]:
fname.with_suffix("." + ext).rename(fname)

Expand Down Expand Up @@ -331,11 +329,12 @@ def show(
match method:
case "notebook":
if not _HAS_IPYTHON:
raise GMTError(
msg = (
"Notebook display is selected, but IPython is not available. "
"Make sure you have IPython installed, "
"or run the script in a Jupyter notebook."
)
raise ImportError(msg)
png = self._preview(
fmt="png", dpi=dpi, anti_alias=True, as_bytes=True, **kwargs
)
Expand All @@ -344,14 +343,15 @@ def show(
pdf = self._preview(
fmt="pdf", dpi=dpi, anti_alias=False, as_bytes=False, **kwargs
)
launch_external_viewer(pdf, waiting=waiting) # type: ignore[arg-type]
launch_external_viewer(pdf, waiting=waiting)
case "none":
pass # Do nothing
case _:
raise GMTInvalidInput(
f"Invalid display method '{method}'. Valid values are 'external', "
"'notebook', 'none' or None."
msg = (
f"Invalid display method '{method}'. "
"Valid values are 'external', 'notebook', 'none' or None."
)
raise GMTInvalidInput(msg)

def _preview(self, fmt: str, dpi: int, as_bytes: bool = False, **kwargs):
"""
Expand Down Expand Up @@ -400,7 +400,7 @@ def _repr_html_(self):
html = '<img src="data:image/png;base64,{image}" width="{width}px">'
return html.format(image=base64_png.decode("utf-8"), width=500)

from pygmt.src import ( # type: ignore [misc]
from pygmt.src import ( # type: ignore[misc]
basemap,
coast,
colorbar,
Expand Down
8 changes: 5 additions & 3 deletions pygmt/tests/test_clib_put_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,12 @@ def test_put_vector_string_dtype():

def test_put_vector_timedelta64_dtype():
"""
Passing timedelta64 type vectors with various time units (year, month,
week, day, hour, minute, second, millisecond, microsecond) to a dataset.
Passing timedelta64 type vectors with various date/time units to a dataset.
Valid date/time units can be found at
https://numpy.org/devdocs/reference/arrays.datetime.html#datetime-units.
"""
for unit in ["Y", "M", "W", "D", "h", "m", "s", "ms", "μs"]:
for unit in ["Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps", "fs", "as"]:
with clib.Session() as lib, GMTTempFile() as tmp_file:
dataset = lib.create_data(
family="GMT_IS_DATASET|GMT_VIA_VECTOR",
Expand Down
17 changes: 13 additions & 4 deletions pygmt/tests/test_figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import numpy.testing as npt
import pytest
from pygmt import Figure, set_display
from pygmt.exceptions import GMTError, GMTInvalidInput
from pygmt.exceptions import GMTInvalidInput
from pygmt.figure import SHOW_CONFIG, _get_default_display_method
from pygmt.helpers import GMTTempFile

Expand Down Expand Up @@ -196,12 +196,21 @@ def test_figure_savefig_transparent():
fname = f"{prefix}.{fmt}"
with pytest.raises(GMTInvalidInput):
fig.savefig(fname, transparent=True)
# png should not raise an error

# PNG should support transparency and should not raise an error.
fname = Path(f"{prefix}.png")
fig.savefig(fname, transparent=True)
assert fname.exists()
fname.unlink()

# The companion PNG file with KML format should also support transparency.
fname = Path(f"{prefix}.kml")
fig.savefig(fname, transparent=True)
assert fname.exists()
fname.unlink()
assert fname.with_suffix(".png").exists()
fname.with_suffix(".png").unlink()


def test_figure_savefig_filename_with_spaces():
"""
Expand Down Expand Up @@ -321,7 +330,7 @@ def test_figure_show_notebook_error_without_ipython():
"""
fig = Figure()
fig.basemap(region=[0, 1, 2, 3], frame=True)
with pytest.raises(GMTError):
with pytest.raises(ImportError):
fig.show(method="notebook")


Expand Down Expand Up @@ -361,7 +370,7 @@ def test_set_display(self):
assert mock_viewer.call_count == 0
assert mock_display.call_count == 1
else:
with pytest.raises(GMTError):
with pytest.raises(ImportError):
fig.show()

# Test the "external" display method
Expand Down
Loading

0 comments on commit ccf4eff

Please sign in to comment.