Skip to content

Commit 2eac57f

Browse files
committed
Merge branch 'hotfix-1.3.9'
2 parents c20c146 + 86a0eb3 commit 2eac57f

File tree

11 files changed

+165
-93
lines changed

11 files changed

+165
-93
lines changed

CHANGELOG.md

+44-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,33 @@ https://keepachangelog.com/en/1.0.0/
1010
https://semver.org/spec/v2.0.0.html
1111

1212

13+
## [1.3.9] - 2023-12-26
14+
15+
### Fixed
16+
- Fix `GeosLibrary` wrapper to also work with CMake >= 3.27.0 and
17+
Python 2.7 on Windows by adding '/MANIFEST:NO' to override the new
18+
default '/MANIFEST:EMBED,ID=2' provided to linker.
19+
- Fix broken `Proj.__call__` when the input arguments are provided as
20+
a combined single array.
21+
- Fix flipped coastlines with pseudocylindrical projections when `lon_0`
22+
is greater than 0 deg (solves issues [#443] and [#463], thanks to
23+
@YilongWang).
24+
- Fix `antialiased` argument being ignored in `Basemap.drawcounties` and
25+
`Basemap.readshapefile` (solves issue [#501], thanks to @TheFizzWare).
26+
- Fix `BaseGeometry.intersection` in `_geoslib` so that it also works
27+
with `GEOS_GEOMETRYCOLLECTION` objects returned by `GEOSIntersection`
28+
(solves issue [#566], where country boundaries are missing due to this
29+
bug, thanks to @guidocioni).
30+
- Fix bug with elliptical maps causing warped images (Blue Marble,
31+
ETOPO, Shaded Relief) to be shown behind the map background when the
32+
map boundary is not initialised manually (solves issue [#577], thanks
33+
to @YilongWang).
34+
- Fix references to removed `numpy.float` alias (solves issue [#589],
35+
thanks to @quickbrett).
36+
- Fix wrong reference to `ireland.py` example in FAQ, which should be
37+
`hires.py` instead, and fix wrong use of locals and invalid syntax
38+
in this example (solves issue [#592], thanks to @timcoote).
39+
1340
## [1.3.8] - 2023-08-18
1441

1542
### Changed
@@ -976,6 +1003,10 @@ https://semver.org/spec/v2.0.0.html
9761003
- Fix glitches in drawing of parallels and meridians.
9771004

9781005

1006+
[#592]:
1007+
https://github.com/matplotlib/basemap/issues/592
1008+
[#589]:
1009+
https://github.com/matplotlib/basemap/issues/589
9791010
[#583]:
9801011
https://github.com/matplotlib/basemap/issues/583
9811012
[#582]:
@@ -986,8 +1017,12 @@ https://github.com/matplotlib/basemap/issues/581
9861017
https://github.com/matplotlib/basemap/pull/580
9871018
[#579]:
9881019
https://github.com/matplotlib/basemap/issues/579
1020+
[#577]:
1021+
https://github.com/matplotlib/basemap/issues/577
9891022
[#573]:
9901023
https://github.com/matplotlib/basemap/issues/573
1024+
[#566]:
1025+
https://github.com/matplotlib/basemap/issues/566
9911026
[#564]:
9921027
https://github.com/matplotlib/basemap/pull/564
9931028
[#563]:
@@ -1046,6 +1081,8 @@ https://github.com/matplotlib/basemap/issues/512
10461081
https://github.com/matplotlib/basemap/issues/510
10471082
[#505]:
10481083
https://github.com/matplotlib/basemap/pull/505
1084+
[#501]:
1085+
https://github.com/matplotlib/basemap/issues/501
10491086
[#491]:
10501087
https://github.com/matplotlib/basemap/issues/491
10511088
[#489]:
@@ -1056,12 +1093,16 @@ https://github.com/matplotlib/basemap/issues/488
10561093
https://github.com/matplotlib/basemap/issues/487
10571094
[#476]:
10581095
https://github.com/matplotlib/basemap/pull/476
1096+
[#463]:
1097+
https://github.com/matplotlib/basemap/issues/463
10591098
[#461]:
10601099
https://github.com/matplotlib/basemap/issues/461
10611100
[#456]:
10621101
https://github.com/matplotlib/basemap/issues/456
10631102
[#445]:
10641103
https://github.com/matplotlib/basemap/issues/445
1104+
[#443]:
1105+
https://github.com/matplotlib/basemap/issues/443
10651106
[#436]:
10661107
https://github.com/matplotlib/basemap/issues/436
10671108
[#422]:
@@ -1080,7 +1121,9 @@ https://github.com/matplotlib/basemap/issues/228
10801121
https://github.com/matplotlib/basemap/issues/179
10811122

10821123
[Unreleased]:
1083-
https://github.com/matplotlib/basemap/compare/v1.3.8...develop
1124+
https://github.com/matplotlib/basemap/compare/v1.3.9...develop
1125+
[1.3.9]:
1126+
https://github.com/matplotlib/basemap/compare/v1.3.8...v1.3.9
10841127
[1.3.8]:
10851128
https://github.com/matplotlib/basemap/compare/v1.3.7...v1.3.8
10861129
[1.3.7]:

FAQ

+22-22
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
1-
Q: It takes a long time to make a plot with the 'intermediate' or 'high'
1+
Q: It takes a long time to make a plot with the 'intermediate' or 'high'
22
resolution coastlines, how can I speed it up?
33

4-
A: There is a overhead in processing boundary datasets when a Basemap
5-
class in created, and this overhead can be significant for the higher
6-
resolution boundaries. If you are makeing many maps for the same region,
7-
you only need to create you Basemap class instance once, then re-use it
8-
for each plot. If the plots are being created by different scripts, you
9-
can save the Basemap class instance to a Pickle on disk, then read it in
10-
whatever script needs it (it's much faster to read a pickle from disk than
11-
it is to create the Basemap instance originally). The ireland.py example
4+
A: There is a overhead in processing boundary datasets when a Basemap
5+
class in created, and this overhead can be significant for the higher
6+
resolution boundaries. If you are makeing many maps for the same region,
7+
you only need to create you Basemap class instance once, then re-use it
8+
for each plot. If the plots are being created by different scripts, you
9+
can save the Basemap class instance to a Pickle on disk, then read it in
10+
whatever script needs it (it's much faster to read a pickle from disk than
11+
it is to create the Basemap instance originally). The hires.py example
1212
illustrates how to do this.
1313

14-
Q: I have my own boundary dataset that I would like to use, how do I use
14+
Q: I have my own boundary dataset that I would like to use, how do I use
1515
it in place of (or in addition to) the built-in basemap boundary datasets?
1616

17-
A: If your dataset is in ESRI shapefile format, this is relatively easy.
18-
Just create your Basemap class instance, then call the 'readshapefile'
19-
method on that instance to import your data. Setting 'drawbounds=True'
20-
will draw the boundaries in the shapefile. The fillstates.py example
17+
A: If your dataset is in ESRI shapefile format, this is relatively easy.
18+
Just create your Basemap class instance, then call the 'readshapefile'
19+
method on that instance to import your data. Setting 'drawbounds=True'
20+
will draw the boundaries in the shapefile. The fillstates.py example
2121
shows how to do this.
2222

23-
Q: How do I specify the map projection region if I don't know what the
23+
Q: How do I specify the map projection region if I don't know what the
2424
latitude and longitudes of the corners are?
2525

26-
A: As an alternative to specifying the lat/lon values for the upper-right
27-
and lower-left corners of the projection domain (using the llcrnrlat,
28-
llcrnrlon, urcrnrlat and urcrnrlon keywords) you can specify the center of
29-
the map projection domain (using the lat_0 and lon_0 keywords) and the
30-
width and height of the domain in map projection coordinates (meters)
31-
using the width and height keywords. Basemap will then calculate the
32-
corresponging values of llcrnrlat, llcrnrlon, urcrnrlat and urcrnrlon.
26+
A: As an alternative to specifying the lat/lon values for the upper-right
27+
and lower-left corners of the projection domain (using the llcrnrlat,
28+
llcrnrlon, urcrnrlat and urcrnrlon keywords) you can specify the center of
29+
the map projection domain (using the lat_0 and lon_0 keywords) and the
30+
width and height of the domain in map projection coordinates (meters)
31+
using the width and height keywords. Basemap will then calculate the
32+
corresponging values of llcrnrlat, llcrnrlon, urcrnrlat and urcrnrlon.
3333
Examples of this are given in the garp.py and setwh.py examples.

examples/hires.py

+43-41
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,51 @@
1-
from __future__ import (absolute_import, division, print_function)
1+
from __future__ import print_function
2+
3+
import time
4+
import pickle
25

3-
from mpl_toolkits.basemap import Basemap
46
import numpy as np
57
import matplotlib.pyplot as plt
6-
import pickle, time
8+
from mpl_toolkits.basemap import Basemap
9+
710

8-
# create figure with aqua background (will be oceans)
11+
# Create figure.
912
fig = plt.figure()
1013

11-
# create Basemap instance. Use 'high' resolution coastlines.
12-
t1 = time.clock()
13-
#m = Basemap(llcrnrlon=-10.5,llcrnrlat=49.5,urcrnrlon=3.5,urcrnrlat=59.5,
14-
# resolution='h',projection='tmerc',lon_0=-4,lat_0=0)
15-
m = Basemap(width=920000,height=1100000,
16-
resolution='f',projection='tmerc',lon_0=-4.2,lat_0=54.6)
17-
# make sure countries and rivers are loaded
18-
m.drawcountries()
19-
m.drawrivers()
20-
print(time.clock()-t1,' secs to create original Basemap instance')
21-
22-
# pickle the class instance.
23-
pickle.dump(m,open('map.pickle','wb'),-1)
24-
25-
# clear the figure
14+
# Create Basemap instance:
15+
# - Use 'full' resolution coastlines.
16+
# - Make sure that countries and rivers are loaded.
17+
t0 = time.time()
18+
bmap1 = Basemap(width=920000, height=1100000, resolution="f",
19+
projection="tmerc", lon_0=-4.2, lat_0=54.6)
20+
bmap1.drawcountries()
21+
bmap1.drawrivers()
22+
t1 = time.time()
23+
print("{0:.3f} secs to plot with a Basemap instance created at runtime".format(t1 - t0))
24+
25+
# Clear the figure.
2626
plt.clf()
27-
# read pickle back in and plot it again (should be much faster).
28-
t1 = time.clock()
29-
m2 = pickle.load(open('map.pickle','rb'))
30-
# draw coastlines and fill continents.
31-
m.drawcoastlines()
32-
# fill continents and lakes
33-
m.fillcontinents(color='coral',lake_color='aqua')
34-
# draw political boundaries.
35-
m.drawcountries(linewidth=1)
36-
# fill map projection region light blue (this will
37-
# paint ocean areas same color as lakes).
38-
m.drawmapboundary(fill_color='aqua')
39-
# draw major rivers.
40-
m.drawrivers(color='b')
41-
print(time.clock()-t1,' secs to plot using using a pickled Basemap instance')
42-
# draw parallels
43-
circles = np.arange(48,65,2).tolist()
44-
m.drawparallels(circles,labels=[1,1,0,0])
45-
# draw meridians
46-
meridians = np.arange(-12,13,2)
47-
m.drawmeridians(meridians,labels=[0,0,1,1])
48-
plt.title("High-Res British Isles",y=1.04)
27+
28+
# Pickle the class instance.
29+
with open("map.pickle", "wb") as fd:
30+
pickle.dump(bmap1, fd, protocol=-1)
31+
32+
# Read pickle back in and plot it again (should be much faster):
33+
# - Draw coastlines and fill continents and lakes.
34+
# - Draw political boundaries and rivers.
35+
# - Draw parallels and meridians.
36+
# - Draw map boundary and fill map background.
37+
t0 = time.time()
38+
with open("map.pickle", "rb") as fd:
39+
bmap2 = pickle.load(fd)
40+
bmap2.drawcoastlines()
41+
bmap2.fillcontinents(color="coral", lake_color="aqua")
42+
bmap2.drawcountries(linewidth=1)
43+
bmap2.drawrivers(color="b")
44+
bmap2.drawparallels(np.arange(48, 65, 2), labels=[1, 1, 0, 0])
45+
bmap2.drawmeridians(np.arange(-12, 13, 2), labels=[0, 0, 1, 1])
46+
bmap2.drawmapboundary(fill_color="aqua")
47+
t1 = time.time()
48+
print("{0:.3f} secs to plot with a pickled Basemap instance".format(t1 - t0))
49+
50+
plt.title("High-Res British Isles", y=1.04)
4951
plt.show()

packages/basemap/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,6 @@ https://spdx.org/licenses/LGPL-2.1-only.html
4545
https://spdx.org/licenses/MIT.html
4646

4747
[`LICENSE`]:
48-
https://github.com/matplotlib/basemap/blob/v1.3.8/packages/basemap/LICENSE
48+
https://github.com/matplotlib/basemap/blob/v1.3.9/packages/basemap/LICENSE
4949
[`LICENSE.geos`]:
50-
https://github.com/matplotlib/basemap/blob/v1.3.8/packages/basemap/LICENSE.geos
50+
https://github.com/matplotlib/basemap/blob/v1.3.9/packages/basemap/LICENSE.geos

packages/basemap/doc/users/figures/plotwindvec.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
uin = data.variables['U-component_of_wind_height_above_ground'][:].squeeze()
2222
vin = data.variables['V-component_of_wind_height_above_ground'][:].squeeze()
2323
# add cyclic points manually (could use addcyclic function)
24-
slp = np.zeros((slpin.shape[0],slpin.shape[1]+1),np.float)
24+
slp = np.zeros((slpin.shape[0],slpin.shape[1]+1),np.float64)
2525
slp[:,0:-1] = slpin[::-1]; slp[:,-1] = slpin[::-1,0]
2626
u = np.zeros((uin.shape[0],uin.shape[1]+1),np.float64)
2727
u[:,0:-1] = uin[::-1]; u[:,-1] = uin[::-1,0]

packages/basemap/setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ def run(self):
172172
"name":
173173
"basemap",
174174
"version":
175-
"1.3.8",
175+
"1.3.9",
176176
"license":
177177
"MIT",
178178
"description":

packages/basemap/src/_geoslib.pyx

+24
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,30 @@ cdef class BaseGeometry:
307307
b = _get_coords(gout)
308308
p = LineString(b)
309309
pout.append(p)
310+
elif typeid == GEOS_GEOMETRYCOLLECTION:
311+
numgeoms = GEOSGetNumGeometries(g3)
312+
pout = []
313+
for i from 0 <= i < numgeoms:
314+
gout = GEOSGetGeometryN(g3, i)
315+
typeid = GEOSGeomTypeId(gout)
316+
if typeid == GEOS_POLYGON:
317+
b = _get_coords(gout)
318+
p = Polygon(b)
319+
pout.append(p)
320+
elif typeid == GEOS_LINESTRING:
321+
b = _get_coords(gout)
322+
p = LineString(b)
323+
pout.append(p)
324+
else:
325+
# More cases might need to be handled here:
326+
# - GEOS_MULTILINESTRING
327+
# - GEOS_MULTIPOLYGON
328+
# - GEOS_GEOMETRYCOLLECTION
329+
# The underlying problem is the need of a generic
330+
# converter from GEOSGeom pointers to `_geoslib`
331+
# objects, since postprocessing `GeometryCollections`
332+
# might need recursiveness.
333+
pass
310334
else:
311335
#type = PyBytes_FromString(GEOSGeomType(g3))
312336
#raise NotImplementedError("intersections of type '%s' not yet implemented" % (type))

packages/basemap/src/mpl_toolkits/basemap/__init__.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
import functools
5555

5656

57-
__version__ = "1.3.8"
57+
__version__ = "1.3.9"
5858

5959
# basemap data files now installed in lib/matplotlib/toolkits/basemap/data
6060
# check to see if environment variable BASEMAPDATA set to a directory,
@@ -1990,7 +1990,7 @@ def drawcounties(self,linewidth=0.1,linestyle='solid',color='k',antialiased=1,
19901990
county_info = self.readshapefile(gis_file,'counties',\
19911991
default_encoding='latin-1',drawbounds=drawbounds)
19921992
counties = [coords for coords in self.counties]
1993-
counties = PolyCollection(counties)
1993+
counties = PolyCollection(counties, antialiaseds=(antialiased,))
19941994
counties.set_linestyle(linestyle)
19951995
counties.set_linewidth(linewidth)
19961996
counties.set_edgecolor(color)
@@ -2203,7 +2203,7 @@ def readshapefile(self,shapefile,name,drawbounds=True,zorder=None,
22032203
# get current axes instance (if none specified).
22042204
ax = ax or self._check_ax()
22052205
# make LineCollections for each polygon.
2206-
lines = LineCollection(coords,antialiaseds=(1,))
2206+
lines = LineCollection(coords,antialiaseds=(antialiased,))
22072207
lines.set_color(color)
22082208
lines.set_linewidth(linewidth)
22092209
lines.set_label('_nolabel_')
@@ -3203,7 +3203,7 @@ def set_axes_limits(self,ax=None):
32033203
# first draw boundary, no fill
32043204
limb1 = self.drawmapboundary(fill_color='none', ax=ax)
32053205
# draw another filled patch, with no boundary.
3206-
limb2 = self.drawmapboundary(linewidth=0, ax=ax)
3206+
limb2 = self.drawmapboundary(fill_color='none', linewidth=0, ax=ax)
32073207
self._mapboundarydrawn = limb2
32083208
# for elliptical map, always turn off axis_frame.
32093209
if ((self.projection in ['ortho', 'geos', 'nsper', 'aeqd'] and
@@ -4181,9 +4181,9 @@ def warpimage(self,image="bluemarble",scale=None,**kwargs):
41814181
lonsr,latsr = self(x,y,inverse=True)
41824182
mask = ma.zeros((ny,nx,4),np.int8)
41834183
lon_0 = self.projparams['lon_0']
4184-
lonright = lon_0+180.
4185-
lonleft = lon_0-180.
4186-
x1 = np.array(ny*[0.5*(self.xmax + self.xmin)],np.float)
4184+
lonright = lon_0 + 180. - 1E-10
4185+
lonleft = lon_0 - 180. + 1E-10
4186+
x1 = np.array(ny*[0.5*(self.xmax + self.xmin)],np.float64)
41874187
y1 = np.linspace(self.ymin, self.ymax, ny)
41884188
lons1, lats1 = self(x1,y1,inverse=True)
41894189
lats1 = np.where(lats1 < -89.999999, -89.999999, lats1)

packages/basemap/src/mpl_toolkits/basemap/proj.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from matplotlib.cbook import dedent
1212

1313

14-
__version__ = "1.3.8"
14+
__version__ = "1.3.9"
1515

1616
_dg2rad = math.radians(1.)
1717
_rad2dg = math.degrees(1.)
@@ -195,8 +195,8 @@ def __init__(self,projparams,llcrnrlon,llcrnrlat,
195195
raise ValueError(_lower_left_out_of_bounds)
196196
elif self.projection in _pseudocyl:
197197
self._proj4 = pyproj.Proj(projparams)
198-
xtmp,urcrnry = self(projparams['lon_0'],90.)
199-
urcrnrx,xtmp = self(projparams['lon_0']+180.,0)
198+
xtmp, urcrnry = self(projparams['lon_0'], 90.)
199+
urcrnrx, xtmp = self(projparams['lon_0'] + 180. - 1E-10, 0)
200200
llcrnrx = -urcrnrx
201201
llcrnry = -urcrnry
202202
if self.ellipsoid and self.projection in ['kav7','eck4','mbtfpq']:
@@ -236,8 +236,8 @@ def __init__(self,projparams,llcrnrlon,llcrnrlat,
236236
if urcrnrx > 1.e20 or urcrnry > 1.e20:
237237
raise ValueError(_upper_right_out_of_bounds)
238238
elif self.projection in _pseudocyl:
239-
xtmp,urcrnry = self(projparams['lon_0'],90.)
240-
urcrnrx,xtmp = self(projparams['lon_0']+180.,0)
239+
xtmp, urcrnry = self(projparams['lon_0'], 90.)
240+
urcrnrx, xtmp = self(projparams['lon_0'] + 180. - 1E-10, 0)
241241
else:
242242
urcrnrx = urcrnrlon
243243
urcrnry = urcrnrlat
@@ -290,7 +290,8 @@ def __call__(self, *args, **kw):
290290
return x,y
291291
inverse = kw.get('inverse', False)
292292
if onearray:
293-
outxy = self._proj4(xy, inverse=inverse)
293+
outx, outy = self._proj4(*xy.T, inverse=inverse)
294+
outxy = np.asarray([outx, outy]).T
294295
else:
295296
outx,outy = self._proj4(x, y, inverse=inverse)
296297
if inverse:

0 commit comments

Comments
 (0)