2-d graph with two different axis showing different min and max MATLAB - matlab

I have the graph below I need to create two different x-axis. The unique part of this problem is where the min and max values need to be located. The range for is 0-100 for both, however the 100% value on the second x-axis needs to be where the 50% value is on the first. See the picture for clarification. The red is what I need to add using MATLAB.
I did a lot of looking and while it's very simple to put two different axis on one graph, I couldn't find a solution for this particular problem. I'd like this to be done in the code and not plot tools.

How about this
% dummy data
y = 1:80;
x1 = 100*sin( 4*pi*y/80 ).^2 ;
x2 = 100*cos( 5*pi*y/80).^2;
Plot the first line
figure;
line( x1, y, 'Color', 'b', 'LineWidth', 2 );
Get position and size of first plot
haxes1 = gca;
haxes1_pos = get(haxes1,'Position');
set the 100% of second plot to 50% of first ("tweaking" the width of the axis)
haxes1_pos(3) = haxes1_pos(3)/2;
haxes2 = axes('Position',haxes1_pos,'XAxisLocation','top','Color','none','XColor','r');
Plot the second line
line( x2, y, 'Color', 'k', 'LineWidth',2,'Parent',haxes2);
And this is what you get

Related

Draw error bars in Matlab

I have created an example scatter plot with five points in MATLAB as follows:
x = linspace(0,pi,5);
y = cos(x);
scatter(x,y);
In my case, the y-value of each point shall be in a predefined range defined as follows:
y_limits = {[0.9 1.1], [0.6 0.8], [-0.1 0.1], [-0.8 -0.6], [-1.1 -0.9]};
So for example, the y value of point 1 at x = 0 shall be in the range [0.9 1.1].
I would somehow like to draw five vertical boundaries nicely in the same plot perhaps by means of
five vertical lines with endpoints at the respective two limits
five filled vertical areas between the respective two limits
something else that may be more appropriate
I would like to get some suggestions or sample code of people who are more experienced than me in such kind of graphical representations.
You can do this in one line by using the errorbar function
% Your example variables
x = linspace(0,pi,5)';
y = cos(x);
y_limits = [0.9, 1.1; 0.6, 0.8; -0.1, 0.1; -0.8, -0.6; -1.1, -0.9];
% Plot
errorbar(x, y, y - y_limits(:,1), y_limits(:,2) - y, 'x');
% Format: (x, y, negative error, positive error, point style)
Result:
Edit, you can set the line properties of the plot as you call errorbar. For example, you could use larger, blue circle markers with thicker, red error bars
using:
errorbar(x, y, y - y_limits(:,1), y_limits(:,2) - y, 'o', 'MarkerSize', 2, 'MarkerFaceColor', 'b', 'MarkerEdgeColor', 'b', 'Color', 'r', 'LineWidth', 1);
Note for these images I'm using grid on to add the grid. Second result:
Creating a lines is done with the line command.
for i = 1:length(x)
line([x(i) x(i)], [y_limits{i}]);
end
Filled areas can be done with patch or fill. Some reordering of the limits is necessary so that the order given follows a path around the area to be filled. One nice trick is to use the alpha command on those filled areas to create transparency.
hold on
y_corners = reshape([y_limits{:}], 2, length(x)).'; %make an array
y_corners = [y_corners(:,1); flipud(y_corners(:,2))]; %corners follow a path around the shape
fill([x fliplr(x)], y_corners, 'blue');
alpha(0.5);

How to plot a group of subplots in fixed axes setting automatically in Matlab?

The plotting code is shown as:
figure;
snr_idx = 1:2:7;
for n = 1:4
subplot(2,2,n);
ith = snr_idx(n);
xx_cpd(:,n) = reshape(theta_est_s1(1,ith,:,1), 500,1);
yy_cpd(:,n) = reshape(theta_est_s1(2,ith,:,1), 500,1);
scatter(xx_cpd(:,n), yy_cpd(:,n), 30, 'o', 'LineWidth', 5e-5)
grid on
xlabel('\phi_1 (deg)','fontsize',12)
ylabel('\phi_2 (deg)','fontsize',12)
title(['SNR = ',num2str(SNRvec(ith)), 'dB' ])
end
Where SNRvec is a vector as: [-3 0 3 6 9 12 15].
theta_est_s1 is a four-dimensional array, the size of theta_est_s1 is 2×7×500×3.
Then the resulting figure is shown as following:
However, the contrast between each subplot is not remarkable enough. I want all the subplots have the same axis setting as the first subplot, i.e. when the first subplot is made, the axis is fixed, which is shown as:
If I use axis([60 70 110 120]) command in this example, the resulting figure is correct. Nevertheless, the range of theta_est_s1 is not fixed. When the input data is changed, the maximum and minimum of theta_est_s1 are changed a lot. Therefore I cannot merely set the axis manually in a direct way.
Is there any method to figure out this issue?
Thanks!
Here is an idea if I got your question right:
Since MATLAB automatically resizes the axis to fit with the range of the data, you can let it set the limit for the first plot only, and then in each subsequent plot retrieve the x- and y limits and assign them to every subplot.
Example with your code:
figure;
snr_idx = 1:2:7;
for n = 1:4
subplot(2,2,n);
ith = snr_idx(n);
xx_cpd(:,n) = reshape(theta_est_s1(1,ith,:,1), 500,1);
yy_cpd(:,n) = reshape(theta_est_s1(2,ith,:,1), 500,1);
scatter(xx_cpd(:,n), yy_cpd(:,n), 30, 'o', 'LineWidth', 5e-5)
%// Get the axis limits after the 1st plot
if n == 1
X_axis_lim = get(gca,'XLim')
Y_axis_lim = get(gca,'YLim')
else %// After 1st iteration, adjust limits
set(gca,'XLim',X_axis_lim);
set(gca,'YLim',Y_axis_lim);
end
grid on
xlabel('\phi_1 (deg)','fontsize',12)
ylabel('\phi_2 (deg)','fontsize',12)
title(['SNR = ',num2str(SNRvec(ith)), 'dB' ])
end

draw a line of best fit through data with shaded region for error

I have the following data:
dat = [9.3,0.6,0.4,0.7;...
3.2,1.2,0.7,1.9;...
3.9,1.8,0.7,1.9;...
1.0,7.4,5.6,10.7;...
4.7,1.0,0.5,1.3;...
2.2,2.6,1.2,2.7;...
7.2,1.0,0.5,1.1;...
1.0,4.8,7.5,10.3;...
2.7,1.8,1.7,4.0;...
8.2,0.8,0.4,0.9;...
1.0,4.9,5.7,8.2;...
12.9,1.3,0.6,1.6;...
7.7,0.8,0.5,1.3;...
5.8,0.9,0.6,1.9;...
1.1,4.5,6.2,12.1;...
1.1,4.5,2.8,4.8;...
16.4,0.3,0.3,0.5;...
10.4,0.6,0.3,0.7;...
2.2,3.1,2.2,4.6];
where the first column shows the observed values the second column shows the modeled values and the third and fourth columns show the min and max respectively.
I can plot the relationship between observed and modeled by
scatter(d(:,1),d(:,2))
Next, I would like to draw a smooth line through these points to show the relationship. How can this be done? Obviously a simple straight line would not be much use here.
Secondly, I would like to use the min and max (3rd and 4th columns respectively) to draw a shaded region around the modeled values in order to show the associated error.
I would eventually like to have something that looks like
http://www.giss.nasa.gov/research/briefs/rosenzweig_03/figure2.gif
Something like this?
%// Rename and sort your data
[x,I] = sort(dat(:,1));
y = dat(I,2);
mins = dat(I,3);
maxs = dat(I,4);
%// Assume a model of the form y = A + B/x. Solve for A and B
%// using least squares
P = [ones(size(x)) 1./x] \ y;
%// Initialize figure
figure(1), clf, hold on
set(1, 'Renderer', 'OpenGl');
%// Plot "shaded" areas
fill([x; flipud(x)], [mins; flipud(maxs)], 'y',...
'FaceAlpha', 0.2,...
'EdgeColor', 'r');
%// Plot data and fit
legendEntry(1) = plot(x, P(1) + P(2)./x, 'b',...
'LineWidth', 2);
legendEntry(2) = plot(dat(:,1), dat(:,2), 'r.',...
'Markersize', 15);

MATLAB fill area between lines

