MATLAB: Scatterplot - points with different shapes according to position - matlab

The properties of my figure I want to build are the following:
The figure shows 200 points. The points above the diagonal should be shown with red stars and the one below the diagonal, with blue triangles.
This is what I've managed to do so far
x=[0 1];
y=[0 1];
line(x,y, 'linewidth', 1);
hggroup = scatter(rand(100,1),rand(100,1));
axis tight;
axis square;
title('Scatterplot')
Could you help me with that? Thanks in advance.

How about this:
line([0 1],[0 1], 'linewidth', 1);
hold on
x = rand(100,1);
y = rand(100,1);
idx = y>x;
scatter(x(idx),y(idx),'r*');
scatter(x(~idx),y(~idx),'b^');
axis tight;
axis square;
title('Scatterplot')

Related

Smoothing/interpolation of a 3D surface colormap

I'm trying to smooth or interpolate away the "steps" building up to a intensity maximum, and at the same time preserving the shape of the surface so that the estimated width does not get shifted or changed. I have tried interpolating to a higher resolution using 2D spline, but the "steps" are still present and the estimated maxima region changes. Could someone please help me in smoothing/interpolating away those steps to make the surface look more continuous while conserving the surface shape?
As always, many thanks in advance for any advice or help!!
Uninterpolated
Interpolated
Attempt
conversion = 1/49.0196; % in mm/pixel
new_xData = linspace(xData(1), xData(end), 10*length(xData));
new_yData = linspace(yData(1), yData(end), 10*length(yData)).';
new_zData = interp2(xData, yData, zData, new_xData, new_yData, 'spline');
xData = new_xData; yData = new_yData; zData = new_zData;
h = figure();
surf(xData, yData, zData, 'LineStyle', 'none', 'FaceColor', 'interp');
xlim([xData(1) xData(end)])
ylim([yData(1) yData(end)])
zlim([0 ceil(max(zData(:)))]);
colormap(jet(4096))
xlabel('mm'); ylabel('mm'); zlabel('ln(Intensity)');
set(gca,'Ydir', 'reverse')
grid on
shading interp
view(3); axis vis3d; camlight;
% Change x and y tick labels from pixels to mm
addMM = #(x) sprintf('%.1f', x * conversion);
xticklabels(cellfun(addMM,num2cell(xticks'),'UniformOutput',false));
yticklabels(cellfun(addMM,num2cell(yticks'),'UniformOutput',false));
% Find maxium intensity region and plot it
hold on
maxValue = max(zData(:));
[rowsOfMaxes, colsOfMaxes] = find(zData == maxValue);
x_minind = min(colsOfMaxes(:));
x_maxind = max(colsOfMaxes(:));
p = zeros(1, 2);
p(1) = plot3(linspace(xData(x_minind), xData(x_minind), ...
length(yData)), yData, zData(:, x_minind), 'Linestyle', '-.', ...
'Color', 'black', 'LineWidth', 2.0);
p(2) = plot3(linspace(xData(x_maxind), xData(x_maxind), ...
length(yData)), yData, zData(:, x_maxind), 'Linestyle', '-.', ...
'Color', 'black', 'LineWidth', 2.0);
hold off
legend(p(1), 'Estimated width of maximum intensity', 'Location', 'North')
set(gca, 'FontSize', 14)

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:

Additional axis on 3D surface in MATLAB

Suppose I plot a 3d graph using
[X,Y,Z] = peaks(25);
figure
surf(X,Y,Z);
How can I add addtional x and y axis with labels to the z=0 plane like the red ones shown in this picture? I would like to keep the original axis as is.
I would just draw my own fake axis. I'm not sure there is a better solution, but this one works.
[X,Y,Z] = peaks(25);
figure
surf(X,Y,Z);
hold on;
%define the plot limits
xlim_arr = [-4 4];
ylim_arr = [-5 5];
zlim_arr = [-10 10];
%fix the limits of the real axes
xlim(xlim_arr);
ylim(ylim_arr);
zlim(zlim_arr);
%add grid and labels through all x-points
for i=xlim_arr(1):xlim_arr(2)
plot3([i i],[ylim_arr(1) ylim_arr(2)], [0 0], 'Color', [0.7 0.7 0.7], 'LineWidth',0.4);
text(i, ylim_arr(1)-0.4, 0, num2str(i));
text(i, ylim_arr(2)+0.4, 0, num2str(i));
end
%add grid and labels through all y-points
for i=ylim_arr(1):ylim_arr(2)
plot3([xlim_arr(1) xlim_arr(2)], [i i], [0 0], 'Color', [0.7 0.7 0.7], 'LineWidth',0.4);
text(xlim_arr(1)-0.4, i, 0, num2str(i));
text(xlim_arr(2)+0.4, i, 0, num2str(i));
end
%add the bold frame to highlight the fake axes
px = [xlim_arr(1) xlim_arr(1) xlim_arr(2) xlim_arr(2) xlim_arr(1)];
py = [ylim_arr(1) ylim_arr(2) ylim_arr(2) ylim_arr(1) ylim_arr(1)];
pz = [0 0 0 0 0];
plot3(px,py,pz, 'k', 'LineWidth', 0.5);

Colorbar height is too large and overlapping figure title

I have a three-dimensional density distribution and create a figure with two subplots. One of the XY plane and one of the YZ plane. For both figures I want a correct colorbar and for some reason the XY plane colorbar is perfect and the YZ plane colorbar is too big and overlaps the figure title. See below for my code and an image of result. EDIT: added functioning example at bottom
%// Data slice in the XY plane
subplot(1,2,1)
h=slice(xi,yi,zi,density,[],[],0);
set(h,'edgecolor','none');
caxis([-8,-2])
colormap(jet);
c = colorbar;
c.Label.String = 'Density in log 10 scale';
view(2)
daspect([1 1 1])
xlabel('X-axis [km]')
ylabel('Y-axis [km]')
zlabel('Z-axis [km]')
title_orbit = ['Mg sputtering in orbital plane at orbit angle ',is];
title({title_orbit,''})
%// Data slice in the YZ plane
subplot(1,2,2)
g=slice(xi,yi,zi,density,0,[],[]);
set(g,'edgecolor','none');
caxis([-8,-2])
colormap(jet);
d = colorbar;
d.Label.String = 'Density in log 10 scale';
view(90,0)
daspect([1 1 1])
xlabel('X-axis [km]')
ylabel('Y-axis [km]')
zlabel('Z-axis [km]')
title_perp = ['Mg sputtering in perpendicular plane at orbit angle ',is];
title({title_perp,''})
For those who want a working example for trying to fix it, see code below.
% Create data with similar structure as original
x = linspace(-100,100,100);
y = linspace(-100,100,100);
z = linspace(-100,100,100);
[xg,yg,zg] = meshgrid(x,y,z);
density = rand([100,100,100]);
% Plot data
figure
subplot(1,2,1)
h=slice(xg,yg,zg,density,[],[],0);
set(h,'edgecolor','none');
colormap(jet);
c = colorbar;
view(2)
daspect([1 1 1])
subplot(1,2,2)
g=slice(xg,yg,zg,density,0,[],[]);
set(g,'edgecolor','none');
colormap(jet);
c = colorbar;
view(90,0)
daspect([1 1 1])
here's a possible workaround, first get the color data from each slice, then use imagesc or imshowto plot that slice data. Using your example:
h=slice(xg,yg,zg,density,0,[],[]);
H=get(h,'CData');
...
g=slice(xg,yg,zg,density,0,[],[]);
G=get(g,'CData');
...
Then open a new figure and use imagesc or imshow:
figure;
subplot(1,2,1)
imshow(H); colormap(jet); colorbar
subplot(1,2,2)
imshow(G); colormap(jet); colorbar

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