Creating animated plots in the command line with Julia - julia

Julia has the delightful ability to generate plots constructed from Unicode symbols which are printed directly to the command line in a very straightforward way. For example, the following code generates a Unicode plot of a sine function directly to the command line:
using Plots
unicodeplots();
x = [0:0.1:2*pi;];
y = sin.(x);
plot(x,y)
I would like to try to find a way to create an animated plot of this form directly on the command line. Ideally, I would like to generate a single plot in Unicode that is ``updated" in such a way that it appears animated.
However, although printing hundreds of distinct frames to the command line is naturally less appealing, such a solution is acceptable if it ``looks" like an animation. Another less acceptable solution is to print such Unicode plots into a gif in a way that is consistent for all platforms; attempts to do any of this involving jury-rigging #animate and #gif have largely failed, since either function cannot even print Unicode plots to a file in the Windows form of Julia.
UPDATE: Here is an example of code that generates an "animation" in the command line that is not really acceptable, which simply plots each distinct frame followed by "spacing" in the command line provided by a special Unicode character (tip provided by niczky12):
using Plots
unicodeplots();
n = 100;
x = [0:0.1:4*pi;];
for i = 1:30
y = sin.(x .+ (i/2));
plot(x, y, show=true, xlims = (0,4*pi), ylims = (-1,1))
sleep(0.01)
println("\33[2J")
end

A slight improvement might be this:
let
print("\33[2J")
for i in 1:30
println("\33[H")
y = sin.(x .+ (i/2));
plot(x, y, show=true, xlims = (0,4*pi), ylims = (-1,1))
sleep(0.01)
end
end

Related

Is it possible to plot the tabuler representation of a dataframe from DataFrames.jl using Makie.jl?

I would like to plot the tabular representation of a dataframe from the DataFrames.jl package using Makie.jl or using any of the other plotting libraries in Julia. Another option would be to save the dataframe as an image.
You can just use annotate!, you just need to remember that inbuilt monospace font in Plots.jl does not nicely support all Unicode characters so you need to use a simpler table formatting (markdown formatting will actually look good and nice). On the other hand Makie seems to support system fonts so you can get nicer formatting.
using DataFrames, PrettyTables, Plots
pyplot()
df=DataFrame(a=1:5,b='a':'e',c=rand(5))
io = IOBuffer()
pretty_table(io, df, tf = tf_markdown, show_row_number = true)
str = String(io.data)
plot() # do whatever plotting you need
annotate!(0.5, 0.5, text(str; family="monospace", pointsize=8))
And here is the same example with Makie:
using CairoMakie, Makie
f = Figure()
ax = Axis(f[1, 1])
io = IOBuffer()
pretty_table(io, df)
str = String(io.data)
text(5,5, text=str, font="Consolas", textsize=14)

Julia Plotting: delete and modify existing lines

Two questions in one: Given a line plotted in Julia, how can I
delete it from the plot and legend (without clearing the whole plot)
change its properties (such as color, thickness, opacity)
As a concrete example in the code below, how can I 1. delete previous regression lines OR 2. change their opacity to 0.1?
using Plots; gr()
f = x->.3x+.2
g = x->f(x)+.2*randn()
x = rand(2)
y = g.(x)
plt = scatter(x,y,c=:orange)
plot!(0:.1:1, f, ylim=(0,1), c=:green, alpha=.3, linewidth=10)
anim = Animation()
for i=1:200
r = rand()
x_new, y_new = r, g(r)
push!(plt, x_new, y_new)
push!(x, x_new)
push!(y, y_new)
A = hcat(fill(1., size(x)), x)
coefs = A\y
plot!(0:.1:1, x->coefs[2]*x+coefs[1], c=:blue) # plot new regression line
# 1. delete previous line
# 2. set alpha of previous line to .1
frame(anim)
end
gif(anim, "regression.gif", fps=5)
I tried combinations of delete, pop! and remove but without success.
A related question in Python can be found here: How to remove lines in a Matplotlib plot
Here is a fun and illustrative example of how you can use pop!() to undo plotting in Julia using Makie. Note that you will see this goes back in the reverse order that everything was plotted (think, like adding and removing from a stack), so deleteat!(scene.plots, ind) will still be necessary to remove a plot at a specific index.
using Makie
x = range(0, stop = 2pi, length = 80)
f1(x) = sin.(x)
f2(x) = exp.(-x) .* cos.(2pi*x)
y1 = f1(x)
y2 = f2(x)
scene = lines(x, y1, color = :blue)
scatter!(scene, x, y1, color = :red, markersize = 0.1)
lines!(scene, x, y2, color = :black)
scatter!(scene, x, y2, color = :green, marker = :utriangle, markersize = 0.1)
display(scene)
sleep(10)
pop!(scene.plots)
display(scene)
sleep(10)
pop!(scene.plots)
display(scene)
You can see the images above that show how the plot progressively gets undone using pop(). The key idea with respect to sleep() is that if we were not using it (and you can test this on your own by running the code with it removed), the fist and only image shown on the screen will be the final image above because of the render time.
You can see if you run this code that the window renders and then sleeps for 10 seconds (in order to give it time to render) and then uses pop!() to step back through the plot.
Docs for sleep()
I have to say that I don't know what the formal way is to accomplish them.
There is a cheating method.
plt.series_list stores all the plots (line, scatter...).
If you have 200 lines in the plot, then length(plt.series_list) will be 200.
plt.series_list[1].plotattributes returns a dictionary containing attributes for the first line(or scatter plot, depends on the order).
One of the attributes is :linealpha, and we can use it to modify the transparency of a line or let it disappear.
# your code ...
plot!(0:.1:1, x->coefs[2]*x+coefs[1], c=:blue) # plot new regression line
# modify the alpha value of the previous line
if i > 1
plt.series_list[end-1][:linealpha] = 0.1
end
# make the previous line invisible
if i > 2
plt.series_list[end-2][:linealpha] = 0.0
end
frame(anim)
# your code ...
You cannot do that with the Plots package. Even the "cheating" method in the answer by Pei Huang will end up with the whole frame getting redrawn.
You can do this with Makie, though - in fact the ability to interactively change plots was one of the reasons for creating that package (point 1 here http://makie.juliaplots.org/dev/why-makie.html)
Not sure about the other popular plotting packages for Julia.

How to generate a series of plot with `for`

I learn to program in Julia language.
I want to test which color is better, so I use the following code:
using Plots
x = 1:10; y = rand(10,2);
for i in [0 0.1 0.2]
plot(x,y, seriestype=:scatter,background_color=RGB(0.4,0.8,i))
end
How, nothing show.
Can anyone tell me how to generate plot with loop?
P.S.
I have tried another way,
[plot(x,y, seriestype=:scatter,background_color=RGB(0.4,0.8,i)) for i in 0:0.1:1]
Nothing happened with above code.
The following code does not work either:
map(i->plot(x,y, seriestype=:scatter,background_color=RGB(0.4,0.8,i)), [0 0.1 0.2])
In a script plot is not shown unless you use display function to show it (see section Plotting in scripts here http://docs.juliaplots.org/latest/tutorial/).
You have several options here. This one is the simplest:
for i in [0 0.1 0.2]
display(plot(x,y, seriestype=:scatter,background_color=RGB(0.4,0.8,i)))
sleep(1)
end
It will plot your figures in a sequence. I use sleep(1) to make Julia pause between plotting.
Otherwise you can do:
p = [plot(x,y, seriestype=:scatter,background_color=RGB(0.4,0.8,i)) for i in 0:0.1:1]
and then plot your figures from Julia REPL like this:
julia> p[5]
will plot fifth figure. Now you do not have to use display because in REPL it will be invoked anyway as I did not use ; at the end of the line. You could write display(p[5]) to get the same effect.
Finally you can consider saving the figures to PNG file and inspecting them later. You can do it either using p array defined above like this:
foreach(i -> savefig(p[i], "fig$i.png"), eachindex(p))
or in a loop like this:
for i in [0 0.1 0.2]
p = plot(x,y, seriestype=:scatter,background_color=RGB(0.4,0.8,i))
savefig(p, "fig$i.png)
end

ggplot graphs appearing empty when using Rmarkdown

I am having problems using ggplot with Rmarkdown.
I have a code that is supposed to return a ggplot graph.When I execute the code in a R session it works but the same code returns an empty plot when using R markdown.This is the code I am using in the R session
m<-ggplot(data=t,aes_string(x=v,y =t$cnt_pct))
m+geom_bar(stat = "identity",fill="#FF0000",color='black')+geom_text(aes(label = cnt_pct),vjust=-0.2)+ggtitle(paste(v,paste("graph")))+theme(plot.title = element_text(hjust = 0.5))+ylab("percent")+geom_line(aes_string(x=v,y =t$keshel_pct),group=1,size=2)
This is the code I am using in the Rmarkdown
m<-ggplot(data=t,aes_string(x=v,y =t$cnt_pct))
m+geom_bar(stat = "identity",fill="#FF0000",color='black')+geom_text(aes(label = cnt_pct),vjust=-0.2)+ggtitle(paste(v,paste("graph")))+theme(plot.title = element_text(hjust = 0.5))+ylab("percent")+geom_line(aes_string(x=v,y =t$keshel_pct),group=1,size=2)
plot(m)
The only diffrence between the two is that with the Rmarkwond a plot(m) line is added.
For some reason the plot command makes the graph empty, when I remove it and run the Rmarkdown no graphs are returned.
This is the graph empty
This is the graph working in a session of R
Anybody has any idea what is my mistake?
Any help will be appriciated
You have a few issues here:
1) your plot syntax has issues. aes_string takes strings referring to column names, but you're passing a variable v for x and direct column data t$cnt_pnt for y. Check some ggplot examples to get the syntax right.
2) The plot(m) statement shouldn't work for two reasons: first, you print ggplot objects, not plot them. Second, you are not assigning the m + geom_bar(...) statement to anything, so even if your plot statement did work, you'd get the plot without the geom_bar(...) stuff. Try e.g. y = m+ geom_bar(...); print(y) instead.

Octave hist plot number format

I want to plot data with octaves hist() function. Unfortunately, as the numbers of the x-axis are quite large, they are displayed in scientific format, for example like 2e+007.
As this is a bit hard to read, I'd like them to be dislayed only as exponentials to the base 10, without the product or the e. So just like 10^5 for example. How can I achieve this?
When I plot data with the loglog() function, it uses the scale as I need it by default, but not for the hist().
EDIT:
To be a bit more preceise, I add some code and a picture of my plot.
NUM_SAMPLES = 10000;
% Open file.
input = fopen(filename);
x = [];
for i=[1:NUM_SAMPLES]
line = fgetl(input);
data = strsplit(line, ';');
x(end + 1) = str2num(data{1,2})/(1000);
endfor
% Close file.
fclose(input);
% Plot histogram.
figure('Position',[0,0,700,500]);
hist(x, 500);
So I just read some big numbers from my file and want to plot it with hist. Because the numbers are big, the automatically get displayed in loc scale and scientific format. Here you can see an example plot:
Unfortunately set(gca(), 'xscale', 'log'); doesn't change anything, so I think this plot is also consider log scale, but just a bad number format.
You can set the xticklabel or yticklabel manually, for example:
x = [1e7, 1e8, 1e9];
ax = gca();
set(ax, 'xticklabel', {'0','2e8','4e8','6e8','8e8','10e8'});
hist(x);
Alternatively, you can set the x axis to be in log scale:
set(ax, 'xscale', 'log');

Resources