I would like to simulate/model a closed-loop, linear, time-invariant system (specifically a locked PLL approximation) with python.
Each sub-block within the model has a known transfer function which is given in terms of complex frequency H(s) = K / ( s * tau + 1 ). Using the model, I would like to see how the system response as well as the noise response is affected as parameters (e.g. the VCO gain) are changed. This would involve using Bode plots and root-locus plots.
What Python modules should I seek out to get the job done?
I know this is a bit old, but a search brought me to this question. I put this together when I couldn't find a good module for it. It's not much, but it's a good start if somebody else finds themselves here.
import matplotlib.pylab as plt
import numpy as np
import scipy.signal
def bode(G,f=np.arange(.01,100,.01)):
plt.figure()
jw = 2*np.pi*f*1j
y = np.polyval(G.num, jw) / np.polyval(G.den, jw)
mag = 20.0*np.log10(abs(y))
phase = np.arctan2(y.imag, y.real)*180.0/np.pi % 360
plt.subplot(211)
#plt.semilogx(jw.imag, mag)
plt.semilogx(f,mag)
plt.grid()
plt.gca().xaxis.grid(True, which='minor')
plt.ylabel(r'Magnitude (db)')
plt.subplot(212)
#plt.semilogx(jw.imag, phase)
plt.semilogx(f,phase)
plt.grid()
plt.gca().xaxis.grid(True, which='minor')
plt.ylabel(r'Phase (deg)')
plt.yticks(np.arange(0, phase.min()-30, -30))
return mag, phase
f=scipy.signal.lti([1],[1,1])
bode(f)
Edit: I am back here because somebody upvoted this answer, you should try Control Systems Library. They have implemented the bulk of the Matlab control systems toolbox with matching syntax and everything.
According to http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.bode.html
you can now use this:
from scipy import signal
import matplotlib.pyplot as plt
s1 = signal.lti([1], [1, 1])
w, mag, phase = signal.bode(s1)
plt.figure()
plt.semilogx(w, mag) # bode magnitude plot
plt.figure()
plt.semilogx(w, phase) # bode phase plot
plt.show()
As #Matt said, I know this is old. But this came up as my first google hit, so I wanted to edit it.
You can use scipy.signal.lti to model linear, time invariant systems. That gives you lti.bode.
For an impulse response in the form of H(s) = (As^2 + Bs + C)/(Ds^2 + Es + F), you would enter h = scipy.signal.lti([A,B,C],[D,E,F]). To get the bode plot, you would do plot(*h.bode()[:2]).
I got Bode plots working out this way, using python-control.
from matplotlib.pyplot import * # Grab MATLAB plotting functions
from control.matlab import * # MATLAB-like functions
# Transfer functions for dynamics
G_modele = tf([1], [13500, 345, 1]);
# Use state space versions
G_modele = tf2ss(G_modele);
figure(1);
bode(G_modele, dB=1);
show();
The code was mainly taken from this example which is very extensive
http://www.cds.caltech.edu/~murray/wiki/index.php/Python-control/Example:_Vertical_takeoff_and_landing_aircraft
scipy and numpy modules are suited for your application.
Related
I am currently working on a Convolution Neural Network (CNN) and started to look at different spectrogram plots:
With regards to the Librosa Plot (MFCC), the spectrogram is way different that the other spectrogram plots. I took a look at the comment posted here talking about the "undetailed" MFCC spectrogram. How to accomplish the task (Python Code wise) posted by the solution given there?
Also, would this poor resolution MFCC plot miss any nuisances as the images go through the CNN?
Any help in carrying out the Python Code mentioned here will be sincerely appreciated!
Here is my Python code for the comparison of the Spectrograms and here is the location of the wav file being analyzed.
Python Code
# Load various imports
import os
import librosa
import librosa.display
import matplotlib.pyplot as plt
import scipy.io.wavfile
#24bit accessible version
import wavfile
plt.figure(figsize=(17, 30))
filename = 'AWCK AR AK 47 Attached.wav'
librosa_audio, librosa_sample_rate = librosa.load(filename, sr=None)
plt.subplot(4,1,1)
xmin = 0
plt.title('Original Audio - 24BIT')
fig_1 = plt.plot(librosa_audio)
sr = librosa_sample_rate
plt.subplot(4,1,2)
mfccs = librosa.feature.mfcc(y=librosa_audio, sr=librosa_sample_rate, n_mfcc=40)
librosa.display.specshow(mfccs, sr=librosa_sample_rate, x_axis='time', y_axis='hz')
plt.title('Librosa Plot')
print(mfccs.shape)
plt.subplot(4,1,3)
X = librosa.stft(librosa_audio)
Xdb = librosa.amplitude_to_db(abs(X))
librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='hz')
# plt.colorbar()
# maximum frequency
Fs = 96000.
samplerate, data = scipy.io.wavfile.read(filename)
plt.subplot(4,1,4)
plt.specgram(data, Fs=samplerate)
plt.title('Scipy Plot (Fs=96000)')
plt.show()
MFCCs are not spectrograms (time-frequency), but "cepstrograms" (time-cepstrum). Comparing MFCC with spectrogram visually is not easy, and I am not sure it is very useful either. If you wish to do so, then invert the MFCC to get back a (mel) spectrogram, by doing an inverse DCT. You can probably use mfcc_to_mel for that.
This will allow to estimate how much data has been lost in the MFCC forward transformation. But it may not say much about how much relevant information for your task has been lost, or how much reduction there has been in irrelevant noise.
This needs to be evaluated for your task and dataset. The best way is to try different settings, and evaluate performance using the evaluation metrics that you care about.
Note that MFCCs may not be such a great representation for the typical 2D CNNs that are applied to spectrograms. That is because the locality has been reduced: In the MFCC domain, frequencies that are close to eachother are no longer next to eachother in vertical axis. And because 2D CNNs have kernels with limited locality (typ 3x3 or 5x5 early on), this can reduce performance of the model.
I am new in Neural network and matlab. My problem -> I have some XYgraphs (X-data, Y-Time). All graphs have same time, but different X values. Also I have a starting point Z. I want to get the actual graph which start from Z, based on above said XY graphs. I tried it by using "nntool" which was available in matlab. I tried few algorithms like TRAINBR, TRAINLM, TRAINB etc. But the output of the trained network never starts from Z. I tried arranging my data, changed input ranges, tried with higher number of layers, epochs, neurons etc. Nothing worked. Please tell me how to solve this problem. No need to use nntool itself.You can suggest any better options... Please help me... A example picture is here...
From what I can infer, you are trying to interpolate. Naively one can do it by shifting the mean of the data to Z. I don't have MATLAB, but it shouldn't be difficult to read the Python code.
import matplotlib.pyplot as plt
import numpy as np
Z = 250
# Creating some fake data
y = np.zeros((1000,3))
y[:,0] = np.arange(1000)-500
y[:,1] = np.arange(1000)
y[:,2] = np.arange(1000)+500
x = np.arange(1000)
# Plotting fake data
plt.plot(x,y)
#Take mean along Y axis
ymean = np.mean(y,axis=1)
# Shift the mean to the desired Z after shifting it to origin
Zdash = ymean + (Z - ymean[0])
plt.plot(x,y)
plt.plot(x,Zdash)
I try to fit my data to a poisson distribution:
import seaborn as sns
import scipy.stats as stats
sns.distplot(x, kde = False, fit = stats.poisson)
But I get this error:
AttributeError: 'poisson_gen' object has no attribute 'fit'
Other distribution (gamma, etc) de work well.
The Poisson distribution (implemented in scipy as scipy.stats.poisson) is a discrete distribution. The discrete distributions in scipy do not have a fit method.
I'm not very familiar with the seaborn.distplot function, but it appears to assume that the data comes from a continuous distribution. If that is the case, then even if scipy.stats.poisson had a fit method, it would not be an appropriate distribution to pass to distplot.
The question title is "How to fit a poisson distribution with seaborn?", so for the sake of completeness, here's one way to get a plot of the data and its fit. seaborn is only used for the bar plot, using #mwaskom's suggestion to use seaborn.countplot. The fitting is actually trivial, because the maximum likelihood estimation for the Poisson distribution is simply the mean of the data.
First, the imports:
In [136]: import numpy as np
In [137]: from scipy.stats import poisson
In [138]: import matplotlib.pyplot as plt
In [139]: import seaborn
Generate some data to work with:
In [140]: x = poisson.rvs(0.4, size=100)
These are the values in the x:
In [141]: k = np.arange(x.max()+1)
In [142]: k
Out[142]: array([0, 1, 2, 3])
Use seaborn.countplot to plot the data:
In [143]: seaborn.countplot(x, order=k, color='g', alpha=0.5)
Out[143]: <matplotlib.axes._subplots.AxesSubplot at 0x114700490>
The maximum likelihood estimation of the Poisson parameter is simply the mean of the data:
In [144]: mlest = x.mean()
Use poisson.pmf() to get the expected probability, and multiply by the size of the data set to get the expected counts, and then plot using matplotlib. The bars are the counts of the actual data, and the dots are the expected counts of the fitted distribution:
In [145]: plt.plot(k, poisson.pmf(k, mlest)*len(x), 'go', markersize=9)
Out[145]: [<matplotlib.lines.Line2D at 0x114da74d0>]
I am relatively new to Python and trying to use it to solve a second order nonlinear differential equation, specifically the Poisson-Boltzmann equation in an electrolyte.
phi''(r) + (2/r)*phi'(r) = (k^2)*sinh(phi(r))
Essentially it describes the decay of electrostatic potential (phi) away from a charged surface in an electrolyte with the rate of decay governed by a paramter k.
phi(r) - the potential at r
dphi(r) - derivative of potential at r
r - distance from the surface (I am solving for r = 1 to r = R in this case)
and the boundary conditions
phi(1) = 5
dphi(R) = 0
The problem bit of code is as follows
from scipy.integrate import odeint
from scipy.optimize import root
from pylab import * # for plotting commands
k = 0.5
phi = 5
dphi = -10
R = 21
def deriv(z,r): # return derivatives of the array z (where z = [phi, phi'])
return np.array([
(z[1]),
((k**2)*sinh(z[0]))-((2/r)*z[1])
])
result = odeint(deriv,np.array([phi,dphi]),np.linspace(1,R,1017), full_output = 1)
Generally for low values of k the integration works fine and I can use root from scipy.optimize to solve it subject to the boundary conditions, however when I try to use relatively large values of k (0.5 and higher) the integration runs into problems and outputs the following error
Excess work done on this call (perhaps wrong Dfun type).
Having run it with full_output = 1 and had a look at the tcur parameter it seems to count up smoothly until a certain point and then oscillate wildly from very large to very small values. At the same point nfe the number of function evaluations drops to zero. When working correctly the tcur parameter runs smoothly from 1 to R. Could anyone enlighten me to why this is happening? Is it a problem with my implementation or is there an instability in the equation?
Thanks in advance for any help,
Dave
The ODE is probably unstable. The related equation
phi''(r) = (k^2)*sinh(phi(r))
has a solution for k=1 (for corresponding initial conditions at r=1):
phi(r) = 2 arctanh(sin(r))
The solution has a singularity at r=pi/2. A numerical ODE solver will not be able to integrate the equation beyond this point. It's plausible that a similar equation with the first-derivative term (which should be negligible close to singularities anyway) behaves similarly.
The actual problem that you have is that a shooting method using an ODE solver is not a good way to solve boundary value problems --- you should use collocation methods, which are fairly stable. See e.g. http://www.scholarpedia.org/article/Boundary_value_problem and references therein.
For Python software, see https://pypi.python.org/pypi?%3Aaction=search&term=boundary+value+problem&submit=search
It's usually also very easy to write such solvers yourself, as the only needed step is discretization of the problem to a set of (many) equations, after which root can solve them.
In order to generate Autoregressive model, we have the aryule() command and we can also use filtersEstimating AR model. But how do I generate MA model? For instance, can somebody please show how to generate MA(20) model? I could not find any appropriate technique to do so. The noise is generated from a nonlinear map
epsilon(1) = 0.01;
for i =1 : N
epsilon(i+1) = 4*epsilon(i)*(1-epsilon(i));
end
So, the MA model will regress over epsilon terms.
Q1: Shall be extremely helpful if the code and functional form of an MA model is shown preferably MA(20) using the above noise model.
Q2: This is how I generated an AR(20) using random noise but don't know how to use the above equation as the noise instead of using rand for both MA and AR
%Generate sine wave = A*sin(2*pi*f*t + phi)
t = linspace(0,1,1000);
A = 5;
f = 2;
phi = pi/8;
sinewave = A*sin(2*pi*f*t + phi);
noisy_sine=sinewave+0.5*randn(size(t));
subplot(1,2,1);
plot(t, sinewave)
hold on;
subplot(1,2,2);
plot(t,noisy_sine);
%Generate AR model(20)
order =20;
ARCoeff = aryule(noisy_sine,order);
I had a same problem. The following links can help :
https://www.mathworks.com/examples/econometrics/mw/econ-ex18477389-simulate-an-ma-process
Simulate an MA Process
This example shows how to simulate sample paths from a stationary MA(12) process without specifying presample observations.
Contents
Specify a model.
Generate sample paths.
Plot the simulation variance.
Step 1. Specify a model.
Specify the MA(12) model
where the innovation distribution is Gaussian with variance 0.2.
model = arima('Constant',0.5,'MA',{0.8,0.2},...
'MALags',[1,12],'Variance',0.2);
Step 2. Generate sample paths.
Generate 200 sample paths, each with 60 observations.
rng('default')
Y = simulate(model,60,'NumPaths',200);
Step 3. Plot the simulation variance.
figure
plot(Y,'Color',[.85,.85,.85])
hold on
h = plot(mean(Y,2),'k','LineWidth',2)
legend(h,'Simulation Mean','Location','NorthWest')
title('MA(12) Process')
hold off
You can do that with one line of code using filter.
Let us talk about AR and MA in the Laplace domain. Say that your have a transfer function H = B/A, where B and A are polynomials. B have the coefficients of your MA and A will have your AR coefficients. In equations:
Thus, given your input signal x, you can use Matlab's y=filter(B,A,x) to generate your AR, MA and ARMA processes. The documentation about filter is here. For your specific case of a pure MA model, just make B=1 and your A as a vector with 20 elements.
You probably already know that, but just in case and to help future readers here is a link with a review on how to transform your difference equations to Laplace domain. TL;DR: