Plot many horizontal Bar Plots in the same graph - matlab

I need to plot a x-y function, that shows the histograms at x-values. Something similar to the bottom plot of the next figure:
I tried to use matlab's "barh", but can't plot many in the same figure.
Any ideas?
Or, maybe displacing the origin (baseline, basevalue in barseries properties) of successive plots would work. How could I do that for barh?
thanks.

Using 'Position' of axes property
% generate "data"
m = rand( 40,10 );
[n x] = hist( m, 50 );
% the actual plotting
figure;
ma = axes('Position',[.1 .1 .8 .8] ); % "parent" axes
N = size(n,2); % number of vertical bars
for ii=1:N,
% create an axes inside the parent axes for the ii-the barh
sa = axes('Position', [0.1+(ii-1)*.8/N, 0.1, .8/N, .8]); % position the ii-th barh
barh( x, n(:,ii), 'Parent', sa);
axis off;
end

Related

Set legend over colorbar in matlab

I'd like to have the legend (of some contours) over the colorbar of a surf plot.
How can I have a layout similar to the image in a figure plot?
From the black
colorbar;
legend('label1','label2','Location','northeastoutside');
to the red one?
You can manually change the position of both the colorbar and the legend
% Make a demo plot
figure(); hold on
plot( rand(20,3) ); % lines for the legend
peaks(10); % surface for the colorbar
view(3); % 3D view
% Create a legend and colorbar, retain their handles
L = legend( 'show', 'location', 'eastoutside' );
C = colorbar();
% Get some key variables from the current position of the colorbar/legend
% -> avg mid point of colorbar and legend
x = ( L.Position(1) + (C.Position(1)+C.Position(3)) ) / 2;
% -> Max width of the two objects
w = max( L.Position(3), C.Position(3) );
% -> A nominal y value and padding to dictate the spacing
y = 0.1;
pad = 0.05;
% Move the legend and colorbar
% First move the x/y coords of the legend to be on top, centred around common x
L.Position(1:2) = [x - L.Position(3)/2, 1 - y - L.Position(4)];
% Then move the x/y coords of the colorbar to be on the bottom, centred around common x
C.Position(1:2) = [x - C.Position(3)/2, y];
% Then resize the colorbar to use the vertical space not utilised by the legend
C.Position(4) = L.Position(2) - pad - y;
% By moving the legend/colorbar the axes will have "popped" to use the full width
% Need to move it to span between the current left edge and the newly moved leg/colorbar
ax = gca();
ax.Units = 'Norm';
ax.Position(3) = (x-w/2) - pad - ax.Position(1) ;
Result:
You can do this interactively by clicking the "Cursor" icon in the top of the plot window and adjusting the legend/colorbar. Once you have finished editing choose "Generate Code" in the "File" menu of the plot window to have code generated so you can repeatedly create the plot.

hist3 plot with additional z axis

The following code creates a 2D stacked histogram for two 2D distributions:
%%first dataset
x1 = 200 + 300.*rand(1000,1)'; %rand values between 0 and 200
y1 = 100 + 250.*rand(1000,1)'; %rand values between 100 and 500
%%secnd dataset
x2 = 100 + 200.*rand(1000,1)'; %rand values between 0 and 200
y2 = 200 + 400.*rand(1000,1)'; %rand values between 100 and 500
one = linspace(100,400,20);
two = linspace(100,500,20);
EDGES = {one, two}; %edges
[n1,c1] = hist3([x1' y1'],'Edges',EDGES);%first dataset
[n2,c2] = hist3([x2' y2'],'Edges',EDGES);%second dataset
figure('Color','w');
% plot the first data set
bh=bar3(n1);
% Loop through each row and shift bars upwards
for ii=1:length(bh)
zz = get(bh(ii),'Zdata');
kk = 1;
% Bars are defined by 6 faces(?), adding values from data2 will
% shift the bars upwards accordingly, I'm sure this could be made
% better!
for jj = 0:6:(6*length(bh)-6)
zz(jj+1:jj+6,:)=zz(jj+1:jj+6,:)+n2(kk,ii);
kk=kk+1;
end
%erase zero height bars
%# get the ZData matrix of the current group
Z = get(bh(ii), 'ZData');
%# row-indices of Z matrix. Columns correspond to each rectangular bar
rowsInd = reshape(1:size(Z,1), 6,[]);
%# find bars with zero height
barsIdx = all([Z(2:6:end,2:3) Z(3:6:end,2:3)]==0, 2);
%# replace their values with NaN for those bars
Z(rowsInd(:,barsIdx),:) = NaN;
%# update the ZData
set(bh(ii), 'ZData',Z)
end
% Set face colour to blue for data1
set(bh,'FaceColor',[0 0 1]);
% Apply hold so that data2 can be plotted
hold on;
% Plot data2
bh=bar3(n2);
%erase zero height bars
for ii=1:numel(bh)
%# get the ZData matrix of the current group
Z = get(bh(ii), 'ZData');
%# row-indices of Z matrix. Columns correspond to each rectangular bar
rowsInd = reshape(1:size(Z,1), 6,[]);
%# find bars with zero height
barsIdx = all([Z(2:6:end,2:3) Z(3:6:end,2:3)]==0, 2);
%# replace their values with NaN for those bars
Z(rowsInd(:,barsIdx),:) = NaN;
%# update the ZData
set(bh(ii), 'ZData',Z)
end
% Set face color to red
set(bh,'FaceColor',[1 0 0]);
%set ticks
set(gca,'XTick',1:6:numel(one),'XTickLabel',one(1:6:end))
set(gca,'YTick',1:6:numel(one),'YTickLabel',one(1:6:end))
view(20,40)
%labels
xlabel('x')
ylabel('y')
zlabel('z')
%set transparency
set(gcf,'renderer','opengl');
set(get(gca,'child'),'FaceAlpha',0.8);
set(get(gca,'child'),'EdgeAlpha',0.3);
A first issue is the transparency (but I think it is a problem of my matlab version 2014a, so I am not bothered by that). It just makes all blurry.
My question is how to add a mesh plot on the same picture. The code creating the meshes is the following:
%create surface I want to plot
[X,Y] = meshgrid(one,two);
inds1=find(X(:).*Y(:)<.3e5);%condition
inds2=find(X(:).*Y(:)>.3e5);
I=Y./X.^2;%first surface
I(inds1)=NaN;%second surface
figure('Color','w');hold on
mesh(X,Y,I,'FaceColor',[0 0 1],'EdgeColor','none')
I(:,:)=NaN;
I(inds1)=Y(inds1)./X(inds1);%second surface
mesh(X,Y,I,'FaceColor',[1 0 0],'EdgeColor','none')
alpha(.5)
grid on
view(20,40)
%labels
xlabel('x')
ylabel('y')
zlabel('z')
The domain of the histograms and the meshes are the same. So I just need to add an extra z-axis on the first figure.
I tried substituting figure('Color','w');hold on in the second code with AxesH = axes('NextPlot', 'add');, but I was really wrong about that:
That just overlayed the two figures..
I also tried something along the lines of:
%add axis
axesPosition = get(gca,'Position'); %# Get the current axes position
hNewAxes = axes('Position',axesPosition,... %# Place a new axes on top...
'Color','none',... %# ... with no background color
'ZLim',[0 400],... %# ... and a different scale
'ZAxisLocation','right',... %# ... located on the right
'XTick',[],... %# ... with no x tick marks
'YTick',[],... %# ... with no y tick marks
'Box','off');
but it is not feasible because the property ZAxisLocation does not exist.
Does anyone know how to add the z-axis?
Also, if you have other comments on how to ameliorate the code, they're welcome!
acknowledgements
2d stacked histogram:https://stackoverflow.com/a/17477348/3751931
erasing the zero values in the hist plot: https://stackoverflow.com/a/17477348/3751931
I now think that this is not yet possible (http://www.mathworks.com/matlabcentral/answers/95949-is-there-a-function-to-include-two-3-d-plots-with-different-z-axes-on-the-same-plot-area-similar-to).
So I just added a fake axis:
[X,Y] = meshgrid(one,two);
inds1=find(X(:).*Y(:)<.3e5);%condition
inds2=find(X(:).*Y(:)>.3e5);
s=Y./X.^2;%first surface
s(inds1)=NaN;%second surface
%mesh(X,Y,I,'FaceColor',[0 0 1],'EdgeColor','none')
mesh((X-min(min(X)))/max(max(X-min(min(X))))*20,(Y-min(min(Y)))/max(max(Y-min(min(Y))))*20,...
s/max(max(s))*max(max(n1))+max(max(n1)),'FaceColor','g','EdgeColor','none','facealpha',.5)
s(:,:)=NaN;
s(inds1)=Y(inds1)./X(inds1);%second surface
%mesh(X,Y,I,'FaceColor',[1 0 0],'EdgeColor','none')
mesh((X-min(min(X)))/max(max(X-min(min(X))))*20,(Y-min(min(Y)))/max(max(Y-min(min(Y))))*20,...
s/max(max(s))*max(max(n1))+max(max(n1)),'FaceColor','y','EdgeColor','none','facealpha',.5)
alpha(.5)
grid on
%add fake z axis
line([20 20],[1 1],[max(max(n1))-min(min(s)) 20],...
'color','g','linewidth',2)
% text(20*ones(1,5),zeros(1,5),linspace(max(max(n1))-min(min(I)),20,5),...
% num2str(linspace(0,max(max(I)),5)),'color','g')
z=linspace(max(max(n1))-min(min(s)),20,5);
txto=linspace(0,max(max(s)),5);
for ii=1:5
line([20 20.3],[1 1],[z(ii) z(ii)],'color','g')%ticks
text(20,0,z(ii),num2str(txto(ii)),'color','g')%ticklabel
end
text(19.8,1,21,'s','color','g')%label
Over all the code is quite ugly and needs a lot of tuning..

Add surface/line to 3D stem plot in Matlab

Say I have a 3D stem plot using stem3
stem3(xx,yy,zz,'red')
I want to add a line or a semitransparent surface to a height of 550 (zz = 550). is there a way to do this?
You can do this with just a normal surf object.
% Create your stem3 object
stem3(rand(10), rand(10), rand(10) * 700, 'r');
hold on
% Get the current X and Y Limits of the axes
xdata = get(gca, 'xlim');
ydata = get(gca, 'ylim');
% Ensure that the axes limimts don't change when we plot the surface
axis manual
% Create a surface that spans the axes and is of height 550 (the third input)
% Use alpha value of 0.1 for the face transparency
surf(xdata, ydata, 550 * ones(2), 'FaceAlpha', 0.1, 'FaceColor', 'red');

Zoom region within a plot in Matlab

I'm using Matlab to produce figures, and I'm wondering if there is a way to plot a zoomed region in a figure of the overall data?
I have scatter data plotted over one week, with the x-axis in hours, and I want to zoom into the first 3 hours, and display them within the main figure with the x-axis label of minutes.
The plotting code I have so far is as follows:
allvalsx = marabint(:,2)
allvalsy = marabint(:,5)
subvalsx = marabint(1:7,2);
subvalsy = marabint(1:7,2);
%% Plots the scatter chart.
sizemarker = 135
handle = scatter(allvalsx, allvalsy, sizemarker, '.')
figure(1)
axes('Position',[.2 .2 .2 .2])
handle2 = scatter(subvalsx, subvalsy, '.r')
title(plotTitle)
xlabel('Time since treatment (hours)')
ylabel('Contact angle (deg)')
% Axis scales x1, x2, y1, y2
axis([0, marabint(length(marabint),2) + 10, 0, 120]);
% This adds a red horizontal line indicating the untreated angle of the
% sample.
untreatedLine = line('XData', [0 marabint(length(marabint),2) + 10], 'YData', [untreatedAngle untreatedAngle], 'LineStyle', '-', ...
'LineWidth', 1, 'Color','r');
% Adding a legend to the graph
legendInfo = horzcat('Untreated angle of ', untreatedString)
hleg1 = legend(untreatedLine, legendInfo);
% This encases the plot in a box
a = gca;
% set box property to off and remove background color
set(a,'box','off','color','none')
% create new, empty axes with box but without ticks
b = axes('Position',get(a,'Position'),'box','on','xtick',[],'ytick',[]);
% set original axes as active
axes(a)
% link axes in case of zooming
linkaxes([a b])
set(gcf,'PaperUnits','inches');
set(gcf,'PaperSize', [8.267 5.25]);
set(gcf,'PaperPosition',[0 0.2625 8.267 4.75]);
set(gcf,'PaperPositionMode','Manual');
set(handle,'Marker','.');
print(gcf, '-dpdf', '-r150', horzcat('markertest4.pdf'));
This produces the following
Can anyone help me out with this?
yeah, I think I know what you need. Try this:
zoomStart = 0;
zoomStop = 3;
set(gca, 'XLim', [zoomStart zoomStop])
Let me know if that doesn't do what you need, and I'll give you a different way.

Plot outside axis in Matlab

How to plot something outside the axis with MATLAB? I had like to plot something similar to this figure;
Thank you.
Here is one possible trick by using two axes:
%# plot data as usual
x = randn(1000,1);
[count bin] = hist(x,50);
figure, bar(bin,count,'hist')
hAx1 = gca;
%# create a second axis as copy of first (without its content),
%# reduce its size, and set limits accordingly
hAx2 = copyobj(hAx1,gcf);
set(hAx2, 'Position',get(hAx1,'Position').*[1 1 1 0.9], ...
'XLimMode','manual', 'YLimMode','manual', ...
'YLim',get(hAx1,'YLim').*[1 0.9])
delete(get(hAx2,'Children'))
%# hide first axis, and adjust Z-order
axis(hAx1,'off')
uistack(hAx1,'top')
%# add title and labels
title(hAx2,'Title')
xlabel(hAx2, 'Frequency'), ylabel(hAx2, 'Mag')
and here is the plot before and after:
You can display one axis with the scale you want, then plot your data on another axis which is invisible and large enough to hold the data you need:
f = figure;
% some fake data
x = 0:20;
y = 23-x;
a_max = 20;
b_max = 23;
a_height = .7;
%% axes you'll see
a = axes('Position', [.1 .1 .8 a_height]);
xlim([0 20]);
ylim([0 20]);
%% axes you'll use
scale = b_max/a_max;
a2 = axes('Position', [.1 .1 .8 scale*a_height]);
p = plot(x, y);
xlim([0 20]);
ylim([0 b_max]);
set(a2, 'Color', 'none', 'Visible', 'off');
I had similar problem and I've solved it thanks to this answer. In case of bar series the code is as follows:
[a,b] = hist(randn(1000,1)); % generate random data and histogram
h = bar(b,a); % plot bar series
ylim([0 70]) % set limits
set(get(h,'children'),'clipping','off')% turn off clippings