Julia Plotting: push!() adds to wrong line - animation

I want to use push!() in a for loop to continue two separate plotting lines. Consider the following example:
using Plots; gr()
f = x->x*x
g = x->f(x)+.2*randn()
p = plot(-1:.1:0, f, ylim=(-1,2), c=:blue)
s = scatter!(-1:.1:0, g, c=:red)
anim = Animation()
for i=1:10
x = i/10
push!(p, x, f(x))
push!(s, x, g(x)) # without this, f gets continued as expected
frame(anim)
end
gif(anim, "test.gif", fps=2)
Why does push!(p, ...) and push!(s,...) both continue the blue line?
How to append scattered data to s instead?
I know that the second plot at this link achieves a similar result by plotting and pushing both lines at once, but that solution is not always practical, especially in more complicated plots.

In your code, p and s are the same objects.
It means that p == s will return true.
The data will be stored in p.series_list.
You can get your y-axis data in p.series_list[1][:y] for line plot, p.series_list[2][:y] for scatter plot.
Now just slightly modify the original code!
First, remove s and use p only.
Second, in the push!() function, the 2nd argument is given to indicate the data index we want to append new data.
f = x->x*x
g = x->f(x)+.2*randn()
p = plot(-1:.1:0, f, ylim=(-1,2), c=:blue)
scatter!(-1:.1:0, g, c=:red)
anim = Animation()
for i=1:10
x = i/10
push!(p, 1, x, f(x))
push!(p, 2, x, g(x))
frame(anim)
end
gif(anim, "test.gif", fps=2)

Related

matplotlib FuncAnimation clear plot each repeat cycle

The code below works, but I think is overplotting the original points each repeat cycle. I want it to start from the origin, each repeat cycle, with a clear plot. Amongst many approaches to fixing this, I have tried inserting ax.clear() in both the init and update functions; not effective. I have left in the code what I thought would reset the ln, artist to having an empty set; again this is not the solution I am looking for. I would appreciate some guidance on what the correct way to reinitiate each cycle is in this toy example so that, when applied to my more complex problem, I don't incur cumulative penalties. This works fine in terms of refreshing if passing an array...Thanks for any help.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, writers
#from basic_units import radians
# # Set up formatting for the movie files
# Writer = writers['ffmpeg']
# writer = Writer(fps=20, metadata=dict(artist='Llew'), bitrate=1800)
#Polar stuff
fig = plt.figure(figsize=(10,8))
ax = plt.subplot(111,polar=True)
ax.set_title("A line plot on a polar axis", va='bottom')
ax.set_rticks([0.5, 1, 1.5, 2]) # fewer radial ticks
ax.set_facecolor(plt.cm.gray(.95))
ax.grid(True)
xT=plt.xticks()[0]
xL=['0',r'$\frac{\pi}{4}$',r'$\frac{\pi}{2}$',r'$\frac{3\pi}{4}$',\
r'$\pi$',r'$\frac{5\pi}{4}$',r'$\frac{3\pi}{2}$',r'$\frac{7\pi}{4}$']
plt.xticks(xT, xL)
r = []
theta = []
# Animation requirements.
ln, = plt.plot([], [], 'r:',
markersize=1.5,
alpha=1,
animated=True)
def init():
ax.set_xlim(0, 2)
ax.set_ylim(0, 2)
return ln,
def update(frame):
r.append(frame)
theta.append(5*np.pi*frame)
ln.set_data(theta, r)
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0,2,400),
init_func=init, interval=10, blit=True,repeat=True)
plt.show()
I tried to reset the lists (and with arrays also) using this somewhat crude approach, which wiped the list, but did not re-initiate the cycle.
def update(frame,r,theta):
r.append(frame)
theta.append(5*np.pi*frame)
if len(r)>=400:
r = [0]
theta=[0]
ln.set_data(theta, r)
return ln,
In contrast, this does work as intended...
for i in range(25):
r.append(i)
print('len(r)',len(r), r)
if len(r) >=10:
r = []
print('if r>=10:',r)
print('Post conditional clause r',len(r),r)
This led me to try the following, noting that passing the internal (r,theta) within the update() outside requires declaring it as a global variable. With the following code, the plot now resets each cycle instead of overplotting. My sense is that this is a rather long way around a simple procedure -- any improvements gratefully accepted.
#This solution also works
def update(frame):
r.append(frame)
theta.append(5*np.pi*frame)
if len(r)>=400:
global r
r = []
global theta
theta=[]
ln.set_data(theta, r)
return ln,
If I understand your code and your question, you want to display only one point at each frame of the animation, is that correct?
If so, your problem is simply that you are appending each new point to all previous points in the function update(). Instead, simply update the data coordinates, like so:
def update(frame):
r = frame
theta = 2*np.pi*frame
ln.set_data(theta, r)
return ln,
EDIT Let's see if I get this right this time around.
You could choose to only show the last N points like so:
N=10
def update(frame):
r.append(frame)
theta.append(2*np.pi*frame)
ln.set_data(theta[-N:], r[-N:])
return ln,
or you can append N points to your array, then reset to an empty array. I think that might be what you were trying to do. Here, you have to be careful. If you simply do r = [] then you change which object r references to, and that breaks the animation. What you need to do is change the content of the array with the syntax r[:] = [].
def update(frame):
r_ = frame
theta_ = 2*np.pi*frame
if len(r)>N:
r[:] = [r_]
theta[:] = [theta_]
else:
r.append(r_)
theta.append(theta_)
ln.set_data(theta, r)
return ln,

