.. |MLA (TM)| unicode:: MLA U+2122 .. index: Stream Recorder .. _stream-recorder-label: Stream Recorder =============== .. image:: ../Icons/streamrecorder.png :width: 20mm :align: left When scanning a sample, the |MLA (TM)| process end-of-line (EOL) and end-of-file (EOF) triggers and lockin data is stored at pixel locations in a scan file. The stream recorder operates in a different manner: it ignores all triggers and stores data as one continuous, uninterrupted stream. This mode is quite useful for taking data when the AFM probe slowly approachs and retracts from a surface. The data stream can be stored in either :ref:`time-mode-label` or :ref:`frequency-mode-label` (see :ref:`intermodulation-measurement-label`). * ``Start`` will start the stream record. Click again to ``Stop``. If the `Autosave` box is checked in the :ref:`status-bar-label`, each run of the stream recorder will result in a file being saved in the session folder. The file name has the form **record01234** where the number is automatically incremented. In :ref:`time-mode-label` the files will have the **.std** extension, and in :ref:`frequency-mode-label` the files will have the **.imp** extension (see the :ref:`file-management-label` section for more information on file types). Unchecking the ``Autosave`` box will result in no data being saved. * ``Mode`` selects weather the data is stored in :ref:`time-mode-label` or :ref:`frequency-mode-label`. In either mode all data is saved as a continuous stream without any breaks or gaps in the data. * ``Plot`` controls only which data is being plotted and does not effect the saving of data. You can adjust the number of points to be plotted in the past number of seconds. The check boxes enable plotting of the amplitudes (or amplitude and phase in the polar plot) at the different frequencies listed. Note that in the :ref:`time-mode-label` the response at all frequencies in the comb can be examined by analyzing stream data with the Fast Fourier Transform. A script called *PlotTimeMode* (see :ref:`scripting-interface-label`) is provided which gives a simple GUI inteface for plotting and extracting time-mode data taken with the stream recorder. Below we give an example which can be a useful starting point for your own analysis scripts. The script can be copied to a new filename.py, modified and run, for example in the iPython shell. Example script '''''''''''''' This script reads a time-mode stream data file (.std file) and parses it in to time windows or 'beats', on which the signal is periodic. Each time window is assigned an index (the beat index) and the terminal asks for the beat index on which you want to perform analysis. The script extracts that beat from the data file, and simply plots both time data and the frequency data. Note that you must input the path to the AFM Suite on your computer, and the path to the .std file that you want to analyze:: import matplotlib.pyplot as plt import numpy as np import sys # Path to AFM Suite suitepath = '/Users/david_haviland/IntermodulatorSuite' sys.path.append(suitepath) from StreamRecorder import stdfile # Path to stream recorder file in time-mode recorder_path = 'path_to_file.std' # full path to recorder file in .std format print "loading file", recorder_path sf = stdfile.stdfile(recorder_path,b_raw=False,do_scale=False) # Read metadata from file fs = sf.freq_samples # Sampling frequency, Hz f1 = sf.f1 # First drive frequency, Hz f2 = sf.f2 # Second drive frequency, Hz # Calculate number of samples to avoid Fourier leakage n_samples_beat = int(np.round(fs/abs(f2-f1))) # Number of samples in one beat t = 1./fs*np.arange(n_samples_beat) # Time axis for plotting df = fs/n_samples_beat # Frequency resolution freqs = df*np.arange(n_samples_beat/2+1) # Frequency axis for plotting # Index each beat in the stream ii_s = np.arange(0,sf.n_samples,n_samples_beat)[:-1] # remove last since it might not be complete # Loop through all beats and read max value beats_to_plot = 1000 if len(ii_s)<=beats_to_plot: ii_plot = ii_s else: skip = float(len(ii_s))/beats_to_plot ii_plot = np.int_(skip*np.arange(beats_to_plot)) peak = np.zeros(len(ii_plot)) for i,beat_i in enumerate(ii_plot): if i%100==0: print "Beat %i / %i"%(beat_i, len(ii_s)) # Read data i_start = ii_s[beat_i] data = sf.get_samples(i_start,n_samples_beat) peak[i] = max(data) # Plot plt.figure(1) plt.clf() plt.plot(ii_plot,peak) plt.xlabel("Beat index") plt.ylabel("Peak value [ADU]") plt.show() # Ask terminal for beat number, then data from that beat n = -1 while n == -1: s = raw_input("Enter beat index to plot: ") try: n = int(s) except ValueError: print "Input must be an interger" data = sf.get_samples(ii_s[n],n_samples_beat) data_fft = np.fft.rfft(data)/len(data) # Plot plt.figure(2) plt.subplot(211) plt.plot(t,data) plt.xlabel("Time [s]") plt.ylabel("In [ADU]") plt.subplot(212) plt.semilogy(freqs*1e-3,2*abs(data_fft)) plt.xlabel("Frequency [kHz]") plt.ylabel("Amplitude [ADU]") plt.show()