Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add function(s) for computing a FFT #77

Closed
S-Hanly opened this issue Dec 2, 2021 · 5 comments · Fixed by #123
Closed

Add function(s) for computing a FFT #77

S-Hanly opened this issue Dec 2, 2021 · 5 comments · Fixed by #123
Assignees
Labels
endaq.calc Related to `endaq.calc` enhancement New feature or request TODO A priority enhancement

Comments

@S-Hanly
Copy link
Contributor

S-Hanly commented Dec 2, 2021

Suggest a function using scipy's welch which allows specifying the bin width, but won't return phase angle, and another function using Numpy's rfft that would return phase.

Here are two examples:

def welch_fft(df, bin_width=0.5):
  fft = endaq.calc.psd.welch(df, bin_width=bin_width, scaling='parseval', window='boxcar', noverlap=0)
  return fft**0.5 * (2**0.5) #scale from g^2 as RMS to g-peak  

def numpy_fft(df):
  """
  Using Numpy's rfft functions compute a discrete Fourier Transform
  """
  freq = np.fft.rfftfreq(len(df), d=endaq.calc.utils.sample_spacing(df))
  df_mag = pd.DataFrame(index=pd.Series(freq, name="frequency (Hz)"), columns=df.columns)
  df_phase = df_mag.copy()

  for col in df.columns:
    sp = np.fft.rfft(df[col].to_numpy())
    df_mag[col] = np.absolute(sp)/len(sp)
    df_phase[col] = np.angle(sp)

  return df_mag, df_phase
@S-Hanly S-Hanly added the endaq.calc Related to `endaq.calc` label Dec 2, 2021
@S-Hanly
Copy link
Contributor Author

S-Hanly commented Dec 2, 2021

@CFlaniganMide suggested we could also look to optimize the welch's method computation by not "blindly" picking a bin width in samples that closest matches the Hz resolution the user-provided. There could be another parameter like optimize which if passed as True would round down to the nearest power of 2.

@StokesMIDE StokesMIDE added enhancement New feature or request TODO A priority enhancement labels Dec 14, 2021
@S-Hanly
Copy link
Contributor Author

S-Hanly commented Dec 17, 2021

@pscheidler asked for some test data, here are two I used in the webinar:

real_accel = endaq.ide.to_pandas(endaq.ide.get_doc('https://info.endaq.com/hubfs/100Hz_shake_cal.ide').channels[80],time_mode='seconds')[4.5:9.5]

time = np.linspace(0,200,2**20,endpoint=False)
sine_waves = pd.DataFrame(index=time)
sine_waves['10g @ 100 Hz'] = 10*np.sin(2*np.pi*100 * time)
sine_waves['8g @ 99 Hz'] = 8*np.sin(2*np.pi*99 * time)
sine_waves['6g @ 100.25 Hz'] = 6*np.sin(2*np.pi*100.25 * time)

Also totally open to making this one function, changing the name, and slight tweaks to the API but overall I'm looking for:

  • Input of time series dataframe (like what to_pandas) returns
    • Optional parameter to define the frequency resolution which would mean we'd be using welch's method and averaging
    • Optional parameter to optimize by zero padding to nearest power of 2 and then scaling appropriately
  • Output of a dataframe of magnitude vs frequency
    • Include dataframe of phase vs frequency if not using welchs

@SamRagusa
Copy link
Contributor

At some point I remember someone writing some code to do speed tests for the possible FFT approaches we're considering, can someone link me to it?

I have an additional FFT function I'd like to evaluate against our approaches.

@S-Hanly
Copy link
Contributor Author

S-Hanly commented Dec 17, 2021

Here's what I did for the webinar: https://colab.research.google.com/drive/1cuZa5Yx55qXLhhnBMdzsJ0iiklwVi5Mq#scrollTo=p6xZVN152WKG

But I know @CFlaniganMide did some too.

@pscheidler
Copy link
Member

Issue: Even though this all returns the FFT data most folks want, it is a different return type from what most provide. I think we should give it a different name to make that difference more obvious. I don't have great ideas, but maybe get_fft_magnitude and get_fft_magnitude_phase

Are you sure you don't want the phase to be in the same dataframe as the magnitude?

@CFlaniganMide CFlaniganMide linked a pull request Jan 5, 2022 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
endaq.calc Related to `endaq.calc` enhancement New feature or request TODO A priority enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants