Changed Fft API to also be able to compute for one channel
This commit is contained in:
parent
63b45d8dfe
commit
85636ce946
@ -164,7 +164,7 @@ cmat* AvPowerSpectra_addTimeData(AvPowerSpectra* aps,
|
||||
|
||||
const us oo = aps->oo;
|
||||
us* os = &aps->os;
|
||||
iVARTRACE(15,*os);
|
||||
|
||||
us os_timedata = 0;
|
||||
|
||||
dmat buffer = aps->buffer;
|
||||
|
@ -483,7 +483,7 @@ static inline cmat cmat_submat(cmat* parent,
|
||||
* @param to : Vector to write to
|
||||
* @param from : Vector to read from
|
||||
*/
|
||||
static inline void vd_copy(vd* to,vd* from) {
|
||||
static inline void vd_copy(vd* to,const vd* from) {
|
||||
dbgassert(to && from,NULLPTRDEREF);
|
||||
dbgassert(to->size==from->size,SIZEINEQUAL);
|
||||
d_copy(to->ptr,from->ptr,to->size);
|
||||
@ -494,7 +494,7 @@ static inline void vd_copy(vd* to,vd* from) {
|
||||
* @param to : Vector to write to
|
||||
* @param from : Vector to read from
|
||||
*/
|
||||
static inline void vc_copy(vc* to,vc* from) {
|
||||
static inline void vc_copy(vc* to,const vc* from) {
|
||||
dbgassert(to && from,NULLPTRDEREF);
|
||||
dbgassert(to->size==from->size,SIZEINEQUAL);
|
||||
c_copy(to->ptr,from->ptr,to->size);
|
||||
|
@ -13,19 +13,12 @@
|
||||
|
||||
typedef struct Fft_s {
|
||||
us nfft;
|
||||
us nchannels;
|
||||
vd fft_work;
|
||||
} Fft;
|
||||
|
||||
Fft* Fft_alloc(const us nfft,const us nchannels) {
|
||||
Fft* Fft_alloc(const us nfft) {
|
||||
fsTRACE(15);
|
||||
|
||||
if(nchannels > ASCEE_MAX_NUM_CHANNELS) {
|
||||
WARN("Too high number of channels! Please increase the "
|
||||
"ASCEE_MAX_NUM_CHANNELS compilation flag");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Fft* fft = a_malloc(sizeof(Fft));
|
||||
if(fft==NULL) {
|
||||
WARN("Fft allocation failed");
|
||||
@ -33,7 +26,6 @@ Fft* Fft_alloc(const us nfft,const us nchannels) {
|
||||
}
|
||||
|
||||
fft->nfft = nfft;
|
||||
fft->nchannels = nchannels;
|
||||
|
||||
/* Initialize foreign fft lib */
|
||||
fft->fft_work = vd_alloc(2*nfft+15);
|
||||
@ -52,55 +44,73 @@ void Fft_free(Fft* fft) {
|
||||
a_free(fft);
|
||||
feTRACE(15);
|
||||
}
|
||||
us Fft_nchannels(const Fft* fft) {return fft->nchannels;}
|
||||
us Fft_nfft(const Fft* fft) {return fft->nfft;}
|
||||
void Fft_fft_single(const Fft* fft,const vd* timedata,vc* result) {
|
||||
|
||||
fsTRACE(15);
|
||||
dbgassert(fft && timedata && result,NULLPTRDEREF);
|
||||
|
||||
const us nfft = fft->nfft;
|
||||
|
||||
dbgassert(timedata->size == nfft,
|
||||
"Invalid size for time data rows."
|
||||
" Should be equal to nfft");
|
||||
|
||||
dbgassert(result->size == (nfft/2+1),"Invalid number of rows in"
|
||||
" result array");
|
||||
|
||||
vd fft_result = vd_alloc(nfft);
|
||||
|
||||
vd_copy(&fft_result,timedata);
|
||||
|
||||
/* Perform fft */
|
||||
npy_rfftf(nfft,fft_result.ptr,fft->fft_work.ptr);
|
||||
|
||||
/* Fftpack stores the data a bit strange, the resulting array
|
||||
* has the DC value at 0,the first cosine at 1, the first sine
|
||||
* at 2 etc. This needs to be shifted properly in the
|
||||
* resulting matrix, as for the complex data, the imaginary
|
||||
* part of the DC component equals zero. */
|
||||
|
||||
*getvcval(result,0) = *getvdval(&fft_result,0);
|
||||
|
||||
memcpy((void*) getvcval(result,1),
|
||||
(void*) getvdval(&fft_result,1),
|
||||
(nfft-1)*sizeof(d));
|
||||
|
||||
/* Set imaginary part of Nyquist frequency to zero */
|
||||
((d*) getvcval(result,nfft/2))[1] = 0;
|
||||
|
||||
check_overflow_vx(fft_result);
|
||||
check_overflow_vx(fft->fft_work);
|
||||
vd_free(&fft_result);
|
||||
feTRACE(15);
|
||||
|
||||
}
|
||||
void Fft_fft(const Fft* fft,const dmat* timedata,cmat* result) {
|
||||
fsTRACE(15);
|
||||
|
||||
dbgassert(fft && timedata && result,NULLPTRDEREF);
|
||||
dbgassert(timedata->n_rows == fft->nfft,"Invalid size for time data rows."
|
||||
" Should be equal to nfft");
|
||||
dbgassert(timedata->n_cols == fft->nchannels,"Invalid size for time data cols."
|
||||
" Should be equal to nchannels");
|
||||
|
||||
const us nfft = fft->nfft;
|
||||
const us nchannels = timedata->n_cols;
|
||||
dbgassert(timedata->n_cols == result->n_cols,
|
||||
"Number of columns in timedata and result"
|
||||
" should be equal.");
|
||||
|
||||
vd fft_result = vd_alloc(fft->nfft);
|
||||
for(us col=0;col<fft->nchannels;col++) {
|
||||
for(us col=0;col<nchannels;col++) {
|
||||
|
||||
vd timedata_col = dmat_column((dmat*) timedata,col);
|
||||
vd_copy(&fft_result,&timedata_col);
|
||||
vc result_col = cmat_column(result,col);
|
||||
|
||||
Fft_fft_single(fft,&timedata_col,&result_col);
|
||||
|
||||
vd_free(&timedata_col);
|
||||
|
||||
npy_rfftf(fft->nfft,fft_result.ptr,fft->fft_work.ptr);
|
||||
|
||||
/* Fftpack stores the data a bit strange, the resulting array
|
||||
* has the DC value at 0,the first cosine at 1, the first sine
|
||||
* at 2 etc. This needs to be shifted properly in the
|
||||
* resulting matrix, as for the complex data, the imaginary
|
||||
* part of the DC component equals zero. */
|
||||
|
||||
check_overflow_vx(fft_result);
|
||||
check_overflow_vx(fft->fft_work);
|
||||
|
||||
vc resultcol = cmat_column(result,col);
|
||||
*getvcval(&resultcol,0) = *getvdval(&fft_result,0);
|
||||
|
||||
memcpy((void*) getvcval(&resultcol,1),
|
||||
(void*) getvdval(&fft_result,1),
|
||||
(nfft-1)*sizeof(d));
|
||||
|
||||
/* Set imaginary part of Nyquist frequency to zero */
|
||||
((d*) getvcval(&resultcol,nfft/2))[1] = 0;
|
||||
check_overflow_xmat(*timedata);
|
||||
|
||||
/* Free up storage of the result column */
|
||||
vc_free(&resultcol);
|
||||
vc_free(&result_col);
|
||||
}
|
||||
check_overflow_xmat(*timedata);
|
||||
check_overflow_xmat(*result);
|
||||
|
||||
|
||||
/* print_vd(&fft->fft_work); */
|
||||
|
||||
vd_free(&fft_result);
|
||||
feTRACE(15);
|
||||
}
|
||||
|
||||
|
@ -21,19 +21,10 @@ typedef struct Fft_s Fft;
|
||||
* Construct an Fft object
|
||||
*
|
||||
* @param nfft Nfft size
|
||||
* @param nchannels Number of channels
|
||||
*
|
||||
* @return Pointer to Fft handle, NULL on error
|
||||
*/
|
||||
Fft* Fft_alloc(const us nfft,const us nchannels);
|
||||
|
||||
/**
|
||||
* Returns the number of channels for this Fft instance
|
||||
*
|
||||
* @return nchannels
|
||||
*/
|
||||
us Fft_nchannels(const Fft*);
|
||||
|
||||
Fft* Fft_alloc(const us nfft);
|
||||
/**
|
||||
* Returns the nfft for this Fft instance
|
||||
*
|
||||
@ -41,18 +32,36 @@ us Fft_nchannels(const Fft*);
|
||||
*/
|
||||
us Fft_nfft(const Fft*);
|
||||
|
||||
/**
|
||||
* Compute the fft of a single channel.
|
||||
*
|
||||
* @param[in] fft Fft handle.
|
||||
*
|
||||
* @param[in] timedata Input time data pointer, should have size nfft
|
||||
* @param[out] result Pointer to result vector should have size
|
||||
* nfft/2+1
|
||||
*/
|
||||
void Fft_fft_single(const Fft* fft,const vd* timedata,vc* result);
|
||||
|
||||
/**
|
||||
* Compute the fft of the data matrix, first axis is assumed to be
|
||||
* the time axis.
|
||||
*
|
||||
* @param[in] timedata Input time data pointer, such that
|
||||
* data[i*nfft+j) is the i-th channel from data stream j.
|
||||
*
|
||||
* @param[out] result: Fft't data, size should be (nfft/2+1)*nchannels
|
||||
*/
|
||||
void Fft_fft(const Fft*,const dmat* timedata,cmat* result);
|
||||
* @param[in] fft Fft handle.
|
||||
|
||||
* @param[in] timedata Input time data. First axis is assumed to be
|
||||
* the time, second the channel number.
|
||||
*
|
||||
* @param[out] result: Fft't data, should have size (nfft/2+1) *
|
||||
* nchannels
|
||||
*/
|
||||
void Fft_fft(const Fft* fft,const dmat* timedata,cmat* result);
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param fft
|
||||
*/
|
||||
void Fft_free(Fft* fft);
|
||||
|
||||
#endif // FFT_H
|
||||
|
@ -5,7 +5,7 @@
|
||||
// Description:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/* #define TRACERPLUS 1000 */
|
||||
#define TRACERPLUS (-5)
|
||||
#include "ps.h"
|
||||
#include "fft.h"
|
||||
#include "ascee_alloc.h"
|
||||
@ -33,7 +33,7 @@ PowerSpectra* PowerSpectra_alloc(const us nfft,
|
||||
}
|
||||
|
||||
/* ALlocate space */
|
||||
Fft* fft = Fft_alloc(nfft,nchannels);
|
||||
Fft* fft = Fft_alloc(nfft);
|
||||
if(fft == NULL) {
|
||||
WARN("Fft allocation failed");
|
||||
return NULL;
|
||||
@ -76,7 +76,7 @@ void PowerSpectra_compute(const PowerSpectra* ps,
|
||||
|
||||
dbgassert(ps && timedata && result,NULLPTRDEREF);
|
||||
|
||||
const us nchannels = Fft_nchannels(ps->fft);
|
||||
const us nchannels = timedata->n_rows;
|
||||
const us nfft = Fft_nfft(ps->fft);
|
||||
uVARTRACE(15,nchannels);
|
||||
const d win_pow = ps->win_pow;
|
||||
|
@ -7,28 +7,27 @@ cdef extern from "cblas.h":
|
||||
|
||||
# If we touch this variable: we get segfaults when running from
|
||||
# Spyder!
|
||||
#openblas_set_num_threads(8)
|
||||
# openblas_set_num_threads(8)
|
||||
# print("Number of threads: ",
|
||||
# openblas_get_num_threads())
|
||||
|
||||
def cls():
|
||||
clearScreen()
|
||||
cls()
|
||||
# cls()
|
||||
|
||||
cdef extern from "fft.h":
|
||||
ctypedef struct c_Fft "Fft"
|
||||
c_Fft* Fft_alloc(us nfft,us nchannels)
|
||||
c_Fft* Fft_alloc(us nfft)
|
||||
void Fft_free(c_Fft*)
|
||||
void Fft_fft(c_Fft*,dmat * timedate,cmat * res) nogil
|
||||
us Fft_nchannels(c_Fft*)
|
||||
us Fft_nfft(c_Fft*)
|
||||
|
||||
cdef class Fft:
|
||||
cdef:
|
||||
c_Fft* _fft
|
||||
|
||||
def __cinit__(self, us nfft,us nchannels):
|
||||
self._fft = Fft_alloc(nfft,nchannels)
|
||||
def __cinit__(self, us nfft):
|
||||
self._fft = Fft_alloc(nfft)
|
||||
if self._fft == NULL:
|
||||
raise RuntimeError('Fft allocation failed')
|
||||
|
||||
@ -39,9 +38,8 @@ cdef class Fft:
|
||||
def fft(self,d[::1,:] timedata):
|
||||
|
||||
cdef us nfft = Fft_nfft(self._fft)
|
||||
cdef us nchannels = Fft_nchannels(self._fft)
|
||||
cdef us nchannels = timedata.shape[1]
|
||||
assert timedata.shape[0] ==nfft
|
||||
assert timedata.shape[1] == nchannels
|
||||
|
||||
result = np.empty((nfft//2+1,nchannels),
|
||||
dtype=NUMPY_COMPLEX_TYPE,
|
||||
@ -67,22 +65,25 @@ cdef class Fft:
|
||||
|
||||
cdef extern from "window.h":
|
||||
ctypedef enum WindowType:
|
||||
Hann = 0
|
||||
Hamming = 1
|
||||
Rectangular = 2
|
||||
Bartlett = 3
|
||||
Blackman = 4
|
||||
hann = 0
|
||||
hamming = 1
|
||||
rectangular = 2
|
||||
bartlett = 3
|
||||
blackman = 4
|
||||
Hann
|
||||
Hamming
|
||||
Rectangular
|
||||
Bartlett
|
||||
Blackman
|
||||
|
||||
# Export these constants to Python
|
||||
hann = Hann
|
||||
hamming = Hamming
|
||||
rectangular = Rectangular
|
||||
bartlett = Bartlett
|
||||
blackman = Blackman
|
||||
|
||||
cdef extern from "ps.h":
|
||||
ctypedef struct c_PowerSpectra "PowerSpectra"
|
||||
c_PowerSpectra* PowerSpectra_alloc(const us nfft,
|
||||
const us nchannels,
|
||||
const WindowType wt)
|
||||
|
||||
void PowerSpectra_compute(const c_PowerSpectra* ps,
|
||||
const dmat * timedata,
|
||||
cmat * result)
|
||||
@ -156,7 +157,7 @@ cdef extern from "aps.h":
|
||||
|
||||
|
||||
void AvPowerSpectra_free(c_AvPowerSpectra*)
|
||||
|
||||
us AvPowerSpectra_getAverages(const c_AvPowerSpectra*);
|
||||
|
||||
cdef class AvPowerSpectra:
|
||||
cdef:
|
||||
@ -180,7 +181,9 @@ cdef class AvPowerSpectra:
|
||||
def __dealloc__(self):
|
||||
if self.aps:
|
||||
AvPowerSpectra_free(self.aps)
|
||||
|
||||
def getAverages(self):
|
||||
return AvPowerSpectra_getAverages(self.aps)
|
||||
|
||||
def addTimeData(self,d[::1,:] timedata):
|
||||
"""!
|
||||
Adds time data, returns current result
|
||||
@ -223,7 +226,6 @@ cdef class AvPowerSpectra:
|
||||
cmat_free(&res)
|
||||
dmat_free(&td)
|
||||
|
||||
|
||||
return result
|
||||
|
||||
def getFreq(self, d fs):
|
||||
|
@ -26,7 +26,7 @@ X = np.fft.rfft(x,axis=0)
|
||||
print('Numpy fft')
|
||||
print(X)
|
||||
|
||||
fft = Fft(nfft,nchannels)
|
||||
fft = Fft(nfft)
|
||||
Y = fft.fft(x)
|
||||
print('Fftpack fft')
|
||||
print(Y)
|
||||
|
@ -16,9 +16,9 @@ int main() {
|
||||
|
||||
iVARTRACE(15,getTracerLevel());
|
||||
|
||||
Fft* fft = Fft_alloc(100000,8);
|
||||
Fft* fft = Fft_alloc(100000);
|
||||
|
||||
Fft_fft(fft,NULL,NULL);
|
||||
/* Fft_fft(fft,NULL,NULL); */
|
||||
|
||||
Fft_free(fft);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user