Jump to content

Formula Question: Tables vs. Groups vs. Samples


Brent Railey
 Share

Recommended Posts

I have an interesting question that I need some assistance on.

We have a signal that generally has no dominant frequency. However, it sometimes does get a dominant frequency and when it does, we are really interested in two things: 

  1. What is the dominant frequency?
  2. How dominant is it? ( Let's call this "magnitude." )
  3. Tracking both the dominant frequency and the intensity over time using a rolling 2 to 3 hour window every 5 minutes. 

This value has predictive capability when it does show up, and it intensifies as it gets closer to a particular event we are trying to predict. 

I've been able get the peak frequency because the formulas are clear enough to figure this out. The problem is the magnitude.

The "Frequency Analysis" panel results show something like this: 

2020-09-13_20-07-23.jpg?psid=1

 

How do I get that peak value? I don't want to have to specify a hard-coded frequency band for this. 

The problem is that I don't see a function for that.

I can call the

fft()

function in a way in which it returns a "Table" type. 

 signal.fft ( bounds , period , units ) : Table
Create a table of frequency magnitudes by analyzing the signal in the bounds. The table will have 2 columns, frequency and magnitude.

Then I can use the top() function to return the top 1 row ordered by the greatest "magnitude" column:

table.top ( limit , columnName , direction ) : Table

However, I cannot for the life of me figure out how to get the "mangitude" value out of the first row returned in "Table" the above function and convert it into a sample at the ending point of the rolling 3 hour/5min period.

Is this even possible. Is there a better way? 

// Getting a rolling 3 hour window every 5 minutes. 
$periods = periods(3h, 5min)

// for condition, get a signal with samples ending at each capsule representing:
// key: end of 3hr window
// value: peak magnitude of the fft of the $waveSignal
$periods.transformToSamples(
   $cap -> { // excute the expression for each capsule in condition.  
      $tbl = $waveSignal.fft($cap, 1s, 's') // want the results in period lengths, not frequencies. 
      // get the largest magnitude, filtering for the frequency/period length range of interest
      // get the first row of that table. 
      $r = $tbl.filter('frequency'. isBetween(30s, 150s))
               .top(1, 'magnitude', 'desc') 
               .getFirstRow() // *******HOW DO I DO THIS???******
      // convert that magnitude calculated to sample located at the end of this capsule. 
      sample($cap.getEnd(), $r.get('magnitude'))     
   }
)

Thanks in advance! 

Even better would be: getting the sum of the values in the peakFrequency +-/ 2s window. 

Edited by Brent Railey
Link to comment
Share on other sites

  • Administrators

Brent,

I would avoid using tables and transforms for this calculation.  I would look towards the peakFrequency() and the rmspower() functions.  They are used with the aggregate function, so they are applied to a condition. 

To find the peak frequency the following syntax can be used in the formula tool.
 

$condition = periods(1h, 30min)

$sampleRate = (1min)   //This is the spacing for used in the sampling for the FFT

$waveSignal.aggregate( fft($sampleRate).peakFrequency('min'),$condition,startKey())

Here is a screen shot of the formula tool window.

Capture1.PNG

For the magnitude I suggest looking at the rmsPower() function in formula.  If you know the band range where you expect the peak to occur, you can use that band range and be done.  However, if there is multiple places that the peak could occur you can use multiple rmsPower() functions and add them together or take the maximum of them.  If you are planning on taking the maximum you will want to make sure that you are using the same size band for each rmsPower() calculation so that the comparisons are equivalent.

The example syntax below can be used to fine the maximum rms power of a set of peaks.

$condition = periods(1h, 30min)

$sampleRate = (1min)

$peak1=$waveSignal.aggregate( fft($sampleRate).rmsPower(4.5min,5.5min),$condition,startKey()).toStep()
$peak2=$waveSignal.aggregate( fft($sampleRate).rmsPower(9.5min,10.5min),$condition,startKey()).toStep()
$peak3=$waveSignal.aggregate( fft($sampleRate).rmsPower(24.5min,25.5min),$condition,startKey()).toStep()

// you will need to pick ranges and a sample rate that makes sense for your process

$peak1.max($peak2).max($peak3).toStep()

Below is a screen shot of the formula setup.

Capture2.PNG

Note: if you want to add the peaks instead of finding the max.  You would just add the peaks instead of using the max function.

 

Final screenshot.

Capture3.PNG

Hope this helps.

Teddy

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...