I have a 3D big matrix of size 2001 , 2001 , 30. I want to show its 30 slices in a 3D plot. I try to do it using matlab 'slice' command. However, since 'slice' needs to get the X Y Z locations as 3D arrays from the 'meshgrid' command, I get an 'out of memory error'.
My code is presented below.
How can I get over the 'Out of Memory' error without having to shrink
my 3D matrix, and with using my x,y,z locations of the matrix data ??
function presentFig4_ver4
close all; clc;
%im3 is of size of im3 = 201 201 30
load('img3D_shrinked.mat' , 'im3' , 'y_n_mm' , 'x_n_mm')
% next code until the mesh grid is in order to have the axes arranged
% so that the slices are shown one after the other in the depth
% direction of the figure and not from the bottom of the figure to the top of the figure
x_len=length(x_n_mm);
y_len=length(y_n_mm);
im3_reshaped=zeros(y_len , x_len , y_len);
for (ind_slice=1:30)
im3_reshaped(:,ind_slice,:)=im3(:,:,ind_slice);
end
[X,Y,Z]=meshgrid(x_n_mm,y_n_mm,y_n_mm);
slices=x_n_mm %= 0.23:0.1:(0.23+((30-1)*0.1)); %This is the same as x_n_mm
shownSlices=[1:30];
h=slice(X,Y,Z, im3_reshaped, [slices(shownSlices)],[],[]);
set(h,'EdgeColor','none','FaceColor','interp');
set( h , 'FaceAlpha', 'interp','AlphaData',im3*10^3)
dcm_obj = datacursormode(gcf); %datacursor mode on
set(dcm_obj,'enable','on','updatefcn',{#updateMe X Y Z im3_reshaped}) %update, need X,Y,Z, im3-values
set(gca,'FontName', 'Arial' ,'FontSize',14)
set(gca,'Position',[.32 .19 .41 0.9]) % [horizontal distance, vertical distance, width, height]
hold on
%camproj perspective
c_h=colorbar('horiz');
set( c_h, 'XDir', 'reverse' , 'Position' , [0.2 0.2 0.7 0.04],'FontSize',12);
opengl software
daspect([ 1 10 10])
axis tight
view(-49,16)
maxAxisLim=2; %mm
ylim([-maxAxisLim maxAxisLim])
zlim([-maxAxisLim maxAxisLim])
xlim([0.23 3.13])
camzoom(2)
xlabel('X [mm]','FontName', 'Arial' , 'FontSize',14)
ylabel('Y[mm]','FontName', 'Arial' ,'FontSize',14)
zlabel('Z [mm]','FontName', 'Arial' , 'FontSize',14)
x_h=get(gca,'XLabel');
y_h=get(gca,'YLabel');
z_h=get(gca,'ZLabel');
set(y_h, 'Units','normalized','Position', [0.03 -0.08 ] );
set(x_h, 'Units','normalized','Position', [0.6 0.12] );
set(z_h, 'Units','normalized','Position', [-0.08 0.27] );
set(get(gca,'YLabel'),'Rotation',-20);
set(get(gca,'XLabel'),'Rotation',12);
set(gca,'XTick',[0.23 0.5:0.5:3 3.13])
set(gca,'XTickLabel',{'0.23' '0.5' '1' '1.5' '2' '2.5' '3' '3.1' })
end % of presentFig4_ver4 function
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function msg = updateMe(src,evt,X,Y,Z,f)
evt = get(evt); %what's happenin'?
pos = evt.Position; %position
fval = f(X==pos(1)&Y==pos(2)&Z==pos(3)); %where?
msg = num2str(fval); %create msg
end
Related
I am trying to format my graph so that the border ends at the max x and max y so there is not extra space between them and the border. Also, I'm trying to completely replace my first plot command with my second one. Should I just delete my first plot? Currently, the second plot goes over my first plot, removing most of my formatting.
clear all, close all
%%command to clear all variables and log history
x = linspace(-pi, pi, 200);
%creating x variable between - pi and 200 with pi distance between each
%value
y = sin(x) + cos(x);
%Creating y varable with the help of x
figure
plot(x,y)
title('2-D Plot')
xlabel('Theta (in radians)')
ylabel('Function Y')
xlim([-pi pi])
ylim([-1.414 1.414])
grid
plot(x,y,'r--')
grid
To fit the axes box tightly around the data without manually adjusting the axis limits, use:
axis tight;
and instead of re-plotting, you can update the relevant properties of the line.
x = linspace(-pi, pi, 200);
y = sin(x) + cos(x);
figure;
h = plot(x,y); %handle for the line plot
title('2-D Plot');
xlabel('Theta (in radians)');
ylabel('Function Y');
grid;
axis tight; %to set the axis limits equal to the range of the data
set(h, 'LineStyle', '--', 'Color', 'r'); %Updating the plot with required changes
Here are the coordinates that I am planning to plot, filename is Coords:
x y
0.0110 0.1105
-0.2730 0.2559
0.3610 0.1528
-0.0077 -0.2520
-0.2412 -0.1979
0.0444 -0.0526
0.0543 -0.0076
-0.1710 0.1170
0.12741 -0.0448
0.0949 -0.0811
Here is my code that plots the scatter graph first:
Hold on
%Plot Coordinate
For i=1:10
dot_size = 100;
scatter ( Coords(i,1) ,Coords(i,2), dot_size, 'filled', 'MarkerEdgeColor', 'k' );
end
%Draw line distance between each points
for i=1:10
for j=1:10
plot( [Coords(i,1) Coords(i,2)], [Coords(j,1) Coords(j,2)] );
end
end
Hold off
%Sets the size of the y and x axis
xlim( [ min( Coords(:,1)) max( Coords(:,1)) ] );
ylim( [ min( Coords(:,2)) max( Coords(:,2)) ] );
axis off;
Here is the result I get:
I don't know why the lines are being drawn everywhere. I also notice that even when plot(x,y) = 0, the line is still being drawn.
I also would like to change the thickness and opacity of the line depending on the distance between the two points: E.g. thicker and darker line for short distance between points. And thinner /lighter line if the distance between two points are long.
I want my plot to look something like this:
The reason your lines do not match the scattered points is the coordinates you give to plot; The coordinates are in wrong order and therefore they do not define the lines correctly.
I modified your code to correct this issue. I replaced plot with line, but you can also do the same with plot. In addition, I defined the anonymous functions f and g to define the color and thickness of each line based on distance of the two ends, d. You can modify these functionalities to get different graphical behaviors.
n = 10; % number of points
dot_size = 100;
Coords = rand(n, 2);
% maximum possible length in your coordination plane:
L = norm([max(Coords(:,1))-min(Coords(:,1)),max(Coords(:,2))-min(Coords(:,2))]);
% this function defines the line width:
f = #(x) L / (x + 0.1); % 0.1 avoids huge line widths in very small distances
% this function defines the color:
g = #(x) x * [1 1 1] / L;
figure
hold on
for ii = 1:n-1
for jj = ii+1:n
d = norm([Coords(ii,1)-Coords(jj,1), Coords(ii,2)-Coords(jj,2)]);
line([Coords(ii,1) Coords(jj,1)], [Coords(ii,2) Coords(jj,2)], ...
'LineWidth', f(d), 'Color', g(d));
end
end
scatter (Coords(:,1), Coords(:,2), dot_size, 'filled', 'MarkerEdgeColor', 'k');
axis tight
axis off
With this output:
Notes:
axis tight is a command that sets the limits to the tightest possible. It is equivalent to your xlim( [ min( Coords(:,1)) max( Coords(:,1)) ] ); and the next line.
In the for-loops you should try to avoid choosing one pair of points twice or same point as both sides of a line.
For scattering you do not need a loop. It could all be done at once.
I brought scatter after plotting the lines, so the circles are drawn on top.
There is also a specialized MATLAB function for generating plots like this: gplot.
data = [
0.0110 0.1105
-0.2730 0.2559
0.3610 0.1528
-0.0077 -0.2520
-0.2412 -0.1979
0.0444 -0.0526
0.0543 -0.0076
-0.1710 0.1170
0.12741 -0.0448
0.0949 -0.0811]; % Coordinates
adjM = squareform(pdist(data)); %
adjM (adjM > 0) = 1; % Form adjacency matrix based on Euclidean distances
figure; gplot(adjM, data, '-o') % Plot figure based on coordinates and adjacency matrix
Then, customize to your liking, e.g. if you want to change marker type, remove the axis, add labels etc.
I have a problem when printing a 2D plot to pdf in matlab. I'm trying to print the following plot to a file (pdf, eps, svg, doesn't matter):
The problem is that at some points the line is very "jiggly" (sorry for the lack of a better word). I zoomed in on the upper part so you can see what I mean:
This is obviously not a problem for the matlab figure window. But when I print it to pdf, this is what it looks like:
The result is identical for pdf, svg and eps. I guess the problem is that matlab is creating a vectorized path (that is good!) but the path line is too thick and then every little spike can be seen.
Here's the code I'm using to produce the pdf:
sTitle = 'trajectory';
sFile = 'Data/trajectory.mat';
sPdfFile = 'pdfs/trajectory.pdf';
linewidth = 1;
fontsize1 = 18;
fig = figure;
% Adjust figure window size
set(fig, 'Position', [100 100 1400 800]);
% Set title
title(sTitle);
% Get states
[s, t] = load_data(some_data);
% Draw trajectory
plot(s(1,:), s(2,:), 'linewidth', linewidth);
% Labels and stuff
xlabel('x^W [m]', 'fontsize', fontsize1);
ylabel('y^W [m]', 'fontsize', fontsize1);
set(gca, 'fontsize', fontsize1)
% Axis font
set( gca , ...
'FontName' , 'Helvetica' );
set(gca, ...
'Box' , 'on' , ...
'TickDir' , 'out' , ...
'TickLength' , [.02 .02] , ...
'XMinorTick' , 'on' , ...
'XGrid' , 'on' , ...
'XMinorGrid' , 'off' , ...
'YMinorTick' , 'on' , ...
'YGrid' , 'on' , ...
'XColor' , [.3 .3 .3], ...
'YColor' , [.3 .3 .3], ...
'XTick' , -5:1:5, ...
'XTickLabelMode', 'auto', ...
'YTick' , -5:1:5, ...
'LineWidth' , 1 );
% Adjust view
axis([-2.5 2.5, -2.7 0.5]);
% Correct data aspect ratio
daspect([1,1,1])
% Print to PDF
width = 10;
height = 5;
set(gcf, 'PaperPosition', [0 0 width height]); %Position plot at left hand corner with width 5 and height 5.
set(gcf, 'PaperSize', [width height]); %Set the paper to have width 5 and height 5.
print('-dpdf', '-r600', sPdfFile);
According to this answer, this is an acknowledged bug, and the answerer provided a function to correct the issue for EPS files.
Since you are creating a PDF, I'd suggest using export_fig (requires a Ghostscript install) which, on the test script below, creates a smooth line in the produced PDF.
clc();
clear();
figure(1);
% Get states
n = 800;
x = linspace(0,2*pi,n);
s = [x.*cos(x);x.*sin(x)] + 0.3*exp(-0.3*[x;x]).*(rand(2,n)-0.5) ;
% Draw trajectory
plot(s(1,:), s(2,:), 'linewidth', 1);
axis([-20,20,-20,20]);
daspect([1,1,1])
% Print to PDF
print('traj.pdf','-dpdf', '-r600');
export_fig('traj2.pdf','-dpdf','-r600');
print PDF output:
export_fig PDF output:
I am creating a 2D plot in Matlab by calling this command: imagesc(vector1, vector2, mat_weights). Then, I run the colorbar command.
I now have a smooth 2D plot, but I want to add space between the cells. Here's how I want it to look:
How do I add such spacing between the cells/boxes?
You can add spaces between patches of color using another function than imagesc. Here, scatter provides a straightforward solution when used with option 'filled' and marker 'square'.
Note that you need to transform your 2-D matrix into a vector, but you don't have to scale your data: scatter takes the min and max values from your data and assign them to the min and max colors of the colormap.
The code
% 2-D in 1-D:
Z = diag(1:10); %example of 2-D matrix to be plotted
C = reshape(Z,1,[]); %1-D transform for vector color
% input definition
sz_matrix = 10;
X = repmat( (1:sz_matrix), 1, sz_matrix);
Y = kron(1:sz_matrix,ones(1,sz_matrix));
S = 1000; % size of marker (handle spaces between patches)
%C = (X.^2 + Y.^2); % second color scheme
%plot
figure('Color', 'w', 'position', [10 10 600 400]);
scatter(X, Y, S, C, 'fill', 's');
set(gca, 'XLim', [0 11], 'YLim', [0 11]);
axis square;
colormap summer
colorbar
will give
EDIT
Here is a piece of code for a rectangular matrix. Please note the inversion of the Y axis direction so that the graphical representation matches disp(Z). To have similar (x,y) proportion in the white area separating color patches, one may try to resize manually the figure.
Z = diag(1:10); %example of 2-D matrix to be plotted
Z = Z(1:end-2,:); %trim for rectangular
% input definition
X = repmat(1:size(Z,2), 1, size(Z,1));
Y = kron(1:size(Z,1),ones(1,size(Z,2)));
C = reshape(Z',1,[]); %1-D transform for vector color
S = 1000; % size of marker (handle spaces between patches)
%plot
figure('Color', 'w');
scatter(X, Y, S, C, 'fill', 's');
set(gca, 'XLim', [0 size(Z,2)+1], 'YLim', [0 size(Z,1)+1]);
colormap jet
colorbar
set(gca, 'YDir','reverse');
The ouput:
I'm plotting some data with MATLAB and I'd like to adjust the distance between axis label and the axis itself. However, simply adding a bit to the "Position" property of the label makes the label move out of the figure window. Is there a "margin" property or something similar?
In the above figure, I'd like to increase the distance between the numbers and the label "Time (s)" while automatically extending the figures size so that the label does not move out of bounds.
This is how I set up the figure / axis.
figure;
set(gca, ...
'Box' , 'off' , ...
'LooseInset' , get(gca, 'TightInset') * 1.5 , ...
'TickDir' , 'in' , ...
'XMinorTick' , 'off' , ...
'YMinorTick' , 'off' , ...
'TickLength' , [.02 .02] , ...
'LineWidth' , 1 , ...
'XGrid' , 'off' , ...
'YGrid' , 'off' , ...
'FontSize' , 18 );
I wrote a function that should do exactly what you want. It keeps the axes at the exact same size and position, it moves the x-label down and increases the figure size to be large enough to show the label:
function moveLabel(ax,offset,hFig,hAxes)
% get figure position
posFig = get(hFig,'Position');
% get axes position in pixels
set(hAxes,'Units','pixels')
posAx = get(hAxes,'Position');
% get label position in pixels
if ax=='x'
set(get(hAxes,'XLabel'),'Units','pixels')
posLabel = get(get(hAxes,'XLabel'),'Position');
else
set(get(hAxes,'YLabel'),'Units','pixels')
posLabel = get(get(hAxes,'YLabel'),'Position');
end
% resize figure
if ax=='x'
posFigNew = posFig + [0 -offset 0 offset];
else
posFigNew = posFig + [-offset 0 offset 0];
end
set(hFig,'Position',posFigNew)
% move axes
if ax=='x'
set(hAxes,'Position',posAx+[0 offset 0 0])
else
set(hAxes,'Position',posAx+[offset 0 0 0])
end
% move label
if ax=='x'
set(get(hAxes,'XLabel'),'Position',posLabel+[0 -offset 0])
else
set(get(hAxes,'YLabel'),'Position',posLabel+[-offset 0 0])
end
% set units back to 'normalized' and 'data'
set(hAxes,'Units','normalized')
if ax=='x'
set(get(hAxes,'XLabel'),'Units','data')
else
set(get(hAxes,'YLabel'),'Units','data')
end
end
In this case offset should be the absolute offset in pixels. If you want relative offsets, I think this function could easily be rewritten. hFig is the figure handle and hAxes the axes handle.
EDIT: create the figure using hFig = figure; and the axes by hAxes = axes; (then set up the axes like you did in the question: set(hAxes,...)) before calling the function.
EDIT2: added the lines where the 'Units' of hAxes and the XLabel are changed back to 'normalized' and 'data' respectively. That way the figure stays the way you want it after resizing.
EDIT3: modified the function to work for both X and Y labels. Additional input ax should be 'x' or 'y'.
You can accomplish this by adjusting the position of the axis an xlabel. I also suggest using "normalized" units so your positioning does not depend on the data range. Here's an example:
figure
plot(rand(1,10))
set(gca, 'Units', 'Normalized');
pos = get(gca, 'Position');
offset = 0.1;
set(gca, ...
'Box' , 'off' , ...
'LooseInset' , get(gca, 'TightInset') * 1.5 , ...
'TickDir' , 'in' , ...
'XMinorTick' , 'off' , ...
'YMinorTick' , 'off' , ...
'TickLength' , [.02 .02] , ...
'LineWidth' , 1 , ...
'XGrid' , 'off' , ...
'YGrid' , 'off' , ...
'FontSize' , 18 , ...
'Position' , pos + [0, offset, 0, -offset]);
h = xlabel('Time (s)');
set(h, 'Units', 'Normalized');
pos = get(h, 'Position');
set(h, 'Position', pos + [0, -offset, 0]);
I know this has been answered and all, but this is (to some extent) a simpler way:
relative_offset = 1.5;
close all;
figure(99);clf
plot(rand(1,10))
xlabel('The x-axis')
xh = get(gca,'XLabel'); % Handle of the x label
pause(0.2)
set(xh, 'Units', 'Normalized')
pause(0.2)
pos = get(xh, 'Position');
set(xh, 'Position',pos.*[1,relative_offset,1])
I have included the pause commands, since my system will get ahead of itself in some weird way otherwise.
/Niels