0

我是 Python 新手,来自 MATLAB,很久以前来自 C。我在 MATLAB 中编写了一个脚本,将河流中的泥沙输送模拟为马尔可夫过程。该代码将随机直径的圆随机放置在指定尺寸的矩形区域内。圆圈的大小不均匀,是从指定的大小范围内随机绘制的。我不知道我会通过多少次循环放置操作,所以我使用一个while循环来完成这个过程。为了更加面向社区,我将 MATLAB 脚本翻译成 Python。我使用在线工具 OMPC 开始,并且一直在从自动翻译版本手动完成它(没有那么有用,这并不奇怪)。为了调试代码,我通常使用 MATLAB 生成的结果与 Python 中的结果进行比较和对比。我似乎很清楚,我声明变量的方式会在脚本中进行计算时引入问题。以下是不同代码执行实例之间存在一致性问题的两个示例。首先,代码生成了我认为是数组中的数组,因为脚本返回的结果如下所示:

  • 数组([[真] [假]],dtype = bool)

此结果是在overlap_logix 操作中为以下代码片段生成的:

CenterCoord_Array = np.asarray(CenterCoordinates)
Diameter_Array = np.asarray(Diameter)
dist_check = ((CenterCoord_Array[:,0] - x_Center) ** 2 + (CenterCoord_Array[:,1] - y_Center) ** 2) ** 0.5
radius_check = (Diameter_Array / 2) + radius
radius_check_update = np.reshape(radius_check,(len(radius_check),1))
radius_overlap = (radius_check_update >= dist_check)
    # Now actually check the overalp condition.
    if np.sum([radius_overlap]) == 0:
        # The new circle does not overlap so proceed.
        newCircle_Found = 1
        debug_value = 2
    elif np.sum([radius_overlap]) == 1:
        # The new circle overlaps with one other circle
        overlap = np.arange(0,len(radius_overlap), dtype=int)
        overlap_update = np.reshape(overlap,(len(overlap),1))
        overlap_logix = (radius_overlap == 1)
        idx_true = overlap_update[overlap_logix]
        radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)

对于变量,相同运行产生了类似的结果:

  • radius_check_update
  • 半径重叠
  • 重叠更新

这是工作 MATLAB 版本的相同代码片段(根据要求):

distcheck = ((Circles.CenterCoordinates(1,:)-x_Center).^2 +  (Circles.CenterCoordinates(2,:)-y_Center).^2).^0.5;
radius_check = (Circles.Diameter ./ 2) + radius;
radius_overlap = (radius_check >= distcheck);
    % Now actually check the overalp condition.
    if sum(radius_overlap) == 0
        % The new circle does not overlap so proceed.
        newCircle_Found = 1;
        debug_value = 2;
    elseif sum(radius_overlap) == 1
        % The new circle overlaps with one other circle
        temp = 1:size(radius_overlap,2);
        idx_true = temp(radius_overlap == 1);
        radius = distcheck(1,idx_true) - (Circles.Diameter(1,idx_true)/2);

在 Python 版本中,我从列表创建了数组,以便更轻松地对内容进行操作(代码片段的前两行)。数组结果中的数组和创建数组以访问数据向我表明我错误地声明了变量类型,但我不确定。此外,一些变量具有大小,例如 (2L,)(数字维度会随着圆圈的放置而变化),其中没有第二维度。当我尝试将该数组与另一个大小为 (2L,1L) 的数组一起使用时,这会产生明显的问题。由于这些问题,我开始重塑数组,然后我停止了,因为我认为这些是 hack,因为我错误地声明了一个或多个变量。其次,对于同一次运行,我遇到了以下错误:

  • TypeError:“numpy.ndarray”对象不可调用

对于操作:

radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)

它出现在上述代码片段的底部。我在以下链接中发布了整个脚本,因为为自己执行脚本可能更有用:

https://github.com/smchartrand/MarkovProcess_Bedload

我已经设置了代码以使用一些初始参数值运行,因此不需要做出决定;这些参数值在基于 MATLAB 的脚本中产生预期的结果,绘制时看起来像这样:在此处输入图像描述

所以,我似乎特别遇到了第 151-165 行的操作问题,具体取决于测试值np.sum([radius_overlap])我认为这是因为我错误地声明了变量类型,但我真的不确定。我可以自信地说,Python 版本和 MATLAB 版本通过 while 循环的第一步和进入 while 循环第二步的代码行 127 的输出是一致的。在代码中的这一点以下,上述记录的问题最终会导致脚本崩溃。有时脚本执行到 15% 完成,有时它没有达到 5% - 这是由于圆圈放置的随机性。我正在 Spyder (Python 2.7) IDE 中准备代码,并将作为我研究的一部分公开分享工作代码。我将非常感谢可以提供的任何帮助,以识别我在 python 编码实践中的错误和误用。

4

1 回答 1

0

我相信我已经回答了我自己的问题,也许它对以后的人有用。对我来说,主要的指导来源可以在以下三个网页上找到:

Stackoverflow 问题 176011

SciPy 常见问题解答

面向 Matlab 用户的 SciPy NumPy

第三个网页对我来自 MATLAB 非常有帮助。这是与上面提供的原始代码段相关的修改和工作的 Python 代码段:

dist_check = ((CenterCoordinates[0,:] - x_Center) ** 2 + (CenterCoordinates[1,:] - y_Center) ** 2) ** 0.5
radius_check = (Diameter / 2) + radius
radius_overlap = (radius_check >= dist_check)
# Now actually check the overalp condition.
if np.sum([radius_overlap]) == 0:
    # The new circle does not overlap so proceed.
    newCircle_Found = 1
    debug_value = 2
elif np.sum([radius_overlap]) == 1:
    # The new circle overlaps with one other circle
    overlap = np.arange(0,len(radius_overlap[0]), dtype=int).reshape(1, len(radius_overlap[0]))
    overlap_logix = (radius_overlap == 1)
    idx_true = overlap[overlap_logix]
    radius = dist_check[idx_true] - (Diameter[0,idx_true] / 2)

最后,我很清楚,对于这个示例来说,使用 numpy 数组与列表来存储填充矩形区域的每次迭代的结果更简单。对于更正的代码片段,这意味着我初始化了变量:

  • 中心坐标和
  • 直径

作为 numpy 数组,而我在发布的问题中将它们初始化为列表。这使得一些数学运算更加简单。我也错误地使用括号 () 索引变量,而不是使用括号 [] 的正确方法。这是我所做的一个更正示例,它帮助代码按预期执行:

  • 不正确:半径 = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)
  • 正确:radius = dist_check[idx_true] - (Diameter[0,idx_true] / 2)

此示例还表明我遇到了数组维度的问题,我逐个变量地纠正了这些问题。我仍然不确定我的工作代码是否是以随机方式填充矩形区域的最 Pythonic 或最有效的方法,但我已经成功测试了大约 100 次。修改后的工作代码可以在这里下载:

使用 Python 脚本随机填充圆的矩形区域

这是成功运行工作代码的最终结果的图像:

在此处输入图像描述

对我来说主要的教训是(1)numpy 数组对于重复数值计算更有效,(2)我创建的数组的维数并不总是我期望的那样,在建立数组时必须小心。感谢那些查看我的问题并要求澄清的人。

于 2018-05-29T17:10:13.213 回答