I'm trying to do something similar to what's outlined in this post:
MATLAB, Filling in the area between two sets of data, lines in one figure
but running into a roadblock. I'm trying to shade the area of a graph that represents the mean +/- standard deviation. The variable definitions are a bit complicated but it boils down to this code, and when plotted without shading, I get the screenshot below:
x = linspace(0, 100, 101)';
mean = torqueRnormMean(:,1);
meanPlusSTD = torqueRnormMean(:,1) + torqueRnormStd(:,1);
meanMinusSTD = torqueRnormMean(:,1) - torqueRnormStd(:,1);
plot(x, mean, 'k', 'LineWidth', 2)
plot(x, meanPlusSTD, 'k--')
plot(x, meanMinusSTD, 'k--')
But when I try to implement shading just on the lower half of the graph (between mean and meanMinusSTD) by adding the code below, I get a plot that looks like this:
fill( [x fliplr(x)], [mean fliplr(meanMinusSTD)], 'y', 'LineStyle','--');
It's obviously not shading the correct area of the graph, and new near-horizontal lines are being created close to 0 that are messing with the shading.
Any thoughts? I'm stumped.
You may be getting a problem with using mean as a variable, since it's also a reserved MATLAB command. Try clearing the variable space and then using a unique variable name.
As for the second problem, you want
fill( [x fliplr(x)], [meanUniqueName fliplr(meanMinusSTD)], 'y', 'LineStyle','--');
You also don't need to do this in two steps, but can do it all at once. A code snippet from a script I'm currently working on does the exact same thing and contains the lines:
avar = allan(DATA, tau);
xFill = [avar.tau1 fliplr(avar.tau1)];
yFill = [avar.sig2+avar.sig2err fliplr(avar.sig2-avar.sig2err)];
figure(2);
fill(xFill,yFill,'y','LineStyle','--')
line(avar.tau1,avar.sig2);
So I fill the area between the two error lines, and then draw the data line on top.
It turned out to be a column vs row vector issue. For some reason using the fill method above with flipud with the original column vectors doesn't work, but transposing the original variables then using fliplr does. Go figure. Here's the code in case it helps someone else:
x = linspace(0,100, 101);
mean = torqueRnormMean(:,DOF)';
meanPlusSTD = torqueRnormMean(:,DOF)' + torqueRnormStd(:,DOF)';
meanMinusSTD = torqueRnormMean(:,DOF)' - torqueRnormStd(:,DOF)';
fill( [x fliplr(x)], [meanPlusSTD fliplr(meanMinusSTD)], 'k');
alpha(.25);
plot(x, mean, 'k', 'LineWidth', 2)
plot(x, meanPlusSTD, 'k')
plot(x, meanMinusSTD, 'k')
Note that I removed the dotted line and just used thin vs. thick lines to denote standard deviation and mean. I did this because the line style was inconsistent. This code is in a loop where DOF runs from 1:9, and in some of the subplots both std curves would be dashed and in some just the top or bottom. It didn't matter enough to me to have them dashed so I kept it simple. Now this is an example of the graph I get:
One thing that you appear to be doing wrong is that you're applying fliplr to column vectors. That will have no effect. The example you cited uses row vectors. You also concatenate them into a matrix instead of into a single vector like the example. I think that the equivalent with column vectors would be:
fill( [x;flipud(x)], [mean;flipud(meanMinusSTD)], 'y');
Another possibility:
x = 1:1000; % example x values
y_upper = 5+sin(2*pi/200*x); % example upper curve
y_lower = 2+sin(2*pi/230*x); % example lower curve
bar(x, y_upper, 1, 'b', 'edgecolor', 'b');
hold on
bar(x, y_lower, 1, 'w', 'edgecolor', 'w');
axis([0 1000 0 7])
It uses bar (with unit width and same-color edges) to fill the upper curve, and then a second bar to "remove" (plot in white) the lower part.

Overlaying two axes in a Matlab plot

I am looking for a way to overlay an x-y time series, say created with 'plot', on top of a display generated by 'contourf', with different scaling on the y-axes.
It seems that the typical way to do this in the case of two x-y plots is to use the built-in function 'plotyy', which can even be driven by functions other than 'plot' (such as 'loglog') as long as the input arguments remain the same (x,y). However, since in my case contourf requires three input arguments, 'plotyy' seems to not be applicable. Here is some sample code describing what I would like to do:
x1 = 1:1:50;
y1 = 1:1:10;
temp_data = rand(10,50);
y2 = rand(50,1)*20;
figure; hold on;
contourf(x1,y1,temp_data);
colormap('gray');
plot(x1,y2,'r-');
Ideally, I would like the timeseries (x1,y2) to have its own y-axes displayed on the right, and be scaled to the same vertical extent as the contourf plot.
Thanks for your time.
I don't think there's a "clean" way to do this, but you can fake it by overlaying two axes over each other.
x1 = 1:1:50;
y1 = 1:1:10;
temp_data = rand(10,50);
y2 = rand(50,1)*20;
figure;
contourf(x1, y1, temp_data);
colormap('gray');
h_ax = gca;
h_ax_line = axes('position', get(h_ax, 'position')); % Create a new axes in the same position as the first one, overlaid on top
plot(x1,y2,'r-');
set(h_ax_line, 'YAxisLocation', 'right', 'xlim', get(h_ax, 'xlim'), 'color', 'none'); % Put the new axes' y labels on the right, set the x limits the same as the original axes', and make the background transparent
ylabel(h_ax, 'Contour y-values');
ylabel(h_ax_line, 'Line y-values');
In fact, this "plot overlay" is almost definitely what the plotyy function does internally.
Here's example output (I increased the font size for legibility):