Julia: "Plot not defined" when attempting to add slider bars - julia

I am learning how to create plots with slider bars. Here is my code based off the first example of this tutorial
using Plots
gr()
using GLMakie
function plotLaneEmden(log_delta_xi=-4, n=3)
fig = Figure()
ax = Axis(fig[1, 1])
sl_x = Slider(fig[2, 1], range = 0:0.01:4.99, startvalue = 3)
sl_y = Slider(fig[1, 2], range = -6:0.01:0.1, horizontal = false, startvalue = -2)
point = lift(sl_x.value, sl_y.value) do n, log_delta_xi
Point2f(n, log_delta_xi)
end
plot(n, 1 .- log_delta_xi.^2/6, linecolor = :green, label="n = $n")
xlabel!("ξ")
ylabel!("θ")
end
plotLaneEmden()
When I run this, it gives UndefVarError: plot not defined. What am I missing here?

It looks like you are trying to mix and match Plots.jl and Makie.jl. Specifically, the example from your link is entirely for Makie (specifically, with the GLMakie backend), while the the plot function you are trying to add uses syntax specific to the Plots.jl version of plot (specifically including linecolor and label keyword arguments).
Plots.jl and Makie.jl are two separate and unrelated plotting libraries, so you have to pick one and stick with it. Since both libraries export some of the same function names, using both at once will lead to ambiguity and UndefVarErrors if not disambiguated.
The other potential problem is that it looks like you are trying to make a line plot with only a single x and y value (n and log_delta_xi are both single numbers in your code as written). If that's what you want, you'll need a scatter plot instead of a line plot; and if that's not what you want you'll need to make those variables vectors instead somehow.
Depending on what exactly you want, you might try something more along the lines of (in a new session, using only Makie and not Plots):
using GLMakie
function plotLaneEmden(log_delta_xi=-4, n=3)
fig = Figure()
ax = Axis(fig[1, 1], xlabel="ξ", ylabel="θ")
sl_x = Slider(fig[2, 1], range = 0:0.01:4.99, startvalue = n)
sl_y = Slider(fig[1, 2], range = -6:0.01:0.1, horizontal = false, startvalue = log_delta_xi)
point = lift(sl_x.value, sl_y.value) do n, log_delta_xi
Point2f(n, 1 - log_delta_xi^2/6)
end
sca = scatter!(point, color = :green, markersize = 20)
axislegend(ax, [sca], ["n = $n"])
fig
end
plotLaneEmden()
Or, below, a simple example for interactively plotting a line rather than a point:
using GLMakie
function quadraticsliders(x=-5:0.01:5)
fig = Figure()
ax = Axis(fig[1, 1], xlabel="X", ylabel="Y")
sl_a = Slider(fig[2, 1], range = -3:0.01:3, startvalue = 0.)
sl_b = Slider(fig[1, 2], range = -3:0.01:3, horizontal = false, startvalue = 0.)
points = lift(sl_a.value, sl_b.value) do a, b
Point2f.(x, a.*x.^2 .+ b.*x)
end
l = lines!(points, color = :blue)
onany((a,b)->axislegend(ax, [l], ["$(a)x² + $(b)x"]), sl_a.value, sl_b.value)
limits!(ax, minimum(x), maximum(x), -10, 10)
fig
end
quadraticsliders()
ETA: A couple examples closer to what you might be looking for

Related

Julia I can't make a streamplot with my own function of data

