From 269637ccae7624b570ff7b039922aab761d338fd Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Wed, 14 Aug 2024 09:53:40 +0200
Subject: [PATCH] Clarify input data and expected SNR.

---
 .../model/pfb_bunton_annotated/reconstruct.m  | 54 +++++++++++++------
 1 file changed, 39 insertions(+), 15 deletions(-)

diff --git a/applications/lofar2/model/pfb_bunton_annotated/reconstruct.m b/applications/lofar2/model/pfb_bunton_annotated/reconstruct.m
index 22c31fcdca..c4f1200dcd 100644
--- a/applications/lofar2/model/pfb_bunton_annotated/reconstruct.m
+++ b/applications/lofar2/model/pfb_bunton_annotated/reconstruct.m
@@ -8,47 +8,65 @@
 % Correct = 1 applies the correction filter to the reconstructed signal
 % outData
 % John Bunton 2015
+%
+% Usage from README.txt:
+% . first run Gen_filter12 to create prototype lowpass filter cl
+% . then run reconstruct with ImpulseResponse = 1 and Correct = 1 to calculate
+%   an impulse response and a correction filter for the analysis PFB and
+%   synthesis PFB transfer function error
+% . then rerun reconstruct with ImpulseResponse = 0 and Correct = 0 or 1
+% . use rng('default') to check SNR results, comment rng() to experiment with
+%   new noise input evry rerun
 
 close all
 
+% Uncomment rng() line or run rng() line first in shell, to produce same random
+% numbers as with MATLAB restart, to verify the SNR results for Correct = 0, 1.
+rng('default')
+
 ImpulseResponse = 0;  % set to 1 to calculate correction filter
 Correct = 1;          % set to 1 to allow correction filter to be applied
 
-len = 5000;
-z = rand(len,1);
-z = z > 0.5;
-z = 2 * (z - 0.5);
-
 % cl is the prototype lowpass filter
 Ncoefs = length(cl);  % = 2304
 Ntaps = 12;
 Nfft = Ncoefs / Ntaps;  % = 192
 
+% Input data
+% 1) random block wave signal
 % Create random block wave signal with block size Nhold = 16 samples, first
 % insert 16-1 zeros between every sample in z. This yield length
 % (len - 1) * 16 + 1. Then convolve with ones(16, 1) to replicate each value
 % of z instead of the zeros. The length of conv(A, B) is length(A) +
 % length(B) - 1, so length of inData becomes ((len - 1) * 16 + 1) + (16 - 1) =
 % len * 16 = 80000.
+len = 5000;
+z = rand(len,1);
+z = z > 0.5;
+z = 2 * (z - 0.5);
 clear inData
 Nhold = 16;
 inData(1:Nhold:len*Nhold) = z;
 inData = conv(inData, ones(Nhold, 1));
-k = len * Nhold;  % = length(inData)
+k = length(inData);  % = len * Nhold
+
+% 2) random normal noise signal
+%inData = randn(1, k);  % yields similar SNR as random block wave signal
 
-%inData = cos(((1:k).^2 ) * len / (k)^2);  % comment out these two line to have random signal input
+% 3) sine wave signal
+%inData = cos(((1:k).^2 ) * len / (k)^2);
 %inData = cos(2*pi*(1:k) * 0.031 / 16);
 
+% 4) impulse signal
 if ImpulseResponse == 1
-    inData = inData .* 0;   % for testing impulse response of system
-    inData(k / 2) = 1;  % and allows calculation of correction filter
+    inData = inData .* 0;  % for testing impulse response of system
+    inData(k / 2) = 1;     % and allows calculation of correction filter
 end
 
 % Set up parameters for the analysis and synthesis filterbank
 Ros = 32 / 24;
 % fix() rounds to nearest integer towards zero.
 Nstep = fix(Nfft / Ros);  % = 144
-clf
 
 % these is the actual analysis and synthesis operations
 outBins = polyphase_analysis(inData, cl, Nfft, Nstep);
@@ -62,8 +80,8 @@ adjust = adjust * Nfft;  % normalize gain per bin for synthesis LPF
 outData = adjust * outData;
 
 if ImpulseResponse == 1
-     % correction filter to fix frequency response error, also
-     % corrects gain because input inData has unit level
+    % correction filter to fix frequency response error, also
+    % corrects gain because input inData has unit level
     correct = real(ifft(1./fft(outData)));
 end
 
@@ -78,7 +96,7 @@ corr = correct;
 % Correct for time shift for transfer function correction filter
 corr(1+k:length(corr)) = corr(1:length(corr)-k);
 
-% Correct for errror in transfer function
+% Correct for error in transfer function
 if Correct == 1
     outData = ifft(fft(outData) .* fft(fftshift(corr)));
 end
@@ -87,10 +105,16 @@ end
 diff = outData - inData(1:length(outData));
 
 % SNR
-% First do rng('default') to reset the random number generator, then
-% run reconstruct. The original code by John Bunton then yields:
+% First do rng('default') to reset the random number generator, then run
+% reconstruct. The original code by John Bunton for the random block wave wave
+% input signal then yields:
 % . rng('default'); reconstruct, with Correct = 0: SNR = 30.56 dB
 % . rng('default'); reconstruct, with Correct = 1: SNR = 62.24 dB
+% Note:
+% . With the impulse data input the SNR = 304.46 dB, so perfect.
+% . For other input data there is still some error, due to the limited stopband
+%   attenuation of the prototype LPF (can be seen using DEVS = 0.003 instead of
+%   0.0003 in Gen_filter12).
 SNR = 10 * log10(sum(abs(inData(10000:70000) .^ 2)) / sum(abs(diff(10000:70000) .^ 2)));
 sprintf('SNR = %6.2f [dB]', SNR)
 
-- 
GitLab