Skip to content

Commit b08e52d

Browse files
committed
Merge branch 'master' into nbsphinx-docs
2 parents 53aff70 + 3224bbd commit b08e52d

File tree

2 files changed

+57
-11
lines changed

2 files changed

+57
-11
lines changed

proplot/utils.py

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from icecream import ic
1515
except ImportError: # graceful fallback if IceCream isn't installed
1616
ic = lambda *a: None if not a else (a[0] if len(a) == 1 else a) # noqa
17-
__all__ = ['arange', 'edges', 'units']
17+
__all__ = ['arange', 'edges', 'edges2d', 'units']
1818

1919
# Change this to turn on benchmarking
2020
BENCHMARK = False
@@ -153,22 +153,50 @@ def edges(array, axis=-1):
153153
array = np.array(array)
154154
array = np.swapaxes(array, axis, -1)
155155
# Next operate
156-
flip = False
157-
idxs = [[0] for _ in range(array.ndim-1)] # must be list because we use it twice
158-
if array[np.ix_(*idxs, [1])] < array[np.ix_(*idxs, [0])]:
159-
flip = True
160-
array = np.flip(array, axis=-1)
161156
array = np.concatenate((
162157
array[...,:1] - (array[...,1]-array[...,0])/2,
163158
(array[...,1:] + array[...,:-1])/2,
164159
array[...,-1:] + (array[...,-1]-array[...,-2])/2,
165160
), axis=-1)
166-
if flip:
167-
array = np.flip(array, axis=-1)
168161
# Permute back and return
169162
array = np.swapaxes(array, axis, -1)
170163
return array
171164

165+
def edges2d(z):
166+
"""
167+
Like :func:`edges` but for 2D arrays.
168+
The size of both axes are increased of one.
169+
170+
Parameters
171+
----------
172+
array : array-like
173+
Two-dimensional array.
174+
175+
Returns
176+
-------
177+
`~numpy.ndarray`
178+
Array of "edge" coordinates.
179+
"""
180+
z = np.asarray(z)
181+
ny, nx = z.shape
182+
zzb = np.zeros((ny+1, nx+1))
183+
184+
# Inner
185+
zzb[1:-1, 1:-1] = 0.25 * (z[1:, 1:] + z[:-1, 1:] +
186+
z[1:, :-1] + z[:-1, :-1])
187+
# Lower and upper
188+
zzb[0] += edges(1.5*z[0]-0.5*z[1])
189+
zzb[-1] += edges(1.5*z[-1]-0.5*z[-2])
190+
191+
# Left and right
192+
zzb[:, 0] += edges(1.5*z[:, 0]-0.5*z[:, 1])
193+
zzb[:, -1] += edges(1.5*z[:, -1]-0.5*z[:, -2])
194+
195+
# Corners
196+
zzb[[0, 0, -1, -1], [0, -1, -1, 0]] *= 0.5
197+
198+
return zzb
199+
172200
def units(value, numeric='in'):
173201
"""
174202
Flexible units -- this function is used internally all over ProPlot, so

proplot/wrappers.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,13 @@ def standardize_2d(self, func, *args, order='C', globe=False, **kwargs):
476476
if all(z.ndim == 1 and z.size > 1 and z.dtype != 'object' for z in (x,y)):
477477
x = utils.edges(x)
478478
y = utils.edges(y)
479+
else:
480+
if (x.ndim == 2 and x.shape[0] > 1 and x.shape[1] > 1 and
481+
x.dtype != 'object'):
482+
x = utils.edges2d(x)
483+
if (y.ndim == 2 and y.shape[0] > 1 and y.shape[1] > 1 and
484+
y.dtype != 'object'):
485+
y = utils.edges2d(y)
479486
elif Z.shape[1] != xlen-1 or Z.shape[0] != ylen-1:
480487
raise ValueError(f'Input shapes x {x.shape} and y {y.shape} must match Z centers {Z.shape} or Z borders {tuple(i+1 for i in Z.shape)}.')
481488
# Optionally re-order
@@ -494,10 +501,19 @@ def standardize_2d(self, func, *args, order='C', globe=False, **kwargs):
494501
for Z in Zs:
495502
if Z.ndim != 2:
496503
raise ValueError(f'Input arrays must be 2D, instead got shape {Z.shape}.')
497-
elif Z.shape[1] == xlen-1 and Z.shape[0] == ylen-1 and x.ndim == 1 and y.ndim == 1:
504+
elif Z.shape[1] == xlen-1 and Z.shape[0] == ylen-1:
498505
if all(z.ndim == 1 and z.size > 1 and z.dtype != 'object' for z in (x,y)):
499506
x = (x[1:] + x[:-1])/2
500507
y = (y[1:] + y[:-1])/2
508+
else:
509+
if (x.ndim == 2 and x.shape[0] > 1 and x.shape[1] > 1 and
510+
x.dtype != 'object'):
511+
x = 0.25 * (x[:-1, :-1] + x[:-1, 1:] +
512+
x[1:, :-1] + x[1:, 1:])
513+
if (y.ndim == 2 and y.shape[0] > 1 and y.shape[1] > 1 and
514+
y.dtype != 'object'):
515+
y = 0.25 * (y[:-1, :-1] + y[:-1, 1:] +
516+
y[1:, :-1] + y[1:, 1:])
501517
elif Z.shape[1] != xlen or Z.shape[0] != ylen:
502518
raise ValueError(f'Input shapes x {x.shape} and y {y.shape} must match Z centers {Z.shape} or Z borders {tuple(i+1 for i in Z.shape)}.')
503519
# Optionally re-order
@@ -2215,9 +2231,11 @@ def legend_wrapper(self,
22152231
self.add_artist(leg)
22162232
leg.legendPatch.update(outline) # or get_frame()
22172233
for obj in leg.legendHandles:
2218-
obj.update(kw_handle)
2234+
if isinstance(obj, martist.Artist):
2235+
obj.update(kw_handle)
22192236
for obj in leg.get_texts():
2220-
obj.update(kw_text)
2237+
if isinstance(obj, martist.Artist):
2238+
obj.update(kw_text)
22212239
# Draw manual fancy bounding box for un-aligned legend
22222240
# WARNING: The matplotlib legendPatch transform is the default transform,
22232241
# i.e. universal coordinates in points. Means we have to transform

0 commit comments

Comments
 (0)