C++ - Complex Value Calculation Error in Cross Spectral Density - c++

I am a very beginner in c++ and I want to do some spectral calculations, in this case calculating the 'Cross Spectral Density' of two signal (vecFirst, vecSecond), which are already processed with a FastFourierTransformation. Resulting in freqvec and freqvec2, containing complex values for each frequency.
For this calculating it is essential to keep every value as a complex value. E.g.: CoSpectrum, which is calculated in line 6, should has a complex value as a result.
RowVectorXcd freqvec;
RowVectorXcd freqvec2;
fft.fwd(freqvec, vecFirst);
fft.fwd(freqvec2, vecSecond);
// # Create conjugate complex
freqvec.conjugate();
freqvec2.conjugate();
RowVectorXcd Rxy(freqvec.cols());
for (int i = 0; i < freqvec.cols(); i++) {
std::complex<double>CoSpectrum( freqvec(i).real() * freqvec2(i).real() + freqvec(i).imag() * freqvec2(i).imag()) ;
std::complex<double>QuadSpectrum( freqvec(i).real() * freqvec2(i).imag() - freqvec(i).real() * freqvec2(i).imag() ) ;
std::complex<double>CoSpectrum_sqr = CoSpectrum * CoSpectrum ;
std::complex<double>QuadSpectrum_sqr = QuadSpectrum * QuadSpectrum ;
Rxy(i) = sqrt(std::complex<double>(CoSpectrum_sqr + QuadSpectrum_sqr)) ;
}
}
Unfortunately I only get complex values with zero in the imaginary part.
Can anyone tell me why?
I am guessing the expression freqvec(i).real() only returns a double value, but how can I get the real part but keep it a complexvalue. Or, accordingly, just multiply the imaginary part of a complex number with the real part of another and keep it the result a complex double.
Thanks for any help in advance.

At first: Thank you very much. I had thought of something like that, but wasn't sure. Thank got there a nice people like you who care about beginners.
So I changed the snippet as following:
// ### Attempting to compute the Frequency Power for Frequency Bins..
RowVectorXcd freqvec;
RowVectorXcd freqvec2;
fft.fwd(freqvec, vecFirst);
fft.fwd(freqvec2, vecSecond);
std::cout<<"freqvec:"<<freqvec.cols()<<std::endl;
// ### Attempting to compute the PowerSpectralDensitiy(PSD) and CrossSpectralDensity(CSD). The cross-spectral density is the Fourier transform of the cross-correlation function.
RowVectorXcd Rxy(n_Epochs, freqvec.cols());
RowVectorXcd Rxx(n_Epochs, freqvec.cols());
RowVectorXcd Ryy(n_Epochs, freqvec.cols());
for (int i = 0; i < n_Epochs; i++) {
std::complex<double>CoSpectrum( std::complex<double>(freqvec(i).real(),0) * std::complex<double>(freqvec2(i).real(),0) + std::complex<double>(0,freqvec(i).imag()) * std::complex<double>(0, freqvec2(i).imag()) ) ;
std::complex<double>QuadSpectrum( std::complex<double>(freqvec(i).real(), 0) * std::complex<double>(0, freqvec2(i).imag()) - std::complex<double>(0,freqvec(i).imag()) * std::complex<double>(freqvec2(i).real(), 0) ) ;
std::complex<double>CoSpectrum_sqr = CoSpectrum * CoSpectrum ;
std::complex<double>QuadSpectrum_sqr = QuadSpectrum * QuadSpectrum ;
Rxy(i) = sqrt(std::complex<double>(CoSpectrum_sqr + QuadSpectrum_sqr)) ;
Rxx(i) = std::complex<double>(freqvec(i).real(), 0) * std::complex<double>(freqvec(i).real(), 0) + std::complex<double>(0, freqvec(i).imag()) * std::complex<double>(0, freqvec(i).imag()) ;
Ryy(i) = std::complex<double>(freqvec2(i).real(), 0) * std::complex<double>(freqvec2(i).real(), 0) + std::complex<double>(0, freqvec2(i).imag()) * std::complex<double>(0, freqvec2(i).imag()) ;
}
}
This solved my problem. Thanks again for the nice discussion.

Related

Need help understanding how to work with 2D/3D glyphs

Here's the code snippet I'd like help understanding
for (i = 0; i < samplesX; i++)
for (j = 0; j < samplesY; j++)
{
newI = DIM * i / samplesX;
newJ = DIM * j / samplesY;
idx = (round(newJ) * DIM) + round(newI);
if (color_dir == 1 && draw_vecs == 1) {
direction_to_color(vx[idx], vy[idx], color_dir);
}
if (color_dir == 1 && draw_vecs == 2) {
direction_to_color(fx[idx], fy[idx], color_dir);
}
else if (color_dir == 2) {
scalar = rho[idx];
set_colormap(scalar, min, max, clampLow, clampHigh);
}
else if (color_dir == 3) {
scalar = sqrt(vx[idx] * vx[idx] + vy[idx] * vy[idx]);
set_colormap(scalar, min, max, clampLow, clampHigh);
}
else if (color_dir == 4) {
scalar = sqrt(fx[idx] * fx[idx] + fy[idx] * fy[idx]);
set_colormap(scalar, min, max, clampLow, clampHigh);
}
/*if (draw_vecs == 1) {
glVertex2f(wn + (fftw_real)newI * wn, hn + (fftw_real)newJ * hn);
glVertex2f((wn + (fftw_real)newI * wn) + vec_scale * vx[idx], (hn + (fftw_real)newJ * hn) + vec_scale * vy[idx]);
}
else if (draw_vecs == 2) {
glVertex2f(wn + (fftw_real)newI * wn, hn + (fftw_real)newJ * hn);
glVertex2f((wn + (fftw_real)newI * wn) + vec_scale * fx[idx], (hn + (fftw_real)newJ * hn) + vec_scale * fy[idx]);
}*/
if (draw_vecs == 1) {
glVertex2f(wn + (fftw_real)i * wn, hn + (fftw_real)j * hn);
glVertex2f((wn + (fftw_real)i * wn) + vec_scale * vx[idx], (hn + (fftw_real)j * hn) + vec_scale * vy[idx]);
}
else if (draw_vecs == 2) {
glVertex2f(wn + (fftw_real)i * wn, hn + (fftw_real)j * hn);
glVertex2f((wn + (fftw_real)i * wn) + vec_scale * fx[idx], (hn + (fftw_real)j * hn) + vec_scale * fy[idx]);
}
}
glEnd();
}
What this currently does, as far as my understanding goes, is display these two-dimensional lines/arrows (hedgehogs) that visualize force/velocity in 2D as can be seen in the picture below.
Sadly, my understanding of linear algebra, calculus and computer graphics in general only goes so far and I'm having trouble dissecting this piece.
Ideally I'd like to understand this and also understand how I can take this pre-existing code and also add in functionality that can display two other glyph types that show a vector and/or scalar field such as
three-dimensional cones
three-dimensional ellipsoids
If I'm missing anything here, please let me know!
Some of the variables included in the above snippet:
const int DIM = 50; //size of simulation grid
int color_dir = 0; //use direction color-coding or not
float scalar;
int newI, newJ;
float temp;
float vec_scale = 1000; //scaling of hedgehogs
int draw_vecs = 1; //draw the vector field or not
The code snippet you have there could have been written simpler (also it takes some educated guessing what some of the variables and functions mean).
Let's break it down.
The first two lines are easy to understand, they're the standard stanza to iterate over a 2D array
for (i = 0; i < samplesX; i++)
for (j = 0; j < samplesY; j++)
i and j are running indices, that will iterate over every discrete coordinate tuple in (i,j) ∈ [i, samplesX) × [j, samplesY). The next two lines remap the 2D indices into into a new value range, specifically [i, samplesX)×[j, samplesY) → [0, DIM)×[0, DIM). A missing piece of information is, what type is DIM of. It would make for it to be some floating point type.
newI = DIM * i / samplesX;
newJ = DIM * j / samplesY;
The next line is bug prone. It translates newI and newJ into a running 1D index for a 1D array, that's addressed by i and j.
Why is this problematic? Because in the conversion to DIM-space information may have been lost. This kind of information loss may lead to security bugs(!), as a matter of fact, Skia, the rendering library used by Google Chrome, Android and other projects had exactly this kind of bug recently; the writeup is a worthwhile read: https://googleprojectzero.blogspot.com/2019/02/the-curious-case-of-convexity-confusion.html
The correct way to implement this is to have DIM be an integer and perform fixed point arithmetic on it, eventually truncating the fractional digits. But I digress. The next block is essentially performing a poor man's lookup table lookup. vx``vy and fx``fy are some flattened 2D arrays, accessed through an 1D index, and direction_to_color maps either to a value presumably to a call of glColor; the same probably also goes for set_colormap. This is a bad use of OpenGL.
The whole remapping from i and j to DIM and then the lookups are just poor implementation of a texture lookup. OpenGL already has textures. Just load as texture coordinate array and enable texturing.
Finally for each spine, two calls of glVertex are made, one with the staring point, which lies on grid centers (wn, hn), to an offset location (wn, hn) + (i, j).
My verdict of that code: Utter garbage! All of this could have been done far more elegantly, even back in 1994 with OpenGL-1.0, which is code seems to have been written for. If you want to implement your own vector field plot, don't use this as a starting point.
These days we have programmable GPUs with shaders. All of that bulk up there can be done is a few lines of shader code.

