Equivalent to MATLAB's freqz in Julia - matlab

MATLAB has a nice library of digital signals processing functions that give you a lot of control over linear-time invariant systems. My goal is to view the frequency response of a system governed by two vectors a=[1, -1.1, 0.46] and b=[1, 0.04, 0.76].
To do this in MATLAB, I'd just use the freqz(b,a) and get back the frequency response h and frequencies evaluated w. I am working in Julia and am using the DSP package, so I'm attempting to use the DSP.Filters.freqresp function. To set this up, I define the vectors and import the relevant package:
a=[1, -1.1, 0.46]
b=[1, 0.04, 0.76]
using DSP.Filters : freqresp
h, w = freqresp([b,a])
When I run this I get the error
MethodError: no method matching freqresp(::Vector{Int64})
How should I be implementing this function to obtain a valid result?

#Shayan pointed me in the right direction by mentioning PolynomialRatio, as plugging in the a and b vectors give a representation that freqresp will accept. As a result, I get the same answer as in MATLAB
a=[1, -1.1, 0.46]
b=[1, 0.04, 0.76]
using DSP
z = PolynomialRatio(b,a)
h, w = freqresp(z)
mag = abs.(h)
phase = atan.(imag.(h)./real.(h))*180/pi
p1 = plot(w, mag)
xaxis!("")
yaxis!("Magnitude")
p2 = plot(w, phase)
xaxis!("Normalized Frequency")
yaxis!("Wrapped Phase [deg]")
plot(p1, p2, layout=(2,1))
Which gives

You can also make use of the ControlSystems.jl package for this:
julia> using ControlSystemsBase, Plots
julia> a=[1, -1.1, 0.46]
3-element Vector{Float64}:
1.0
-1.1
0.46
julia> b=[1, 0.04, 0.76]
3-element Vector{Float64}:
1.0
0.04
0.76
julia> Z = tf(b,a,1)
TransferFunction{Discrete{Int64}, ControlSystemsBase.SisoRational{Float64}}
1.0z^2 + 0.04z + 0.76
---------------------
1.0z^2 - 1.1z + 0.46
Sample Time: 1 (seconds)
Discrete-time transfer function model
julia> bodeplot(Z)
The bodeplot plot recipe handles phase unrolling etc. for you.

Related

How to correctly set the 'rtol' and 'atol' in scipy integration module 'solve_ivp' for solving a system of ODE with unknown analytic solution?

I was trying to reproduce some results of ode45 solver in Python using solve_ivp. Though all parameters, initial conditions, step size, and 'atol' and 'rtol' (which are 1e-6 and 1e-3) are same, I am getting different solutions. Both of the solutions are converging to a periodic solution but of different kind. As solve_ivp uses same rk4(5) method as ode45, this discrepancy in the final result is not quite understable. How can we know which one is the correct solution?
The code is included below
import sys
import numpy as np
from scipy.integrate import solve_ivp
#from scipy import integrate
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
# Pendulum rod lengths (m), bob masses (kg).
L1, L2, mu, a1 = 1, 1, 1/5, 1
m1, m2, B = 1, 1, 0.1
# The gravitational acceleration (m.s-2).
g = 9.81
# The forcing frequency,forcing amplitude
w, a_m =10, 4.5
A=(a_m*w**2)/g
A1=a_m/g
def deriv(t, y, mu, a1, B, w, A): # beware of the order of the aruments
"""Return the first derivatives of y = theta1, z1, theta2, z2, z3."""
a, c, b, d, e = y
#c, s = np.cos(theta1-theta2), np.sin(theta1-theta2)
adot = c
cdot = (-(1-A*np.sin(e))*(((1+mu)*np.sin(a))-(mu*np.cos(a-b)*np.sin(b)))-((mu/a1)*((d**2)+(a1*np.cos(a-b)*c**2))*np.sin(a-b))-(2*B*(1+(np.sin(a-b))**2)*c)-((2*B*A/w)*(2*np.sin(a)-(np.cos(a-b)*np.sin(b)))*np.cos(e)))/(1+mu*(np.sin(a-b))**2)
bdot = d
ddot = ((-a1*(1+mu)*(1-A*np.sin(e))*(np.sin(b)-(np.cos(a-b)*np.sin(a))))+(((a1*(1+mu)*c**2)+(mu*np.cos(a-b)*d**2))*np.sin(a-b))-((2*B/mu)*(((1+mu*(np.sin(a-b))**2)*d)+(a1*(1-mu)*np.cos(a-b)*c)))-((2*B*a1*A/(w*mu))*(((1+mu)*np.sin(b))-(2*mu*np.cos(a-b)*np.sin(a)))*np.cos(e)))/(1+mu*(np.sin(a-b))**2)
edot = w
return adot, cdot, bdot, ddot, edot
# Initial conditions: theta1, dtheta1/dt, theta2, dtheta2/dt.
y0 = np.array([3.15, -0.1, 3.13, 0.1, 0])
# Do the numerical integration of the equations of motion
sol = integrate.solve_ivp(deriv,[0,40000], y0, args=(mu, a1, B, w, A), method='RK45',t_eval=np.arange(0, 40000, 0.005), dense_output=True, rtol=1e-3, atol=1e-6)
T = sol.t
Y = sol.y
I am expecting similar result from ode45 in MATLAB and solve_ivp in Python. How can I exactly reproduce the result from ode45 in python? What is the reason of discrepancy?
Even if ode45and RK45use the same underlying scheme, they do not necessarily use the same exact strategy regarding the evolution of the time step and its adaptation to match the error tolerance. Thus, it is difficult to know which one is better.
The only thing you could is simply trying lower tolerances, e.g. 1e-10. Then, both solutions should end up being virtually identical... Here, your current error tolerance might be insufficiently low, so that small discrepancies in the fine details of both algorithms create a visible difference in the solution.

