Python 从给定的二维方差创建二维高斯随机场

Python 从给定的二维方差创建二维高斯随机场,python,numpy,variance,markov-random-fields,Python,Numpy,Variance,Markov Random Fields,我一直在尝试使用我计算的方差创建一个物质斑点(高斯随机场)的2D地图。该方差是一个二维数组。我尝试过使用numpy.random.normal,因为它允许方差的2D输入,但它并没有真正创建一个带有我期望的输入参数趋势的映射。一个重要的输入常数lambda_c应显示为水滴的物理尺寸(直径)。但是,当我更改lambda_c时,水滴的大小根本不会改变。例如,如果我设置lambda_c=40 parsecs,则贴图需要直径为40 parsecs的blob。使用我的方差生成地图的MWE: import n

我一直在尝试使用我计算的方差创建一个物质斑点(高斯随机场)的2D地图。该方差是一个二维数组。我尝试过使用numpy.random.normal,因为它允许方差的2D输入,但它并没有真正创建一个带有我期望的输入参数趋势的映射。一个重要的输入常数lambda_c应显示为水滴的物理尺寸(直径)。但是,当我更改lambda_c时,水滴的大小根本不会改变。例如,如果我设置lambda_c=40 parsecs,则贴图需要直径为40 parsecs的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()
将numpy导入为np
随机输入
将matplotlib.pyplot作为plt导入
从matplotlib.pyplot导入显示,打印
导入scipy.integrate作为integrate
从scipy.interpolate导入矩形二元样条线
n=300
c=3e8
G=6.67e-11
M_sun=1.989e30
pc=3.086e16#c
Dds=1097.07889283e6*pc
Ds=1726.62069147e6*pc
Dd=1259e6*pc
FOV_弧段_原始=5。
FOV_arcmin=FOV_arcsec_原件/60。
pix2rad=((视场弧分/60。)/float(n))*np.pi/180。
rad2pix=1./pix2rad
x_-pix=np.linspace(-FOV_-arcec_-original/2/pix2rad/180.*np.pi/3600.,FOV_-arcec_-original/2/pix2rad/180.*np.pi/3600.,n)
y_-pix=np.linspace(-FOV_-arcec_-original/2/pix2rad/180.*np.pi/3600.,FOV_-arcec_-original/2/pix2rad/180.*np.pi/3600.,n)
X_pix,Y_pix=np.meshgrid(X_pix,Y_pix)
浓度=10。
M=1e13*M_太阳
r_s=18*1e3*pc
lambda_c=40*pc####这是一个重要参数,在更改时似乎不会在映射中显示出来
rho_s=M/((4*np.pi*r_s**3)*(np.log(1+conc)-(conc/(1+conc)))
西格玛标准=(c**2*Ds)/(4*np.pi*G*Dd*Dds)
k_s=rho_s*r_s/sigma_临界值
θs=r\u s/Dd
雷诺数=(4*G/c**2)*(Dds/(Dd*Ds))
####在这里,我只是插值和放大我的视野,以获得更好的分辨率
A=np.sqrt(X_pix**2+Y_pix**2)*pix2rad/θs
A_1=A[100:200,0:100]
n_x=n_y=100
FOV_ARCEC_x=FOV_ARCEC_原件*(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_弧段_y=FOV_弧段_原件*(100./300)
FOV_arcmin_y=FOV_arcsec_y/60。
pix2rad_y=((视场角为60°)/float(n_y))*np.pi/180。
rad2pix_y=1./pix2rad_y
x1=np.linspace(-FOV_arcesec_x/2/pix2rad_x/180.*np.pi/3600.,FOV_arcesec_x/2/pix2rad_x/180.*np.pi/3600.,n_x)
y1=np.linspace(-FOV_arcec_y/2/pix2rad_y/180.*np.pi/3600.,FOV_arcec_y/2/pix2rad_y/180.*np.pi/3600.,n_y)
X1,Y1=np.网格(X1,Y1)
n_x_2=500
n_y_2=500
x2=np.linspace(-FOV_arcesec_x/2/pix2rad_x/180.*np.pi/3600.,FOV_arcesec_x/2/pix2rad_x/180.*np.pi/3600.,n_x_2)
y2=np.linspace(-FOV_arcec_y/2/pix2rad_y/180.*np.pi/3600.,FOV_arcec_y/2/pix2rad_y/180.*np.pi/3600.,n_y_2)
X2,Y2=np.网格(X2,Y2)
插值样条=矩形二元样条(y1,x1,A_1)
A_2=内部样条曲线(y2,x2)
A_3=A_2[50:450,0:400]
n_x_3=n_y_3=400
FOV_ARCEC_x=FOV_ARCEC_原件*(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_弧段_y=FOV_弧段_原件*(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_arcec_x/2/pix2rad_x/180.*np.pi/3600.,FOV_arcec_x/2/pix2rad_x/180.*np.pi/3600.,n_x_3)
y3=np.linspace(-FOV_arcec_y/2/pix2rad_y/180.*np.pi/3600.,FOV_arcec_y/2/pix2rad_y/180.*np.pi/3600.,n_y_3)
X3,Y3=np.网格(X3,Y3)
n_x_4=1000
n_y_4=1000
x4=np.linspace(-FOV_arcec_x/2/pix2rad_x/180.*np.pi/3600.,FOV_arcec_x/2/pix2rad_x/180.*np.pi/3600.,n_x_4)
y4=np.linspace(-FOV_arcec_y/2/pix2rad_y/180.*np.pi/3600.,FOV_arcec_y/2/pix2rad_y/180.*np.pi/3600.,n_y_4)
X4,Y4=np.网格(X4,Y4)
插值样条=矩形二元样条(y3,x3,A_3)
A_4=内部样条曲线(y4,x4)
###############用于计算方差的函数
方差=np.零((len(A_4),len(A_4)))
def方差_波动(x):
对于x范围内的i(len(x)):
对于x范围内的j(len(x)):
如果x[j][i]<1:
方差[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.*
elif x[j][i]>1:
方差[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 1.*
方差和波动(A和4)
####创建地图
平均值=0
delta_kappa=np.随机.正态(0,方差,A_4.形状)
xfinal=np.linspace(-FOV_arcec_x*np.pi/180./3600.*Dd/pc/2,FOV_arcec_x*np.pi/180./3600.*Dd/pc/21000)
yfinal=np.linspace(-FOV_arcec_x*np.pi/180./3600.*Dd/pc/2,FOV_arcec_x*np.pi/180./3600.*Dd/pc/21000)
Xfinal,Yfinal=np.meshgrid(Xfinal,Yfinal)
等高线平面图(Xfinal,Yfinal,delta_-kappa,100)
plt.show()

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

我想知道np.random.normal函数是否真的没有达到我期望的效果?我觉得地图的像素比例和样本的绘制方式与斑点的大小没有任何联系。也许有一个更好的方法来创建地图使用方差,如果有任何见解将不胜感激


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

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
使其更压缩。 这是我用yo得到的图像
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();
pip install FyeldGenerator