geometric random graph in a circle - matlab

I wanted to generate a set of coordinates distributed uniformly at random within a ball of radius R. Is there any way to do this in Matlab without for loops, in a matrix-like form?
Thanks
UPDATE:
I'm sorry for the confusion. I only need to generate n points uniformly at random over a circle of radius R, not a sphere.

the correct answer is here http://mathworld.wolfram.com/DiskPointPicking.html. The distribution is known as "Disk point picking"

I was about to mark this as a duplicate of a previous question on generating uniform distribution of points in a sphere, but I think you deserve the benefit of doubt here, as although there's a matlab script in the question, most of that thread is python.
This little function given in the question (and I'm pasting it directly from there), is what you need.
function X = randsphere(m,n,r)
% This function returns an m by n array, X, in which
% each of the m rows has the n Cartesian coordinates
% of a random point uniformly-distributed over the
% interior of an n-dimensional hypersphere with
% radius r and center at the origin. The function
% 'randn' is initially used to generate m sets of n
% random variables with independent multivariate
% normal distribution, with mean 0 and variance 1.
% Then the incomplete gamma function, 'gammainc',
% is used to map these points radially to fit in the
% hypersphere of finite radius r with a uniform % spatial distribution.
% Roger Stafford - 12/23/05
X = randn(m,n);
s2 = sum(X.^2,2);
X = X.*repmat(r*(gammainc(s2/2,n/2).^(1/n))./sqrt(s2),1,n);
To learn why you can't just use uniform random variable for all three co-ordinates as one might think is the correct way, give this article a read.

For the sake of completeness, here is some MATLAB code for a point-culling solution. It generates a set of random points within a unit cube, removes points that are outside a unit sphere, and scales the coordinate points up to fill a sphere of radius R:
XYZ = rand(1000,3)-0.5; %# 1000 random 3-D coordinates
index = (sum(XYZ.^2,2) <= 0.25); %# Find the points inside the unit sphere
XYZ = 2*R.*XYZ(index,:); %# Remove points and scale the coordinates
One key drawback to this point-culling method is that it makes it difficult to generate a specific number of points. For example, if you want to generate 1000 points within your sphere, how many do you have to create in the cube before culling them? If you scale up the number of points generated in the cube by a factor of 6/pi (i.e. the ratio of the volume of a unit cube to a unit sphere), then you can get close to the number of desired points in the sphere. However, since we're dealing with (pseudo)random numbers after all, we can never be absolutely certain we will generate enough points that fall in the sphere.
In short, if you want to generate a specific number of points, I'd try out one of the other solutions suggested. Otherwise, the point-culling solution is nice and simple.

Not sure if I understand your question correctly, but can't you just generate any random number inside a sphere by setting φ, θ and r, assigned to random numbers?

Related

How to generate random uniformly distributed vectors of euclidian length of one?

I am trying to randomly generate uniformly distributed vectors, which are of Euclidian length of 1. By uniformly distributed I mean that each entry (coordinate) of the vectors is uniformly distributed.
More specifically, I would like to create a set of, say, 1000 vectors (lets call them V_i, with i=1,…,1000), where each of these random vectors has unit Euclidian length and the same dimension V_i=(v_1i,…,v_ni)' (let’s say n = 5, but the algorithm should work with any dimension). If we then look on the distribution of e.g. v_1i, the first element of each V_i, then I would like that this is uniformly distributed.
In the attached MATLAB example you see that you cannot simply draw random vectors from a uniform distribution and then normalize the vectors to Euclidian length of 1, as the distribution of the elements across the vectors is then no longer uniform.
Is there a way to generate this set of vectors such, that the distribution of the single elements across the vector-set is uniform?
Thank you for any ideas.
PS: MATLAB is our Language of choice, but solutions in any languages are, of course, welcome.
clear all
rng('default')
nvar=5;
sample = 1000;
x = zeros(nvar,sample);
for ii = 1:sample
y=rand(nvar,1);
x(:,ii) = y./norm(y);
end
hist(x(1,:))
figure
hist(x(2,:))
figure
hist(x(3,:))
figure
hist(x(4,:))
figure
hist(x(5,:))
What you want cannot be accomplished.
Vectors with a length of 1 sit on a circle (or sphere or hypersphere depending on the number of dimensions). Let's focus on the 2D case, if it cannot be done there, it will be clear that it cannot be done with more dimensions either.
Because the points are on a circle, their x and y coordinates are dependent, the one can be computed based on the other. Thus, the distributions of x and y coordinates cannot be defined independently. We can define the distribution of the one, generate random values for it, but the other coordinate must be computed from the first.
Let's make points on a half circle with a uniform x coordinate (can be extended to a full circle by adding a random sign to the y coordinate):
N = 1000;
x = 2 * rand(N,1) - 1;
y = sqrt(1 - x.^2);
plot(x,y,'.')
axis equal
histogram(y)
The plot generates shows a clearly non-uniform distribution, with many more samples generated near y=1 than near y=0. If we add a random sign to the y-coordinate we'd have more samples near y=1 and y=-1 than near y=0.

Finding length between a lot of elements

I have an image of a cytoskeleton. There are a lot of small objects inside and I want to calculate the length between all of them in every axis and to get a matrix with all this data. I am trying to do this in matlab.
My final aim is to figure out if there is any axis with a constant distance between the object.
I've tried bwdist and to use connected components without any luck.
Do you have any other ideas?
So, the end goal is that you want to globally stretch this image in a certain direction (linearly) so that the distances between nearest pairs end up the closest together, hopefully the same? Or may you do more complex stretching ? (note that with arbitrarily complex one you can always make it work :) )
If linear global one, distance in x' and y' is going to be a simple multiplication of the old distance in x and y, applied to every pair of points. So, the final euclidean distance will end up being sqrt((SX*x)^2 + (SY*y)^2), with SX being stretch in x and SY stretch in y; X and Y are distances in X and Y between pairs of points.
If you are interested in just "the same" part, solution is not so difficult:
Find all objects of interest and put their X and Y coordinates in a N*2 matrix.
Calculate distances between all pairs of objects in X and Y. You will end up with 2 matrices sized N*N (with 0 on the diagonal, symmetric and real, not sure what is the name for that type of matrix).
Find minimum distance (say this is between A an B).
You probably already have this. Now:
Take C. Make N-1 transformations, which all end up in C->nearestToC = A->B. It is a simple system of equations, you have X1^2*SX^2+Y1^2*SY^2 = X2^2*SX^2+Y2*SY^2.
So, first say A->B = C->A, then A->B = C->B, then A->B = C->D etc etc. Make sure transformation is normalized => SX^2 + SY^2 = 1. If it cannot be found, the only valid transformation is SX = SY = 0 which means you don't have solution here. Obviously, SX and SY need to be real.
Note that this solution is unique except in case where X1 = X2 and Y1 = Y2. In this case, grab some other point than C to find this transformation.
For each transformation check the remaining points and find all nearest neighbours of them. If distance is always the same as these 2 (to a given tolerance), great, you found your transformation. If not, this transformation does not work and you should continue with the next one.
If you want a transformation that minimizes variations between distances (but doesn't require them to be nearly equal), I would do some optimization method and search for a minimum - I don't know how to find an exact solution otherwise. I would pick this also in case you don't have linear or global stretch.
If i understand your question correctly, the first step is to obtain all of the objects center of mass points in the image as (x,y) coordinates. Then, you can easily compute all of the distances between all points. I suggest taking a look on a histogram of those distances which may provide some information as to the nature of distance distribution (for example if it is uniformly random, or are there any patterns that appear).
Obtaining the center of mass points is not an easy task, consider transforming the image into a binary one, or some sort of background subtraction with blob detection or/and edge detector.
For building a histogram you can use histogram.

random distribution on n-dimensional cube in matlab

How can i generate random-uniform points in the surface of a N-dimensional cube with edge E?
There is a code for generating for a N-dimensional sphere, but I can't figure it out how can I generate it for a cube.
The nice thing with the N-dimensional hypercube is that its faces are hypercubes of dimension (N-1). Therefore I would proceed in four steps steps.
Draw a random integer called d in the range 1..N to select the hypercube face direction. d=randi(N)
To select a specific face among the two possible ones, draw a random integer called s which can take either of the two values: 0 or 1. s =randi(2)-1
Draw a random uniformly distributed vector called v of length N in the range 0..1. v=rand(N,1)
replace s as the d-th coordinate in v and multiply the result by the edge length E. v(d)=s, v=E*v
Plotting 1000 points on the surface or the 3-d cube of edge-length 2 would we something like:
N=3;
E=2;
Nsamples=1000;
d=randi(N,1,Nsamples);
s =randi(2,1,Nsamples)-1;
v=rand(N,Nsamples);
for i=1:Nsamples
v(d(i),i)=s(i);
end
v = E*v;
plot3(v(1,:),v(2,:),v(3,:),'.');
This implementation is probably not the best in terms of pure efficiency, but you understand how it works.
Hope this helps.
Adrien.

Calculating the number of points in each of several subregions

I have points distributed over a square according to some point process, probably Poisson point process. I want to divide the square into smaller squares and calculate the number of points in each sub-square. Is there an easy way to do it in Matlab by probably a built-in function?
As Nras said, the built-in command hist3 does exactly what you want. To demonstrate its use, I generated points with uniformly distributed polar radius and polar angle:
n = 100000;
r = rand(n,1);
theta = 2*pi*rand(n,1);
points = [r.*cos(theta), r.*sin(theta)];
hist3(points,[15,15]); % [15,15] is the number of bins in each direction
The graphic output is below. If you want the actual counts instead of a picture, replace the last command with
counts = hist3(points,[15,15]);

2D color plot using a limited dataset

I couldn't find a solution after trying for a long time.
I have 3 columns of data: x, y, and the stress value (S) at every point (x,y). I want to generate a 2D color plot displaying continuous color change with the magnitude of the stress (S). The stress values increase from -3*10^4 Pa to 4*10^4 Pa. I only have hundreds of data points for an area, but I want to see the stress magnitude (read from the color) at every location (x, y). What Matlab command should I use?
I want to make a 2D color plot showing stress magnitude (S) at every location (x, y) based on continuous color change using limited data points
I'd use patch with interpolated coloring:
% some data, x/y are random
N = 50;
x = rand(N,1);
y = rand(N,1);
S = sin(2*x)+y;
% plotting
tr = delaunay(x,y);
trisurf(tr,x,y,zeros(N,1),S,'FaceColor','interp');
view (2)
Take a look at surf and mesh in the MATLAB documentation
To further contribute on Gunther Struyf answer; assuming it is a FEM analysis you may already have a connectivity matrix say 'M' and 'x' 'y' column vectors with node coordinates. Stress values at the nodes may be contained in a column vector 'S'; then you may use the patch function as stated above:
patch('faces',M,'vertices',[x(:) y(:)],'facevertexcdata',S(:),'FaceColor','interp');
and you will have a 2D plot of your data similar to the one posted by Gunther Struyf.