I want to generate 750 random number in 2D data x (0,1) and y (0,1)
X1 = np.random.random((750,2))
However, I want to make sure I don't have any value in the circular region such as
I can remove the value, but I want to fix the number of the random number to be 750. What would be the best way to generate such list?
import random
points = []
radius = 1
num_points=1500
index = 0
max_coord = 750
while index < num_points:
x=random.random()*max_coord
y=random.random()*max_coord
if x**2 + y**2 > radius**2:
points = points + [[x,y]]
index = index + 1
print(points)
Change max_coor to obtain bigger numbers. This only gives you 1500 points outside the circle of the given radius=1. Each coordinate varies between 0 and 750
you can just apply pythagorean's theorem. Here is my code to do that
import numpy as np
import matplotlib.pyplot as plt
dist = 0.2
X1 = np.random.random((750,2))
X2 = [x for x in X1 if (x[0]-0.5)**2 + (x[1]-0.5)**2 > dist**2] # filter values that are to close to center
# for plotting
x = [x[0] for x in X2]
y = [y[1] for y in X2]
plt.scatter(x,y)
plt.show()
You can do this with a well-known technique called rejection sampling. Generate candidate values and see if they meet your constraints. If so, accept them, otherwise reject and repeat. With 2-d sampling, the probability of acceptance on a given trial is P{Accept} = Area(acceptance region) / Area(generating region). Repetitions due to rejection are independent, so the number of trials has a geometric distribution with parameter p = P{Accept}
and Expected # trials = 1 / P{Accept}. For example, if the rejection region is a circle with radius 1/2 centered in a unit square, P{Accept} = (4 - Pi)/4 andon average it will take 4/(4 - Pi) (approximately 4.66) attempts per value generated. Obviously this won't work if the radius is >= sqrt(2)/2, and gets expensive as you approach that limit.
Note that the rejection circle does not need to be centered in the square, you just reject any candidate that is less than radius away from the circle's center.
Here's the code:
import numpy as np
def generate_pt(exclusion_radius):
while True:
candidate = np.random.sample(2)
# The following assumes the rejection circle is centered at (0.5, 0.5).
# Adjust by subtracting individual x/y coordinates for the center of
# the circle if you don't want it centered. Acceptance/rejection
# distance is determined by Pythagorean theorem.
if np.sum(np.square(candidate - 0.5)) >= exclusion_radius * exclusion_radius:
return candidate
# Generate 750 points outside the centered circle of radius 0.3.
data = np.array([generate_pt(0.3) for _ in range(750)])
Related
I'm running a model of particles, and I want to have initial conditions for the particle locations mimicking a gaussian distribution.
If I have N number of particles on 1D grid from -10 to 10, I want them to be distributed on the grid according to a gaussian with a known mean and standard deviation. It's basically creating a histogram where each bin width is 1 (the x-axis of locations resolution is 1), and the frequency of each bin should be how many particles are in it, which should all add up to N.
My strategy was to plot a gaussian function on the x-axis grid, and then just approximate the value of each point for the number of particles:
def gaussian(x, mu, sig):
return 1./(np.sqrt(2.*np.pi)*sig)*np.exp(-np.power((x - mu)/sig, 2.)/2)
mean = 0
sigma = 1
x_values = np.arange(-10, 10, 1)
y = gaussian(x_values, mean, sigma)
However, I have normalization issues (the sum doesn't add up to N), and the number of particles in each point should be an integer (I thought about converting the y array to integers but again, because of the normalization issue I get a flat line).
Usually, the problem is fitting a gaussian to histogram, but in my case, I need to do the reverse - and I couldn't find a solution for it yet. I will appreciate any help!
Thank you!!!
You can use numpy.random.normal to sample this distribution. You can get N points inside range (-10, 10) that follows Gaussian distribution with the following code.
import numpy as np
import matplotlib.pyplot as plt
N = 10000
mean = 5
sigma = 3
bin_edges = np.arange(-10, 11, 1)
x_values = (bin_edges[1:] + bin_edges[:-1]) / 2
points = np.random.normal(mean, sigma, N * 10)
mask = np.logical_and(points < 10, points > -10)
points = points[mask] # drop points outside range
points = points[:N] # only use the first N points
y, _ = np.histogram(points, bins=bin_edges)
plt.scatter(x_values, y)
plt.show()
The idea is to generate a lot of random numbers (10 N in the code), and ignores the points outside your desired range.
I know there are countless ways to do this that are better than my way, but I really want to figure out what I'm doing wrong here.
I'm trying to get to the value of PI doing a monte carlo simulation,but I don't get what I'm doing wrong
PI Monte Carlo
import random
import pylab
def MonteCarloPI(numtries):
circle = 0
for i in range (numtries):
a = (float(random.random())+1)**0.5
b = float(random.random())*a
if b <= 1:
circle += 1
rapportoAree = (circle/numtries)
return rapportoAree*4
print(MonteCarloPI(1000))
Edit
The point of this is to find the area of the circle without using x and y coordinates.
The idea is that if 'a' is a random number between 1 and sqrt2 and then 'b' is a random number between 0 and 'a' In theory all values of 'b' that are <1 should be inside the circle, so I should have the number of points in the circle and the number of total points, that way I can calculate the fraction that is proportional to PI
I hope this image can explain better than my words
The problem is that your distribution of (a, b)values is not equivalent to the uniform distribution of (x, y) values (Cartesian coordinates). Your implementation uses something akin to polar coordinates, with a uniform distribution of the radius (over the range of a square) and a quadratically skewed distribution of the reference angle.
As a result, you generate more points within the circle than is proper for the measurement you want. To fix this, you'll need to alter your formulas to account for the polar transformations you've introduced.
-- a --
Your posted formula:
a = (float(random.random())+1)**0.5
Does not yield a uniform distribution over the range (1.0, sqrt(2.0)). It's more dense the higher you go. For comparison, let's extend this to the range (1, 10) -- we'll choose a random integer 0-99.
a = (random.randint(0, 99) + 1)**0.5
All 100 integers are equally likely, but let's look at the resulting distribution. At the bottom, the results in the range [1.0, 2.0) will be hit with only integers 1 and 2. At the top, results in the range [9.0, 10.0) -- the same size -- will be hit with integers 80 through 99 (a total of 20 values). Thus, 9 <= a < 10 is ten times as likely as 1 <= a < 2.
Your formula suffers from a lesser version of this problem. You can correct this by generating numbers in a uniform distribution over [1.0, sqrt(2.0)].
-- b --
To illustrate the problem with b, draw some equally-spaced (according to the a values you generate) line segments. What is the total length of these segments? The "inside" component of each segment is 1.0, but note that the points represented are much more dense near the origin -- inside the circle -- than outside.
To calculate b, you need to undo the center bias of your polar coordinates. I will leave this derivation as an exercise for the student ... should you want to continue this line of attack.
Three different methods using Cartesian coordinates.
import random
import math
def MonteCarloPI(numtries):
inside = 0
for i in range (numtries):
x2 = random.random()**2
y2 = random.random()**2
if (math.sqrt(x2 + y2) < 1.0):
inside += 1
return (float(inside) / numtries) * 4
outputs:
>>> print(MonteCarloPI(1000))
3.14
and
>>> print(MonteCarloPI(100000))
3.14476
you can even clean up the function using the built in math.hypot which calculates euclidean norms:
import random
from math import hypot
def MonteCarloPI(numtries):
inside = 0
for i in range (numtries):
if hypot(random.random(), random.random()) < 1:
inside += 1
return (float(inside) / numtries) * 4
>>> print(MonteCarloPI(100000))
3.14364
or numpy one liner
import numpy as np
def MonteCarloPI(n):
return np.sum(np.random.rand(n)**2+np.random.rand(n)**2<1)/float(n)*4
outputs:
>>> print(MonteCarloPI(100000))
3.1462
First of all, will appreciate if someone will give me a proper term for "annulus with a shifted hole", see exactly what kind of shape I mean on a picture below.
Back to main question: I want to pick a random point in the orange area, uniform distribution is not required. For a case of a usual annulus I would've picked random point in (r:R) range and a random angle, then transform those to x,y and it's done. But for this unusual shape... is there even a "simple" formula for that, or should I approach it by doing some kind of polygonal approximation of a shape?
I'm interested in a general approach but will appreciate an example in python, javascript or any coding language of your choice.
Here's a simple method that gives a uniform distribution with no resampling.
For simplicity assume that the center of the outer boundary circle (radius r_outer) is at (0, 0) and that the center of the inner circular boundary (radius r_inner) lies at (x_inner, y_inner).
Write D for the outer disk, H1 for the subset of the plane given by the off-center inner hole, and H2 for the central disk of radius r_inner, centered at (0, 0).
Now suppose that we ignore the fact that the inner circle is not central, and instead of sampling from D-H1 we sample from D-H2 (which is easy to do uniformly). Then we've made two mistakes:
there's a region A = H1 - H2 that we might sample from, even though those samples shouldn't be in the result.
there's a region B = H2 - H1 that we never sample from, even though we should
But here's the thing: the regions A and B are congruent: given any point (x, y) in the plane, (x, y) is in H2 if and only if (x_inner - x, y_inner - y) is in H1, and it follows that (x, y) is in A if and only if (x_inner - x, y_inner - y) is in B! The map (x, y) -> (x_inner - x, y_inner - y) represents a rotation by 180 degress around the point (0.5*x_inner, 0.5*y_inner). So there's a simple trick: generate from D - H2, and if we end up with something in H1 - H2, rotate to get the corresponding point of H2 - H1 instead.
Here's the code. Note the use of the square root of a uniform distribution to choose the radius: this is a standard trick. See this article, for example.
import math
import random
def sample(r_outer, r_inner, x_inner, y_inner):
"""
Sample uniformly from (x, y) satisfiying:
x**2 + y**2 <= r_outer**2
(x-x_inner)**2 + (y-y_inner)**2 > r_inner**2
Assumes that the inner circle lies inside the outer circle;
i.e., that hypot(x_inner, y_inner) <= r_outer - r_inner.
"""
# Sample from a normal annulus with radii r_inner and r_outer.
rad = math.sqrt(random.uniform(r_inner**2, r_outer**2))
angle = random.uniform(-math.pi, math.pi)
x, y = rad*math.cos(angle),rad*math.sin(angle)
# If we're inside the forbidden hole, reflect.
if math.hypot(x - x_inner, y - y_inner) < r_inner:
x, y = x_inner - x, y_inner - y
return x, y
And an example plot, generated by the following:
import matplotlib.pyplot as plt
samples = [sample(5, 2, 1.0, 2.0) for _ in range(10000)]
xs, ys = zip(*samples)
plt.scatter(xs, ys, s=0.1)
plt.axis("equal")
plt.show()
Do you really need exact sampling? Because with acceptance/rejection it should work just fine. I assume big orange circle is located at (0,0)
import math
import random
def sample_2_circles(xr, yr, r, R):
"""
R - big radius
r, xr, yr - small radius and its position
"""
x = xr
y = yr
cnd = True
while cnd:
# sample uniformly in whole orange circle
phi = 2.0 * math.pi * random.random()
rad = R * math.sqrt(random.random())
x = rad * math.cos(phi)
y = rad * math.sin(phi)
# check condition - if True we continue in the loop with sampling
cnd = ( (x-xr)**2 + (y-yr)**2 < r*r )
return (x,y)
Since you have shown no equation, algorithm, or code of your own, but just an outline of an algorithm for center-aligned circles, I'll also just give the outline of an algorithm here for the more general case.
The smaller circle is the image of the larger circle under a similarity transformation. I.e. there is a fixed point in the larger circle and a ratio (which is R/r, greater than one) such that you can take any point on the smaller circle, examine the vector from the fixed point to that point, and multiply that vector by the ratio, then the end of that vector when it starts from the fixed point is a point on the larger circle. This transformation is one-to-one.
So you can choose a random point on the smaller circle (choose the angle at random between 0 and two-pi) and choose a ratio at random between 1 and the proportionality ratio R/r between the circles. Then use that the similarity transformation with the same fixed point but using the random ratio to get the image point of the just-chosen point on the smaller circle. This is a random point in your desired region.
This method is fairly simple. In fact, the hardest mathematical part is finding the fixed point of the similarity transformation. But this is pretty easy, given the centers and radii of the two circles. Hint: the transformation takes the center of the smaller circle to the center of the larger circle.
Ask if you need more detail. My algorithm does not yield a uniform distribution: the points will be more tightly packed where the circles are closest together and less tightly packed where the circles are farthest apart.
Here is some untested Python 3.6.2 code that does the above. I'll test it and show a graphic for it when I can.
import math
import random
def rand_pt_between_circles(x_inner,
y_inner,
r_inner,
x_outer,
y_outer,
r_outer):
"""Return a random floating-point 2D point located between the
inner and the outer circles given by their center coordinates and
radii. No error checking is done on the parameters."""
# Find the fixed point of the similarity transformation from the
# inner circle to the outer circle.
x_fixed = x_inner - (x_outer - x_inner) / (r_outer - r_inner) * r_inner
y_fixed = y_inner - (y_outer - y_inner) / (r_outer - r_inner) * r_inner
# Find a a random transformation ratio between 1 and r_outer / r_inner
# and a random point on the inner circle
ratio = 1 + (r_outer - r_inner) * random.random()
theta = 2 * math.pi * random.random()
x_start = x_inner + r_inner * math.cos(theta)
y_start = y_inner + r_inner * math.sin(theta)
# Apply the similarity transformation to the random point.
x_result = x_fixed + (x_start - x_fixed) * ratio
y_result = y_fixed + (y_start - y_fixed) * ratio
return x_result, y_result
The acceptance/rejection method as described by Severin Pappadeux is probably the simplest.
For a direct approach, you can also work in polar coordinates, with the center of the hole as the pole.
The polar equation (Θ, σ) (sorry, no rho) of the external circle will be
(σ cosΘ - xc)² + (σ sinΘ - yc)² = σ² - 2(cosΘ xc + sinΘ yc)σ + xc² + yc² = R²
This is a quadratic equation in σ, that you can easily solve in terms of Θ. Then you can draw an angle in 0, 2π an draw a radius between r and σ.
This won't give you a uniform distribution, because the range of σ is a function of Θ and because of the polar bias. This might be fixed by computing a suitable transfer function, but this is a little technical and probably not tractable analytically.
I am trying to generate an efficient code for generating a number of random position vectors which I then use to calculate a pair correlation function. I am wondering if there is straightforward way to set a constraint on the minimum distance allowed between any two points placed in my box.
My code currently is as follows:
def pointRun(number, dr):
"""
Compute the 3D pair correlation function
for a random distribution of 'number' particles
placed into a 1.0x1.0x1.0 box.
"""
## Create array of distances over which to calculate.
r = np.arange(0., 1.0+dr, dr)
## Generate list of arrays to define the positions of all points,
## and calculate number density.
a = np.random.rand(number, 3)
numberDensity = len(a)/1.0**3
## Find reference points within desired region to avoid edge effects.
b = [s for s in a if all(s > 0.4) and all(s < 0.6) ]
## Compute pairwise correlation for each reference particle
dist = scipy.spatial.distance.cdist(a, b, 'euclidean')
allDists = dist[(dist < np.sqrt(3))]
## Create histogram to generate radial distribution function, (RDF) or R(r)
Rr, bins = np.histogram(allDists, bins=r, density=False)
## Make empty containers to hold radii and pair density values.
radii = []
rhor = []
## Normalize RDF values by distance and shell volume to get pair density.
for i in range(len(Rr)):
y = (r[i] + r[i+1])/2.
radii.append(y)
x = np.average(Rr[i])/(4./3.*np.pi*(r[i+1]**3 - r[i]**3))
rhor.append(x)
## Generate normalized pair density function, by total number density
gr = np.divide(rhor, numberDensity)
return radii, gr
I have previously tried using a loop that calculated all distances for each point as it was made and then accepted or rejected. This method was very slow if I use a lot of points.
Here is a scalable O(n) solution using numpy. It works by initially specifying an equidistant grid of points and then perturbing the points by some amount keeping the distance between the points at most min_dist.
You'll want to tweak the number of points, box shape and perturbation sensitivity to get the min_dist you want.
Note: If you fix the size of a box and specify a minimum distance between every point, it makes sense that there will be a limit to the number of points you can draw satisfying the minimum distance.
import numpy as np
import matplotlib.pyplot as plt
# specify params
n = 500
shape = np.array([64, 64])
sensitivity = 0.8 # 0 means no movement, 1 means max distance is init_dist
# compute grid shape based on number of points
width_ratio = shape[1] / shape[0]
num_y = np.int32(np.sqrt(n / width_ratio)) + 1
num_x = np.int32(n / num_y) + 1
# create regularly spaced neurons
x = np.linspace(0., shape[1]-1, num_x, dtype=np.float32)
y = np.linspace(0., shape[0]-1, num_y, dtype=np.float32)
coords = np.stack(np.meshgrid(x, y), -1).reshape(-1,2)
# compute spacing
init_dist = np.min((x[1]-x[0], y[1]-y[0]))
min_dist = init_dist * (1 - sensitivity)
assert init_dist >= min_dist
print(min_dist)
# perturb points
max_movement = (init_dist - min_dist)/2
noise = np.random.uniform(
low=-max_movement,
high=max_movement,
size=(len(coords), 2))
coords += noise
# plot
plt.figure(figsize=(10*width_ratio,10))
plt.scatter(coords[:,0], coords[:,1], s=3)
plt.show()
Based on #Samir 's answer, and make it a callable function for your convenience :)
import numpy as np
import matplotlib.pyplot as plt
def generate_points_with_min_distance(n, shape, min_dist):
# compute grid shape based on number of points
width_ratio = shape[1] / shape[0]
num_y = np.int32(np.sqrt(n / width_ratio)) + 1
num_x = np.int32(n / num_y) + 1
# create regularly spaced neurons
x = np.linspace(0., shape[1]-1, num_x, dtype=np.float32)
y = np.linspace(0., shape[0]-1, num_y, dtype=np.float32)
coords = np.stack(np.meshgrid(x, y), -1).reshape(-1,2)
# compute spacing
init_dist = np.min((x[1]-x[0], y[1]-y[0]))
# perturb points
max_movement = (init_dist - min_dist)/2
noise = np.random.uniform(low=-max_movement,
high=max_movement,
size=(len(coords), 2))
coords += noise
return coords
coords = generate_points_with_min_distance(n=8, shape=(2448,2448), min_dist=256)
# plot
plt.figure(figsize=(10,10))
plt.scatter(coords[:,0], coords[:,1], s=3)
plt.show()
As I understood, you're looking for an algorithm to create many random points in a box such that no two points are closer than some minimum distance. If this is your problem, then you can take advantage of statistical physics, and solve it using molecular dynamics software. Moreover, you do need molecular dynamics or Monte Carlo to obtain exact solution of this problem.
You place N atoms in a rectangular box, create a repulsive interaction of a fixed radius between them (such as shifted Lennard-Jones interaction), and run simulation for some time (untill you see that the points spread out uniformly throughout the box). By laws of statistical physics you can show that positions of the points would be maximally random given the constraint that points cannot be close than some distance. This would not be true if you use iterative algorithm, such as placing points one-by-one and rejecting them if they overlap
I would estimate a runtime of several seconds for 10000 points, and several minutes for 100k. I use OpenMM for all my moelcular dynamics simulations.
#example of generating 50 points in a square of 4000x4000 and with minimum distance of 400
import numpy as np
import random as rnd
n_points=50
x,y = np.zeros(n_points),np.zeros(n_points)
x[0],y[0]=np.round(rnd.uniform(0,4000)),np.round(rnd.uniform(0,4000))
min_distances=[]
i=1
while i<n_points :
x_temp,y_temp=np.round(rnd.uniform(0,4000)),np.round(rnd.uniform(0,4000))
distances = []
for j in range(0,i):
distances.append(np.sqrt((x_temp-x[j])**2+(y_temp-y[j])**2))
min_distance = np.min(distances)
if min_distance>400 :
min_distances.append(min_distance)
x[i]=x_temp
y[i]=y_temp
i = i+1
print(x,y)
I need to fit several thousand 2D gaussian functions to star profiles (14x14 pixel blocks) on CCD image and get centroid coordinates, FWHM over long and short axes and angle of rotation of the long axis. The problem is that my current code takes too long to execute. Several 10s of seconds on i7 processor and I need it to make much faster. Preferably as fast as possible. I tested several gaussian fitting functions and it appears that the one used in AsPyLib is the fastest http://www.aspylib.com/doc/aspylib_fitting.html
Below is the code that I'm trying to make run faster. Profiling showed that most of the time is spent inside mplfit function.So my question is if this can be accelerated? I tried cythonizing the code but it provided really minor boost. Calculating moments (10x faster) is not suitable for many images that I have due to noise issues which make estimates unreliable. And probably due to the fact that star profiles are often far from being gaussian due to aberrations.
Multiprocessing wasn't a solution either as new process creation overhead was too high for fitting just 1 star profile.
Any ideas where to look further?
import numpy as np
from scipy.optimize import leastsq
def fit_gauss_elliptical(xy, data):
"""
---------------------
Purpose
Fitting a star with a 2D elliptical gaussian PSF.
---------------------
Inputs
* xy (list) = list with the form [x,y] where x and y are the integer positions in the complete image of the first pixel (the one with x=0 and y=0) of the small subimage that is used for fitting.
* data (2D Numpy array) = small subimage, obtained from the full FITS image by slicing. It must contain a single object : the star to be fitted, placed approximately at the center.
---------------------
Output (list) = list with 8 elements, in the form [maxi, floor, height, mean_x, mean_y, fwhm_small, fwhm_large, angle]. The list elements are respectively:
- maxi is the value of the star maximum signal,
- floor is the level of the sky background (fit result),
- height is the PSF amplitude (fit result),
- mean_x and mean_y are the star centroid x and y positions, on the full image (fit results),
- fwhm_small is the smallest full width half maximum of the elliptical gaussian PSF (fit result) in pixels
- fwhm_large is the largest full width half maximum of the elliptical gaussian PSF (fit result) in pixels
- angle is the angular direction of the largest fwhm, measured clockwise starting from the vertical direction (fit result) and expressed in degrees. The direction of the smallest fwhm is obtained by adding 90 deg to angle.
---------------------
"""
#find starting values
dat=data.flatten()
maxi = data.max()
floor = np.ma.median(dat)
height = maxi - floor
if height==0.0: #if star is saturated it could be that median value is 32767 or 65535 --> height=0
floor = np.mean(dat)
height = maxi - floor
mean_x = (np.shape(data)[0]-1)/2
mean_y = (np.shape(data)[1]-1)/2
fwhm = np.sqrt(np.sum((data>floor+height/2.).flatten()))
fwhm_1 = fwhm
fwhm_2 = fwhm
sig_1 = fwhm_1 / (2.*np.sqrt(2.*np.log(2.)))
sig_2 = fwhm_2 / (2.*np.sqrt(2.*np.log(2.)))
angle = 0.
p0 = floor, height, mean_x, mean_y, sig_1, sig_2, angle
#---------------------------------------------------------------------------------
#fitting gaussian
def gauss(floor, height, mean_x, mean_y, sig_1, sig_2, angle):
A = (np.cos(angle)/sig_1)**2. + (np.sin(angle)/sig_2)**2.
B = (np.sin(angle)/sig_1)**2. + (np.cos(angle)/sig_2)**2.
C = 2.0*np.sin(angle)*np.cos(angle)*(1./(sig_1**2.)-1./(sig_2**2.))
#do not forget factor 0.5 in exp(-0.5*r**2./sig**2.)
return lambda x,y: floor + height*np.exp(-0.5*(A*((x-mean_x)**2)+B*((y-mean_y)**2)+C*(x-mean_x)*(y-mean_y)))
def err(p,data):
return np.ravel(gauss(*p)(*np.indices(data.shape))-data)
p = leastsq(err, p0, args=(data), maxfev=200)
p = p[0]
#---------------------------------------------------------------------------------
#formatting results
floor = p[0]
height = p[1]
mean_x = p[2] + xy[0]
mean_y = p[3] + xy[1]
#angle gives the direction of the p[4]=sig_1 axis, starting from x (vertical) axis, clockwise in direction of y (horizontal) axis
if np.abs(p[4])>np.abs(p[5]):
fwhm_large = np.abs(p[4]) * (2.*np.sqrt(2.*np.log(2.)))
fwhm_small = np.abs(p[5]) * (2.*np.sqrt(2.*np.log(2.)))
angle = np.arctan(np.tan(p[6]))
else: #then sig_1 is the smallest : we want angle to point to sig_y, the largest
fwhm_large = np.abs(p[5]) * (2.*np.sqrt(2.*np.log(2.)))
fwhm_small = np.abs(p[4]) * (2.*np.sqrt(2.*np.log(2.)))
angle = np.arctan(np.tan(p[6]+np.pi/2.))
output = [maxi, floor, height, mean_x, mean_y, fwhm_small, fwhm_large, angle]
return output
I have come across this method before but not implemented it:
http://www.nature.com/nmeth/journal/v9/n7/full/nmeth.2071.html
Might be worth a look as a short-cut method. There is even code to copy on his website http://physics-server.uoregon.edu/~raghu/particle_tracking.html