Skip to content

Fixes for SciPy 1.0 compatibility #170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions control/bdalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"""

import scipy as sp
import numpy as np
from . import xferfcn as tf
from . import statesp as ss
from . import frdata as frd
Expand Down Expand Up @@ -221,18 +222,18 @@ def feedback(sys1, sys2=1, sign=-1):
"""

# Check for correct input types.
if not isinstance(sys1, (int, float, complex, tf.TransferFunction,
ss.StateSpace, frd.FRD)):
if not isinstance(sys1, (int, float, complex, np.number,
Copy link
Contributor

@roryyorke roryyorke Dec 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm struggling to find docs on numpy.number; it has a __doc__ string, but no entry, e.g., here: https://docs.scipy.org/doc/numpy-1.13.0/genindex.html . This use seems reasonable, just not sure how standard it is.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tf.TransferFunction, ss.StateSpace, frd.FRD)):
raise TypeError("sys1 must be a TransferFunction, StateSpace " +
"or FRD object, or a scalar.")
if not isinstance(sys2, (int, float, complex, tf.TransferFunction,
ss.StateSpace, frd.FRD)):
if not isinstance(sys2, (int, float, complex, np.number,
tf.TransferFunction, ss.StateSpace, frd.FRD)):
raise TypeError("sys2 must be a TransferFunction, StateSpace " +
"or FRD object, or a scalar.")

# If sys1 is a scalar, convert it to the appropriate LTI type so that we can
# its feedback member function.
if isinstance(sys1, (int, float, complex)):
if isinstance(sys1, (int, float, complex, np.number)):
if isinstance(sys2, tf.TransferFunction):
sys1 = tf._convertToTransferFunction(sys1)
elif isinstance(sys2, ss.StateSpace):
Expand Down
11 changes: 6 additions & 5 deletions control/frdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"""

# External function declarations
import numpy as np
from numpy import angle, array, empty, ones, \
real, imag, matrix, absolute, eye, linalg, where, dot
from scipy.interpolate import splprep, splev
Expand Down Expand Up @@ -219,7 +220,7 @@ def __mul__(self, other):
"""Multiply two LTI objects (serial connection)."""

# Convert the second argument to a transfer function.
if isinstance(other, (int, float, complex)):
if isinstance(other, (int, float, complex, np.number)):
return FRD(self.fresp * other, self.omega,
smooth=(self.ifunc is not None))
else:
Expand All @@ -245,7 +246,7 @@ def __rmul__(self, other):
"""Right Multiply two LTI objects (serial connection)."""

# Convert the second argument to an frd function.
if isinstance(other, (int, float, complex)):
if isinstance(other, (int, float, complex, np.number)):
return FRD(self.fresp * other, self.omega,
smooth=(self.ifunc is not None))
else:
Expand All @@ -272,7 +273,7 @@ def __rmul__(self, other):
def __truediv__(self, other):
"""Divide two LTI objects."""

if isinstance(other, (int, float, complex)):
if isinstance(other, (int, float, complex, np.number)):
return FRD(self.fresp * (1/other), self.omega,
smooth=(self.ifunc is not None))
else:
Expand All @@ -295,7 +296,7 @@ def __div__(self, other):
# TODO: Division of MIMO transfer function objects is not written yet.
def __rtruediv__(self, other):
"""Right divide two LTI objects."""
if isinstance(other, (int, float, complex)):
if isinstance(other, (int, float, complex, np.number)):
return FRD(other / self.fresp, self.omega,
smooth=(self.ifunc is not None))
else:
Expand Down Expand Up @@ -449,7 +450,7 @@ def _convertToFRD(sys, omega, inputs=1, outputs=1):

return FRD(fresp, omega, smooth=True)

elif isinstance(sys, (int, float, complex)):
elif isinstance(sys, (int, float, complex, np.number)):
fresp = ones((outputs, inputs, len(omega)), dtype=float)*sys
return FRD(fresp, omega, smooth=True)