I'm doing my dissertetion and I need to make a streamplot with the velocities matrix.
I have resolved Navier-stokes equations and I have one matrix of u-velocity 19x67 and other matrix of v-velocity 19x67.
To obtain a continuos function I have done a bilinear interpolation but I have problem with the plotting.
I don't know if I explain myself very well but y let you the code.
#BILINEAR INTERPOLATION#
X=2
Y=0.67
x_pos=findlast(x->x<X, x)
y_pos=findlast(x->x<Y, y)
x1=((x_pos-1))*Dx
x2=(x_pos)*Dx
y1=((y_pos-1)-0.5)*Dy
y2=(y_pos-0.5)*Dy
u1=u[y_pos-1,x_pos-1]
u2=u[y_pos-1,x_pos]
u3=u[y_pos,x_pos-1]
u4=u[y_pos,x_pos]
u_int(Y,X)=(1/(Dx*Dy))*((x2.-X).*(y2.-Y).*u1+(X.-x1).*(y2.-Y).*u2+(x2.-X).*(Y.-y1).*u3+(X.-x1).*(Y.-y1).*u4)
xx1=((x_pos-1)-0.5)*Dx
xx2=(x_pos-0.5)*Dx
yy1=((y_pos-1))*Dy
yy2=(y_pos)*Dy
v1=v[y_pos-1,x_pos-1]
v2=v[y_pos-1,x_pos]
v3=v[y_pos,x_pos-1]
v4=v[y_pos,x_pos]
v_int(Y,X)=(1/(Dx*Dy))*((x2-X)*(y2-Y)*v1+(X-x1)*(y2-Y)*v2+(x2-X)*(Y-y1)*v3+(X-x1)*(Y-y1)*v4)
#PLOT#
function stream(Y,X)
u_c=u_int(Y,X)
v_c=v_int(Y,X)
return u_c,v_c
end
using CairoMakie
let
fig = Figure(resolution = (600, 400))
ax = Axis(fig[1, 1], xlabel = "x", ylabel = "y", backgroundcolor = :black)
streamplot!(ax, stream, -2 .. 4, -2 .. 2, colormap = Reverse(:plasma),
gridsize = (32, 32), arrow_size = 10)
display(fig)
end;
Any solution?
If you know other method with other package, pls tell me.

Plotting a 3D surface in Julia, using either Plots or PyPlot

I would like to plot a two variable function(s) (e_pos and e_neg in the code). Here, t and a are constants which I have given the value of 1.
My code to plot this function is the following:
t = 1
a = 1
kx = ky = range(3.14/a, step=0.1, 3.14/a)
# Doing a meshgrid for values of k
KX, KY = kx'.*ones(size(kx)[1]), ky'.*ones(size(ky)[1])
e_pos = +t.*sqrt.((3 .+ (4).*cos.((3)*KX*a/2).*cos.(sqrt(3).*KY.*a/2) .+ (2).*cos.(sqrt(3).*KY.*a)));
e_neg = -t.*sqrt.((3 .+ (4).*cos.((3)*KX*a/2).*cos.(sqrt(3).*KY.*a/2) .+ (2).*cos.(sqrt(3).*KY.*a)));
using Plots
plot(KX,KY,e_pos, st=:surface,cmap="inferno")
If I use Plots this way, sometimes I get an empty 3D plane without the surface. What am I doing wrong? I think it may have to do with the meshgrids I did for kx and ky, but I am unsure.
Edit: I also get the following error:
I changed some few things in my code.
First, I left the variables as ranges. Second, I simply computed the functions I needed without mapping the variables onto them. Here's the code:
t = 2.8
a = 1
kx = range(-pi/a,stop = pi/a, length=100)
ky = range(-pi/a,stop = pi/a, length=100)
#e_pos = +t*np.sqrt(3 + 4*np.cos(3*KX*a/2)*np.cos(np.sqrt(3)*KY*a/2) + 2*np.cos(np.sqrt(3)*KY*a))
e_pos(kx,ky) = t*sqrt(3+4cos(3*kx*a/2)*cos(sqrt(3)*ky*a/2) + 2*cos(sqrt(3)*ky*a))
e_neg(kx,ky) = -t*sqrt(3+4cos(3*kx*a/2)*cos(sqrt(3)*ky*a/2) + 2*cos(sqrt(3)*ky*a))
# Sort of broadcasting?
e_posfunc = e_pos.(kx,ky);
e_negfunc = e_neg.(kx,ky);
For the plotting I simply used the GR backend:
using Plots
gr()
plot(kx,ky,e_pos,st=:surface)
plot!(kx,ky,e_neg,st=:surface, xlabel="kx", ylabel="ky",zlabel="E(k)")
I got what I wanted!

Show Two Plots in Separate Windows Using Plots

let's assume I have a file called plot.jl:
using Plotsfunction plotSine()
x = LinRange(0,2π, 101)
y = sin.(x) gr()
p = plot(x,y, title="Sine from 0 to 2π", xlabel="x", ylabel="y")
display(p)
endfunction plotTwoFunctions()
x = LinRange(0, 2, 101)
y1 = exp.(x)
y2 = log.(x) gr()
p = plot(x,y1, title="Two functions", xlabel="x x", ylabel="y")
plot!(p, x,y2)
display(p)
endplotSine()
plotTwoFunctions()
I starta REPL session and include it and it opens the window for the sine function plot but that get's instantly overwritten by the second function call.
Is there a blocking display() function? Can I somehow force a new window to open?
Try reuse=false as in this example below:
using Plots
pyplot()
p1 = plot(rand(5))
p2 = plot(rand(50), reuse=false)

