Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/polynomial/polyutils.py @ 87:2a2c65a20a8b
Add Python libs and headers
author | Chris Cannam |
---|---|
date | Wed, 25 Feb 2015 14:05:22 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
86:413a9d26189e | 87:2a2c65a20a8b |
---|---|
1 """ | |
2 Utililty classes and functions for the polynomial modules. | |
3 | |
4 This module provides: error and warning objects; a polynomial base class; | |
5 and some routines used in both the `polynomial` and `chebyshev` modules. | |
6 | |
7 Error objects | |
8 ------------- | |
9 | |
10 .. autosummary:: | |
11 :toctree: generated/ | |
12 | |
13 PolyError base class for this sub-package's errors. | |
14 PolyDomainError raised when domains are mismatched. | |
15 | |
16 Warning objects | |
17 --------------- | |
18 | |
19 .. autosummary:: | |
20 :toctree: generated/ | |
21 | |
22 RankWarning raised in least-squares fit for rank-deficient matrix. | |
23 | |
24 Base class | |
25 ---------- | |
26 | |
27 .. autosummary:: | |
28 :toctree: generated/ | |
29 | |
30 PolyBase Obsolete base class for the polynomial classes. Do not use. | |
31 | |
32 Functions | |
33 --------- | |
34 | |
35 .. autosummary:: | |
36 :toctree: generated/ | |
37 | |
38 as_series convert list of array_likes into 1-D arrays of common type. | |
39 trimseq remove trailing zeros. | |
40 trimcoef remove small trailing coefficients. | |
41 getdomain return the domain appropriate for a given set of abscissae. | |
42 mapdomain maps points between domains. | |
43 mapparms parameters of the linear map between domains. | |
44 | |
45 """ | |
46 from __future__ import division, absolute_import, print_function | |
47 | |
48 import numpy as np | |
49 | |
50 __all__ = [ | |
51 'RankWarning', 'PolyError', 'PolyDomainError', 'as_series', 'trimseq', | |
52 'trimcoef', 'getdomain', 'mapdomain', 'mapparms', 'PolyBase'] | |
53 | |
54 # | |
55 # Warnings and Exceptions | |
56 # | |
57 | |
58 class RankWarning(UserWarning): | |
59 """Issued by chebfit when the design matrix is rank deficient.""" | |
60 pass | |
61 | |
62 class PolyError(Exception): | |
63 """Base class for errors in this module.""" | |
64 pass | |
65 | |
66 class PolyDomainError(PolyError): | |
67 """Issued by the generic Poly class when two domains don't match. | |
68 | |
69 This is raised when an binary operation is passed Poly objects with | |
70 different domains. | |
71 | |
72 """ | |
73 pass | |
74 | |
75 # | |
76 # Base class for all polynomial types | |
77 # | |
78 | |
79 class PolyBase(object): | |
80 """ | |
81 Base class for all polynomial types. | |
82 | |
83 Deprecated in numpy 1.9.0, use the abstract | |
84 ABCPolyBase class instead. Note that the latter | |
85 reguires a number of virtual functions to be | |
86 implemented. | |
87 | |
88 """ | |
89 pass | |
90 | |
91 # | |
92 # Helper functions to convert inputs to 1-D arrays | |
93 # | |
94 def trimseq(seq): | |
95 """Remove small Poly series coefficients. | |
96 | |
97 Parameters | |
98 ---------- | |
99 seq : sequence | |
100 Sequence of Poly series coefficients. This routine fails for | |
101 empty sequences. | |
102 | |
103 Returns | |
104 ------- | |
105 series : sequence | |
106 Subsequence with trailing zeros removed. If the resulting sequence | |
107 would be empty, return the first element. The returned sequence may | |
108 or may not be a view. | |
109 | |
110 Notes | |
111 ----- | |
112 Do not lose the type info if the sequence contains unknown objects. | |
113 | |
114 """ | |
115 if len(seq) == 0: | |
116 return seq | |
117 else: | |
118 for i in range(len(seq) - 1, -1, -1): | |
119 if seq[i] != 0: | |
120 break | |
121 return seq[:i+1] | |
122 | |
123 | |
124 def as_series(alist, trim=True): | |
125 """ | |
126 Return argument as a list of 1-d arrays. | |
127 | |
128 The returned list contains array(s) of dtype double, complex double, or | |
129 object. A 1-d argument of shape ``(N,)`` is parsed into ``N`` arrays of | |
130 size one; a 2-d argument of shape ``(M,N)`` is parsed into ``M`` arrays | |
131 of size ``N`` (i.e., is "parsed by row"); and a higher dimensional array | |
132 raises a Value Error if it is not first reshaped into either a 1-d or 2-d | |
133 array. | |
134 | |
135 Parameters | |
136 ---------- | |
137 a : array_like | |
138 A 1- or 2-d array_like | |
139 trim : boolean, optional | |
140 When True, trailing zeros are removed from the inputs. | |
141 When False, the inputs are passed through intact. | |
142 | |
143 Returns | |
144 ------- | |
145 [a1, a2,...] : list of 1-D arrays | |
146 A copy of the input data as a list of 1-d arrays. | |
147 | |
148 Raises | |
149 ------ | |
150 ValueError | |
151 Raised when `as_series` cannot convert its input to 1-d arrays, or at | |
152 least one of the resulting arrays is empty. | |
153 | |
154 Examples | |
155 -------- | |
156 >>> from numpy import polynomial as P | |
157 >>> a = np.arange(4) | |
158 >>> P.as_series(a) | |
159 [array([ 0.]), array([ 1.]), array([ 2.]), array([ 3.])] | |
160 >>> b = np.arange(6).reshape((2,3)) | |
161 >>> P.as_series(b) | |
162 [array([ 0., 1., 2.]), array([ 3., 4., 5.])] | |
163 | |
164 """ | |
165 arrays = [np.array(a, ndmin=1, copy=0) for a in alist] | |
166 if min([a.size for a in arrays]) == 0: | |
167 raise ValueError("Coefficient array is empty") | |
168 if any([a.ndim != 1 for a in arrays]): | |
169 raise ValueError("Coefficient array is not 1-d") | |
170 if trim: | |
171 arrays = [trimseq(a) for a in arrays] | |
172 | |
173 if any([a.dtype == np.dtype(object) for a in arrays]): | |
174 ret = [] | |
175 for a in arrays: | |
176 if a.dtype != np.dtype(object): | |
177 tmp = np.empty(len(a), dtype=np.dtype(object)) | |
178 tmp[:] = a[:] | |
179 ret.append(tmp) | |
180 else: | |
181 ret.append(a.copy()) | |
182 else: | |
183 try: | |
184 dtype = np.common_type(*arrays) | |
185 except: | |
186 raise ValueError("Coefficient arrays have no common type") | |
187 ret = [np.array(a, copy=1, dtype=dtype) for a in arrays] | |
188 return ret | |
189 | |
190 | |
191 def trimcoef(c, tol=0): | |
192 """ | |
193 Remove "small" "trailing" coefficients from a polynomial. | |
194 | |
195 "Small" means "small in absolute value" and is controlled by the | |
196 parameter `tol`; "trailing" means highest order coefficient(s), e.g., in | |
197 ``[0, 1, 1, 0, 0]`` (which represents ``0 + x + x**2 + 0*x**3 + 0*x**4``) | |
198 both the 3-rd and 4-th order coefficients would be "trimmed." | |
199 | |
200 Parameters | |
201 ---------- | |
202 c : array_like | |
203 1-d array of coefficients, ordered from lowest order to highest. | |
204 tol : number, optional | |
205 Trailing (i.e., highest order) elements with absolute value less | |
206 than or equal to `tol` (default value is zero) are removed. | |
207 | |
208 Returns | |
209 ------- | |
210 trimmed : ndarray | |
211 1-d array with trailing zeros removed. If the resulting series | |
212 would be empty, a series containing a single zero is returned. | |
213 | |
214 Raises | |
215 ------ | |
216 ValueError | |
217 If `tol` < 0 | |
218 | |
219 See Also | |
220 -------- | |
221 trimseq | |
222 | |
223 Examples | |
224 -------- | |
225 >>> from numpy import polynomial as P | |
226 >>> P.trimcoef((0,0,3,0,5,0,0)) | |
227 array([ 0., 0., 3., 0., 5.]) | |
228 >>> P.trimcoef((0,0,1e-3,0,1e-5,0,0),1e-3) # item == tol is trimmed | |
229 array([ 0.]) | |
230 >>> i = complex(0,1) # works for complex | |
231 >>> P.trimcoef((3e-4,1e-3*(1-i),5e-4,2e-5*(1+i)), 1e-3) | |
232 array([ 0.0003+0.j , 0.0010-0.001j]) | |
233 | |
234 """ | |
235 if tol < 0: | |
236 raise ValueError("tol must be non-negative") | |
237 | |
238 [c] = as_series([c]) | |
239 [ind] = np.where(np.abs(c) > tol) | |
240 if len(ind) == 0: | |
241 return c[:1]*0 | |
242 else: | |
243 return c[:ind[-1] + 1].copy() | |
244 | |
245 def getdomain(x): | |
246 """ | |
247 Return a domain suitable for given abscissae. | |
248 | |
249 Find a domain suitable for a polynomial or Chebyshev series | |
250 defined at the values supplied. | |
251 | |
252 Parameters | |
253 ---------- | |
254 x : array_like | |
255 1-d array of abscissae whose domain will be determined. | |
256 | |
257 Returns | |
258 ------- | |
259 domain : ndarray | |
260 1-d array containing two values. If the inputs are complex, then | |
261 the two returned points are the lower left and upper right corners | |
262 of the smallest rectangle (aligned with the axes) in the complex | |
263 plane containing the points `x`. If the inputs are real, then the | |
264 two points are the ends of the smallest interval containing the | |
265 points `x`. | |
266 | |
267 See Also | |
268 -------- | |
269 mapparms, mapdomain | |
270 | |
271 Examples | |
272 -------- | |
273 >>> from numpy.polynomial import polyutils as pu | |
274 >>> points = np.arange(4)**2 - 5; points | |
275 array([-5, -4, -1, 4]) | |
276 >>> pu.getdomain(points) | |
277 array([-5., 4.]) | |
278 >>> c = np.exp(complex(0,1)*np.pi*np.arange(12)/6) # unit circle | |
279 >>> pu.getdomain(c) | |
280 array([-1.-1.j, 1.+1.j]) | |
281 | |
282 """ | |
283 [x] = as_series([x], trim=False) | |
284 if x.dtype.char in np.typecodes['Complex']: | |
285 rmin, rmax = x.real.min(), x.real.max() | |
286 imin, imax = x.imag.min(), x.imag.max() | |
287 return np.array((complex(rmin, imin), complex(rmax, imax))) | |
288 else: | |
289 return np.array((x.min(), x.max())) | |
290 | |
291 def mapparms(old, new): | |
292 """ | |
293 Linear map parameters between domains. | |
294 | |
295 Return the parameters of the linear map ``offset + scale*x`` that maps | |
296 `old` to `new` such that ``old[i] -> new[i]``, ``i = 0, 1``. | |
297 | |
298 Parameters | |
299 ---------- | |
300 old, new : array_like | |
301 Domains. Each domain must (successfully) convert to a 1-d array | |
302 containing precisely two values. | |
303 | |
304 Returns | |
305 ------- | |
306 offset, scale : scalars | |
307 The map ``L(x) = offset + scale*x`` maps the first domain to the | |
308 second. | |
309 | |
310 See Also | |
311 -------- | |
312 getdomain, mapdomain | |
313 | |
314 Notes | |
315 ----- | |
316 Also works for complex numbers, and thus can be used to calculate the | |
317 parameters required to map any line in the complex plane to any other | |
318 line therein. | |
319 | |
320 Examples | |
321 -------- | |
322 >>> from numpy import polynomial as P | |
323 >>> P.mapparms((-1,1),(-1,1)) | |
324 (0.0, 1.0) | |
325 >>> P.mapparms((1,-1),(-1,1)) | |
326 (0.0, -1.0) | |
327 >>> i = complex(0,1) | |
328 >>> P.mapparms((-i,-1),(1,i)) | |
329 ((1+1j), (1+0j)) | |
330 | |
331 """ | |
332 oldlen = old[1] - old[0] | |
333 newlen = new[1] - new[0] | |
334 off = (old[1]*new[0] - old[0]*new[1])/oldlen | |
335 scl = newlen/oldlen | |
336 return off, scl | |
337 | |
338 def mapdomain(x, old, new): | |
339 """ | |
340 Apply linear map to input points. | |
341 | |
342 The linear map ``offset + scale*x`` that maps the domain `old` to | |
343 the domain `new` is applied to the points `x`. | |
344 | |
345 Parameters | |
346 ---------- | |
347 x : array_like | |
348 Points to be mapped. If `x` is a subtype of ndarray the subtype | |
349 will be preserved. | |
350 old, new : array_like | |
351 The two domains that determine the map. Each must (successfully) | |
352 convert to 1-d arrays containing precisely two values. | |
353 | |
354 Returns | |
355 ------- | |
356 x_out : ndarray | |
357 Array of points of the same shape as `x`, after application of the | |
358 linear map between the two domains. | |
359 | |
360 See Also | |
361 -------- | |
362 getdomain, mapparms | |
363 | |
364 Notes | |
365 ----- | |
366 Effectively, this implements: | |
367 | |
368 .. math :: | |
369 x\\_out = new[0] + m(x - old[0]) | |
370 | |
371 where | |
372 | |
373 .. math :: | |
374 m = \\frac{new[1]-new[0]}{old[1]-old[0]} | |
375 | |
376 Examples | |
377 -------- | |
378 >>> from numpy import polynomial as P | |
379 >>> old_domain = (-1,1) | |
380 >>> new_domain = (0,2*np.pi) | |
381 >>> x = np.linspace(-1,1,6); x | |
382 array([-1. , -0.6, -0.2, 0.2, 0.6, 1. ]) | |
383 >>> x_out = P.mapdomain(x, old_domain, new_domain); x_out | |
384 array([ 0. , 1.25663706, 2.51327412, 3.76991118, 5.02654825, | |
385 6.28318531]) | |
386 >>> x - P.mapdomain(x_out, new_domain, old_domain) | |
387 array([ 0., 0., 0., 0., 0., 0.]) | |
388 | |
389 Also works for complex numbers (and thus can be used to map any line in | |
390 the complex plane to any other line therein). | |
391 | |
392 >>> i = complex(0,1) | |
393 >>> old = (-1 - i, 1 + i) | |
394 >>> new = (-1 + i, 1 - i) | |
395 >>> z = np.linspace(old[0], old[1], 6); z | |
396 array([-1.0-1.j , -0.6-0.6j, -0.2-0.2j, 0.2+0.2j, 0.6+0.6j, 1.0+1.j ]) | |
397 >>> new_z = P.mapdomain(z, old, new); new_z | |
398 array([-1.0+1.j , -0.6+0.6j, -0.2+0.2j, 0.2-0.2j, 0.6-0.6j, 1.0-1.j ]) | |
399 | |
400 """ | |
401 x = np.asanyarray(x) | |
402 off, scl = mapparms(old, new) | |
403 return off + scl*x |