1

我已经仔细阅读了笨拙的 1 存储库中的文档和演示笔记本(我完全有可能错过了一些明显的东西),但是我误入了陌生的领域,希望得到一些帮助。

假设我在极坐标系中有点,我使用尴尬1 库将这些点作为记录数组提供给用户。一些用户可能更喜欢使用笛卡尔坐标系中的点,因此我可以通过添加行为来适应它们,以下示例有效。

import awkward1 as ak
import numpy as np


class Polar2Cartesian(object):
    """Mixin class to convert from polar to Cartesian."""
    @property
    def x(self):
        return self.r * np.cos(self.theta)

    # And similarly for y, but this is just an example


# Register the behaviors with awkward
class Point(ak.Record, Polar2Cartesian):
    pass

class PointArray(ak.Array, Polar2Cartesian):
    pass

ak.behavior['Point'] = Point
ak.behavior['*', 'Point'] = PointArray

# Define the points
r = np.array([2.53, 0.29, 3.18])
theta = np.array([np.pi/4, np.pi, -np.pi/3])
points = ak.zip({'r': r, 'theta': theta}, with_name='Point')

# x-component of the first point
points[0].x == r[0] * np.cos(theta[0]) # True

# x-components of all points
points.x == r * np.cos(theta) # <Array [True, True, True] type='3 * bool'>

现在假设转换必须使用 Numba 编译的函数。我在以下示例中定义了一个,但原则上它可能来自我无法控制的第三方库。以下适用于单个记录,但会在记录数组上引发 TypingError。

import awkward1 as ak
import numba as nb
import numpy as np


@nb.njit
def cos(x):
    """A contrived example appears."""
    return np.cos(x)

class Polar2Cartesian(object):
    """Mixin class to convert from polar to Cartesian."""
    @property
    def x(self):
        return self.r * cos(self.theta) # uses jitted function here

    # And similarly for y, but this is just an example

# Define and register the behaviors like before, and create
# the same array of Points as in the previous example

# This still works
points[0].x == r[0] * np.cos(theta[0]) # True

# This now raises a TypingError
points.x == r * np.cos(theta)

解析回溯揭示了 TypingError 的原因:

TypingError: can't resolve ufunc cos for types (awkward1.ArrayView(awkward1.NumpyArrayType(array(float64, 1d, A), none, {}), None, ()),)

这是公平的,因为期望 Numba 在没有开发人员帮助的情况下知道如何使用这种类型是不合理的。

我发现的一种解决方法是np.asarray()在 的定义内调用Polar2Cartesian.x,即cos(np.asarray(self.theta))。虽然cos返回一个 NumPy 数组,Polar2Cartesian.x但由于随后与self.r. 一般来说,可以根据需要将返回值转换为不合适的记录或数组。

但是这个解决方案是“awkward1-approved”,还是我应该走我为 theta 和 x 提供 typer 和 lower 函数作为附加行为的路线?如果是后者,有人可以指导我如何正确编写 typer 和 lower 函数吗?

在这一点上,我想知道我的问题标题的范围是否过于广泛。如果有人有更好的建议,请告诉我。

4

0 回答 0