我正在编写到达探测器的光子的蒙特卡罗模拟。检测到的光子总数N_detected
遵循泊松分布(我使用scipy.stats.poisson
生成),每个单个光子的检测时间遵循给定的概率分布函数(PDF)。为了生成N_detected
光子的检测时间,我使用N_detected
函数生成介于0和1之间的numpy.random.random()
随机数,并使用Inverse Transform Method。
我必须多次运行模拟。因此,为了避免重复很多次,我想使用numpy数组一次进行每个模拟。最终的结果是,我想获得N_sim
列的2D数组,其中每一列都对应于不同的模拟并包含生成的检测时间。问题在于,每次模拟都会产生不同数量的光子(由于它是随机的),因此我找不到用不同长度的列创建2D阵列的方法。
我的一个想法是创建具有相同长度(最大N_deteceted
)的所有列,并用NaN
填充不需要的元素,其余的填充我需要的随机数,但是我不知道我可以做到这一点。
这是到目前为止我能做的最好的事情:
import numpy as np
import numpy.ma as ma
from scipy.stats import poisson
beta = 0.0048 # Parameter of the PDF
""" Inverse of the time CDF (needed for the Inverse transform method) """
def inverse_time_cdf(x):
return -np.log( (np.exp(-1000*beta)-1)*x + 1 )/beta
""" Simulation of N_sim experiments through the inverse transfrom method """
T = 1000 # Duration of the experiment [s]
rate = 3.945 # [events/s]
lam = rate*T # Poisson distribution parameter
def photon_arrival_simulation(N_sim):
N_detection = poisson.rvs(lam, size = N_sim) # Number of detections in each experiment
t = np.array([inverse_time_cdf(np.random.random(N)) for N in N_detection])
return N_detection, t
[如果可能,我想避免在photon_arrival_simulation()
函数的列表理解中使用循环,并且还获得2D数组而不是数组的数组(因为我无法进行数组操作,例如采用log
在一个数组中)。
我不知道该在此处还是在Physics Stack Exchange中发布此问题,但在此先感谢任何人。
我认为不可能在行中制作长度可变的随机数组以填充NaN值而不会在任何地方循环。但是这里是解决二维数组问题的方法,您有使用NaN的正确想法。我肯定会在屏蔽数组上使用NaN,因为屏蔽数组更多是为了方便而不是性能。另外,您还应该将文档字符串放在函数声明下方的适当位置。
def photon_arrival_simulation(N_sim):
"""Simulation of N_sim experiments through the inverse transform method"""
N_detection = poisson.rvs(lam, size=N_sim)
rand = np.random.random((len(N_detection), N_detection.max()))
for i, N in enumerate(N_detection):
rand[i, N:] = np.nan
t = inverse_time_cdf(rand)
return N_detection, t
我不确定我是否真的了解您要搜索的内容,但这可能会有所帮助...:
N_sim = 3
N_det_max = 5
a = np.zeros((N_det_max, N_sim))
a[:] = np.nan
b = [[1, 2, 3], [4, 5], [6, 7, 8, 9, 10]]
for i, l in enumerate(b):
a[:len(l), i] = l
print(a)
# [[ 1. 4. 6.]
# [ 2. 5. 7.]
# [ 3. nan 8.]
# [nan nan 9.]
# [nan nan 10.]]