Power spectrum with Cython

2024/10/1 15:32:02

I am trying to optimize my code with Cython. It is doing a a power spectrum, not using FFT, because this is what we were told to do in class. I've tried to write to code in Cython, but do not see any difference. Here is my code

#! /usr/bin/env python
# -*- coding: utf8 -*-from __future__ import division
cimport numpy as np
import numpy as np
cimport cython@cython.boundscheck(False)
def power_spectrum(time, data, double f_min, double f_max, double df,w=1 ):cdef double com,fcdef double s,c,sc,cc,sscdef np.ndarray[double, ndim=1] powercdef np.ndarray[double, ndim=1] freqalfa, beta = [],[] m = np.mean(data)data -= m       freq = np.arange( f_min,f_max,df )for f in freq:sft = np.sin(2*np.pi*f*time)cft = np.cos(2*np.pi*f*time)s   = np.sum( w*data*sft )c   = np.sum( w*data*cft )ss  = np.sum( w*sft**2  )cc  = np.sum( w*cft**2  )sc  = np.sum( w*sft*cft )alfa.append( ( s*cc-c*sc )/( ss*cc-sc**2 ))beta.append( ( c*ss-s*sc )/( ss*cc-sc**2 ))com = -(f-f_min)/(f_min-f_max)*100print "%0.3f%% complete" %compower = np.array(alfa)**2 + np.array(beta)**2return freq,power,alfa,beta

The time and data is loaded via numpy.loadtxt and sent to this function. When I do

cython -a power_spectrum.pyx

the .html file is very yellow, so not very efficient. Especially the entire for-loop and the calulation of power and returning everything.

I have tried to read the official guide to Cython, but as I have never coded in C it is somewhat hard to understand.

All help is very preciated :)

Answer

Cython can read numpy arrays according to this but it won't magically compile stuff like np.sum - you are still just calling the numpy methods.

What you need to do is re-write your inner loop in pure cython which can then compile it for you. So you will need to re-implement np.sum, np.sin etc. Pre-allocating aplfa and beta is a good idea so you don't use append and try to cdef as many variables as possible.

EDIT

Here is an complete example showing the inner loop completely C compiled (no yellow). I've no idea whether the code is correct but it should be a good starting point! In particular note use of cdef everywhere, turning on cdivision and import of sin and cos from the standard library.

from __future__ import division
cimport numpy as np
import numpy as np
cimport cython
from math import picdef extern from "math.h":double cos(double theta)double sin(double theta)@cython.boundscheck(False)
@cython.cdivision(True)
def power_spectrum(np.ndarray[double, ndim=1] time, np.ndarray[double, ndim=1] data, double f_min, double f_max, double df, double w=1 ):cdef double com,fcdef double s,c,sc,cc,ss,t,dcdef double twopi = 6.283185307179586cdef np.ndarray[double, ndim=1] powercdef np.ndarray[double, ndim=1] freq = np.arange( f_min,f_max,df )cdef int n = len(freq)cdef np.ndarray[double, ndim=1] alfa = np.zeros(n)cdef np.ndarray[double, ndim=1] beta = np.zeros(n)cdef int ndata = len(data)cdef int i, jm = np.mean(data)data -= m       for i in range(ndata):f = freq[i]s = 0.0c = 0.0ss = 0.0cc = 0.0sc = 0.0for j in range(n):t = time[j]d = data[j]sf = sin(twopi*f*t)cf = cos(twopi*f*t)s += w*d*sfc += w*d*cfss += w*sf**2cc += w*cf**2sc += w*sf*cfalfa[i] = ( s*cc-c*sc )/( ss*cc-sc**2 )beta[i] = ( c*ss-s*sc )/( ss*cc-sc**2 )power = np.array(alfa)**2 + np.array(beta)**2return freq,power,alfa,beta
https://en.xdnf.cn/q/70952.html

Related Q&A

Detect abbreviations in the text in python

I want to find abbreviations in the text and remove it. What I am currently doing is identifying consecutive capital letters and remove them.But I see that it does not remove abbreviations such as MOOC…

filtering of tweets received from statuses/filter (streaming API)

I have N different keywords that i am tracking (for sake of simplicity, let N=3). So in GET statuses/filter, I will give 3 keywords in the "track" argument.Now the tweets that i will be recei…

UndefinedError: current_user is undefined

I have a app with flask which works before But Now I use Blueprint in it and try to run it but got the error so i wonder that is the problem Blueprint that g.user Not working? and how can I fix it Thn…

Scipy filter with multi-dimensional (or non-scalar) output

Is there a filter similar to ndimages generic_filter that supports vector output? I did not manage to make scipy.ndimage.filters.generic_filter return more than a scalar. Uncomment the line in the cod…

How do I stop execution inside exec command in Python 3?

I have a following code:code = """ print("foo")if True: returnprint("bar") """exec(code) print(This should still be executed)If I run it I get:Tracebac…

sqlalchemy concurrency update issue

I have a table, jobs, with fields id, rank, and datetime started in a MySQL InnoDB database. Each time a process gets a job, it "checks out" that job be marking it started, so that no other p…

Python matplotlib: Change axis labels/legend from bold to regular weight

Im trying to make some publication-quality plots, but I have encountered a small problem. It seems by default that matplotlib axis labels and legend entries are weighted heavier than the axis tick mark…

Negative extra_requires in Python setup.py

Id like to make a Python package that installs a dependency by default unless the user specially signals they do not want that.Example:pip install package[no-django]Does current pip and setup.py mechan…

Get Type in Robot Framework

Could you tell me about how to get the variable type in Robot Framework.${ABC} Set Variable Test ${XYZ} Set Variable 1233Remark: Get the variable Type such as string, intget ${ABC} type = strin…

Keras 2, TypeError: cant pickle _thread.lock objects

I am using Keras to create an ANN and do a grid search on the network. I have encountered the following error while running the code below:model = KerasClassifier(build_fn=create_model(input_dim), verb…