matplotlib / basemap

Plot on map projections (with coastlines and political boundaries) using matplotlib
MIT License
774 stars 392 forks source link

ValueError: 'vertices' must be a 2D list or array with shape Nx2 #512

Closed flaviodoliveira closed 1 year ago

flaviodoliveira commented 3 years ago

I'm using Python 3.8.5 Matplotlib version 3.1.2 and basemap-1.2.2+dev

I'm running something like:


    llon = lons.min()
    llat = lats.min()
    ulon = lons.max()
    ulat = lats.max()

    fig, ax = plt.subplots()

    m = Basemap(llcrnrlon=llon, llcrnrlat=llat, urcrnrlon=ulon,
                urcrnrlat=ulat, resolution='h')

    m.drawcoastlines(linewidth=0.8)
    m.drawcountries(linewidth=0.8)
    m.drawstates(linewidth=0.8)

and then I got this:

File "plt_RAIN.py", line 62, in m.drawcoastlines(linewidth=0.8) File "/usr/local/lib/python3.8/dist-packages/mpl_toolkits/basemap/init.py", line 1859, in drawcoastlines coastlines = LineCollection(self.coastsegs,antialiaseds=(antialiased,)) File "/usr/lib/python3/dist-packages/matplotlib/collections.py", line 1333, in init self.set_segments(segments) File "/usr/lib/python3/dist-packages/matplotlib/collections.py", line 1348, in set_segments self._paths = [mpath.Path(_seg) for _seg in _segments] File "/usr/lib/python3/dist-packages/matplotlib/collections.py", line 1348, in self._paths = [mpath.Path(_seg) for _seg in _segments] File "/usr/lib/python3/dist-packages/matplotlib/path.py", line 129, in init raise ValueError( ValueError: 'vertices' must be a 2D list or array with shape Nx2

I checked everything, but I'm used to run this on basemap 1.0.7 and everything was ok. And when I run without m.drawcoastlines(), there is no problem.

What can I do to run it?

guziy commented 2 years ago

I have a similar problem. I think this might be because your domain does not intersect any coastlines? I have this reproducer:

# fails 
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
b = Basemap(projection="cea", llcrnrlon=267.5, urcrnrlon=283.995, llcrnrlat=41.35, urcrnrlat=51, resolution="l") 
b.drawcoastlines()
plt.show()

Note: The above fails in basemap 1.2.1 (matplotlib 3.5.1) and works in basemap 1.1.0 (matplotlib 2.1.1), regression somewhere...

But if I extend a bit to have an intersection with the ocean coastlines (in this case to the Hudson Bay) it works

# works 
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
b = Basemap(projection="cea", llcrnrlon=267.5, urcrnrlon=283.995, llcrnrlat=41.35, urcrnrlat=51.8, resolution="l") 
b.drawcoastlines()
plt.show()

@jswhit I know we are not supposed to bug you with this project, but maybe you have a workaround for this...

WeatherGod commented 2 years ago

This is most likely due to a change I made to address a problem with an update in proj4. IIRC, the projection parameters were getting cast to float32, thereby reducing the accuracy of the projection. Most likely, I removed the casting, so maybe an integer passing though is causing issues?

On Thu, Mar 31, 2022 at 12:02 PM Huziy Oleksandr @.***> wrote:

I have a similar problem. I think this might be because your domain does not intersect any coastlines? I have this reproducer:

fails from mpl_toolkits.basemap import Basemapb = Basemap(projection="cea", llcrnrlon=267.5, urcrnrlon=283.995, llcrnrlat=41.35, urcrnrlat=51, resolution="l") b.drawcoastlines()

Note: The above fails in basemap 1.2.1 and works in basemap 1.1.0, regression somewhere...

But if I extend a bit to have an intersection with the ocean coastlines (in this case to the Hudson Bay) it works

works from mpl_toolkits.basemap import Basemapb = Basemap(projection="cea", llcrnrlon=267.5, urcrnrlon=283.995, llcrnrlat=41.35, urcrnrlat=51.8, resolution="l") b.drawcoastlines()

@jswhit https://github.com/jswhit I know we are not supposed to bug you with this project, but maybe you have a workaround for this...

— Reply to this email directly, view it on GitHub https://github.com/matplotlib/basemap/issues/512#issuecomment-1084787378, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACHF6GGGE47N3R2IDWZAX3VCXECRANCNFSM4YPWKFLQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>

molinav commented 2 years ago

@guziy With the latest basemap I am not able to reproduce it. If I type your first snippet in IPython, I get this:

(py38) vic@onyx:~$ python -m IPython --pylab=Tk
Python 3.8.12 (default, Jan  3 2022, 10:33:21)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.30.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from mpl_toolkits.basemap import Basemap
   ...: import matplotlib.pyplot as plt
   ...: b = Basemap(projection="cea",
   ...:             llcrnrlon=267.5, urcrnrlon=283.995,
   ...:             llcrnrlat=41.35, urcrnrlat=51, resolution="l")
   ...: b.drawcoastlines()
   ...: plt.show()

In [2]: from mpl_toolkits import basemap

In [3]: basemap.__version__
Out[3]: '1.3.2'

plot_first_snippet

For this example I am using the basemap wheel in PyPI, which bundles a relatively old GEOS library (3.5.1). Could it be that your basemap installation uses the GEOS from your system, which is probably newer, and the new GEOS does not get on well with the current implementation?

guziy commented 2 years ago

@molinav Could you please try to create the following conda environment:

conda create -n py39 python=3.9 basemap ipython
conda activate py39

Here are the versions

conda list 'matplotlib|basemap|geos'
#
# Name                    Version                   Build  Channel
basemap                   1.2.2            py39h2103e0b_4    conda-forge
geos                      3.9.1                h9c3ff4c_2    conda-forge
matplotlib-base           3.5.1            py39h2fa2bec_0    conda-forge
matplotlib-inline         0.1.3              pyhd8ed1ab_0    conda-forge

Here is the info for the basemap=1.2.2 conda package:

conda search basemap=1.2.2 --info
basemap 1.2.2 py39hc66db60_2
----------------------------
file name   : basemap-1.2.2-py39hc66db60_2.conda
name        : basemap
version     : 1.2.2
build       : py39hc66db60_2
build number: 2
size        : 14.5 MB
license     : MIT
subdir      : linux-64
url         : https://repo.anaconda.com/pkgs/main/linux-64/basemap-1.2.2-py39hc66db60_2.conda
md5         : e6b784f1281dbe3070858be9d49f7df6
timestamp   : 2021-12-22 10:32:34 UTC
constraints : 
  - proj4 <6
  - proj <6
dependencies: 
  - geos >=3.8.0,<3.8.1.0a0
  - libgcc-ng >=7.5.0
  - libstdcxx-ng >=7.5.0
  - matplotlib-base >=1.0.0,!=3.0.1
  - numpy >=1.16.6,<2.0a0
  - proj
  - pyproj >=1.9.3
  - pyshp >=1.2.0
  - python >=3.9,<3.10.0a0
  - six
molinav commented 2 years ago

@guziy The basemap conda package needs an update at some point, but I haven't still had time to learn a bit on how to refactor the basemap conda recipe appropriately after my split of basemap into three parts.

From other issue (https://github.com/matplotlib/basemap/issues/522#issuecomment-1021245967) it seems that we are blocked at the moment to GEOS < 3.9.

guziy commented 2 years ago
molinav commented 2 years ago

The conda recipe is available in a separate repo: https://github.com/conda-forge/basemap-feedstock

There were a couple of external attempts to update the recipe but they did not succeed or were closed before finishing: https://github.com/conda-forge/basemap-feedstock/pull/92 https://github.com/conda-forge/basemap-feedstock/pull/93

Unfortunately, I could not still find time to learn about conda recipes to provide my own update there.

molinav commented 1 year ago

@guziy This issue and your fix were included in basemap 1.3.3. Since April, a bit of development on the conda-forge side has been ongoing, and we now have up-to-date basemap packages in conda-forge as well as in PyPI.

The latest basemap release (1.3.5) has been deployed to PyPI and conda-forge today, it also includes this bugfix of course, and it solves the problem about linking with newer GEOS versions (#522). So I think we can safely close this issue!