Why do Extra Function Calls Speed Up a Program in Python?

If I extract a computation and place it in another function shouldn't
the code be slower? Evidently not. Below, I can't believe fun2 is slower
than fun1, because fun1 clearly does more computation. What is going on?
(Maybe I can have functions call functions call function and REALLY speed
up my code.)
Heading
##
Python code:
MAX = 10000000
def fun1(): # 4.26 seconds.
def multiply (X, Y): # multiply two 2x2 matrices
a, b, c, d = X
e, f, g, h = Y
return a*e+b*g, a*f+b*h, c*e+d*g, c*f+d*h
X = [1,2,3,4]
Y = [5,6,7,8]
for n in range (MAX):
Z = multiply (X, Y) # Make the call
return Z
#-------------------------------------------------
def fun2(): # 6.56 seconds.
X = [1,2,3,4]
Y = [5,6,7,8]
for n in range (MAX):
Z = X[0]*Y[0] + X[1]*Y[2], \
X[0]*Y[1] + X[1]*Y[3], \
X[2]*Y[0] + X[3]*Y[2], \
X[2]*Y[1] + X[3]*Y[3] # Don't make the call.
return Z
I'm not sure, but I think it might be that
a,b,c,d = X
and then referencing a,b,c and d directly is faster that referencing X[0] (and so on).
Every index in list is another lookup, while a,b,c,d=X is only one lookup (I think).
I finally figured out my own question. The function dispensed with square brackets, and that is where the speed increase came from, not from the function call itself. A Python list contains both values and bit-sizes (or addresses, I don't know which). To access x[3], the computer goes to address x reads the address of x[1], moves there, reads the address of x[2], moves there, reads the address of x[3], moves there and finally accesses the value. This takes time and can be speeded up by assigning the list elements to simple identifiers.

How to multiply tensors in MATLAB without looping?

Suppose I have:
A = rand(1,10,3);
B = rand(10,16);
And I want to get:
C(:,1) = A(:,:,1)*B;
C(:,2) = A(:,:,2)*B;
C(:,3) = A(:,:,3)*B;
Can I somehow multiply this in a single line so that it is faster?
What if I create new tensor b like this
for i = 1:3
b(:,:,i) = B;
end
Can I multiply A and b to get the same C but faster? Time taken in creation of b by the loop above doesn't matter since I will be needing C for many different A-s while B stays the same.
Permute the dimensions of A and B and then apply matrix multiplication:
C = B.'*permute(A, [2 3 1]);
If A is a true 3D array, something like A = rand(4,10,3) and assuming that B stays as a 2D array, then each A(:,:,1)*B would yield a 2D array.
So, assuming that you want to store those 2D arrays as slices in the third dimension of output array, C like so -
C(:,:,1) = A(:,:,1)*B;
C(:,:,2) = A(:,:,2)*B;
C(:,:,3) = A(:,:,3)*B; and so on.
To solve this in a vectorized manner, one of the approaches would be to use reshape A into a 2D array merging the first and third dimensions and then performing matrix-muliplication. Finally, to bring the output size same as the earlier listed C, we need a final step of reshaping.
The implementation would look something like this -
%// Get size and then the final output C
[m,n,r] = size(A);
out = permute(reshape(reshape(permute(A,[1 3 2]),[],n)*B,m,r,[]),[1 3 2]);
Sample run -
>> A = rand(4,10,3);
B = rand(10,16);
C(:,:,1) = A(:,:,1)*B;
C(:,:,2) = A(:,:,2)*B;
C(:,:,3) = A(:,:,3)*B;
>> [m,n,r] = size(A);
out = permute(reshape(reshape(permute(A,[1 3 2]),[],n)*B,m,r,[]),[1 3 2]);
>> all(C(:)==out(:)) %// Verify results
ans =
1
As per the comments, if A is a 3D array with always a singleton dimension at the start, you can just use squeeze and then matrix-multiplication like so -
C = B.'*squeeze(A)
EDIT: #LuisMendo points out that this is indeed possible for this specific use case. However, it is not (in general) possible if the first dimension of A is not 1.
I've grappled with this for a while now, and I've never been able to come up with a solution. Performing element-wise calculations is made nice by bsxfun, but tensor multiplication is something which is woefully unsupported. Sorry, and good luck!
You can check out this mathworks file exchange file, which will make it easier for you and supports the behavior you're looking for, but I believe that it relies on loops as well. Edit: it relies on MEX/C++, so it isn't a pure MATLAB solution if that's what you're looking for.
I have to agree with #GJSein, the for loop is really fast
time
0.7050 0.3145
Here's the timer function
function time
n = 1E7;
A = rand(1,n,3);
B = rand(n,16);
t = [];
C = {};
tic
C{length(C)+1} = squeeze(cell2mat(cellfun(#(x) x*B,num2cell(A,[1 2]),'UniformOutput',false)));
t(length(t)+1) = toc;
tic
for i = 1:size(A,3)
C{length(C)+1}(:,i) = A(:,:,i)*B;
end
t(length(t)+1) = toc;
disp(t)
end

MATLAB vectorization: creating a cell array of neighbor index arrays

I have a logical matrix X of n points, where X(i, j) == 1 if points i and j are neighbors and 0 otherwise.
I would like to create a cell array Y with each entry Y{i} (i from 1 to n) containing an array with the indeces of point i's neighbors.
In other words, I would like to vectorize the following:
n = 10;
X = (rand(n, n) < 0.5);
Y = cell(1, 10);
for i = 1:10
[Y{i}] = find(X(i, :));
end
As one approach you can use accumarray -
[R,C] = find(X.') %//'
Y = accumarray(C(:),R(:),[],#(x) {x})
If you need each cell to be a row vector, you need to add one transpose there with x, like so -
Y = accumarray(C(:),R(:),[],#(x) {x.'})
As another approach, you can also use arrayfun, but I don't think this would be a vectorized solution -
Y = arrayfun(#(n) R(C==n),1:max(C),'Uni',0)
If you don't care about the order of elements in each cell, you can avoid the transpose of X to get R and C like so -
[R,C] = find(X)
Then, interchange the positions of R and C with the accumarray and arrayfun based approaches as listed earlier.
Here's some more voodoo:
Y = mat2cell(nonzeros(bsxfun(#times, X, 1:size(X,1)).').', 1, sum(X,2));
The most important function here is bsxfun. To see how the code works, I suggest you observe partial results from innermost outwards: first bsxfun(#times, X, 1:size(X,1)).', then nonzeros(...), etc.

How to overlay several images in Matlab?

I have the images A, B and C. How to overlay these images to result in D using Matlab? I have at least 50 images to make it. Thanks.
Please, see images here.
Download images:
A: https://docs.google.com/open?id=0B5AOSYBy_josQ3R3Y29VVFJVUHc
B: https://docs.google.com/open?id=0B5AOSYBy_josTVIwWUN1a085T0U
C: https://docs.google.com/open?id=0B5AOSYBy_josLVRwQ3JNYmJUUFk
D: https://docs.google.com/open?id=0B5AOSYBy_josd09TTFE2VDJIMzQ
To fade the images together:
Well since images in matlab are just matrices, you can add them together.
D = A + B + C
Of course if the images don't have the same dimensions, you will have to crop all the images to the dimensions of the smallest one.
The more you apply this principle, the larger the pixel values are going to get. It might be beneficial to display the images with imshow(D, []), where the empty matrix argument tells imshow to scale the pixel values to the actual minimum and maximum values contained in D.
To replace changed parts of original image:
Create a function combine(a,b).
Pseudocode:
# create empty answer matrix
c = zeros(width(a), height(a))
# compare each pixel in a to each pixel in b
for x in 1..width
for y in 1..height
p1 = a(x,y)
p2 = b(x,y)
if (p1 != p2)
c(x,y) = p2
else
c(x,y) = p1
end
end
end
Use this combine(a,b) function like so:
D = combine(combine(A,B),C)
or in a loop:
D = combine(images(1), images(2));
for i = 3:numImages
D = combine(D, images(i));
end
Judging from the example, it seems to me that the operation requested is a trivial case of "alpha compositing" in the specified order.
Something like this should work - don't have matlab handy right now, so this is untested, but it should be correct or almost so.
function abc = composite(a, b, c)
m = size(a,1); n = size(a,2);
abc = zeros(m, n, 3);
for i=1:3
% Vectorize the i-th channel of a, add it to the accumulator.
ai = a(:,:,i);
acc = ai(:);
% Vectorize the i-th channel of b, replace its nonzero pixels in the accumulator
bi = b(:,:,i);
bi = bi(:);
z = (bi ~= 0);
acc(z) = bi(z);
% Likewise for c
ci = c(:,:,i);
ci = ci(:);
z = (ci ~= 0);
acc(z) = ci(z);
% Place the result in the i-th channel of abc
abc(:,:,i) = reshape(acc, m, n);
end

Resources