freqdemod-quickstart-1

Author information

John A. Marohn (jam99@cornell.edu)
Department of Chemistry and Chemical Biology
Cornell University
Ithaca, NY USA; 14853-1301

Date

2014/11/23

Abstract

Create a sine wave with noise and demodulate it to obtains the sine wave's frequency.

Preliminaries

So we can import the package in the usual way, use setup.py development mode. Here we are following directions here. In the base directory, run:

python setup.py develop

We should now be able to import parts of the package in the usual way using an import statement


In [42]:
from freqdemod import Signal

Execute the the first line below if you want the plots to show inline. If instead you want each plot to display in a separate pop-up window, then don't execute the first line. Set up plotting defaults so the plots will look nice inline:


In [43]:
%matplotlib inline

import numpy as np
import matplotlib.pylab as plt

font = {'family' : 'serif',
        'weight' : 'normal',
        'size'   : 20}

plt.rc('font', **font)
plt.rcParams['figure.figsize'] = 8, 6

Create a test signal

The test signal is a sine wave with noise added.


In [44]:
fd = 50.0e3    # digitization frequency
f0 = 2.00e3    # signal frequency
nt = 60e3      # number of signal points    
sn = 1.0       # signal zero-to-peak amplitude
sn_rms = 0.01  # noise rms amplitude

dt = 1 / fd
t = dt * np.arange(nt)
signal = sn * np.sin(2*np.pi*f0*t) + np.random.normal(0, sn_rms, t.size)

Plot the test signal


In [45]:
plt.plot(1E3*t[0:100], signal[0:100])
plt.xlabel('time [ms]')
plt.ylabel('amplitude [nm]')
plt.show()


Load the test signal into a Signal object

Create an instance of the Signal object


In [46]:
s = Signal()     # Create a signal
s.load_nparray(signal,"x","nm",dt)   # Load the data into the file

Process the Signal object

Open the Signal file and process it.


In [47]:
s.time_mask_binarate("middle")  # Pull out the middle section
s.time_window_cyclicize(3E-3)   # Force the data to start and end at zero
s.fft()                         # Fourier transform the data
s.freq_filter_Hilbert_complex() # Take the complex Hilbert transform
s.freq_filter_bp(1.00)          # Apply a 1 kHz wide bandpass filter
s.time_mask_rippleless(15E-3)   # Set up a filter to remove ripple
s.ifft()                        # Inverse Fourier transform the data
s.fit_phase(221.34E-6)          # Fit the phase vs time data

Plot the intermediate results

Decide wheter to plot using LaTeX axes labels. Using latex=True may make plotting very slow, so I suggest using latex=False to start.


In [48]:
latex = False

Begin by re-plotting the data


In [49]:
s.plot('y', LaTeX=latex)


Plot the intermediate results


In [50]:
s.plot('workup/time/mask/binarate', LaTeX=latex)



In [51]:
s.plot('workup/time/window/cyclicize', LaTeX=latex)



In [52]:
s.plot('workup/freq/FT', LaTeX=latex, component='abs')



In [53]:
s.plot('workup/freq/filter/Hc', LaTeX=latex)



In [54]:
s.plot('workup/freq/filter/bp', LaTeX=latex)



In [55]:
s.plot('workup/time/mask/rippleless', LaTeX=latex)


Summarize the data workup

The signal object creates a comment which summarizes the data workup. Print out this comment.


In [56]:
print(s)


Signal report
=============
* HDF5 file 172119-b8b743.h5 created in core memory

* Add a signal x[nm] of length 60000, time step 20.000 us, and duration 1.200 s

* Make an array, workup/time/mask/binarate, to be used to truncate the signal to be 32768 points long (a power of two). The truncated array will start at point 13616 and stop before point 46384.

* Create a windowing function, workup/time/window/cyclicize, with a rising/falling blackman filter having a rise/fall time of 3000.000 us (150 points).

* Fourier transform the windowed signal. It took 6.1 ms to compute the FFT.

* Create the complex Hilbert transform filter.

* Create a bandpass filter with center frequency = 2.000427 kHz, bandwidth = 1.000 kHz, and order = 50. Best estimate of the resonance frequency = 1.996504 kHz.

* Make an array, workup/time/mask/rippleless, to be used to remove leading and trailing ripple.  The dead time is 15000.000 us.

* Apply an inverse Fourier transform.

* Curve fit the phase data. The target chunk duration is 221.340 us; the actual chunk duration is 220.000 us (11 points). The associated Nyquist frequency is 2.273 kHz. A total of 2842 chunks will be curve fit, corresponding to 625.240 ms of data.

* Curve fit the phase data. The target chunk duration is 221.340 us; the actual chunk duration is 220.000 us (11 points). The associated Nyquist frequency is 2.273 kHz. A total of 2842 chunks will be curve fit, corresponding to 625.240 ms of data. It took 1.3 ms to perform the curve fit and obtain the frequency.

Plot the primary results

... including the complex signal, the amplitude, the phase, and the frequency.


In [57]:
s.plot('workup/time/z', LaTeX=latex, component='both')



In [58]:
s.plot('workup/time/a', LaTeX=latex)



In [59]:
s.plot('workup/time/p', LaTeX=latex)



In [60]:
s.plot('workup/fit/y', LaTeX=latex)


Explore the Signal object


In [61]:
s.list()


Signal file summary
===================
<HDF5 file "172119-b8b743.h5" (mode r+)> (File) /
     y (Dataset) /y     len = (60000,)
     x (Dataset) /x     len = (60000,)
     workup (Group) /workup
         freq (Group) /workup/freq
             filter (Group) /workup/freq/filter
                 Hc (Dataset) /workup/freq/filter/Hc     len = (32768,)
                 bp (Dataset) /workup/freq/filter/bp     len = (32768,)
             freq (Dataset) /workup/freq/freq     len = (32768,)
             FT (Dataset) /workup/freq/FT     len = (32768,)
         fit (Group) /workup/fit
             y (Dataset) /workup/fit/y     len = (2842,)
             x (Dataset) /workup/fit/x     len = (2842,)
         time (Group) /workup/time
             a (Dataset) /workup/time/a     len = (31268,)
             x_binarated (Dataset) /workup/time/x_binarated     len = (32768,)
             mask (Group) /workup/time/mask
                 rippleless (Dataset) /workup/time/mask/rippleless     len = (32768,)
                 binarate (Dataset) /workup/time/mask/binarate     len = (60000,)
             x_rippleless (Dataset) /workup/time/x_rippleless     len = (31268,)
             p (Dataset) /workup/time/p     len = (31268,)
             window (Group) /workup/time/window
                 cyclicize (Dataset) /workup/time/window/cyclicize     len = (32768,)
             z (Dataset) /workup/time/z     len = (31268,)

Clean up

Close the signal file.


In [62]:
s.close()