psambit9791 / jdsp

A Java Library for Digital Signal Processing
https://jdsp.dev
MIT License
240 stars 45 forks source link

Interpreting FFT symmetry #39

Closed LobsterMan123 closed 2 years ago

LobsterMan123 commented 2 years ago

Hello,

The image below is the FFT plot of my data and it is showing symmetry (I did not change the values printed on the x axis to reflect the frequency of the original time domain, but the shown FFT plot below is assuredly of transformed data). Would you please tell me if such symmetry is indicative of raw data that is too noisy or lacking of any discernible constituent sinusoids (my raw data does actually have a nice bandwidth - fixed y max and fixed x max - throughout the collected data oscillations)? I've been looking at FFT plots of a more "textbook" like quality and those plots give nice and discernible/distinct peaks that don't have symmetry in their profile and those ideal peaks shoot up from the x axis as opposed to my profile which looks like raw data itself (such idealized "textbook" data tends to be of the waveform from a guitar or violin string just to point out what I've been looking at). Thanks for any direction or tips you can provide.

LM

FFT_data

psambit9791 commented 2 years ago

Could you share the code you used to generate this?

LobsterMan123 commented 2 years ago

The specific code I used to invoke the FFT is

_Fourier ft = new FastFourier(XArray); ft.transform(); boolean onlyPositive = false; double[] xOut = ft.getMagnitude(onlyPositive);

The code for making the plot is:

width = 600; height = 500; title = "Angle Transform"; x_axis = "Frequency"; y_axis = "Don't Know"; Plotting xFrequencies = new Plotting(width, height, title, x_axis, y_axis); xFrequencies.initialisePlot(); xFrequencies.addSignal("Angle Transform", xOut, false); xFrequencies.saveAsPNG("AngleFrequencies.png");

Thanks.

LM

psambit9791 commented 2 years ago

@LobsterMan123

FFTs of real signals are always mirrored. The reason why this happens is very well explained in this post. And his is where the parameter onlyPositive comes into play. onlyPositive returns the value of only the positive frequency components (for complex signals, the negative frequency components are also returned). If you plot this, you will see the length is half of what you have now and the mirroring effect does not occur.

The fact that there are multiple peaks, implies there may be some harmonic components. But the overall signal is fairly noisy determined from how jagged the FFT profile looks overall.

LobsterMan123 commented 2 years ago

Thanks for the explanation and the post. This is starting to make sense.

My follow-up question is: is it advisable then to carry out a filtration of the original signal with something like Butterworth and then execute the transform on the filtered data (my plotted raw data and its Butterworth filtration is seen in the figure below - raw data in blue and filtered signal in green)? Is transforming a filtered signal physically or mathematically meaningful and/or feasible? Thanks.

LM

Butterworth Filtered Data

LobsterMan123 commented 2 years ago

In continuation to my previous question, I went and transformed (FFT) the filtered (Butterworth) signal just to see how it looks should it mean anything physically or mathematically. The image is below. Thanks.

FFT on Butterworth

psambit9791 commented 2 years ago

For the first part, whether it should be done or not is entirely problem-dependant. If you think that applying a filter can be helpful to your end goal, it can definitely be done. In terms of meaningfulness, it can indeed be done. Filtering fundamentally removes signals from a specific frequency; so applying an FFT on the filtered signal would lead to those specific frequency bins to be empty.

For the second part, it appears you have used a high-pass filter on the signal before transforming. Other than that, I cannot particularly comment about anything because again, interpretation of a plot is problem-dependant. FFT ad filters are simply tools to help you achieve certain tasks; the usage,utility and the interpretation of results is still on the user.

LobsterMan123 commented 2 years ago

Sounds good, thanks.

So I went ahead and obtained only the positive values of the DFT and I also printed that frequency data from the transform out to a file and I am seeing that only the "y-axis" data is printed. Looking at the graph/plot I can eyball what the frequencies are, that correspond to peaks of interest but I would like to be able to quote the specific frequency value (the actual "x-axis" value) that goes with said peak/local maximum. Is there a way to do this, to get the x-values that go with the y-values?

Also, since my data is data from real world phenomena (strictly real number input data that was transformed), do I need to worry about the complex/imaginary components when I do my FFT? Thanks again.

LM

psambit9791 commented 2 years ago

The current version of JDSP (v1.0.0) does not include the functionality to get the frequency bins based on the FFT. It has been added in the upcoming release with the getFFTFreq() function. Currently, to compute the frequencies for the data, you need to generate the bins yourself. Please refer to the function from this commit file on a guide to compute the same.

LobsterMan123 commented 2 years ago

Ok, I went ahead and tried using the commit file with my code but three things happened:

1) I needed to delete "implements _Fourier" from line 30 in order for it to compile and work with my code

2) I needed to delete the "if" block (lines 58-60) beginning with "if (this.output == null)" in order for the code to compile since the array named "output" is always null/doesn't change its value.

3) Executing the above changes results in the "results" array being populated with nothing but zeros. I also provided various different sampling frequencies but when I print out the length of the "results" array the length is always the same number (65 for me).

I also set the "onlyPositive" parameter in the "getFFTFreq" method to "true" since I am working with only the positive values of the DFT.

Should I be doing other changes to the code instead? Thanks.

LM

psambit9791 commented 2 years ago

Right. So I don't think this is the right forum to discuss about potential coding problems; especially since the relevant code will be deployed in a future release.

However, the expectation was not to modify the library itself, but to write a separate function derived from the referred function getFFTFreq() to compute the FFT frequency bins separately. This can be done independently of the FFT and has no dependency on the actual transform. All that is needed to compute the FFT Frequency bins is the signal length and the sampling frequency.

Hope this helps.

psambit9791 commented 2 years ago

Also, if you are finding JDSP useful, please considering starring the project.

LobsterMan123 commented 2 years ago

Got it. Since the signal length and sampling frequency is all I need, I'll take a look then at the maths for calculating the bins in light of what you also have in the commit file.

Yes, I've starred the project as it's proving to be extremely useful for my own work (it's showing up as having gone up to 97 stars with my contribution).

LM

LobsterMan123 commented 2 years ago

Also, is there a general timeline when the next release with the feature of calculating the bins will come out (a few months, next year, etc...)? Thanks.

psambit9791 commented 2 years ago

The potential release date for v2.0.0 which includes some speech-processing tools is the middle of the fourth quarter of 2022. Given the issues that have been reported for v1.0.0, I might be inclined to make an intermediary release with the minor feature updates. This will be done once the peak detection time issues are resolved - so potentially in July.

However, if you want to use the development version of the code, please refer to the README file where you can find reference to a tool called JitPack which allows users to work with development versions of the codebase. Please make sure you are building from the dev branch.

LobsterMan123 commented 2 years ago

Wonderful, I'll keep an eye out then for the new release even if it is the intermediary version for the short term. Will the new maven summons code for the pom file be found on https://jdsp.dev/get_started.html whenever the new release(s) come(s) out? Thanks.

LM

psambit9791 commented 2 years ago

For any new release, the website will be updated with the latest summons and the latest API usage example.