C++ - Complex Value mistake, computing Cross Spectral Density (CSD)

Dear community,
I am facing a rather annoying problem. I am calculating the Cross Spectral Density (CSD) between two time signals, which were already proccessed with FFT to two complex frequency vectors(Singal1 =>freqvec, Signal2 => freqvec2).
RowVectorXcd CSD(n_Epochs, fftsize);
for(int j = 0; j < fftsize; j++) {
std::complex<double> cospectrum = freqvec(j).real() * freqvec2(j).real() + freqvec(j).imag() * freqvec2(j).imag() ;
std::complex<double> quadspectrum = freqvec(j).real() * freqvec2(j).imag() - freqvec(j).imag() * freqvec2(j).real() ;
std::cout << "cospectrum:"<<cospectrum<< std::endl;
CSD(j) = sqrt( pow( cospectrum, 2 ) + pow( quadspectrum, 2) ) ;
For further computations I need to get the imaginary part of this calculation correctly.
The calculation does work, but somehow the result always has an imaginary value of zero.

C++ Average VectorXcd along axis

I am a beginner in C++ programming. I try working with arrays and the Eigen module. Now I came across a problem I could solve in hours. Maybe it is pretty basic, but I am lost.
QPair<int, double> ConnectivityMeasures::calcImaginaryCoherence(const RowVectorXd& vecFirst, const RowVectorXd& vecSecond, int iNumberEpochs)
{
Eigen::FFT<double> fft;
int N = std::max( vecFirst.cols(), vecSecond.cols() ) ;
//Compute the NFFT
int b = ceil( log2(2.0 * N - 1) ) ;
int fftsize = pow(2,b) ;
//Zero Padding --> Cropping/Extending the Signal to the NFFT size. Cropping=Deleting Values; Extending=Fill up with Zeros
RowVectorXd xImCohInputVecFirst = RowVectorXd::Zero(fftsize) ;
xImCohInputVecFirst.head(vecFirst.cols() ) = vecFirst ;
RowVectorXd xImCohInputVecSecond = RowVectorXd::Zero(fftsize) ;
xImCohInputVecSecond.head( vecSecond.cols() ) = vecSecond ;
//FFT for freq domain to both vectors
RowVectorXcd freqvec ;
RowVectorXcd freqvec2 ;
fft.fwd(freqvec, xImCohInputVecFirst) ;
freqvec.conjugate() ;
fft.fwd(freqvec2, xImCohInputVecSecond) ;
freqvec2.conjugate() ;
// Calculate PowerSpectralDensitiy (PSD) and CrossSpectralDensity(CSD)
VectorXcd Rxy(iNumberEpochs, fftsize);
VectorXcd Rxx(iNumberEpochs, fftsize);
VectorXcd Ryy(iNumberEpochs, fftsize);
for (int i = 0; i < iNumberEpochs; i++)
{
Rxy[i] = sqrt( pow((freqvec[i].real() * freqvec2[i].real() + freqvec[i].imag() * freqvec2[i].imag()), 2 ) + pow((freqvec[i].real() * freqvec2[i].imag() + freqvec[i].imag() * freqvec2[i].real()), 2) );
Rxx[i] = ( pow(freqvec[i], 2) );
Ryy[i] = ( pow(freqvec2[i], 2) );
}
// Average PSD, CSD over the Number of Epochs; not over channels
RowVectorXcd Rxy_mean(freqvec) = Rxy.mean() ;
RowVectorXcd Rxx_mean(freqvec) = Rxx.mean() ;
RowVectorXcd Ryy_mean(freqvec2) = Ryy.mean() ;
So my problem starts here. I have a 2D Array for my Rxy, Rxx and Ryy values. Stored like [number of epochs, number of frequencies].
Now I want to average all frequency values of each epoch to a single value and store them as Rxy_mean, Ryy_mean and Rxx_mean
My Compiler spit out ' Syntax error: missing ";" before "=" '
Does anyone can say how to fix this, proceed or point out my mistake with a simple example ?
Thanks in advance,
Daniel

bandpass FIR filter

I need to make a simple bandpass audio filter.
Now I've used this simple C++ class: http://www.cardinalpeak.com/blog/a-c-class-to-implement-low-pass-high-pass-and-band-pass-filters
It works well and cut off the desired bands. But when I try to change upper or lower limit with small steps, on some values of limit I hear the wrong result - attenuated or shifted in frequency (not corresponding to current limits) sound.
Function for calculating impulse response:
void Filter::designBPF()
{
int n;
float mm;
for(n = 0; n < m_num_taps; n++){
mm = n - (m_num_taps - 1.0) / 2.0;
if( mm == 0.0 ) m_taps[n] = (m_phi - m_lambda) / M_PI;
else m_taps[n] = ( sin( mm * m_phi ) -
sin( mm * m_lambda ) ) / (mm * M_PI);
}
return;
}
where
m_lambda = M_PI * Fl / (Fs/2);
m_phi = M_PI * Fu / (Fs/2);
Fs - sample rate (44.100)
Fl - lower limit
Fu - upper limit
And simple filtering function:
float Filter::do_sample(float data_sample)
{
int i;
float result;
if( m_error_flag != 0 ) return(0);
for(i = m_num_taps - 1; i >= 1; i--){
m_sr[i] = m_sr[i-1];
}
m_sr[0] = data_sample;
result = 0;
for(i = 0; i < m_num_taps; i++) result += m_sr[i] * m_taps[i];
return result;
}
Do I need to use any window function (Blackman, etc.)? If yes, how do I do this?
I have tried to multiply my impulse response to Blackman window:
m_taps[n] *= 0.42 - 0.5 * cos(2.0 * M_PI * n / double(N - 1)) +
0.08 * cos(4.0 * M_PI * n / double(N - 1));
but the result was wrong.
And do I need to normalize taps?
I found a good free implementation of FIR filter:
http://www.iowahills.com/A7ExampleCodePage.html
...This Windowed FIR Filter C Code has two parts, the first is the
calculation of the impulse response for a rectangular window (low
pass, high pass, band pass, or notch). Then a window (Kaiser, Hanning,
etc) is applied to the impulse response. There are several windows to
choose from...
y[i] = waveform[i] × (0.42659071 – 0.49656062cos(w) + 0.07684867cos(2w))
where w = (2)i/n and n is the number of elements in the waveform
Try this I got the code from:
http://zone.ni.com/reference/en-XX/help/370592P-01/digitizers/blackman_window/
I hope this helps.

FIR filtering using window function: implementation problem

I want to make a FIR filter using a window function. I have some sample data and size variable is a count of samples. The windowSize variable is a size of the window function.
At first I create the window function (blackman window): the variable window
Then I need to multiply it by sin(x) / x function and convolve with real data (variable data):
for (int i = 0; i < size; ++i) {
for (j = 0; j < windowSize; ++j) {
double arg = 2.0 * PI * ((double)j - (double)windowSize / 2.0) / (double)windowSize;
if (i + j - windowSize / 2 < 0)
continue;
if (arg == 0) {
filteredData[i] += data[i + j - windowSize / 2] * window[j] * 1.0 / (double)windowSize;
} else
filteredData[i] += data[i + j - windowSize / 2] * window[j] * (sin(arg) / arg) / (double)windowSize;
}
}
The problem:
As a result I get a filtered data with an average which very different than the average of the original data. Where is a mistake?
In the DSP book it is written that in order to make a FIR filter we should multiply the function sin(x) / x by a window function and then perform the convolution, but nothing is written about x in the sin(x) / x, so I used the:
double arg = 2.0 * PI * ((double)j - (double)windowSize / 2.0) / (double)windowSize;
for the x value, the argument of sine, is it correct?
The sin(x)/x filter is a lowpass filter. That is, it suppresses all frequencies above a certain cutoff frequency.
If the sampling frequency is Fs (Hertz) and you want a cutoff frequency of fc (Hertz), You should be using x = 2*PI*fc/(2*Fs)*n where n goes from -N to +N and N is large enough that the sin(x)/x function is close to zero. Don't forget that sin(x)/x is 1 when x is zero.
To maintain the average of the signal you have to normalize the filter coefficients by their sum. I.e., set f_norm[k] = f[k] / sum(f[k], k=...)
That's all I have to say at this point. It seems like you have a lot to learn. I suggest a good book on signal processing.
As far as the implementation is concerned it looks like you need to initialise filteredData[i], e.g.
for (int i = 0; i < size; ++i) {
filteredData[i] = 0;
for (j = 0; j < windowSize; ++j) {
...