How to plot a 3-D function using Julia's Plots package? - plot

Is it possible to reproduce this graph using the Julia Plots Package?
Plotting using gnuplot
x = y = -15:0.4:15
f1 = (x,y) -> #. sin(sqrt(x*x+y*y))/sqrt(x*x+y*y)
surf(x, y, f1, w = :p, marker = "dot", Axes(hidden3d = :on))

Not exactly the same, but you can plot a surface with surface:
using Plots
x = y = -15:0.4:15
f(x,y) = sin(sqrt(x^2+y^2))/sqrt(x^2+y^2)
surface(x, y, f)
which will give
or a wireframe
wireframe(x, y, f)
will give
But if you really want a 3D scatter, then you need to create the mesh by hand and rearrange the data into vectors I think, like
X = [x for x in x for y in y]
Y = [y for x in x for y in y]
scatter3d(X, Y, f.(X,Y))

Related

How to Plot a Cylinder with GLMakie or Plotlyjs in Julia?

I want to plot a 3-dimensional cylinder.
the parametric equations will be like this:
x= r*cos(u)
y=r*sin(u)
z=v
with $u \in [0, 2 \pi] $ and $v \in [0, h]$
I am able to create a sphere with GLMakie with this code:
using GLMakie
n = 20
θ = [0;(0.5:n-0.5)/n;1]
φ = [(0:2n-2)*2/(2n-1);2]
x = [cospi(φ)*sinpi(θ) for θ in θ, φ in φ]
y = [sinpi(φ)*sinpi(θ) for θ in θ, φ in φ]
z = [cospi(θ) for θ in θ, φ in φ]
surface(x, y, z)
but when I try to make a cylinder it fails:
using GLMakie
GLMakie.activate!()
set_theme!(backgroundcolor = :white)
# A cylinder of radius r, and height h, having z-axis as symmetry axis
# it is a stack of circles of radius r
r = 5
h = 3
n = 50
θ = LinRange(0, 2pi, 100)
#θ = [0;(0.5:n-0.5)/n;2π]
v = [0;(1:n)/n;h]
x = [r*cos(θ) for θ in θ]
y = [r*sin(θ) for θ in θ]
z = [v for v in v]
surface(x, y, z)
can anyone help me?
Thanks
Edited: (still need help for perfecting the plot)
I am now able to plot a cylinder, but it is still hollow on the top and at the bottom, here is the code:
using Plots
plotlyjs()
# If x, y, z are vectors then it won't generate a surface
# for a parameterized surface x,y,z should be matrices:
# Check for: typeof(X), typeof(Y), typeof(Z)
r = 5
h = 3
m, n =200, 150
u = range(0, 2pi, length=n)
v = range(0, h, length=m)
us = ones(m)*u'
vs = v*ones(n)'
#Surface parameterization
X = r*cos.(us)
Y = r*sin.(us)
Z = vs
Plots.surface(X, Y, Z, size=(600,600), cbar=:none, legend=false)
All of the surface you specify has radius of 5, so the interior of the ends is not filled in. You could additionally draw a disc at each end, though.

How to plot 3D HeatMap in Julia?

