我正在研究蒙特卡罗辐射传输代码,该代码模拟通过介质发射光子并对其随机行走进行统计建模。它一次慢慢地发射一个光子,所以我想对它进行矢量化并一次运行1000个光子。
我将我的平板分开,光子通过该平板进入光学深度nlayers
和0
之间的depth
切片。实际上,这意味着我有nlayers + 2
个区域(nlayers
加上板块上方的区域和板块下方的区域)。在每一步,我都要跟踪每个光子通过的层。
假设我已经知道两个光子从第0层开始。一个步骤结束,第二个结束,另一个步骤结束,第六层结束。这表示为数组pastpresent
看起来像这样:
[[ 0 2]
[ 0 6]]
我想生成一个数组traveled_through
,其中包含(nlayers + 2)
列和2行,描述光子i
是否通过了层j
(包含端点)。它看起来像这样(nlayers = 10
):
[[ 1 1 1 0 0 0 0 0 0 0 0 0]
[ 1 1 1 1 1 1 1 0 0 0 0 0]]
我可以通过迭代光子并单独生成traveled_through
的每一行来做到这一点,但这相当慢,并且有点击败了同时运行多个光子的点,所以我&#39 ;而不是那样做。
我尝试按如下方式定义数组:
traveled_through = np.zeros((2, nlayers)).astype(int)
traveled_through[ : , np.min(pastpresent, axis = 1) : np.max(pastpresent, axis = 1) + ] = 1
这个想法是,在一个给定的光子行中,从起始层到包括结束层的索引将被设置为1,其他所有其他值保持为0.但是,我得到以下错误:< / p>
traveled_through[ : , np.min(pastpresent, axis = 1) : np.max(pastpresent, axis = 1) + 1 ] = 1
IndexError: invalid slice
我最好的猜测是numpy不允许使用此方法对数组的不同行进行不同的索引。有没有人建议如何为任意数量的光子和任意数量的层生成traveled_through
?
答案 0 :(得分:2)
如果两个光子总是从0开始,你可以按如下方式构造你的数组。
首先设置变量......
>>> pastpresent = np.array([[0, 2], [0, 6]])
>>> nlayers = 10
...然后构建数组:
>>> (pastpresent[:,1][:,np.newaxis] + 1 > np.arange(nlayers+2)).astype(int)
array([[1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]])
或者光子是否有任意起始层:
>>> pastpresent2 = np.array([[1, 7], [3, 9]])
>>> (pastpresent2[:,0][:,np.newaxis] < np.arange(nlayers+2)) &
(pastpresent2[:,1][:,np.newaxis] + 1 > np.arange(nlayers+2)).astype(int)
array([[0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0]])
答案 1 :(得分:1)
我喜欢这种事情的一个小技巧涉及accumulate
ufunc的logical_xor
方法:
>>> a = np.zeros(10, dtype=int)
>>> b = [3, 7]
>>> a[b] = 1
>>> a
array([0, 0, 0, 1, 0, 0, 0, 1, 0, 0])
>>> np.logical_xor.accumulate(a, out=a)
array([0, 0, 0, 1, 1, 1, 1, 0, 0, 0])
请注意,这会将1
中的位置设置为b
,第一个包含索引,最后一个索引包含,因此您必须处理1个错误,具体取决于您的确切位置。
有几行,您可以将其设为:
>>> a = np.zeros((3, 10), dtype=int)
>>> b = np.array([[1, 7], [0, 4], [3, 8]])
>>> b[:, 1] += 1 # handle the off by 1 error
>>> a[np.arange(len(b))[:, None], b] = 1
>>> a
array([[0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
[1, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 1]])
>>> np.logical_xor.accumulate(a, axis=1, out=a)
array([[0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0]])