How to customize contour lines in Matlab? - matlab

I am preparing a contour map where I am supposed to highlight the contour line for a specific level. For Example, my contour line values are lying between -1 and 1 and I want to highlight the line corresponding to the value 0. I tried to do this using the following procedure,
[M,c]=contourf(longitude,latitude,delta',-1:0.2:1);
s=size(c.LevelList,2);
for i=1:s
if (c.LevelList(i)==0)
c.LevelWidth=2;
end;
end;
However, it does nothing to the contour map. Can anyone please help me with the appropriate procedure?

I would suggest simply using contour on your desired levels to highlight after the initial contourf, like so:
% Input.
x = linspace(-2*pi, 2*pi, 101);
y = x + pi;
[X, Y] = meshgrid(x, y);
Z = 0.5 * (sin(X) + cos(Y));
% Levels to plot with contourf.
levelsf = -1:0.2:1;
% Levels to highlight.
levels = [0 0.3];
figure(1);
hold on;
% Contourf all levels.
contourf(X, Y, Z, levelsf);
% Highlight levels with simple contour.
contour(X, Y, Z, levels, 'r', 'LineWidth', 2);
hold off;
For highlighting levels = [0 0.3], you'll get:

Related

Edit the x limits of least squares line

I created two scatter plots and then used lsline to add regression lines for each plot. I used this code:
for i=1:2
x = ..;
y = ..;
scatter(x, y, 50, 'MarkerFaceColor',myColours(i, :));
end
h_lines = lsline;
However, the darker line extends far beyond the last data point in that scatter plot (which is at around x=0.3):
lsline doesn't seem to have properties that allow its horizontal range to be set. Is there a workaround to set this separately for the two lines, in Matlab 2016a?
For a single data set
This is a workaround rather than a solution. lsline internally calls refline, which plots a line filling the axis as given by their current limits (xlim and ylim). So you can change those limits to the extent you want for the line, call lsline, and then restore the limits.
Example:
x = randn(1,100);
y = 2*x + randn(1,100); % random, correlated data
plot(x, y, '.') % scatter plot
xlim([-1.5 1.5]) % desired limit for line
lsline % plot line
xlim auto % restore axis limit
For several data sets
In this case you can apply the same procedure for each data set sequentially, but you need to keep only one data set visible when you call lsline; otherwise when you call it to create the second line it will also create a new version of the first (with the wrong range).
Example:
x = randn(1,100); y = 2*x + randn(1,100); % random, correlated data
h = plot(x, y, 'b.'); % scatter plot
axis([min(x) max(x) min(y) max(y)]) % desired limit for line
lsline % plot line
xlim auto % restore axis limit
hold on
x = 2*randn(1,100) - 5; y = 1.2*x + randn(1,100) + 6; % random, correlated data
plot(x, y, 'r.') % scatter plot
axis([min(x) max(x) min(y) max(y)]) % desired limit for line
set(h, 'HandleVisibility', 'off'); % hide previous plot
lsline % plot line
set(h, 'HandleVisibility', 'on'); % restore visibility
xlim auto % restore axis limit
Yet another solution: implement your own hsline. It's easy!
In MATLAB, doing a least squares fit of a straight line is trivial. Given column vectors x and y with N elements, b = [ones(N,1),x] \ y; are the parameters to the best fit line. [1,x1;1,x2]*b are the y locations of two points along the line with x-coordinates x1 and x2. Thus you can write (following Luis' example, and getting the exact same output):
N = 100;
x = randn(N,1); y = 2*x + randn(N,1); % random, correlated data
h = plot(x, y, 'b.'); % scatter plot
hold on
b = [ones(N,1),x] \ y;
x = [min(x);max(x)];
plot(x,[ones(2,1),x] * b, 'b-')
x = 2*randn(N,1) - 5; y = 1.2*x + randn(N,1) + 6; % random, correlated data
plot(x, y, 'r.') % scatter plot
b = [ones(N,1),x] \ y;
x = [min(x);max(x)];
plot(x,[ones(2,1),x] * b, 'r-')
You can get the points that define the line using
h_lines =lsline;
h_lines(ii).XData and h_lines(ii).YData will contain 2 points that define the lines for each ii=1,2 line. Use those to create en equation of a line, and plot the line in the range you want.

How can I fill an area below a 3D graph in MATLAB?

I created the following 3d plot in MATLAB using the function plot3:
Now, I want to get a hatched area below the "2d sub-graphs" (i.e. below the blue and red curves). Unfortunately, I don't have any idea how to realize that.
I would appreciate it very much if somebody had an idea.
You can do this using the function fill3 and referencing this answer for the 2D case to see how you have to add points on the ends of your data vectors to "close" your filled polygons. Although creating a pattern (i.e. hatching) is difficult if not impossible, an alternative is to simply adjust the alpha transparency of the filled patch. Here's a simple example for just one patch:
x = 1:10;
y = rand(1, 10);
hFill = fill3(zeros(1, 12), x([1 1:end end]), [0 y 0], 'b', 'FaceAlpha', 0.5);
grid on
And here's the plot this makes:
You can also create multiple patches in one call to fill3. Here's an example with 4 sets of data:
nPoints = 10; % Number of data points
nPlots = 4; % Number of curves
data = rand(nPoints, nPlots); % Sample data, one curve per column
% Create data matrices:
[X, Y] = meshgrid(0:(nPlots-1), [1 1:nPoints nPoints]);
Z = [zeros(1, nPlots); data; zeros(1, nPlots)];
patchColor = [0 0.4470 0.7410]; % RGB color for patch edge and face
% Plot patches:
hFill = fill3(X, Y, Z, patchColor, 'LineWidth', 1, 'EdgeColor', patchColor, ...
'FaceAlpha', 0.5);
set(gca, 'YDir', 'reverse', 'YLim', [1 nPoints]);
grid on
And here's the plot this makes:

plot some data such as pairs in matlab

I want to plot some data, but I can't.
It is assumed that we have 820 rows in 2 columns, representing the x and y coordinates.
My code is as follows:
load('MyMatFileName.mat');
[m , n]=size(inputs);
s = zeros(m,2);
for m=1:820
if inputs(m,end-1)<2 & inputs(m,end)<2
x = inputs(m,end-1)
y = inputs(m,end)
plot(x,y,'r','LineWidth',1.5)
hold on
end
end
I've edited your code and added comments to explain the changes you could make, but see below I've also re-written your code to be more like how it should be done:
load('MyMatFileName.mat'); % It's assumed "inputs" is in here
% You don't use the second size output, so use a tilde ~
[m, ~] = size(inputs);
%s = zeros(m,2); % You never use s...
% Use a different variable for the loop, as m is already the size variable
% I've assumed you wanted ii=1:m rather than m=1:820
figure
hold on % Use hold on and hold off around all of your plotting
for ii=1:m
if inputs(m,end-1)<2 && inputs(m,end)<2 % Use double ampersand for individual comparison
x = inputs(m,end-1)
y = inputs(m,end)
% Include the dot . to specify you want a point, not a line!
plot(x, y, 'r.','LineWidth',1.5)
end
end
hold off
A better way of doing this whole operation in Matlab would be to vectorise your code:
load('MyMatFileName.mat');
[m, ~] = size(inputs);
x = inputs(inputs(:,end-1) < 2 & inputs(:,end) < 2, end-1);
y = inputs(inputs(:,end-1) < 2 & inputs(:,end) < 2, end);
plot(x, y, 'r.', 'linewidth', 1.5);
Note that this will plot points, if you want to plot the line, use
plot(x, y, 'r', 'linewidth', 1.5); % or plot(x, y, 'r-', 'linewidth', 1.5);

MATLAB how to plot contour with special LineWidth for certain value

I have the following script:
close all; clear all; clc;
x = linspace(-2*pi,2*pi);
y = linspace(0,4*pi);
[X,Y] = meshgrid(x,y);
Z = sin(X)+cos(Y);
values = -10:0.5:10;
figure
[C,hh] = contour(X, Y, Z, values,'r', 'LineWidth',1);
clabel(C, hh, values, 'fontsize',7)
As you can see in the contour lines, all of the lines are plotted with LineWidth = 1. I would like to plot special line for the value = 0, with LineWidth = 2, how to set it? Thanks a lor for your help.
You will need to make a secondary contour plot to highlight the desired contour levels. The MathWorks has an example of this in the documentation.
For your case we'll have something like the following:
% Generate sample data
x = linspace(-2*pi,2*pi);
y = linspace(0,4*pi);
[X,Y] = meshgrid(x,y);
Z = sin(X)+cos(Y);
values = -10:0.5:10;
% Generate initial contour plot
figure
[C,hh] = contour(X, Y, Z, values,'r', 'LineWidth',1);
clabel(C, hh, values, 'fontsize',7)
% Generate second contour plot with desired contour level highlighted
hold on
contour(X, Y, Z, [0 0], 'b', 'LineWidth', 2);
hold off
Which returns the following:
Not that I've specified the single contour level as a vector. This is explained by the documentation for contour:
contour(Z,v) draws a contour plot of matrix Z with contour lines at the data values specified in the monotonically increasing vector v. To display a single contour line at a particular value, define v as a two-element vector with both elements equal to the desired contour level. For example, to draw contour lines at level k, use contour(Z,[k k])
If you want to highlight multiple levels then this does not apply (e.g. contour(X, Y, Z, [-1 0], 'b', 'LineWidth', 2) to highlight -1 and 0)

Plot Multiple Points Simultaneously

Let me start by saying that I suspect this is a very simple solution that I am somehow barely missing.
I'm trying to write a script that will plot one set of data in four separate subplots (each showing a different view of a 3D shape the points are being plot in), but I only want to show the current points - as in, I don't want to see every point, just one set of points as they progresses with time (I'm capturing video of the plot to visualize movement with time). However, for every instant in time, there are n points to plot simultaneously. I know this should be simple, but I can't manage to get all n points to plot at once - I can only seem to get it to plot one point at a time, which is pretty meaningless when you have n markers moving with time, all of which you'd like to see moving at the same time.
The following code works to plot every point in sequence, but does not plot all n points together, refreshing those points for every t:
n = 0;
for i = 1:length(data)
% every marker occurs in one row of a specific set of data, and is split
% into x, y, z, so I correct here for each marker being every 3rd column
for j = 1:(cind/3) % cycle through every marker
x = markerLoc(i, j*3 - 2);
y = markerLoc(i, j*3 - 1);
z = markerLoc(i, j*3);
if j == 1 && i == 1 % set up the initial plots for each subplot
% s1,2,3,4 are the handles for the subplots
h1 = scatter3(s1,x, y, z, 'MarkerFaceColor', [0 .75 .75],...
'MarkerEdgeColor','k');
h2 = scatter3(s2,x, y, z, 'MarkerFaceColor', [0 .75 .75],...
'MarkerEdgeColor','k');
h3 = scatter3(s3,x, y, z, 'MarkerFaceColor', [0 .75 .75],...
'MarkerEdgeColor','k');
h4 = scatter3(s4,x, y, z, 'MarkerFaceColor', [0 .75 .75],...
'MarkerEdgeColor','k');
else % update data
% this is probably insanely redundant
set(h1, 'XData', x, 'YData', y, 'ZData', z);
set(h2, 'XData', x, 'YData', y, 'ZData', z);
set(h3, 'XData', x, 'YData', y, 'ZData', z);
set(h4, 'XData', x, 'YData', y, 'ZData', z);
end
end
frames(n) = getframe(gcf); % capture frames
n = n + 1;
end
Can anyone help find what I need to change here to make it plot, instead of after every j (individual marker), after ever nth j?
As it is, you are currently only updating the XData, YData, and ZData for one marker at each instant at a time. Instead you want to get rid of the inner loop and get an array of x, y, and z variables. You can then use these for the scatter3 calls as well as to update the XData, YData, and ZData.
for i = 1:length(data)
%// Get XYZ coordinates for all markers at this time and reshape so X,Y,Z are rows
xyz = reshape(markerLoc(i,:), 3, []);
if i == 1
%// Put these in an array so we can update them easier
h(1) = scatter3(s1, xyz(1,:), xyz(2,:), xyz(3,:), ...
'MarkerFaceColor', [0 .75 .75],...
'MarkerEdgeColor','k');
%// Just use copyobj to make a copy of this plot to all axes
h(2:4) = copyobj(h(1), [s2, s3, s4]);
else
set(h, 'XData', xyz(1,:), 'YData', xyz(2,:), 'ZData', xyz(3,:))
end
end