I want to plot 3D HeatMap for 3D function f(x,y,z).
For 2D function f(x,y), I know the below code works.
using Plots
x = 1:L # coordinate range
y = 1:L
F = Float64[f(ix,iy) for ix in x, iy in y]' #convert f(x,y) to an array
plot(F,st=:heatmap,color= cgrad(:blues))
plot!(xlabel="x",ylabel="y",aspect_ratio=:equal)
plot!(xlims=(1,L),ylims=(1,L))
For 3D function, where should I change?
using Plots
x = 1:L # coordinate range
y = 1:L
z = 1:L
F = Float64[f(ix,iy,iz) for ix in x, iy in y,iz in z] #convert f(x,y,z) to an array
plot(F,st=:heatmap,color = cgrad(:blues),alpha=0.1)
plot!(xlabel="x",ylabel="y",zlabel="z",aspect_ratio=:equal)
plot!(xlims=(1,L),ylims=(1,L),zlims=(1,L))
This code passes, but something is wrong.
color = cgrad(:blues),alpha=0.1,xlabel="x",ylabel="y" are not reflected.
In addition, the figure does not seem to be f(x,y,z). For example, f(x,y,z) = x^2 + y^2 +z^2 gives a spherical gradation, but the result is not.
The above approach is slow for more data points. However, I think you don't want heatmaps as the heatmaps in the previous link are just projections from 2D into 3D planes.
I think you need something like this.
See code here.
https://lazarusa.github.io/BeautifulMakie/surfWireLines/volume/
See image
And for convenience also here:
using GLMakie
let
x = 1:10
y = 1:10
z = 1:10
f(x,y,z) = x^2 + y^2 + z^2
vol = [f(ix,iy,iz) for ix in x, iy in y, iz in z]
fig, ax, _ = volume(x, y, z, vol, colormap = :plasma,colorrange = (minimum(vol), maximum(vol)),
figure = (; resolution = (800,800)),
axis=(; type=Axis3, perspectiveness = 0.5, azimuth = 7.19, elevation = 0.57,
aspect = (1,1,1)))
fig
end
3D HeatMap by Makie.jl
I don't know how to plot 3D HeatMap by Plots.jl yet, but I found the another way by Makie.jl : https://lazarusa.github.io/BeautifulMakie/surfWireLines/RGBcube/ .
With the help of this sample code, I got the following code.
using GLMakie, GeometryBasics, Colors
positions = vec([(i, j, k) for i=1:L,j=1:L,k=1:L]) #3D coordinate
F = zeros(Float64,length(positions)
for i = 1:length(positions) #convert f(x,y,z) to an array
x = positions[i][1]
y = positions[i][2]
z = positions[i][3]
   F[i] = f(x,y,z)
end
fig, ax = mesh(HyperRectangle(Vec3f0(positions[1]...),Vec3f0(0.8)), color = RGBA(0,0,F[1],0.5), transparency = false) #HyperRectangle(::position,::length),color=(::red,::green,::blue,::alpha)
wireframe!(ax,HyperRectangle(Vec3f0(positions[1]...), Vec3f0(0.8)), linewidth = 0.1, overdraw = false)
for i in 2:length(positions)
mesh!(ax, HyperRectangle(Vec3f0(positions[i]...), Vec3f0(0.8)), color = RGBA(0,0,F[i],0.5))
wireframe!(ax, HyperRectangle(Vec3f0(positions[i]...), Vec3f0(0.8)), linewidth = 0.1, overdraw = false)
end
fig

3d Surface Plot in R with plotly

I am looking to use the R plotly library to create a 3d surface plot of x,y,z coordinate data, similar to what is shown at the link below:
https://plot.ly/r/3d-surface-plots/
It appears that the plot_ly function requires the z coordinates to be in a matrix of dimensions x * y, as seen in datasets::volcano, used in the linked example. I'd appreciate some guidance on how to construct this matrix. Here is my sample x,y coordinate data:
## x coordinates
xSeq = seq(0, 1, .01)
## y coordinates
ySeq = seq(0, 1, .01)
## list with x, y coordinates
exmplList = list(x = xSeq, y = ySeq)
The z coordinates would be calculated via a formula from the x,y pairs (example formula used here is x + y). I've played around with something like:
exmplList = within(exmplList, z <- matrix(x + y, nrow = length(xSeq), ncol = length(ySeq)))
But that doesn't accomplish the pair combinations that I am trying to achieve.
Plotly surface needs a matrix so you could simply use this bit directly:
z = matrix(xSeq + ySeq, nrow = length(xSeq), ncol = length(ySeq))
Instead of doing a list. So, by running the following code:
## x coordinates
xSeq = seq(0, 1, 0.01)
## y coordinates
ySeq = seq(0, 1, 0.01)
## list with x, y coordinates
z = matrix(xSeq + ySeq, nrow = length(xSeq), ncol = length(ySeq))
fig = plot_ly(z = ~z) %>% add_surface()
fig
One obtains the following plot:
You might need to click and rotate a bit to see the plane. Hope it helps, cheers.

How to draw two 3d graphs (one on top of another) in R using scatterplot?

I'm sure this is a very simple problem, but somehow I can not find the answer. So in 2D if I want to display predictions on top actual values I do something like this:
plot(x, y, type = “l”, col = “green")
lines(x`, y`, type = “l”, col = "blue")
but I can not figure out how to do this in 3d (I’m using scatterplot3d)
I manage to display actual values
s3d<-scatterplot3d(x, y, z, color = “blue”, type = “l”, …)
s3d.coords <- s3d$xyz.convert(x,y,z)
D3_coord=cbind(s3d.coords$x,s3d.coords$y)
but how do I draw a graph for predicted values on top of that?
Thank you in advance.
I'm not sure if this is what you are going for, but here is one option (notice the differing data structure as input to scatterplot3d - a vector rather than a matrix for z):
library(scatterplot3d)
n <- 10
x <- seq(-10,10,,n)
y <- seq(-10,10,,n)
grd <- expand.grid(x=x,y=y)
z <- matrix(2*grd$x^3 + 3*grd$y^2, length(x), length(y))
image(x, y, z, col=rainbow(100))
plot(x, y, type = "l", col = "green")
X <- grd$x
Y <- grd$y
Z <- 2*X^3 + 3*Y^2
s3d <- scatterplot3d(X, Y, Z, color = "blue", pch=20)
s3d.coords <- s3d$xyz.convert(X, Y, Z)
D3_coord=cbind(s3d.coords$x,s3d.coords$y)
lines(D3_coord, t="l", col=rgb(0,0,0,0.2))

stack contour plot in R

I have two different matrices (same x and y axis) which a plot as contour plots contour (x,y,z). I would like to figure out how to stack both matrix into a single plot in R.
I've been trying to use the as.layer function but it doesn't work
heteroplot <- contour(a[,1],t(a[,1]),nlevels=7,heterocov^2,col="green",xlab="ppm",ylab="ppm",bty="n")
homocov <- contour(a[,1],t(a[,1]),nlevels=7,cova^2,col="red",xlab="ppm",ylab="ppm",bty="n")
as.layer(homocov,x.same = TRUE, y.same = TRUE)
thanks!
You can do this, if I've understood correctly, using the add argument to contour(). For example:
x <- -6:16
y <- x
z1 <- outer(x, sqrt(abs(x)), FUN = "/")
z2 <- outer(x, abs(x), FUN = "/")
contour(x, x, z1)
contour(x, x, z2, add = TRUE, col = "red") ## overlay second contour
which gives:
Not sure where the as.layer function comes from...?

Resources