I am facing a challenge with julia range - julia

I am new to Julia.
While trying out examples online, I got to the plot below:
using Plots
# 10 data points in 4 series
xs = range(0, 2π, length = 10)
data = [sin.(xs) cos.(xs) 2sin.(xs) 2cos.(xs)]
# We put labels in a row vector: applies to each series
labels = ["Apples" "Oranges" "Hats" "Shoes"]
# Marker shapes in a column vector: applies to data points
markershapes = [:circle, :star5]
# Marker colors in a matrix: applies to series and data points
markercolors = [
:green :orange :black :purple
:red :yellow :brown :white
]
plot(
xs,
data,
label = labels,
shape = markershapes,
color = markercolors,
markersize = 10
)
The Problem I am facing is at the beginning. Even if I try below alone on REPL
julia> xs = range(0, 2π, length = 10)
I receive the error below:
ERROR: MethodError: no method matching range(::Int64, ::Float64; length=10)
Closest candidates are:
range(::Any; length, stop, step) at range.jl:76
Stacktrace:
[1] top-level scope at none:0
Did I forget to include some Package?

Which version of Julia are you using? It sounds like you are using a version that is older than the tutorial you are reading. I can verify that range(0, 2π, length = 10) yields 0.0:0.6981317007977318:6.283185307179586 on Julia 1.5 and Julia 1.6, even without specifying stop

I guess I should have made more research before posting. it's an error in the original post I guess.
I should have used:
julia> xs = range(0, stop=2π, length = 10)
0.0:0.6981317007977318:6.283185307179586
No more errors!!
It's weird, I am following official tutorial... :((

Related

Understanding Forward.Diff issues

I got an apparently quite common Julia error when trying to use AD with forward.diff. The error messages vary a bit (sometimes matching function name sometimes Float64)
MethodError: no method matching logL_multinom(::Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(logL_multinom), Real}, Real, 7}})
My goal: Transform a probability vector to be unbounded (θ -> y), do some stuff (namely HMC sampling) and transform back to the simplex space whenever the unnormalized posterior (logL_multinom()) is evaluated. DA should be used to overome problems for later, more complex, models than this.
Unfortunately, neither the Julia documentation, not the solutions from other questions helped me figure the particular problem out. Especially, it seems to work when I do the first transformation (y -> z) outside of the function, but the first transformation is a 1-to-1 mapping via logistic and should not cause any harm to differentiation.
Here is an MWE:
using LinearAlgebra
using ForwardDiff
using Base
function logL_multinom(y)
# transform to constrained
K = length(y)+1
k = collect(1:(K-1))
# inverse logit:
z = 1 ./ (1 .+ exp.(-y .- log.(K .- k))) # if this is outside, it works
θ = zeros(eltype(y),K) ; x_cumsum = zeros(eltype(y),K-1)
typeof(θ)
for i in k
x_cumsum[i] = 1-sum(θ)
θ[i] = (x_cumsum[i]) * z[i]
end
θ[K] = x_cumsum[K-1] - θ[K-1]
#log_dens_correction = sum( log(z*(1-z)*x_cumsum) )
dot(colSums, log.(θ))
end
colSums = [835, 52, 1634, 3469, 3053, 2507, 2279, 1115]
y0 = [-0.8904013824298864, -0.8196709647741431, -0.2676845405543302, 0.31688184351556026, -0.870860684394019,0.15187821053559714,0.39888119498547964]
logL_multinom(y0)
∇L = y -> ForwardDiff.gradient(logL_multinom,y)
∇L(y0)
Thanks a lot and especially some further readings/ explanations for the problem are appreciated since I'll be working with it moreoften :D
Edit: I tried to convert the input and any intermediate variable into Real / arrays of these, but nothing helped so far.

What is the equivalent of Matlab's mesh function in Julia Plots.jl

