I am trying to take numbers from two intervals in Julia. The problem is the following, I am trying to create concentric circles and I need to generate vectors of dimension equal to 15 filled with numbers taken from each circle. The code is:
rmax = 5
ra = fill(0.0,1,rmax)
for i=1:rmax-1
ra[:,i].=rad/i
ra[:,rmax].= 0
end
for i=1:3
ptset = Any[]
for j=1:200
yt= 0
yt= rand(Truncated(Normal(0, 1), -ra[i], ra[i] ))
if -ra[(i+1)] < yt <= -ra[i] || ra[(i+1)] <= yt < ra[i]
push!(ptset,yt)
if length(ptset) == 15
break
end
end
end
end
Here I try to take elements that fulfill one of the two conditions
-ra[(i+1)] < yt <= -ra[i]
or
ra[(i+1)] <= yt < ra[i]
i.e. I would like to generate a vector with positive and negative numbers. I used the operator || but it seems to take only the positive part. I am new in Julia and I am not sure how to take the elements from both parts of the interval. Does anyone has a hit on how to do it?. Thanks in advance
using LinearAlgebra # for norm()
function randshell(dimension, inner_radius::T, thickness::T) where {T<:AbstractFloat}
v = randn(dimension)
while norm(v) < 1e-3
v = randn(dimension)
end
r = thickness * rand(T)^(1/dimension) + inner_radius
return r * v / norm(v)
end
Edit:
This is tricky to visualize, so I tried cutting out a corner of the sphere so you could see the shell. Works OK if you can interact with it.
using Plots
plotlyjs()
function plotit(N=10_000)
points = zeros(Float64, 3, N)
for i in 1:N
points[:, i] = randshell(3, 4.0, 2.0)
end
# cut out a corner so you can see the shell
# all points with all positive coordinates
cut_points = points[:, ((points[1, :] .> 0) .& (points[2, :] .> 0) .& (points[3, :] .> 0))]
scatter(cut_points[1, :], cut_points[2, :], cut_points[3, :], c=round.(Integer, (6 .+ cut_points[3, :])),
markersize=2, cmap="Spectral", aspect_ratio=:equal)
end
Thank you for your nice reply and the code. Just a question, I understood that the code creates uniform points inside a sphere with radius thikness, and then it changes it adding inner_radius, but I think that I missed the concept, so when I try
N=1
dimen=15
rad = 0.8660254037844386
rmax = 4
ra = range(0, rad, length=rmax)
points = zeros(Float64, dimen, N)
for j=1: rmax
for i in 1:N
points[:, i] = randshell( dimen, ra[2] , ra[j] )
end
end
I will obtain numbers for a sphere of radius ra[j] plus ra[2], is that correct?. I think is a silly question, but I am misunderstanding something in in the randshell function. Thanks in advance.
Yes, you are correct. The function creates a shell of points in the interval r=inner_radius to r=(inner_radius + thickness) with uniform direction. The important part is to scale the density of points so that they are uniform in volume (the ^(1 / dimension)). I’m pretty sure adding inner_radius afterwards should be the same as scaling (thickness + inner_radius) and then discarding all the points smaller than inner_radius.