Expand Down
9 changes: 5 additions & 4 deletions control/lti.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
timebaseEqual()
"""

import numpy as np
from numpy import absolute, real

__all__ = ['issiso', 'timebase', 'timebaseEqual', 'isdtime', 'isctime',
Expand Down Expand Up @@ -96,7 +97,7 @@ def dcgain(self):

# Test to see if a system is SISO
def issiso(sys, strict=False):
if isinstance(sys, (int, float, complex)) and not strict:
if isinstance(sys, (int, float, complex, np.number)) and not strict:
return True
elif not isinstance(sys, LTI):
raise ValueError("Object is not an LTI system")
Expand All @@ -114,7 +115,7 @@ def timebase(sys, strict=True):
set to False, dt = True will be returned as 1.
"""
# System needs to be either a constant or an LTI system
if isinstance(sys, (int, float, complex)):
if isinstance(sys, (int, float, complex, np.number)):
return None
elif not isinstance(sys, LTI):
raise ValueError("Timebase not defined")
Expand Down Expand Up @@ -162,7 +163,7 @@ def isdtime(sys, strict=False):
"""

# Check to see if this is a constant
if isinstance(sys, (int, float, complex)):
if isinstance(sys, (int, float, complex, np.number)):
# OK as long as strict checking is off
return True if not strict else False

Expand All @@ -187,7 +188,7 @@ def isctime(sys, strict=False):
"""

# Check to see if this is a constant
if isinstance(sys, (int, float, complex)):
if isinstance(sys, (int, float, complex, np.number)):
# OK as long as strict checking is off
return True if not strict else False

Expand Down
14 changes: 7 additions & 7 deletions control/statesp.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
from numpy.random import rand, randn
from numpy.linalg import solve, eigvals, matrix_rank
from numpy.linalg.linalg import LinAlgError
import scipy as sp
from scipy.signal import lti, cont2discrete
# from exceptions import Exception
import warnings
Expand Down Expand Up @@ -218,7 +219,7 @@ def __add__(self, other):
"""Add two LTI systems (parallel connection)."""

# Check for a couple of special cases
if (isinstance(other, (int, float, complex))):
if (isinstance(other, (int, float, complex, np.number))):
# Just adding a scalar; put it in the D matrix
A, B, C = self.A, self.B, self.C;
D = self.D + other;
Expand Down Expand Up @@ -275,7 +276,7 @@ def __mul__(self, other):
"""Multiply two LTI objects (serial connection)."""

# Check for a couple of special cases
if isinstance(other, (int, float, complex)):
if isinstance(other, (int, float, complex, np.number)):
# Just multiplying by a scalar; change the output
A, B = self.A, self.B
C = self.C * other
Expand Down Expand Up @@ -316,7 +317,7 @@ def __rmul__(self, other):
"""Right multiply two LTI objects (serial connection)."""

# Check for a couple of special cases
if isinstance(other, (int, float, complex)):
if isinstance(other, (int, float, complex, np.number)):
# Just multiplying by a scalar; change the input
A, C = self.A, self.C;
B = self.B * other;
Expand Down Expand Up @@ -699,11 +700,10 @@ def _convertToStateSpace(sys, **kw):
# TODO: do we want to squeeze first and check dimenations?
# I think this will fail if num and den aren't 1-D after
# the squeeze
lti_sys = lti(squeeze(sys.num), squeeze(sys.den))
return StateSpace(lti_sys.A, lti_sys.B, lti_sys.C, lti_sys.D,
sys.dt)
A, B, C, D = sp.signal.tf2ss(squeeze(sys.num), squeeze(sys.den))
return StateSpace(A, B, C, D, sys.dt)

