Cython: return double * heap array from cython function to python as a 1D np.ndarray

45 Views Asked by At

I am trying to generate time series noise. My noise array are ~350,000 in size so they must be heap allocated. How can I return my heap allocated array back to the python code that called the function when the function is called? I have tried converting it to a nd.array but python complains during compilation.

I am new to cython and would love a real explanation on how this works. Everything I find online is super convoluted and not beginner friendly.

Also, if anyone know how to replace the np.random.normal call for a cython version that would be great. I can't find anything on the internet that is not super complex for a simple gaussian random number generator.

Here is my pyx file:

import numpy as np
cimport numpy as np

from libc.stdlib cimport malloc, free



# TODO turn this into a cython script. Generate function is slow for 350,000 samples
cdef class NoiseGenerator():

    cdef double mean, std, tau, start_value, previous_value
    cdef double* noise


    def __cinit__(self, double mean=0.0, double std=1.0, float tau=0.2, float start_y=0):
        self.mean = mean
        self.std = std
        self.tau = tau
        self.start_value = start_y


    cdef double sample_next(NoiseGenerator self, double dx):

        cdef double red_noise, wnoise 

        if self.previous_value is None:
            red_noise = self.start_value

        else:
            wnoise = np.random.normal(loc=self.mean, scale=self.std, size=1)
            red_noise = ((self.tau/(self.tau + dx)) * (dx*wnoise + self.previous_value))

        self.previous_value = red_noise
        return red_noise


    cdef np.array generate(NoiseGenerator self, double dx, int samples):

        self.noise = <double *>malloc(samples * sizeof(double))

        for idx in range(samples):

            noise[idx] = self.sample_next(dx)

        return nd.array(self.noise)


    def __dealloc__(NoiseGenerator self):

        free(self.noise)

from a python script this is how I want to use it:

import numpy as np
import pyximport; pyximport.install(setup_args={'include_dirs': np.get_include()})
from CNoiseGenerator import NoiseGenerator


mean = -2.5914938426209425e-06
std=0.00024610271604726564
dx=0.0018104225094430712
samples=352036

noise = NoiseGenerator(mean, std).generate(dx, samples)

Any advice on how to refactor my class would be greatly appreciated. Again still learning here!

0

There are 0 best solutions below