How do I specify the size of the circles in the scatter plot so that the length of their diameters is equal to length of one unit on the axes?

10 次查看(过去 30 天)
I am doing molecular dynamics simulations and plotting circles(scatter plots) with the data points I get from the simulation.My length scale is such that diameter of circle=1 unit on x and y axes.I want to know how to specify the scatter size so that it matches with the scale. please help.
h=figure('visible','off');
xlim([-25 25]);
hold on;
ylim([-25 25]);
hold on;
scatter(data(:,1),data(:,2),50);

回答(1 个)

Walter Roberson
Walter Roberson 2017-6-1
That is not possible. The size for scatter is always area in "points squared" (one point is 1/72 of an inch). That is an absolute size that does not change as you zoom the plot in or out, so it is not possible to control it in data units (because data units change as you zoom in or out).
You can
ax = gca;
AR = get(gca, 'dataaspectratio');
if ~isequal(AR(1:2), [1 1])
error('Units are not equal on X and Y, cannot create marker size that is one unit on both');
end
oldunits = get(ax, 'Units');
set(ax, 'Units', 'points');
pos = get(ax, 'Position'); %[X Y width height]
set(ax, 'Units', oldunits');
XL = xlim(ax);
points_per_unit = pos(3) / (XL(2) - XL(1));
marker_size = points_per_unit .^2 * pi / 4; %pi*r^2 but remember points_per_unit is d not r
  7 个评论
Arghadwip Paul
Arghadwip Paul 2017-6-9
编辑:Walter Roberson 2017-6-9
I used the rectangle() function to generate the plots and it is giving correct results. But the computation time has increased since I am using a loop to find the position [x y 1 1]. You can see my code. How can I compute it faster? With scatter, the computation time is not much, but I have no control over the size then, which is an important aspect of the plots.
myfolder= '.........';
num_particles=10000;
data=zeros(num_particles,6);
datfiles = dir('*.txt');
baseFileNames = natsortfiles({datfiles.name});
for k = 1 : numel(baseFileNames)
fullFilename= fullfile(myfolder, baseFileNames{k});
[pathstr,name,ext]=fileparts(fullFilename);
% data = load(fullFilename);
fid = fopen(fullFilename);
datum=fread(fid,'double');
j=1;
for i=1:num_particles
data(i,1)=datum(j);
data(i,2)=datum(j+1);
data(i,3)=datum(j+2);
data(i,4)=datum(j+3);
data(i,5)=datum(j+4);
data(i,6)=datum(j+5);
j=j+6;
end
fprintf(1, 'Now reading %s\n', fullFilename);
fclose(fid);
h=figure('visible','off');
xlim([-65 65]);
hold on;
ylim([-65 65]);
hold on;
for m=1:num_particles
xx=data(m,1)-0.5;
yy=data(m,2)-0.5;
pos=[xx yy 1 1];
rectangle('Position',pos,'Curvature',[1 1]);
hold on;
end
quiver(data(:,1),data(:,2),data(:,4),data(:,5),0.2);
[pathstr,name,ext]=fileparts(fullFilename);
title(name);
% print -r2500 % set resolution
saveas(h,sprintf('fig%d.png',k));
% saveas(h,name,'png');
hold off;
end
Walter Roberson
Walter Roberson 2017-6-9
ax = gca;
Any time you are working with "current" objects like "current axes", which object is "current" can change in between lines, because the user might click. In particular, if the user is debugging, then MATLAB processes pending graphics events every time the keyboard is given control, so if the user clicks on a window to grab it to move it aside to be able to view something (like the code) then the window can accidentally become the "current". It is therefore best practice to take a copy of the "current" axes into a variable if you are going to refer to it, so that if what gca refers to changes, you still consistently refer to the original axes.
AR = get(gca, 'dataaspectratio');
if ~isequal(AR(1:2), [1 1])
error('Units are not equal on X and Y, cannot create marker size that is one unit on both');
end
axes have a dataaspectratio property that describes how many data units in one direction equal how many data units in the other direction. The calculations of area that we need to do are only correct of 1 unit horizontally is the same as 1 unit vertically, so we check to see whether that is the case and reject the situation if it is not.
oldunits = get(ax, 'Units');
set(ax, 'Units', 'points');
pos = get(ax, 'Position'); %[X Y width height]
set(ax, 'Units', oldunits');
The Position property of an axes does not have a fixed unit of measure. The unit of measure it uses is given by the Units property. The way to find out how big something is in a particular unit of measure (such as Points) is to take a copy of the current unit of measure, change to the unit of measure we are interested in, ask the size, and then switch back to the old unit of measure.
XL = xlim(ax);
points_per_unit = pos(3) / (XL(2) - XL(1));
We already established that we are using a 1:1 data aspect ratio, so the ratio for x is the same as the ratio for y, so it does not matter whether we query x or y, so we pick one of the two.
The first element of xlim is the data units of the left side of the axes; the second element of xlim is the data units of the right side of the axes. Subtract the two to find out how many data units the horizontal axes spans. The third element of Position is the width, which we have configured to be in Points. So the ratio of the width in points to the data units tells us how many points there are for each data unit.
marker_size = points_per_unit .^2 * pi / 4; %pi*r^2 but remember points_per_unit is d not r
This is a standard area = pi*r^2 = pi*(d/2)^2 after an implicit points_per_unit * 1 data_unit

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 2-D and 3-D Plots 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by