In Matlab, we would first use [x, y] = meshgrid to generate the grid, then use mesh(x, y, z) to plot the 3D plot. I want to use the same funtionality in Julia Plots.jl, which API should I use? And how can I achieve that?
Thanks a lot in advance!!!
use surface
using Plots
xs = range(-2, stop=2, length=100)\
ys = range(-pi, stop=pi, length=100)
f(x,y) = x*sin(y)
surface(xs, ys, f)
In modern Julia, v1.17, the approach is to create x and y ranges. Julia has changed over the years, and used to have linspace - it doesn't anymore.
There are three ways to create a range:
x = start:step:end
x = range(start,end,step=step)
x = range(start,end,length=npts)
You will also need Plots. If you precompile it, it takes less time to load.
]
pkg > add Plots
pkg > precompile
pkg > Ctrl-C
You need to select your backend for Plots. Choices are:
pyplot() to select PyPlot (also requires Python's MatPlotLib)
plotly() to select Plotly (displays in web browser)
gr() to select GR, the default
Finally, you need to use surface to draw the surface. The function surface can take either a function or a matrix of z values. The function takes two parameters, x and y. Either the function is supplied directly, or it is applied to the ranges:
z = f.(x',y);
One of the ranges is transposed with ', and output suppressed with ;
Surface also takes optional parameters:
fill = :fillname
legend = true | false
size = (width,height)
clims = (lowlimit,highlimit)
An example:
using Plots
plotly()
x=range(-5,5,length=101)
y=range(-5,5,length=101)
function f(x,y)
r = sqrt(x^2+y^2)
sinc(r)
end
z = f.(x',y);
surface(x,y,z,size=(1600,1000),fill=:greens,legend=false)

Use LsqFit for multi-variate output?

I wanted to fit a geometric mapping parameter with some input/output (x,y) points. The model is very simple:
xp = x .+ k.*x.*(x.^2+y.^2)
yp = y .+ k.*y.*(x.^2+y.^2)
k is the only parameter, (x,y) is an input point and (xp,yp) is an output point.
I formulated the input/output data array as:
x = [x for x=-2.:2. for y=-2.:2.]
y = [y for x=-2.:2. for y=-2.:2.]
in_data = [x y]
out_data = [xp yp]
However I'm confused about how to turn this into the LsqFit model, I tried:
k0=[0.]
#. model(x,p) = [x[:,1]+p[1]*x[:,1]*(x[:,1]^2+x[:,2]^2) x[:,2]+p[1]*x[:,2]*(x[:,1]^2+x[:,2]^2)]
ret = curve_fit(model, in_data, out_data, k0)
but got an error:
DimensionMismatch("dimensions must match: a has dims (Base.OneTo(25),
Base.OneTo(2)), must have singleton at dim 2")
So the question is: is it possible to use LsqFit for multi-variate output? (even though this particular problem can be solved analytically)
OK Just figured out the correct way to do this. The vector output variable needs to be stacked together to form a 1D array. So the only changes needed is:
out_data = [xp; yp]

How to plot Daubechies psi and phi wavelet functions in R?

The analysis with wavelets seems to be carried out as a discrete transform via matrix multiplication. So it is not surprising, I guess, that when plotting, for example, D4, the R package wmtsa returns the plot:
require(wmtsa)
filters <- wavDaubechies("d4")
plot(filters)
The question is how to go from this discretized plot to the plot in the Wikipedia entry:
Please note that I'm not interested in generating these curves precisely with wmtsa. Any other package will do - I don't have Matlab or Mathematica. But I wonder if the way to go is to start with translating this Mathematica chunk of code in this paper into R, rather than using built-in functions:
Wave1etTransform.m
c[k-1 := c[k] = Daubechies[4][[k+l]];
phi[l] = (l+Sqrt[3])/2 // N;
phi[2] = (l-Sqrt[3])/2 // N;
phi[xJ; xc=0 II x>=3] : = 0
phi[x-?NumberQ] := phi[x] =
N[Sqrt[2]] Sum[c[k] phi[2x-k],{k,0,3}];
In order to plot the wavelet and scaling function all you need are the four numbers shown in the first two plots. I'll focus on plotting the scaling function.
Integer shifts of the scaling function, 𝜑, form an orthonormal basis of the subspace V0 of the multiresolution analysis. We also have that V-1 ⊆ V0 and that 𝜑(x/2) ∈ V-1. Using this gives us the identity
𝜑(x/2) = ∑k ∈ ℤ hk𝜑(x-k)
Now we just need the values of hk. For the Daubechies wavelet these are the values show in the discrete plot you gave (and zero for every other value of k). For an exact value of the hk, first let 𝜇 = (1+sqrt(3))/2. Then we have that
h0 = 𝜇/4
h1 = (1+𝜇)/4
h2 = (2-𝜇)/4
h3 = (1-𝜇)/4
and hk = 0 otherwise.
Using these two things we are able to plot the function using what is known as the cascade algorithm. First notice that 𝜑(0) = 𝜑(0/2) = h0𝜑(0) + h1𝜑(0-1) + h2𝜑(0-2) + h3𝜑(0-3). The only way this equation can hold is if 𝜑(0) = 𝜑(-1) = 𝜑(-2) = 𝜑(-3) = 0. Extending this will show that for x ≦ 0 we have that 𝜑(x) = 0. Furthermore, a similar argument can show that 𝜑(x) = 0 for x ≥ 3.
Thus, we only need to worry about x = 1 and x = 2 to find non-zero values of 𝜑 for integer values of x. If we put x = 2 into the identity for 𝜑(x/2) we get that 𝜑(1) = h0𝜑(2) + h1𝜑(1). Putting x = 4 into the identity gives us that 𝜑(2) = h2𝜑(2) + h3𝜑(1).
We can rewrite the above two equations as a matrix multiplied by a vector equals a vector. In fact, it will be in the form v = Av (v is the same vector on both sides). This means that v is an eigenvector of the matrix A with eigenvalue 1. But v = (𝜑(1), 𝜑(2)) and so by finding this eigenvector using the standard methods we will be able to find the values of 𝜑(1) and 𝜑(2).
In fact, this gives us that 𝜑(1) = (1+sqrt(3))/2 and 𝜑(2) = (1-sqrt(3))/2 (this is where those values in the Mathematica code sample come from). Also note that we need to specifically chose the eigenvector of magnitude 2 for this algorithm to work so you must use those values for 𝜑(1) and 𝜑(2) even though you could rescale the eigenvector.
Now we can find the values of 𝜑(1/2), 𝜑(3/2), and 𝜑(5/2). For example, 𝜑(1/2) = h0𝜑(1) and 𝜑(3/2) = h1𝜑(2) + h2𝜑(1).
With these values, you can then find the values of 𝜑(1/4), 𝜑(3/4), and so on. Continuing this process will give you the value of 𝜑 for all dyadic rationals (rational numbers in the form k/2j.
The same process can be used to find the wavelet function. You only need to use the four different values shown in the first plot rather than the four shown in the second plot.
I recently implemented this Python. An R implementation will be fairly similar.
import numpy as np
import matplotlib.pyplot as plt
def cascade_algorithm(j: int):
mu = (1 + np.sqrt(3))/2
h_k = np.array([mu/4, (1+mu)/4, (2-mu)/4, (1-mu)/4])
# Array to store all the value of phi.
phi_vals = np.zeros((2, 3*2**j+1), dtype=np.float64)
for i in range(3*2**j+1):
phi_vals[0][i] = i/(2**j)
calced_vals = np.zeros((3*2**j+1), dtype=np.bool)
# Input values for 1 and 2.
phi_vals[1][1*2**j] = (1+np.sqrt(3))/2
phi_vals[1][2*2**j] = (1-np.sqrt(3))/2
# We now know the values for 0, 1, 2, and 3.
calced_vals[0] = True
calced_vals[1*2**j] = True
calced_vals[2*2**j] = True
calced_vals[3*2**j] = True
# Now calculate for all the dyadic rationals.
for k in range(1, j+1):
for l in range(1, 3*2**k):
x = l/(2**k)
if calced_vals[int(x*2**j)] != True:
calced_vals[int(x*2**j)] = True
two_x = 2*x
which_k = np.array([0, 1, 2, 3], dtype=np.int)
which_k = ((two_x - which_k > 0) & (two_x - which_k < 3))
phi = 0
for n, _ in enumerate(which_k):
if which_k[n] == True:
phi += h_k[n]*phi_vals[1][int((two_x-n)*2**j)]
phi_vals[1][int(x*2**j)] = 2*phi
return phi_vals
phi_vals = cascade_algorithm(10)
plt.plot(phi_vals[0], phi_vals[1])
plt.show()
If you just want to plot the graphs, then you can use the package "wavethresh" to plot for example the D4 with the following commands:
draw.default(filter.number=4, family="DaubExPhase", enhance=FALSE, main="D4 Mother", scaling.function = F) # mother wavelet
draw.default(filter.number=4, family="DaubExPhase", enhance=FALSE, main="D4 Father", scaling.function = T) # father wavelet
Notice that the mother wavelet and the father wavelets will be plotted depending on the variable "scaling.function". If true, then it plots the father wavelet (scaling), else it plots the mother wavelet.
If you want to generate it by yourself, without packages, I'd suggest you follow Daubechies-Lagarias algorithm, in this paper. It is not hard to implement.

Julia - plot with 2 arrays of same size

I have two arrays:
sigma = logspace(-4,4,5)
which looks like = [10^-4,10^-2,10,10^2,10^4]
and some other array that contains 5 values which were generated from norm-2 of some 5 different vectors.
assume this is the second array:
Xnorm = [1,2,3,4,5]
I'm trying to plot those two arrays:
figure()
plot(Xnorm,sigma)
I would like that sigma will represent the X-axis and Xnorm the y-axis.
The result right now is an empty graph. (I've tried to swap between both of them also).
Unfortunately, I did not found any good documentation for plotting with array.
You need to import the plotting library
sigma = logspace(-4,4,5)
Xnorm = [1,2,3,4,5]
# Pkg.add("Plots") # Do this only the first time to install.
using Plots
plot(Xnorm,sigma)

Resources