Skip to content

Commit

Permalink
add inverseS
Browse files Browse the repository at this point in the history
True inverse S transform function inverseS
  • Loading branch information
xli2522 committed Nov 8, 2021
1 parent 95aaa3e commit 52c40ac
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 33 deletions.
56 changes: 43 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

Step 1: Quadratic chirp signal

Generate a quadratic chirp signal from 10 Hz to 120 Hz in 1 second with 10,000 sampling points.

```Python
import numpy as np
import scipy
Expand All @@ -12,45 +14,73 @@ import matplotlib.pyplot as plt
# Generate a quadratic chirp signal
dt = 0.0001
rate = int(1/dt)
ts = np.linspace(0, 5, int(1/dt))
data = scipy.signal.chirp(ts, 10, 5, 300, method='quadratic')
ts = np.linspace(0, 1, int(1/dt))
data = scipy.signal.chirp(ts, 10, 1, 120, method='quadratic')
```

Step 2: S Transform Spectrogram

```Python
import TFchirp
from s import *

# Compute S Transform Spectrogram
spectrogram = TFchirp.sTransform(data, sample_rate=rate)
spectrogram = sTransform(data, sample_rate=rate)
plt.imshow(abs(spectrogram), origin='lower', aspect='auto')
plt.title('Original Spectrogram')
plt.show()
```