elif isinstance(sys, (int, float, complex)):
elif isinstance(sys, (int, float, complex, np.number)):
if "inputs" in kw:
inputs = kw["inputs"]
else:
Expand Down
33 changes: 17 additions & 16 deletions control/xferfcn.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@
"""

# External function declarations
import numpy as np
from numpy import angle, any, array, empty, finfo, insert, ndarray, ones, \
polyadd, polymul, polyval, roots, sort, sqrt, zeros, squeeze, exp, pi, \
where, delete, real, poly, poly1d
import numpy as np
import scipy as sp
from scipy.signal import lti, tf2zpk, zpk2tf, cont2discrete
from copy import deepcopy
from warnings import warn
Expand Down Expand Up @@ -126,7 +127,7 @@ def __init__(self, *args):
data = [num, den]
for i in range(len(data)):
# Check for a scalar (including 0d ndarray)
if (isinstance(data[i], (int, float, complex)) or
if (isinstance(data[i], (int, float, complex, np.number)) or
(isinstance(data[i], ndarray) and data[i].ndim == 0)):
# Convert scalar to list of list of array.
if (isinstance(data[i], int)):
Expand All @@ -135,7 +136,7 @@ def __init__(self, *args):
else:
data[i] = [[array([data[i]])]]
elif (isinstance(data[i], (list, tuple, ndarray)) and
isinstance(data[i][0], (int, float, complex))):
isinstance(data[i][0], (int, float, complex, np.number))):
# Convert array to list of list of array.
if (isinstance(data[i][0], int)):
# Convert integers to floats at this point
Expand All @@ -146,7 +147,8 @@ def __init__(self, *args):
elif (isinstance(data[i], list) and
isinstance(data[i][0], list) and
isinstance(data[i][0][0], (list, tuple, ndarray)) and
isinstance(data[i][0][0][0], (int, float, complex))):
isinstance(data[i][0][0][0], (int, float, complex,
np.number))):
# We might already have the right format. Convert the
# coefficient vectors to arrays, if necessary.
for j in range(len(data[i])):
Expand Down Expand Up @@ -363,7 +365,7 @@ def __rsub__(self, other):
def __mul__(self, other):
"""Multiply two LTI objects (serial connection)."""
# Convert the second argument to a transfer function.
if isinstance(other, (int, float, complex)):
if isinstance(other, (int, float, complex, np.number)):
other = _convertToTransferFunction(other, inputs=self.inputs,
outputs=self.inputs)
else:
Expand Down Expand Up @@ -410,7 +412,7 @@ def __rmul__(self, other):
"""Right multiply two LTI objects (serial connection)."""

# Convert the second argument to a transfer function.
if isinstance(other, (int, float, complex)):
if isinstance(other, (int, float, complex, np.number)):
other = _convertToTransferFunction(other, inputs=self.inputs,
outputs=self.inputs)
else:
Expand Down Expand Up @@ -458,7 +460,7 @@ def __rmul__(self, other):
def __truediv__(self, other):
"""Divide two LTI objects."""

if isinstance(other, (int, float, complex)):
if isinstance(other, (int, float, complex, np.number)):
other = _convertToTransferFunction(
other, inputs=self.inputs,
outputs=self.inputs)
Expand Down Expand Up @@ -492,7 +494,7 @@ def __div__(self, other):
# TODO: Division of MIMO transfer function objects is not written yet.
def __rtruediv__(self, other):
"""Right divide two LTI objects."""
if isinstance(other, (int, float, complex)):
if isinstance(other, (int, float, complex, np.number)):
other = _convertToTransferFunction(
other, inputs=self.inputs,
outputs=self.inputs)
Expand Down Expand Up @@ -1128,22 +1130,21 @@ def _convertToTransferFunction(sys, **kw):
# Each transfer function matrix row
# has a common denominator.
den[i][j] = list(tfout[5][i, :])
# print(num)
# print(den)

except ImportError:
# If slycot is not available, use signal.lti (SISO only)
if (sys.inputs != 1 or sys.outputs != 1):
raise TypeError("No support for MIMO without slycot")

lti_sys = lti(sys.A, sys.B, sys.C, sys.D)
num = squeeze(lti_sys.num)
den = squeeze(lti_sys.den)
# print(num)
# print(den)
# Do the conversion using sp.signal.ss2tf
# Note that this returns a 2D array for the numerator
num, den = sp.signal.ss2tf(sys.A, sys.B, sys.C, sys.D)
num = squeeze(num) # Convert to 1D array
den = squeeze(den) # Probably not needed

return TransferFunction(num, den, sys.dt)

elif isinstance(sys, (int, float, complex)):
elif isinstance(sys, (int, float, complex, np.number)):
if "inputs" in kw:
inputs = kw["inputs"]
else:
Expand Down