Extending np array using Cython with dictionary of np arrays as input

26 views
Skip to first unread message

Jessie van Schijndel

unread,
Apr 11, 2022, 10:32:48 AM4/11/22
to cython-users
I am trying to create a class which extends numpy arrays. It takes an argument S which is a dictionary whose keys are integers and values are numpy arrays. When I try to create an object from this class I get the following TypeError:

TypeError: expected sequence object with len >= 0 or a single integer

NewMatrix.pyx

import cython
import numpy as np
cimport numpy as cnp
from copy import copy
from libcpp.map cimport map


cdef class NewMatrix(cnp.ndarray):

cdef __new__(cls, map[int, float[:,:]] S):
shape = (S[0].shape[0], S[0].shape[1])
obj = np.ndarray.__new__(NewMatrix, shape=shape)
obj.S = S
return obj

example.py

from NewMatrix import NewMatrix
import numpy as np

S = {0: np.array([[1,1], [1,1]])}
print(S)
matrix = NewMatrix(S)
print(matrix.S)

setup.py

from setuptools import setup, find_packages, Extension
from Cython.Build import cythonize
import numpy

module = Extension('NewMatrix', sources=['NewMatrix.pyx'], language="c++")

setup(
name="example",
version="1.0",
packages=find_packages(),
url="",
license="",
author="",
author_email="",
description="",
ext_modules=cythonize(module),
#cmdclass = {'build_ext': build_ext},
include_dirs=[numpy.get_include()]
)



Stefan Behnel

unread,
Apr 15, 2022, 11:46:42 AM4/15/22
to cython...@googlegroups.com
Hi,

Jessie van Schijndel schrieb am 11.04.22 um 16:22:
> I am trying to create a class which extends numpy arrays. It takes an
> argument *S* which is a dictionary whose keys are integers and values are
> numpy arrays. When I try to create an object from this class I get the
> following TypeError:
>
> *TypeError: expected sequence object with len >= 0 or a single integer*
>
> *NewMatrix.pyx*
>
> import cython
> import numpy as np
> cimport numpy as cnp
> from copy import copy
> from libcpp.map cimport map
>
>
> cdef class NewMatrix(cnp.ndarray):
>
> cdef __new__(cls, map[int, float[:,:]] S):
> shape = (S[0].shape[0], S[0].shape[1])
> obj = np.ndarray.__new__(NewMatrix, shape=shape)
> obj.S = S
> return obj

I guess that your actual code is more complex than this example, but do you
really need to inherit from "ndarray" here? And if so, do you need to do it
in a Cython extension type, or would a Python subclass be ok for you? Maybe
you can use a factory function instead of a new constructor?

The reason why I'm asking (ok, apart from design and simplicity
considerations) is that the "__new__" special method (and especially
something like "cdef __new__") does not actually exist in Cython. It's a
relict that maps to "__cinit__" (which does something entirely different),
but it looks like we don't emit a warning for it. We should.


> *example.py*
>
> from NewMatrix import NewMatrix
> import numpy as np
>
> S = {0: np.array([[1,1], [1,1]])}
> print(S)
> matrix = NewMatrix(S)

I assume that this is where you get the exception. It's actually
interesting that you get this far. We should catch this earlier.

Stefan
Reply all
Reply to author
Forward
0 new messages