I have been trying to add axis to a surf plot i have. I've tried various suggestions but can't get it to work. I have 3 matrices:
final -> 3460x300 double
spec -> 1x300 double (x-axis)
timedate -> 1x3460 double (y-axis)
The timedate matrix values are converted time and dates with date2num.
I tried
plot = surf(final);
set(plot,'LineStyle','none');
which gives me the correct graph but the axis are wrong. See image:
When i try
[xx,yy] = meshgrid(spec,timedate)
plot2 = surf(xx,yy,final);
set(plot,'LineStyle','none');
It gives me the correct axis but the graph seems stretched
How could i solve this?
Thanks in advance
The second graph seems to be correct, the first one assumes a fixed distance between samples and the second one uses the complete info (x, y and z axis), below is a simplification of your problem:
Let's say you want to graph the curve described by the points (0.5, 1), (1, 2), (1.5, 3), (2, 4), the correct way of doing that is:
x = [0.5, 1, 1.5, 2];
y = [1, 2, 3, 4];
plot(x, y)
But you are doing:
plot(y)
Both graphs will show the same curve (because points are sampled with fixed distance in the x axis) but the points will be scaled and displaced along the X axis.
But, What if the points are now (0.5, 1), (1.2, 2), (1.4, 3), (2.2, 4)?:
plot(x,y) and plot(y) will show different curves because points were not sampled with fixed distance along the x axis, that's what happens in your problem.
Related
I working on a Matlab worksheet to study for my final. I know the answer, but I'm having trouble understanding, which is the entire point.
for the fill function, where fill is "fill(x, y, colorspec)"
If x and y are represented as vectors, how would I visualize them?
In the following: fill([1 -1 -1 1],[1 1 -1 -1], 'k') a black filled square is generated.
I'm just having trouble understanding how those two vectors make a square.
Work backwards. Draw a square with corners at all possible combinations of +/-1. Label the corners with the coordinates. Trace the square from the upper right (1, 1), going counter-clockwise. You get the sequence (1, 1), (-1, 1), (-1, -1), (1, -1). The arrays x and y are the x- and y-coordinates of the points in that sequence, respectively: x = [1, -1, -1, 1] and y = [1, 1, -1, -1].
In general, fill expects you to represent any n-sided polygon with two vectors of length n containing the x- and y-coordinates of the vertices.
I have two equations:
ellipseOne = '((x-1)^2)/6^2 + y^2/3^2 = 1';
and
ellipseTwo = '((x+2)^2)/2^2 + ((y-5)^2)/4^2 = 1';
and I plotted them:
ezplot(ellipseOne, [-10, 10, -10, 10])
hold on
ezplot(ellipseTwo, [-10, 10, -10, 10])
title('Ellipses')
hold off
Now I'm trying to find the intersection of the two ellipses. I tried:
intersection = solve(ellipseOne, ellipseTwo)
intersection.x
intersection.y
to find the points where they intersect, but MATLAB is giving me a matrix and an equation as an answer which I don't understand. Could anyone point me in the right direction to get the coordinates of intersection?
The solution is in symbolic form. The last step you need to take is to transform it into numeric. Simply convert the result using double. However, because this is a pair of quadratic equations, there are 4 possible solutions due to the sign ambiguity (i.e. +/-) and can possibly give imaginary roots. Therefore, isolate out the real solutions and what is left should be your answer.
Therefore:
% Your code
ellipseOne = '((x-1)^2)/6^2 + y^2/3^2 = 1';
ellipseTwo = '((x+2)^2)/2^2 + ((y-5)^2)/4^2 = 1';
intersection = solve(ellipseOne, ellipseTwo);
% Find the points of intersection
X = double(intersection.x);
Y = double(intersection.y);
mask = ~any(imag(X), 2) | ~any(imag(Y), 2);
X = X(mask); Y = Y(mask);
The first three lines of code are what you did. The next four lines extract out the roots in numeric form, then I create a logical mask that isolates out only the points that are real. This looks at the imaginary portion of both the X and Y coordinate of all of the roots and if there is such a component for any of the roots, we want to eliminate those. We finally remove the roots that are imaginary and we should be left with two real roots.
We thus get for our intersection points:
>> disp([X Y])
-3.3574 2.0623
-0.2886 2.9300
The first column is the X coordinate and the second column is the Y coordinate. This also seems to agree with the plot. I'll take your ellipse plotting code and also insert the intersection points as blue dots using the above solution:
ezplot(ellipseOne, [-10, 10, -10, 10])
hold on
ezplot(ellipseTwo, [-10, 10, -10, 10])
% New - place intersection points
plot(X, Y, 'b.');
title('Ellipses');
hold off;
I would like create a Matlab figure with a double X axis (m/s and km/h) with the same plot.
I have found plotyy and - in Matlab reposity - plotyyy, but I am looking for:
A double X axis.
Together below the plot.
My code is very simple:
stem(M(:, 1) .* 3.6, M(:, 3));
grid on
xlabel('Speed (km/h)');
ylabel('Samples');
M(:, 1) is the speed (in m/s), and M(:, 3) is the data.
I would like only a second line, in the bottom, with the speeds in m/s.
You can do something like the following. In comparison to the solution of #Benoit_11 I do use the normal Matlab labels and refer to both axes with handles so the assignments are explicit.
The following code creates an empty x-axis b with the units m/s with a negligible height. After this, the actual plot is drawn in a second axes a located a bit above the other axes and with units km/h. To plot on a specific axes, insert the axes-handle as the first argument of stem. The conversion from m/s to km/h is directly written in the call to stem. Finally, it's needed to set the xlim-property of the both axes to the same values.
% experimental data
M(:,1) = [ 0, 1, 2, 3, 4, 5];
M(:,3) = [12, 10, 15, 12, 11, 13];
% get bounds
xmaxa = max(M(:,1))*3.6; % km/h
xmaxb = max(M(:,1)); % m/s
figure;
% axis for m/s
b=axes('Position',[.1 .1 .8 1e-12]);
set(b,'Units','normalized');
set(b,'Color','none');
% axis for km/h with stem-plot
a=axes('Position',[.1 .2 .8 .7]);
set(a,'Units','normalized');
stem(a,M(:,1).*3.6, M(:,3));
% set limits and labels
set(a,'xlim',[0 xmaxa]);
set(b,'xlim',[0 xmaxb]);
xlabel(a,'Speed (km/h)')
xlabel(b,'Speed (m/s)')
ylabel(a,'Samples');
title(a,'Double x-axis plot');
As a very simple alternative you could also create a 2nd axis (transparent) and put it below the first one so that you only see the x axis.
Example:
clear
clc
close all
x = 1:10;
x2 = x/3.6;
y = rand(size(x));
hP1 = plot(x,y);
a1Pos = get(gca,'Position');
%// Place axis 2 below the 1st.
ax2 = axes('Position',[a1Pos(1) a1Pos(2)-.05 a1Pos(3) a1Pos(4)],'Color','none','YTick',[],'YTickLabel',[]);
%// Adjust limits
xlim([min(x2(:)) max(x2(:))])
text(2.85,0 ,'m/s','FontSize',14,'Color','r')
text(2.85,.05 ,'km/h','FontSize',14,'Color','r')
Output:
Then you can manually add the x labels for each unit, in different color for example.
The best way i can think to do it is to use 2 plots, for example, you can split the plot into a large and small section by doing something like this:
subplot(100, 1, 1:99) // plot your graph as you normally would
plot(...
subplot(100, 1, 100) // Plot a really small plot to get the axis
plot(...)
b = axis()
axis([b(1:2), 0, 0]) // set the y axis to really small
This is untested, you might need to fiddle around a little but it should hopefully put you on the right track.
i just started with my master thesis and i already am in trouble with my capability/understanding of matlab.
The thing is, i have a trajectory on a surface of a planet/moon whatever (a .mat with the time, and the coordinates. Then i have some .mat with time and the measurement at that time.
I am able to plot this as a color coded trajectory (using the measurement and the coordinates) in scatter(). This works awesomely nice.
However my problem is that i need something more sophisticated.
I now need to take the trajectory and instead of color-coding it, i am supposed to add the graph (value) of the measurement (which is given for each point) to the trajectory (which is not always a straight line). I will added a little sketch to explain what i want. The red arrow shows what i want to add to my plot and the green shows what i have.
You can always transform your data yourself: (using the same notation as #Shai)
x = 0:0.1:10;
y = x;
m = 10*sin(x);
So what you need is the vector normal to the curve at each datapoint:
dx = diff(x); % backward finite differences for 2:end points
dx = [dx(1) dx]; % forward finite difference for 1th point
dy = diff(y);
dy = [dy(1) dy];
curve_tang = [dx ; dy];
% rotate tangential vectors 90° counterclockwise
curve_norm = [-dy; dx];
% normalize the vectors:
nrm_cn = sqrt(sum(abs(curve_norm).^2,1));
curve_norm = curve_norm ./ repmat(sqrt(sum(abs(curve_norm).^2,1)),2,1);
Multiply that vector with the measurement (m), offset it with the datapoint coordinates and you're done:
mx = x + curve_norm(1,:).*m;
my = y + curve_norm(2,:).*m;
plot it with:
figure; hold on
axis equal;
scatter(x,y,[],m);
plot(mx,my)
which is imo exactly what you want. This example has just a straight line as coordinates, but this code can handle any curve just fine:
x=0:0.1:10;y=x.^2;m=sin(x);
t=0:pi/50:2*pi;x=5*cos(t);y=5*sin(t);m=sin(5*t);
If I understand your question correctly, what you need is to rotate your actual data around an origin point at a certain angle. This is pretty simple, as you only need to multiply the coordinates by a rotation matrix. You can then use hold on and plot to overlay your plot with the rotated points, as suggested in the comments.
Example
First, let's generate some data that resembles yours and create a scatter plot:
% # Generate some data
t = -20:0.1:20;
idx = (t ~= 0);
y = ones(size(t));
y(idx) = abs(sin(t(idx)) ./ t(idx)) .^ 0.25;
% # Create a scatter plot
x = 1:numel(y);
figure
scatter(x, x, 10, y, 'filled')
Now let's rotate the points (specified by the values of x and y) around (0, 0) at a 45° angle:
P = [x(:) * sqrt(2), y(:) * 100] * [1, 1; -1, 1] / sqrt(2);
and then plot them on top of the scatter plot:
hold on
axis square
plot(P(:, 1), P(:, 2))
Note the additional things have been done here for visualization purposes:
The final x-coordinates have been stretched (by sqrt(2)) to the appropriate length.
The final y-coordinates have been magnified (by 100) so that the rotated plot stands out.
The axes have been squared to avoid distortion.
This is what you should get:
It seems like you are interested in 3D plotting.
If I understand your question correctly, you have a 2D curve represented as [x(t), y(t)].
Additionally, you have some value m(t) for each point.
Thus we are looking at the plot of a 3D curve [x(t) y(t) m(t)].
you can easily achieve this using
plot3( x, y, m ); % assuming x,y, and m are sorted w.r.t t
alternatively, you can use the 3D version of scatter
scatter3( x, y, m );
pick your choice.
Nice plot BTW.
Good luck with your thesis.
p = [3,3]
plot(p, 'x')
This weirdly generates this:
I'd like it to be a point at x=3/y=3 on the plot. How?
#mathematician1975 is right, but I feel like this requires a bit more explanation:
Like the official documentation states:
plot(Y) plots the columns of Y versus the index of each value when Y is a real number.
so in fact this is not weird at all that plot(p, 'x') plots each value in p against its index, i.e. the points (1, 3) and (2, 3).
This is actually handy in some cases (when you want the x-coordiantes to be a running index), but not in yours. To plot point p correctly, use the syntax plot(X, Y), that is:
plot(p(2), p(1), 'x')
(here I assumed that the y-coordinate is the first in p, but if it's the x-coordinates you can just swap the places of the input arguments).
In the general case, if p is a matrix with two columns (say, the first contains all y-coordinates and the second all x-coordinates), you can plot all points like so:
plot(p(:, 2), p(:, 1), 'x')
You need vectors of each coordinate. For example:
x = [3,4]
y = [5,6]
plot(x,y,'x')
will plot the points (3,5) and (4,6)