Assigning curve fitting polynomial value to a vector - matlab

I am trying to get a vector of different torque values with respect to speed of an electric motor. To do that I used some torque values at certain speeds and tried to fit a curve to them.
tpdata=[0 10 20 30 40 50 60 65 70 75 80 85 90 93.3 95.8 98 99 100];
pdata=[3.3 3.05 2.81 2.79 2.80 2.88 3.02 3.12 3.20 3.28 3.13 2.75 2.10 1.5 1 0.5 0.25 0];
I modified it according to my need
u=2880/690
ydata=pdata*3.65*u
tsdata=tpdata*30/u
I used the curve fitting tool to get the constants.
p1 = -2.4592e-20
p2 = 1.51e-16
p3 = -2.7946e-13
p4 = 2.3662e-10
p5 = -1.0391e-07
p6 = 2.3887e-05
p7 = -0.0024883
p8 = 0.035497
p9 = 50.272
I want to assign the solution of the fitted polynomial (from 1 rpm to 720 rpm) to a vector that I named as y (torque values)
I can get the solution plot but I cannot see them or assign them as a vector.
for i=1:720
y = p1*i^8 + p2*i^7 + p3*i^6 + p4*i^5 + p5*i^4 + p6*i^3 + p7*i^2 + p8*i + p9;
plot(i,y,'d');
hold on
grid on
end
When I add y=zeros(1,720) and change y to y(1,i) the script fails.
What is the reason of this?

You are saving the solution each time in y that is being overwritten in the next loop. You should probably do like this:
for i=1:720
y(i) = p1*i^8 + p2*i^7 + p3*i^6 + p4*i^5 + p5*i^4 + p6*i^3 + p7*i^2 + p8*i + p9;
end
plot(y,'d');
hold on
grid on
Now you get a vector y(1x720). You dont need to do y=zeros(1,720)...

Related

Matlab calculating line parameter x for 10 layers in the given wavelength range