solve system of ODEs with read in external forcing

In Julia, I want to solve a system of ODEs with external forcings g1(t), g2(t) like
dx1(t) / dt = f1(x1, t) + g1(t)
dx2(t) / dt = f2(x1, x2, t) + g2(t)
with the forcings read in from a file.
I am using this study to learn Julia and the package DifferentialEquations, but I am having difficulties finding the correct approach.
I could imagine that using a callback could work, but that seems pretty cumbersome.
Do you have an idea of how to implement such an external forcing?
You can use functions inside of the integration function. So you can use something like Interpolations.jl to build an interpolating polynomial from the data in your file, and then do something like:
g1 = interpolate(data1, options...)
g2 = interpolate(data2, options...)
p = (g1,g2) # Localize these as parameters to the model
function f(du,u,p,t)
g1,g2 = p
du[1] = ... + g1[t] # Interpolations.jl interpolates via []
du[2] = ... + g2[t]
end
# Define u0 and tspan
ODEProblem(f,u0,tspan,p)
Thanks for a nice question and nice answer by #Chris Rackauckas.
Below a complete reproducible example of such a problem. Note that Interpolations.jl has changed the indexing to g1(t).
using Interpolations
using DifferentialEquations
using Plots
time_forcing = -1.:9.
data_forcing = [1,0,0,1,1,0,2,0,1, 0, 1]
g1_cst = interpolate((time_forcing, ), data_forcing, Gridded(Constant()))
g1_lin = scale(interpolate(data_forcing, BSpline(Linear())), time_forcing)
p_cst = (g1_cst) # Localize these as parameters to the model
p_lin = (g1_lin) # Localize these as parameters to the model
function f(du,u,p,t)
g1 = p
du[1] = -0.5 + g1(t) # Interpolations.jl interpolates via ()
end
# Define u0 and tspan
u0 = [0.]
tspan = (-1.,9.) # Note, that we would need to extrapolate beyond
ode_cst = ODEProblem(f,u0,tspan,p_cst)
ode_lin = ODEProblem(f,u0,tspan,p_lin)
# Solve and plot
sol_cst = solve(ode_cst)
sol_lin = solve(ode_lin)
# Plot
time_dense = -1.:0.1:9.
scatter(time_forcing, data_forcing, label = "discrete forcing")
plot!(time_dense, g1_cst(time_dense), label = "forcing1", line = (:dot, :red))
plot!(sol_cst, label = "solution1", line = (:solid, :red))
plot!(time_dense, g1_lin(time_dense), label = "forcing2", line = (:dot, :blue))
plot!(sol_lin, label = "solution2", line = (:solid, :blue))

Barplot with errors in bokeh

I am trying to draw a figure like that http://seaborn.pydata.org/_images/seaborn-barplot-1.png
As I understand bokeh don't have special method for barplot with error, so I decided to use Seaborn and then convert it into bokeh chart by to_bokeh() function.
sns.set_style("whitegrid")
plot = sns.barplot(data=[[1,2], [3,4]])
plot.get_figure().savefig('1.jpg')
l = layout([[widgetbox(*controls), to_bokeh(plot.get_figure())]])
save(l)
It save normal plot, like at the picture, but bokeh shows only error line, and no bars.
What do I wrong, is it bug? Is there simpler way to draw chars like that in bokeh. I also should use strings as a ticks.Does bokeh support it?
I have found solution (at least I hope :) )
box_plot = figure(x_range=['Ctrl', '- FBC', 'Rescue'])
X = range(1, 4)
Y = some_data # e.g. mean(data)
Err = another_piece_of_data # e.g. std(data)
box_plot.vbar(x=X, width=0.5, top=Y)
#add errors
err_xs = []
err_ys = []
for x, y, err in zip(X, Y, Err):
err_xs.append((x, x))
err_ys.append((y - err, y + err))
box_plot.multi_line(err_xs, err_ys, color='red', line_width=2)
l = layout([[box_plot]])
save(l)

Resources