【问题标题】:Creating a 2D Gaussian random field from a given 2D variance从给定的 2D 方差创建 2D 高斯随机场
【发布时间】:2020-01-13 08:34:53
【问题描述】:

我一直在尝试使用我计算的方差创建物质斑点(高斯随机场)的 2D 地图。这个方差是一个二维数组。我尝试使用 numpy.random.normal 因为它允许方差的 2D 输入,但它并没有真正创建具有我期望输入参数的趋势的地图。重要的输入常量之一 lambda_c 应该表现为 blob 的物理大小(直径)。但是,当我更改我的 lambda_c 时,blob 的大小根本不会改变。例如,如果我设置 lambda_c = 40 秒差距,则地图需要直径为 40 秒差距的 blob。使用我的方差生成地图的 MWE:

import numpy as np
import random
import matplotlib.pyplot as plt
from matplotlib.pyplot import show, plot
import scipy.integrate as integrate
from scipy.interpolate import RectBivariateSpline



n = 300
c = 3e8
G = 6.67e-11
M_sun = 1.989e30
pc = 3.086e16  # parsec
Dds = 1097.07889283e6*pc 
Ds = 1726.62069147e6*pc
Dd = 1259e6*pc

FOV_arcsec_original = 5.
FOV_arcmin = FOV_arcsec_original/60.   


pix2rad = ((FOV_arcmin/60.)/float(n))*np.pi/180.
rad2pix = 1./pix2rad

x_pix = np.linspace(-FOV_arcsec_original/2/pix2rad/180.*np.pi/3600.,FOV_arcsec_original/2/pix2rad/180.*np.pi/3600.,n)
y_pix = np.linspace(-FOV_arcsec_original/2/pix2rad/180.*np.pi/3600.,FOV_arcsec_original/2/pix2rad/180.*np.pi/3600.,n)
X_pix,Y_pix = np.meshgrid(x_pix,y_pix)

conc = 10.
M = 1e13*M_sun
r_s = 18*1e3*pc

lambda_c = 40*pc  ### The important parameter that doesn't seem to manifest itself in the map when changed

rho_s = M/((4*np.pi*r_s**3)*(np.log(1+conc) - (conc/(1+conc)))) 
sigma_crit = (c**2*Ds)/(4*np.pi*G*Dd*Dds)
k_s = rho_s*r_s/sigma_crit
theta_s = r_s/Dd
Renorm = (4*G/c**2)*(Dds/(Dd*Ds))
#### Here I just interpolate and zoom into my field of view to get better resolutions
A = np.sqrt(X_pix**2 + Y_pix**2)*pix2rad/theta_s



A_1 = A[100:200,0:100]

n_x = n_y = 100

FOV_arcsec_x = FOV_arcsec_original*(100./300)
FOV_arcmin_x = FOV_arcsec_x/60.   
pix2rad_x = ((FOV_arcmin_x/60.)/float(n_x))*np.pi/180.
rad2pix_x = 1./pix2rad_x

FOV_arcsec_y = FOV_arcsec_original*(100./300)
FOV_arcmin_y = FOV_arcsec_y/60.   
pix2rad_y = ((FOV_arcmin_y/60.)/float(n_y))*np.pi/180.
rad2pix_y = 1./pix2rad_y

x1 = np.linspace(-FOV_arcsec_x/2/pix2rad_x/180.*np.pi/3600.,FOV_arcsec_x/2/pix2rad_x/180.*np.pi/3600.,n_x)
y1 = np.linspace(-FOV_arcsec_y/2/pix2rad_y/180.*np.pi/3600.,FOV_arcsec_y/2/pix2rad_y/180.*np.pi/3600.,n_y)
X1,Y1 = np.meshgrid(x1,y1)



n_x_2 = 500
n_y_2 = 500


x2 = np.linspace(-FOV_arcsec_x/2/pix2rad_x/180.*np.pi/3600.,FOV_arcsec_x/2/pix2rad_x/180.*np.pi/3600.,n_x_2)
y2 = np.linspace(-FOV_arcsec_y/2/pix2rad_y/180.*np.pi/3600.,FOV_arcsec_y/2/pix2rad_y/180.*np.pi/3600.,n_y_2)
X2,Y2 = np.meshgrid(x2,y2)

interp_spline = RectBivariateSpline(y1,x1,A_1)

A_2 = interp_spline(y2,x2)



A_3 = A_2[50:450,0:400]

n_x_3 = n_y_3 = 400

FOV_arcsec_x = FOV_arcsec_original*(100./300)*400./500.
FOV_arcmin_x = FOV_arcsec_x/60.   
pix2rad_x = ((FOV_arcmin_x/60.)/float(n_x_3))*np.pi/180.
rad2pix_x = 1./pix2rad_x

