Reputation: 630
I would like to write a function that returns an np.array
of size nx
x ny
that contains a centered gaussian distribution with mean mu
and sd sig
. The code below works in certain cases but in many not - what's wrong or what else should I write to get what I need?
import matplotlib.pyplot as plt
import numpy as np
def create2dGaussian(mu, sigma, nx, ny):
x, y = np.meshgrid(np.linspace(-nx / 2.0, +nx / 2.0, nx), np.linspace(-ny / 2.0, +ny / 2.0, ny))
d = np.sqrt(x * x + y * y)
g = np.exp(-((d - mu) ** 2 / (2.0 * sigma ** 2)))
# just for debugging:
np.set_printoptions(precision=1, suppress=True)
print(g.shape)
print(g)
plt.imshow(g, cmap='jet', interpolation='nearest')
plt.colorbar()
plt.show()
return g
Here are some test cases with comments:
from create2dGaussian import create2dGaussian
create2dGaussian(1, 10, 25, 25) # seems to work
create2dGaussian(1, 5, 25, 25) # the middle is not quite the peak anymore
create2dGaussian(1, 1, 25, 25) # the above problem more clearly visible
create2dGaussian(1, 1, 5, 5) # here it is extrem as the middle is now only 0.6
create2dGaussian(5, 10, 25, 25) # mean is still 1 and not 5
Upvotes: 2
Views: 346
Reputation: 1220
Your issue is that when creating your dataset, you are creating values that already have a mean and standard deviation. They are all at distance from each other implied by the nx, ny parameters. When you then apply the gaussian and provide a mean and standard deviation that is not the same as that of your dataset, it will show the actual mean of the dataset which is not in the center, as you specified it without looking at the data.
Take for example this case:
create2dGaussian(1, 1, 5, 5)
you tell it to have a mean of 1, but the center of the distribution is a 0.
import matplotlib.pyplot as plt
import numpy as np
def create2dGaussian(mu, sigma, nx, ny):
x, y = np.meshgrid(np.linspace(-nx / 2.0, +nx / 2.0, nx), np.linspace(-ny / 2.0, +ny / 2.0, ny))
d = np.sqrt(x * x + y * y)
g = mu * np.exp(-((d - mu) ** 2 / (2.0 * sigma ** 2)))
np.set_printoptions(precision=1, suppress=True)
print(("x", x))
print(("y", y))
print(("d", d))
plt.imshow(g, cmap='jet', interpolation='nearest')
plt.colorbar()
plt.show()
return g
#create2dGaussian(1, 10, 25, 25) # seems to work
#create2dGaussian(1, 5, 25, 25) # the middle is not quite the peak anymore
#create2dGaussian(1, 5, 25, 25) # the above problem more clearly visible
create2dGaussian(1, 1, 5, 5) # here it is extrem as the middle is now only 0.6
#create2dGaussian(5.0, 10.0, 25.0, 25.0) # mean is still 1 and not 5
Output:
('x', array([
[-2.5, -1.2, 0. , 1.2, 2.5],
[-2.5, -1.2, 0. , 1.2, 2.5],
[-2.5, -1.2, 0. , 1.2, 2.5],
[-2.5, -1.2, 0. , 1.2, 2.5],
[-2.5, -1.2, 0. , 1.2, 2.5]]))
('y', array([
[-2.5, -2.5, -2.5, -2.5, -2.5],
[-1.2, -1.2, -1.2, -1.2, -1.2],
[ 0. , 0. , 0. , 0. , 0. ],
[ 1.2, 1.2, 1.2, 1.2, 1.2],
[ 2.5, 2.5, 2.5, 2.5, 2.5]]))
('d', array([
[3.5, 2.8, 2.5, 2.8, 3.5],
[2.8, 1.8, 1.2, 1.8, 2.8],
[2.5, 1.2, 0. , 1.2, 2.5],
[2.8, 1.8, 1.2, 1.8, 2.8],
[3.5, 2.8, 2.5, 2.8, 3.5]]))
('g', array([
[0. , 0.2, 0.3, 0.2, 0. ],
[0.2, 0.7, 1. , 0.7, 0.2],
[0.3, 1. , 0.6, 1. , 0.3],
[0.2, 0.7, 1. , 0.7, 0.2],
[0. , 0.2, 0.3, 0.2, 0. ]]))
Upvotes: 1
Reputation: 165
There is a confusion with the mean in what you propose. In the 1D case, saying it is centered is exactly saying its mean is 0
. For a 2D gaussian there are so to speak two means, defined as the expectation of x
and of y
. Again saying it is centered is exactly saying they are both 0
.
To summarize, your density is not the density of a centered 2D gaussian, which should be
exp(-((x**2 +y**2) / (2.0 * sigma ** 2)))
If the gaussian is centered at (xm, ym)
then the density is
exp(-(((x-xm)**2 +(y-ym)**2) / (2.0 * sigma ** 2)))
But there is no such thing as a centered gaussian with mean mu
.
Upvotes: 2