Algorithm for vitamin D concentration - problem with writting algorithm based on formulas

I am trying to implement in Matlab an algorithm that calculates the vitamin D concentration in the blood based on some formulas from an article. Main formula is:
where:
- T is the day of the year for which the concentration is measured;
- A is constant for the simplest measurement described in the journal
- E (sun exposure on particular month in a year) is given in the article
- R (vitamin D concentration after single exposure for the sunlight) can be calculated using formula
where F, alpha, beta are constants, t - day.
An Author of the article wrote that after calculating concentration using C(t) formula he added a constant value 33 in every day.
Formula for R(t) is simple and my chart is the same as in the article, but I have a problem with formula for calculating C(t).
This is my code:
function [C] = calculateConcentration(A,E,T,R)
C=zeros(1,T);
C(1) = E(1)*A*R(1);
month=1;
for i=2:(T)
for j=1:i
if mod(j,30)==0 && month<12
month=month+1;
end
C(i) = C(i)+E(month)*A*R(T-j+1);
end
month=1;
end
for i=1:T
C(i)=C(i)+33;
end
end
Here is my chart:
Here is the chart from the article:
So, I have two problems with this chart. First, the biggest values on my chart are smaller than values on the chart from the article and second, my chart is constantly growing.
Thank you very much in advance help.
[EDIT] I attach the values of all constants and a function to calculate R (t).
function [R]= calculateR(T)
R = zeros(1,T);
F = 13;
alpha = 30;
beta = 3;
for i=1:T
R(i)=F*(2.^(-i/alpha)-2.^(-i/beta));
end
end
A=0.1;
T=365;
R = calculateR(T);
E = [0.03, 0.06, 0.16, 0.25, 0.36, 0.96, 0.87, 0.89, 0.58, 0.24, 0.08, 0.02];
plot(1:T,R)
C = calculateConcentration(A,E,T,R);
figure; plot(1:T,C);
Code formatting is horrible in comments so posting this as an answer.
I have stated what I think (!) is the basic problem with your code in the comments.
Cumulative sums can get confusing very quickly, hence it is often better to write them more explicitly.
I would write the function like so:
function C = calculateConcentration(T, E, A, R)
c = zeros(1, T);
% compute contribution of each individual day
for t = 1:T
c(t) = E(mod(floor(t / 30), 12) +1) * A * R(t);
end
% add offset
c(1) = c(1) + 33;
C = cumsum(c);
end
Disclaimer: I haven't written any matlab code in years, and don't have it installed on this machine, so make sure to test this.
EDIT
Not sure if the author is plotting what you say he is plotting.
If you chose A to be 100 (this might be fine with the correct choice of units), apply the offset of c(1) to all values of c (in my implementation), don't actually take the cumulative sum, but return (lowercase) c instead, and then only plot the data from the midpoint in each month, then you get the following plot:
However, it is worth noting that if you plot all data points you get the following.
At face value, I would say whoever came up with this model is full of BS. But a more definitive answer would require a careful read of the paper.

Find z-transform and plot it's pole-zero map with MATLAB

I have this function:
x[n] = (1/2) ^ n * u[n] + (-1/3) ^ n * u[n]
I need to do two things with this using MATLAB:
Find it's z-transform.
Plot it's poles and zeros.
I am using the following code:
syms n;
f = (1/2)^n + (-1/3)^n;
F = ztrans(f);
I get the z-transform in the F variable, but I can't see how to create it's pole-zero plot. I am using the built-in function pzmap (pzmap(F);), but it doesn't seem to work with the output of ztrans(f).
What am I doing wrong? Do I need to change the z-transform into some other form like like a transfer function model or a zero-pole gain model? If so, can someone explain how that can be done using the output of ztrans(f)?
The first bit of code you gave uses symbolic math to solve for the z-transform. You'll need to convert the output to a discrete-time model supported by the Control System toolbox.
syms n;
f = (1/2)^n + (-1/3)^n;
F = ztrans(f)
returns z/(z - 1/2) + z/(z + 1/3). You can optionally use collect to convert this
F2 = collect(F)
to (12*z^2 - z)/(6*z^2 - z - 1). Then you'll want to find the coefficients of the polynomials in the numerator and denominator and create a discrete-time transfer function object with tf for a particular sampling period:
[num,den] = numden(F2);
Ts = 0.1; % Sampling period
H = tf(sym2poly(num),sym2poly(den),Ts)
Then pzmap(H) will produce a plot like this:

