I have used this code but it showing me error. Help me solve this.
som=MiniSom(x=10,y=10,input_len=15,sigma=1.0,learning_rate=0.5)
som.random_weights_init(x)
som.train_random(data=x,num_iteration=100)
from pylab import bone, pcolor, colorbar, plot, show
bone()
pcolor(som.distance_map().T)
colorbar()
markers = ['o', 's']
colors = ['r', 'g']
for i, x1 in enumerate(x):
w = som.winner(x)
plot(w[0] + 0.5,
w[1] + 0.5,
markers[y[i]],
markeredgecolor = colors[y[i]],
markerfacecolor = 'None',
markersize = 10,
markeredgewidth = 2)
show()
The line w = som.winner(x) should be replaced with w = som.winner(x1)
MiniSom.winner() method computes the coordinates of the winning neuron for the sample x, where sample x is one single row of your dataset, and the corresponding variable name in your code is x1.
You are iterating x1 over rows of x, however still trying to use the dataset variable x with som.winner() method.
Related
How can multiple surfaces be plotted on the axes but surfaces uses a different colormap?.
Using colormap("...") changes it for the entire figure, not just a single surface.
Thanks
Do You mean on same axes?
I haven't found a function that does this directly. But it is possible to pass the desired colors in the surf function.
Way I found:
Convert the data to a 0-1 scale and then convert to the desired colormap.
Example with hot and jet colormaps:
tx = ty = linspace (-8, 8, 41)';
[xx, yy] = meshgrid (tx, ty);
r = sqrt (xx .^ 2 + yy .^ 2) + eps;
tz = sin (r) ./ r ;
function normalized = normalize_01(data)
data_min = min(min(data))
data_max = max(max(data))
normalized = (data - data_min)/(data_max - data_min)
endfunction
function rgb = data2rgb(data, color_bits, cmap)
grays = normalize_01(data)
indexes = gray2ind(grays, color_bits)
rgb = ind2rgb(indexes, cmap)
endfunction
color_bits = 128
cmap_1 = hot(color_bits)
rgb_1 = data2rgb(tz, color_bits, cmap_1)
surf(tx, ty, tz, rgb_1)
hold on
cmap_2 = jet(color_bits)
rgb_2 = data2rgb(tz+3, color_bits, cmap_2)
surf(tx, ty, tz+3, rgb_2)
But if you also need a colorbar, this way might not be useful. Unless you find a way to manually add two colorbar like I did with the cmap.
All, I am trying to take the laplacian of the following function:
g(x,y) = 1/2cx^2+1/2dy2
The laplacian is c + d, which is a constant. Using FFT I should get the same ( in my FFT example I am padding the function to avoid edge effects).
Here is my code:
Define a 2D function
n = 30 # number of points
Lx = 30 # extension in x
Ly = 30 # extension in x
dx = n/Lx # Step in x
dy = n/Ly # Step in x
c=4
d=4
x=np.arange(-Lx/2,Lx/2)
y=np.arange(-Ly/2,Ly/2)
g = np.zeros((Lx,Ly))
lapg = np.zeros((Lx,Ly))
for j in range(Ly):
for i in range(Lx):
g[i,j] = (1/2)*c*x[i]**2 + (1/2)*d*y[j]**2
lapg[i,j] = c + d
kxpad = 2*np.pi*np.fft.fftfreq(2*Lx,d=dx)
#kxpad = (2*np.pi/(2*Lx))*np.arange(-2*Lx/2,2*Lx/2)
#kxpad = np.fft.fftshift(kxpad)
#kypad = (2*np.pi/(2*Ly))*np.arange(-2*Ly/2,2*Ly/2)
#kypad = np.fft.fftshift(kypad)
kypad = 2*np.pi*np.fft.fftfreq(2*Ly,d=dy)
kpad = np.zeros((2*Lx,2*Ly))
for j in range(2*Ly):
for i in range(2*Lx):
kpad[i,j] = math.sqrt(kxpad[i]**2+kypad[j]**2)
kpad = np.fft.fftshift(kpad)
gpad = np.zeros((2*Lx,2*Ly))
gpad[:Lx,:Ly] = g # Filling main part of g in gpad
gpad[:Lx,Ly:] = g[:,-1::-1] # Filling the last 3 columns of gpad with g flipped
gpad[Lx:,:Ly] = g[-1::-1,:]# Filling the last 3 lines of gpad with g flipped
gpad[Lx:,Ly:] = g[-1::-1, -1::-1]# Filling the last 3 lines and last 3 columns of gpad with g flipped in line and column
rdFFT2D = np.zeros((Lx,Ly))
gpadhat = np.fft.fft2(gpad)
dgpadhat = -(kpad**2)*gpadhat #taking the derivative iwFFT(f)
rdpadFFT2D = np.real(np.fft.ifft2(dgpadhat))
rdFFT2D = rdpadFFT2D[:Lx,:Ly]
[
First image is the plot of the original function g(x,y), 2nd image is the analytical laplacian of g and 3rd image is the sugar loaf in Rio de Janeiro( lol ), actually it is the laplacian using FFT. What Am I doing wrong here?
Edit : Commenting on ripple effect.
Cris you mean the ripple effect due to the set_zlimit in the image below?Just to remember you that the result should be 8.
Edit 2 : Using non-symmetrical x and y values, produce the two images.
The padding will not change the boundary condition: You are padding by replicating the function, mirrored, four times. The function is symmetric, so the mirroring doesn't change it. Thus, your padding simply repeats the function four times. The convolution through the DFT (which you're attempting to implement) uses a periodic boundary condition, and thus already sees the input function as periodic. Replicating the function will not improve the convolution results at the edges.
To improve the result at the edges, you would need to implement a different boundary condition, the most effective one (since the input is analytical anyway) is to simply extend your domain and then crop it after applying the convolution. This introduces a boundary extension where the image is padded by seeing more data outside the original domain. It is an ideal boundary extension suitable for an ideal case where we don't have to deal with real-world data.
This implements the Laplace though the DFT with greatly simplified code, where we ignore any boundary extension, as well as the sample spacing (basically setting dx=1 and dy=1):
import numpy as np
import matplotlib.pyplot as pp
n = 30 # number of points
c = 4
d = 4
x = np.arange(-n//2,n//2)
y = np.arange(-n//2,n//2)
g = (1/2)*c*x[None,:]**2 + (1/2)*d*y[:,None]**2
kx = 2 * np.pi * np.fft.fftfreq(n)
ky = 2 * np.pi * np.fft.fftfreq(n)
lapg = np.real(np.fft.ifft2(np.fft.fft2(g) * (-kx[None, :]**2 - ky[:, None]**2)))
fig = pp.figure()
ax = fig.add_subplot(121, projection='3d')
ax.plot_surface(x[None,:], y[:,None], g)
ax = fig.add_subplot(122, projection='3d')
ax.plot_surface(x[None,:], y[:,None], lapg)
pp.show()
Edit: Boundary extension would work as follows:
import numpy as np
import matplotlib.pyplot as pp
n_true = 30 # number of pixels we want to compute
n_boundary = 15 # number of pixels to extend the image in all directions
c = 4
d = 4
# First compute g and lapg including boundary extenstion
n = n_true + n_boundary * 2
x = np.arange(-n//2,n//2)
y = np.arange(-n//2,n//2)
g = (1/2)*c*x[None,:]**2 + (1/2)*d*y[:,None]**2
kx = 2 * np.pi * np.fft.fftfreq(n)
ky = 2 * np.pi * np.fft.fftfreq(n)
lapg = np.real(np.fft.ifft2(np.fft.fft2(g) * (-kx[None, :]**2 - ky[:, None]**2)))
# Now crop the two images to our desired size
x = x[n_boundary:-n_boundary]
y = y[n_boundary:-n_boundary]
g = g[n_boundary:-n_boundary, n_boundary:-n_boundary]
lapg = lapg[n_boundary:-n_boundary, n_boundary:-n_boundary]
# Display
fig = pp.figure()
ax = fig.add_subplot(121, projection='3d')
ax.plot_surface(x[None,:], y[:,None], g)
ax.set_zlim(0, 800)
ax = fig.add_subplot(122, projection='3d')
ax.plot_surface(x[None,:], y[:,None], lapg)
ax.set_zlim(0, 800)
pp.show()
Note that I'm scaling the z-axes of the two plots in the same way to not enhance the effects of the boundary too much. Fourier-domain filtering like this is typically much more sensitive to edge effects than spatial-domain (or temporal-domain) filtering because the filter has an infinitely-long impulse response. If you leave out the set_zlim command, you'll see a ripple effect in the otherwise flat lapg image. The ripples are very small, but no matter how small, they'll look huge on a completely flat function because they'll stretch from the bottom to the top of the plot. The equal set_zlim in the two plots just puts this noise in proportion.
I have two sets of coordinates (both positive and negative values, not necessarily in increasing order, and in many cases there are different values of y for the same value of x) which I can load into two row vectors of equal size.
I want to calculate the area enclosed by the curve.
How to do it with octave?
I tried this answer but it does not work because it seems that the area printed (204.64) is too high (see picture).
I tried the code:
function showdata(fName)
M = dlmread(fName);
H = M(2:end, 1); % starting row number is 2
B = M(2:end, 2);
aux = figure();
plot(H, B,'linewidth',2);
xlabel ("Auxilary field H (A/m)");
ylabel ("Magnetic Field B (Tesla)");
area = polyarea(H,B)
axis([min(H), max(H), min(B), max(B)]);
grid on;
grid minor on;
title (area,"fontsize",20);
Then I am calling showdata('data.txt') in Octave.
Picture of Data points:
This is the data file I am using.
There is a function for computing convex hull called "convhull" in Octave. It returns the indices of the points formming convex hull data.
M = dlmread("data.txt"); #I removed the header in data.txt
x = M(:,1);
y = M(:,2);
k = convhull(x,y);
plot (x(k), y(k), "r-", x, y, "b+");
n = rows(k);
x_prime = vertcat(x(k(n)), x(k(1:n-1)));
y_prime = vertcat(y(k(n)), y(k(1:n-1)));
A = .5*abs(x_prime'*y(k)-y_prime'*x(k)); #80.248
polyarea(x(k), y(k)) == A and true
Maybe convex hull is not good estimate of area because the top left and the down-right lines are a little far away from the points. There are other ways to form a polygon from data
, one of which could be alpha shape. However, alpha shape are more complicated and there is no corresponding pre-built function in Octave.
Update:
Each x corresponds to at least one y cordinate. I marked the highest point and lowest point laying on the same x and estimate the area again.
There is the code:
[uni, ~] = sort(unique(x));
n = rows(uni);
outline = [];
for i = 1:n
y_list = y(x==uni(i));
[y_max, ~] = max(y_list);
outline(i, :)= [uni(i), y_max];
[y_min, ~] = min(y_list);
outline(2*n-i+1,:)= [uni(i), y_min];
endfor
figure;
plot (x(k), y(k), "r-", x, y, "b+", outline(:,1), outline(:,2), "g-", "linewidth", 3);
polyarea(outline(:,1), outline(:,2)) #74.856
By the way, if the arguments of function polyarea do not form a close curve function polyarea would return wrong area.
Four point on a unit square:
[(0,0), (1,0), (1,1), (0,1)], [(0,0), (1,1), (1,0), (0,1)]
polyarea([0,1,1,0],[0,0,1,1])!==polyarea([0,1,1,0],[0,1,0,1]).
I have a scilab function that looks something like this (very simplified code just to get the concept of how it works):
function [A, S, Q]=myfunc(a)
A = a^2;
S = a+a+a;
if S > A then
Q = "Bigger";
else
Q = "Lower";
end
endfunction
And I get the expected result if I run:
--> [A,S,Q]=myfunc(2)
Q =
Bigger
S =
6.
A =
4.
But if I put matrices into the function I expect to get equivalent matrices back as an answer with a result but instead I got this:
--> [A,S,Q]=myfunc([2 4 6 8])
Q =
Lower
S =
6. 12. 18. 24.
A =
4. 16. 36. 64.
Why isn't Q returning matrices of values like S and A? And how do I achieve that it will return "Bigger. Lower. Lower. Lower." as an answer? That is, I want to perform the operation on each element of the matrix.
Because in your program you wrote Q = "Bigger" and Q = "Lower". That means that Q will only have one value. If you want to store the comparisons for every value in A and S, you have to make Scilab do that.
You can achieve such behavior by using loops. This is how you can do it by using two for loops:
function [A, S, Q]=myfunc(a)
A = a^2;
S = a+a+a;
//Get the size of input a
[nrows, ncols] = size(a)
//Traverse all rows of the input
for i = 1 : nrows
//Traverse all columns of the input
for j = 1 : ncols
//Compare each element
if S(i,j) > A(i,j) then
//Store each result
Q(i,j) = "Bigger"
else
Q(i,j) = "Lower"
end
end
end
endfunction
Beware of A = a^2. It can break your function. It has different behaviors if input a is a vector (1-by-n or n-by-1 matrix), rectangle matrix (m-by-n matrix, m ≠ n ), or square matrix (n-by-n matrix):
Vector: it works like .^, i.e. it raises each element individually (see Scilab help).
Rectangle: it won't work because it has to follow the rule of matrix multiplication.
Square: it works and follows the rule of matrix multiplication.
I will add that in Scilab, the fewer the number of loop, the better : so #luispauloml answer may rewrite to
function [A, S, Q]=myfunc(a)
A = a.^2; // used element wise power, see luispauloml advice
S = a+a+a;
Q(S > A) = "Bigger"
Q(S <= A) = "Lower"
Q = matrix(Q,size(a,1),size(a,2)) // a-like shape
endfunction
I have a problem with estimation.
I have a function, which is dependent on the values of an unknown vector V = [v1, …, v4].
I also have a vector of reference data YREF = [yref1, …, yrefn].
I would like to write a function, which returns the vector Y (in order to compare it later, say using lsqnonlin). I am aware of the “arrayfun”, but it seems not to work.
I have a subfunction, which returns a concrete value from the range [-100, 100],
%--------------------------------------------------------------------------
function y = SubFunction(Y, V)
y = fzero(#(x) v(1).*sinh(x./v(2)) + v(3).*x - Y, [-100 100]);
end
%--------------------------------------------------------------------------
then I make some operations on the results:
%--------------------------------------------------------------------------
function y = SomeFunction(Y,V)
temp = SubFunction (Y,V);
y = temp + v(4).*Y;
end
%--------------------------------------------------------------------------
These functions work well for a single value of Y, but not for the whole vector. How to store the results into a matrix for future comparison?
Thanks in advance
Chris
If Y is a vector, then the anonymous function defined as an argument to fzero returns a vector, not a scalar.
You can solve it by using a loop (notice the Y(k) inside the anonymous function definition):
function y = SubFunction(Y, v)
y = zeros (size(Y));
for k = 1 : length (Y)
y(k) = fzero(#(x) v(1).*sinh(x./v(2)) + v(3).*x - Y(k), [-100 100]);
end
end