Example: Dual basis pursuit (dual BP) with the DFT and STFT

Decompose a signal into two distinct signal components using dual basis pursuit (BP); i.e., MCA. In this example, the signal is the sum of a sinusoid and a pulse. The DFT and STFT are used for the two transforms.

Ivan Selesnick
November, 2013

Contents

Start

clear
% close all

I = sqrt(-1);

Create data

Sinusoid + pulse

N = 100;                    % N : signal length
n = 0:N-1;

f1 = 0.112;
s1 = sin(2*pi*f1*n);      % s1 : complex sinusoid

f2 = 0.15;
K = 20;                     % K : duration of transient
M = 55;                     % M : start-time of transient
A = 3;
s2 = zeros(size(n));        % s2 : transient
s2(M+(1:K)) = A*sin(2*pi*f2*(1:K)) .* hamming(K)';

y = s1 + s2;                % Add two components

figure(1)
clf

subplot(2, 1, 1)
plot(n, y)
title('Noise-free signal')
xlabel('Time')

Define transforms

K = 200;                    % K : length of DFT
[A1, A1H, normA1] = MakeTransforms('DFT', N, K);

R = 16;                     % R : frame length
Nfft = 16;                  % Nfft : DFT length in STFT (Nfft >= R)
[A2, A2H, normA2] = MakeTransforms('STFT', N, [R Nfft]);
Reconstruction error = 0.000000
Energy ratio = 1.000000
Reconstruction error = 0.000000
Energy ratio = 1.000000

Verify transform A1

Verify properties of transform A1 (A AH = I)

% Verify perfect reconstruction property of transform 1 (A1*A1H = I)
c = A1H(y);
err = y - A1(c);
re = max(abs(err(:)));          % should be zero
fprintf('Reconstruction error = %f\n', re)

% Verify Parseval energy identity
E = sum(abs(y(:)).^2);
E1 = sum(abs(c(:)).^2);         % should be unity
fprintf('Energy ratio = %f\n', E1/E)
Reconstruction error = 0.000000
Energy ratio = 1.000000

Verify transform A2

Verify properties of transform A2 (A AH = I)

% Verify perfect reconstruction property of transform 2 (A2*A2H = I)
c = A2H(y);
err = y - A2(c);
re = max(abs(err(:)));          % should be zero
fprintf('Reconstruction error = %f\n', re)

% Verify Parseval energy identity
E = sum(abs(y(:)).^2);
E1 = sum(abs(c(:)).^2);         % should be unity
fprintf('Energy ratio = %f\n', E1/E)
Reconstruction error = 0.000000
Energy ratio = 1.000000

Peform signal separation using dual BP

Use 'dualBP' (dual basis pursuit) to separate the signal into two components.

% Algorithm parameters
theta = 0.5;              % theta : trade-off parameter (0 < theta < 1)
Nit = 100;                % Nit : number of iterations
mu = 1;                   % mu : ADMM parameter

[x1, x2, c1, c2, cost] = dualBP(y, A1, A1H, A2, A2H, theta, mu, Nit);

% Display cost function history
figure(1)
clf
plot(cost)
xlim([0 Nit])
title('Cost function history')
xlabel('Iteration')

Display signal components

figure(1)
clf

subplot(2, 1, 1)
plot(n, real(x1))
title('DFT component [Output of dual BP]');
xlabel('Time')
ylabel('real( A1 c1)')

subplot(2, 1, 2)
plot(n, real(x2))
title('STFT component [Output of dual BP]');
xlabel('Time')
ylabel('real( A2 c2)')

Display sparse component coefficients

f = (0:K-1)/K;          % f : frequency axis

tt = R/2 * ( (0:size(c2, 2)) - 1 );  % tt : time axis for STFT

figure(2)
clf

subplot(2, 1, 1)
plot(f, abs(c1))
title('Dual-BP DFT coefficients (c1, Output of dual BP)')
xlabel('Frequency')

subplot(2, 1, 2)
imagesc(tt, [0 1], abs(c2))
xlim([0 N])
ylim([0 1])
axis xy
title('Dual-BP STFT coefficients (c2, Output of dual BP)')
xlabel('Time')
ylabel('Frequency')

cm = colormap(gray);                % cm : colormap for STFT
cm = cm(end:-1:1, :);
colormap(cm)

Save figure to file

MyGraphPrefs('on')

figure(4)
clf

ylim1 = 4*[-1 1];

subplot(5, 1, 1)
line(n, y)
mytitle('y = s1 + s2');
xlabel('Time')
ylim(ylim1)

% Display sparse component coefficients

subplot(5, 1, 2)
line(f, abs(c1), 'marker', '.')
mytitle('DFT coefficients (c1) [Output of dual-BP]');
xlabel('Frequency')
ylabel('abs( c1 )')
xlim([0 0.5])

subplot(5, 1, 3)
imagesc(tt, [0 1], abs(c2))
xlim([0 N])
ylim([0 0.5])
axis xy
mytitle('STFT coefficients (c2) [Output of dual-BP]');
xlabel('Time')
ylabel('Frequency')
colormap(cm)
box off

% Dispaly signal components

subplot(5, 1, 4)
line(n, real(x1))
mytitle('Sinusoid component (reconstructed from c1)');
ylabel('real(A1 c1)')
xlabel('Time')
ylim(ylim1)

subplot(5, 1, 5)
line(n, real(x2))
ylim(ylim1)
mytitle('Pulse component (reconstructed from c2)');
ylabel('real(A2 c2)')
xlabel('Time')


% print figure to pdf file
orient tall
print -dpdf figures/dualBP_example1

% print figure to eps file
set(gcf, 'PaperPosition', [1 1 4.7 9])
print -deps figures_eps/dualBP_example1

MyGraphPrefs('off')