FOV_arcsec_y = FOV_arcsec_original*(100./300)*400./500.
FOV_arcmin_y = FOV_arcsec_y/60.   
pix2rad_y = ((FOV_arcmin_y/60.)/float(n_y_3))*np.pi/180.
rad2pix_y = 1./pix2rad_y

x3 = np.linspace(-FOV_arcsec_x/2/pix2rad_x/180.*np.pi/3600.,FOV_arcsec_x/2/pix2rad_x/180.*np.pi/3600.,n_x_3)
y3 = np.linspace(-FOV_arcsec_y/2/pix2rad_y/180.*np.pi/3600.,FOV_arcsec_y/2/pix2rad_y/180.*np.pi/3600.,n_y_3)
X3,Y3 = np.meshgrid(x3,y3)

n_x_4 = 1000
n_y_4 = 1000


x4 = np.linspace(-FOV_arcsec_x/2/pix2rad_x/180.*np.pi/3600.,FOV_arcsec_x/2/pix2rad_x/180.*np.pi/3600.,n_x_4)
y4 = np.linspace(-FOV_arcsec_y/2/pix2rad_y/180.*np.pi/3600.,FOV_arcsec_y/2/pix2rad_y/180.*np.pi/3600.,n_y_4)
X4,Y4 = np.meshgrid(x4,y4)

interp_spline = RectBivariateSpline(y3,x3,A_3)

A_4 = interp_spline(y4,x4)

############### Function to calculate variance

variance = np.zeros((len(A_4),len(A_4)))



def variance_fluctuations(x):
    for i in xrange(len(x)):
        for j in xrange(len(x)):
            if x[j][i] < 1.:
                variance[j][i] = (k_s**2)*(lambda_c/r_s)*((np.pi/x[j][i]) - (1./(x[j][i]**2 -1)**3.)*(((6.*x[j][i]**4. - 17.*x[j][i]**2. + 26)/3.)+ (((2.*x[j][i]**6. - 7.*x[j][i]**4. + 8.*x[j][i]**2. - 8)*np.arccosh(1./x[j][i]))/(np.sqrt(1-x[j][i]**2.)))))
            elif x[j][i] > 1.:
                variance[j][i] = (k_s**2)*(lambda_c/r_s)*((np.pi/x[j][i]) - (1./(x[j][i]**2 -1)**3.)*(((6.*x[j][i]**4. - 17.*x[j][i]**2. + 26)/3.)+ (((2.*x[j][i]**6. - 7.*x[j][i]**4. + 8.*x[j][i]**2. - 8)*np.arccos(1./x[j][i]))/(np.sqrt(x[j][i]**2.-1)))))



variance_fluctuations(A_4)

#### Creating the map 

mean = 0

delta_kappa = np.random.normal(0,variance,A_4.shape)  

xfinal = np.linspace(-FOV_arcsec_x*np.pi/180./3600.*Dd/pc/2,FOV_arcsec_x*np.pi/180./3600.*Dd/pc/2,1000)
yfinal = np.linspace(-FOV_arcsec_x*np.pi/180./3600.*Dd/pc/2,FOV_arcsec_x*np.pi/180./3600.*Dd/pc/2,1000)

Xfinal, Yfinal = np.meshgrid(xfinal,yfinal)
plt.contourf(Xfinal,Yfinal,delta_kappa,100)
plt.show()

地图看起来像这样,斑点的密度向右增加。但是,无论我使用 lambda_c = 40*pc 还是 lambda_c = 400*pc,blob 的大小都不会改变,并且地图看起来几乎相同。

我想知道 np.random.normal 函数是否真的没有按照我的预期做?我觉得地图的像素比例和绘制样本的方式与斑点的大小无关。也许有更好的方法来使用方差创建地图,不胜感激。

我希望地图看起来像这样,blob 大小会根据我的方差的输入参数而变化:

【问题讨论】:

  • 您的代码正在绘制具有随机级别而不是 blob 的点。我会尽快发送一个带有 blob 的示例...
  • 谢谢,等着看你的例子,我只需要它们遵循我根据比例和幅度计算的方差(因为这是控制高斯的仅有的两个参数)跨度>
  • 很想知道哪个望远镜:)
  • 你把 blob 放在哪里?
  • @jtlz2 这是一个模拟,而不是来自望远镜的数据:D 它应该是一个高斯随机场,所以斑点会随机放置

标签: python numpy variance markov-random-fields


【解决方案1】:

这是天文学和宇宙学中(令人惊讶的惊喜)中相当受欢迎的问题。