![Original Spectrogram](https://raw.githubusercontent.com/xli2522/TFchirp/main/img/original_spectrogram.png)
![Original Spectrogram](https://github.com/xli2522/S-Transform/blob/main/img/original_spectrogram.png?raw=true)

Step 3: Quick recovery of full ts from S transform * 0 frequency row*

Step 3: Quick Recovery of ts from sTransform Spectrogram
(This recovered ts is computed based on the fact that the 0 frequency row always contain the full FFT result of the ts in this program by design.)

```Python
# Quick ts Recovery from sTransform
inverse_ts = TFchirp.inverse_S(spectrogram)
plt.plot(inverse_ts-data)
# Quick Recovery of ts from S Transform 0 frequency row
recovered_ts = recoverS(spectrogram)
plt.plot(recovered_ts-data)
plt.title('Time Series Reconstruction Error')
plt.show()
```

![Reconstruction Error](https://raw.githubusercontent.com/xli2522/TFchirp/main/img/reconstruction_error.png)
![Reconstruction Error](https://github.com/xli2522/S-Transform/blob/main/img/reconstruction_error.png?raw=true)

Recovered spectrogram:
Step 4: Recovered spectrogram:

```Python
# Compute S Transform Spectrogram on the recovered time series
inverseSpectrogram = TFchirp.sTransform(inverse_ts, sample_rate=rate)
recoveredSpectrogram = sTransform(recovered_ts, sample_rate=rate, frange=[0,500])
plt.imshow(abs(recoveredSpectrogram), origin='lower', aspect='auto')
plt.title('Recovered Specctrogram')
plt.show()
```

![Recovered](https://github.com/xli2522/S-Transform/blob/main/img/recovered_spectrogram.png?raw=true)

Step 5: The real inverse S transform

```python
# Quick Inverse of ts from S Transform
inverse_ts, inverse_tsFFT = inverseS(spectrogram)
plt.plot(inverse_ts)
plt.plot(inverse_ts-data)
plt.title('Time Series Reconstruction Error')
plt.legend(['Recovered ts', 'Error'])
plt.show()
```

![Recovered ts and Error](https://github.com/xli2522/S-Transform/blob/main/img/recovered_ts_error.png?raw=true)

Step 6: Recovered spectrogram on the *real* inverse S transform ts

```python
# Compute S Transform Spectrogram on the recovered time series
inverseSpectrogram = sTransform(inverse_ts, sample_rate=rate, frange=[0,500])
plt.imshow(abs(inverseSpectrogram), origin='lower', aspect='auto')
plt.title('Recovered Specctrogram')
plt.show()
```

![Recovered](https://raw.githubusercontent.com/xli2522/TFchirp/main/img/recovered_spectrogram.png)
![Recovered Spectrogram](https://github.com/xli2522/S-Transform/blob/main/img/real_recovered_spectrogram.png?raw=true)

56 changes: 45 additions & 11 deletions TFchirp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,37 @@
import numpy as np
import scipy.signal

def sTransform(ts, sample_rate, frange=[0, 800], frate = 1):
def sTransform(ts, sample_rate, frange=[0, 500], frate = 1, onesided=True, elevated=True, elevation=10e-8):
'''Compute the S Transform
Input:
ts (ndarray) time series data
sample_rate (int) sample rate
frange (list, optional) frequency range (Hz)
frate (int, optional) frequency sampling rate
onesided (bool, optional) include only the left side of the FFT if True
elevated (bool, optional) when True, add elevation to the Gaussian
elevation (float, optional) magnitude of the elevation
Output:
amp (ndarray) spectrogram table
Note:
amp shape [frequency, time], lower -> higher
'''

length = len(ts)
Nfreq = [int(frange[0]*length/sample_rate), int(frange[1]*length/sample_rate)]
Nfreq = [int(frange[0]*length/sample_rate), int(frange[1]*length/sample_rate)]
tsVal = np.copy(ts)
amp = np.zeros((int((Nfreq[1]-Nfreq[0])/frate)+1,length), dtype='c8')
amp = np.zeros((int((Nfreq[1]-Nfreq[0])/frate)+1,length), dtype='c8')
tsFFT = np.fft.fft(tsVal)
vec = np.hstack((tsFFT, tsFFT))

amp[0] = np.fft.ifft(vec[0:length]*_window_normal(length, 0)) # set the lowest frequency row to small values => 'zero' frequency
# set the lowest frequency row to small values => 'zero' frequency
amp[0] = np.fft.ifft(vec[0:length]*_window_normal(length, 0, elevated=elevated, elevation=elevation))
for i in range(frate, (Nfreq[1]-Nfreq[0])+1, frate):
amp[int(i/frate)] = np.fft.ifft(vec[Nfreq[0]+i:Nfreq[0]+i+length]*_window_normal(length, Nfreq[0]+i, factor=1))

amp[int(i/frate)] = np.fft.ifft(vec[Nfreq[0]+i:Nfreq[0]+i+length]*_window_normal(length, Nfreq[0]+i, factor=1, elevated=elevated, elevation=elevation))
return amp

def _window_normal(length, freq, factor = 1, elevated=True, elevation = 10e-8):
def _window_normal(length, freq, factor = 1, elevated=True, elevation =10e-8):
'''Gaussian Window function w/ elevation
Input:
length (int) length of the Gaussian window
Expand All @@ -67,19 +71,49 @@ def _window_normal(length, freq, factor = 1, elevated=True, elevation = 10e-8):

return win

def inverse_S(table, lowFreq = 0):
'''Quick Inverse of S Transform Spectrogram
def recoverS(table, lowFreq = 0, elevated=True, elevation=10e-8):
'''Quick 'Perfect' Recovery of Time-Series from S Transform Spectrogram Generated using sTransform
Input:
table (ndarray) spectrogram table
lowFreq (int, optional) starting frequency
elevated (bool, optional) when True, add elevation to the Gaussian
elevation (float, optional) magnitude of the elevation
Output:
ts_recovered (ndarray) recovered time series
Note:
*only when [0] frequency row encodes full time-series information
'''
tablep = np.copy(table)
length = tablep.shape[1]
s_row = tablep[0]
tsFFT_recovered = np.fft.fft(s_row)/_window_normal(length, lowFreq)
tsFFT_recovered = np.fft.fft(s_row)/_window_normal(length, lowFreq, elevated=elevated, elevation=elevation)

ts_recovered = np.fft.ifft(tsFFT_recovered)

return ts_recovered
return ts_recovered

def inverseS(table, lowFreq = 0, elevated=True, elevation =10e-8):
'''The True Inverse S Transform (without optimization)
Input:
table (ndarray) spectrogram table
lowFreq (int, optional) starting frequency
elevated (bool, optional) when True, add elevation to the Gaussian
elevation (float, optional) magnitude of the elevation
Output:
ts_recovered (ndarray) recovered time series
recovered_tsFFT (ndarray) the recovered FFT of the time series (left side only)
Note:
ts_recovered is not optimized
'''
tablep = np.copy(table)
length = tablep.shape[1]
recovered_tsFFT = np.zeros(length, dtype='c8')

full_tsFFT = np.fft.fft(tablep[0])/_window_normal(length, 0)

for i in range(tablep.shape[0]):
recovered_tsFFT[i] = np.fft.fft(tablep[i])[0]/_window_normal(length, i, elevated=True, elevation = 10e-8)[0]

recovered_ts = np.fft.ifft(recovered_tsFFT)*2

return recovered_ts, recovered_tsFFT
Binary file modified img/original_spectrogram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/reconstruction_error.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/recovered_spectrogram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/recovered_ts_error.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 52c40ac

Please sign in to comment.