|
14 | 14 | from icecream import ic
|
15 | 15 | except ImportError: # graceful fallback if IceCream isn't installed
|
16 | 16 | 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'] |
18 | 18 |
|
19 | 19 | # Change this to turn on benchmarking
|
20 | 20 | BENCHMARK = False
|
@@ -153,22 +153,50 @@ def edges(array, axis=-1):
|
153 | 153 | array = np.array(array)
|
154 | 154 | array = np.swapaxes(array, axis, -1)
|
155 | 155 | # 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) |
161 | 156 | array = np.concatenate((
|
162 | 157 | array[...,:1] - (array[...,1]-array[...,0])/2,
|
163 | 158 | (array[...,1:] + array[...,:-1])/2,
|
164 | 159 | array[...,-1:] + (array[...,-1]-array[...,-2])/2,
|
165 | 160 | ), axis=-1)
|
166 |
| - if flip: |
167 |
| - array = np.flip(array, axis=-1) |
168 | 161 | # Permute back and return
|
169 | 162 | array = np.swapaxes(array, axis, -1)
|
170 | 163 | return array
|
171 | 164 |
|
| 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 | + |
172 | 200 | def units(value, numeric='in'):
|
173 | 201 | """
|
174 | 202 | Flexible units -- this function is used internally all over ProPlot, so
|
|
0 commit comments