Dash MATLAB Example: Signal with FFT and noise

New to Dash MATLAB®? See:

Follow this link to see more examples and learn how to use Dash for MATLAB®!

We encorage you to ask any questions you may have about Dash for MATLAB®. We are here to help! You can also share your ideas with the community.

In this example we are going to see how can we make a Dash app with some signal, and compute its Fast Fourier Transform.

This app will have two subplots (one for the original signal, and another for the fft), four sliders, and a boolean swtich.

The function we are going to use is:

A1·Sin(2·π·f1·t) + A2·Sin(2·π·f2·t)

Therefore we have one slider for each parameter: A1, A2, f1 and f2.

The boolean switch lets us choose whether we want to add a random noise to the signal or not.

The running app looks like this:

fftExample

Make a new MATLAB script called fftApp.m with the following code:

terminate(pyenv);
clearvars;

uiFigure = uifigure('visible', 'off');
size = [12, 12];
uiGrid = uigridlayout(uiFigure, size);

% Initial Plot
ax = axes(uiGrid);
ax.Tag = 'my-plot';

% Toggle FFT switch
switchButton = uiswitch(uiGrid, 'Tag', 'my-switch');
switchButton.Layout.Row = 1;
switchButton.Layout.Column = 8;

switchLabel = uilabel(uiGrid, 'Text', 'Touch to add/remove noise',...
    'FontSize', 14, 'FontColor', 'white');
switchLabel.Layout.Row = 1;
switchLabel.Layout.Column = 8;

% Frequency 1
frequencySlider1 = uislider(uiGrid, 'Tag', 'freq-slider-1');
frequencySlider1.Value = 50;
frequencySlider1.MajorTicks = (0:25:500);
frequencySlider1.Layout.Row = 3;
frequencySlider1.Layout.Column = [1, 6];

frequencyLabel1 = uilabel(uiGrid, 'Text', 'Frequency 1',...
    'FontSize', 16, 'FontWeight', 'bold', 'FontColor', 'white');
frequencyLabel1.Layout.Row = 2;
frequencyLabel1.Layout.Column = [2, 4];

% Frequency 2
frequencySlider2 = uislider(uiGrid, 'Tag', 'freq-slider-2');
frequencySlider2.Limits = [0 140];
frequencySlider2.Value = 125.0;
frequencySlider2.MajorTicks = (0:25:500);
frequencySlider2.Layout.Row = 3;
frequencySlider2.Layout.Column = [7, 12];

frequencyLabel1 = uilabel(uiGrid, 'Text', 'Frequency 2',...
    'FontSize', 16, 'FontWeight', 'bold', 'FontColor', 'white');
frequencyLabel1.Layout.Row = 2;
frequencyLabel1.Layout.Column = [9, 11];

% Amplitude 1
amplitudeSlider1 = uislider(uiGrid, 'Tag', 'ampl-slider-1');
amplitudeSlider1.Value = 0.7;
amplitudeSlider1.MajorTicks = (0:0.1:2);
amplitudeSlider1.Layout.Row = 5;
amplitudeSlider1.Layout.Column = [1, 6];

amplitudeLabel1 = uilabel(uiGrid, 'Text', 'Amplitude 1',...
    'FontSize', 16, 'FontWeight', 'bold', 'FontColor', 'white');
amplitudeLabel1.Layout.Row = 4;
amplitudeLabel1.Layout.Column = [2, 4];

% Amplitude 2
amplitudeSlider2 = uislider(uiGrid, 'Tag', 'ampl-slider-2');
amplitudeSlider2.Value = 1.0;
amplitudeSlider2.MajorTicks = (0:0.1:2);
amplitudeSlider2.Layout.Row = 5;
amplitudeSlider2.Layout.Column = [7, 12];

amplitudeLabel2 = uilabel(uiGrid, 'Text', 'Amplitude 2',...
    'FontSize', 16, 'FontWeight', 'bold', 'FontColor', 'white');
amplitudeLabel2.Layout.Row = 4;
amplitudeLabel2.Layout.Column = [9, 11];

args = {...
    argsOut('my-plot', 'figure'),...
    argsIn('freq-slider-1','value'),...
    argsIn('freq-slider-2','value'),...
    argsIn('ampl-slider-1','value'),...
    argsIn('ampl-slider-2','value'),...
    argsIn('my-switch','on')};  
handle = 'updateGraph'; % Callback function

callbackDat = {args, handle};

% run the app
startDash(uiGrid, 8057, callbackDat, 'SOLAR');

The callback function updateGraph.m:

function plotlyFig = updateGraph(freq1, freq2, amp1, amp2, noiseButton)
    F1 = double(freq1);
    F2 = double(freq2);
    A1 = double(amp1);
    A2 = double(amp2);
    
    % Signal
    subplot(2,1,1);
    Fs = 1000;            % Sampling frequency                    
    T = 1/Fs;             % Sampling period       
    L = 1500;             % Length of signal
    t = (0:L-1)*T;        % Time vector 
    S = A1*sin(2*pi*F1*t) + A2*sin(2*pi*F2*t);
    if strcmp(string(noiseButton), 'true')
        X = S + 2*randn(size(t));
    else
        X = S;
    end
    plot(1000*t(1:50),X(1:50), 'LineWidth', 1.5)
    title(A1+"·sin(2·π·"+F1+"·t)+"+...
        A2+"·sin(2·π·"+F2+"·t)", 'FontSize', 16)
    xlabel('t (milliseconds)', 'FontSize', 14)
    ylabel('X(t)', 'FontSize', 14)
    
    % Compute FFT
    subplot(2,1,2);
    Y = fft(X);
    P2 = abs(Y/L);
    P1 = P2(1:L/2+1);
    P1(2:end-1) = 2*P1(2:end-1);
    f = Fs*(0:(L/2))/L;
    plot(f,P1, 'LineWidth', 1.5) 
    title('Single-Sided Amplitude Spectrum of X(t)', 'FontSize', 16)
    xlabel('f (Hz)', 'FontSize', 14)
    ylabel('|P1(f)|', 'FontSize', 14)

    fig = fig2plotly(gcf, 'offline', true, 'open', false, 'Visible', false);
    addtheme(fig, 'plotly_dark');
    
    plotlyFig1 = {struct('data', {fig.('data')}, 'layout', fig.('layout'))};
    plotlyFig = char(jsonencode(plotlyFig1));
end

You can try to add a third term to the signal, or you can try to include a custom signal from an external file!

1 Like