Chris@87
|
1 from __future__ import division, absolute_import, print_function
|
Chris@87
|
2
|
Chris@87
|
3 import warnings
|
Chris@87
|
4 import sys
|
Chris@87
|
5 import collections
|
Chris@87
|
6 import operator
|
Chris@87
|
7
|
Chris@87
|
8 import numpy as np
|
Chris@87
|
9 import numpy.core.numeric as _nx
|
Chris@87
|
10 from numpy.core import linspace, atleast_1d, atleast_2d
|
Chris@87
|
11 from numpy.core.numeric import (
|
Chris@87
|
12 ones, zeros, arange, concatenate, array, asarray, asanyarray, empty,
|
Chris@87
|
13 empty_like, ndarray, around, floor, ceil, take, dot, where, intp,
|
Chris@87
|
14 integer, isscalar
|
Chris@87
|
15 )
|
Chris@87
|
16 from numpy.core.umath import (
|
Chris@87
|
17 pi, multiply, add, arctan2, frompyfunc, cos, less_equal, sqrt, sin,
|
Chris@87
|
18 mod, exp, log10
|
Chris@87
|
19 )
|
Chris@87
|
20 from numpy.core.fromnumeric import (
|
Chris@87
|
21 ravel, nonzero, sort, partition, mean
|
Chris@87
|
22 )
|
Chris@87
|
23 from numpy.core.numerictypes import typecodes, number
|
Chris@87
|
24 from numpy.lib.twodim_base import diag
|
Chris@87
|
25 from .utils import deprecate
|
Chris@87
|
26 from ._compiled_base import _insert, add_docstring
|
Chris@87
|
27 from ._compiled_base import digitize, bincount, interp as compiled_interp
|
Chris@87
|
28 from ._compiled_base import add_newdoc_ufunc
|
Chris@87
|
29 from numpy.compat import long
|
Chris@87
|
30
|
Chris@87
|
31 # Force range to be a generator, for np.delete's usage.
|
Chris@87
|
32 if sys.version_info[0] < 3:
|
Chris@87
|
33 range = xrange
|
Chris@87
|
34
|
Chris@87
|
35
|
Chris@87
|
36 __all__ = [
|
Chris@87
|
37 'select', 'piecewise', 'trim_zeros', 'copy', 'iterable', 'percentile',
|
Chris@87
|
38 'diff', 'gradient', 'angle', 'unwrap', 'sort_complex', 'disp',
|
Chris@87
|
39 'extract', 'place', 'vectorize', 'asarray_chkfinite', 'average',
|
Chris@87
|
40 'histogram', 'histogramdd', 'bincount', 'digitize', 'cov', 'corrcoef',
|
Chris@87
|
41 'msort', 'median', 'sinc', 'hamming', 'hanning', 'bartlett',
|
Chris@87
|
42 'blackman', 'kaiser', 'trapz', 'i0', 'add_newdoc', 'add_docstring',
|
Chris@87
|
43 'meshgrid', 'delete', 'insert', 'append', 'interp', 'add_newdoc_ufunc'
|
Chris@87
|
44 ]
|
Chris@87
|
45
|
Chris@87
|
46
|
Chris@87
|
47 def iterable(y):
|
Chris@87
|
48 """
|
Chris@87
|
49 Check whether or not an object can be iterated over.
|
Chris@87
|
50
|
Chris@87
|
51 Parameters
|
Chris@87
|
52 ----------
|
Chris@87
|
53 y : object
|
Chris@87
|
54 Input object.
|
Chris@87
|
55
|
Chris@87
|
56 Returns
|
Chris@87
|
57 -------
|
Chris@87
|
58 b : {0, 1}
|
Chris@87
|
59 Return 1 if the object has an iterator method or is a sequence,
|
Chris@87
|
60 and 0 otherwise.
|
Chris@87
|
61
|
Chris@87
|
62
|
Chris@87
|
63 Examples
|
Chris@87
|
64 --------
|
Chris@87
|
65 >>> np.iterable([1, 2, 3])
|
Chris@87
|
66 1
|
Chris@87
|
67 >>> np.iterable(2)
|
Chris@87
|
68 0
|
Chris@87
|
69
|
Chris@87
|
70 """
|
Chris@87
|
71 try:
|
Chris@87
|
72 iter(y)
|
Chris@87
|
73 except:
|
Chris@87
|
74 return 0
|
Chris@87
|
75 return 1
|
Chris@87
|
76
|
Chris@87
|
77
|
Chris@87
|
78 def histogram(a, bins=10, range=None, normed=False, weights=None,
|
Chris@87
|
79 density=None):
|
Chris@87
|
80 """
|
Chris@87
|
81 Compute the histogram of a set of data.
|
Chris@87
|
82
|
Chris@87
|
83 Parameters
|
Chris@87
|
84 ----------
|
Chris@87
|
85 a : array_like
|
Chris@87
|
86 Input data. The histogram is computed over the flattened array.
|
Chris@87
|
87 bins : int or sequence of scalars, optional
|
Chris@87
|
88 If `bins` is an int, it defines the number of equal-width
|
Chris@87
|
89 bins in the given range (10, by default). If `bins` is a sequence,
|
Chris@87
|
90 it defines the bin edges, including the rightmost edge, allowing
|
Chris@87
|
91 for non-uniform bin widths.
|
Chris@87
|
92 range : (float, float), optional
|
Chris@87
|
93 The lower and upper range of the bins. If not provided, range
|
Chris@87
|
94 is simply ``(a.min(), a.max())``. Values outside the range are
|
Chris@87
|
95 ignored.
|
Chris@87
|
96 normed : bool, optional
|
Chris@87
|
97 This keyword is deprecated in Numpy 1.6 due to confusing/buggy
|
Chris@87
|
98 behavior. It will be removed in Numpy 2.0. Use the density keyword
|
Chris@87
|
99 instead.
|
Chris@87
|
100 If False, the result will contain the number of samples
|
Chris@87
|
101 in each bin. If True, the result is the value of the
|
Chris@87
|
102 probability *density* function at the bin, normalized such that
|
Chris@87
|
103 the *integral* over the range is 1. Note that this latter behavior is
|
Chris@87
|
104 known to be buggy with unequal bin widths; use `density` instead.
|
Chris@87
|
105 weights : array_like, optional
|
Chris@87
|
106 An array of weights, of the same shape as `a`. Each value in `a`
|
Chris@87
|
107 only contributes its associated weight towards the bin count
|
Chris@87
|
108 (instead of 1). If `normed` is True, the weights are normalized,
|
Chris@87
|
109 so that the integral of the density over the range remains 1
|
Chris@87
|
110 density : bool, optional
|
Chris@87
|
111 If False, the result will contain the number of samples
|
Chris@87
|
112 in each bin. If True, the result is the value of the
|
Chris@87
|
113 probability *density* function at the bin, normalized such that
|
Chris@87
|
114 the *integral* over the range is 1. Note that the sum of the
|
Chris@87
|
115 histogram values will not be equal to 1 unless bins of unity
|
Chris@87
|
116 width are chosen; it is not a probability *mass* function.
|
Chris@87
|
117 Overrides the `normed` keyword if given.
|
Chris@87
|
118
|
Chris@87
|
119 Returns
|
Chris@87
|
120 -------
|
Chris@87
|
121 hist : array
|
Chris@87
|
122 The values of the histogram. See `normed` and `weights` for a
|
Chris@87
|
123 description of the possible semantics.
|
Chris@87
|
124 bin_edges : array of dtype float
|
Chris@87
|
125 Return the bin edges ``(length(hist)+1)``.
|
Chris@87
|
126
|
Chris@87
|
127
|
Chris@87
|
128 See Also
|
Chris@87
|
129 --------
|
Chris@87
|
130 histogramdd, bincount, searchsorted, digitize
|
Chris@87
|
131
|
Chris@87
|
132 Notes
|
Chris@87
|
133 -----
|
Chris@87
|
134 All but the last (righthand-most) bin is half-open. In other words, if
|
Chris@87
|
135 `bins` is::
|
Chris@87
|
136
|
Chris@87
|
137 [1, 2, 3, 4]
|
Chris@87
|
138
|
Chris@87
|
139 then the first bin is ``[1, 2)`` (including 1, but excluding 2) and the
|
Chris@87
|
140 second ``[2, 3)``. The last bin, however, is ``[3, 4]``, which *includes*
|
Chris@87
|
141 4.
|
Chris@87
|
142
|
Chris@87
|
143 Examples
|
Chris@87
|
144 --------
|
Chris@87
|
145 >>> np.histogram([1, 2, 1], bins=[0, 1, 2, 3])
|
Chris@87
|
146 (array([0, 2, 1]), array([0, 1, 2, 3]))
|
Chris@87
|
147 >>> np.histogram(np.arange(4), bins=np.arange(5), density=True)
|
Chris@87
|
148 (array([ 0.25, 0.25, 0.25, 0.25]), array([0, 1, 2, 3, 4]))
|
Chris@87
|
149 >>> np.histogram([[1, 2, 1], [1, 0, 1]], bins=[0,1,2,3])
|
Chris@87
|
150 (array([1, 4, 1]), array([0, 1, 2, 3]))
|
Chris@87
|
151
|
Chris@87
|
152 >>> a = np.arange(5)
|
Chris@87
|
153 >>> hist, bin_edges = np.histogram(a, density=True)
|
Chris@87
|
154 >>> hist
|
Chris@87
|
155 array([ 0.5, 0. , 0.5, 0. , 0. , 0.5, 0. , 0.5, 0. , 0.5])
|
Chris@87
|
156 >>> hist.sum()
|
Chris@87
|
157 2.4999999999999996
|
Chris@87
|
158 >>> np.sum(hist*np.diff(bin_edges))
|
Chris@87
|
159 1.0
|
Chris@87
|
160
|
Chris@87
|
161 """
|
Chris@87
|
162
|
Chris@87
|
163 a = asarray(a)
|
Chris@87
|
164 if weights is not None:
|
Chris@87
|
165 weights = asarray(weights)
|
Chris@87
|
166 if np.any(weights.shape != a.shape):
|
Chris@87
|
167 raise ValueError(
|
Chris@87
|
168 'weights should have the same shape as a.')
|
Chris@87
|
169 weights = weights.ravel()
|
Chris@87
|
170 a = a.ravel()
|
Chris@87
|
171
|
Chris@87
|
172 if (range is not None):
|
Chris@87
|
173 mn, mx = range
|
Chris@87
|
174 if (mn > mx):
|
Chris@87
|
175 raise AttributeError(
|
Chris@87
|
176 'max must be larger than min in range parameter.')
|
Chris@87
|
177
|
Chris@87
|
178 if not iterable(bins):
|
Chris@87
|
179 if np.isscalar(bins) and bins < 1:
|
Chris@87
|
180 raise ValueError(
|
Chris@87
|
181 '`bins` should be a positive integer.')
|
Chris@87
|
182 if range is None:
|
Chris@87
|
183 if a.size == 0:
|
Chris@87
|
184 # handle empty arrays. Can't determine range, so use 0-1.
|
Chris@87
|
185 range = (0, 1)
|
Chris@87
|
186 else:
|
Chris@87
|
187 range = (a.min(), a.max())
|
Chris@87
|
188 mn, mx = [mi + 0.0 for mi in range]
|
Chris@87
|
189 if mn == mx:
|
Chris@87
|
190 mn -= 0.5
|
Chris@87
|
191 mx += 0.5
|
Chris@87
|
192 bins = linspace(mn, mx, bins + 1, endpoint=True)
|
Chris@87
|
193 else:
|
Chris@87
|
194 bins = asarray(bins)
|
Chris@87
|
195 if (np.diff(bins) < 0).any():
|
Chris@87
|
196 raise AttributeError(
|
Chris@87
|
197 'bins must increase monotonically.')
|
Chris@87
|
198
|
Chris@87
|
199 # Histogram is an integer or a float array depending on the weights.
|
Chris@87
|
200 if weights is None:
|
Chris@87
|
201 ntype = int
|
Chris@87
|
202 else:
|
Chris@87
|
203 ntype = weights.dtype
|
Chris@87
|
204 n = np.zeros(bins.shape, ntype)
|
Chris@87
|
205
|
Chris@87
|
206 block = 65536
|
Chris@87
|
207 if weights is None:
|
Chris@87
|
208 for i in arange(0, len(a), block):
|
Chris@87
|
209 sa = sort(a[i:i+block])
|
Chris@87
|
210 n += np.r_[sa.searchsorted(bins[:-1], 'left'),
|
Chris@87
|
211 sa.searchsorted(bins[-1], 'right')]
|
Chris@87
|
212 else:
|
Chris@87
|
213 zero = array(0, dtype=ntype)
|
Chris@87
|
214 for i in arange(0, len(a), block):
|
Chris@87
|
215 tmp_a = a[i:i+block]
|
Chris@87
|
216 tmp_w = weights[i:i+block]
|
Chris@87
|
217 sorting_index = np.argsort(tmp_a)
|
Chris@87
|
218 sa = tmp_a[sorting_index]
|
Chris@87
|
219 sw = tmp_w[sorting_index]
|
Chris@87
|
220 cw = np.concatenate(([zero, ], sw.cumsum()))
|
Chris@87
|
221 bin_index = np.r_[sa.searchsorted(bins[:-1], 'left'),
|
Chris@87
|
222 sa.searchsorted(bins[-1], 'right')]
|
Chris@87
|
223 n += cw[bin_index]
|
Chris@87
|
224
|
Chris@87
|
225 n = np.diff(n)
|
Chris@87
|
226
|
Chris@87
|
227 if density is not None:
|
Chris@87
|
228 if density:
|
Chris@87
|
229 db = array(np.diff(bins), float)
|
Chris@87
|
230 return n/db/n.sum(), bins
|
Chris@87
|
231 else:
|
Chris@87
|
232 return n, bins
|
Chris@87
|
233 else:
|
Chris@87
|
234 # deprecated, buggy behavior. Remove for Numpy 2.0
|
Chris@87
|
235 if normed:
|
Chris@87
|
236 db = array(np.diff(bins), float)
|
Chris@87
|
237 return n/(n*db).sum(), bins
|
Chris@87
|
238 else:
|
Chris@87
|
239 return n, bins
|
Chris@87
|
240
|
Chris@87
|
241
|
Chris@87
|
242 def histogramdd(sample, bins=10, range=None, normed=False, weights=None):
|
Chris@87
|
243 """
|
Chris@87
|
244 Compute the multidimensional histogram of some data.
|
Chris@87
|
245
|
Chris@87
|
246 Parameters
|
Chris@87
|
247 ----------
|
Chris@87
|
248 sample : array_like
|
Chris@87
|
249 The data to be histogrammed. It must be an (N,D) array or data
|
Chris@87
|
250 that can be converted to such. The rows of the resulting array
|
Chris@87
|
251 are the coordinates of points in a D dimensional polytope.
|
Chris@87
|
252 bins : sequence or int, optional
|
Chris@87
|
253 The bin specification:
|
Chris@87
|
254
|
Chris@87
|
255 * A sequence of arrays describing the bin edges along each dimension.
|
Chris@87
|
256 * The number of bins for each dimension (nx, ny, ... =bins)
|
Chris@87
|
257 * The number of bins for all dimensions (nx=ny=...=bins).
|
Chris@87
|
258
|
Chris@87
|
259 range : sequence, optional
|
Chris@87
|
260 A sequence of lower and upper bin edges to be used if the edges are
|
Chris@87
|
261 not given explicitly in `bins`. Defaults to the minimum and maximum
|
Chris@87
|
262 values along each dimension.
|
Chris@87
|
263 normed : bool, optional
|
Chris@87
|
264 If False, returns the number of samples in each bin. If True,
|
Chris@87
|
265 returns the bin density ``bin_count / sample_count / bin_volume``.
|
Chris@87
|
266 weights : array_like (N,), optional
|
Chris@87
|
267 An array of values `w_i` weighing each sample `(x_i, y_i, z_i, ...)`.
|
Chris@87
|
268 Weights are normalized to 1 if normed is True. If normed is False,
|
Chris@87
|
269 the values of the returned histogram are equal to the sum of the
|
Chris@87
|
270 weights belonging to the samples falling into each bin.
|
Chris@87
|
271
|
Chris@87
|
272 Returns
|
Chris@87
|
273 -------
|
Chris@87
|
274 H : ndarray
|
Chris@87
|
275 The multidimensional histogram of sample x. See normed and weights
|
Chris@87
|
276 for the different possible semantics.
|
Chris@87
|
277 edges : list
|
Chris@87
|
278 A list of D arrays describing the bin edges for each dimension.
|
Chris@87
|
279
|
Chris@87
|
280 See Also
|
Chris@87
|
281 --------
|
Chris@87
|
282 histogram: 1-D histogram
|
Chris@87
|
283 histogram2d: 2-D histogram
|
Chris@87
|
284
|
Chris@87
|
285 Examples
|
Chris@87
|
286 --------
|
Chris@87
|
287 >>> r = np.random.randn(100,3)
|
Chris@87
|
288 >>> H, edges = np.histogramdd(r, bins = (5, 8, 4))
|
Chris@87
|
289 >>> H.shape, edges[0].size, edges[1].size, edges[2].size
|
Chris@87
|
290 ((5, 8, 4), 6, 9, 5)
|
Chris@87
|
291
|
Chris@87
|
292 """
|
Chris@87
|
293
|
Chris@87
|
294 try:
|
Chris@87
|
295 # Sample is an ND-array.
|
Chris@87
|
296 N, D = sample.shape
|
Chris@87
|
297 except (AttributeError, ValueError):
|
Chris@87
|
298 # Sample is a sequence of 1D arrays.
|
Chris@87
|
299 sample = atleast_2d(sample).T
|
Chris@87
|
300 N, D = sample.shape
|
Chris@87
|
301
|
Chris@87
|
302 nbin = empty(D, int)
|
Chris@87
|
303 edges = D*[None]
|
Chris@87
|
304 dedges = D*[None]
|
Chris@87
|
305 if weights is not None:
|
Chris@87
|
306 weights = asarray(weights)
|
Chris@87
|
307
|
Chris@87
|
308 try:
|
Chris@87
|
309 M = len(bins)
|
Chris@87
|
310 if M != D:
|
Chris@87
|
311 raise AttributeError(
|
Chris@87
|
312 'The dimension of bins must be equal to the dimension of the '
|
Chris@87
|
313 ' sample x.')
|
Chris@87
|
314 except TypeError:
|
Chris@87
|
315 # bins is an integer
|
Chris@87
|
316 bins = D*[bins]
|
Chris@87
|
317
|
Chris@87
|
318 # Select range for each dimension
|
Chris@87
|
319 # Used only if number of bins is given.
|
Chris@87
|
320 if range is None:
|
Chris@87
|
321 # Handle empty input. Range can't be determined in that case, use 0-1.
|
Chris@87
|
322 if N == 0:
|
Chris@87
|
323 smin = zeros(D)
|
Chris@87
|
324 smax = ones(D)
|
Chris@87
|
325 else:
|
Chris@87
|
326 smin = atleast_1d(array(sample.min(0), float))
|
Chris@87
|
327 smax = atleast_1d(array(sample.max(0), float))
|
Chris@87
|
328 else:
|
Chris@87
|
329 smin = zeros(D)
|
Chris@87
|
330 smax = zeros(D)
|
Chris@87
|
331 for i in arange(D):
|
Chris@87
|
332 smin[i], smax[i] = range[i]
|
Chris@87
|
333
|
Chris@87
|
334 # Make sure the bins have a finite width.
|
Chris@87
|
335 for i in arange(len(smin)):
|
Chris@87
|
336 if smin[i] == smax[i]:
|
Chris@87
|
337 smin[i] = smin[i] - .5
|
Chris@87
|
338 smax[i] = smax[i] + .5
|
Chris@87
|
339
|
Chris@87
|
340 # avoid rounding issues for comparisons when dealing with inexact types
|
Chris@87
|
341 if np.issubdtype(sample.dtype, np.inexact):
|
Chris@87
|
342 edge_dt = sample.dtype
|
Chris@87
|
343 else:
|
Chris@87
|
344 edge_dt = float
|
Chris@87
|
345 # Create edge arrays
|
Chris@87
|
346 for i in arange(D):
|
Chris@87
|
347 if isscalar(bins[i]):
|
Chris@87
|
348 if bins[i] < 1:
|
Chris@87
|
349 raise ValueError(
|
Chris@87
|
350 "Element at index %s in `bins` should be a positive "
|
Chris@87
|
351 "integer." % i)
|
Chris@87
|
352 nbin[i] = bins[i] + 2 # +2 for outlier bins
|
Chris@87
|
353 edges[i] = linspace(smin[i], smax[i], nbin[i]-1, dtype=edge_dt)
|
Chris@87
|
354 else:
|
Chris@87
|
355 edges[i] = asarray(bins[i], edge_dt)
|
Chris@87
|
356 nbin[i] = len(edges[i]) + 1 # +1 for outlier bins
|
Chris@87
|
357 dedges[i] = diff(edges[i])
|
Chris@87
|
358 if np.any(np.asarray(dedges[i]) <= 0):
|
Chris@87
|
359 raise ValueError(
|
Chris@87
|
360 "Found bin edge of size <= 0. Did you specify `bins` with"
|
Chris@87
|
361 "non-monotonic sequence?")
|
Chris@87
|
362
|
Chris@87
|
363 nbin = asarray(nbin)
|
Chris@87
|
364
|
Chris@87
|
365 # Handle empty input.
|
Chris@87
|
366 if N == 0:
|
Chris@87
|
367 return np.zeros(nbin-2), edges
|
Chris@87
|
368
|
Chris@87
|
369 # Compute the bin number each sample falls into.
|
Chris@87
|
370 Ncount = {}
|
Chris@87
|
371 for i in arange(D):
|
Chris@87
|
372 Ncount[i] = digitize(sample[:, i], edges[i])
|
Chris@87
|
373
|
Chris@87
|
374 # Using digitize, values that fall on an edge are put in the right bin.
|
Chris@87
|
375 # For the rightmost bin, we want values equal to the right edge to be
|
Chris@87
|
376 # counted in the last bin, and not as an outlier.
|
Chris@87
|
377 for i in arange(D):
|
Chris@87
|
378 # Rounding precision
|
Chris@87
|
379 mindiff = dedges[i].min()
|
Chris@87
|
380 if not np.isinf(mindiff):
|
Chris@87
|
381 decimal = int(-log10(mindiff)) + 6
|
Chris@87
|
382 # Find which points are on the rightmost edge.
|
Chris@87
|
383 not_smaller_than_edge = (sample[:, i] >= edges[i][-1])
|
Chris@87
|
384 on_edge = (around(sample[:, i], decimal) ==
|
Chris@87
|
385 around(edges[i][-1], decimal))
|
Chris@87
|
386 # Shift these points one bin to the left.
|
Chris@87
|
387 Ncount[i][where(on_edge & not_smaller_than_edge)[0]] -= 1
|
Chris@87
|
388
|
Chris@87
|
389 # Flattened histogram matrix (1D)
|
Chris@87
|
390 # Reshape is used so that overlarge arrays
|
Chris@87
|
391 # will raise an error.
|
Chris@87
|
392 hist = zeros(nbin, float).reshape(-1)
|
Chris@87
|
393
|
Chris@87
|
394 # Compute the sample indices in the flattened histogram matrix.
|
Chris@87
|
395 ni = nbin.argsort()
|
Chris@87
|
396 xy = zeros(N, int)
|
Chris@87
|
397 for i in arange(0, D-1):
|
Chris@87
|
398 xy += Ncount[ni[i]] * nbin[ni[i+1:]].prod()
|
Chris@87
|
399 xy += Ncount[ni[-1]]
|
Chris@87
|
400
|
Chris@87
|
401 # Compute the number of repetitions in xy and assign it to the
|
Chris@87
|
402 # flattened histmat.
|
Chris@87
|
403 if len(xy) == 0:
|
Chris@87
|
404 return zeros(nbin-2, int), edges
|
Chris@87
|
405
|
Chris@87
|
406 flatcount = bincount(xy, weights)
|
Chris@87
|
407 a = arange(len(flatcount))
|
Chris@87
|
408 hist[a] = flatcount
|
Chris@87
|
409
|
Chris@87
|
410 # Shape into a proper matrix
|
Chris@87
|
411 hist = hist.reshape(sort(nbin))
|
Chris@87
|
412 for i in arange(nbin.size):
|
Chris@87
|
413 j = ni.argsort()[i]
|
Chris@87
|
414 hist = hist.swapaxes(i, j)
|
Chris@87
|
415 ni[i], ni[j] = ni[j], ni[i]
|
Chris@87
|
416
|
Chris@87
|
417 # Remove outliers (indices 0 and -1 for each dimension).
|
Chris@87
|
418 core = D*[slice(1, -1)]
|
Chris@87
|
419 hist = hist[core]
|
Chris@87
|
420
|
Chris@87
|
421 # Normalize if normed is True
|
Chris@87
|
422 if normed:
|
Chris@87
|
423 s = hist.sum()
|
Chris@87
|
424 for i in arange(D):
|
Chris@87
|
425 shape = ones(D, int)
|
Chris@87
|
426 shape[i] = nbin[i] - 2
|
Chris@87
|
427 hist = hist / dedges[i].reshape(shape)
|
Chris@87
|
428 hist /= s
|
Chris@87
|
429
|
Chris@87
|
430 if (hist.shape != nbin - 2).any():
|
Chris@87
|
431 raise RuntimeError(
|
Chris@87
|
432 "Internal Shape Error")
|
Chris@87
|
433 return hist, edges
|
Chris@87
|
434
|
Chris@87
|
435
|
Chris@87
|
436 def average(a, axis=None, weights=None, returned=False):
|
Chris@87
|
437 """
|
Chris@87
|
438 Compute the weighted average along the specified axis.
|
Chris@87
|
439
|
Chris@87
|
440 Parameters
|
Chris@87
|
441 ----------
|
Chris@87
|
442 a : array_like
|
Chris@87
|
443 Array containing data to be averaged. If `a` is not an array, a
|
Chris@87
|
444 conversion is attempted.
|
Chris@87
|
445 axis : int, optional
|
Chris@87
|
446 Axis along which to average `a`. If `None`, averaging is done over
|
Chris@87
|
447 the flattened array.
|
Chris@87
|
448 weights : array_like, optional
|
Chris@87
|
449 An array of weights associated with the values in `a`. Each value in
|
Chris@87
|
450 `a` contributes to the average according to its associated weight.
|
Chris@87
|
451 The weights array can either be 1-D (in which case its length must be
|
Chris@87
|
452 the size of `a` along the given axis) or of the same shape as `a`.
|
Chris@87
|
453 If `weights=None`, then all data in `a` are assumed to have a
|
Chris@87
|
454 weight equal to one.
|
Chris@87
|
455 returned : bool, optional
|
Chris@87
|
456 Default is `False`. If `True`, the tuple (`average`, `sum_of_weights`)
|
Chris@87
|
457 is returned, otherwise only the average is returned.
|
Chris@87
|
458 If `weights=None`, `sum_of_weights` is equivalent to the number of
|
Chris@87
|
459 elements over which the average is taken.
|
Chris@87
|
460
|
Chris@87
|
461
|
Chris@87
|
462 Returns
|
Chris@87
|
463 -------
|
Chris@87
|
464 average, [sum_of_weights] : {array_type, double}
|
Chris@87
|
465 Return the average along the specified axis. When returned is `True`,
|
Chris@87
|
466 return a tuple with the average as the first element and the sum
|
Chris@87
|
467 of the weights as the second element. The return type is `Float`
|
Chris@87
|
468 if `a` is of integer type, otherwise it is of the same type as `a`.
|
Chris@87
|
469 `sum_of_weights` is of the same type as `average`.
|
Chris@87
|
470
|
Chris@87
|
471 Raises
|
Chris@87
|
472 ------
|
Chris@87
|
473 ZeroDivisionError
|
Chris@87
|
474 When all weights along axis are zero. See `numpy.ma.average` for a
|
Chris@87
|
475 version robust to this type of error.
|
Chris@87
|
476 TypeError
|
Chris@87
|
477 When the length of 1D `weights` is not the same as the shape of `a`
|
Chris@87
|
478 along axis.
|
Chris@87
|
479
|
Chris@87
|
480 See Also
|
Chris@87
|
481 --------
|
Chris@87
|
482 mean
|
Chris@87
|
483
|
Chris@87
|
484 ma.average : average for masked arrays -- useful if your data contains
|
Chris@87
|
485 "missing" values
|
Chris@87
|
486
|
Chris@87
|
487 Examples
|
Chris@87
|
488 --------
|
Chris@87
|
489 >>> data = range(1,5)
|
Chris@87
|
490 >>> data
|
Chris@87
|
491 [1, 2, 3, 4]
|
Chris@87
|
492 >>> np.average(data)
|
Chris@87
|
493 2.5
|
Chris@87
|
494 >>> np.average(range(1,11), weights=range(10,0,-1))
|
Chris@87
|
495 4.0
|
Chris@87
|
496
|
Chris@87
|
497 >>> data = np.arange(6).reshape((3,2))
|
Chris@87
|
498 >>> data
|
Chris@87
|
499 array([[0, 1],
|
Chris@87
|
500 [2, 3],
|
Chris@87
|
501 [4, 5]])
|
Chris@87
|
502 >>> np.average(data, axis=1, weights=[1./4, 3./4])
|
Chris@87
|
503 array([ 0.75, 2.75, 4.75])
|
Chris@87
|
504 >>> np.average(data, weights=[1./4, 3./4])
|
Chris@87
|
505 Traceback (most recent call last):
|
Chris@87
|
506 ...
|
Chris@87
|
507 TypeError: Axis must be specified when shapes of a and weights differ.
|
Chris@87
|
508
|
Chris@87
|
509 """
|
Chris@87
|
510 if not isinstance(a, np.matrix):
|
Chris@87
|
511 a = np.asarray(a)
|
Chris@87
|
512
|
Chris@87
|
513 if weights is None:
|
Chris@87
|
514 avg = a.mean(axis)
|
Chris@87
|
515 scl = avg.dtype.type(a.size/avg.size)
|
Chris@87
|
516 else:
|
Chris@87
|
517 a = a + 0.0
|
Chris@87
|
518 wgt = np.array(weights, dtype=a.dtype, copy=0)
|
Chris@87
|
519
|
Chris@87
|
520 # Sanity checks
|
Chris@87
|
521 if a.shape != wgt.shape:
|
Chris@87
|
522 if axis is None:
|
Chris@87
|
523 raise TypeError(
|
Chris@87
|
524 "Axis must be specified when shapes of a and weights "
|
Chris@87
|
525 "differ.")
|
Chris@87
|
526 if wgt.ndim != 1:
|
Chris@87
|
527 raise TypeError(
|
Chris@87
|
528 "1D weights expected when shapes of a and weights differ.")
|
Chris@87
|
529 if wgt.shape[0] != a.shape[axis]:
|
Chris@87
|
530 raise ValueError(
|
Chris@87
|
531 "Length of weights not compatible with specified axis.")
|
Chris@87
|
532
|
Chris@87
|
533 # setup wgt to broadcast along axis
|
Chris@87
|
534 wgt = np.array(wgt, copy=0, ndmin=a.ndim).swapaxes(-1, axis)
|
Chris@87
|
535
|
Chris@87
|
536 scl = wgt.sum(axis=axis)
|
Chris@87
|
537 if (scl == 0.0).any():
|
Chris@87
|
538 raise ZeroDivisionError(
|
Chris@87
|
539 "Weights sum to zero, can't be normalized")
|
Chris@87
|
540
|
Chris@87
|
541 avg = np.multiply(a, wgt).sum(axis)/scl
|
Chris@87
|
542
|
Chris@87
|
543 if returned:
|
Chris@87
|
544 scl = np.multiply(avg, 0) + scl
|
Chris@87
|
545 return avg, scl
|
Chris@87
|
546 else:
|
Chris@87
|
547 return avg
|
Chris@87
|
548
|
Chris@87
|
549
|
Chris@87
|
550 def asarray_chkfinite(a, dtype=None, order=None):
|
Chris@87
|
551 """
|
Chris@87
|
552 Convert the input to an array, checking for NaNs or Infs.
|
Chris@87
|
553
|
Chris@87
|
554 Parameters
|
Chris@87
|
555 ----------
|
Chris@87
|
556 a : array_like
|
Chris@87
|
557 Input data, in any form that can be converted to an array. This
|
Chris@87
|
558 includes lists, lists of tuples, tuples, tuples of tuples, tuples
|
Chris@87
|
559 of lists and ndarrays. Success requires no NaNs or Infs.
|
Chris@87
|
560 dtype : data-type, optional
|
Chris@87
|
561 By default, the data-type is inferred from the input data.
|
Chris@87
|
562 order : {'C', 'F'}, optional
|
Chris@87
|
563 Whether to use row-major ('C') or column-major ('FORTRAN') memory
|
Chris@87
|
564 representation. Defaults to 'C'.
|
Chris@87
|
565
|
Chris@87
|
566 Returns
|
Chris@87
|
567 -------
|
Chris@87
|
568 out : ndarray
|
Chris@87
|
569 Array interpretation of `a`. No copy is performed if the input
|
Chris@87
|
570 is already an ndarray. If `a` is a subclass of ndarray, a base
|
Chris@87
|
571 class ndarray is returned.
|
Chris@87
|
572
|
Chris@87
|
573 Raises
|
Chris@87
|
574 ------
|
Chris@87
|
575 ValueError
|
Chris@87
|
576 Raises ValueError if `a` contains NaN (Not a Number) or Inf (Infinity).
|
Chris@87
|
577
|
Chris@87
|
578 See Also
|
Chris@87
|
579 --------
|
Chris@87
|
580 asarray : Create and array.
|
Chris@87
|
581 asanyarray : Similar function which passes through subclasses.
|
Chris@87
|
582 ascontiguousarray : Convert input to a contiguous array.
|
Chris@87
|
583 asfarray : Convert input to a floating point ndarray.
|
Chris@87
|
584 asfortranarray : Convert input to an ndarray with column-major
|
Chris@87
|
585 memory order.
|
Chris@87
|
586 fromiter : Create an array from an iterator.
|
Chris@87
|
587 fromfunction : Construct an array by executing a function on grid
|
Chris@87
|
588 positions.
|
Chris@87
|
589
|
Chris@87
|
590 Examples
|
Chris@87
|
591 --------
|
Chris@87
|
592 Convert a list into an array. If all elements are finite
|
Chris@87
|
593 ``asarray_chkfinite`` is identical to ``asarray``.
|
Chris@87
|
594
|
Chris@87
|
595 >>> a = [1, 2]
|
Chris@87
|
596 >>> np.asarray_chkfinite(a, dtype=float)
|
Chris@87
|
597 array([1., 2.])
|
Chris@87
|
598
|
Chris@87
|
599 Raises ValueError if array_like contains Nans or Infs.
|
Chris@87
|
600
|
Chris@87
|
601 >>> a = [1, 2, np.inf]
|
Chris@87
|
602 >>> try:
|
Chris@87
|
603 ... np.asarray_chkfinite(a)
|
Chris@87
|
604 ... except ValueError:
|
Chris@87
|
605 ... print 'ValueError'
|
Chris@87
|
606 ...
|
Chris@87
|
607 ValueError
|
Chris@87
|
608
|
Chris@87
|
609 """
|
Chris@87
|
610 a = asarray(a, dtype=dtype, order=order)
|
Chris@87
|
611 if a.dtype.char in typecodes['AllFloat'] and not np.isfinite(a).all():
|
Chris@87
|
612 raise ValueError(
|
Chris@87
|
613 "array must not contain infs or NaNs")
|
Chris@87
|
614 return a
|
Chris@87
|
615
|
Chris@87
|
616
|
Chris@87
|
617 def piecewise(x, condlist, funclist, *args, **kw):
|
Chris@87
|
618 """
|
Chris@87
|
619 Evaluate a piecewise-defined function.
|
Chris@87
|
620
|
Chris@87
|
621 Given a set of conditions and corresponding functions, evaluate each
|
Chris@87
|
622 function on the input data wherever its condition is true.
|
Chris@87
|
623
|
Chris@87
|
624 Parameters
|
Chris@87
|
625 ----------
|
Chris@87
|
626 x : ndarray
|
Chris@87
|
627 The input domain.
|
Chris@87
|
628 condlist : list of bool arrays
|
Chris@87
|
629 Each boolean array corresponds to a function in `funclist`. Wherever
|
Chris@87
|
630 `condlist[i]` is True, `funclist[i](x)` is used as the output value.
|
Chris@87
|
631
|
Chris@87
|
632 Each boolean array in `condlist` selects a piece of `x`,
|
Chris@87
|
633 and should therefore be of the same shape as `x`.
|
Chris@87
|
634
|
Chris@87
|
635 The length of `condlist` must correspond to that of `funclist`.
|
Chris@87
|
636 If one extra function is given, i.e. if
|
Chris@87
|
637 ``len(funclist) - len(condlist) == 1``, then that extra function
|
Chris@87
|
638 is the default value, used wherever all conditions are false.
|
Chris@87
|
639 funclist : list of callables, f(x,*args,**kw), or scalars
|
Chris@87
|
640 Each function is evaluated over `x` wherever its corresponding
|
Chris@87
|
641 condition is True. It should take an array as input and give an array
|
Chris@87
|
642 or a scalar value as output. If, instead of a callable,
|
Chris@87
|
643 a scalar is provided then a constant function (``lambda x: scalar``) is
|
Chris@87
|
644 assumed.
|
Chris@87
|
645 args : tuple, optional
|
Chris@87
|
646 Any further arguments given to `piecewise` are passed to the functions
|
Chris@87
|
647 upon execution, i.e., if called ``piecewise(..., ..., 1, 'a')``, then
|
Chris@87
|
648 each function is called as ``f(x, 1, 'a')``.
|
Chris@87
|
649 kw : dict, optional
|
Chris@87
|
650 Keyword arguments used in calling `piecewise` are passed to the
|
Chris@87
|
651 functions upon execution, i.e., if called
|
Chris@87
|
652 ``piecewise(..., ..., lambda=1)``, then each function is called as
|
Chris@87
|
653 ``f(x, lambda=1)``.
|
Chris@87
|
654
|
Chris@87
|
655 Returns
|
Chris@87
|
656 -------
|
Chris@87
|
657 out : ndarray
|
Chris@87
|
658 The output is the same shape and type as x and is found by
|
Chris@87
|
659 calling the functions in `funclist` on the appropriate portions of `x`,
|
Chris@87
|
660 as defined by the boolean arrays in `condlist`. Portions not covered
|
Chris@87
|
661 by any condition have a default value of 0.
|
Chris@87
|
662
|
Chris@87
|
663
|
Chris@87
|
664 See Also
|
Chris@87
|
665 --------
|
Chris@87
|
666 choose, select, where
|
Chris@87
|
667
|
Chris@87
|
668 Notes
|
Chris@87
|
669 -----
|
Chris@87
|
670 This is similar to choose or select, except that functions are
|
Chris@87
|
671 evaluated on elements of `x` that satisfy the corresponding condition from
|
Chris@87
|
672 `condlist`.
|
Chris@87
|
673
|
Chris@87
|
674 The result is::
|
Chris@87
|
675
|
Chris@87
|
676 |--
|
Chris@87
|
677 |funclist[0](x[condlist[0]])
|
Chris@87
|
678 out = |funclist[1](x[condlist[1]])
|
Chris@87
|
679 |...
|
Chris@87
|
680 |funclist[n2](x[condlist[n2]])
|
Chris@87
|
681 |--
|
Chris@87
|
682
|
Chris@87
|
683 Examples
|
Chris@87
|
684 --------
|
Chris@87
|
685 Define the sigma function, which is -1 for ``x < 0`` and +1 for ``x >= 0``.
|
Chris@87
|
686
|
Chris@87
|
687 >>> x = np.linspace(-2.5, 2.5, 6)
|
Chris@87
|
688 >>> np.piecewise(x, [x < 0, x >= 0], [-1, 1])
|
Chris@87
|
689 array([-1., -1., -1., 1., 1., 1.])
|
Chris@87
|
690
|
Chris@87
|
691 Define the absolute value, which is ``-x`` for ``x <0`` and ``x`` for
|
Chris@87
|
692 ``x >= 0``.
|
Chris@87
|
693
|
Chris@87
|
694 >>> np.piecewise(x, [x < 0, x >= 0], [lambda x: -x, lambda x: x])
|
Chris@87
|
695 array([ 2.5, 1.5, 0.5, 0.5, 1.5, 2.5])
|
Chris@87
|
696
|
Chris@87
|
697 """
|
Chris@87
|
698 x = asanyarray(x)
|
Chris@87
|
699 n2 = len(funclist)
|
Chris@87
|
700 if (isscalar(condlist) or not (isinstance(condlist[0], list) or
|
Chris@87
|
701 isinstance(condlist[0], ndarray))):
|
Chris@87
|
702 condlist = [condlist]
|
Chris@87
|
703 condlist = array(condlist, dtype=bool)
|
Chris@87
|
704 n = len(condlist)
|
Chris@87
|
705 # This is a hack to work around problems with NumPy's
|
Chris@87
|
706 # handling of 0-d arrays and boolean indexing with
|
Chris@87
|
707 # numpy.bool_ scalars
|
Chris@87
|
708 zerod = False
|
Chris@87
|
709 if x.ndim == 0:
|
Chris@87
|
710 x = x[None]
|
Chris@87
|
711 zerod = True
|
Chris@87
|
712 if condlist.shape[-1] != 1:
|
Chris@87
|
713 condlist = condlist.T
|
Chris@87
|
714 if n == n2 - 1: # compute the "otherwise" condition.
|
Chris@87
|
715 totlist = np.logical_or.reduce(condlist, axis=0)
|
Chris@87
|
716 condlist = np.vstack([condlist, ~totlist])
|
Chris@87
|
717 n += 1
|
Chris@87
|
718 if (n != n2):
|
Chris@87
|
719 raise ValueError(
|
Chris@87
|
720 "function list and condition list must be the same")
|
Chris@87
|
721
|
Chris@87
|
722 y = zeros(x.shape, x.dtype)
|
Chris@87
|
723 for k in range(n):
|
Chris@87
|
724 item = funclist[k]
|
Chris@87
|
725 if not isinstance(item, collections.Callable):
|
Chris@87
|
726 y[condlist[k]] = item
|
Chris@87
|
727 else:
|
Chris@87
|
728 vals = x[condlist[k]]
|
Chris@87
|
729 if vals.size > 0:
|
Chris@87
|
730 y[condlist[k]] = item(vals, *args, **kw)
|
Chris@87
|
731 if zerod:
|
Chris@87
|
732 y = y.squeeze()
|
Chris@87
|
733 return y
|
Chris@87
|
734
|
Chris@87
|
735
|
Chris@87
|
736 def select(condlist, choicelist, default=0):
|
Chris@87
|
737 """
|
Chris@87
|
738 Return an array drawn from elements in choicelist, depending on conditions.
|
Chris@87
|
739
|
Chris@87
|
740 Parameters
|
Chris@87
|
741 ----------
|
Chris@87
|
742 condlist : list of bool ndarrays
|
Chris@87
|
743 The list of conditions which determine from which array in `choicelist`
|
Chris@87
|
744 the output elements are taken. When multiple conditions are satisfied,
|
Chris@87
|
745 the first one encountered in `condlist` is used.
|
Chris@87
|
746 choicelist : list of ndarrays
|
Chris@87
|
747 The list of arrays from which the output elements are taken. It has
|
Chris@87
|
748 to be of the same length as `condlist`.
|
Chris@87
|
749 default : scalar, optional
|
Chris@87
|
750 The element inserted in `output` when all conditions evaluate to False.
|
Chris@87
|
751
|
Chris@87
|
752 Returns
|
Chris@87
|
753 -------
|
Chris@87
|
754 output : ndarray
|
Chris@87
|
755 The output at position m is the m-th element of the array in
|
Chris@87
|
756 `choicelist` where the m-th element of the corresponding array in
|
Chris@87
|
757 `condlist` is True.
|
Chris@87
|
758
|
Chris@87
|
759 See Also
|
Chris@87
|
760 --------
|
Chris@87
|
761 where : Return elements from one of two arrays depending on condition.
|
Chris@87
|
762 take, choose, compress, diag, diagonal
|
Chris@87
|
763
|
Chris@87
|
764 Examples
|
Chris@87
|
765 --------
|
Chris@87
|
766 >>> x = np.arange(10)
|
Chris@87
|
767 >>> condlist = [x<3, x>5]
|
Chris@87
|
768 >>> choicelist = [x, x**2]
|
Chris@87
|
769 >>> np.select(condlist, choicelist)
|
Chris@87
|
770 array([ 0, 1, 2, 0, 0, 0, 36, 49, 64, 81])
|
Chris@87
|
771
|
Chris@87
|
772 """
|
Chris@87
|
773 # Check the size of condlist and choicelist are the same, or abort.
|
Chris@87
|
774 if len(condlist) != len(choicelist):
|
Chris@87
|
775 raise ValueError(
|
Chris@87
|
776 'list of cases must be same length as list of conditions')
|
Chris@87
|
777
|
Chris@87
|
778 # Now that the dtype is known, handle the deprecated select([], []) case
|
Chris@87
|
779 if len(condlist) == 0:
|
Chris@87
|
780 warnings.warn("select with an empty condition list is not possible"
|
Chris@87
|
781 "and will be deprecated",
|
Chris@87
|
782 DeprecationWarning)
|
Chris@87
|
783 return np.asarray(default)[()]
|
Chris@87
|
784
|
Chris@87
|
785 choicelist = [np.asarray(choice) for choice in choicelist]
|
Chris@87
|
786 choicelist.append(np.asarray(default))
|
Chris@87
|
787
|
Chris@87
|
788 # need to get the result type before broadcasting for correct scalar
|
Chris@87
|
789 # behaviour
|
Chris@87
|
790 dtype = np.result_type(*choicelist)
|
Chris@87
|
791
|
Chris@87
|
792 # Convert conditions to arrays and broadcast conditions and choices
|
Chris@87
|
793 # as the shape is needed for the result. Doing it seperatly optimizes
|
Chris@87
|
794 # for example when all choices are scalars.
|
Chris@87
|
795 condlist = np.broadcast_arrays(*condlist)
|
Chris@87
|
796 choicelist = np.broadcast_arrays(*choicelist)
|
Chris@87
|
797
|
Chris@87
|
798 # If cond array is not an ndarray in boolean format or scalar bool, abort.
|
Chris@87
|
799 deprecated_ints = False
|
Chris@87
|
800 for i in range(len(condlist)):
|
Chris@87
|
801 cond = condlist[i]
|
Chris@87
|
802 if cond.dtype.type is not np.bool_:
|
Chris@87
|
803 if np.issubdtype(cond.dtype, np.integer):
|
Chris@87
|
804 # A previous implementation accepted int ndarrays accidentally.
|
Chris@87
|
805 # Supported here deliberately, but deprecated.
|
Chris@87
|
806 condlist[i] = condlist[i].astype(bool)
|
Chris@87
|
807 deprecated_ints = True
|
Chris@87
|
808 else:
|
Chris@87
|
809 raise ValueError(
|
Chris@87
|
810 'invalid entry in choicelist: should be boolean ndarray')
|
Chris@87
|
811
|
Chris@87
|
812 if deprecated_ints:
|
Chris@87
|
813 msg = "select condlists containing integer ndarrays is deprecated " \
|
Chris@87
|
814 "and will be removed in the future. Use `.astype(bool)` to " \
|
Chris@87
|
815 "convert to bools."
|
Chris@87
|
816 warnings.warn(msg, DeprecationWarning)
|
Chris@87
|
817
|
Chris@87
|
818 if choicelist[0].ndim == 0:
|
Chris@87
|
819 # This may be common, so avoid the call.
|
Chris@87
|
820 result_shape = condlist[0].shape
|
Chris@87
|
821 else:
|
Chris@87
|
822 result_shape = np.broadcast_arrays(condlist[0], choicelist[0])[0].shape
|
Chris@87
|
823
|
Chris@87
|
824 result = np.full(result_shape, choicelist[-1], dtype)
|
Chris@87
|
825
|
Chris@87
|
826 # Use np.copyto to burn each choicelist array onto result, using the
|
Chris@87
|
827 # corresponding condlist as a boolean mask. This is done in reverse
|
Chris@87
|
828 # order since the first choice should take precedence.
|
Chris@87
|
829 choicelist = choicelist[-2::-1]
|
Chris@87
|
830 condlist = condlist[::-1]
|
Chris@87
|
831 for choice, cond in zip(choicelist, condlist):
|
Chris@87
|
832 np.copyto(result, choice, where=cond)
|
Chris@87
|
833
|
Chris@87
|
834 return result
|
Chris@87
|
835
|
Chris@87
|
836
|
Chris@87
|
837 def copy(a, order='K'):
|
Chris@87
|
838 """
|
Chris@87
|
839 Return an array copy of the given object.
|
Chris@87
|
840
|
Chris@87
|
841 Parameters
|
Chris@87
|
842 ----------
|
Chris@87
|
843 a : array_like
|
Chris@87
|
844 Input data.
|
Chris@87
|
845 order : {'C', 'F', 'A', 'K'}, optional
|
Chris@87
|
846 Controls the memory layout of the copy. 'C' means C-order,
|
Chris@87
|
847 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous,
|
Chris@87
|
848 'C' otherwise. 'K' means match the layout of `a` as closely
|
Chris@87
|
849 as possible. (Note that this function and :meth:ndarray.copy are very
|
Chris@87
|
850 similar, but have different default values for their order=
|
Chris@87
|
851 arguments.)
|
Chris@87
|
852
|
Chris@87
|
853 Returns
|
Chris@87
|
854 -------
|
Chris@87
|
855 arr : ndarray
|
Chris@87
|
856 Array interpretation of `a`.
|
Chris@87
|
857
|
Chris@87
|
858 Notes
|
Chris@87
|
859 -----
|
Chris@87
|
860 This is equivalent to
|
Chris@87
|
861
|
Chris@87
|
862 >>> np.array(a, copy=True) #doctest: +SKIP
|
Chris@87
|
863
|
Chris@87
|
864 Examples
|
Chris@87
|
865 --------
|
Chris@87
|
866 Create an array x, with a reference y and a copy z:
|
Chris@87
|
867
|
Chris@87
|
868 >>> x = np.array([1, 2, 3])
|
Chris@87
|
869 >>> y = x
|
Chris@87
|
870 >>> z = np.copy(x)
|
Chris@87
|
871
|
Chris@87
|
872 Note that, when we modify x, y changes, but not z:
|
Chris@87
|
873
|
Chris@87
|
874 >>> x[0] = 10
|
Chris@87
|
875 >>> x[0] == y[0]
|
Chris@87
|
876 True
|
Chris@87
|
877 >>> x[0] == z[0]
|
Chris@87
|
878 False
|
Chris@87
|
879
|
Chris@87
|
880 """
|
Chris@87
|
881 return array(a, order=order, copy=True)
|
Chris@87
|
882
|
Chris@87
|
883 # Basic operations
|
Chris@87
|
884
|
Chris@87
|
885
|
Chris@87
|
886 def gradient(f, *varargs, **kwargs):
|
Chris@87
|
887 """
|
Chris@87
|
888 Return the gradient of an N-dimensional array.
|
Chris@87
|
889
|
Chris@87
|
890 The gradient is computed using second order accurate central differences
|
Chris@87
|
891 in the interior and either first differences or second order accurate
|
Chris@87
|
892 one-sides (forward or backwards) differences at the boundaries. The
|
Chris@87
|
893 returned gradient hence has the same shape as the input array.
|
Chris@87
|
894
|
Chris@87
|
895 Parameters
|
Chris@87
|
896 ----------
|
Chris@87
|
897 f : array_like
|
Chris@87
|
898 An N-dimensional array containing samples of a scalar function.
|
Chris@87
|
899 varargs : list of scalar, optional
|
Chris@87
|
900 N scalars specifying the sample distances for each dimension,
|
Chris@87
|
901 i.e. `dx`, `dy`, `dz`, ... Default distance: 1.
|
Chris@87
|
902 edge_order : {1, 2}, optional
|
Chris@87
|
903 Gradient is calculated using N\ :sup:`th` order accurate differences
|
Chris@87
|
904 at the boundaries. Default: 1.
|
Chris@87
|
905
|
Chris@87
|
906 .. versionadded:: 1.9.1
|
Chris@87
|
907
|
Chris@87
|
908 Returns
|
Chris@87
|
909 -------
|
Chris@87
|
910 gradient : ndarray
|
Chris@87
|
911 N arrays of the same shape as `f` giving the derivative of `f` with
|
Chris@87
|
912 respect to each dimension.
|
Chris@87
|
913
|
Chris@87
|
914 Examples
|
Chris@87
|
915 --------
|
Chris@87
|
916 >>> x = np.array([1, 2, 4, 7, 11, 16], dtype=np.float)
|
Chris@87
|
917 >>> np.gradient(x)
|
Chris@87
|
918 array([ 1. , 1.5, 2.5, 3.5, 4.5, 5. ])
|
Chris@87
|
919 >>> np.gradient(x, 2)
|
Chris@87
|
920 array([ 0.5 , 0.75, 1.25, 1.75, 2.25, 2.5 ])
|
Chris@87
|
921
|
Chris@87
|
922 >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=np.float))
|
Chris@87
|
923 [array([[ 2., 2., -1.],
|
Chris@87
|
924 [ 2., 2., -1.]]), array([[ 1. , 2.5, 4. ],
|
Chris@87
|
925 [ 1. , 1. , 1. ]])]
|
Chris@87
|
926
|
Chris@87
|
927 >>> x = np.array([0, 1, 2, 3, 4])
|
Chris@87
|
928 >>> dx = np.gradient(x)
|
Chris@87
|
929 >>> y = x**2
|
Chris@87
|
930 >>> np.gradient(y, dx, edge_order=2)
|
Chris@87
|
931 array([-0., 2., 4., 6., 8.])
|
Chris@87
|
932 """
|
Chris@87
|
933 f = np.asanyarray(f)
|
Chris@87
|
934 N = len(f.shape) # number of dimensions
|
Chris@87
|
935 n = len(varargs)
|
Chris@87
|
936 if n == 0:
|
Chris@87
|
937 dx = [1.0]*N
|
Chris@87
|
938 elif n == 1:
|
Chris@87
|
939 dx = [varargs[0]]*N
|
Chris@87
|
940 elif n == N:
|
Chris@87
|
941 dx = list(varargs)
|
Chris@87
|
942 else:
|
Chris@87
|
943 raise SyntaxError(
|
Chris@87
|
944 "invalid number of arguments")
|
Chris@87
|
945
|
Chris@87
|
946 edge_order = kwargs.pop('edge_order', 1)
|
Chris@87
|
947 if kwargs:
|
Chris@87
|
948 raise TypeError('"{}" are not valid keyword arguments.'.format(
|
Chris@87
|
949 '", "'.join(kwargs.keys())))
|
Chris@87
|
950 if edge_order > 2:
|
Chris@87
|
951 raise ValueError("'edge_order' greater than 2 not supported")
|
Chris@87
|
952
|
Chris@87
|
953 # use central differences on interior and one-sided differences on the
|
Chris@87
|
954 # endpoints. This preserves second order-accuracy over the full domain.
|
Chris@87
|
955
|
Chris@87
|
956 outvals = []
|
Chris@87
|
957
|
Chris@87
|
958 # create slice objects --- initially all are [:, :, ..., :]
|
Chris@87
|
959 slice1 = [slice(None)]*N
|
Chris@87
|
960 slice2 = [slice(None)]*N
|
Chris@87
|
961 slice3 = [slice(None)]*N
|
Chris@87
|
962 slice4 = [slice(None)]*N
|
Chris@87
|
963
|
Chris@87
|
964 otype = f.dtype.char
|
Chris@87
|
965 if otype not in ['f', 'd', 'F', 'D', 'm', 'M']:
|
Chris@87
|
966 otype = 'd'
|
Chris@87
|
967
|
Chris@87
|
968 # Difference of datetime64 elements results in timedelta64
|
Chris@87
|
969 if otype == 'M':
|
Chris@87
|
970 # Need to use the full dtype name because it contains unit information
|
Chris@87
|
971 otype = f.dtype.name.replace('datetime', 'timedelta')
|
Chris@87
|
972 elif otype == 'm':
|
Chris@87
|
973 # Needs to keep the specific units, can't be a general unit
|
Chris@87
|
974 otype = f.dtype
|
Chris@87
|
975
|
Chris@87
|
976 # Convert datetime64 data into ints. Make dummy variable `y`
|
Chris@87
|
977 # that is a view of ints if the data is datetime64, otherwise
|
Chris@87
|
978 # just set y equal to the the array `f`.
|
Chris@87
|
979 if f.dtype.char in ["M", "m"]:
|
Chris@87
|
980 y = f.view('int64')
|
Chris@87
|
981 else:
|
Chris@87
|
982 y = f
|
Chris@87
|
983
|
Chris@87
|
984 for axis in range(N):
|
Chris@87
|
985
|
Chris@87
|
986 if y.shape[axis] < 2:
|
Chris@87
|
987 raise ValueError(
|
Chris@87
|
988 "Shape of array too small to calculate a numerical gradient, "
|
Chris@87
|
989 "at least two elements are required.")
|
Chris@87
|
990
|
Chris@87
|
991 # Numerical differentiation: 1st order edges, 2nd order interior
|
Chris@87
|
992 if y.shape[axis] == 2 or edge_order == 1:
|
Chris@87
|
993 # Use first order differences for time data
|
Chris@87
|
994 out = np.empty_like(y, dtype=otype)
|
Chris@87
|
995
|
Chris@87
|
996 slice1[axis] = slice(1, -1)
|
Chris@87
|
997 slice2[axis] = slice(2, None)
|
Chris@87
|
998 slice3[axis] = slice(None, -2)
|
Chris@87
|
999 # 1D equivalent -- out[1:-1] = (y[2:] - y[:-2])/2.0
|
Chris@87
|
1000 out[slice1] = (y[slice2] - y[slice3])/2.0
|
Chris@87
|
1001
|
Chris@87
|
1002 slice1[axis] = 0
|
Chris@87
|
1003 slice2[axis] = 1
|
Chris@87
|
1004 slice3[axis] = 0
|
Chris@87
|
1005 # 1D equivalent -- out[0] = (y[1] - y[0])
|
Chris@87
|
1006 out[slice1] = (y[slice2] - y[slice3])
|
Chris@87
|
1007
|
Chris@87
|
1008 slice1[axis] = -1
|
Chris@87
|
1009 slice2[axis] = -1
|
Chris@87
|
1010 slice3[axis] = -2
|
Chris@87
|
1011 # 1D equivalent -- out[-1] = (y[-1] - y[-2])
|
Chris@87
|
1012 out[slice1] = (y[slice2] - y[slice3])
|
Chris@87
|
1013
|
Chris@87
|
1014 # Numerical differentiation: 2st order edges, 2nd order interior
|
Chris@87
|
1015 else:
|
Chris@87
|
1016 # Use second order differences where possible
|
Chris@87
|
1017 out = np.empty_like(y, dtype=otype)
|
Chris@87
|
1018
|
Chris@87
|
1019 slice1[axis] = slice(1, -1)
|
Chris@87
|
1020 slice2[axis] = slice(2, None)
|
Chris@87
|
1021 slice3[axis] = slice(None, -2)
|
Chris@87
|
1022 # 1D equivalent -- out[1:-1] = (y[2:] - y[:-2])/2.0
|
Chris@87
|
1023 out[slice1] = (y[slice2] - y[slice3])/2.0
|
Chris@87
|
1024
|
Chris@87
|
1025 slice1[axis] = 0
|
Chris@87
|
1026 slice2[axis] = 0
|
Chris@87
|
1027 slice3[axis] = 1
|
Chris@87
|
1028 slice4[axis] = 2
|
Chris@87
|
1029 # 1D equivalent -- out[0] = -(3*y[0] - 4*y[1] + y[2]) / 2.0
|
Chris@87
|
1030 out[slice1] = -(3.0*y[slice2] - 4.0*y[slice3] + y[slice4])/2.0
|
Chris@87
|
1031
|
Chris@87
|
1032 slice1[axis] = -1
|
Chris@87
|
1033 slice2[axis] = -1
|
Chris@87
|
1034 slice3[axis] = -2
|
Chris@87
|
1035 slice4[axis] = -3
|
Chris@87
|
1036 # 1D equivalent -- out[-1] = (3*y[-1] - 4*y[-2] + y[-3])
|
Chris@87
|
1037 out[slice1] = (3.0*y[slice2] - 4.0*y[slice3] + y[slice4])/2.0
|
Chris@87
|
1038
|
Chris@87
|
1039 # divide by step size
|
Chris@87
|
1040 out /= dx[axis]
|
Chris@87
|
1041 outvals.append(out)
|
Chris@87
|
1042
|
Chris@87
|
1043 # reset the slice object in this dimension to ":"
|
Chris@87
|
1044 slice1[axis] = slice(None)
|
Chris@87
|
1045 slice2[axis] = slice(None)
|
Chris@87
|
1046 slice3[axis] = slice(None)
|
Chris@87
|
1047 slice4[axis] = slice(None)
|
Chris@87
|
1048
|
Chris@87
|
1049 if N == 1:
|
Chris@87
|
1050 return outvals[0]
|
Chris@87
|
1051 else:
|
Chris@87
|
1052 return outvals
|
Chris@87
|
1053
|
Chris@87
|
1054
|
Chris@87
|
1055 def diff(a, n=1, axis=-1):
|
Chris@87
|
1056 """
|
Chris@87
|
1057 Calculate the n-th order discrete difference along given axis.
|
Chris@87
|
1058
|
Chris@87
|
1059 The first order difference is given by ``out[n] = a[n+1] - a[n]`` along
|
Chris@87
|
1060 the given axis, higher order differences are calculated by using `diff`
|
Chris@87
|
1061 recursively.
|
Chris@87
|
1062
|
Chris@87
|
1063 Parameters
|
Chris@87
|
1064 ----------
|
Chris@87
|
1065 a : array_like
|
Chris@87
|
1066 Input array
|
Chris@87
|
1067 n : int, optional
|
Chris@87
|
1068 The number of times values are differenced.
|
Chris@87
|
1069 axis : int, optional
|
Chris@87
|
1070 The axis along which the difference is taken, default is the last axis.
|
Chris@87
|
1071
|
Chris@87
|
1072 Returns
|
Chris@87
|
1073 -------
|
Chris@87
|
1074 diff : ndarray
|
Chris@87
|
1075 The `n` order differences. The shape of the output is the same as `a`
|
Chris@87
|
1076 except along `axis` where the dimension is smaller by `n`.
|
Chris@87
|
1077
|
Chris@87
|
1078 See Also
|
Chris@87
|
1079 --------
|
Chris@87
|
1080 gradient, ediff1d, cumsum
|
Chris@87
|
1081
|
Chris@87
|
1082 Examples
|
Chris@87
|
1083 --------
|
Chris@87
|
1084 >>> x = np.array([1, 2, 4, 7, 0])
|
Chris@87
|
1085 >>> np.diff(x)
|
Chris@87
|
1086 array([ 1, 2, 3, -7])
|
Chris@87
|
1087 >>> np.diff(x, n=2)
|
Chris@87
|
1088 array([ 1, 1, -10])
|
Chris@87
|
1089
|
Chris@87
|
1090 >>> x = np.array([[1, 3, 6, 10], [0, 5, 6, 8]])
|
Chris@87
|
1091 >>> np.diff(x)
|
Chris@87
|
1092 array([[2, 3, 4],
|
Chris@87
|
1093 [5, 1, 2]])
|
Chris@87
|
1094 >>> np.diff(x, axis=0)
|
Chris@87
|
1095 array([[-1, 2, 0, -2]])
|
Chris@87
|
1096
|
Chris@87
|
1097 """
|
Chris@87
|
1098 if n == 0:
|
Chris@87
|
1099 return a
|
Chris@87
|
1100 if n < 0:
|
Chris@87
|
1101 raise ValueError(
|
Chris@87
|
1102 "order must be non-negative but got " + repr(n))
|
Chris@87
|
1103 a = asanyarray(a)
|
Chris@87
|
1104 nd = len(a.shape)
|
Chris@87
|
1105 slice1 = [slice(None)]*nd
|
Chris@87
|
1106 slice2 = [slice(None)]*nd
|
Chris@87
|
1107 slice1[axis] = slice(1, None)
|
Chris@87
|
1108 slice2[axis] = slice(None, -1)
|
Chris@87
|
1109 slice1 = tuple(slice1)
|
Chris@87
|
1110 slice2 = tuple(slice2)
|
Chris@87
|
1111 if n > 1:
|
Chris@87
|
1112 return diff(a[slice1]-a[slice2], n-1, axis=axis)
|
Chris@87
|
1113 else:
|
Chris@87
|
1114 return a[slice1]-a[slice2]
|
Chris@87
|
1115
|
Chris@87
|
1116
|
Chris@87
|
1117 def interp(x, xp, fp, left=None, right=None):
|
Chris@87
|
1118 """
|
Chris@87
|
1119 One-dimensional linear interpolation.
|
Chris@87
|
1120
|
Chris@87
|
1121 Returns the one-dimensional piecewise linear interpolant to a function
|
Chris@87
|
1122 with given values at discrete data-points.
|
Chris@87
|
1123
|
Chris@87
|
1124 Parameters
|
Chris@87
|
1125 ----------
|
Chris@87
|
1126 x : array_like
|
Chris@87
|
1127 The x-coordinates of the interpolated values.
|
Chris@87
|
1128
|
Chris@87
|
1129 xp : 1-D sequence of floats
|
Chris@87
|
1130 The x-coordinates of the data points, must be increasing.
|
Chris@87
|
1131
|
Chris@87
|
1132 fp : 1-D sequence of floats
|
Chris@87
|
1133 The y-coordinates of the data points, same length as `xp`.
|
Chris@87
|
1134
|
Chris@87
|
1135 left : float, optional
|
Chris@87
|
1136 Value to return for `x < xp[0]`, default is `fp[0]`.
|
Chris@87
|
1137
|
Chris@87
|
1138 right : float, optional
|
Chris@87
|
1139 Value to return for `x > xp[-1]`, default is `fp[-1]`.
|
Chris@87
|
1140
|
Chris@87
|
1141 Returns
|
Chris@87
|
1142 -------
|
Chris@87
|
1143 y : {float, ndarray}
|
Chris@87
|
1144 The interpolated values, same shape as `x`.
|
Chris@87
|
1145
|
Chris@87
|
1146 Raises
|
Chris@87
|
1147 ------
|
Chris@87
|
1148 ValueError
|
Chris@87
|
1149 If `xp` and `fp` have different length
|
Chris@87
|
1150
|
Chris@87
|
1151 Notes
|
Chris@87
|
1152 -----
|
Chris@87
|
1153 Does not check that the x-coordinate sequence `xp` is increasing.
|
Chris@87
|
1154 If `xp` is not increasing, the results are nonsense.
|
Chris@87
|
1155 A simple check for increasing is::
|
Chris@87
|
1156
|
Chris@87
|
1157 np.all(np.diff(xp) > 0)
|
Chris@87
|
1158
|
Chris@87
|
1159
|
Chris@87
|
1160 Examples
|
Chris@87
|
1161 --------
|
Chris@87
|
1162 >>> xp = [1, 2, 3]
|
Chris@87
|
1163 >>> fp = [3, 2, 0]
|
Chris@87
|
1164 >>> np.interp(2.5, xp, fp)
|
Chris@87
|
1165 1.0
|
Chris@87
|
1166 >>> np.interp([0, 1, 1.5, 2.72, 3.14], xp, fp)
|
Chris@87
|
1167 array([ 3. , 3. , 2.5 , 0.56, 0. ])
|
Chris@87
|
1168 >>> UNDEF = -99.0
|
Chris@87
|
1169 >>> np.interp(3.14, xp, fp, right=UNDEF)
|
Chris@87
|
1170 -99.0
|
Chris@87
|
1171
|
Chris@87
|
1172 Plot an interpolant to the sine function:
|
Chris@87
|
1173
|
Chris@87
|
1174 >>> x = np.linspace(0, 2*np.pi, 10)
|
Chris@87
|
1175 >>> y = np.sin(x)
|
Chris@87
|
1176 >>> xvals = np.linspace(0, 2*np.pi, 50)
|
Chris@87
|
1177 >>> yinterp = np.interp(xvals, x, y)
|
Chris@87
|
1178 >>> import matplotlib.pyplot as plt
|
Chris@87
|
1179 >>> plt.plot(x, y, 'o')
|
Chris@87
|
1180 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
1181 >>> plt.plot(xvals, yinterp, '-x')
|
Chris@87
|
1182 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
1183 >>> plt.show()
|
Chris@87
|
1184
|
Chris@87
|
1185 """
|
Chris@87
|
1186 if isinstance(x, (float, int, number)):
|
Chris@87
|
1187 return compiled_interp([x], xp, fp, left, right).item()
|
Chris@87
|
1188 elif isinstance(x, np.ndarray) and x.ndim == 0:
|
Chris@87
|
1189 return compiled_interp([x], xp, fp, left, right).item()
|
Chris@87
|
1190 else:
|
Chris@87
|
1191 return compiled_interp(x, xp, fp, left, right)
|
Chris@87
|
1192
|
Chris@87
|
1193
|
Chris@87
|
1194 def angle(z, deg=0):
|
Chris@87
|
1195 """
|
Chris@87
|
1196 Return the angle of the complex argument.
|
Chris@87
|
1197
|
Chris@87
|
1198 Parameters
|
Chris@87
|
1199 ----------
|
Chris@87
|
1200 z : array_like
|
Chris@87
|
1201 A complex number or sequence of complex numbers.
|
Chris@87
|
1202 deg : bool, optional
|
Chris@87
|
1203 Return angle in degrees if True, radians if False (default).
|
Chris@87
|
1204
|
Chris@87
|
1205 Returns
|
Chris@87
|
1206 -------
|
Chris@87
|
1207 angle : {ndarray, scalar}
|
Chris@87
|
1208 The counterclockwise angle from the positive real axis on
|
Chris@87
|
1209 the complex plane, with dtype as numpy.float64.
|
Chris@87
|
1210
|
Chris@87
|
1211 See Also
|
Chris@87
|
1212 --------
|
Chris@87
|
1213 arctan2
|
Chris@87
|
1214 absolute
|
Chris@87
|
1215
|
Chris@87
|
1216
|
Chris@87
|
1217
|
Chris@87
|
1218 Examples
|
Chris@87
|
1219 --------
|
Chris@87
|
1220 >>> np.angle([1.0, 1.0j, 1+1j]) # in radians
|
Chris@87
|
1221 array([ 0. , 1.57079633, 0.78539816])
|
Chris@87
|
1222 >>> np.angle(1+1j, deg=True) # in degrees
|
Chris@87
|
1223 45.0
|
Chris@87
|
1224
|
Chris@87
|
1225 """
|
Chris@87
|
1226 if deg:
|
Chris@87
|
1227 fact = 180/pi
|
Chris@87
|
1228 else:
|
Chris@87
|
1229 fact = 1.0
|
Chris@87
|
1230 z = asarray(z)
|
Chris@87
|
1231 if (issubclass(z.dtype.type, _nx.complexfloating)):
|
Chris@87
|
1232 zimag = z.imag
|
Chris@87
|
1233 zreal = z.real
|
Chris@87
|
1234 else:
|
Chris@87
|
1235 zimag = 0
|
Chris@87
|
1236 zreal = z
|
Chris@87
|
1237 return arctan2(zimag, zreal) * fact
|
Chris@87
|
1238
|
Chris@87
|
1239
|
Chris@87
|
1240 def unwrap(p, discont=pi, axis=-1):
|
Chris@87
|
1241 """
|
Chris@87
|
1242 Unwrap by changing deltas between values to 2*pi complement.
|
Chris@87
|
1243
|
Chris@87
|
1244 Unwrap radian phase `p` by changing absolute jumps greater than
|
Chris@87
|
1245 `discont` to their 2*pi complement along the given axis.
|
Chris@87
|
1246
|
Chris@87
|
1247 Parameters
|
Chris@87
|
1248 ----------
|
Chris@87
|
1249 p : array_like
|
Chris@87
|
1250 Input array.
|
Chris@87
|
1251 discont : float, optional
|
Chris@87
|
1252 Maximum discontinuity between values, default is ``pi``.
|
Chris@87
|
1253 axis : int, optional
|
Chris@87
|
1254 Axis along which unwrap will operate, default is the last axis.
|
Chris@87
|
1255
|
Chris@87
|
1256 Returns
|
Chris@87
|
1257 -------
|
Chris@87
|
1258 out : ndarray
|
Chris@87
|
1259 Output array.
|
Chris@87
|
1260
|
Chris@87
|
1261 See Also
|
Chris@87
|
1262 --------
|
Chris@87
|
1263 rad2deg, deg2rad
|
Chris@87
|
1264
|
Chris@87
|
1265 Notes
|
Chris@87
|
1266 -----
|
Chris@87
|
1267 If the discontinuity in `p` is smaller than ``pi``, but larger than
|
Chris@87
|
1268 `discont`, no unwrapping is done because taking the 2*pi complement
|
Chris@87
|
1269 would only make the discontinuity larger.
|
Chris@87
|
1270
|
Chris@87
|
1271 Examples
|
Chris@87
|
1272 --------
|
Chris@87
|
1273 >>> phase = np.linspace(0, np.pi, num=5)
|
Chris@87
|
1274 >>> phase[3:] += np.pi
|
Chris@87
|
1275 >>> phase
|
Chris@87
|
1276 array([ 0. , 0.78539816, 1.57079633, 5.49778714, 6.28318531])
|
Chris@87
|
1277 >>> np.unwrap(phase)
|
Chris@87
|
1278 array([ 0. , 0.78539816, 1.57079633, -0.78539816, 0. ])
|
Chris@87
|
1279
|
Chris@87
|
1280 """
|
Chris@87
|
1281 p = asarray(p)
|
Chris@87
|
1282 nd = len(p.shape)
|
Chris@87
|
1283 dd = diff(p, axis=axis)
|
Chris@87
|
1284 slice1 = [slice(None, None)]*nd # full slices
|
Chris@87
|
1285 slice1[axis] = slice(1, None)
|
Chris@87
|
1286 ddmod = mod(dd + pi, 2*pi) - pi
|
Chris@87
|
1287 _nx.copyto(ddmod, pi, where=(ddmod == -pi) & (dd > 0))
|
Chris@87
|
1288 ph_correct = ddmod - dd
|
Chris@87
|
1289 _nx.copyto(ph_correct, 0, where=abs(dd) < discont)
|
Chris@87
|
1290 up = array(p, copy=True, dtype='d')
|
Chris@87
|
1291 up[slice1] = p[slice1] + ph_correct.cumsum(axis)
|
Chris@87
|
1292 return up
|
Chris@87
|
1293
|
Chris@87
|
1294
|
Chris@87
|
1295 def sort_complex(a):
|
Chris@87
|
1296 """
|
Chris@87
|
1297 Sort a complex array using the real part first, then the imaginary part.
|
Chris@87
|
1298
|
Chris@87
|
1299 Parameters
|
Chris@87
|
1300 ----------
|
Chris@87
|
1301 a : array_like
|
Chris@87
|
1302 Input array
|
Chris@87
|
1303
|
Chris@87
|
1304 Returns
|
Chris@87
|
1305 -------
|
Chris@87
|
1306 out : complex ndarray
|
Chris@87
|
1307 Always returns a sorted complex array.
|
Chris@87
|
1308
|
Chris@87
|
1309 Examples
|
Chris@87
|
1310 --------
|
Chris@87
|
1311 >>> np.sort_complex([5, 3, 6, 2, 1])
|
Chris@87
|
1312 array([ 1.+0.j, 2.+0.j, 3.+0.j, 5.+0.j, 6.+0.j])
|
Chris@87
|
1313
|
Chris@87
|
1314 >>> np.sort_complex([1 + 2j, 2 - 1j, 3 - 2j, 3 - 3j, 3 + 5j])
|
Chris@87
|
1315 array([ 1.+2.j, 2.-1.j, 3.-3.j, 3.-2.j, 3.+5.j])
|
Chris@87
|
1316
|
Chris@87
|
1317 """
|
Chris@87
|
1318 b = array(a, copy=True)
|
Chris@87
|
1319 b.sort()
|
Chris@87
|
1320 if not issubclass(b.dtype.type, _nx.complexfloating):
|
Chris@87
|
1321 if b.dtype.char in 'bhBH':
|
Chris@87
|
1322 return b.astype('F')
|
Chris@87
|
1323 elif b.dtype.char == 'g':
|
Chris@87
|
1324 return b.astype('G')
|
Chris@87
|
1325 else:
|
Chris@87
|
1326 return b.astype('D')
|
Chris@87
|
1327 else:
|
Chris@87
|
1328 return b
|
Chris@87
|
1329
|
Chris@87
|
1330
|
Chris@87
|
1331 def trim_zeros(filt, trim='fb'):
|
Chris@87
|
1332 """
|
Chris@87
|
1333 Trim the leading and/or trailing zeros from a 1-D array or sequence.
|
Chris@87
|
1334
|
Chris@87
|
1335 Parameters
|
Chris@87
|
1336 ----------
|
Chris@87
|
1337 filt : 1-D array or sequence
|
Chris@87
|
1338 Input array.
|
Chris@87
|
1339 trim : str, optional
|
Chris@87
|
1340 A string with 'f' representing trim from front and 'b' to trim from
|
Chris@87
|
1341 back. Default is 'fb', trim zeros from both front and back of the
|
Chris@87
|
1342 array.
|
Chris@87
|
1343
|
Chris@87
|
1344 Returns
|
Chris@87
|
1345 -------
|
Chris@87
|
1346 trimmed : 1-D array or sequence
|
Chris@87
|
1347 The result of trimming the input. The input data type is preserved.
|
Chris@87
|
1348
|
Chris@87
|
1349 Examples
|
Chris@87
|
1350 --------
|
Chris@87
|
1351 >>> a = np.array((0, 0, 0, 1, 2, 3, 0, 2, 1, 0))
|
Chris@87
|
1352 >>> np.trim_zeros(a)
|
Chris@87
|
1353 array([1, 2, 3, 0, 2, 1])
|
Chris@87
|
1354
|
Chris@87
|
1355 >>> np.trim_zeros(a, 'b')
|
Chris@87
|
1356 array([0, 0, 0, 1, 2, 3, 0, 2, 1])
|
Chris@87
|
1357
|
Chris@87
|
1358 The input data type is preserved, list/tuple in means list/tuple out.
|
Chris@87
|
1359
|
Chris@87
|
1360 >>> np.trim_zeros([0, 1, 2, 0])
|
Chris@87
|
1361 [1, 2]
|
Chris@87
|
1362
|
Chris@87
|
1363 """
|
Chris@87
|
1364 first = 0
|
Chris@87
|
1365 trim = trim.upper()
|
Chris@87
|
1366 if 'F' in trim:
|
Chris@87
|
1367 for i in filt:
|
Chris@87
|
1368 if i != 0.:
|
Chris@87
|
1369 break
|
Chris@87
|
1370 else:
|
Chris@87
|
1371 first = first + 1
|
Chris@87
|
1372 last = len(filt)
|
Chris@87
|
1373 if 'B' in trim:
|
Chris@87
|
1374 for i in filt[::-1]:
|
Chris@87
|
1375 if i != 0.:
|
Chris@87
|
1376 break
|
Chris@87
|
1377 else:
|
Chris@87
|
1378 last = last - 1
|
Chris@87
|
1379 return filt[first:last]
|
Chris@87
|
1380
|
Chris@87
|
1381
|
Chris@87
|
1382 @deprecate
|
Chris@87
|
1383 def unique(x):
|
Chris@87
|
1384 """
|
Chris@87
|
1385 This function is deprecated. Use numpy.lib.arraysetops.unique()
|
Chris@87
|
1386 instead.
|
Chris@87
|
1387 """
|
Chris@87
|
1388 try:
|
Chris@87
|
1389 tmp = x.flatten()
|
Chris@87
|
1390 if tmp.size == 0:
|
Chris@87
|
1391 return tmp
|
Chris@87
|
1392 tmp.sort()
|
Chris@87
|
1393 idx = concatenate(([True], tmp[1:] != tmp[:-1]))
|
Chris@87
|
1394 return tmp[idx]
|
Chris@87
|
1395 except AttributeError:
|
Chris@87
|
1396 items = sorted(set(x))
|
Chris@87
|
1397 return asarray(items)
|
Chris@87
|
1398
|
Chris@87
|
1399
|
Chris@87
|
1400 def extract(condition, arr):
|
Chris@87
|
1401 """
|
Chris@87
|
1402 Return the elements of an array that satisfy some condition.
|
Chris@87
|
1403
|
Chris@87
|
1404 This is equivalent to ``np.compress(ravel(condition), ravel(arr))``. If
|
Chris@87
|
1405 `condition` is boolean ``np.extract`` is equivalent to ``arr[condition]``.
|
Chris@87
|
1406
|
Chris@87
|
1407 Parameters
|
Chris@87
|
1408 ----------
|
Chris@87
|
1409 condition : array_like
|
Chris@87
|
1410 An array whose nonzero or True entries indicate the elements of `arr`
|
Chris@87
|
1411 to extract.
|
Chris@87
|
1412 arr : array_like
|
Chris@87
|
1413 Input array of the same size as `condition`.
|
Chris@87
|
1414
|
Chris@87
|
1415 Returns
|
Chris@87
|
1416 -------
|
Chris@87
|
1417 extract : ndarray
|
Chris@87
|
1418 Rank 1 array of values from `arr` where `condition` is True.
|
Chris@87
|
1419
|
Chris@87
|
1420 See Also
|
Chris@87
|
1421 --------
|
Chris@87
|
1422 take, put, copyto, compress
|
Chris@87
|
1423
|
Chris@87
|
1424 Examples
|
Chris@87
|
1425 --------
|
Chris@87
|
1426 >>> arr = np.arange(12).reshape((3, 4))
|
Chris@87
|
1427 >>> arr
|
Chris@87
|
1428 array([[ 0, 1, 2, 3],
|
Chris@87
|
1429 [ 4, 5, 6, 7],
|
Chris@87
|
1430 [ 8, 9, 10, 11]])
|
Chris@87
|
1431 >>> condition = np.mod(arr, 3)==0
|
Chris@87
|
1432 >>> condition
|
Chris@87
|
1433 array([[ True, False, False, True],
|
Chris@87
|
1434 [False, False, True, False],
|
Chris@87
|
1435 [False, True, False, False]], dtype=bool)
|
Chris@87
|
1436 >>> np.extract(condition, arr)
|
Chris@87
|
1437 array([0, 3, 6, 9])
|
Chris@87
|
1438
|
Chris@87
|
1439
|
Chris@87
|
1440 If `condition` is boolean:
|
Chris@87
|
1441
|
Chris@87
|
1442 >>> arr[condition]
|
Chris@87
|
1443 array([0, 3, 6, 9])
|
Chris@87
|
1444
|
Chris@87
|
1445 """
|
Chris@87
|
1446 return _nx.take(ravel(arr), nonzero(ravel(condition))[0])
|
Chris@87
|
1447
|
Chris@87
|
1448
|
Chris@87
|
1449 def place(arr, mask, vals):
|
Chris@87
|
1450 """
|
Chris@87
|
1451 Change elements of an array based on conditional and input values.
|
Chris@87
|
1452
|
Chris@87
|
1453 Similar to ``np.copyto(arr, vals, where=mask)``, the difference is that
|
Chris@87
|
1454 `place` uses the first N elements of `vals`, where N is the number of
|
Chris@87
|
1455 True values in `mask`, while `copyto` uses the elements where `mask`
|
Chris@87
|
1456 is True.
|
Chris@87
|
1457
|
Chris@87
|
1458 Note that `extract` does the exact opposite of `place`.
|
Chris@87
|
1459
|
Chris@87
|
1460 Parameters
|
Chris@87
|
1461 ----------
|
Chris@87
|
1462 arr : array_like
|
Chris@87
|
1463 Array to put data into.
|
Chris@87
|
1464 mask : array_like
|
Chris@87
|
1465 Boolean mask array. Must have the same size as `a`.
|
Chris@87
|
1466 vals : 1-D sequence
|
Chris@87
|
1467 Values to put into `a`. Only the first N elements are used, where
|
Chris@87
|
1468 N is the number of True values in `mask`. If `vals` is smaller
|
Chris@87
|
1469 than N it will be repeated.
|
Chris@87
|
1470
|
Chris@87
|
1471 See Also
|
Chris@87
|
1472 --------
|
Chris@87
|
1473 copyto, put, take, extract
|
Chris@87
|
1474
|
Chris@87
|
1475 Examples
|
Chris@87
|
1476 --------
|
Chris@87
|
1477 >>> arr = np.arange(6).reshape(2, 3)
|
Chris@87
|
1478 >>> np.place(arr, arr>2, [44, 55])
|
Chris@87
|
1479 >>> arr
|
Chris@87
|
1480 array([[ 0, 1, 2],
|
Chris@87
|
1481 [44, 55, 44]])
|
Chris@87
|
1482
|
Chris@87
|
1483 """
|
Chris@87
|
1484 return _insert(arr, mask, vals)
|
Chris@87
|
1485
|
Chris@87
|
1486
|
Chris@87
|
1487 def disp(mesg, device=None, linefeed=True):
|
Chris@87
|
1488 """
|
Chris@87
|
1489 Display a message on a device.
|
Chris@87
|
1490
|
Chris@87
|
1491 Parameters
|
Chris@87
|
1492 ----------
|
Chris@87
|
1493 mesg : str
|
Chris@87
|
1494 Message to display.
|
Chris@87
|
1495 device : object
|
Chris@87
|
1496 Device to write message. If None, defaults to ``sys.stdout`` which is
|
Chris@87
|
1497 very similar to ``print``. `device` needs to have ``write()`` and
|
Chris@87
|
1498 ``flush()`` methods.
|
Chris@87
|
1499 linefeed : bool, optional
|
Chris@87
|
1500 Option whether to print a line feed or not. Defaults to True.
|
Chris@87
|
1501
|
Chris@87
|
1502 Raises
|
Chris@87
|
1503 ------
|
Chris@87
|
1504 AttributeError
|
Chris@87
|
1505 If `device` does not have a ``write()`` or ``flush()`` method.
|
Chris@87
|
1506
|
Chris@87
|
1507 Examples
|
Chris@87
|
1508 --------
|
Chris@87
|
1509 Besides ``sys.stdout``, a file-like object can also be used as it has
|
Chris@87
|
1510 both required methods:
|
Chris@87
|
1511
|
Chris@87
|
1512 >>> from StringIO import StringIO
|
Chris@87
|
1513 >>> buf = StringIO()
|
Chris@87
|
1514 >>> np.disp('"Display" in a file', device=buf)
|
Chris@87
|
1515 >>> buf.getvalue()
|
Chris@87
|
1516 '"Display" in a file\\n'
|
Chris@87
|
1517
|
Chris@87
|
1518 """
|
Chris@87
|
1519 if device is None:
|
Chris@87
|
1520 device = sys.stdout
|
Chris@87
|
1521 if linefeed:
|
Chris@87
|
1522 device.write('%s\n' % mesg)
|
Chris@87
|
1523 else:
|
Chris@87
|
1524 device.write('%s' % mesg)
|
Chris@87
|
1525 device.flush()
|
Chris@87
|
1526 return
|
Chris@87
|
1527
|
Chris@87
|
1528
|
Chris@87
|
1529 class vectorize(object):
|
Chris@87
|
1530 """
|
Chris@87
|
1531 vectorize(pyfunc, otypes='', doc=None, excluded=None, cache=False)
|
Chris@87
|
1532
|
Chris@87
|
1533 Generalized function class.
|
Chris@87
|
1534
|
Chris@87
|
1535 Define a vectorized function which takes a nested sequence
|
Chris@87
|
1536 of objects or numpy arrays as inputs and returns a
|
Chris@87
|
1537 numpy array as output. The vectorized function evaluates `pyfunc` over
|
Chris@87
|
1538 successive tuples of the input arrays like the python map function,
|
Chris@87
|
1539 except it uses the broadcasting rules of numpy.
|
Chris@87
|
1540
|
Chris@87
|
1541 The data type of the output of `vectorized` is determined by calling
|
Chris@87
|
1542 the function with the first element of the input. This can be avoided
|
Chris@87
|
1543 by specifying the `otypes` argument.
|
Chris@87
|
1544
|
Chris@87
|
1545 Parameters
|
Chris@87
|
1546 ----------
|
Chris@87
|
1547 pyfunc : callable
|
Chris@87
|
1548 A python function or method.
|
Chris@87
|
1549 otypes : str or list of dtypes, optional
|
Chris@87
|
1550 The output data type. It must be specified as either a string of
|
Chris@87
|
1551 typecode characters or a list of data type specifiers. There should
|
Chris@87
|
1552 be one data type specifier for each output.
|
Chris@87
|
1553 doc : str, optional
|
Chris@87
|
1554 The docstring for the function. If `None`, the docstring will be the
|
Chris@87
|
1555 ``pyfunc.__doc__``.
|
Chris@87
|
1556 excluded : set, optional
|
Chris@87
|
1557 Set of strings or integers representing the positional or keyword
|
Chris@87
|
1558 arguments for which the function will not be vectorized. These will be
|
Chris@87
|
1559 passed directly to `pyfunc` unmodified.
|
Chris@87
|
1560
|
Chris@87
|
1561 .. versionadded:: 1.7.0
|
Chris@87
|
1562
|
Chris@87
|
1563 cache : bool, optional
|
Chris@87
|
1564 If `True`, then cache the first function call that determines the number
|
Chris@87
|
1565 of outputs if `otypes` is not provided.
|
Chris@87
|
1566
|
Chris@87
|
1567 .. versionadded:: 1.7.0
|
Chris@87
|
1568
|
Chris@87
|
1569 Returns
|
Chris@87
|
1570 -------
|
Chris@87
|
1571 vectorized : callable
|
Chris@87
|
1572 Vectorized function.
|
Chris@87
|
1573
|
Chris@87
|
1574 Examples
|
Chris@87
|
1575 --------
|
Chris@87
|
1576 >>> def myfunc(a, b):
|
Chris@87
|
1577 ... "Return a-b if a>b, otherwise return a+b"
|
Chris@87
|
1578 ... if a > b:
|
Chris@87
|
1579 ... return a - b
|
Chris@87
|
1580 ... else:
|
Chris@87
|
1581 ... return a + b
|
Chris@87
|
1582
|
Chris@87
|
1583 >>> vfunc = np.vectorize(myfunc)
|
Chris@87
|
1584 >>> vfunc([1, 2, 3, 4], 2)
|
Chris@87
|
1585 array([3, 4, 1, 2])
|
Chris@87
|
1586
|
Chris@87
|
1587 The docstring is taken from the input function to `vectorize` unless it
|
Chris@87
|
1588 is specified
|
Chris@87
|
1589
|
Chris@87
|
1590 >>> vfunc.__doc__
|
Chris@87
|
1591 'Return a-b if a>b, otherwise return a+b'
|
Chris@87
|
1592 >>> vfunc = np.vectorize(myfunc, doc='Vectorized `myfunc`')
|
Chris@87
|
1593 >>> vfunc.__doc__
|
Chris@87
|
1594 'Vectorized `myfunc`'
|
Chris@87
|
1595
|
Chris@87
|
1596 The output type is determined by evaluating the first element of the input,
|
Chris@87
|
1597 unless it is specified
|
Chris@87
|
1598
|
Chris@87
|
1599 >>> out = vfunc([1, 2, 3, 4], 2)
|
Chris@87
|
1600 >>> type(out[0])
|
Chris@87
|
1601 <type 'numpy.int32'>
|
Chris@87
|
1602 >>> vfunc = np.vectorize(myfunc, otypes=[np.float])
|
Chris@87
|
1603 >>> out = vfunc([1, 2, 3, 4], 2)
|
Chris@87
|
1604 >>> type(out[0])
|
Chris@87
|
1605 <type 'numpy.float64'>
|
Chris@87
|
1606
|
Chris@87
|
1607 The `excluded` argument can be used to prevent vectorizing over certain
|
Chris@87
|
1608 arguments. This can be useful for array-like arguments of a fixed length
|
Chris@87
|
1609 such as the coefficients for a polynomial as in `polyval`:
|
Chris@87
|
1610
|
Chris@87
|
1611 >>> def mypolyval(p, x):
|
Chris@87
|
1612 ... _p = list(p)
|
Chris@87
|
1613 ... res = _p.pop(0)
|
Chris@87
|
1614 ... while _p:
|
Chris@87
|
1615 ... res = res*x + _p.pop(0)
|
Chris@87
|
1616 ... return res
|
Chris@87
|
1617 >>> vpolyval = np.vectorize(mypolyval, excluded=['p'])
|
Chris@87
|
1618 >>> vpolyval(p=[1, 2, 3], x=[0, 1])
|
Chris@87
|
1619 array([3, 6])
|
Chris@87
|
1620
|
Chris@87
|
1621 Positional arguments may also be excluded by specifying their position:
|
Chris@87
|
1622
|
Chris@87
|
1623 >>> vpolyval.excluded.add(0)
|
Chris@87
|
1624 >>> vpolyval([1, 2, 3], x=[0, 1])
|
Chris@87
|
1625 array([3, 6])
|
Chris@87
|
1626
|
Chris@87
|
1627 Notes
|
Chris@87
|
1628 -----
|
Chris@87
|
1629 The `vectorize` function is provided primarily for convenience, not for
|
Chris@87
|
1630 performance. The implementation is essentially a for loop.
|
Chris@87
|
1631
|
Chris@87
|
1632 If `otypes` is not specified, then a call to the function with the
|
Chris@87
|
1633 first argument will be used to determine the number of outputs. The
|
Chris@87
|
1634 results of this call will be cached if `cache` is `True` to prevent
|
Chris@87
|
1635 calling the function twice. However, to implement the cache, the
|
Chris@87
|
1636 original function must be wrapped which will slow down subsequent
|
Chris@87
|
1637 calls, so only do this if your function is expensive.
|
Chris@87
|
1638
|
Chris@87
|
1639 The new keyword argument interface and `excluded` argument support
|
Chris@87
|
1640 further degrades performance.
|
Chris@87
|
1641
|
Chris@87
|
1642 """
|
Chris@87
|
1643
|
Chris@87
|
1644 def __init__(self, pyfunc, otypes='', doc=None, excluded=None,
|
Chris@87
|
1645 cache=False):
|
Chris@87
|
1646 self.pyfunc = pyfunc
|
Chris@87
|
1647 self.cache = cache
|
Chris@87
|
1648 self._ufunc = None # Caching to improve default performance
|
Chris@87
|
1649
|
Chris@87
|
1650 if doc is None:
|
Chris@87
|
1651 self.__doc__ = pyfunc.__doc__
|
Chris@87
|
1652 else:
|
Chris@87
|
1653 self.__doc__ = doc
|
Chris@87
|
1654
|
Chris@87
|
1655 if isinstance(otypes, str):
|
Chris@87
|
1656 self.otypes = otypes
|
Chris@87
|
1657 for char in self.otypes:
|
Chris@87
|
1658 if char not in typecodes['All']:
|
Chris@87
|
1659 raise ValueError(
|
Chris@87
|
1660 "Invalid otype specified: %s" % (char,))
|
Chris@87
|
1661 elif iterable(otypes):
|
Chris@87
|
1662 self.otypes = ''.join([_nx.dtype(x).char for x in otypes])
|
Chris@87
|
1663 else:
|
Chris@87
|
1664 raise ValueError(
|
Chris@87
|
1665 "Invalid otype specification")
|
Chris@87
|
1666
|
Chris@87
|
1667 # Excluded variable support
|
Chris@87
|
1668 if excluded is None:
|
Chris@87
|
1669 excluded = set()
|
Chris@87
|
1670 self.excluded = set(excluded)
|
Chris@87
|
1671
|
Chris@87
|
1672 def __call__(self, *args, **kwargs):
|
Chris@87
|
1673 """
|
Chris@87
|
1674 Return arrays with the results of `pyfunc` broadcast (vectorized) over
|
Chris@87
|
1675 `args` and `kwargs` not in `excluded`.
|
Chris@87
|
1676 """
|
Chris@87
|
1677 excluded = self.excluded
|
Chris@87
|
1678 if not kwargs and not excluded:
|
Chris@87
|
1679 func = self.pyfunc
|
Chris@87
|
1680 vargs = args
|
Chris@87
|
1681 else:
|
Chris@87
|
1682 # The wrapper accepts only positional arguments: we use `names` and
|
Chris@87
|
1683 # `inds` to mutate `the_args` and `kwargs` to pass to the original
|
Chris@87
|
1684 # function.
|
Chris@87
|
1685 nargs = len(args)
|
Chris@87
|
1686
|
Chris@87
|
1687 names = [_n for _n in kwargs if _n not in excluded]
|
Chris@87
|
1688 inds = [_i for _i in range(nargs) if _i not in excluded]
|
Chris@87
|
1689 the_args = list(args)
|
Chris@87
|
1690
|
Chris@87
|
1691 def func(*vargs):
|
Chris@87
|
1692 for _n, _i in enumerate(inds):
|
Chris@87
|
1693 the_args[_i] = vargs[_n]
|
Chris@87
|
1694 kwargs.update(zip(names, vargs[len(inds):]))
|
Chris@87
|
1695 return self.pyfunc(*the_args, **kwargs)
|
Chris@87
|
1696
|
Chris@87
|
1697 vargs = [args[_i] for _i in inds]
|
Chris@87
|
1698 vargs.extend([kwargs[_n] for _n in names])
|
Chris@87
|
1699
|
Chris@87
|
1700 return self._vectorize_call(func=func, args=vargs)
|
Chris@87
|
1701
|
Chris@87
|
1702 def _get_ufunc_and_otypes(self, func, args):
|
Chris@87
|
1703 """Return (ufunc, otypes)."""
|
Chris@87
|
1704 # frompyfunc will fail if args is empty
|
Chris@87
|
1705 if not args:
|
Chris@87
|
1706 raise ValueError('args can not be empty')
|
Chris@87
|
1707
|
Chris@87
|
1708 if self.otypes:
|
Chris@87
|
1709 otypes = self.otypes
|
Chris@87
|
1710 nout = len(otypes)
|
Chris@87
|
1711
|
Chris@87
|
1712 # Note logic here: We only *use* self._ufunc if func is self.pyfunc
|
Chris@87
|
1713 # even though we set self._ufunc regardless.
|
Chris@87
|
1714 if func is self.pyfunc and self._ufunc is not None:
|
Chris@87
|
1715 ufunc = self._ufunc
|
Chris@87
|
1716 else:
|
Chris@87
|
1717 ufunc = self._ufunc = frompyfunc(func, len(args), nout)
|
Chris@87
|
1718 else:
|
Chris@87
|
1719 # Get number of outputs and output types by calling the function on
|
Chris@87
|
1720 # the first entries of args. We also cache the result to prevent
|
Chris@87
|
1721 # the subsequent call when the ufunc is evaluated.
|
Chris@87
|
1722 # Assumes that ufunc first evaluates the 0th elements in the input
|
Chris@87
|
1723 # arrays (the input values are not checked to ensure this)
|
Chris@87
|
1724 inputs = [asarray(_a).flat[0] for _a in args]
|
Chris@87
|
1725 outputs = func(*inputs)
|
Chris@87
|
1726
|
Chris@87
|
1727 # Performance note: profiling indicates that -- for simple
|
Chris@87
|
1728 # functions at least -- this wrapping can almost double the
|
Chris@87
|
1729 # execution time.
|
Chris@87
|
1730 # Hence we make it optional.
|
Chris@87
|
1731 if self.cache:
|
Chris@87
|
1732 _cache = [outputs]
|
Chris@87
|
1733
|
Chris@87
|
1734 def _func(*vargs):
|
Chris@87
|
1735 if _cache:
|
Chris@87
|
1736 return _cache.pop()
|
Chris@87
|
1737 else:
|
Chris@87
|
1738 return func(*vargs)
|
Chris@87
|
1739 else:
|
Chris@87
|
1740 _func = func
|
Chris@87
|
1741
|
Chris@87
|
1742 if isinstance(outputs, tuple):
|
Chris@87
|
1743 nout = len(outputs)
|
Chris@87
|
1744 else:
|
Chris@87
|
1745 nout = 1
|
Chris@87
|
1746 outputs = (outputs,)
|
Chris@87
|
1747
|
Chris@87
|
1748 otypes = ''.join([asarray(outputs[_k]).dtype.char
|
Chris@87
|
1749 for _k in range(nout)])
|
Chris@87
|
1750
|
Chris@87
|
1751 # Performance note: profiling indicates that creating the ufunc is
|
Chris@87
|
1752 # not a significant cost compared with wrapping so it seems not
|
Chris@87
|
1753 # worth trying to cache this.
|
Chris@87
|
1754 ufunc = frompyfunc(_func, len(args), nout)
|
Chris@87
|
1755
|
Chris@87
|
1756 return ufunc, otypes
|
Chris@87
|
1757
|
Chris@87
|
1758 def _vectorize_call(self, func, args):
|
Chris@87
|
1759 """Vectorized call to `func` over positional `args`."""
|
Chris@87
|
1760 if not args:
|
Chris@87
|
1761 _res = func()
|
Chris@87
|
1762 else:
|
Chris@87
|
1763 ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args)
|
Chris@87
|
1764
|
Chris@87
|
1765 # Convert args to object arrays first
|
Chris@87
|
1766 inputs = [array(_a, copy=False, subok=True, dtype=object)
|
Chris@87
|
1767 for _a in args]
|
Chris@87
|
1768
|
Chris@87
|
1769 outputs = ufunc(*inputs)
|
Chris@87
|
1770
|
Chris@87
|
1771 if ufunc.nout == 1:
|
Chris@87
|
1772 _res = array(outputs,
|
Chris@87
|
1773 copy=False, subok=True, dtype=otypes[0])
|
Chris@87
|
1774 else:
|
Chris@87
|
1775 _res = tuple([array(_x, copy=False, subok=True, dtype=_t)
|
Chris@87
|
1776 for _x, _t in zip(outputs, otypes)])
|
Chris@87
|
1777 return _res
|
Chris@87
|
1778
|
Chris@87
|
1779
|
Chris@87
|
1780 def cov(m, y=None, rowvar=1, bias=0, ddof=None):
|
Chris@87
|
1781 """
|
Chris@87
|
1782 Estimate a covariance matrix, given data.
|
Chris@87
|
1783
|
Chris@87
|
1784 Covariance indicates the level to which two variables vary together.
|
Chris@87
|
1785 If we examine N-dimensional samples, :math:`X = [x_1, x_2, ... x_N]^T`,
|
Chris@87
|
1786 then the covariance matrix element :math:`C_{ij}` is the covariance of
|
Chris@87
|
1787 :math:`x_i` and :math:`x_j`. The element :math:`C_{ii}` is the variance
|
Chris@87
|
1788 of :math:`x_i`.
|
Chris@87
|
1789
|
Chris@87
|
1790 Parameters
|
Chris@87
|
1791 ----------
|
Chris@87
|
1792 m : array_like
|
Chris@87
|
1793 A 1-D or 2-D array containing multiple variables and observations.
|
Chris@87
|
1794 Each row of `m` represents a variable, and each column a single
|
Chris@87
|
1795 observation of all those variables. Also see `rowvar` below.
|
Chris@87
|
1796 y : array_like, optional
|
Chris@87
|
1797 An additional set of variables and observations. `y` has the same
|
Chris@87
|
1798 form as that of `m`.
|
Chris@87
|
1799 rowvar : int, optional
|
Chris@87
|
1800 If `rowvar` is non-zero (default), then each row represents a
|
Chris@87
|
1801 variable, with observations in the columns. Otherwise, the relationship
|
Chris@87
|
1802 is transposed: each column represents a variable, while the rows
|
Chris@87
|
1803 contain observations.
|
Chris@87
|
1804 bias : int, optional
|
Chris@87
|
1805 Default normalization is by ``(N - 1)``, where ``N`` is the number of
|
Chris@87
|
1806 observations given (unbiased estimate). If `bias` is 1, then
|
Chris@87
|
1807 normalization is by ``N``. These values can be overridden by using
|
Chris@87
|
1808 the keyword ``ddof`` in numpy versions >= 1.5.
|
Chris@87
|
1809 ddof : int, optional
|
Chris@87
|
1810 .. versionadded:: 1.5
|
Chris@87
|
1811 If not ``None`` normalization is by ``(N - ddof)``, where ``N`` is
|
Chris@87
|
1812 the number of observations; this overrides the value implied by
|
Chris@87
|
1813 ``bias``. The default value is ``None``.
|
Chris@87
|
1814
|
Chris@87
|
1815 Returns
|
Chris@87
|
1816 -------
|
Chris@87
|
1817 out : ndarray
|
Chris@87
|
1818 The covariance matrix of the variables.
|
Chris@87
|
1819
|
Chris@87
|
1820 See Also
|
Chris@87
|
1821 --------
|
Chris@87
|
1822 corrcoef : Normalized covariance matrix
|
Chris@87
|
1823
|
Chris@87
|
1824 Examples
|
Chris@87
|
1825 --------
|
Chris@87
|
1826 Consider two variables, :math:`x_0` and :math:`x_1`, which
|
Chris@87
|
1827 correlate perfectly, but in opposite directions:
|
Chris@87
|
1828
|
Chris@87
|
1829 >>> x = np.array([[0, 2], [1, 1], [2, 0]]).T
|
Chris@87
|
1830 >>> x
|
Chris@87
|
1831 array([[0, 1, 2],
|
Chris@87
|
1832 [2, 1, 0]])
|
Chris@87
|
1833
|
Chris@87
|
1834 Note how :math:`x_0` increases while :math:`x_1` decreases. The covariance
|
Chris@87
|
1835 matrix shows this clearly:
|
Chris@87
|
1836
|
Chris@87
|
1837 >>> np.cov(x)
|
Chris@87
|
1838 array([[ 1., -1.],
|
Chris@87
|
1839 [-1., 1.]])
|
Chris@87
|
1840
|
Chris@87
|
1841 Note that element :math:`C_{0,1}`, which shows the correlation between
|
Chris@87
|
1842 :math:`x_0` and :math:`x_1`, is negative.
|
Chris@87
|
1843
|
Chris@87
|
1844 Further, note how `x` and `y` are combined:
|
Chris@87
|
1845
|
Chris@87
|
1846 >>> x = [-2.1, -1, 4.3]
|
Chris@87
|
1847 >>> y = [3, 1.1, 0.12]
|
Chris@87
|
1848 >>> X = np.vstack((x,y))
|
Chris@87
|
1849 >>> print np.cov(X)
|
Chris@87
|
1850 [[ 11.71 -4.286 ]
|
Chris@87
|
1851 [ -4.286 2.14413333]]
|
Chris@87
|
1852 >>> print np.cov(x, y)
|
Chris@87
|
1853 [[ 11.71 -4.286 ]
|
Chris@87
|
1854 [ -4.286 2.14413333]]
|
Chris@87
|
1855 >>> print np.cov(x)
|
Chris@87
|
1856 11.71
|
Chris@87
|
1857
|
Chris@87
|
1858 """
|
Chris@87
|
1859 # Check inputs
|
Chris@87
|
1860 if ddof is not None and ddof != int(ddof):
|
Chris@87
|
1861 raise ValueError(
|
Chris@87
|
1862 "ddof must be integer")
|
Chris@87
|
1863
|
Chris@87
|
1864 # Handles complex arrays too
|
Chris@87
|
1865 m = np.asarray(m)
|
Chris@87
|
1866 if y is None:
|
Chris@87
|
1867 dtype = np.result_type(m, np.float64)
|
Chris@87
|
1868 else:
|
Chris@87
|
1869 y = np.asarray(y)
|
Chris@87
|
1870 dtype = np.result_type(m, y, np.float64)
|
Chris@87
|
1871 X = array(m, ndmin=2, dtype=dtype)
|
Chris@87
|
1872
|
Chris@87
|
1873 if X.shape[0] == 1:
|
Chris@87
|
1874 rowvar = 1
|
Chris@87
|
1875 if rowvar:
|
Chris@87
|
1876 N = X.shape[1]
|
Chris@87
|
1877 axis = 0
|
Chris@87
|
1878 else:
|
Chris@87
|
1879 N = X.shape[0]
|
Chris@87
|
1880 axis = 1
|
Chris@87
|
1881
|
Chris@87
|
1882 # check ddof
|
Chris@87
|
1883 if ddof is None:
|
Chris@87
|
1884 if bias == 0:
|
Chris@87
|
1885 ddof = 1
|
Chris@87
|
1886 else:
|
Chris@87
|
1887 ddof = 0
|
Chris@87
|
1888 fact = float(N - ddof)
|
Chris@87
|
1889 if fact <= 0:
|
Chris@87
|
1890 warnings.warn("Degrees of freedom <= 0 for slice", RuntimeWarning)
|
Chris@87
|
1891 fact = 0.0
|
Chris@87
|
1892
|
Chris@87
|
1893 if y is not None:
|
Chris@87
|
1894 y = array(y, copy=False, ndmin=2, dtype=dtype)
|
Chris@87
|
1895 X = concatenate((X, y), axis)
|
Chris@87
|
1896
|
Chris@87
|
1897 X -= X.mean(axis=1-axis, keepdims=True)
|
Chris@87
|
1898 if not rowvar:
|
Chris@87
|
1899 return (dot(X.T, X.conj()) / fact).squeeze()
|
Chris@87
|
1900 else:
|
Chris@87
|
1901 return (dot(X, X.T.conj()) / fact).squeeze()
|
Chris@87
|
1902
|
Chris@87
|
1903
|
Chris@87
|
1904 def corrcoef(x, y=None, rowvar=1, bias=0, ddof=None):
|
Chris@87
|
1905 """
|
Chris@87
|
1906 Return correlation coefficients.
|
Chris@87
|
1907
|
Chris@87
|
1908 Please refer to the documentation for `cov` for more detail. The
|
Chris@87
|
1909 relationship between the correlation coefficient matrix, `P`, and the
|
Chris@87
|
1910 covariance matrix, `C`, is
|
Chris@87
|
1911
|
Chris@87
|
1912 .. math:: P_{ij} = \\frac{ C_{ij} } { \\sqrt{ C_{ii} * C_{jj} } }
|
Chris@87
|
1913
|
Chris@87
|
1914 The values of `P` are between -1 and 1, inclusive.
|
Chris@87
|
1915
|
Chris@87
|
1916 Parameters
|
Chris@87
|
1917 ----------
|
Chris@87
|
1918 x : array_like
|
Chris@87
|
1919 A 1-D or 2-D array containing multiple variables and observations.
|
Chris@87
|
1920 Each row of `m` represents a variable, and each column a single
|
Chris@87
|
1921 observation of all those variables. Also see `rowvar` below.
|
Chris@87
|
1922 y : array_like, optional
|
Chris@87
|
1923 An additional set of variables and observations. `y` has the same
|
Chris@87
|
1924 shape as `m`.
|
Chris@87
|
1925 rowvar : int, optional
|
Chris@87
|
1926 If `rowvar` is non-zero (default), then each row represents a
|
Chris@87
|
1927 variable, with observations in the columns. Otherwise, the relationship
|
Chris@87
|
1928 is transposed: each column represents a variable, while the rows
|
Chris@87
|
1929 contain observations.
|
Chris@87
|
1930 bias : int, optional
|
Chris@87
|
1931 Default normalization is by ``(N - 1)``, where ``N`` is the number of
|
Chris@87
|
1932 observations (unbiased estimate). If `bias` is 1, then
|
Chris@87
|
1933 normalization is by ``N``. These values can be overridden by using
|
Chris@87
|
1934 the keyword ``ddof`` in numpy versions >= 1.5.
|
Chris@87
|
1935 ddof : {None, int}, optional
|
Chris@87
|
1936 .. versionadded:: 1.5
|
Chris@87
|
1937 If not ``None`` normalization is by ``(N - ddof)``, where ``N`` is
|
Chris@87
|
1938 the number of observations; this overrides the value implied by
|
Chris@87
|
1939 ``bias``. The default value is ``None``.
|
Chris@87
|
1940
|
Chris@87
|
1941 Returns
|
Chris@87
|
1942 -------
|
Chris@87
|
1943 out : ndarray
|
Chris@87
|
1944 The correlation coefficient matrix of the variables.
|
Chris@87
|
1945
|
Chris@87
|
1946 See Also
|
Chris@87
|
1947 --------
|
Chris@87
|
1948 cov : Covariance matrix
|
Chris@87
|
1949
|
Chris@87
|
1950 """
|
Chris@87
|
1951 c = cov(x, y, rowvar, bias, ddof)
|
Chris@87
|
1952 try:
|
Chris@87
|
1953 d = diag(c)
|
Chris@87
|
1954 except ValueError: # scalar covariance
|
Chris@87
|
1955 # nan if incorrect value (nan, inf, 0), 1 otherwise
|
Chris@87
|
1956 return c / c
|
Chris@87
|
1957 return c / sqrt(multiply.outer(d, d))
|
Chris@87
|
1958
|
Chris@87
|
1959
|
Chris@87
|
1960 def blackman(M):
|
Chris@87
|
1961 """
|
Chris@87
|
1962 Return the Blackman window.
|
Chris@87
|
1963
|
Chris@87
|
1964 The Blackman window is a taper formed by using the first three
|
Chris@87
|
1965 terms of a summation of cosines. It was designed to have close to the
|
Chris@87
|
1966 minimal leakage possible. It is close to optimal, only slightly worse
|
Chris@87
|
1967 than a Kaiser window.
|
Chris@87
|
1968
|
Chris@87
|
1969 Parameters
|
Chris@87
|
1970 ----------
|
Chris@87
|
1971 M : int
|
Chris@87
|
1972 Number of points in the output window. If zero or less, an empty
|
Chris@87
|
1973 array is returned.
|
Chris@87
|
1974
|
Chris@87
|
1975 Returns
|
Chris@87
|
1976 -------
|
Chris@87
|
1977 out : ndarray
|
Chris@87
|
1978 The window, with the maximum value normalized to one (the value one
|
Chris@87
|
1979 appears only if the number of samples is odd).
|
Chris@87
|
1980
|
Chris@87
|
1981 See Also
|
Chris@87
|
1982 --------
|
Chris@87
|
1983 bartlett, hamming, hanning, kaiser
|
Chris@87
|
1984
|
Chris@87
|
1985 Notes
|
Chris@87
|
1986 -----
|
Chris@87
|
1987 The Blackman window is defined as
|
Chris@87
|
1988
|
Chris@87
|
1989 .. math:: w(n) = 0.42 - 0.5 \\cos(2\\pi n/M) + 0.08 \\cos(4\\pi n/M)
|
Chris@87
|
1990
|
Chris@87
|
1991 Most references to the Blackman window come from the signal processing
|
Chris@87
|
1992 literature, where it is used as one of many windowing functions for
|
Chris@87
|
1993 smoothing values. It is also known as an apodization (which means
|
Chris@87
|
1994 "removing the foot", i.e. smoothing discontinuities at the beginning
|
Chris@87
|
1995 and end of the sampled signal) or tapering function. It is known as a
|
Chris@87
|
1996 "near optimal" tapering function, almost as good (by some measures)
|
Chris@87
|
1997 as the kaiser window.
|
Chris@87
|
1998
|
Chris@87
|
1999 References
|
Chris@87
|
2000 ----------
|
Chris@87
|
2001 Blackman, R.B. and Tukey, J.W., (1958) The measurement of power spectra,
|
Chris@87
|
2002 Dover Publications, New York.
|
Chris@87
|
2003
|
Chris@87
|
2004 Oppenheim, A.V., and R.W. Schafer. Discrete-Time Signal Processing.
|
Chris@87
|
2005 Upper Saddle River, NJ: Prentice-Hall, 1999, pp. 468-471.
|
Chris@87
|
2006
|
Chris@87
|
2007 Examples
|
Chris@87
|
2008 --------
|
Chris@87
|
2009 >>> np.blackman(12)
|
Chris@87
|
2010 array([ -1.38777878e-17, 3.26064346e-02, 1.59903635e-01,
|
Chris@87
|
2011 4.14397981e-01, 7.36045180e-01, 9.67046769e-01,
|
Chris@87
|
2012 9.67046769e-01, 7.36045180e-01, 4.14397981e-01,
|
Chris@87
|
2013 1.59903635e-01, 3.26064346e-02, -1.38777878e-17])
|
Chris@87
|
2014
|
Chris@87
|
2015
|
Chris@87
|
2016 Plot the window and the frequency response:
|
Chris@87
|
2017
|
Chris@87
|
2018 >>> from numpy.fft import fft, fftshift
|
Chris@87
|
2019 >>> window = np.blackman(51)
|
Chris@87
|
2020 >>> plt.plot(window)
|
Chris@87
|
2021 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
2022 >>> plt.title("Blackman window")
|
Chris@87
|
2023 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2024 >>> plt.ylabel("Amplitude")
|
Chris@87
|
2025 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2026 >>> plt.xlabel("Sample")
|
Chris@87
|
2027 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2028 >>> plt.show()
|
Chris@87
|
2029
|
Chris@87
|
2030 >>> plt.figure()
|
Chris@87
|
2031 <matplotlib.figure.Figure object at 0x...>
|
Chris@87
|
2032 >>> A = fft(window, 2048) / 25.5
|
Chris@87
|
2033 >>> mag = np.abs(fftshift(A))
|
Chris@87
|
2034 >>> freq = np.linspace(-0.5, 0.5, len(A))
|
Chris@87
|
2035 >>> response = 20 * np.log10(mag)
|
Chris@87
|
2036 >>> response = np.clip(response, -100, 100)
|
Chris@87
|
2037 >>> plt.plot(freq, response)
|
Chris@87
|
2038 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
2039 >>> plt.title("Frequency response of Blackman window")
|
Chris@87
|
2040 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2041 >>> plt.ylabel("Magnitude [dB]")
|
Chris@87
|
2042 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2043 >>> plt.xlabel("Normalized frequency [cycles per sample]")
|
Chris@87
|
2044 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2045 >>> plt.axis('tight')
|
Chris@87
|
2046 (-0.5, 0.5, -100.0, ...)
|
Chris@87
|
2047 >>> plt.show()
|
Chris@87
|
2048
|
Chris@87
|
2049 """
|
Chris@87
|
2050 if M < 1:
|
Chris@87
|
2051 return array([])
|
Chris@87
|
2052 if M == 1:
|
Chris@87
|
2053 return ones(1, float)
|
Chris@87
|
2054 n = arange(0, M)
|
Chris@87
|
2055 return 0.42 - 0.5*cos(2.0*pi*n/(M-1)) + 0.08*cos(4.0*pi*n/(M-1))
|
Chris@87
|
2056
|
Chris@87
|
2057
|
Chris@87
|
2058 def bartlett(M):
|
Chris@87
|
2059 """
|
Chris@87
|
2060 Return the Bartlett window.
|
Chris@87
|
2061
|
Chris@87
|
2062 The Bartlett window is very similar to a triangular window, except
|
Chris@87
|
2063 that the end points are at zero. It is often used in signal
|
Chris@87
|
2064 processing for tapering a signal, without generating too much
|
Chris@87
|
2065 ripple in the frequency domain.
|
Chris@87
|
2066
|
Chris@87
|
2067 Parameters
|
Chris@87
|
2068 ----------
|
Chris@87
|
2069 M : int
|
Chris@87
|
2070 Number of points in the output window. If zero or less, an
|
Chris@87
|
2071 empty array is returned.
|
Chris@87
|
2072
|
Chris@87
|
2073 Returns
|
Chris@87
|
2074 -------
|
Chris@87
|
2075 out : array
|
Chris@87
|
2076 The triangular window, with the maximum value normalized to one
|
Chris@87
|
2077 (the value one appears only if the number of samples is odd), with
|
Chris@87
|
2078 the first and last samples equal to zero.
|
Chris@87
|
2079
|
Chris@87
|
2080 See Also
|
Chris@87
|
2081 --------
|
Chris@87
|
2082 blackman, hamming, hanning, kaiser
|
Chris@87
|
2083
|
Chris@87
|
2084 Notes
|
Chris@87
|
2085 -----
|
Chris@87
|
2086 The Bartlett window is defined as
|
Chris@87
|
2087
|
Chris@87
|
2088 .. math:: w(n) = \\frac{2}{M-1} \\left(
|
Chris@87
|
2089 \\frac{M-1}{2} - \\left|n - \\frac{M-1}{2}\\right|
|
Chris@87
|
2090 \\right)
|
Chris@87
|
2091
|
Chris@87
|
2092 Most references to the Bartlett window come from the signal
|
Chris@87
|
2093 processing literature, where it is used as one of many windowing
|
Chris@87
|
2094 functions for smoothing values. Note that convolution with this
|
Chris@87
|
2095 window produces linear interpolation. It is also known as an
|
Chris@87
|
2096 apodization (which means"removing the foot", i.e. smoothing
|
Chris@87
|
2097 discontinuities at the beginning and end of the sampled signal) or
|
Chris@87
|
2098 tapering function. The fourier transform of the Bartlett is the product
|
Chris@87
|
2099 of two sinc functions.
|
Chris@87
|
2100 Note the excellent discussion in Kanasewich.
|
Chris@87
|
2101
|
Chris@87
|
2102 References
|
Chris@87
|
2103 ----------
|
Chris@87
|
2104 .. [1] M.S. Bartlett, "Periodogram Analysis and Continuous Spectra",
|
Chris@87
|
2105 Biometrika 37, 1-16, 1950.
|
Chris@87
|
2106 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics",
|
Chris@87
|
2107 The University of Alberta Press, 1975, pp. 109-110.
|
Chris@87
|
2108 .. [3] A.V. Oppenheim and R.W. Schafer, "Discrete-Time Signal
|
Chris@87
|
2109 Processing", Prentice-Hall, 1999, pp. 468-471.
|
Chris@87
|
2110 .. [4] Wikipedia, "Window function",
|
Chris@87
|
2111 http://en.wikipedia.org/wiki/Window_function
|
Chris@87
|
2112 .. [5] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
|
Chris@87
|
2113 "Numerical Recipes", Cambridge University Press, 1986, page 429.
|
Chris@87
|
2114
|
Chris@87
|
2115
|
Chris@87
|
2116 Examples
|
Chris@87
|
2117 --------
|
Chris@87
|
2118 >>> np.bartlett(12)
|
Chris@87
|
2119 array([ 0. , 0.18181818, 0.36363636, 0.54545455, 0.72727273,
|
Chris@87
|
2120 0.90909091, 0.90909091, 0.72727273, 0.54545455, 0.36363636,
|
Chris@87
|
2121 0.18181818, 0. ])
|
Chris@87
|
2122
|
Chris@87
|
2123 Plot the window and its frequency response (requires SciPy and matplotlib):
|
Chris@87
|
2124
|
Chris@87
|
2125 >>> from numpy.fft import fft, fftshift
|
Chris@87
|
2126 >>> window = np.bartlett(51)
|
Chris@87
|
2127 >>> plt.plot(window)
|
Chris@87
|
2128 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
2129 >>> plt.title("Bartlett window")
|
Chris@87
|
2130 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2131 >>> plt.ylabel("Amplitude")
|
Chris@87
|
2132 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2133 >>> plt.xlabel("Sample")
|
Chris@87
|
2134 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2135 >>> plt.show()
|
Chris@87
|
2136
|
Chris@87
|
2137 >>> plt.figure()
|
Chris@87
|
2138 <matplotlib.figure.Figure object at 0x...>
|
Chris@87
|
2139 >>> A = fft(window, 2048) / 25.5
|
Chris@87
|
2140 >>> mag = np.abs(fftshift(A))
|
Chris@87
|
2141 >>> freq = np.linspace(-0.5, 0.5, len(A))
|
Chris@87
|
2142 >>> response = 20 * np.log10(mag)
|
Chris@87
|
2143 >>> response = np.clip(response, -100, 100)
|
Chris@87
|
2144 >>> plt.plot(freq, response)
|
Chris@87
|
2145 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
2146 >>> plt.title("Frequency response of Bartlett window")
|
Chris@87
|
2147 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2148 >>> plt.ylabel("Magnitude [dB]")
|
Chris@87
|
2149 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2150 >>> plt.xlabel("Normalized frequency [cycles per sample]")
|
Chris@87
|
2151 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2152 >>> plt.axis('tight')
|
Chris@87
|
2153 (-0.5, 0.5, -100.0, ...)
|
Chris@87
|
2154 >>> plt.show()
|
Chris@87
|
2155
|
Chris@87
|
2156 """
|
Chris@87
|
2157 if M < 1:
|
Chris@87
|
2158 return array([])
|
Chris@87
|
2159 if M == 1:
|
Chris@87
|
2160 return ones(1, float)
|
Chris@87
|
2161 n = arange(0, M)
|
Chris@87
|
2162 return where(less_equal(n, (M-1)/2.0), 2.0*n/(M-1), 2.0 - 2.0*n/(M-1))
|
Chris@87
|
2163
|
Chris@87
|
2164
|
Chris@87
|
2165 def hanning(M):
|
Chris@87
|
2166 """
|
Chris@87
|
2167 Return the Hanning window.
|
Chris@87
|
2168
|
Chris@87
|
2169 The Hanning window is a taper formed by using a weighted cosine.
|
Chris@87
|
2170
|
Chris@87
|
2171 Parameters
|
Chris@87
|
2172 ----------
|
Chris@87
|
2173 M : int
|
Chris@87
|
2174 Number of points in the output window. If zero or less, an
|
Chris@87
|
2175 empty array is returned.
|
Chris@87
|
2176
|
Chris@87
|
2177 Returns
|
Chris@87
|
2178 -------
|
Chris@87
|
2179 out : ndarray, shape(M,)
|
Chris@87
|
2180 The window, with the maximum value normalized to one (the value
|
Chris@87
|
2181 one appears only if `M` is odd).
|
Chris@87
|
2182
|
Chris@87
|
2183 See Also
|
Chris@87
|
2184 --------
|
Chris@87
|
2185 bartlett, blackman, hamming, kaiser
|
Chris@87
|
2186
|
Chris@87
|
2187 Notes
|
Chris@87
|
2188 -----
|
Chris@87
|
2189 The Hanning window is defined as
|
Chris@87
|
2190
|
Chris@87
|
2191 .. math:: w(n) = 0.5 - 0.5cos\\left(\\frac{2\\pi{n}}{M-1}\\right)
|
Chris@87
|
2192 \\qquad 0 \\leq n \\leq M-1
|
Chris@87
|
2193
|
Chris@87
|
2194 The Hanning was named for Julius van Hann, an Austrian meteorologist.
|
Chris@87
|
2195 It is also known as the Cosine Bell. Some authors prefer that it be
|
Chris@87
|
2196 called a Hann window, to help avoid confusion with the very similar
|
Chris@87
|
2197 Hamming window.
|
Chris@87
|
2198
|
Chris@87
|
2199 Most references to the Hanning window come from the signal processing
|
Chris@87
|
2200 literature, where it is used as one of many windowing functions for
|
Chris@87
|
2201 smoothing values. It is also known as an apodization (which means
|
Chris@87
|
2202 "removing the foot", i.e. smoothing discontinuities at the beginning
|
Chris@87
|
2203 and end of the sampled signal) or tapering function.
|
Chris@87
|
2204
|
Chris@87
|
2205 References
|
Chris@87
|
2206 ----------
|
Chris@87
|
2207 .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power
|
Chris@87
|
2208 spectra, Dover Publications, New York.
|
Chris@87
|
2209 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics",
|
Chris@87
|
2210 The University of Alberta Press, 1975, pp. 106-108.
|
Chris@87
|
2211 .. [3] Wikipedia, "Window function",
|
Chris@87
|
2212 http://en.wikipedia.org/wiki/Window_function
|
Chris@87
|
2213 .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
|
Chris@87
|
2214 "Numerical Recipes", Cambridge University Press, 1986, page 425.
|
Chris@87
|
2215
|
Chris@87
|
2216 Examples
|
Chris@87
|
2217 --------
|
Chris@87
|
2218 >>> np.hanning(12)
|
Chris@87
|
2219 array([ 0. , 0.07937323, 0.29229249, 0.57115742, 0.82743037,
|
Chris@87
|
2220 0.97974649, 0.97974649, 0.82743037, 0.57115742, 0.29229249,
|
Chris@87
|
2221 0.07937323, 0. ])
|
Chris@87
|
2222
|
Chris@87
|
2223 Plot the window and its frequency response:
|
Chris@87
|
2224
|
Chris@87
|
2225 >>> from numpy.fft import fft, fftshift
|
Chris@87
|
2226 >>> window = np.hanning(51)
|
Chris@87
|
2227 >>> plt.plot(window)
|
Chris@87
|
2228 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
2229 >>> plt.title("Hann window")
|
Chris@87
|
2230 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2231 >>> plt.ylabel("Amplitude")
|
Chris@87
|
2232 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2233 >>> plt.xlabel("Sample")
|
Chris@87
|
2234 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2235 >>> plt.show()
|
Chris@87
|
2236
|
Chris@87
|
2237 >>> plt.figure()
|
Chris@87
|
2238 <matplotlib.figure.Figure object at 0x...>
|
Chris@87
|
2239 >>> A = fft(window, 2048) / 25.5
|
Chris@87
|
2240 >>> mag = np.abs(fftshift(A))
|
Chris@87
|
2241 >>> freq = np.linspace(-0.5, 0.5, len(A))
|
Chris@87
|
2242 >>> response = 20 * np.log10(mag)
|
Chris@87
|
2243 >>> response = np.clip(response, -100, 100)
|
Chris@87
|
2244 >>> plt.plot(freq, response)
|
Chris@87
|
2245 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
2246 >>> plt.title("Frequency response of the Hann window")
|
Chris@87
|
2247 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2248 >>> plt.ylabel("Magnitude [dB]")
|
Chris@87
|
2249 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2250 >>> plt.xlabel("Normalized frequency [cycles per sample]")
|
Chris@87
|
2251 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2252 >>> plt.axis('tight')
|
Chris@87
|
2253 (-0.5, 0.5, -100.0, ...)
|
Chris@87
|
2254 >>> plt.show()
|
Chris@87
|
2255
|
Chris@87
|
2256 """
|
Chris@87
|
2257 if M < 1:
|
Chris@87
|
2258 return array([])
|
Chris@87
|
2259 if M == 1:
|
Chris@87
|
2260 return ones(1, float)
|
Chris@87
|
2261 n = arange(0, M)
|
Chris@87
|
2262 return 0.5 - 0.5*cos(2.0*pi*n/(M-1))
|
Chris@87
|
2263
|
Chris@87
|
2264
|
Chris@87
|
2265 def hamming(M):
|
Chris@87
|
2266 """
|
Chris@87
|
2267 Return the Hamming window.
|
Chris@87
|
2268
|
Chris@87
|
2269 The Hamming window is a taper formed by using a weighted cosine.
|
Chris@87
|
2270
|
Chris@87
|
2271 Parameters
|
Chris@87
|
2272 ----------
|
Chris@87
|
2273 M : int
|
Chris@87
|
2274 Number of points in the output window. If zero or less, an
|
Chris@87
|
2275 empty array is returned.
|
Chris@87
|
2276
|
Chris@87
|
2277 Returns
|
Chris@87
|
2278 -------
|
Chris@87
|
2279 out : ndarray
|
Chris@87
|
2280 The window, with the maximum value normalized to one (the value
|
Chris@87
|
2281 one appears only if the number of samples is odd).
|
Chris@87
|
2282
|
Chris@87
|
2283 See Also
|
Chris@87
|
2284 --------
|
Chris@87
|
2285 bartlett, blackman, hanning, kaiser
|
Chris@87
|
2286
|
Chris@87
|
2287 Notes
|
Chris@87
|
2288 -----
|
Chris@87
|
2289 The Hamming window is defined as
|
Chris@87
|
2290
|
Chris@87
|
2291 .. math:: w(n) = 0.54 - 0.46cos\\left(\\frac{2\\pi{n}}{M-1}\\right)
|
Chris@87
|
2292 \\qquad 0 \\leq n \\leq M-1
|
Chris@87
|
2293
|
Chris@87
|
2294 The Hamming was named for R. W. Hamming, an associate of J. W. Tukey
|
Chris@87
|
2295 and is described in Blackman and Tukey. It was recommended for
|
Chris@87
|
2296 smoothing the truncated autocovariance function in the time domain.
|
Chris@87
|
2297 Most references to the Hamming window come from the signal processing
|
Chris@87
|
2298 literature, where it is used as one of many windowing functions for
|
Chris@87
|
2299 smoothing values. It is also known as an apodization (which means
|
Chris@87
|
2300 "removing the foot", i.e. smoothing discontinuities at the beginning
|
Chris@87
|
2301 and end of the sampled signal) or tapering function.
|
Chris@87
|
2302
|
Chris@87
|
2303 References
|
Chris@87
|
2304 ----------
|
Chris@87
|
2305 .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power
|
Chris@87
|
2306 spectra, Dover Publications, New York.
|
Chris@87
|
2307 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The
|
Chris@87
|
2308 University of Alberta Press, 1975, pp. 109-110.
|
Chris@87
|
2309 .. [3] Wikipedia, "Window function",
|
Chris@87
|
2310 http://en.wikipedia.org/wiki/Window_function
|
Chris@87
|
2311 .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
|
Chris@87
|
2312 "Numerical Recipes", Cambridge University Press, 1986, page 425.
|
Chris@87
|
2313
|
Chris@87
|
2314 Examples
|
Chris@87
|
2315 --------
|
Chris@87
|
2316 >>> np.hamming(12)
|
Chris@87
|
2317 array([ 0.08 , 0.15302337, 0.34890909, 0.60546483, 0.84123594,
|
Chris@87
|
2318 0.98136677, 0.98136677, 0.84123594, 0.60546483, 0.34890909,
|
Chris@87
|
2319 0.15302337, 0.08 ])
|
Chris@87
|
2320
|
Chris@87
|
2321 Plot the window and the frequency response:
|
Chris@87
|
2322
|
Chris@87
|
2323 >>> from numpy.fft import fft, fftshift
|
Chris@87
|
2324 >>> window = np.hamming(51)
|
Chris@87
|
2325 >>> plt.plot(window)
|
Chris@87
|
2326 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
2327 >>> plt.title("Hamming window")
|
Chris@87
|
2328 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2329 >>> plt.ylabel("Amplitude")
|
Chris@87
|
2330 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2331 >>> plt.xlabel("Sample")
|
Chris@87
|
2332 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2333 >>> plt.show()
|
Chris@87
|
2334
|
Chris@87
|
2335 >>> plt.figure()
|
Chris@87
|
2336 <matplotlib.figure.Figure object at 0x...>
|
Chris@87
|
2337 >>> A = fft(window, 2048) / 25.5
|
Chris@87
|
2338 >>> mag = np.abs(fftshift(A))
|
Chris@87
|
2339 >>> freq = np.linspace(-0.5, 0.5, len(A))
|
Chris@87
|
2340 >>> response = 20 * np.log10(mag)
|
Chris@87
|
2341 >>> response = np.clip(response, -100, 100)
|
Chris@87
|
2342 >>> plt.plot(freq, response)
|
Chris@87
|
2343 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
2344 >>> plt.title("Frequency response of Hamming window")
|
Chris@87
|
2345 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2346 >>> plt.ylabel("Magnitude [dB]")
|
Chris@87
|
2347 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2348 >>> plt.xlabel("Normalized frequency [cycles per sample]")
|
Chris@87
|
2349 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2350 >>> plt.axis('tight')
|
Chris@87
|
2351 (-0.5, 0.5, -100.0, ...)
|
Chris@87
|
2352 >>> plt.show()
|
Chris@87
|
2353
|
Chris@87
|
2354 """
|
Chris@87
|
2355 if M < 1:
|
Chris@87
|
2356 return array([])
|
Chris@87
|
2357 if M == 1:
|
Chris@87
|
2358 return ones(1, float)
|
Chris@87
|
2359 n = arange(0, M)
|
Chris@87
|
2360 return 0.54 - 0.46*cos(2.0*pi*n/(M-1))
|
Chris@87
|
2361
|
Chris@87
|
2362 ## Code from cephes for i0
|
Chris@87
|
2363
|
Chris@87
|
2364 _i0A = [
|
Chris@87
|
2365 -4.41534164647933937950E-18,
|
Chris@87
|
2366 3.33079451882223809783E-17,
|
Chris@87
|
2367 -2.43127984654795469359E-16,
|
Chris@87
|
2368 1.71539128555513303061E-15,
|
Chris@87
|
2369 -1.16853328779934516808E-14,
|
Chris@87
|
2370 7.67618549860493561688E-14,
|
Chris@87
|
2371 -4.85644678311192946090E-13,
|
Chris@87
|
2372 2.95505266312963983461E-12,
|
Chris@87
|
2373 -1.72682629144155570723E-11,
|
Chris@87
|
2374 9.67580903537323691224E-11,
|
Chris@87
|
2375 -5.18979560163526290666E-10,
|
Chris@87
|
2376 2.65982372468238665035E-9,
|
Chris@87
|
2377 -1.30002500998624804212E-8,
|
Chris@87
|
2378 6.04699502254191894932E-8,
|
Chris@87
|
2379 -2.67079385394061173391E-7,
|
Chris@87
|
2380 1.11738753912010371815E-6,
|
Chris@87
|
2381 -4.41673835845875056359E-6,
|
Chris@87
|
2382 1.64484480707288970893E-5,
|
Chris@87
|
2383 -5.75419501008210370398E-5,
|
Chris@87
|
2384 1.88502885095841655729E-4,
|
Chris@87
|
2385 -5.76375574538582365885E-4,
|
Chris@87
|
2386 1.63947561694133579842E-3,
|
Chris@87
|
2387 -4.32430999505057594430E-3,
|
Chris@87
|
2388 1.05464603945949983183E-2,
|
Chris@87
|
2389 -2.37374148058994688156E-2,
|
Chris@87
|
2390 4.93052842396707084878E-2,
|
Chris@87
|
2391 -9.49010970480476444210E-2,
|
Chris@87
|
2392 1.71620901522208775349E-1,
|
Chris@87
|
2393 -3.04682672343198398683E-1,
|
Chris@87
|
2394 6.76795274409476084995E-1
|
Chris@87
|
2395 ]
|
Chris@87
|
2396
|
Chris@87
|
2397 _i0B = [
|
Chris@87
|
2398 -7.23318048787475395456E-18,
|
Chris@87
|
2399 -4.83050448594418207126E-18,
|
Chris@87
|
2400 4.46562142029675999901E-17,
|
Chris@87
|
2401 3.46122286769746109310E-17,
|
Chris@87
|
2402 -2.82762398051658348494E-16,
|
Chris@87
|
2403 -3.42548561967721913462E-16,
|
Chris@87
|
2404 1.77256013305652638360E-15,
|
Chris@87
|
2405 3.81168066935262242075E-15,
|
Chris@87
|
2406 -9.55484669882830764870E-15,
|
Chris@87
|
2407 -4.15056934728722208663E-14,
|
Chris@87
|
2408 1.54008621752140982691E-14,
|
Chris@87
|
2409 3.85277838274214270114E-13,
|
Chris@87
|
2410 7.18012445138366623367E-13,
|
Chris@87
|
2411 -1.79417853150680611778E-12,
|
Chris@87
|
2412 -1.32158118404477131188E-11,
|
Chris@87
|
2413 -3.14991652796324136454E-11,
|
Chris@87
|
2414 1.18891471078464383424E-11,
|
Chris@87
|
2415 4.94060238822496958910E-10,
|
Chris@87
|
2416 3.39623202570838634515E-9,
|
Chris@87
|
2417 2.26666899049817806459E-8,
|
Chris@87
|
2418 2.04891858946906374183E-7,
|
Chris@87
|
2419 2.89137052083475648297E-6,
|
Chris@87
|
2420 6.88975834691682398426E-5,
|
Chris@87
|
2421 3.36911647825569408990E-3,
|
Chris@87
|
2422 8.04490411014108831608E-1
|
Chris@87
|
2423 ]
|
Chris@87
|
2424
|
Chris@87
|
2425
|
Chris@87
|
2426 def _chbevl(x, vals):
|
Chris@87
|
2427 b0 = vals[0]
|
Chris@87
|
2428 b1 = 0.0
|
Chris@87
|
2429
|
Chris@87
|
2430 for i in range(1, len(vals)):
|
Chris@87
|
2431 b2 = b1
|
Chris@87
|
2432 b1 = b0
|
Chris@87
|
2433 b0 = x*b1 - b2 + vals[i]
|
Chris@87
|
2434
|
Chris@87
|
2435 return 0.5*(b0 - b2)
|
Chris@87
|
2436
|
Chris@87
|
2437
|
Chris@87
|
2438 def _i0_1(x):
|
Chris@87
|
2439 return exp(x) * _chbevl(x/2.0-2, _i0A)
|
Chris@87
|
2440
|
Chris@87
|
2441
|
Chris@87
|
2442 def _i0_2(x):
|
Chris@87
|
2443 return exp(x) * _chbevl(32.0/x - 2.0, _i0B) / sqrt(x)
|
Chris@87
|
2444
|
Chris@87
|
2445
|
Chris@87
|
2446 def i0(x):
|
Chris@87
|
2447 """
|
Chris@87
|
2448 Modified Bessel function of the first kind, order 0.
|
Chris@87
|
2449
|
Chris@87
|
2450 Usually denoted :math:`I_0`. This function does broadcast, but will *not*
|
Chris@87
|
2451 "up-cast" int dtype arguments unless accompanied by at least one float or
|
Chris@87
|
2452 complex dtype argument (see Raises below).
|
Chris@87
|
2453
|
Chris@87
|
2454 Parameters
|
Chris@87
|
2455 ----------
|
Chris@87
|
2456 x : array_like, dtype float or complex
|
Chris@87
|
2457 Argument of the Bessel function.
|
Chris@87
|
2458
|
Chris@87
|
2459 Returns
|
Chris@87
|
2460 -------
|
Chris@87
|
2461 out : ndarray, shape = x.shape, dtype = x.dtype
|
Chris@87
|
2462 The modified Bessel function evaluated at each of the elements of `x`.
|
Chris@87
|
2463
|
Chris@87
|
2464 Raises
|
Chris@87
|
2465 ------
|
Chris@87
|
2466 TypeError: array cannot be safely cast to required type
|
Chris@87
|
2467 If argument consists exclusively of int dtypes.
|
Chris@87
|
2468
|
Chris@87
|
2469 See Also
|
Chris@87
|
2470 --------
|
Chris@87
|
2471 scipy.special.iv, scipy.special.ive
|
Chris@87
|
2472
|
Chris@87
|
2473 Notes
|
Chris@87
|
2474 -----
|
Chris@87
|
2475 We use the algorithm published by Clenshaw [1]_ and referenced by
|
Chris@87
|
2476 Abramowitz and Stegun [2]_, for which the function domain is
|
Chris@87
|
2477 partitioned into the two intervals [0,8] and (8,inf), and Chebyshev
|
Chris@87
|
2478 polynomial expansions are employed in each interval. Relative error on
|
Chris@87
|
2479 the domain [0,30] using IEEE arithmetic is documented [3]_ as having a
|
Chris@87
|
2480 peak of 5.8e-16 with an rms of 1.4e-16 (n = 30000).
|
Chris@87
|
2481
|
Chris@87
|
2482 References
|
Chris@87
|
2483 ----------
|
Chris@87
|
2484 .. [1] C. W. Clenshaw, "Chebyshev series for mathematical functions", in
|
Chris@87
|
2485 *National Physical Laboratory Mathematical Tables*, vol. 5, London:
|
Chris@87
|
2486 Her Majesty's Stationery Office, 1962.
|
Chris@87
|
2487 .. [2] M. Abramowitz and I. A. Stegun, *Handbook of Mathematical
|
Chris@87
|
2488 Functions*, 10th printing, New York: Dover, 1964, pp. 379.
|
Chris@87
|
2489 http://www.math.sfu.ca/~cbm/aands/page_379.htm
|
Chris@87
|
2490 .. [3] http://kobesearch.cpan.org/htdocs/Math-Cephes/Math/Cephes.html
|
Chris@87
|
2491
|
Chris@87
|
2492 Examples
|
Chris@87
|
2493 --------
|
Chris@87
|
2494 >>> np.i0([0.])
|
Chris@87
|
2495 array(1.0)
|
Chris@87
|
2496 >>> np.i0([0., 1. + 2j])
|
Chris@87
|
2497 array([ 1.00000000+0.j , 0.18785373+0.64616944j])
|
Chris@87
|
2498
|
Chris@87
|
2499 """
|
Chris@87
|
2500 x = atleast_1d(x).copy()
|
Chris@87
|
2501 y = empty_like(x)
|
Chris@87
|
2502 ind = (x < 0)
|
Chris@87
|
2503 x[ind] = -x[ind]
|
Chris@87
|
2504 ind = (x <= 8.0)
|
Chris@87
|
2505 y[ind] = _i0_1(x[ind])
|
Chris@87
|
2506 ind2 = ~ind
|
Chris@87
|
2507 y[ind2] = _i0_2(x[ind2])
|
Chris@87
|
2508 return y.squeeze()
|
Chris@87
|
2509
|
Chris@87
|
2510 ## End of cephes code for i0
|
Chris@87
|
2511
|
Chris@87
|
2512
|
Chris@87
|
2513 def kaiser(M, beta):
|
Chris@87
|
2514 """
|
Chris@87
|
2515 Return the Kaiser window.
|
Chris@87
|
2516
|
Chris@87
|
2517 The Kaiser window is a taper formed by using a Bessel function.
|
Chris@87
|
2518
|
Chris@87
|
2519 Parameters
|
Chris@87
|
2520 ----------
|
Chris@87
|
2521 M : int
|
Chris@87
|
2522 Number of points in the output window. If zero or less, an
|
Chris@87
|
2523 empty array is returned.
|
Chris@87
|
2524 beta : float
|
Chris@87
|
2525 Shape parameter for window.
|
Chris@87
|
2526
|
Chris@87
|
2527 Returns
|
Chris@87
|
2528 -------
|
Chris@87
|
2529 out : array
|
Chris@87
|
2530 The window, with the maximum value normalized to one (the value
|
Chris@87
|
2531 one appears only if the number of samples is odd).
|
Chris@87
|
2532
|
Chris@87
|
2533 See Also
|
Chris@87
|
2534 --------
|
Chris@87
|
2535 bartlett, blackman, hamming, hanning
|
Chris@87
|
2536
|
Chris@87
|
2537 Notes
|
Chris@87
|
2538 -----
|
Chris@87
|
2539 The Kaiser window is defined as
|
Chris@87
|
2540
|
Chris@87
|
2541 .. math:: w(n) = I_0\\left( \\beta \\sqrt{1-\\frac{4n^2}{(M-1)^2}}
|
Chris@87
|
2542 \\right)/I_0(\\beta)
|
Chris@87
|
2543
|
Chris@87
|
2544 with
|
Chris@87
|
2545
|
Chris@87
|
2546 .. math:: \\quad -\\frac{M-1}{2} \\leq n \\leq \\frac{M-1}{2},
|
Chris@87
|
2547
|
Chris@87
|
2548 where :math:`I_0` is the modified zeroth-order Bessel function.
|
Chris@87
|
2549
|
Chris@87
|
2550 The Kaiser was named for Jim Kaiser, who discovered a simple
|
Chris@87
|
2551 approximation to the DPSS window based on Bessel functions. The Kaiser
|
Chris@87
|
2552 window is a very good approximation to the Digital Prolate Spheroidal
|
Chris@87
|
2553 Sequence, or Slepian window, which is the transform which maximizes the
|
Chris@87
|
2554 energy in the main lobe of the window relative to total energy.
|
Chris@87
|
2555
|
Chris@87
|
2556 The Kaiser can approximate many other windows by varying the beta
|
Chris@87
|
2557 parameter.
|
Chris@87
|
2558
|
Chris@87
|
2559 ==== =======================
|
Chris@87
|
2560 beta Window shape
|
Chris@87
|
2561 ==== =======================
|
Chris@87
|
2562 0 Rectangular
|
Chris@87
|
2563 5 Similar to a Hamming
|
Chris@87
|
2564 6 Similar to a Hanning
|
Chris@87
|
2565 8.6 Similar to a Blackman
|
Chris@87
|
2566 ==== =======================
|
Chris@87
|
2567
|
Chris@87
|
2568 A beta value of 14 is probably a good starting point. Note that as beta
|
Chris@87
|
2569 gets large, the window narrows, and so the number of samples needs to be
|
Chris@87
|
2570 large enough to sample the increasingly narrow spike, otherwise NaNs will
|
Chris@87
|
2571 get returned.
|
Chris@87
|
2572
|
Chris@87
|
2573 Most references to the Kaiser window come from the signal processing
|
Chris@87
|
2574 literature, where it is used as one of many windowing functions for
|
Chris@87
|
2575 smoothing values. It is also known as an apodization (which means
|
Chris@87
|
2576 "removing the foot", i.e. smoothing discontinuities at the beginning
|
Chris@87
|
2577 and end of the sampled signal) or tapering function.
|
Chris@87
|
2578
|
Chris@87
|
2579 References
|
Chris@87
|
2580 ----------
|
Chris@87
|
2581 .. [1] J. F. Kaiser, "Digital Filters" - Ch 7 in "Systems analysis by
|
Chris@87
|
2582 digital computer", Editors: F.F. Kuo and J.F. Kaiser, p 218-285.
|
Chris@87
|
2583 John Wiley and Sons, New York, (1966).
|
Chris@87
|
2584 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The
|
Chris@87
|
2585 University of Alberta Press, 1975, pp. 177-178.
|
Chris@87
|
2586 .. [3] Wikipedia, "Window function",
|
Chris@87
|
2587 http://en.wikipedia.org/wiki/Window_function
|
Chris@87
|
2588
|
Chris@87
|
2589 Examples
|
Chris@87
|
2590 --------
|
Chris@87
|
2591 >>> np.kaiser(12, 14)
|
Chris@87
|
2592 array([ 7.72686684e-06, 3.46009194e-03, 4.65200189e-02,
|
Chris@87
|
2593 2.29737120e-01, 5.99885316e-01, 9.45674898e-01,
|
Chris@87
|
2594 9.45674898e-01, 5.99885316e-01, 2.29737120e-01,
|
Chris@87
|
2595 4.65200189e-02, 3.46009194e-03, 7.72686684e-06])
|
Chris@87
|
2596
|
Chris@87
|
2597
|
Chris@87
|
2598 Plot the window and the frequency response:
|
Chris@87
|
2599
|
Chris@87
|
2600 >>> from numpy.fft import fft, fftshift
|
Chris@87
|
2601 >>> window = np.kaiser(51, 14)
|
Chris@87
|
2602 >>> plt.plot(window)
|
Chris@87
|
2603 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
2604 >>> plt.title("Kaiser window")
|
Chris@87
|
2605 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2606 >>> plt.ylabel("Amplitude")
|
Chris@87
|
2607 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2608 >>> plt.xlabel("Sample")
|
Chris@87
|
2609 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2610 >>> plt.show()
|
Chris@87
|
2611
|
Chris@87
|
2612 >>> plt.figure()
|
Chris@87
|
2613 <matplotlib.figure.Figure object at 0x...>
|
Chris@87
|
2614 >>> A = fft(window, 2048) / 25.5
|
Chris@87
|
2615 >>> mag = np.abs(fftshift(A))
|
Chris@87
|
2616 >>> freq = np.linspace(-0.5, 0.5, len(A))
|
Chris@87
|
2617 >>> response = 20 * np.log10(mag)
|
Chris@87
|
2618 >>> response = np.clip(response, -100, 100)
|
Chris@87
|
2619 >>> plt.plot(freq, response)
|
Chris@87
|
2620 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
2621 >>> plt.title("Frequency response of Kaiser window")
|
Chris@87
|
2622 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2623 >>> plt.ylabel("Magnitude [dB]")
|
Chris@87
|
2624 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2625 >>> plt.xlabel("Normalized frequency [cycles per sample]")
|
Chris@87
|
2626 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2627 >>> plt.axis('tight')
|
Chris@87
|
2628 (-0.5, 0.5, -100.0, ...)
|
Chris@87
|
2629 >>> plt.show()
|
Chris@87
|
2630
|
Chris@87
|
2631 """
|
Chris@87
|
2632 from numpy.dual import i0
|
Chris@87
|
2633 if M == 1:
|
Chris@87
|
2634 return np.array([1.])
|
Chris@87
|
2635 n = arange(0, M)
|
Chris@87
|
2636 alpha = (M-1)/2.0
|
Chris@87
|
2637 return i0(beta * sqrt(1-((n-alpha)/alpha)**2.0))/i0(float(beta))
|
Chris@87
|
2638
|
Chris@87
|
2639
|
Chris@87
|
2640 def sinc(x):
|
Chris@87
|
2641 """
|
Chris@87
|
2642 Return the sinc function.
|
Chris@87
|
2643
|
Chris@87
|
2644 The sinc function is :math:`\\sin(\\pi x)/(\\pi x)`.
|
Chris@87
|
2645
|
Chris@87
|
2646 Parameters
|
Chris@87
|
2647 ----------
|
Chris@87
|
2648 x : ndarray
|
Chris@87
|
2649 Array (possibly multi-dimensional) of values for which to to
|
Chris@87
|
2650 calculate ``sinc(x)``.
|
Chris@87
|
2651
|
Chris@87
|
2652 Returns
|
Chris@87
|
2653 -------
|
Chris@87
|
2654 out : ndarray
|
Chris@87
|
2655 ``sinc(x)``, which has the same shape as the input.
|
Chris@87
|
2656
|
Chris@87
|
2657 Notes
|
Chris@87
|
2658 -----
|
Chris@87
|
2659 ``sinc(0)`` is the limit value 1.
|
Chris@87
|
2660
|
Chris@87
|
2661 The name sinc is short for "sine cardinal" or "sinus cardinalis".
|
Chris@87
|
2662
|
Chris@87
|
2663 The sinc function is used in various signal processing applications,
|
Chris@87
|
2664 including in anti-aliasing, in the construction of a Lanczos resampling
|
Chris@87
|
2665 filter, and in interpolation.
|
Chris@87
|
2666
|
Chris@87
|
2667 For bandlimited interpolation of discrete-time signals, the ideal
|
Chris@87
|
2668 interpolation kernel is proportional to the sinc function.
|
Chris@87
|
2669
|
Chris@87
|
2670 References
|
Chris@87
|
2671 ----------
|
Chris@87
|
2672 .. [1] Weisstein, Eric W. "Sinc Function." From MathWorld--A Wolfram Web
|
Chris@87
|
2673 Resource. http://mathworld.wolfram.com/SincFunction.html
|
Chris@87
|
2674 .. [2] Wikipedia, "Sinc function",
|
Chris@87
|
2675 http://en.wikipedia.org/wiki/Sinc_function
|
Chris@87
|
2676
|
Chris@87
|
2677 Examples
|
Chris@87
|
2678 --------
|
Chris@87
|
2679 >>> x = np.linspace(-4, 4, 41)
|
Chris@87
|
2680 >>> np.sinc(x)
|
Chris@87
|
2681 array([ -3.89804309e-17, -4.92362781e-02, -8.40918587e-02,
|
Chris@87
|
2682 -8.90384387e-02, -5.84680802e-02, 3.89804309e-17,
|
Chris@87
|
2683 6.68206631e-02, 1.16434881e-01, 1.26137788e-01,
|
Chris@87
|
2684 8.50444803e-02, -3.89804309e-17, -1.03943254e-01,
|
Chris@87
|
2685 -1.89206682e-01, -2.16236208e-01, -1.55914881e-01,
|
Chris@87
|
2686 3.89804309e-17, 2.33872321e-01, 5.04551152e-01,
|
Chris@87
|
2687 7.56826729e-01, 9.35489284e-01, 1.00000000e+00,
|
Chris@87
|
2688 9.35489284e-01, 7.56826729e-01, 5.04551152e-01,
|
Chris@87
|
2689 2.33872321e-01, 3.89804309e-17, -1.55914881e-01,
|
Chris@87
|
2690 -2.16236208e-01, -1.89206682e-01, -1.03943254e-01,
|
Chris@87
|
2691 -3.89804309e-17, 8.50444803e-02, 1.26137788e-01,
|
Chris@87
|
2692 1.16434881e-01, 6.68206631e-02, 3.89804309e-17,
|
Chris@87
|
2693 -5.84680802e-02, -8.90384387e-02, -8.40918587e-02,
|
Chris@87
|
2694 -4.92362781e-02, -3.89804309e-17])
|
Chris@87
|
2695
|
Chris@87
|
2696 >>> plt.plot(x, np.sinc(x))
|
Chris@87
|
2697 [<matplotlib.lines.Line2D object at 0x...>]
|
Chris@87
|
2698 >>> plt.title("Sinc Function")
|
Chris@87
|
2699 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2700 >>> plt.ylabel("Amplitude")
|
Chris@87
|
2701 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2702 >>> plt.xlabel("X")
|
Chris@87
|
2703 <matplotlib.text.Text object at 0x...>
|
Chris@87
|
2704 >>> plt.show()
|
Chris@87
|
2705
|
Chris@87
|
2706 It works in 2-D as well:
|
Chris@87
|
2707
|
Chris@87
|
2708 >>> x = np.linspace(-4, 4, 401)
|
Chris@87
|
2709 >>> xx = np.outer(x, x)
|
Chris@87
|
2710 >>> plt.imshow(np.sinc(xx))
|
Chris@87
|
2711 <matplotlib.image.AxesImage object at 0x...>
|
Chris@87
|
2712
|
Chris@87
|
2713 """
|
Chris@87
|
2714 x = np.asanyarray(x)
|
Chris@87
|
2715 y = pi * where(x == 0, 1.0e-20, x)
|
Chris@87
|
2716 return sin(y)/y
|
Chris@87
|
2717
|
Chris@87
|
2718
|
Chris@87
|
2719 def msort(a):
|
Chris@87
|
2720 """
|
Chris@87
|
2721 Return a copy of an array sorted along the first axis.
|
Chris@87
|
2722
|
Chris@87
|
2723 Parameters
|
Chris@87
|
2724 ----------
|
Chris@87
|
2725 a : array_like
|
Chris@87
|
2726 Array to be sorted.
|
Chris@87
|
2727
|
Chris@87
|
2728 Returns
|
Chris@87
|
2729 -------
|
Chris@87
|
2730 sorted_array : ndarray
|
Chris@87
|
2731 Array of the same type and shape as `a`.
|
Chris@87
|
2732
|
Chris@87
|
2733 See Also
|
Chris@87
|
2734 --------
|
Chris@87
|
2735 sort
|
Chris@87
|
2736
|
Chris@87
|
2737 Notes
|
Chris@87
|
2738 -----
|
Chris@87
|
2739 ``np.msort(a)`` is equivalent to ``np.sort(a, axis=0)``.
|
Chris@87
|
2740
|
Chris@87
|
2741 """
|
Chris@87
|
2742 b = array(a, subok=True, copy=True)
|
Chris@87
|
2743 b.sort(0)
|
Chris@87
|
2744 return b
|
Chris@87
|
2745
|
Chris@87
|
2746
|
Chris@87
|
2747 def _ureduce(a, func, **kwargs):
|
Chris@87
|
2748 """
|
Chris@87
|
2749 Internal Function.
|
Chris@87
|
2750 Call `func` with `a` as first argument swapping the axes to use extended
|
Chris@87
|
2751 axis on functions that don't support it natively.
|
Chris@87
|
2752
|
Chris@87
|
2753 Returns result and a.shape with axis dims set to 1.
|
Chris@87
|
2754
|
Chris@87
|
2755 Parameters
|
Chris@87
|
2756 ----------
|
Chris@87
|
2757 a : array_like
|
Chris@87
|
2758 Input array or object that can be converted to an array.
|
Chris@87
|
2759 func : callable
|
Chris@87
|
2760 Reduction function Kapable of receiving an axis argument.
|
Chris@87
|
2761 It is is called with `a` as first argument followed by `kwargs`.
|
Chris@87
|
2762 kwargs : keyword arguments
|
Chris@87
|
2763 additional keyword arguments to pass to `func`.
|
Chris@87
|
2764
|
Chris@87
|
2765 Returns
|
Chris@87
|
2766 -------
|
Chris@87
|
2767 result : tuple
|
Chris@87
|
2768 Result of func(a, **kwargs) and a.shape with axis dims set to 1
|
Chris@87
|
2769 which can be used to reshape the result to the same shape a ufunc with
|
Chris@87
|
2770 keepdims=True would produce.
|
Chris@87
|
2771
|
Chris@87
|
2772 """
|
Chris@87
|
2773 a = np.asanyarray(a)
|
Chris@87
|
2774 axis = kwargs.get('axis', None)
|
Chris@87
|
2775 if axis is not None:
|
Chris@87
|
2776 keepdim = list(a.shape)
|
Chris@87
|
2777 nd = a.ndim
|
Chris@87
|
2778 try:
|
Chris@87
|
2779 axis = operator.index(axis)
|
Chris@87
|
2780 if axis >= nd or axis < -nd:
|
Chris@87
|
2781 raise IndexError("axis %d out of bounds (%d)" % (axis, a.ndim))
|
Chris@87
|
2782 keepdim[axis] = 1
|
Chris@87
|
2783 except TypeError:
|
Chris@87
|
2784 sax = set()
|
Chris@87
|
2785 for x in axis:
|
Chris@87
|
2786 if x >= nd or x < -nd:
|
Chris@87
|
2787 raise IndexError("axis %d out of bounds (%d)" % (x, nd))
|
Chris@87
|
2788 if x in sax:
|
Chris@87
|
2789 raise ValueError("duplicate value in axis")
|
Chris@87
|
2790 sax.add(x % nd)
|
Chris@87
|
2791 keepdim[x] = 1
|
Chris@87
|
2792 keep = sax.symmetric_difference(frozenset(range(nd)))
|
Chris@87
|
2793 nkeep = len(keep)
|
Chris@87
|
2794 # swap axis that should not be reduced to front
|
Chris@87
|
2795 for i, s in enumerate(sorted(keep)):
|
Chris@87
|
2796 a = a.swapaxes(i, s)
|
Chris@87
|
2797 # merge reduced axis
|
Chris@87
|
2798 a = a.reshape(a.shape[:nkeep] + (-1,))
|
Chris@87
|
2799 kwargs['axis'] = -1
|
Chris@87
|
2800 else:
|
Chris@87
|
2801 keepdim = [1] * a.ndim
|
Chris@87
|
2802
|
Chris@87
|
2803 r = func(a, **kwargs)
|
Chris@87
|
2804 return r, keepdim
|
Chris@87
|
2805
|
Chris@87
|
2806
|
Chris@87
|
2807 def median(a, axis=None, out=None, overwrite_input=False, keepdims=False):
|
Chris@87
|
2808 """
|
Chris@87
|
2809 Compute the median along the specified axis.
|
Chris@87
|
2810
|
Chris@87
|
2811 Returns the median of the array elements.
|
Chris@87
|
2812
|
Chris@87
|
2813 Parameters
|
Chris@87
|
2814 ----------
|
Chris@87
|
2815 a : array_like
|
Chris@87
|
2816 Input array or object that can be converted to an array.
|
Chris@87
|
2817 axis : int or sequence of int, optional
|
Chris@87
|
2818 Axis along which the medians are computed. The default (axis=None)
|
Chris@87
|
2819 is to compute the median along a flattened version of the array.
|
Chris@87
|
2820 A sequence of axes is supported since version 1.9.0.
|
Chris@87
|
2821 out : ndarray, optional
|
Chris@87
|
2822 Alternative output array in which to place the result. It must have
|
Chris@87
|
2823 the same shape and buffer length as the expected output, but the
|
Chris@87
|
2824 type (of the output) will be cast if necessary.
|
Chris@87
|
2825 overwrite_input : bool, optional
|
Chris@87
|
2826 If True, then allow use of memory of input array (a) for
|
Chris@87
|
2827 calculations. The input array will be modified by the call to
|
Chris@87
|
2828 median. This will save memory when you do not need to preserve the
|
Chris@87
|
2829 contents of the input array. Treat the input as undefined, but it
|
Chris@87
|
2830 will probably be fully or partially sorted. Default is False. Note
|
Chris@87
|
2831 that, if `overwrite_input` is True and the input is not already an
|
Chris@87
|
2832 ndarray, an error will be raised.
|
Chris@87
|
2833 keepdims : bool, optional
|
Chris@87
|
2834 If this is set to True, the axes which are reduced are left
|
Chris@87
|
2835 in the result as dimensions with size one. With this option,
|
Chris@87
|
2836 the result will broadcast correctly against the original `arr`.
|
Chris@87
|
2837
|
Chris@87
|
2838 .. versionadded:: 1.9.0
|
Chris@87
|
2839
|
Chris@87
|
2840
|
Chris@87
|
2841 Returns
|
Chris@87
|
2842 -------
|
Chris@87
|
2843 median : ndarray
|
Chris@87
|
2844 A new array holding the result (unless `out` is specified, in which
|
Chris@87
|
2845 case that array is returned instead). If the input contains
|
Chris@87
|
2846 integers, or floats of smaller precision than 64, then the output
|
Chris@87
|
2847 data-type is float64. Otherwise, the output data-type is the same
|
Chris@87
|
2848 as that of the input.
|
Chris@87
|
2849
|
Chris@87
|
2850 See Also
|
Chris@87
|
2851 --------
|
Chris@87
|
2852 mean, percentile
|
Chris@87
|
2853
|
Chris@87
|
2854 Notes
|
Chris@87
|
2855 -----
|
Chris@87
|
2856 Given a vector V of length N, the median of V is the middle value of
|
Chris@87
|
2857 a sorted copy of V, ``V_sorted`` - i.e., ``V_sorted[(N-1)/2]``, when N is
|
Chris@87
|
2858 odd. When N is even, it is the average of the two middle values of
|
Chris@87
|
2859 ``V_sorted``.
|
Chris@87
|
2860
|
Chris@87
|
2861 Examples
|
Chris@87
|
2862 --------
|
Chris@87
|
2863 >>> a = np.array([[10, 7, 4], [3, 2, 1]])
|
Chris@87
|
2864 >>> a
|
Chris@87
|
2865 array([[10, 7, 4],
|
Chris@87
|
2866 [ 3, 2, 1]])
|
Chris@87
|
2867 >>> np.median(a)
|
Chris@87
|
2868 3.5
|
Chris@87
|
2869 >>> np.median(a, axis=0)
|
Chris@87
|
2870 array([ 6.5, 4.5, 2.5])
|
Chris@87
|
2871 >>> np.median(a, axis=1)
|
Chris@87
|
2872 array([ 7., 2.])
|
Chris@87
|
2873 >>> m = np.median(a, axis=0)
|
Chris@87
|
2874 >>> out = np.zeros_like(m)
|
Chris@87
|
2875 >>> np.median(a, axis=0, out=m)
|
Chris@87
|
2876 array([ 6.5, 4.5, 2.5])
|
Chris@87
|
2877 >>> m
|
Chris@87
|
2878 array([ 6.5, 4.5, 2.5])
|
Chris@87
|
2879 >>> b = a.copy()
|
Chris@87
|
2880 >>> np.median(b, axis=1, overwrite_input=True)
|
Chris@87
|
2881 array([ 7., 2.])
|
Chris@87
|
2882 >>> assert not np.all(a==b)
|
Chris@87
|
2883 >>> b = a.copy()
|
Chris@87
|
2884 >>> np.median(b, axis=None, overwrite_input=True)
|
Chris@87
|
2885 3.5
|
Chris@87
|
2886 >>> assert not np.all(a==b)
|
Chris@87
|
2887
|
Chris@87
|
2888 """
|
Chris@87
|
2889 r, k = _ureduce(a, func=_median, axis=axis, out=out,
|
Chris@87
|
2890 overwrite_input=overwrite_input)
|
Chris@87
|
2891 if keepdims:
|
Chris@87
|
2892 return r.reshape(k)
|
Chris@87
|
2893 else:
|
Chris@87
|
2894 return r
|
Chris@87
|
2895
|
Chris@87
|
2896 def _median(a, axis=None, out=None, overwrite_input=False):
|
Chris@87
|
2897 # can't be reasonably be implemented in terms of percentile as we have to
|
Chris@87
|
2898 # call mean to not break astropy
|
Chris@87
|
2899 a = np.asanyarray(a)
|
Chris@87
|
2900 if axis is not None and axis >= a.ndim:
|
Chris@87
|
2901 raise IndexError(
|
Chris@87
|
2902 "axis %d out of bounds (%d)" % (axis, a.ndim))
|
Chris@87
|
2903
|
Chris@87
|
2904 if overwrite_input:
|
Chris@87
|
2905 if axis is None:
|
Chris@87
|
2906 part = a.ravel()
|
Chris@87
|
2907 sz = part.size
|
Chris@87
|
2908 if sz % 2 == 0:
|
Chris@87
|
2909 szh = sz // 2
|
Chris@87
|
2910 part.partition((szh - 1, szh))
|
Chris@87
|
2911 else:
|
Chris@87
|
2912 part.partition((sz - 1) // 2)
|
Chris@87
|
2913 else:
|
Chris@87
|
2914 sz = a.shape[axis]
|
Chris@87
|
2915 if sz % 2 == 0:
|
Chris@87
|
2916 szh = sz // 2
|
Chris@87
|
2917 a.partition((szh - 1, szh), axis=axis)
|
Chris@87
|
2918 else:
|
Chris@87
|
2919 a.partition((sz - 1) // 2, axis=axis)
|
Chris@87
|
2920 part = a
|
Chris@87
|
2921 else:
|
Chris@87
|
2922 if axis is None:
|
Chris@87
|
2923 sz = a.size
|
Chris@87
|
2924 else:
|
Chris@87
|
2925 sz = a.shape[axis]
|
Chris@87
|
2926 if sz % 2 == 0:
|
Chris@87
|
2927 part = partition(a, ((sz // 2) - 1, sz // 2), axis=axis)
|
Chris@87
|
2928 else:
|
Chris@87
|
2929 part = partition(a, (sz - 1) // 2, axis=axis)
|
Chris@87
|
2930 if part.shape == ():
|
Chris@87
|
2931 # make 0-D arrays work
|
Chris@87
|
2932 return part.item()
|
Chris@87
|
2933 if axis is None:
|
Chris@87
|
2934 axis = 0
|
Chris@87
|
2935 indexer = [slice(None)] * part.ndim
|
Chris@87
|
2936 index = part.shape[axis] // 2
|
Chris@87
|
2937 if part.shape[axis] % 2 == 1:
|
Chris@87
|
2938 # index with slice to allow mean (below) to work
|
Chris@87
|
2939 indexer[axis] = slice(index, index+1)
|
Chris@87
|
2940 else:
|
Chris@87
|
2941 indexer[axis] = slice(index-1, index+1)
|
Chris@87
|
2942 # Use mean in odd and even case to coerce data type
|
Chris@87
|
2943 # and check, use out array.
|
Chris@87
|
2944 return mean(part[indexer], axis=axis, out=out)
|
Chris@87
|
2945
|
Chris@87
|
2946
|
Chris@87
|
2947 def percentile(a, q, axis=None, out=None,
|
Chris@87
|
2948 overwrite_input=False, interpolation='linear', keepdims=False):
|
Chris@87
|
2949 """
|
Chris@87
|
2950 Compute the qth percentile of the data along the specified axis.
|
Chris@87
|
2951
|
Chris@87
|
2952 Returns the qth percentile of the array elements.
|
Chris@87
|
2953
|
Chris@87
|
2954 Parameters
|
Chris@87
|
2955 ----------
|
Chris@87
|
2956 a : array_like
|
Chris@87
|
2957 Input array or object that can be converted to an array.
|
Chris@87
|
2958 q : float in range of [0,100] (or sequence of floats)
|
Chris@87
|
2959 Percentile to compute which must be between 0 and 100 inclusive.
|
Chris@87
|
2960 axis : int or sequence of int, optional
|
Chris@87
|
2961 Axis along which the percentiles are computed. The default (None)
|
Chris@87
|
2962 is to compute the percentiles along a flattened version of the array.
|
Chris@87
|
2963 A sequence of axes is supported since version 1.9.0.
|
Chris@87
|
2964 out : ndarray, optional
|
Chris@87
|
2965 Alternative output array in which to place the result. It must
|
Chris@87
|
2966 have the same shape and buffer length as the expected output,
|
Chris@87
|
2967 but the type (of the output) will be cast if necessary.
|
Chris@87
|
2968 overwrite_input : bool, optional
|
Chris@87
|
2969 If True, then allow use of memory of input array `a` for
|
Chris@87
|
2970 calculations. The input array will be modified by the call to
|
Chris@87
|
2971 percentile. This will save memory when you do not need to preserve
|
Chris@87
|
2972 the contents of the input array. In this case you should not make
|
Chris@87
|
2973 any assumptions about the content of the passed in array `a` after
|
Chris@87
|
2974 this function completes -- treat it as undefined. Default is False.
|
Chris@87
|
2975 Note that, if the `a` input is not already an array this parameter
|
Chris@87
|
2976 will have no effect, `a` will be converted to an array internally
|
Chris@87
|
2977 regardless of the value of this parameter.
|
Chris@87
|
2978 interpolation : {'linear', 'lower', 'higher', 'midpoint', 'nearest'}
|
Chris@87
|
2979 This optional parameter specifies the interpolation method to use,
|
Chris@87
|
2980 when the desired quantile lies between two data points `i` and `j`:
|
Chris@87
|
2981 * linear: `i + (j - i) * fraction`, where `fraction` is the
|
Chris@87
|
2982 fractional part of the index surrounded by `i` and `j`.
|
Chris@87
|
2983 * lower: `i`.
|
Chris@87
|
2984 * higher: `j`.
|
Chris@87
|
2985 * nearest: `i` or `j` whichever is nearest.
|
Chris@87
|
2986 * midpoint: (`i` + `j`) / 2.
|
Chris@87
|
2987
|
Chris@87
|
2988 .. versionadded:: 1.9.0
|
Chris@87
|
2989 keepdims : bool, optional
|
Chris@87
|
2990 If this is set to True, the axes which are reduced are left
|
Chris@87
|
2991 in the result as dimensions with size one. With this option,
|
Chris@87
|
2992 the result will broadcast correctly against the original `arr`.
|
Chris@87
|
2993
|
Chris@87
|
2994 .. versionadded:: 1.9.0
|
Chris@87
|
2995
|
Chris@87
|
2996 Returns
|
Chris@87
|
2997 -------
|
Chris@87
|
2998 percentile : scalar or ndarray
|
Chris@87
|
2999 If a single percentile `q` is given and axis=None a scalar is
|
Chris@87
|
3000 returned. If multiple percentiles `q` are given an array holding
|
Chris@87
|
3001 the result is returned. The results are listed in the first axis.
|
Chris@87
|
3002 (If `out` is specified, in which case that array is returned
|
Chris@87
|
3003 instead). If the input contains integers, or floats of smaller
|
Chris@87
|
3004 precision than 64, then the output data-type is float64. Otherwise,
|
Chris@87
|
3005 the output data-type is the same as that of the input.
|
Chris@87
|
3006
|
Chris@87
|
3007 See Also
|
Chris@87
|
3008 --------
|
Chris@87
|
3009 mean, median
|
Chris@87
|
3010
|
Chris@87
|
3011 Notes
|
Chris@87
|
3012 -----
|
Chris@87
|
3013 Given a vector V of length N, the q-th percentile of V is the q-th ranked
|
Chris@87
|
3014 value in a sorted copy of V. The values and distances of the two
|
Chris@87
|
3015 nearest neighbors as well as the `interpolation` parameter will
|
Chris@87
|
3016 determine the percentile if the normalized ranking does not match q
|
Chris@87
|
3017 exactly. This function is the same as the median if ``q=50``, the same
|
Chris@87
|
3018 as the minimum if ``q=0`` and the same as the maximum if ``q=100``.
|
Chris@87
|
3019
|
Chris@87
|
3020 Examples
|
Chris@87
|
3021 --------
|
Chris@87
|
3022 >>> a = np.array([[10, 7, 4], [3, 2, 1]])
|
Chris@87
|
3023 >>> a
|
Chris@87
|
3024 array([[10, 7, 4],
|
Chris@87
|
3025 [ 3, 2, 1]])
|
Chris@87
|
3026 >>> np.percentile(a, 50)
|
Chris@87
|
3027 array([ 3.5])
|
Chris@87
|
3028 >>> np.percentile(a, 50, axis=0)
|
Chris@87
|
3029 array([[ 6.5, 4.5, 2.5]])
|
Chris@87
|
3030 >>> np.percentile(a, 50, axis=1)
|
Chris@87
|
3031 array([[ 7.],
|
Chris@87
|
3032 [ 2.]])
|
Chris@87
|
3033
|
Chris@87
|
3034 >>> m = np.percentile(a, 50, axis=0)
|
Chris@87
|
3035 >>> out = np.zeros_like(m)
|
Chris@87
|
3036 >>> np.percentile(a, 50, axis=0, out=m)
|
Chris@87
|
3037 array([[ 6.5, 4.5, 2.5]])
|
Chris@87
|
3038 >>> m
|
Chris@87
|
3039 array([[ 6.5, 4.5, 2.5]])
|
Chris@87
|
3040
|
Chris@87
|
3041 >>> b = a.copy()
|
Chris@87
|
3042 >>> np.percentile(b, 50, axis=1, overwrite_input=True)
|
Chris@87
|
3043 array([[ 7.],
|
Chris@87
|
3044 [ 2.]])
|
Chris@87
|
3045 >>> assert not np.all(a==b)
|
Chris@87
|
3046 >>> b = a.copy()
|
Chris@87
|
3047 >>> np.percentile(b, 50, axis=None, overwrite_input=True)
|
Chris@87
|
3048 array([ 3.5])
|
Chris@87
|
3049
|
Chris@87
|
3050 """
|
Chris@87
|
3051 q = array(q, dtype=np.float64, copy=True)
|
Chris@87
|
3052 r, k = _ureduce(a, func=_percentile, q=q, axis=axis, out=out,
|
Chris@87
|
3053 overwrite_input=overwrite_input,
|
Chris@87
|
3054 interpolation=interpolation)
|
Chris@87
|
3055 if keepdims:
|
Chris@87
|
3056 if q.ndim == 0:
|
Chris@87
|
3057 return r.reshape(k)
|
Chris@87
|
3058 else:
|
Chris@87
|
3059 return r.reshape([len(q)] + k)
|
Chris@87
|
3060 else:
|
Chris@87
|
3061 return r
|
Chris@87
|
3062
|
Chris@87
|
3063
|
Chris@87
|
3064 def _percentile(a, q, axis=None, out=None,
|
Chris@87
|
3065 overwrite_input=False, interpolation='linear', keepdims=False):
|
Chris@87
|
3066 a = asarray(a)
|
Chris@87
|
3067 if q.ndim == 0:
|
Chris@87
|
3068 # Do not allow 0-d arrays because following code fails for scalar
|
Chris@87
|
3069 zerod = True
|
Chris@87
|
3070 q = q[None]
|
Chris@87
|
3071 else:
|
Chris@87
|
3072 zerod = False
|
Chris@87
|
3073
|
Chris@87
|
3074 # avoid expensive reductions, relevant for arrays with < O(1000) elements
|
Chris@87
|
3075 if q.size < 10:
|
Chris@87
|
3076 for i in range(q.size):
|
Chris@87
|
3077 if q[i] < 0. or q[i] > 100.:
|
Chris@87
|
3078 raise ValueError("Percentiles must be in the range [0,100]")
|
Chris@87
|
3079 q[i] /= 100.
|
Chris@87
|
3080 else:
|
Chris@87
|
3081 # faster than any()
|
Chris@87
|
3082 if np.count_nonzero(q < 0.) or np.count_nonzero(q > 100.):
|
Chris@87
|
3083 raise ValueError("Percentiles must be in the range [0,100]")
|
Chris@87
|
3084 q /= 100.
|
Chris@87
|
3085
|
Chris@87
|
3086 # prepare a for partioning
|
Chris@87
|
3087 if overwrite_input:
|
Chris@87
|
3088 if axis is None:
|
Chris@87
|
3089 ap = a.ravel()
|
Chris@87
|
3090 else:
|
Chris@87
|
3091 ap = a
|
Chris@87
|
3092 else:
|
Chris@87
|
3093 if axis is None:
|
Chris@87
|
3094 ap = a.flatten()
|
Chris@87
|
3095 else:
|
Chris@87
|
3096 ap = a.copy()
|
Chris@87
|
3097
|
Chris@87
|
3098 if axis is None:
|
Chris@87
|
3099 axis = 0
|
Chris@87
|
3100
|
Chris@87
|
3101 Nx = ap.shape[axis]
|
Chris@87
|
3102 indices = q * (Nx - 1)
|
Chris@87
|
3103
|
Chris@87
|
3104 # round fractional indices according to interpolation method
|
Chris@87
|
3105 if interpolation == 'lower':
|
Chris@87
|
3106 indices = floor(indices).astype(intp)
|
Chris@87
|
3107 elif interpolation == 'higher':
|
Chris@87
|
3108 indices = ceil(indices).astype(intp)
|
Chris@87
|
3109 elif interpolation == 'midpoint':
|
Chris@87
|
3110 indices = floor(indices) + 0.5
|
Chris@87
|
3111 elif interpolation == 'nearest':
|
Chris@87
|
3112 indices = around(indices).astype(intp)
|
Chris@87
|
3113 elif interpolation == 'linear':
|
Chris@87
|
3114 pass # keep index as fraction and interpolate
|
Chris@87
|
3115 else:
|
Chris@87
|
3116 raise ValueError(
|
Chris@87
|
3117 "interpolation can only be 'linear', 'lower' 'higher', "
|
Chris@87
|
3118 "'midpoint', or 'nearest'")
|
Chris@87
|
3119
|
Chris@87
|
3120 if indices.dtype == intp: # take the points along axis
|
Chris@87
|
3121 ap.partition(indices, axis=axis)
|
Chris@87
|
3122 # ensure axis with qth is first
|
Chris@87
|
3123 ap = np.rollaxis(ap, axis, 0)
|
Chris@87
|
3124 axis = 0
|
Chris@87
|
3125
|
Chris@87
|
3126 if zerod:
|
Chris@87
|
3127 indices = indices[0]
|
Chris@87
|
3128 r = take(ap, indices, axis=axis, out=out)
|
Chris@87
|
3129 else: # weight the points above and below the indices
|
Chris@87
|
3130 indices_below = floor(indices).astype(intp)
|
Chris@87
|
3131 indices_above = indices_below + 1
|
Chris@87
|
3132 indices_above[indices_above > Nx - 1] = Nx - 1
|
Chris@87
|
3133
|
Chris@87
|
3134 weights_above = indices - indices_below
|
Chris@87
|
3135 weights_below = 1.0 - weights_above
|
Chris@87
|
3136
|
Chris@87
|
3137 weights_shape = [1, ] * ap.ndim
|
Chris@87
|
3138 weights_shape[axis] = len(indices)
|
Chris@87
|
3139 weights_below.shape = weights_shape
|
Chris@87
|
3140 weights_above.shape = weights_shape
|
Chris@87
|
3141
|
Chris@87
|
3142 ap.partition(concatenate((indices_below, indices_above)), axis=axis)
|
Chris@87
|
3143 x1 = take(ap, indices_below, axis=axis) * weights_below
|
Chris@87
|
3144 x2 = take(ap, indices_above, axis=axis) * weights_above
|
Chris@87
|
3145
|
Chris@87
|
3146 # ensure axis with qth is first
|
Chris@87
|
3147 x1 = np.rollaxis(x1, axis, 0)
|
Chris@87
|
3148 x2 = np.rollaxis(x2, axis, 0)
|
Chris@87
|
3149
|
Chris@87
|
3150 if zerod:
|
Chris@87
|
3151 x1 = x1.squeeze(0)
|
Chris@87
|
3152 x2 = x2.squeeze(0)
|
Chris@87
|
3153
|
Chris@87
|
3154 if out is not None:
|
Chris@87
|
3155 r = add(x1, x2, out=out)
|
Chris@87
|
3156 else:
|
Chris@87
|
3157 r = add(x1, x2)
|
Chris@87
|
3158
|
Chris@87
|
3159 return r
|
Chris@87
|
3160
|
Chris@87
|
3161
|
Chris@87
|
3162 def trapz(y, x=None, dx=1.0, axis=-1):
|
Chris@87
|
3163 """
|
Chris@87
|
3164 Integrate along the given axis using the composite trapezoidal rule.
|
Chris@87
|
3165
|
Chris@87
|
3166 Integrate `y` (`x`) along given axis.
|
Chris@87
|
3167
|
Chris@87
|
3168 Parameters
|
Chris@87
|
3169 ----------
|
Chris@87
|
3170 y : array_like
|
Chris@87
|
3171 Input array to integrate.
|
Chris@87
|
3172 x : array_like, optional
|
Chris@87
|
3173 If `x` is None, then spacing between all `y` elements is `dx`.
|
Chris@87
|
3174 dx : scalar, optional
|
Chris@87
|
3175 If `x` is None, spacing given by `dx` is assumed. Default is 1.
|
Chris@87
|
3176 axis : int, optional
|
Chris@87
|
3177 Specify the axis.
|
Chris@87
|
3178
|
Chris@87
|
3179 Returns
|
Chris@87
|
3180 -------
|
Chris@87
|
3181 trapz : float
|
Chris@87
|
3182 Definite integral as approximated by trapezoidal rule.
|
Chris@87
|
3183
|
Chris@87
|
3184 See Also
|
Chris@87
|
3185 --------
|
Chris@87
|
3186 sum, cumsum
|
Chris@87
|
3187
|
Chris@87
|
3188 Notes
|
Chris@87
|
3189 -----
|
Chris@87
|
3190 Image [2]_ illustrates trapezoidal rule -- y-axis locations of points
|
Chris@87
|
3191 will be taken from `y` array, by default x-axis distances between
|
Chris@87
|
3192 points will be 1.0, alternatively they can be provided with `x` array
|
Chris@87
|
3193 or with `dx` scalar. Return value will be equal to combined area under
|
Chris@87
|
3194 the red lines.
|
Chris@87
|
3195
|
Chris@87
|
3196
|
Chris@87
|
3197 References
|
Chris@87
|
3198 ----------
|
Chris@87
|
3199 .. [1] Wikipedia page: http://en.wikipedia.org/wiki/Trapezoidal_rule
|
Chris@87
|
3200
|
Chris@87
|
3201 .. [2] Illustration image:
|
Chris@87
|
3202 http://en.wikipedia.org/wiki/File:Composite_trapezoidal_rule_illustration.png
|
Chris@87
|
3203
|
Chris@87
|
3204 Examples
|
Chris@87
|
3205 --------
|
Chris@87
|
3206 >>> np.trapz([1,2,3])
|
Chris@87
|
3207 4.0
|
Chris@87
|
3208 >>> np.trapz([1,2,3], x=[4,6,8])
|
Chris@87
|
3209 8.0
|
Chris@87
|
3210 >>> np.trapz([1,2,3], dx=2)
|
Chris@87
|
3211 8.0
|
Chris@87
|
3212 >>> a = np.arange(6).reshape(2, 3)
|
Chris@87
|
3213 >>> a
|
Chris@87
|
3214 array([[0, 1, 2],
|
Chris@87
|
3215 [3, 4, 5]])
|
Chris@87
|
3216 >>> np.trapz(a, axis=0)
|
Chris@87
|
3217 array([ 1.5, 2.5, 3.5])
|
Chris@87
|
3218 >>> np.trapz(a, axis=1)
|
Chris@87
|
3219 array([ 2., 8.])
|
Chris@87
|
3220
|
Chris@87
|
3221 """
|
Chris@87
|
3222 y = asanyarray(y)
|
Chris@87
|
3223 if x is None:
|
Chris@87
|
3224 d = dx
|
Chris@87
|
3225 else:
|
Chris@87
|
3226 x = asanyarray(x)
|
Chris@87
|
3227 if x.ndim == 1:
|
Chris@87
|
3228 d = diff(x)
|
Chris@87
|
3229 # reshape to correct shape
|
Chris@87
|
3230 shape = [1]*y.ndim
|
Chris@87
|
3231 shape[axis] = d.shape[0]
|
Chris@87
|
3232 d = d.reshape(shape)
|
Chris@87
|
3233 else:
|
Chris@87
|
3234 d = diff(x, axis=axis)
|
Chris@87
|
3235 nd = len(y.shape)
|
Chris@87
|
3236 slice1 = [slice(None)]*nd
|
Chris@87
|
3237 slice2 = [slice(None)]*nd
|
Chris@87
|
3238 slice1[axis] = slice(1, None)
|
Chris@87
|
3239 slice2[axis] = slice(None, -1)
|
Chris@87
|
3240 try:
|
Chris@87
|
3241 ret = (d * (y[slice1] + y[slice2]) / 2.0).sum(axis)
|
Chris@87
|
3242 except ValueError:
|
Chris@87
|
3243 # Operations didn't work, cast to ndarray
|
Chris@87
|
3244 d = np.asarray(d)
|
Chris@87
|
3245 y = np.asarray(y)
|
Chris@87
|
3246 ret = add.reduce(d * (y[slice1]+y[slice2])/2.0, axis)
|
Chris@87
|
3247 return ret
|
Chris@87
|
3248
|
Chris@87
|
3249
|
Chris@87
|
3250 #always succeed
|
Chris@87
|
3251 def add_newdoc(place, obj, doc):
|
Chris@87
|
3252 """Adds documentation to obj which is in module place.
|
Chris@87
|
3253
|
Chris@87
|
3254 If doc is a string add it to obj as a docstring
|
Chris@87
|
3255
|
Chris@87
|
3256 If doc is a tuple, then the first element is interpreted as
|
Chris@87
|
3257 an attribute of obj and the second as the docstring
|
Chris@87
|
3258 (method, docstring)
|
Chris@87
|
3259
|
Chris@87
|
3260 If doc is a list, then each element of the list should be a
|
Chris@87
|
3261 sequence of length two --> [(method1, docstring1),
|
Chris@87
|
3262 (method2, docstring2), ...]
|
Chris@87
|
3263
|
Chris@87
|
3264 This routine never raises an error.
|
Chris@87
|
3265
|
Chris@87
|
3266 This routine cannot modify read-only docstrings, as appear
|
Chris@87
|
3267 in new-style classes or built-in functions. Because this
|
Chris@87
|
3268 routine never raises an error the caller must check manually
|
Chris@87
|
3269 that the docstrings were changed.
|
Chris@87
|
3270 """
|
Chris@87
|
3271 try:
|
Chris@87
|
3272 new = getattr(__import__(place, globals(), {}, [obj]), obj)
|
Chris@87
|
3273 if isinstance(doc, str):
|
Chris@87
|
3274 add_docstring(new, doc.strip())
|
Chris@87
|
3275 elif isinstance(doc, tuple):
|
Chris@87
|
3276 add_docstring(getattr(new, doc[0]), doc[1].strip())
|
Chris@87
|
3277 elif isinstance(doc, list):
|
Chris@87
|
3278 for val in doc:
|
Chris@87
|
3279 add_docstring(getattr(new, val[0]), val[1].strip())
|
Chris@87
|
3280 except:
|
Chris@87
|
3281 pass
|
Chris@87
|
3282
|
Chris@87
|
3283
|
Chris@87
|
3284 # Based on scitools meshgrid
|
Chris@87
|
3285 def meshgrid(*xi, **kwargs):
|
Chris@87
|
3286 """
|
Chris@87
|
3287 Return coordinate matrices from coordinate vectors.
|
Chris@87
|
3288
|
Chris@87
|
3289 Make N-D coordinate arrays for vectorized evaluations of
|
Chris@87
|
3290 N-D scalar/vector fields over N-D grids, given
|
Chris@87
|
3291 one-dimensional coordinate arrays x1, x2,..., xn.
|
Chris@87
|
3292
|
Chris@87
|
3293 .. versionchanged:: 1.9
|
Chris@87
|
3294 1-D and 0-D cases are allowed.
|
Chris@87
|
3295
|
Chris@87
|
3296 Parameters
|
Chris@87
|
3297 ----------
|
Chris@87
|
3298 x1, x2,..., xn : array_like
|
Chris@87
|
3299 1-D arrays representing the coordinates of a grid.
|
Chris@87
|
3300 indexing : {'xy', 'ij'}, optional
|
Chris@87
|
3301 Cartesian ('xy', default) or matrix ('ij') indexing of output.
|
Chris@87
|
3302 See Notes for more details.
|
Chris@87
|
3303
|
Chris@87
|
3304 .. versionadded:: 1.7.0
|
Chris@87
|
3305 sparse : bool, optional
|
Chris@87
|
3306 If True a sparse grid is returned in order to conserve memory.
|
Chris@87
|
3307 Default is False.
|
Chris@87
|
3308
|
Chris@87
|
3309 .. versionadded:: 1.7.0
|
Chris@87
|
3310 copy : bool, optional
|
Chris@87
|
3311 If False, a view into the original arrays are returned in order to
|
Chris@87
|
3312 conserve memory. Default is True. Please note that
|
Chris@87
|
3313 ``sparse=False, copy=False`` will likely return non-contiguous
|
Chris@87
|
3314 arrays. Furthermore, more than one element of a broadcast array
|
Chris@87
|
3315 may refer to a single memory location. If you need to write to the
|
Chris@87
|
3316 arrays, make copies first.
|
Chris@87
|
3317
|
Chris@87
|
3318 .. versionadded:: 1.7.0
|
Chris@87
|
3319
|
Chris@87
|
3320 Returns
|
Chris@87
|
3321 -------
|
Chris@87
|
3322 X1, X2,..., XN : ndarray
|
Chris@87
|
3323 For vectors `x1`, `x2`,..., 'xn' with lengths ``Ni=len(xi)`` ,
|
Chris@87
|
3324 return ``(N1, N2, N3,...Nn)`` shaped arrays if indexing='ij'
|
Chris@87
|
3325 or ``(N2, N1, N3,...Nn)`` shaped arrays if indexing='xy'
|
Chris@87
|
3326 with the elements of `xi` repeated to fill the matrix along
|
Chris@87
|
3327 the first dimension for `x1`, the second for `x2` and so on.
|
Chris@87
|
3328
|
Chris@87
|
3329 Notes
|
Chris@87
|
3330 -----
|
Chris@87
|
3331 This function supports both indexing conventions through the indexing
|
Chris@87
|
3332 keyword argument. Giving the string 'ij' returns a meshgrid with
|
Chris@87
|
3333 matrix indexing, while 'xy' returns a meshgrid with Cartesian indexing.
|
Chris@87
|
3334 In the 2-D case with inputs of length M and N, the outputs are of shape
|
Chris@87
|
3335 (N, M) for 'xy' indexing and (M, N) for 'ij' indexing. In the 3-D case
|
Chris@87
|
3336 with inputs of length M, N and P, outputs are of shape (N, M, P) for
|
Chris@87
|
3337 'xy' indexing and (M, N, P) for 'ij' indexing. The difference is
|
Chris@87
|
3338 illustrated by the following code snippet::
|
Chris@87
|
3339
|
Chris@87
|
3340 xv, yv = meshgrid(x, y, sparse=False, indexing='ij')
|
Chris@87
|
3341 for i in range(nx):
|
Chris@87
|
3342 for j in range(ny):
|
Chris@87
|
3343 # treat xv[i,j], yv[i,j]
|
Chris@87
|
3344
|
Chris@87
|
3345 xv, yv = meshgrid(x, y, sparse=False, indexing='xy')
|
Chris@87
|
3346 for i in range(nx):
|
Chris@87
|
3347 for j in range(ny):
|
Chris@87
|
3348 # treat xv[j,i], yv[j,i]
|
Chris@87
|
3349
|
Chris@87
|
3350 In the 1-D and 0-D case, the indexing and sparse keywords have no effect.
|
Chris@87
|
3351
|
Chris@87
|
3352 See Also
|
Chris@87
|
3353 --------
|
Chris@87
|
3354 index_tricks.mgrid : Construct a multi-dimensional "meshgrid"
|
Chris@87
|
3355 using indexing notation.
|
Chris@87
|
3356 index_tricks.ogrid : Construct an open multi-dimensional "meshgrid"
|
Chris@87
|
3357 using indexing notation.
|
Chris@87
|
3358
|
Chris@87
|
3359 Examples
|
Chris@87
|
3360 --------
|
Chris@87
|
3361 >>> nx, ny = (3, 2)
|
Chris@87
|
3362 >>> x = np.linspace(0, 1, nx)
|
Chris@87
|
3363 >>> y = np.linspace(0, 1, ny)
|
Chris@87
|
3364 >>> xv, yv = meshgrid(x, y)
|
Chris@87
|
3365 >>> xv
|
Chris@87
|
3366 array([[ 0. , 0.5, 1. ],
|
Chris@87
|
3367 [ 0. , 0.5, 1. ]])
|
Chris@87
|
3368 >>> yv
|
Chris@87
|
3369 array([[ 0., 0., 0.],
|
Chris@87
|
3370 [ 1., 1., 1.]])
|
Chris@87
|
3371 >>> xv, yv = meshgrid(x, y, sparse=True) # make sparse output arrays
|
Chris@87
|
3372 >>> xv
|
Chris@87
|
3373 array([[ 0. , 0.5, 1. ]])
|
Chris@87
|
3374 >>> yv
|
Chris@87
|
3375 array([[ 0.],
|
Chris@87
|
3376 [ 1.]])
|
Chris@87
|
3377
|
Chris@87
|
3378 `meshgrid` is very useful to evaluate functions on a grid.
|
Chris@87
|
3379
|
Chris@87
|
3380 >>> x = np.arange(-5, 5, 0.1)
|
Chris@87
|
3381 >>> y = np.arange(-5, 5, 0.1)
|
Chris@87
|
3382 >>> xx, yy = meshgrid(x, y, sparse=True)
|
Chris@87
|
3383 >>> z = np.sin(xx**2 + yy**2) / (xx**2 + yy**2)
|
Chris@87
|
3384 >>> h = plt.contourf(x,y,z)
|
Chris@87
|
3385
|
Chris@87
|
3386 """
|
Chris@87
|
3387 ndim = len(xi)
|
Chris@87
|
3388
|
Chris@87
|
3389 copy_ = kwargs.pop('copy', True)
|
Chris@87
|
3390 sparse = kwargs.pop('sparse', False)
|
Chris@87
|
3391 indexing = kwargs.pop('indexing', 'xy')
|
Chris@87
|
3392
|
Chris@87
|
3393 if kwargs:
|
Chris@87
|
3394 raise TypeError("meshgrid() got an unexpected keyword argument '%s'"
|
Chris@87
|
3395 % (list(kwargs)[0],))
|
Chris@87
|
3396
|
Chris@87
|
3397 if indexing not in ['xy', 'ij']:
|
Chris@87
|
3398 raise ValueError(
|
Chris@87
|
3399 "Valid values for `indexing` are 'xy' and 'ij'.")
|
Chris@87
|
3400
|
Chris@87
|
3401 s0 = (1,) * ndim
|
Chris@87
|
3402 output = [np.asanyarray(x).reshape(s0[:i] + (-1,) + s0[i + 1::])
|
Chris@87
|
3403 for i, x in enumerate(xi)]
|
Chris@87
|
3404
|
Chris@87
|
3405 shape = [x.size for x in output]
|
Chris@87
|
3406
|
Chris@87
|
3407 if indexing == 'xy' and ndim > 1:
|
Chris@87
|
3408 # switch first and second axis
|
Chris@87
|
3409 output[0].shape = (1, -1) + (1,)*(ndim - 2)
|
Chris@87
|
3410 output[1].shape = (-1, 1) + (1,)*(ndim - 2)
|
Chris@87
|
3411 shape[0], shape[1] = shape[1], shape[0]
|
Chris@87
|
3412
|
Chris@87
|
3413 if sparse:
|
Chris@87
|
3414 if copy_:
|
Chris@87
|
3415 return [x.copy() for x in output]
|
Chris@87
|
3416 else:
|
Chris@87
|
3417 return output
|
Chris@87
|
3418 else:
|
Chris@87
|
3419 # Return the full N-D matrix (not only the 1-D vector)
|
Chris@87
|
3420 if copy_:
|
Chris@87
|
3421 mult_fact = np.ones(shape, dtype=int)
|
Chris@87
|
3422 return [x * mult_fact for x in output]
|
Chris@87
|
3423 else:
|
Chris@87
|
3424 return np.broadcast_arrays(*output)
|
Chris@87
|
3425
|
Chris@87
|
3426
|
Chris@87
|
3427 def delete(arr, obj, axis=None):
|
Chris@87
|
3428 """
|
Chris@87
|
3429 Return a new array with sub-arrays along an axis deleted. For a one
|
Chris@87
|
3430 dimensional array, this returns those entries not returned by
|
Chris@87
|
3431 `arr[obj]`.
|
Chris@87
|
3432
|
Chris@87
|
3433 Parameters
|
Chris@87
|
3434 ----------
|
Chris@87
|
3435 arr : array_like
|
Chris@87
|
3436 Input array.
|
Chris@87
|
3437 obj : slice, int or array of ints
|
Chris@87
|
3438 Indicate which sub-arrays to remove.
|
Chris@87
|
3439 axis : int, optional
|
Chris@87
|
3440 The axis along which to delete the subarray defined by `obj`.
|
Chris@87
|
3441 If `axis` is None, `obj` is applied to the flattened array.
|
Chris@87
|
3442
|
Chris@87
|
3443 Returns
|
Chris@87
|
3444 -------
|
Chris@87
|
3445 out : ndarray
|
Chris@87
|
3446 A copy of `arr` with the elements specified by `obj` removed. Note
|
Chris@87
|
3447 that `delete` does not occur in-place. If `axis` is None, `out` is
|
Chris@87
|
3448 a flattened array.
|
Chris@87
|
3449
|
Chris@87
|
3450 See Also
|
Chris@87
|
3451 --------
|
Chris@87
|
3452 insert : Insert elements into an array.
|
Chris@87
|
3453 append : Append elements at the end of an array.
|
Chris@87
|
3454
|
Chris@87
|
3455 Notes
|
Chris@87
|
3456 -----
|
Chris@87
|
3457 Often it is preferable to use a boolean mask. For example:
|
Chris@87
|
3458
|
Chris@87
|
3459 >>> mask = np.ones(len(arr), dtype=bool)
|
Chris@87
|
3460 >>> mask[[0,2,4]] = False
|
Chris@87
|
3461 >>> result = arr[mask,...]
|
Chris@87
|
3462
|
Chris@87
|
3463 Is equivalent to `np.delete(arr, [0,2,4], axis=0)`, but allows further
|
Chris@87
|
3464 use of `mask`.
|
Chris@87
|
3465
|
Chris@87
|
3466 Examples
|
Chris@87
|
3467 --------
|
Chris@87
|
3468 >>> arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
|
Chris@87
|
3469 >>> arr
|
Chris@87
|
3470 array([[ 1, 2, 3, 4],
|
Chris@87
|
3471 [ 5, 6, 7, 8],
|
Chris@87
|
3472 [ 9, 10, 11, 12]])
|
Chris@87
|
3473 >>> np.delete(arr, 1, 0)
|
Chris@87
|
3474 array([[ 1, 2, 3, 4],
|
Chris@87
|
3475 [ 9, 10, 11, 12]])
|
Chris@87
|
3476
|
Chris@87
|
3477 >>> np.delete(arr, np.s_[::2], 1)
|
Chris@87
|
3478 array([[ 2, 4],
|
Chris@87
|
3479 [ 6, 8],
|
Chris@87
|
3480 [10, 12]])
|
Chris@87
|
3481 >>> np.delete(arr, [1,3,5], None)
|
Chris@87
|
3482 array([ 1, 3, 5, 7, 8, 9, 10, 11, 12])
|
Chris@87
|
3483
|
Chris@87
|
3484 """
|
Chris@87
|
3485 wrap = None
|
Chris@87
|
3486 if type(arr) is not ndarray:
|
Chris@87
|
3487 try:
|
Chris@87
|
3488 wrap = arr.__array_wrap__
|
Chris@87
|
3489 except AttributeError:
|
Chris@87
|
3490 pass
|
Chris@87
|
3491
|
Chris@87
|
3492 arr = asarray(arr)
|
Chris@87
|
3493 ndim = arr.ndim
|
Chris@87
|
3494 if axis is None:
|
Chris@87
|
3495 if ndim != 1:
|
Chris@87
|
3496 arr = arr.ravel()
|
Chris@87
|
3497 ndim = arr.ndim
|
Chris@87
|
3498 axis = ndim - 1
|
Chris@87
|
3499 if ndim == 0:
|
Chris@87
|
3500 warnings.warn(
|
Chris@87
|
3501 "in the future the special handling of scalars will be removed "
|
Chris@87
|
3502 "from delete and raise an error", DeprecationWarning)
|
Chris@87
|
3503 if wrap:
|
Chris@87
|
3504 return wrap(arr)
|
Chris@87
|
3505 else:
|
Chris@87
|
3506 return arr.copy()
|
Chris@87
|
3507
|
Chris@87
|
3508 slobj = [slice(None)]*ndim
|
Chris@87
|
3509 N = arr.shape[axis]
|
Chris@87
|
3510 newshape = list(arr.shape)
|
Chris@87
|
3511
|
Chris@87
|
3512 if isinstance(obj, slice):
|
Chris@87
|
3513 start, stop, step = obj.indices(N)
|
Chris@87
|
3514 xr = range(start, stop, step)
|
Chris@87
|
3515 numtodel = len(xr)
|
Chris@87
|
3516
|
Chris@87
|
3517 if numtodel <= 0:
|
Chris@87
|
3518 if wrap:
|
Chris@87
|
3519 return wrap(arr.copy())
|
Chris@87
|
3520 else:
|
Chris@87
|
3521 return arr.copy()
|
Chris@87
|
3522
|
Chris@87
|
3523 # Invert if step is negative:
|
Chris@87
|
3524 if step < 0:
|
Chris@87
|
3525 step = -step
|
Chris@87
|
3526 start = xr[-1]
|
Chris@87
|
3527 stop = xr[0] + 1
|
Chris@87
|
3528
|
Chris@87
|
3529 newshape[axis] -= numtodel
|
Chris@87
|
3530 new = empty(newshape, arr.dtype, arr.flags.fnc)
|
Chris@87
|
3531 # copy initial chunk
|
Chris@87
|
3532 if start == 0:
|
Chris@87
|
3533 pass
|
Chris@87
|
3534 else:
|
Chris@87
|
3535 slobj[axis] = slice(None, start)
|
Chris@87
|
3536 new[slobj] = arr[slobj]
|
Chris@87
|
3537 # copy end chunck
|
Chris@87
|
3538 if stop == N:
|
Chris@87
|
3539 pass
|
Chris@87
|
3540 else:
|
Chris@87
|
3541 slobj[axis] = slice(stop-numtodel, None)
|
Chris@87
|
3542 slobj2 = [slice(None)]*ndim
|
Chris@87
|
3543 slobj2[axis] = slice(stop, None)
|
Chris@87
|
3544 new[slobj] = arr[slobj2]
|
Chris@87
|
3545 # copy middle pieces
|
Chris@87
|
3546 if step == 1:
|
Chris@87
|
3547 pass
|
Chris@87
|
3548 else: # use array indexing.
|
Chris@87
|
3549 keep = ones(stop-start, dtype=bool)
|
Chris@87
|
3550 keep[:stop-start:step] = False
|
Chris@87
|
3551 slobj[axis] = slice(start, stop-numtodel)
|
Chris@87
|
3552 slobj2 = [slice(None)]*ndim
|
Chris@87
|
3553 slobj2[axis] = slice(start, stop)
|
Chris@87
|
3554 arr = arr[slobj2]
|
Chris@87
|
3555 slobj2[axis] = keep
|
Chris@87
|
3556 new[slobj] = arr[slobj2]
|
Chris@87
|
3557 if wrap:
|
Chris@87
|
3558 return wrap(new)
|
Chris@87
|
3559 else:
|
Chris@87
|
3560 return new
|
Chris@87
|
3561
|
Chris@87
|
3562 _obj = obj
|
Chris@87
|
3563 obj = np.asarray(obj)
|
Chris@87
|
3564 # After removing the special handling of booleans and out of
|
Chris@87
|
3565 # bounds values, the conversion to the array can be removed.
|
Chris@87
|
3566 if obj.dtype == bool:
|
Chris@87
|
3567 warnings.warn(
|
Chris@87
|
3568 "in the future insert will treat boolean arrays and array-likes "
|
Chris@87
|
3569 "as boolean index instead of casting it to integer", FutureWarning)
|
Chris@87
|
3570 obj = obj.astype(intp)
|
Chris@87
|
3571 if isinstance(_obj, (int, long, integer)):
|
Chris@87
|
3572 # optimization for a single value
|
Chris@87
|
3573 obj = obj.item()
|
Chris@87
|
3574 if (obj < -N or obj >= N):
|
Chris@87
|
3575 raise IndexError(
|
Chris@87
|
3576 "index %i is out of bounds for axis %i with "
|
Chris@87
|
3577 "size %i" % (obj, axis, N))
|
Chris@87
|
3578 if (obj < 0):
|
Chris@87
|
3579 obj += N
|
Chris@87
|
3580 newshape[axis] -= 1
|
Chris@87
|
3581 new = empty(newshape, arr.dtype, arr.flags.fnc)
|
Chris@87
|
3582 slobj[axis] = slice(None, obj)
|
Chris@87
|
3583 new[slobj] = arr[slobj]
|
Chris@87
|
3584 slobj[axis] = slice(obj, None)
|
Chris@87
|
3585 slobj2 = [slice(None)]*ndim
|
Chris@87
|
3586 slobj2[axis] = slice(obj+1, None)
|
Chris@87
|
3587 new[slobj] = arr[slobj2]
|
Chris@87
|
3588 else:
|
Chris@87
|
3589 if obj.size == 0 and not isinstance(_obj, np.ndarray):
|
Chris@87
|
3590 obj = obj.astype(intp)
|
Chris@87
|
3591 if not np.can_cast(obj, intp, 'same_kind'):
|
Chris@87
|
3592 # obj.size = 1 special case always failed and would just
|
Chris@87
|
3593 # give superfluous warnings.
|
Chris@87
|
3594 warnings.warn(
|
Chris@87
|
3595 "using a non-integer array as obj in delete will result in an "
|
Chris@87
|
3596 "error in the future", DeprecationWarning)
|
Chris@87
|
3597 obj = obj.astype(intp)
|
Chris@87
|
3598 keep = ones(N, dtype=bool)
|
Chris@87
|
3599
|
Chris@87
|
3600 # Test if there are out of bound indices, this is deprecated
|
Chris@87
|
3601 inside_bounds = (obj < N) & (obj >= -N)
|
Chris@87
|
3602 if not inside_bounds.all():
|
Chris@87
|
3603 warnings.warn(
|
Chris@87
|
3604 "in the future out of bounds indices will raise an error "
|
Chris@87
|
3605 "instead of being ignored by `numpy.delete`.",
|
Chris@87
|
3606 DeprecationWarning)
|
Chris@87
|
3607 obj = obj[inside_bounds]
|
Chris@87
|
3608 positive_indices = obj >= 0
|
Chris@87
|
3609 if not positive_indices.all():
|
Chris@87
|
3610 warnings.warn(
|
Chris@87
|
3611 "in the future negative indices will not be ignored by "
|
Chris@87
|
3612 "`numpy.delete`.", FutureWarning)
|
Chris@87
|
3613 obj = obj[positive_indices]
|
Chris@87
|
3614
|
Chris@87
|
3615 keep[obj, ] = False
|
Chris@87
|
3616 slobj[axis] = keep
|
Chris@87
|
3617 new = arr[slobj]
|
Chris@87
|
3618
|
Chris@87
|
3619 if wrap:
|
Chris@87
|
3620 return wrap(new)
|
Chris@87
|
3621 else:
|
Chris@87
|
3622 return new
|
Chris@87
|
3623
|
Chris@87
|
3624
|
Chris@87
|
3625 def insert(arr, obj, values, axis=None):
|
Chris@87
|
3626 """
|
Chris@87
|
3627 Insert values along the given axis before the given indices.
|
Chris@87
|
3628
|
Chris@87
|
3629 Parameters
|
Chris@87
|
3630 ----------
|
Chris@87
|
3631 arr : array_like
|
Chris@87
|
3632 Input array.
|
Chris@87
|
3633 obj : int, slice or sequence of ints
|
Chris@87
|
3634 Object that defines the index or indices before which `values` is
|
Chris@87
|
3635 inserted.
|
Chris@87
|
3636
|
Chris@87
|
3637 .. versionadded:: 1.8.0
|
Chris@87
|
3638
|
Chris@87
|
3639 Support for multiple insertions when `obj` is a single scalar or a
|
Chris@87
|
3640 sequence with one element (similar to calling insert multiple
|
Chris@87
|
3641 times).
|
Chris@87
|
3642 values : array_like
|
Chris@87
|
3643 Values to insert into `arr`. If the type of `values` is different
|
Chris@87
|
3644 from that of `arr`, `values` is converted to the type of `arr`.
|
Chris@87
|
3645 `values` should be shaped so that ``arr[...,obj,...] = values``
|
Chris@87
|
3646 is legal.
|
Chris@87
|
3647 axis : int, optional
|
Chris@87
|
3648 Axis along which to insert `values`. If `axis` is None then `arr`
|
Chris@87
|
3649 is flattened first.
|
Chris@87
|
3650
|
Chris@87
|
3651 Returns
|
Chris@87
|
3652 -------
|
Chris@87
|
3653 out : ndarray
|
Chris@87
|
3654 A copy of `arr` with `values` inserted. Note that `insert`
|
Chris@87
|
3655 does not occur in-place: a new array is returned. If
|
Chris@87
|
3656 `axis` is None, `out` is a flattened array.
|
Chris@87
|
3657
|
Chris@87
|
3658 See Also
|
Chris@87
|
3659 --------
|
Chris@87
|
3660 append : Append elements at the end of an array.
|
Chris@87
|
3661 concatenate : Join a sequence of arrays together.
|
Chris@87
|
3662 delete : Delete elements from an array.
|
Chris@87
|
3663
|
Chris@87
|
3664 Notes
|
Chris@87
|
3665 -----
|
Chris@87
|
3666 Note that for higher dimensional inserts `obj=0` behaves very different
|
Chris@87
|
3667 from `obj=[0]` just like `arr[:,0,:] = values` is different from
|
Chris@87
|
3668 `arr[:,[0],:] = values`.
|
Chris@87
|
3669
|
Chris@87
|
3670 Examples
|
Chris@87
|
3671 --------
|
Chris@87
|
3672 >>> a = np.array([[1, 1], [2, 2], [3, 3]])
|
Chris@87
|
3673 >>> a
|
Chris@87
|
3674 array([[1, 1],
|
Chris@87
|
3675 [2, 2],
|
Chris@87
|
3676 [3, 3]])
|
Chris@87
|
3677 >>> np.insert(a, 1, 5)
|
Chris@87
|
3678 array([1, 5, 1, 2, 2, 3, 3])
|
Chris@87
|
3679 >>> np.insert(a, 1, 5, axis=1)
|
Chris@87
|
3680 array([[1, 5, 1],
|
Chris@87
|
3681 [2, 5, 2],
|
Chris@87
|
3682 [3, 5, 3]])
|
Chris@87
|
3683
|
Chris@87
|
3684 Difference between sequence and scalars:
|
Chris@87
|
3685 >>> np.insert(a, [1], [[1],[2],[3]], axis=1)
|
Chris@87
|
3686 array([[1, 1, 1],
|
Chris@87
|
3687 [2, 2, 2],
|
Chris@87
|
3688 [3, 3, 3]])
|
Chris@87
|
3689 >>> np.array_equal(np.insert(a, 1, [1, 2, 3], axis=1),
|
Chris@87
|
3690 ... np.insert(a, [1], [[1],[2],[3]], axis=1))
|
Chris@87
|
3691 True
|
Chris@87
|
3692
|
Chris@87
|
3693 >>> b = a.flatten()
|
Chris@87
|
3694 >>> b
|
Chris@87
|
3695 array([1, 1, 2, 2, 3, 3])
|
Chris@87
|
3696 >>> np.insert(b, [2, 2], [5, 6])
|
Chris@87
|
3697 array([1, 1, 5, 6, 2, 2, 3, 3])
|
Chris@87
|
3698
|
Chris@87
|
3699 >>> np.insert(b, slice(2, 4), [5, 6])
|
Chris@87
|
3700 array([1, 1, 5, 2, 6, 2, 3, 3])
|
Chris@87
|
3701
|
Chris@87
|
3702 >>> np.insert(b, [2, 2], [7.13, False]) # type casting
|
Chris@87
|
3703 array([1, 1, 7, 0, 2, 2, 3, 3])
|
Chris@87
|
3704
|
Chris@87
|
3705 >>> x = np.arange(8).reshape(2, 4)
|
Chris@87
|
3706 >>> idx = (1, 3)
|
Chris@87
|
3707 >>> np.insert(x, idx, 999, axis=1)
|
Chris@87
|
3708 array([[ 0, 999, 1, 2, 999, 3],
|
Chris@87
|
3709 [ 4, 999, 5, 6, 999, 7]])
|
Chris@87
|
3710
|
Chris@87
|
3711 """
|
Chris@87
|
3712 wrap = None
|
Chris@87
|
3713 if type(arr) is not ndarray:
|
Chris@87
|
3714 try:
|
Chris@87
|
3715 wrap = arr.__array_wrap__
|
Chris@87
|
3716 except AttributeError:
|
Chris@87
|
3717 pass
|
Chris@87
|
3718
|
Chris@87
|
3719 arr = asarray(arr)
|
Chris@87
|
3720 ndim = arr.ndim
|
Chris@87
|
3721 if axis is None:
|
Chris@87
|
3722 if ndim != 1:
|
Chris@87
|
3723 arr = arr.ravel()
|
Chris@87
|
3724 ndim = arr.ndim
|
Chris@87
|
3725 axis = ndim - 1
|
Chris@87
|
3726 else:
|
Chris@87
|
3727 if ndim > 0 and (axis < -ndim or axis >= ndim):
|
Chris@87
|
3728 raise IndexError(
|
Chris@87
|
3729 "axis %i is out of bounds for an array of "
|
Chris@87
|
3730 "dimension %i" % (axis, ndim))
|
Chris@87
|
3731 if (axis < 0):
|
Chris@87
|
3732 axis += ndim
|
Chris@87
|
3733 if (ndim == 0):
|
Chris@87
|
3734 warnings.warn(
|
Chris@87
|
3735 "in the future the special handling of scalars will be removed "
|
Chris@87
|
3736 "from insert and raise an error", DeprecationWarning)
|
Chris@87
|
3737 arr = arr.copy()
|
Chris@87
|
3738 arr[...] = values
|
Chris@87
|
3739 if wrap:
|
Chris@87
|
3740 return wrap(arr)
|
Chris@87
|
3741 else:
|
Chris@87
|
3742 return arr
|
Chris@87
|
3743 slobj = [slice(None)]*ndim
|
Chris@87
|
3744 N = arr.shape[axis]
|
Chris@87
|
3745 newshape = list(arr.shape)
|
Chris@87
|
3746
|
Chris@87
|
3747 if isinstance(obj, slice):
|
Chris@87
|
3748 # turn it into a range object
|
Chris@87
|
3749 indices = arange(*obj.indices(N), **{'dtype': intp})
|
Chris@87
|
3750 else:
|
Chris@87
|
3751 # need to copy obj, because indices will be changed in-place
|
Chris@87
|
3752 indices = np.array(obj)
|
Chris@87
|
3753 if indices.dtype == bool:
|
Chris@87
|
3754 # See also delete
|
Chris@87
|
3755 warnings.warn(
|
Chris@87
|
3756 "in the future insert will treat boolean arrays and "
|
Chris@87
|
3757 "array-likes as a boolean index instead of casting it to "
|
Chris@87
|
3758 "integer", FutureWarning)
|
Chris@87
|
3759 indices = indices.astype(intp)
|
Chris@87
|
3760 # Code after warning period:
|
Chris@87
|
3761 #if obj.ndim != 1:
|
Chris@87
|
3762 # raise ValueError('boolean array argument obj to insert '
|
Chris@87
|
3763 # 'must be one dimensional')
|
Chris@87
|
3764 #indices = np.flatnonzero(obj)
|
Chris@87
|
3765 elif indices.ndim > 1:
|
Chris@87
|
3766 raise ValueError(
|
Chris@87
|
3767 "index array argument obj to insert must be one dimensional "
|
Chris@87
|
3768 "or scalar")
|
Chris@87
|
3769 if indices.size == 1:
|
Chris@87
|
3770 index = indices.item()
|
Chris@87
|
3771 if index < -N or index > N:
|
Chris@87
|
3772 raise IndexError(
|
Chris@87
|
3773 "index %i is out of bounds for axis %i with "
|
Chris@87
|
3774 "size %i" % (obj, axis, N))
|
Chris@87
|
3775 if (index < 0):
|
Chris@87
|
3776 index += N
|
Chris@87
|
3777
|
Chris@87
|
3778 # There are some object array corner cases here, but we cannot avoid
|
Chris@87
|
3779 # that:
|
Chris@87
|
3780 values = array(values, copy=False, ndmin=arr.ndim, dtype=arr.dtype)
|
Chris@87
|
3781 if indices.ndim == 0:
|
Chris@87
|
3782 # broadcasting is very different here, since a[:,0,:] = ... behaves
|
Chris@87
|
3783 # very different from a[:,[0],:] = ...! This changes values so that
|
Chris@87
|
3784 # it works likes the second case. (here a[:,0:1,:])
|
Chris@87
|
3785 values = np.rollaxis(values, 0, (axis % values.ndim) + 1)
|
Chris@87
|
3786 numnew = values.shape[axis]
|
Chris@87
|
3787 newshape[axis] += numnew
|
Chris@87
|
3788 new = empty(newshape, arr.dtype, arr.flags.fnc)
|
Chris@87
|
3789 slobj[axis] = slice(None, index)
|
Chris@87
|
3790 new[slobj] = arr[slobj]
|
Chris@87
|
3791 slobj[axis] = slice(index, index+numnew)
|
Chris@87
|
3792 new[slobj] = values
|
Chris@87
|
3793 slobj[axis] = slice(index+numnew, None)
|
Chris@87
|
3794 slobj2 = [slice(None)] * ndim
|
Chris@87
|
3795 slobj2[axis] = slice(index, None)
|
Chris@87
|
3796 new[slobj] = arr[slobj2]
|
Chris@87
|
3797 if wrap:
|
Chris@87
|
3798 return wrap(new)
|
Chris@87
|
3799 return new
|
Chris@87
|
3800 elif indices.size == 0 and not isinstance(obj, np.ndarray):
|
Chris@87
|
3801 # Can safely cast the empty list to intp
|
Chris@87
|
3802 indices = indices.astype(intp)
|
Chris@87
|
3803
|
Chris@87
|
3804 if not np.can_cast(indices, intp, 'same_kind'):
|
Chris@87
|
3805 warnings.warn(
|
Chris@87
|
3806 "using a non-integer array as obj in insert will result in an "
|
Chris@87
|
3807 "error in the future", DeprecationWarning)
|
Chris@87
|
3808 indices = indices.astype(intp)
|
Chris@87
|
3809
|
Chris@87
|
3810 indices[indices < 0] += N
|
Chris@87
|
3811
|
Chris@87
|
3812 numnew = len(indices)
|
Chris@87
|
3813 order = indices.argsort(kind='mergesort') # stable sort
|
Chris@87
|
3814 indices[order] += np.arange(numnew)
|
Chris@87
|
3815
|
Chris@87
|
3816 newshape[axis] += numnew
|
Chris@87
|
3817 old_mask = ones(newshape[axis], dtype=bool)
|
Chris@87
|
3818 old_mask[indices] = False
|
Chris@87
|
3819
|
Chris@87
|
3820 new = empty(newshape, arr.dtype, arr.flags.fnc)
|
Chris@87
|
3821 slobj2 = [slice(None)]*ndim
|
Chris@87
|
3822 slobj[axis] = indices
|
Chris@87
|
3823 slobj2[axis] = old_mask
|
Chris@87
|
3824 new[slobj] = values
|
Chris@87
|
3825 new[slobj2] = arr
|
Chris@87
|
3826
|
Chris@87
|
3827 if wrap:
|
Chris@87
|
3828 return wrap(new)
|
Chris@87
|
3829 return new
|
Chris@87
|
3830
|
Chris@87
|
3831
|
Chris@87
|
3832 def append(arr, values, axis=None):
|
Chris@87
|
3833 """
|
Chris@87
|
3834 Append values to the end of an array.
|
Chris@87
|
3835
|
Chris@87
|
3836 Parameters
|
Chris@87
|
3837 ----------
|
Chris@87
|
3838 arr : array_like
|
Chris@87
|
3839 Values are appended to a copy of this array.
|
Chris@87
|
3840 values : array_like
|
Chris@87
|
3841 These values are appended to a copy of `arr`. It must be of the
|
Chris@87
|
3842 correct shape (the same shape as `arr`, excluding `axis`). If
|
Chris@87
|
3843 `axis` is not specified, `values` can be any shape and will be
|
Chris@87
|
3844 flattened before use.
|
Chris@87
|
3845 axis : int, optional
|
Chris@87
|
3846 The axis along which `values` are appended. If `axis` is not
|
Chris@87
|
3847 given, both `arr` and `values` are flattened before use.
|
Chris@87
|
3848
|
Chris@87
|
3849 Returns
|
Chris@87
|
3850 -------
|
Chris@87
|
3851 append : ndarray
|
Chris@87
|
3852 A copy of `arr` with `values` appended to `axis`. Note that
|
Chris@87
|
3853 `append` does not occur in-place: a new array is allocated and
|
Chris@87
|
3854 filled. If `axis` is None, `out` is a flattened array.
|
Chris@87
|
3855
|
Chris@87
|
3856 See Also
|
Chris@87
|
3857 --------
|
Chris@87
|
3858 insert : Insert elements into an array.
|
Chris@87
|
3859 delete : Delete elements from an array.
|
Chris@87
|
3860
|
Chris@87
|
3861 Examples
|
Chris@87
|
3862 --------
|
Chris@87
|
3863 >>> np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]])
|
Chris@87
|
3864 array([1, 2, 3, 4, 5, 6, 7, 8, 9])
|
Chris@87
|
3865
|
Chris@87
|
3866 When `axis` is specified, `values` must have the correct shape.
|
Chris@87
|
3867
|
Chris@87
|
3868 >>> np.append([[1, 2, 3], [4, 5, 6]], [[7, 8, 9]], axis=0)
|
Chris@87
|
3869 array([[1, 2, 3],
|
Chris@87
|
3870 [4, 5, 6],
|
Chris@87
|
3871 [7, 8, 9]])
|
Chris@87
|
3872 >>> np.append([[1, 2, 3], [4, 5, 6]], [7, 8, 9], axis=0)
|
Chris@87
|
3873 Traceback (most recent call last):
|
Chris@87
|
3874 ...
|
Chris@87
|
3875 ValueError: arrays must have same number of dimensions
|
Chris@87
|
3876
|
Chris@87
|
3877 """
|
Chris@87
|
3878 arr = asanyarray(arr)
|
Chris@87
|
3879 if axis is None:
|
Chris@87
|
3880 if arr.ndim != 1:
|
Chris@87
|
3881 arr = arr.ravel()
|
Chris@87
|
3882 values = ravel(values)
|
Chris@87
|
3883 axis = arr.ndim-1
|
Chris@87
|
3884 return concatenate((arr, values), axis=axis)
|