I know how to calculate the line parameter defined as x below for one layer, considering the given wavelength range 50 to 550 um. Now I want to repeat this calculation for all 10 layers. all the other parameters remain as a constant while temperature varies from layer 1 to 10.Any suggestion would be greatly appreciated.
wl=[100 200 300 400 500]; %5 wavelengths, 5 spectral lines
br=[0.12 0.56 0.45 0.67 0.89]; % broadening parameter for each wavelength
T=[101 102 103 104 105 106 107 108 109 110];% temperature for 10 layers
wlall=linspace(50,550,40);%all the wavelength in 50um to 550 um range
% x is defined as,
%(br*wl/(br*br + (wlall-wl)^2))*br;
%If I do a calculation for the first line
((br(1)*T(1)*wl(1))./(br(1)*br(1)*(T(1)) + (wlall(:)-wl(1)).^2))*br(1)*T(1)
%Now I'm going to calculate it for all the lines in the first layer
k= repmat(wlall,5,1);
for i=1:5;
kn(i,:)=(br(i)*T(1)* wl(i)./(br(i)*br(i)*T(1) + (k(i,:)-
wl(i)).^2))*br(i)*T(1);
end
%Above code gives me x parameter for all the wavelengths in the
%given range( 50 to 550 um) in the first layer, dimension is (5,40)
% I need only the maximum value of each column
an=(kn(:,:)');
[ll,mm]=sort(an,2,'descend');
vn=(ll(:,1))'
%Now my output has the dimension , (1,40) one is for the first layer, 40 is
%for the maximum x parameter corresponding to each wavelength in first layer
%Now I want to calculate the x parameter in all 10 layers,So T should vary
%from T(1) to T(10) and get the
%maximum in each column, so my output should have the dimension ( 10, 40)
You just need to run an extra 'for' loop for each value of 'T'. Here is an example:
clc; close all; clear all;
wl=[100 200 300 400 500]; %5 wavelengths, 5 spectral lines
br=[0.12 0.56 0.45 0.67 0.89]; % broadening parameter for each wavelength
T=[101 102 103 104 105 106 107 108 109 110];% temperature for 10 layers
wlall=linspace(50,550,40);%all the wavelength in 50um to 550 um range
% x is defined as,
%(br*wl/(br*br + (wlall-wl)^2))*br;
%If I do a calculation for the first line
((br(1)*T(1)*wl(1))./(br(1)*br(1)*(T(1)) + (wlall(:)-wl(1)).^2))*br(1)*T(1)
%Now I'm going to calculate it for all the lines in the first layer
k= repmat(wlall,5,1);
for index = 1:numel(T)
for i=1:5
kn(i,:, index)=(br(i)*T(index)* wl(i)./(br(i)*br(i)*T(index) + (k(i,:)- wl(i)).^2))*br(i)*T(index);
end
an(:, :, index) = transpose(kn(:, :, index));
vn(:, index) = max(an(:, :, index), [], 2);
end
vn = transpose(vn);

how to apply transform to 2d points in matlab?

Using matlab, I want to apply transform contain of rotate and translate to 2d points.
for example my points are:
points.x=[1 5 7 100 52];
points.y=[42 96 71 3 17];
points.angle=[2 6 7 9 4];
the value of rotate is:30 degree
the value of x_translate is 5.
the value of y_translate is 54.
can any body help me to write matlab code for apply this transform to my points and calculate new coordinate of points after transform?
I don't know what you mean by points.angle since the angle of the points with respect to origin (in a trigonometric sense) is already defined by atand2(y,x)
Here is the code:
clear;clc
oldCoord = [1 5 7 100 52;42 96 71 3 17];
newCoord = zeros(size(oldCoord));
theta = 30 * pi/180;
T = #(theta) [cos(theta), -sin(theta); sin(theta) , cos(theta)];
trans = [5;54];
for m = 1:size(oldCoord,2)
newCoord(:,m) = T(theta) * oldCoord(:,m) + trans;
end
Result:
oldCoord =
1 5 7 100 52
42 96 71 3 17
newCoord =
-15.1340 -38.6699 -24.4378 90.1025 41.5333
90.8731 139.6384 118.9878 106.5981 94.7224

3D histogram and conditional coloring

I have a series of ordered points (X, Y, Z) and I want to plot a 3D histogram, any suggestions?
I'm trying to do it by this tutorial http://www.mathworks.com/help/stats/hist3.html , but points are random here and presented as a function. My example is easier, since i already know the points.
Furthermore, depending on the number value of Z coordinate, i'd like to colour it differently. E.g. Max value - green, min value - red. Similar as in this case Conditional coloring of histogram graph in MATLAB, only in 3D.
So, if I have a series of points:
X = [32 64 32 12 56 76 65]
Y = [160 80 70 48 90 80 70]
Z = [80 70 90 20 45 60 12]
Can you help me with the code for 3D histogram with conditional coloring?
So far the code looks like this:
X = [32 64 32 12 56 76 65];
Y= [160 80 70 48 90 80 70];
Z= [80 70 90 20 45 60 12];
A = full( sparse(X',Y',Z'));
figure;
h = bar3(A); % get handle to graphics
for k=1:numel(h),
z=get(h(k),'ZData'); % old data - need for its NaN pattern
nn = isnan(z);
nz = kron( A(:,k),ones(6,4) ); % map color to height 6 faces per data point
nz(nn) = NaN; % used saved NaN pattern for transparent faces
set(h(k),'CData', nz); % set the new colors
end
colorbar;
Now I just have to clear the lines and design the chart to make it look useful. But how would it be possible to make a bar3 without the entire mesh on 0 level?
Based on this answer, all you need to do is rearrange your data to match the Z format of that answer. After than you might need to remove edgelines and possibly clear the zero height bars.
% Step 1: rearrange your data
X = [32 64 32 12 56 76 65];
Y= [160 80 70 48 90 80 70];
Z= [80 70 90 20 45 60 12];
A = full( sparse(X',Y',Z'));
% Step 2: Use the code from the link to plot the 3D histogram
figure;
h = bar3(A); % get handle to graphics
set(h,'edgecolor','none'); % Hopefully this will remove the lines (from https://www.mathworks.com/matlabcentral/newsreader/view_thread/281581)
for k=1:numel(h),
z=get(h(k),'ZData'); % old data - need for its NaN pattern
nn = isnan(z);
nz = kron( A(:,k),ones(6,4) ); % map color to height 6 faces per data point
nz(nn) = NaN; % used saved NaN pattern for transparent faces
nz(nz==0) = NaN; % This bit makes all the zero height bars have no colour
set(h(k),'CData', nz); % set the new colors. Note in later versions you can do h(k).CData = nz
end
colorbar;

Fast way to find the neighboor of pixel

I am programming for task that finds the neighbor of a given pixel x in image Dthat can formula as:
The formula shown pixels y which satisfy the distance to pixel x is 1, then they are neighbor of pixel x. This is my matlab code. However, it still takes long time to find. Could you suggest a faster way to do it. Thank you so much
%-- Find the neighborhood of one pixel
% x is pixel coordinate
% nrow, ncol is size of image
function N = find_neighbor(x,nrow,ncol)
i = x(1);
j = x(2);
I1 = i+1;
if (I1 > nrow)
I1 = nrow;
end
I2 = i-1;
if (I2 < 1)
I2 = 1;
end
J1 = j+1;
if (J1 > ncol)
J1 = ncol;
end
J2 = j-1;
if (J2 < 1)
J2 = 1;
end
N = [I1, I2, i, i; j, j, J1, J2];
For example: ncol=128; nrow=128; x =[30;110] then output
N =31 29 30 30; 110 110 111 109]
For calling the function in loop
x=[30 31 32 33; 110 123 122 124]
for i=1:length(x)
N = find_neighbor(x(:,i),nrow,ncol);
end
Here's a vectorized approach using bsxfun:
% define four neighbors as coordinate differences
d = [-1 0 ; 1 0 ; 0 -1 ; 0 1]';
% add to pixel coordinates
N = bsxfun(#plus, x, permute(d, [1 3 2]));
% make one long list for the neighbors of all pixels together
N = reshape(N, 2, []);
% identify out-of-bounds coordinates
ind = (N(1, :) < 1) | (N(1, :) > nrow) | (N(2, :) < 1) | (N(2, :) > ncol);
% and remove those "neighbors"
N(:, ind) = [];
The permute is there to move the "dimension" of four different neighbors into the 3rd array index. This way, using bsxfun, we get the combination of every pair of original pixel coordinates with every pair of relative neighbor coordinates. The out-of-bounds check assumes that nrow belongs to the first coordinate and ncol to the second coordinate.
With
ncol=128;
nrow=128;
x = [30 31 32 33; 110 123 122 124];
the result is
N =
29 30 31 32 31 32 33 34 30 31 32 33 30 31 32 33
110 123 122 124 110 123 122 124 109 122 121 123 111 124 123 125
Different neighbors of different pixels can end up to be the same pixel, so there can be duplicates in the list. If you only want each resulting pixel once, use
% remove duplicates?
N = unique(N', 'rows')';
to get
N =
29 30 30 30 31 31 31 32 32 32 33 33 33 34
110 109 111 123 110 122 124 121 123 124 122 123 125 124
Matlab's performance is horrible when calling small functions many time. The Matlab approach is to do vectorize as much as possible. A vectorized version of your code:
function N = find_neighbor(x,nrow,ncol)
N = [min(x(1,:)+1,nrow), max(x(1,:)-1,1), x(1,:), x(1,:); x(2,:), x(2,:),min(x(2,:)+1,ncol), max(x(2,:)-1,1)];
end
and usage
x=[30 31 32 33; 110 123 122 124]
N = find_neighbor(x,nrow,ncol);
BTW, for pixels on the border , your solution always gives 4 neighbors. This is wrong. the neighbors of (1,1) for examples should be only (2,1) and (1,2), while you add two extra (1,1).
The solution to this is quite simple - delete all neighbors that are outside the image
function N = find_neighbor(x,nrow,ncol)
N = [x(1,:)+1, x(1,:)-1, x(1,:), x(1,:); x(2,:), x(2,:),x(2,:)+1, x(2,:)-1];
N(:,N(1,:)<1 | N(1,:)> nrow | N(2,:)<1 | N(2,:)>ncol)=[];
end

Matlab 3D polar plot

I am struggling with the concepts behind plotting a surface polar plot.
I am trying to plot the values measured by a sensor at a combination of different angles over a hemisphere.
I have an array containing the following information:
A(:,1) = azimuth values from 0 to 360º
A(:,2) = zenith values from 0 to 90º
A(:,3) = values measured at the combination of angles of A(:,1) and A(:,2)
For example, here is a snippet:
0 15 0.489502132167206
0 30 0.452957556748497
0 45 0.468147850273115
0 60 0.471115818950192
0 65 0.352532182508945
30 15 0.424997863795610
30 30 0.477814980942155
30 45 0.383999653859467
30 60 0.509625464595446
30 75 0.440940431784788
60 15 0.445028058361392
60 30 0.522388502880219
60 45 0.428092266657885
60 60 0.429315072676194
60 75 0.358172892912138
90 15 0.493704001125912
90 30 0.508762762699997
90 45 0.450598496609200
90 58 0.468523071441297
120 15 0.501619699042408
120 30 0.561755273071577
120 45 0.489660355057938
120 60 0.475478615354648
120 75 0.482572226928475
150 15 0.423716506205776
150 30 0.426735372570756
150 45 0.448548968227972
150 60 0.478055144126694
150 75 0.437389584937356
To clarify, here is a piece of code that shows the measurement points on a polar plot.
th = A(:,1)*pi/180
polar(th,A(:,2))
view([180 90])
This gives me the following plot:
I would like now to plot the same thing, but instead of the points, use the values of these points stored in A(:,3). Then, I would like to interpolate the data to get a colored surface.
After some research, I found that I need to interpolate my values over a grid, then translate to Cartesian coordinates. From there I do not know how to proceed. Could someone point me in the right direction?
I have trouble getting the concept of the interpolation, but this is what I have attempted:
x1 = linspace(0,2*pi,100)
x2 = linspace(0,90,100)
[XX,YY] = meshgrid(x1,x2)
[x,y] = pol2cart(th,A(:,2))
gr=griddata(x,y,A(:,3),XX,YY,'linear')
With this piece of code, your example data points are converted into cartesian coords, and then plotted as "lines". The two tips of a line are one data point and the origin.
az = bsxfun(#times, A(:,1), pi/180);
el = bsxfun(#times, A(:,2), pi/180);
r = A(:,3);
[x,y,z] = sph2cart(az,el,r);
cx = 0; % center of the sphere
cy = 0;
cz = 0;
X = [repmat(cx,1,length(x));x'];
Y = [repmat(cy,1,length(y));y'];
Z = [repmat(cz,1,length(z));z'];
Still thinking how to interpolate the data so you can draw a sphere. See my comments to your question.