[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