Octave - logsig transfer function

Does Octave have a built-in logistic transfer function similar to Matlab's logsig function?
I don't believe Octave does, but you can certainly create logsig outputs yourself. The logsig transfer function (or the Log-Sigmoid function... or simply the Sigmoid function) is simply defined as:
a = 1 ./ (1 + exp(-n));
n would be the input values stored in a vector / matrix / etc. As such, simply place your values into a matrix / vector into n, then use the above code to apply the logsig function to every value that is defined in n.
Example
n = [0; 1; -0.5; 0.5];
a = 1 ./ (1 + exp(-n))
a =
0.5000
0.7311
0.3775
0.6225
Comparing this with MATLAB's logsig function, we get:
a2 = logsig(n)
a2 =
0.5000
0.7311
0.3775
0.6225
logsig is part of the nnet octave-forge package. http://sourceforge.net/p/octave/code/HEAD/tree/trunk/octave-forge/main/nnet/inst/logsig.m
If it's not in core Matlab (Neural Network Toolbox in this case) you should have a look at the corresponding octave-forge package. Unfortunally nnet is unmaintained.
The logsig.m linked is basically the same as rayrengs but also checks for finite.

Calculate posterior distribution of unknown mis-classification with PRTools in MATLAB

I'm using the PRTools MATLAB library to train some classifiers, generating test data and testing the classifiers.
I have the following details:
N: Total # of test examples
k: # of
mis-classification for each
classifier and class
I want to do:
Calculate and plot Bayesian posterior distributions of the unknown probabilities of mis-classification (denoted q), that is, as probability density functions over q itself (so, P(q) will be plotted over q, from 0 to 1).
I have that (math formulae, not matlab code!):
Posterior = Likelihood * Prior / Normalization constant =
P(q|k,N) = P(k|q,N) * P(q|N) / P(k|N)
The prior is set to 1, so I only need to calculate the likelihood and normalization constant.
I know that the likelihood can be expressed as (where B(N,k) is the binomial coefficient):
P(k|q,N) = B(N,k) * q^k * (1-q)^(N-k)
... so the Normalization constant is simply an integral of the posterior above, from 0 to 1:
P(k|N) = B(N,k) * integralFromZeroToOne( q^k * (1-q)^(N-k) )
(The Binomial coefficient ( B(N,k) ) can be omitted though as it appears in both the likelihood and normalization constant)
Now, I've heard that the integral for the normalization constant should be able to be calculated as a series ... something like:
k!(N-k)! / (N+1)!
Is that correct? (I have some lecture notes with this series, but can't figure out if it is for the normalization constant integral, or for the overall distribution of mis-classification (q))
Also, hints are welcome as how to practically calculate this? (factorials are easily creating truncation errors right?) ... AND, how to practically calculate the final plot (the posterior distribution over q, from 0 to 1).
I really haven't done much with Bayesian posterior distributions ( and not for a while), but I'll try to help with what you've given. First,
k!(N-k)! / (N+1)! = 1 / (B(N,k) * (N + 1))
and you can calculate the binomial coefficients in Matlab with nchoosek() though it does say in the docs that there can be accuracy problems for large coefficients. How big are N and k?
Second, according to Mathematica,
integralFromZeroToOne( q^k * (1-q)^(N-k) ) = pi * csc((k-N)*pi) * Gamma(1+k)/(Gamma(k-N) * Gamma(2+N))
where csc() is the cosecant function and Gamma() is the gamma function. However, Gamma(x) = (x-1)! which we'll use in a moment. The problem is that we have a function Gamma(k-N) on the bottom and k-N will be negative. However, the reflection formula will help us with that so that we end up with:
= (N-k)! * k! / (N+1)!
Apparently, your notes were correct.
Let q be the probability of mis-classification. Then the probability that you would observe k mis-classifications in N runs is given by:
P(k|N,q) = B(N,k) q^k (1-q)^(N-k)
You need to then assume a suitable prior for q which is bounded between 0 and 1. A conjugate prior for the above is the beta distribution. If q ~ Beta(a,b) then the posterior is also a Beta distribution. For your info the posterior is:
f(q|-) ~ Beta(a+k,b+N-k)
Hope that helps.