import numpy as np
from scipy import signal
import matplotlib.pyplot as plt

"""
Explanation: Transfer functions and time response
Here we'll define several transfer functions and investigate their responses to a variety of inputs.
Consider the transfer function below which defines our system
$$
G(s) = \frac{2s +25}{s^2 + 4s + 25}
$$
This second order transfer function defines our system, which we can also define within Python.
This example will use the following:

Matplotlib - used to create plots
Scipy Signal - Signal response and processing
End of explanation
"""


num = [2, 25]
den = [1, 4, 25]

sys = signal.TransferFunction(num, den)

"""
Explanation: Now we can define the transfer function using scipy
This system representation allows us to use many of the functions within scipy.signal. 
There are many equivalent variations to define a continuous transfer function.
https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.TransferFunction.html#scipy.signal.TransferFunction
End of explanation
"""


time, response = signal.step(sys)

"""
Explanation: Step response
Recall the step response of our system is defined as
$$
Y(s) = U(s) G(s)
$$
where $ U(s) $ is the unit step.
Here we use Scipy to numerically output the response
End of explanation
"""


plt.plot(time,response,label="Simulation")
plt.show()

"""
Explanation: Once we have the response we can plot it using matplotlib
End of explanation
"""


t = np.linspace(0, 5)
u = 1 * t
tout, resp, x = signal.lsim(sys, u, t)

"""
Explanation: Simulating any arbitrary input
We can use some built in functions for the common step and impulse inputs.
However, if we want to apply any signal we need to use something different.
Here we'll find the response to our system given a ramp input
$$
u(t) = t
$$
We need to define a time vector and an input vector
End of explanation
"""


plt.plot(t, resp, label='Output')
plt.plot(t, u, label='Input')
plt.legend()
plt.title('Ramp Response')
plt.xlabel('Time (sec)')
plt.ylabel('Response')
plt.grid()
plt.show()

"""
Explanation: Now we'll plot the output and input and make our plot a little more fancy
End of explanation
"""


