繁体   English   中英

根据从极坐标到笛卡尔坐标的变换重新排列二维数组中的数据

[英]Rearrange data in two-dimensional array according to transformation from polar to Cartesian coordinates

我有一个二维数组,表示极坐标系中位置处的函数值。 例如:

import numpy as np

radius = np.linspace(0, 1, 50)
angle = np.linspace(0, 2*np.pi, radius.size)
r_grid, a_grid = np.meshgrid(radius, angle)
data = np.sqrt((r_grid/radius.max())**2
               + (a_grid/angle.max())**2)

这里的data排列在与极坐标相对应的矩形网格中。 我想重新排列数组中的数据,使轴代表相应的笛卡尔坐标系。 旧版与新版布局的可视化如下:

import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=plt.figaspect(0.5))
ax1.set(title='Polar coordinates', xlabel='Radius', ylabel='Angle')
ax1.pcolormesh(r_grid, a_grid, data)
ax2.set(title='Cartesian coordinates', xlabel='X', ylabel='Y')
x_grid = r_grid * np.cos(a_grid)
y_grid = r_grid * np.sin(a_grid)
ax2.pcolormesh(x_grid, y_grid, data)

例子

这里明确给出了坐标,并相应地调整了绘图。 我希望将数据重新排列在数据数组本身中。 它应该包含所有值,可选择用零填充以适应形状(类似于scipy.ndimage.rotate(..., reshape=True) )。

如果我手动遍历极坐标数组来计算笛卡尔坐标,结果包含理想情况下也应该填充的空白区域:

new = np.zeros_like(data)
visits = np.zeros_like(new)
for r, a, d in np.nditer((r_grid, a_grid, data)):
    i = 0.5 * (1 + r * np.sin(a)) * new.shape[0]
    j = 0.5 * (1 + r * np.cos(a)) * new.shape[1]
    i = min(int(i), new.shape[0] - 1)
    j = min(int(j), new.shape[1] - 1)
    new[i, j] += d
    visits[i, j] += 1
new /= np.maximum(visits, 1)
ax2.imshow(new, origin='lower')

示例尝试

有没有办法实现转换,同时避免结果数据数组中的空白区域?

tl;dr:不,不改变您的问题的某些条件。

您看到的人工制品是转换的属性。 这不是因为所有半径的角度分辨率都是固定的。 因此,这不是由于转换的错误或错误实施造成的。 笛卡尔网格仅意味着在这些区域具有更高的特殊分辨率,因为存在来自极坐标图的已解析点。

  • 处理这个问题的唯一“干净”方法(我现在能想到的)是在极坐标中有一个可调整的分辨率来解释 1/r 缩放。 (如果你输入数据允许的话)

  • 一种在没有间隙的情况下将其可视化的有点作弊的方法是将它们随机分布在间隙上。 这里的论点是,您无法决定从哪个 bin 开始。 因此,您可以将它们随机地放在一个可能是可能起源的地方,而不是将它们全部放在同一个中(就像您现在所做的那样)。 但是,我想劝阻这种强硬。 它只是给你一个更漂亮的情节。 请注意,这在某种程度上等同于您问题中右上图的行为。

这并没有真正给出预期的结果,但也许会帮助你在一些需要的更正后找到解决方案......


import numpy as np

radius = np.linspace(0, 1, 50)
angle = np.linspace(0, 2*np.pi, radius.size)
r_grid, a_grid = np.meshgrid(radius, angle)
data = np.sqrt((r_grid/radius.max())**2
               + (a_grid/angle.max())**2)


def polar_to_cartesian(data):
    new = np.zeros_like(data) * np.nan
    x = np.linspace(-1, 1, new.shape[1])
    y = np.linspace(-1, 1, new.shape[0])
    for i in range(new.shape[0]):
        for j in range(new.shape[1]):
            x0, y0 = x[j], y[i]
            r, a = np.sqrt(x0**2 + y0**2), np.arctan2(y0, x0)
            data_i = np.argmin(np.abs(a_grid[:, 0] - a))
            data_j = np.argmin(np.abs(r_grid[0, :] - r))
            val = data[data_i, data_j]

            if r <= 1:
                new[i, j] = val

    return new

new = polar_to_cartesian(data)
fig, ax = plt.subplots()
ax.imshow(new, origin='lower')

在此处输入图片说明

编辑:根据 OP 的建议使用np.arctan2修改。

您可以遍历笛卡尔数组,将每个网格点转换为极坐标,并通过从极坐标网格数据进行插值来逼近函数值。 不过,由于缺乏足够接近的数据,您可能仍希望将角区域留空。

我认为没有更好的方法,除非您当然可以访问原始功能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM