diff --git a/MANIFEST.in b/MANIFEST.in index 74e72ad15f5..88e203e9492 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -11,3 +11,4 @@ exclude CONTRIBUTING.md exclude Makefile exclude environment.yml exclude requirements.txt +exclude pygmt/tests/baseline/*.dvc diff --git a/pygmt/helpers/tempfile.py b/pygmt/helpers/tempfile.py index 8ac63006565..d9c132e696b 100644 --- a/pygmt/helpers/tempfile.py +++ b/pygmt/helpers/tempfile.py @@ -126,18 +126,30 @@ def tempfile_from_geojson(geojson): E.g. '1a2b3c4d5e6.gmt'. """ with GMTTempFile(suffix=".gmt") as tmpfile: + # pylint: disable=import-outside-toplevel + import geopandas as gpd + os.remove(tmpfile.name) # ensure file is deleted first ogrgmt_kwargs = {"filename": tmpfile.name, "driver": "OGR_GMT", "mode": "w"} try: + # Map int/int64 to int32 since OGR_GMT only supports 32-bit integer + # https://github.com/geopandas/geopandas/issues/967#issuecomment-842877704 + # https://github.com/GenericMappingTools/pygmt/issues/2497 + if geojson.index.name is None: + geojson.index.name = "index" + geojson = geojson.reset_index(drop=False) + schema = gpd.io.file.infer_schema(geojson) + for col, dtype in schema["properties"].items(): + if dtype in ("int", "int64"): + schema["properties"][col] = "int32" + ogrgmt_kwargs["schema"] = schema # Using geopandas.to_file to directly export to OGR_GMT format geojson.to_file(**ogrgmt_kwargs) except AttributeError: - # pylint: disable=import-outside-toplevel # Other 'geo' formats which implement __geo_interface__ import json import fiona - import geopandas as gpd with fiona.Env(): jsontext = json.dumps(geojson.__geo_interface__) diff --git a/pygmt/src/grdimage.py b/pygmt/src/grdimage.py index 6f200237927..6adf6f70ffa 100644 --- a/pygmt/src/grdimage.py +++ b/pygmt/src/grdimage.py @@ -2,19 +2,26 @@ grdimage - Plot grids or images. """ from pygmt.clib import Session -from pygmt.helpers import build_arg_string, fmt_docstring, kwargs_to_strings, use_alias +from pygmt.helpers import ( + build_arg_string, + deprecate_parameter, + fmt_docstring, + kwargs_to_strings, + use_alias, +) __doctest_skip__ = ["grdimage"] @fmt_docstring +@deprecate_parameter("bit_color", "bitcolor", "v0.10.0", remove_version="v0.12.0") @use_alias( A="img_out", B="frame", C="cmap", D="img_in", E="dpi", - G="bit_color", + G="bitcolor", I="shading", J="projection", M="monochrome", @@ -107,7 +114,7 @@ def grdimage(self, grid, **kwargs): same size (rows and columns) as the input file. Specify **i** to use the PostScript image operator to interpolate the image at the device resolution. - bit_color : str + bitcolor : str *color*\ [**+b**\|\ **f**\]. This parameter only applies when a resulting 1-bit image otherwise would consist of only two colors: black (0) and white (255). If so, diff --git a/pygmt/tests/baseline/test_geopandas_plot_int_dtypes.png.dvc b/pygmt/tests/baseline/test_geopandas_plot_int_dtypes.png.dvc new file mode 100644 index 00000000000..a2e9a9a7975 --- /dev/null +++ b/pygmt/tests/baseline/test_geopandas_plot_int_dtypes.png.dvc @@ -0,0 +1,4 @@ +outs: +- md5: c1c6eda2a88adf4d96f18f4e0c5db4d5 + size: 43582 + path: test_geopandas_plot_int_dtypes.png diff --git a/pygmt/tests/test_geopandas.py b/pygmt/tests/test_geopandas.py index 106ed798cf5..44992df76da 100644 --- a/pygmt/tests/test_geopandas.py +++ b/pygmt/tests/test_geopandas.py @@ -3,7 +3,7 @@ """ import numpy.testing as npt import pytest -from pygmt import Figure, info +from pygmt import Figure, info, makecpt, which gpd = pytest.importorskip("geopandas") shapely = pytest.importorskip("shapely") @@ -131,3 +131,54 @@ def test_geopandas_plot3d_non_default_circle(): style="c0.2c", ) return fig + + +@pytest.mark.parametrize( + "dtype", + [ + "int32", + "int64", + # Enable Int32/Int64 dtypes when geopandas>=0.13.3 is released with + # patch https://github.com/geopandas/geopandas/pull/2950 + # pd.Int32Dtype(), + # pd.Int64Dtype(), + ], +) +@pytest.mark.mpl_image_compare(filename="test_geopandas_plot_int_dtypes.png") +def test_geopandas_plot_int_dtypes(dtype): + """ + Check that plotting a geopandas GeoDataFrame with integer columns works, + including int32 and int64 (non-nullable), Int32 and Int64 (nullable). + + This is a regression test for + https://github.com/GenericMappingTools/pygmt/issues/2497 + """ + # Read shapefile in geopandas.GeoDataFrame + shapefile = which( + fname="@RidgeTest.shp @RidgeTest.shx @RidgeTest.dbf @RidgeTest.prj", + download="c", + ) + gdf = gpd.read_file(shapefile[0]) + + # Reproject geometry and change dtype of NPOINTS column + gdf["geometry"] = ( + gdf.to_crs(crs="EPSG:3857") + .buffer(distance=100000) + .to_crs(crs="OGC:CRS84") # convert to lon/lat to prevent @null in PROJ CRS + ) + gdf["NPOINTS"] = gdf.NPOINTS.astype(dtype=dtype) + + # Plot figure with three polygons colored based on NPOINTS value + fig = Figure() + makecpt(cmap="lisbon", series=[10, 60, 10], continuous=True) + fig.plot( + data=gdf, + frame=True, + pen="1p,black", + close=True, + fill="+z", + cmap=True, + aspatial="Z=NPOINTS", + ) + fig.colorbar() + return fig