您可以使用 lenstool:https://lenstools.readthedocs.io/en/latest/examples/gaussian_random_field.html

你也可以在这里试试:

https://andrewwalker.github.io/statefultransitions/post/gaussian-fields

更不用说:

https://github.com/bsciolla/gaussian-random-fields

我不会在这里复制代码,因为所有功劳都归功于上述作者。然而,他们确实都是通过谷歌搜索出来的:/

最简单的可能是一个 python 模块 FyeldGenerator,显然是为此目的而设计的:

https://github.com/cphyc/FyeldGenerator

所以(改编自 github 示例):

pip install FyeldGenerator
from FyeldGenerator import generate_field

from matplotlib import use
use('Agg')

import matplotlib.pyplot as plt
import numpy as np



plt.figure()

# Helper that generates power-law power spectrum
def Pkgen(n):
    def Pk(k):
        return np.power(k, -n)

    return Pk

# Draw samples from a normal distribution
def distrib(shape):
    a = np.random.normal(loc=0, scale=1, size=shape)
    b = np.random.normal(loc=0, scale=1, size=shape)
    return a + 1j * b


shape = (512, 512)

field = generate_field(distrib, Pkgen(2), shape)

plt.imshow(field, cmap='jet')

plt.savefig('field.png',dpi=400)
plt.close())

这给出了:

对我来说看起来很简单:)

PS:FoV 暗示了对高斯随机场的望远镜观察 :)

【讨论】:

  • 我已经尝试过这些软件包,但不幸的是它们需要功率谱,而且我遇到了差异。不知道如何翻译成这个。
【解决方案2】:

一种完全不同且更快的方法可能只是使用高斯滤波器模糊 delta_kappa 数组。尝试调整 sigma 参数以改变 blob 大小。

from scipy.ndimage.filters import gaussian_filter
dk_gf = gaussian_filter(delta_kappa, sigma=20)
Xfinal, Yfinal = np.meshgrid(xfinal,yfinal)
plt.contourf(Xfinal,Yfinal,dk_ma,100, cmap='jet')
plt.show();

这是sigma=20的图片

这是sigma=2.5的图片

【讨论】:

  • 这个解决方案对您有用吗?它有资格获得赏金吗?
  • 这看起来是个不错的方法!但是blob的大小需要根据sigma在这里手动输入,我在想blob的大小会固定在输入参数lambda_c上吗?不过,我可以尝试改进这种方法,谢谢
【解决方案3】:

ThunderFlash,试试这个代码来绘制地图:

# function to produce blobs:
from scipy.stats import multivariate_normal

def blob (positions, mean=(0,0),  var=1):
    cov = [[var,0],[0,var]]
    return multivariate_normal(mean, cov).pdf(positions)
    
"""
now prepare for blobs generation.
note that I use less dense grid to pick blobs centers (regulated by `step`)
this makes blobs more pronounced and saves calculation time.

use this part instead of your code section below comment #### Creating the map 
"""
delta_kappa = np.random.normal(0,variance,A_4.shape) # same
    
step = 10 # 
dk2 = delta_kappa[::step,::step] # taking every 10th element
x2, y2 = xfinal[::step],yfinal[::step]
field = np.dstack((Xfinal,Yfinal)) 
print (field.shape, dk2.shape, x2.shape, y2.shape)

>> (1000, 1000, 2), (100, 100), (100,), (100,)

result = np.zeros(field.shape[:2]) 

for x in range (len(x2)):
    for y in range (len(y2)):
        res2 = blob(field, mean = (x2[x], y2[y]), var=10000)*dk2[x,y]
        result += res2

# the cycle above took over 20 minutes on Ryzen 2700X. It could be accelerated by vectorization presumably.

plt.contourf(Xfinal,Yfinal,result,100)
plt.show()

您可能想在 blob() 中使用 var 参数来平滑图像,并使用 step 使其更加压缩。 这是我使用您的代码得到的图像(不知何故,轴被翻转,顶部的区域更密集):

【讨论】:

  • 感谢您的回复,我正在运行查看。我对如何创建 blob 以及在哪里指定 blob 的大小感到困惑?例如,就像我提到的,当您将 lambda_c 参数设置为更大/更小的数字时,blob 大小是否会相应改变?
  • 当给定点 (x,y) 处的 blob 乘以 dk2[x,y] 时指定 blob 的大小。它在双循环内。
猜你喜欢
  • 1970-01-01
  • 2014-10-10
  • 1970-01-01
  • 2021-06-14
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
  • 2012-10-17
  • 2013-02-20
相关资源
最近更新 更多