annotate DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/polynomial/_polybase.py @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2a2c65a20a8b
children
rev   line source
Chris@87 1 """
Chris@87 2 Abstract base class for the various polynomial Classes.
Chris@87 3
Chris@87 4 The ABCPolyBase class provides the methods needed to implement the common API
Chris@87 5 for the various polynomial classes. It operates as a mixin, but uses the
Chris@87 6 abc module from the stdlib, hence it is only available for Python >= 2.6.
Chris@87 7
Chris@87 8 """
Chris@87 9 from __future__ import division, absolute_import, print_function
Chris@87 10
Chris@87 11 from abc import ABCMeta, abstractmethod, abstractproperty
Chris@87 12 from numbers import Number
Chris@87 13
Chris@87 14 import numpy as np
Chris@87 15 from . import polyutils as pu
Chris@87 16
Chris@87 17 __all__ = ['ABCPolyBase']
Chris@87 18
Chris@87 19 class ABCPolyBase(object):
Chris@87 20 """An abstract base class for series classes.
Chris@87 21
Chris@87 22 ABCPolyBase provides the standard Python numerical methods
Chris@87 23 '+', '-', '*', '//', '%', 'divmod', '**', and '()' along with the
Chris@87 24 methods listed below.
Chris@87 25
Chris@87 26 .. versionadded:: 1.9.0
Chris@87 27
Chris@87 28 Parameters
Chris@87 29 ----------
Chris@87 30 coef : array_like
Chris@87 31 Series coefficients in order of increasing degree, i.e.,
Chris@87 32 ``(1, 2, 3)`` gives ``1*P_0(x) + 2*P_1(x) + 3*P_2(x)``, where
Chris@87 33 ``P_i`` is the basis polynomials of degree ``i``.
Chris@87 34 domain : (2,) array_like, optional
Chris@87 35 Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
Chris@87 36 to the interval ``[window[0], window[1]]`` by shifting and scaling.
Chris@87 37 The default value is the derived class domain.
Chris@87 38 window : (2,) array_like, optional
Chris@87 39 Window, see domain for its use. The default value is the
Chris@87 40 derived class window.
Chris@87 41
Chris@87 42 Attributes
Chris@87 43 ----------
Chris@87 44 coef : (N,) ndarray
Chris@87 45 Series coefficients in order of increasing degree.
Chris@87 46 domain : (2,) ndarray
Chris@87 47 Domain that is mapped to window.
Chris@87 48 window : (2,) ndarray
Chris@87 49 Window that domain is mapped to.
Chris@87 50
Chris@87 51 Class Attributes
Chris@87 52 ----------------
Chris@87 53 maxpower : int
Chris@87 54 Maximum power allowed, i.e., the largest number ``n`` such that
Chris@87 55 ``p(x)**n`` is allowed. This is to limit runaway polynomial size.
Chris@87 56 domain : (2,) ndarray
Chris@87 57 Default domain of the class.
Chris@87 58 window : (2,) ndarray
Chris@87 59 Default window of the class.
Chris@87 60
Chris@87 61 """
Chris@87 62 __metaclass__ = ABCMeta
Chris@87 63
Chris@87 64 # Not hashable
Chris@87 65 __hash__ = None
Chris@87 66
Chris@87 67 # Don't let participate in array operations. Value doesn't matter.
Chris@87 68 __array_priority__ = 1000
Chris@87 69
Chris@87 70 # Limit runaway size. T_n^m has degree n*m
Chris@87 71 maxpower = 100
Chris@87 72
Chris@87 73 @abstractproperty
Chris@87 74 def domain(self):
Chris@87 75 pass
Chris@87 76
Chris@87 77 @abstractproperty
Chris@87 78 def window(self):
Chris@87 79 pass
Chris@87 80
Chris@87 81 @abstractproperty
Chris@87 82 def nickname(self):
Chris@87 83 pass
Chris@87 84
Chris@87 85 @abstractmethod
Chris@87 86 def _add(self):
Chris@87 87 pass
Chris@87 88
Chris@87 89 @abstractmethod
Chris@87 90 def _sub(self):
Chris@87 91 pass
Chris@87 92
Chris@87 93 @abstractmethod
Chris@87 94 def _mul(self):
Chris@87 95 pass
Chris@87 96
Chris@87 97 @abstractmethod
Chris@87 98 def _div(self):
Chris@87 99 pass
Chris@87 100
Chris@87 101 @abstractmethod
Chris@87 102 def _pow(self):
Chris@87 103 pass
Chris@87 104
Chris@87 105 @abstractmethod
Chris@87 106 def _val(self):
Chris@87 107 pass
Chris@87 108
Chris@87 109 @abstractmethod
Chris@87 110 def _int(self):
Chris@87 111 pass
Chris@87 112
Chris@87 113 @abstractmethod
Chris@87 114 def _der(self):
Chris@87 115 pass
Chris@87 116
Chris@87 117 @abstractmethod
Chris@87 118 def _fit(self):
Chris@87 119 pass
Chris@87 120
Chris@87 121 @abstractmethod
Chris@87 122 def _line(self):
Chris@87 123 pass
Chris@87 124
Chris@87 125 @abstractmethod
Chris@87 126 def _roots(self):
Chris@87 127 pass
Chris@87 128
Chris@87 129 @abstractmethod
Chris@87 130 def _fromroots(self):
Chris@87 131 pass
Chris@87 132
Chris@87 133 def has_samecoef(self, other):
Chris@87 134 """Check if coefficients match.
Chris@87 135
Chris@87 136 .. versionadded:: 1.6.0
Chris@87 137
Chris@87 138 Parameters
Chris@87 139 ----------
Chris@87 140 other : class instance
Chris@87 141 The other class must have the ``coef`` attribute.
Chris@87 142
Chris@87 143 Returns
Chris@87 144 -------
Chris@87 145 bool : boolean
Chris@87 146 True if the coefficients are the same, False otherwise.
Chris@87 147
Chris@87 148 """
Chris@87 149 if len(self.coef) != len(other.coef):
Chris@87 150 return False
Chris@87 151 elif not np.all(self.coef == other.coef):
Chris@87 152 return False
Chris@87 153 else:
Chris@87 154 return True
Chris@87 155
Chris@87 156 def has_samedomain(self, other):
Chris@87 157 """Check if domains match.
Chris@87 158
Chris@87 159 .. versionadded:: 1.6.0
Chris@87 160
Chris@87 161 Parameters
Chris@87 162 ----------
Chris@87 163 other : class instance
Chris@87 164 The other class must have the ``domain`` attribute.
Chris@87 165
Chris@87 166 Returns
Chris@87 167 -------
Chris@87 168 bool : boolean
Chris@87 169 True if the domains are the same, False otherwise.
Chris@87 170
Chris@87 171 """
Chris@87 172 return np.all(self.domain == other.domain)
Chris@87 173
Chris@87 174 def has_samewindow(self, other):
Chris@87 175 """Check if windows match.
Chris@87 176
Chris@87 177 .. versionadded:: 1.6.0
Chris@87 178
Chris@87 179 Parameters
Chris@87 180 ----------
Chris@87 181 other : class instance
Chris@87 182 The other class must have the ``window`` attribute.
Chris@87 183
Chris@87 184 Returns
Chris@87 185 -------
Chris@87 186 bool : boolean
Chris@87 187 True if the windows are the same, False otherwise.
Chris@87 188
Chris@87 189 """
Chris@87 190 return np.all(self.window == other.window)
Chris@87 191
Chris@87 192 def has_sametype(self, other):
Chris@87 193 """Check if types match.
Chris@87 194
Chris@87 195 .. versionadded:: 1.7.0
Chris@87 196
Chris@87 197 Parameters
Chris@87 198 ----------
Chris@87 199 other : object
Chris@87 200 Class instance.
Chris@87 201
Chris@87 202 Returns
Chris@87 203 -------
Chris@87 204 bool : boolean
Chris@87 205 True if other is same class as self
Chris@87 206
Chris@87 207 """
Chris@87 208 return isinstance(other, self.__class__)
Chris@87 209
Chris@87 210 def _get_coefficients(self, other):
Chris@87 211 """Interpret other as polynomial coefficients.
Chris@87 212
Chris@87 213 The `other` argument is checked to see if it is of the same
Chris@87 214 class as self with identical domain and window. If so,
Chris@87 215 return its coefficients, otherwise return `other`.
Chris@87 216
Chris@87 217 .. versionadded:: 1.9.0
Chris@87 218
Chris@87 219 Parameters
Chris@87 220 ----------
Chris@87 221 other : anything
Chris@87 222 Object to be checked.
Chris@87 223
Chris@87 224 Returns
Chris@87 225 -------
Chris@87 226 coef:
Chris@87 227 The coefficients of`other` if it is a compatible instance,
Chris@87 228 of ABCPolyBase, otherwise `other`.
Chris@87 229
Chris@87 230 Raises
Chris@87 231 ------
Chris@87 232 TypeError:
Chris@87 233 When `other` is an incompatible instance of ABCPolyBase.
Chris@87 234
Chris@87 235 """
Chris@87 236 if isinstance(other, ABCPolyBase):
Chris@87 237 if not isinstance(other, self.__class__):
Chris@87 238 raise TypeError("Polynomial types differ")
Chris@87 239 elif not np.all(self.domain == other.domain):
Chris@87 240 raise TypeError("Domains differ")
Chris@87 241 elif not np.all(self.window == other.window):
Chris@87 242 raise TypeError("Windows differ")
Chris@87 243 return other.coef
Chris@87 244 return other
Chris@87 245
Chris@87 246 def __init__(self, coef, domain=None, window=None):
Chris@87 247 [coef] = pu.as_series([coef], trim=False)
Chris@87 248 self.coef = coef
Chris@87 249
Chris@87 250 if domain is not None:
Chris@87 251 [domain] = pu.as_series([domain], trim=False)
Chris@87 252 if len(domain) != 2:
Chris@87 253 raise ValueError("Domain has wrong number of elements.")
Chris@87 254 self.domain = domain
Chris@87 255
Chris@87 256 if window is not None:
Chris@87 257 [window] = pu.as_series([window], trim=False)
Chris@87 258 if len(window) != 2:
Chris@87 259 raise ValueError("Window has wrong number of elements.")
Chris@87 260 self.window = window
Chris@87 261
Chris@87 262 def __repr__(self):
Chris@87 263 format = "%s(%s, %s, %s)"
Chris@87 264 coef = repr(self.coef)[6:-1]
Chris@87 265 domain = repr(self.domain)[6:-1]
Chris@87 266 window = repr(self.window)[6:-1]
Chris@87 267 name = self.__class__.__name__
Chris@87 268 return format % (name, coef, domain, window)
Chris@87 269
Chris@87 270 def __str__(self):
Chris@87 271 format = "%s(%s)"
Chris@87 272 coef = str(self.coef)
Chris@87 273 name = self.nickname
Chris@87 274 return format % (name, coef)
Chris@87 275
Chris@87 276 # Pickle and copy
Chris@87 277
Chris@87 278 def __getstate__(self):
Chris@87 279 ret = self.__dict__.copy()
Chris@87 280 ret['coef'] = self.coef.copy()
Chris@87 281 ret['domain'] = self.domain.copy()
Chris@87 282 ret['window'] = self.window.copy()
Chris@87 283 return ret
Chris@87 284
Chris@87 285 def __setstate__(self, dict):
Chris@87 286 self.__dict__ = dict
Chris@87 287
Chris@87 288 # Call
Chris@87 289
Chris@87 290 def __call__(self, arg):
Chris@87 291 off, scl = pu.mapparms(self.domain, self.window)
Chris@87 292 arg = off + scl*arg
Chris@87 293 return self._val(arg, self.coef)
Chris@87 294
Chris@87 295 def __iter__(self):
Chris@87 296 return iter(self.coef)
Chris@87 297
Chris@87 298 def __len__(self):
Chris@87 299 return len(self.coef)
Chris@87 300
Chris@87 301 # Numeric properties.
Chris@87 302
Chris@87 303 def __neg__(self):
Chris@87 304 return self.__class__(-self.coef, self.domain, self.window)
Chris@87 305
Chris@87 306 def __pos__(self):
Chris@87 307 return self
Chris@87 308
Chris@87 309 def __add__(self, other):
Chris@87 310 try:
Chris@87 311 othercoef = self._get_coefficients(other)
Chris@87 312 coef = self._add(self.coef, othercoef)
Chris@87 313 except TypeError as e:
Chris@87 314 raise e
Chris@87 315 except:
Chris@87 316 return NotImplemented
Chris@87 317 return self.__class__(coef, self.domain, self.window)
Chris@87 318
Chris@87 319 def __sub__(self, other):
Chris@87 320 try:
Chris@87 321 othercoef = self._get_coefficients(other)
Chris@87 322 coef = self._sub(self.coef, othercoef)
Chris@87 323 except TypeError as e:
Chris@87 324 raise e
Chris@87 325 except:
Chris@87 326 return NotImplemented
Chris@87 327 return self.__class__(coef, self.domain, self.window)
Chris@87 328
Chris@87 329 def __mul__(self, other):
Chris@87 330 try:
Chris@87 331 othercoef = self._get_coefficients(other)
Chris@87 332 coef = self._mul(self.coef, othercoef)
Chris@87 333 except TypeError as e:
Chris@87 334 raise e
Chris@87 335 except:
Chris@87 336 return NotImplemented
Chris@87 337 return self.__class__(coef, self.domain, self.window)
Chris@87 338
Chris@87 339 def __div__(self, other):
Chris@87 340 # set to __floordiv__, /, for now.
Chris@87 341 return self.__floordiv__(other)
Chris@87 342
Chris@87 343 def __truediv__(self, other):
Chris@87 344 # there is no true divide if the rhs is not a Number, although it
Chris@87 345 # could return the first n elements of an infinite series.
Chris@87 346 # It is hard to see where n would come from, though.
Chris@87 347 if not isinstance(other, Number) or isinstance(other, bool):
Chris@87 348 form = "unsupported types for true division: '%s', '%s'"
Chris@87 349 raise TypeError(form % (type(self), type(other)))
Chris@87 350 return self.__floordiv__(other)
Chris@87 351
Chris@87 352 def __floordiv__(self, other):
Chris@87 353 res = self.__divmod__(other)
Chris@87 354 if res is NotImplemented:
Chris@87 355 return res
Chris@87 356 return res[0]
Chris@87 357
Chris@87 358 def __mod__(self, other):
Chris@87 359 res = self.__divmod__(other)
Chris@87 360 if res is NotImplemented:
Chris@87 361 return res
Chris@87 362 return res[1]
Chris@87 363
Chris@87 364 def __divmod__(self, other):
Chris@87 365 try:
Chris@87 366 othercoef = self._get_coefficients(other)
Chris@87 367 quo, rem = self._div(self.coef, othercoef)
Chris@87 368 except (TypeError, ZeroDivisionError) as e:
Chris@87 369 raise e
Chris@87 370 except:
Chris@87 371 return NotImplemented
Chris@87 372 quo = self.__class__(quo, self.domain, self.window)
Chris@87 373 rem = self.__class__(rem, self.domain, self.window)
Chris@87 374 return quo, rem
Chris@87 375
Chris@87 376 def __pow__(self, other):
Chris@87 377 coef = self._pow(self.coef, other, maxpower=self.maxpower)
Chris@87 378 res = self.__class__(coef, self.domain, self.window)
Chris@87 379 return res
Chris@87 380
Chris@87 381 def __radd__(self, other):
Chris@87 382 try:
Chris@87 383 coef = self._add(other, self.coef)
Chris@87 384 except:
Chris@87 385 return NotImplemented
Chris@87 386 return self.__class__(coef, self.domain, self.window)
Chris@87 387
Chris@87 388 def __rsub__(self, other):
Chris@87 389 try:
Chris@87 390 coef = self._sub(other, self.coef)
Chris@87 391 except:
Chris@87 392 return NotImplemented
Chris@87 393 return self.__class__(coef, self.domain, self.window)
Chris@87 394
Chris@87 395 def __rmul__(self, other):
Chris@87 396 try:
Chris@87 397 coef = self._mul(other, self.coef)
Chris@87 398 except:
Chris@87 399 return NotImplemented
Chris@87 400 return self.__class__(coef, self.domain, self.window)
Chris@87 401
Chris@87 402 def __rdiv__(self, other):
Chris@87 403 # set to __floordiv__ /.
Chris@87 404 return self.__rfloordiv__(other)
Chris@87 405
Chris@87 406 def __rtruediv__(self, other):
Chris@87 407 # An instance of ABCPolyBase is not considered a
Chris@87 408 # Number.
Chris@87 409 return NotImplemented
Chris@87 410
Chris@87 411 def __rfloordiv__(self, other):
Chris@87 412 res = self.__rdivmod__(other)
Chris@87 413 if res is NotImplemented:
Chris@87 414 return res
Chris@87 415 return res[0]
Chris@87 416
Chris@87 417 def __rmod__(self, other):
Chris@87 418 res = self.__rdivmod__(other)
Chris@87 419 if res is NotImplemented:
Chris@87 420 return res
Chris@87 421 return res[1]
Chris@87 422
Chris@87 423 def __rdivmod__(self, other):
Chris@87 424 try:
Chris@87 425 quo, rem = self._div(other, self.coef)
Chris@87 426 except ZeroDivisionError as e:
Chris@87 427 raise e
Chris@87 428 except:
Chris@87 429 return NotImplemented
Chris@87 430 quo = self.__class__(quo, self.domain, self.window)
Chris@87 431 rem = self.__class__(rem, self.domain, self.window)
Chris@87 432 return quo, rem
Chris@87 433
Chris@87 434 # Enhance me
Chris@87 435 # some augmented arithmetic operations could be added here
Chris@87 436
Chris@87 437 def __eq__(self, other):
Chris@87 438 res = (isinstance(other, self.__class__) and
Chris@87 439 np.all(self.domain == other.domain) and
Chris@87 440 np.all(self.window == other.window) and
Chris@87 441 (self.coef.shape == other.coef.shape) and
Chris@87 442 np.all(self.coef == other.coef))
Chris@87 443 return res
Chris@87 444
Chris@87 445 def __ne__(self, other):
Chris@87 446 return not self.__eq__(other)
Chris@87 447
Chris@87 448 #
Chris@87 449 # Extra methods.
Chris@87 450 #
Chris@87 451
Chris@87 452 def copy(self):
Chris@87 453 """Return a copy.
Chris@87 454
Chris@87 455 Returns
Chris@87 456 -------
Chris@87 457 new_series : series
Chris@87 458 Copy of self.
Chris@87 459
Chris@87 460 """
Chris@87 461 return self.__class__(self.coef, self.domain, self.window)
Chris@87 462
Chris@87 463 def degree(self):
Chris@87 464 """The degree of the series.
Chris@87 465
Chris@87 466 .. versionadded:: 1.5.0
Chris@87 467
Chris@87 468 Returns
Chris@87 469 -------
Chris@87 470 degree : int
Chris@87 471 Degree of the series, one less than the number of coefficients.
Chris@87 472
Chris@87 473 """
Chris@87 474 return len(self) - 1
Chris@87 475
Chris@87 476 def cutdeg(self, deg):
Chris@87 477 """Truncate series to the given degree.
Chris@87 478
Chris@87 479 Reduce the degree of the series to `deg` by discarding the
Chris@87 480 high order terms. If `deg` is greater than the current degree a
Chris@87 481 copy of the current series is returned. This can be useful in least
Chris@87 482 squares where the coefficients of the high degree terms may be very
Chris@87 483 small.
Chris@87 484
Chris@87 485 .. versionadded:: 1.5.0
Chris@87 486
Chris@87 487 Parameters
Chris@87 488 ----------
Chris@87 489 deg : non-negative int
Chris@87 490 The series is reduced to degree `deg` by discarding the high
Chris@87 491 order terms. The value of `deg` must be a non-negative integer.
Chris@87 492
Chris@87 493 Returns
Chris@87 494 -------
Chris@87 495 new_series : series
Chris@87 496 New instance of series with reduced degree.
Chris@87 497
Chris@87 498 """
Chris@87 499 return self.truncate(deg + 1)
Chris@87 500
Chris@87 501 def trim(self, tol=0):
Chris@87 502 """Remove trailing coefficients
Chris@87 503
Chris@87 504 Remove trailing coefficients until a coefficient is reached whose
Chris@87 505 absolute value greater than `tol` or the beginning of the series is
Chris@87 506 reached. If all the coefficients would be removed the series is set
Chris@87 507 to ``[0]``. A new series instance is returned with the new
Chris@87 508 coefficients. The current instance remains unchanged.
Chris@87 509
Chris@87 510 Parameters
Chris@87 511 ----------
Chris@87 512 tol : non-negative number.
Chris@87 513 All trailing coefficients less than `tol` will be removed.
Chris@87 514
Chris@87 515 Returns
Chris@87 516 -------
Chris@87 517 new_series : series
Chris@87 518 Contains the new set of coefficients.
Chris@87 519
Chris@87 520 """
Chris@87 521 coef = pu.trimcoef(self.coef, tol)
Chris@87 522 return self.__class__(coef, self.domain, self.window)
Chris@87 523
Chris@87 524 def truncate(self, size):
Chris@87 525 """Truncate series to length `size`.
Chris@87 526
Chris@87 527 Reduce the series to length `size` by discarding the high
Chris@87 528 degree terms. The value of `size` must be a positive integer. This
Chris@87 529 can be useful in least squares where the coefficients of the
Chris@87 530 high degree terms may be very small.
Chris@87 531
Chris@87 532 Parameters
Chris@87 533 ----------
Chris@87 534 size : positive int
Chris@87 535 The series is reduced to length `size` by discarding the high
Chris@87 536 degree terms. The value of `size` must be a positive integer.
Chris@87 537
Chris@87 538 Returns
Chris@87 539 -------
Chris@87 540 new_series : series
Chris@87 541 New instance of series with truncated coefficients.
Chris@87 542
Chris@87 543 """
Chris@87 544 isize = int(size)
Chris@87 545 if isize != size or isize < 1:
Chris@87 546 raise ValueError("size must be a positive integer")
Chris@87 547 if isize >= len(self.coef):
Chris@87 548 coef = self.coef
Chris@87 549 else:
Chris@87 550 coef = self.coef[:isize]
Chris@87 551 return self.__class__(coef, self.domain, self.window)
Chris@87 552
Chris@87 553 def convert(self, domain=None, kind=None, window=None):
Chris@87 554 """Convert series to a different kind and/or domain and/or window.
Chris@87 555
Chris@87 556 Parameters
Chris@87 557 ----------
Chris@87 558 domain : array_like, optional
Chris@87 559 The domain of the converted series. If the value is None,
Chris@87 560 the default domain of `kind` is used.
Chris@87 561 kind : class, optional
Chris@87 562 The polynomial series type class to which the current instance
Chris@87 563 should be converted. If kind is None, then the class of the
Chris@87 564 current instance is used.
Chris@87 565 window : array_like, optional
Chris@87 566 The window of the converted series. If the value is None,
Chris@87 567 the default window of `kind` is used.
Chris@87 568
Chris@87 569 Returns
Chris@87 570 -------
Chris@87 571 new_series : series
Chris@87 572 The returned class can be of different type than the current
Chris@87 573 instance and/or have a different domain and/or different
Chris@87 574 window.
Chris@87 575
Chris@87 576 Notes
Chris@87 577 -----
Chris@87 578 Conversion between domains and class types can result in
Chris@87 579 numerically ill defined series.
Chris@87 580
Chris@87 581 Examples
Chris@87 582 --------
Chris@87 583
Chris@87 584 """
Chris@87 585 if kind is None:
Chris@87 586 kind = self.__class__
Chris@87 587 if domain is None:
Chris@87 588 domain = kind.domain
Chris@87 589 if window is None:
Chris@87 590 window = kind.window
Chris@87 591 return self(kind.identity(domain, window=window))
Chris@87 592
Chris@87 593 def mapparms(self):
Chris@87 594 """Return the mapping parameters.
Chris@87 595
Chris@87 596 The returned values define a linear map ``off + scl*x`` that is
Chris@87 597 applied to the input arguments before the series is evaluated. The
Chris@87 598 map depends on the ``domain`` and ``window``; if the current
Chris@87 599 ``domain`` is equal to the ``window`` the resulting map is the
Chris@87 600 identity. If the coefficients of the series instance are to be
Chris@87 601 used by themselves outside this class, then the linear function
Chris@87 602 must be substituted for the ``x`` in the standard representation of
Chris@87 603 the base polynomials.
Chris@87 604
Chris@87 605 Returns
Chris@87 606 -------
Chris@87 607 off, scl : float or complex
Chris@87 608 The mapping function is defined by ``off + scl*x``.
Chris@87 609
Chris@87 610 Notes
Chris@87 611 -----
Chris@87 612 If the current domain is the interval ``[l1, r1]`` and the window
Chris@87 613 is ``[l2, r2]``, then the linear mapping function ``L`` is
Chris@87 614 defined by the equations::
Chris@87 615
Chris@87 616 L(l1) = l2
Chris@87 617 L(r1) = r2
Chris@87 618
Chris@87 619 """
Chris@87 620 return pu.mapparms(self.domain, self.window)
Chris@87 621
Chris@87 622 def integ(self, m=1, k=[], lbnd=None):
Chris@87 623 """Integrate.
Chris@87 624
Chris@87 625 Return a series instance that is the definite integral of the
Chris@87 626 current series.
Chris@87 627
Chris@87 628 Parameters
Chris@87 629 ----------
Chris@87 630 m : non-negative int
Chris@87 631 The number of integrations to perform.
Chris@87 632 k : array_like
Chris@87 633 Integration constants. The first constant is applied to the
Chris@87 634 first integration, the second to the second, and so on. The
Chris@87 635 list of values must less than or equal to `m` in length and any
Chris@87 636 missing values are set to zero.
Chris@87 637 lbnd : Scalar
Chris@87 638 The lower bound of the definite integral.
Chris@87 639
Chris@87 640 Returns
Chris@87 641 -------
Chris@87 642 new_series : series
Chris@87 643 A new series representing the integral. The domain is the same
Chris@87 644 as the domain of the integrated series.
Chris@87 645
Chris@87 646 """
Chris@87 647 off, scl = self.mapparms()
Chris@87 648 if lbnd is None:
Chris@87 649 lbnd = 0
Chris@87 650 else:
Chris@87 651 lbnd = off + scl*lbnd
Chris@87 652 coef = self._int(self.coef, m, k, lbnd, 1./scl)
Chris@87 653 return self.__class__(coef, self.domain, self.window)
Chris@87 654
Chris@87 655 def deriv(self, m=1):
Chris@87 656 """Differentiate.
Chris@87 657
Chris@87 658 Return a series instance of that is the derivative of the current
Chris@87 659 series.
Chris@87 660
Chris@87 661 Parameters
Chris@87 662 ----------
Chris@87 663 m : non-negative int
Chris@87 664 The number of integrations to perform.
Chris@87 665
Chris@87 666 Returns
Chris@87 667 -------
Chris@87 668 new_series : series
Chris@87 669 A new series representing the derivative. The domain is the same
Chris@87 670 as the domain of the differentiated series.
Chris@87 671
Chris@87 672 """
Chris@87 673 off, scl = self.mapparms()
Chris@87 674 coef = self._der(self.coef, m, scl)
Chris@87 675 return self.__class__(coef, self.domain, self.window)
Chris@87 676
Chris@87 677 def roots(self):
Chris@87 678 """Return the roots of the series polynomial.
Chris@87 679
Chris@87 680 Compute the roots for the series. Note that the accuracy of the
Chris@87 681 roots decrease the further outside the domain they lie.
Chris@87 682
Chris@87 683 Returns
Chris@87 684 -------
Chris@87 685 roots : ndarray
Chris@87 686 Array containing the roots of the series.
Chris@87 687
Chris@87 688 """
Chris@87 689 roots = self._roots(self.coef)
Chris@87 690 return pu.mapdomain(roots, self.window, self.domain)
Chris@87 691
Chris@87 692 def linspace(self, n=100, domain=None):
Chris@87 693 """Return x, y values at equally spaced points in domain.
Chris@87 694
Chris@87 695 Returns the x, y values at `n` linearly spaced points across the
Chris@87 696 domain. Here y is the value of the polynomial at the points x. By
Chris@87 697 default the domain is the same as that of the series instance.
Chris@87 698 This method is intended mostly as a plotting aid.
Chris@87 699
Chris@87 700 .. versionadded:: 1.5.0
Chris@87 701
Chris@87 702 Parameters
Chris@87 703 ----------
Chris@87 704 n : int, optional
Chris@87 705 Number of point pairs to return. The default value is 100.
Chris@87 706 domain : {None, array_like}, optional
Chris@87 707 If not None, the specified domain is used instead of that of
Chris@87 708 the calling instance. It should be of the form ``[beg,end]``.
Chris@87 709 The default is None which case the class domain is used.
Chris@87 710
Chris@87 711 Returns
Chris@87 712 -------
Chris@87 713 x, y : ndarray
Chris@87 714 x is equal to linspace(self.domain[0], self.domain[1], n) and
Chris@87 715 y is the series evaluated at element of x.
Chris@87 716
Chris@87 717 """
Chris@87 718 if domain is None:
Chris@87 719 domain = self.domain
Chris@87 720 x = np.linspace(domain[0], domain[1], n)
Chris@87 721 y = self(x)
Chris@87 722 return x, y
Chris@87 723
Chris@87 724 @classmethod
Chris@87 725 def fit(cls, x, y, deg, domain=None, rcond=None, full=False, w=None,
Chris@87 726 window=None):
Chris@87 727 """Least squares fit to data.
Chris@87 728
Chris@87 729 Return a series instance that is the least squares fit to the data
Chris@87 730 `y` sampled at `x`. The domain of the returned instance can be
Chris@87 731 specified and this will often result in a superior fit with less
Chris@87 732 chance of ill conditioning.
Chris@87 733
Chris@87 734 Parameters
Chris@87 735 ----------
Chris@87 736 x : array_like, shape (M,)
Chris@87 737 x-coordinates of the M sample points ``(x[i], y[i])``.
Chris@87 738 y : array_like, shape (M,) or (M, K)
Chris@87 739 y-coordinates of the sample points. Several data sets of sample
Chris@87 740 points sharing the same x-coordinates can be fitted at once by
Chris@87 741 passing in a 2D-array that contains one dataset per column.
Chris@87 742 deg : int
Chris@87 743 Degree of the fitting polynomial.
Chris@87 744 domain : {None, [beg, end], []}, optional
Chris@87 745 Domain to use for the returned series. If ``None``,
Chris@87 746 then a minimal domain that covers the points `x` is chosen. If
Chris@87 747 ``[]`` the class domain is used. The default value was the
Chris@87 748 class domain in NumPy 1.4 and ``None`` in later versions.
Chris@87 749 The ``[]`` option was added in numpy 1.5.0.
Chris@87 750 rcond : float, optional
Chris@87 751 Relative condition number of the fit. Singular values smaller
Chris@87 752 than this relative to the largest singular value will be
Chris@87 753 ignored. The default value is len(x)*eps, where eps is the
Chris@87 754 relative precision of the float type, about 2e-16 in most
Chris@87 755 cases.
Chris@87 756 full : bool, optional
Chris@87 757 Switch determining nature of return value. When it is False
Chris@87 758 (the default) just the coefficients are returned, when True
Chris@87 759 diagnostic information from the singular value decomposition is
Chris@87 760 also returned.
Chris@87 761 w : array_like, shape (M,), optional
Chris@87 762 Weights. If not None the contribution of each point
Chris@87 763 ``(x[i],y[i])`` to the fit is weighted by `w[i]`. Ideally the
Chris@87 764 weights are chosen so that the errors of the products
Chris@87 765 ``w[i]*y[i]`` all have the same variance. The default value is
Chris@87 766 None.
Chris@87 767
Chris@87 768 .. versionadded:: 1.5.0
Chris@87 769 window : {[beg, end]}, optional
Chris@87 770 Window to use for the returned series. The default
Chris@87 771 value is the default class domain
Chris@87 772
Chris@87 773 .. versionadded:: 1.6.0
Chris@87 774
Chris@87 775 Returns
Chris@87 776 -------
Chris@87 777 new_series : series
Chris@87 778 A series that represents the least squares fit to the data and
Chris@87 779 has the domain specified in the call.
Chris@87 780
Chris@87 781 [resid, rank, sv, rcond] : list
Chris@87 782 These values are only returned if `full` = True
Chris@87 783
Chris@87 784 resid -- sum of squared residuals of the least squares fit
Chris@87 785 rank -- the numerical rank of the scaled Vandermonde matrix
Chris@87 786 sv -- singular values of the scaled Vandermonde matrix
Chris@87 787 rcond -- value of `rcond`.
Chris@87 788
Chris@87 789 For more details, see `linalg.lstsq`.
Chris@87 790
Chris@87 791 """
Chris@87 792 if domain is None:
Chris@87 793 domain = pu.getdomain(x)
Chris@87 794 elif type(domain) is list and len(domain) == 0:
Chris@87 795 domain = cls.domain
Chris@87 796
Chris@87 797 if window is None:
Chris@87 798 window = cls.window
Chris@87 799
Chris@87 800 xnew = pu.mapdomain(x, domain, window)
Chris@87 801 res = cls._fit(xnew, y, deg, w=w, rcond=rcond, full=full)
Chris@87 802 if full:
Chris@87 803 [coef, status] = res
Chris@87 804 return cls(coef, domain=domain, window=window), status
Chris@87 805 else:
Chris@87 806 coef = res
Chris@87 807 return cls(coef, domain=domain, window=window)
Chris@87 808
Chris@87 809 @classmethod
Chris@87 810 def fromroots(cls, roots, domain=[], window=None):
Chris@87 811 """Return series instance that has the specified roots.
Chris@87 812
Chris@87 813 Returns a series representing the product
Chris@87 814 ``(x - r[0])*(x - r[1])*...*(x - r[n-1])``, where ``r`` is a
Chris@87 815 list of roots.
Chris@87 816
Chris@87 817 Parameters
Chris@87 818 ----------
Chris@87 819 roots : array_like
Chris@87 820 List of roots.
Chris@87 821 domain : {[], None, array_like}, optional
Chris@87 822 Domain for the resulting series. If None the domain is the
Chris@87 823 interval from the smallest root to the largest. If [] the
Chris@87 824 domain is the class domain. The default is [].
Chris@87 825 window : {None, array_like}, optional
Chris@87 826 Window for the returned series. If None the class window is
Chris@87 827 used. The default is None.
Chris@87 828
Chris@87 829 Returns
Chris@87 830 -------
Chris@87 831 new_series : series
Chris@87 832 Series with the specified roots.
Chris@87 833
Chris@87 834 """
Chris@87 835 [roots] = pu.as_series([roots], trim=False)
Chris@87 836 if domain is None:
Chris@87 837 domain = pu.getdomain(roots)
Chris@87 838 elif type(domain) is list and len(domain) == 0:
Chris@87 839 domain = cls.domain
Chris@87 840
Chris@87 841 if window is None:
Chris@87 842 window = cls.window
Chris@87 843
Chris@87 844 deg = len(roots)
Chris@87 845 off, scl = pu.mapparms(domain, window)
Chris@87 846 rnew = off + scl*roots
Chris@87 847 coef = cls._fromroots(rnew) / scl**deg
Chris@87 848 return cls(coef, domain=domain, window=window)
Chris@87 849
Chris@87 850 @classmethod
Chris@87 851 def identity(cls, domain=None, window=None):
Chris@87 852 """Identity function.
Chris@87 853
Chris@87 854 If ``p`` is the returned series, then ``p(x) == x`` for all
Chris@87 855 values of x.
Chris@87 856
Chris@87 857 Parameters
Chris@87 858 ----------
Chris@87 859 domain : {None, array_like}, optional
Chris@87 860 If given, the array must be of the form ``[beg, end]``, where
Chris@87 861 ``beg`` and ``end`` are the endpoints of the domain. If None is
Chris@87 862 given then the class domain is used. The default is None.
Chris@87 863 window : {None, array_like}, optional
Chris@87 864 If given, the resulting array must be if the form
Chris@87 865 ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of
Chris@87 866 the window. If None is given then the class window is used. The
Chris@87 867 default is None.
Chris@87 868
Chris@87 869 Returns
Chris@87 870 -------
Chris@87 871 new_series : series
Chris@87 872 Series of representing the identity.
Chris@87 873
Chris@87 874 """
Chris@87 875 if domain is None:
Chris@87 876 domain = cls.domain
Chris@87 877 if window is None:
Chris@87 878 window = cls.window
Chris@87 879 off, scl = pu.mapparms(window, domain)
Chris@87 880 coef = cls._line(off, scl)
Chris@87 881 return cls(coef, domain, window)
Chris@87 882
Chris@87 883 @classmethod
Chris@87 884 def basis(cls, deg, domain=None, window=None):
Chris@87 885 """Series basis polynomial of degree `deg`.
Chris@87 886
Chris@87 887 Returns the series representing the basis polynomial of degree `deg`.
Chris@87 888
Chris@87 889 .. versionadded:: 1.7.0
Chris@87 890
Chris@87 891 Parameters
Chris@87 892 ----------
Chris@87 893 deg : int
Chris@87 894 Degree of the basis polynomial for the series. Must be >= 0.
Chris@87 895 domain : {None, array_like}, optional
Chris@87 896 If given, the array must be of the form ``[beg, end]``, where
Chris@87 897 ``beg`` and ``end`` are the endpoints of the domain. If None is
Chris@87 898 given then the class domain is used. The default is None.
Chris@87 899 window : {None, array_like}, optional
Chris@87 900 If given, the resulting array must be if the form
Chris@87 901 ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of
Chris@87 902 the window. If None is given then the class window is used. The
Chris@87 903 default is None.
Chris@87 904
Chris@87 905 Returns
Chris@87 906 -------
Chris@87 907 new_series : series
Chris@87 908 A series with the coefficient of the `deg` term set to one and
Chris@87 909 all others zero.
Chris@87 910
Chris@87 911 """
Chris@87 912 if domain is None:
Chris@87 913 domain = cls.domain
Chris@87 914 if window is None:
Chris@87 915 window = cls.window
Chris@87 916 ideg = int(deg)
Chris@87 917
Chris@87 918 if ideg != deg or ideg < 0:
Chris@87 919 raise ValueError("deg must be non-negative integer")
Chris@87 920 return cls([0]*ideg + [1], domain, window)
Chris@87 921
Chris@87 922 @classmethod
Chris@87 923 def cast(cls, series, domain=None, window=None):
Chris@87 924 """Convert series to series of this class.
Chris@87 925
Chris@87 926 The `series` is expected to be an instance of some polynomial
Chris@87 927 series of one of the types supported by by the numpy.polynomial
Chris@87 928 module, but could be some other class that supports the convert
Chris@87 929 method.
Chris@87 930
Chris@87 931 .. versionadded:: 1.7.0
Chris@87 932
Chris@87 933 Parameters
Chris@87 934 ----------
Chris@87 935 series : series
Chris@87 936 The series instance to be converted.
Chris@87 937 domain : {None, array_like}, optional
Chris@87 938 If given, the array must be of the form ``[beg, end]``, where
Chris@87 939 ``beg`` and ``end`` are the endpoints of the domain. If None is
Chris@87 940 given then the class domain is used. The default is None.
Chris@87 941 window : {None, array_like}, optional
Chris@87 942 If given, the resulting array must be if the form
Chris@87 943 ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of
Chris@87 944 the window. If None is given then the class window is used. The
Chris@87 945 default is None.
Chris@87 946
Chris@87 947 Returns
Chris@87 948 -------
Chris@87 949 new_series : series
Chris@87 950 A series of the same kind as the calling class and equal to
Chris@87 951 `series` when evaluated.
Chris@87 952
Chris@87 953 See Also
Chris@87 954 --------
Chris@87 955 convert : similar instance method
Chris@87 956
Chris@87 957 """
Chris@87 958 if domain is None:
Chris@87 959 domain = cls.domain
Chris@87 960 if window is None:
Chris@87 961 window = cls.window
Chris@87 962 return series.convert(domain, cls, window)