[Pyrex] Access to nested structures and arrays
Pierre GM
pgmdevlist at gmail.com
Mon Mar 19 23:25:56 UTC 2007
On Monday 19 March 2007 18:50:47 Greg Ewing wrote:
> Can you post the whole code? I suspect what you're actually
> using doesn't match the snippet above, since with modelflags
> declared as you claim, you shouldn't have got that message.
Indeed. On top of the typos, the snippet was slightly outdated.
Here's a heavily edited excerpt of the .pxd
cdef extern from "loess.h":
ctypedef struct c_loess_model "loess_model":
int parametric[8]
ctypedef struct c_loess "loess":
c_loess_model model
#############################
Now, the .pyx, also edited
######---------------------------------------------------------------------------
##---- ---- loess model ---
######---------------------------------------------------------------------------
cdef class loess_model:
cdef c_loess.c_loess_model *_base
cdef long npar
#.........
cdef setup(self, c_loess.c_loess_model *base, long npar):
self._base = base
self.npar = npar
#.........
property parametric_flags:
def __get__(self):
return boolarray_from_data(self.npar, 1, self._base.parametric)
def __set__(self, paramf):
cdef ndarray p_ndr
cdef int i
p_ndr = numpy.atleast_1d(narray(paramf, copy=False, subok=True,
dtype=numpy.bool))
for i from 0 <= i < min(self.npar, p_ndr.size):
self._base.parametric[i] = p_ndr[i]
#........
def update(self, **modelargs):
...
parametric = modelargs.get('parametric', None)
if parametric is not None:
self.parametric_flags = parametric
#####---------------------------------------------------------------------------
#---- ---- loess base class ---
#####---------------------------------------------------------------------------
cdef class loess:
cdef c_loess.c_loess _base
....
cdef readonly loess_model model
...
def __init__(self, object x, object y, object weights=None, **options):
#
...
# Initialization ..............
c_loess.loess_setup(x_dat, y_dat, n, p, &self._base)
#
self.model = loess_model()
self.model.setup(&self._base.model, p)
# Process options .............
modelopt = {}
for (k,v) in options.iteritems():
if k in ('family', 'span', 'degree', 'normalize',
'parametric', 'drop_square',):
modelopt[k] = v
self.model.update(**modelopt)
###############################
Note that here, I use paremeter_flags as a property. That way, I can read it,
and write to it en masse.
Now, I'd like to be able to write parameter_flags element-wise.
My idea was then to define an extension
class modelflags:
cdef int c_list[8]
def __init__(self):
cdef int i
self.str_list = [False] * 8
for i from 0 <= i <8:
self.c_list = 0
def __getitem__(self, idx):
return self.str_list[idx]
def __setitem__(self, idx, val):
self.c_list[idx] = tmpval
self.str_list[idx] = bool(val)
def __str__(self):
return str(self.str_list)
And define "parameter_flags" as a "model flag" instance. The pb I have is that
if I don't precise that "parameter_flags" should have the type "modelflags"
in the definition of "loess_model", the following code
cdef setup(self, c_loess.c_loess_model *base, long npar):
self._base = base
self.npar = npar
self.parameter_flags = modelflags()
self.parameter_flags.c_list = base.parametric
fails with an "AttributeError, parameter_flags has no attribute cflags". If I
do force
"cdef modelflags parameter_flags"
in the definition of loess_model, the attribute can no longer be accessed from
python. And I can't set it to public as it's a non-generic one.
So I'm stuck. I realize that not being able to directly write from python to a
ndarray is a big limitation. Reading is fine with readonly or a property, the
writing part is trickier.
Once again, sorry for the length, and thanks a lot for your comments
P.
More information about the Pyrex
mailing list