SNR plot and rectangular fit (Matlab) - matlab

I have attached 3 images and the SNR function to calculate the SNR between each of the images. How can I plot this SNR so its easy to understand the levels from the plot rather than just numbers.
SNR function:
% function to calculate the drop in SNR between Best focussed image to
% slightly out of focus image. The value is presented in dB scale and amplitude
%for comparison.
% Terms:
%%Signal image = best focussed image
%%Noise image = slight off focussed image
%%Dark scan = for future reference with respect to Signal image
%---------------Define function to calcuate SNR---------------%
function SNR = SNR(signal, noise, typ, noisy)
% snr - calculate signal-to-noise ratio in decibel or amplitude
%
% Syntax: SNR = snr(signal, noise)
% SNR = snr(signal, signal_noise, typ, true)
%
% Inputs:
% signal - signal amplitude
% noise - noise amplitude or noisy signal
% typ - type of SNR (default:'db' to decibel or 'amp' to amplitude)
% noisy - eval noise flag (use noise as noisy signal)
%
% Outputs:
% SNR - Signal-to-Noise Ratio
%
% Example:
% dt = 0.01;
% T = 0:dt:10;
% sig = sin(2*pi*T);
% noisy = sig + (0 + .5 * randn(1,length(T))); % error mean 0 and sd .5
% snr_db = snr(sig,noisy,'db',true)
%
% Other m-files required: none
% Subfunctions: rms
%------------------------------- BEGIN CODE -------------------------------
if ~exist('typ', 'var')
typ = 'db';
end
if ~exist('noisy', 'var')
noisy = false;
end
if noisy % eval noise
noise = signal-noise;
end
if strcmp(typ,'db')
SNR = 20*log10(rms(signal)/rms(noise));
elseif strcmp(typ,'amp')% string comparison for type value.
SNR = rms(signal)/rms(noise);
end
end
%-------------------------------- END CODE --------------------------------
RMS function
function RMS= rms(varargin)
%
% Written by Phillip M. Feldman March 31, 2006
%
% rms computes the root-mean-square (RMS) of values supplied as a
% vector, matrix, or list of discrete values (scalars). If the input is
% a matrix, rms returns a row vector containing the RMS of each column.
% David Feldman proposed the following simpler function definition:
%
% RMS = sqrt(mean([varargin{:}].^2))
%
% With this definition, the function accepts ([1,2],[3,4]) as input,
% producing 2.7386 (this is the same result that one would get with
% input of (1,2,3,4). I'm not sure how the function should behave for
% input of ([1,2],[3,4]). Probably it should produce the vector
% [rms(1,3) rms(2,4)]. For the moment, however, my code simply produces
% an error message when the input is a list that contains one or more
% non-scalars.
if (nargin == 0)
error('Missing input.');
end
% Section 1: Restructure input to create x vector.
if (nargin == 1)
x= varargin{1};
else
for i= 1 : size(varargin,2)
if (prod(size(varargin{i})) ~= 1)
error(['When input is provided as a list, ' ...
'list elements must be scalar.']);
end
x(i)= varargin{i};
end
end
% Section 2: Compute RMS value of x.
RMS= sqrt (mean (x .^2) );
Script
% sig= best focussed image
% noisy= off focussed image
% dark = no light image
%-------------------------
% calculate SNR between:
% sig and noise
% signal and dark
% noise and dark
clear
sig = rgb2gray(imread('S1-BestFocus.bmp'));
noisy = rgb2gray(imread('S1-OffFocus.bmp'));
dark=rgb2gray(imread('DarkScan.bmp'));
sig_noise = SNR(sig,noisy,'db',true);
sig_dark = SNR(sig,dark,'db',true);
noise_dark = SNR(noisy,dark,'db',true);
Figures:
figures for calculation
I am imaging a slit of 15-18 microns in width and 1mm in length, the slit is not uniform, hence I have to check how much is the variation along the length of the slit in terms of width. What is the best possible way to get the measurement. ( one method is to use rectangular fit).

Related

Obtaining steady state solution for spring mass dashpot system

I'm trying to solve the following problem using MATLAB but I faced multiple issues. The plot I obtained doesn't seem right even though I tried to obtain the steady-state solution, I got a plot that doesn't look steady.
The problem I'm trying to solve
The incorrect plot I got.
and here is the code
% system parameters
m=1; k=1; c=.1; wn=sqrt(k/m); z=c/2/sqrt(m*k); wd=wn*sqrt(1-z^2);
% initial conditions
x0=0; v0=0;
%% time
dt=.001; tMax=8*pi; t=0:(tMax-0)/999:tMax;
% input
A=1
omega=(2*pi)/10
F=A/2-(4*A/pi^2)*cos(omega*t); Fw=fft(F);
F=k*A*cos(omega*t); Fw=fft(F);
% normalize
y = F/m;
% compute coefficients proportional to the Fourier series coefficients
Yw = fft(y);
% setup the equations to solve the particular solution of the differential equation
% by the method of undetermined coefficients
N=1000
T=10
k = [0:N/2];
w = 2*pi*k/T;
A = wn*wn-w.*w;
B = 2*z*wn*w;
% solve the equation [A B;-B A][real(Xw); imag(Xw)] = [real(Yw); imag(Yw)] equation
% Note that solution can be obtained by writing [A B;-B A] as a scaling + rotation
% of a 2D vector, which we solve using complex number algebra
C = sqrt(A.*A+B.*B);
theta = acos(A./C);
Ywp = exp(j*theta)./C.*Yw([1:N/2+1]);
% build a hermitian-symmetric spectrum
Xw = [Ywp conj(fliplr(Ywp(2:end-1)))];
% bring back to time-domain (function synthesis from Fourier Series coefficients)
x = ifft(Xw);
figure()
plot(t,x)
Your forcing function doesn't look like the triangle wave in the problem. I edited the %% time section of your code into the following and appeared to give a steady state response.
%% time
TP = 10; % forcing time period (10 s)
dt=.001;
tMax= 3*TP; % needs to be multiple of the time period
t=0:(tMax-0)/999:tMax;
% input
A=1; % Forcing amplitude
omega=(2*pi)/TP;
% forcing is a triangle wave
% generate a triangle wave with min/max values of 0/1.
F = 0*t;
for i = 1:length(t)
if mod(t(i), TP) <= TP/2
F(i) = mod(t(i), TP)/(TP/2);
else
F(i) = 2 - mod(t(i), TP)/(TP/2);
end
end
F = F*A; % scale triangle wave by amplitude
% you can also use MATLAB's sawtooth() function if you have the signal
% processing toolbox

Exponential fitting for matlab

I have my data in arrays which are exponential like e^(ax+c)+d. I'm trying to draw a fit to them.
a = data1 (:,1);
b = data1 (:,2);
log(b);
p = polyfit (a,log(b),1);
But I don't know what to do now. I found an equation by polyfit and I was hoping to take the exponential of the equation I got from polyfit with
exp (0.5632x+2.435)
But I figured out that it doesn't work like that. Does anyone have any suggestions?
try with nonlinear fitting:
%% PARAMETERS (you need this part)
clear all;
clc, clf;
N = 128; % number of datapoints
Nint = N*10; % number of datapoints for curve interpolation
fun = #(prms,x) prms(4).^(prms(1)*x+prms(2))+prms(3); % write your function
iniPrm = rand(4,1); % find some initial values for the parameters (choose meaningful values for better results)
%% SIMULATE DATA (this is only for testing purposes)
SNR = .01; % signal to noise ratio for simulated data
noise = (rand(1,N)-.5)*SNR; % create some random noise
x = linspace(0,10,N); % create the x axis
y = fun(iniPrm,x) + noise; % simulate a dataset that follows the given function
x = x(:); % reshape as a vector
y = y(:); % reshape as a vector
X = linspace(x(1),x(end),Nint); % interpolate the output to plot it smoothly
plot(x,y,'.r','markersize',10); hold on; % plot the dataset
%% FIT AND INTERPOLATE YOUR MODEL
[out.BETA,out.RESID,out.J,out.COVB,out.MSE] = nlinfit(x,y,fun,iniPrm,[]); % model your data
[out.YPRED,out.DELTA] = nlpredci(fun,X,out.BETA,out.RESID,'Covar',out.COVB); % interpolate your model
out.YPREDLOWCI = out.YPRED - out.DELTA; % find lower confidence intervals of your fitting
out.YPREDUPCI = out.YPRED + out.DELTA; % find upper confidence intervals of your fitting
out.X = X; % store the interpolated X
%% PLOT FITTING
plotCI = #(IO,spec) patch([IO.X(:);flipud(IO.X(:))],[IO.YPREDLOWCI(:);flipud(IO.YPREDUPCI(:))],spec{:}); % create patches: IE: patch(0:10,10:-1:0,ones(10,1)-1,1,{'r','facealpha',0.2})
plot(X,out.YPRED,'-b','linewidth',3);
plotCI(out,{'r','facealpha',.3,'edgealpha',0})

bin2mat running slow need a faster solution

I am using bin2mat function from matlab file exchange, for some reason it runs very slow. Is it possible to make it run faster or is there an alternative? I am trying: zC = bin2mat(s.X,s.Y,s.Z,xC,yC); I am not sure where it gets bogged down. I need to do this on point cloud data to calculate volume and such.
Here is the code:
function ZG = bin2mat(x,y,z,XI,YI,varargin)
% BIN2MAT - create a matrix from scattered data without interpolation
%
% ZG = BIN2MAT(X,Y,Z,XI,YI) - creates a grid from the data
% in the (usually) nonuniformily-spaced vectors (x,y,z)
% using grid-cell averaging (no interpolation). The grid
% dimensions are specified by the uniformily spaced vectors
% XI and YI (as produced by meshgrid).
%
% ZG = BIN2MAT(...,#FUN) - evaluates the function FUN for each
% cell in the specified grid (rather than using the default
% function, mean). If the function FUN returns non-scalar output,
% the output ZG will be a cell array.
%
% ZG = BIN2MAT(...,#FUN,ARG1,ARG2,...) provides aditional
% arguments which are passed to the function FUN.
%
% EXAMPLE
%
% %generate some scattered data
% [x,y,z]=peaks(150);
% ind=(rand(size(x))>0.9);
% xs=x(ind); ys=y(ind); zs=z(ind);
%
% %create a grid, use lower resolution if
% %no gaps are desired
% xi=min(xs):0.25:max(xs);
% yi=min(ys):0.25:max(ys);
% [XI,YI]=meshgrid(xi,yi);
%
% %calculate the mean and standard deviation
% %for each grid-cell using bin2mat
% Zm=bin2mat(xs,ys,zs,XI,YI); %mean
% Zs=bin2mat(xs,ys,zs,XI,YI,#std); %std
%
% %plot the results
% figure
% subplot(1,3,1);
% scatter(xs,ys,10,zs,'filled')
% axis image
% title('Scatter Data')
%
% subplot(1,3,2);
% pcolor(XI,YI,Zm)
% shading flat
% axis image
% title('Grid-cell Average')
%
% subplot(1,3,3);
% pcolor(XI,YI,Zs)
% shading flat
% axis image
% title('Grid-cell Std. Dev.')
%
% SEE also RESHAPE ACCUMARRAY FEVAL
% A. Stevens 3/10/2009
% astevens#usgs.gov
%check inputs
error(nargchk(5,inf,nargin,'struct'));
%make sure the vectors are column vectors
x = x(:);
y = y(:);
z = z(:);
if all(any(diff(cellfun(#length,{x,y,z}))));
error('Inputs x, y, and z must be the same size');
end
%process optional input
fun=#mean;
test=1;
if ~isempty(varargin)
fun=varargin{1};
if ~isa(fun,'function_handle');
fun=str2func(fun);
end
%test the function for non-scalar output
test = feval(fun,rand(5,1),varargin{2:end});
end
%grid nodes
xi=XI(1,:);
yi=YI(:,1);
[m,n]=size(XI);
%limit values to those within the specified grid
xmin=min(xi);
xmax=max(xi);
ymin=min(yi);
ymax=max(yi);
gind =(x>=xmin & x<=xmax & ...
y>=ymin & y<=ymax);
%find the indices for each x and y in the grid
[junk,xind] = histc(x(gind),xi);
[junk,yind] = histc(y(gind),yi);
%break the data into a cell for each grid node
blc_ind=accumarray([yind xind],z(gind),[m n],#(x){x},{NaN});
%evaluate the data in each grid using FUN
if numel(test)>1
ZG=cellfun(#(x)(feval(fun,x,varargin{2:end})),blc_ind,'uni',0);
else
ZG=cellfun(#(x)(feval(fun,x,varargin{2:end})),blc_ind);
end
It is slower on these two steps for one run it took:
ZG=cellfun(#(x)(feval(fun,x,varargin{2:end})),blc_ind); took 33 secs
blc_ind=accumarray([yind xind],z(gind),[m n],#(x){x},{NaN}); took 10 secs
You can change blc_ind = ... to
ZG=accumarray([yind xind],z(gind),[m n],#mean,NaN);
and delete other codes form here so the is no need to if numel(test)>1....

How can I debug the following Matlab code?

The error
File: parameter_estimation_1.m Line: 8 Column: 10
Unexpected MATLAB expression.
crops up when I run the following MATLAB code:
T = 0:0.25:5; % time vector (row)
T = T'; % time vector (column)
seed = [3;0.5]; % seed for noise generation
randn('state',seed); % using the same seed each time
uu = 0.5 1 0.25*randn(length(T),1); % mean of 0.5 with variance
% of 0.25
U = 2*round(uu)-1; % creates PRBS with -1 and 1 values %
sim('est_vdv'); % runs simulation of linear van de vusse % diagram
figure(1); % plot input-output data
subplot(2,1,1),plot(tp,yp,'k',t,y,'ko');
xlabel('time, min'), ylabel('y')
title('PRBS estimation example')
subplot(2,1,2),plot(tp,up,'k'); xlabel('time, min'),ylabel('u')
axis([0 5 -1.1 1.1])
% % generate phi matrix for estimation
for j = 4:22;
phi(j-3,:) = [y(j-2) y(j-3) u(j-2) u(j-3)];
end
%
theta = inv(phi'*phi)*phi'*y(3:21) % estimate parameters
num = [theta(3) theta(4)]; % numerator of discrete transfer function
den = [1 -theta(1) -theta(2)]; % denominator of discrete transfer function
sysd = tf(num,den,0.25) % create discrete tf object
tzero(sysd) % calculate zeros
pole(sysd) % calculate poles
syszpk = zpk(sysd) % zero-pole-k form
This code is supposed to run in tandem with a SIMULINK model titled "est_vdv" to estimate the parameters of a model.
How should I deal with this error?
Thanks Friends for your suggestions, I have been able to figure out what went wrong with the 5th line, it should have been
uu=0.5+0.25.*randn(length(T),1)
Sorry, it was wrongly indicated that the error was in the 8th line.

Morlet wavelet transformation function returns nonsensical plot

I have written a matlab function (Version 7.10.0.499 (R2010a)) to evaluate incoming FT signal and calculate the morlet wavelet for the signal. I have a similar program, but I needed to make it more readable and closer to mathematical lingo. The output plot is supposed to be a 2D plot with colour showing the intensity of the frequencies. My plot seems to have all frequencies the same per time. The program does make an fft per row of time for each frequency, so I suppose another way to look at it is that the same line repeats itself per step in my for loop. The issue is I have checked with the original program, which does return the correct plot, and I cannot locate any difference beyond what I named the values and how I organized the code.
function[msg] = mile01_wlt(FT_y, f_mn, f_mx, K, N, F_s)
%{
Fucntion to perform a full wlt of a morlet wavelett.
optimization of the number of frequencies to be included.
FT_y satisfies the FT(x) of 1 envelope and is our ft signal.
f min and max enter into the analysis and are decided from
the f-image for optimal values.
While performing the transformation there are different scalings
on the resulting "intensity".
Plot is made with a 2D array and a colour code for intensity.
version 05.05.2016
%}
%--------------------------------------------------------------%
%{
tableofcontents:
1: determining nr. of analysis f, prints and readies f's to be used.
2: ensuring correct orientation of FT_y
3:defining arrays
4: declaring waveletdiagram and storage of frequencies
5: for-loop over all frequencies:
6: reducing file to manageable size by truncating time.
7: marking plot to highlight ("randproblemer")
8: plotting waveletdiagram
%}
%--------------------------------------------------------------%
%1: determining nr. of analysis f, prints and readies f's to be used.
DF = floor( log(f_mx/f_mn) / log(1+( 1/(8*K) ) ) ) + 1;% f-spectre analysed
nr_f_analysed = DF %output to commandline
f_step = (f_mx/f_mn)^(1/(DF-1)); % multiplicative step for new f_a
f_a = f_mn; %[Hz] frequency of analysis
T = N/F_s; %[s] total time sampled
C = 2.0; % factor to scale Psi
%--------------------------------------------------------------%
%2: ensuring correct orientation of FT_y
siz = size(FT_y);
if (siz(2)>siz(1))
FT_y = transpose(FT_y);
end;
%--------------------------------------------------------------%
%3:defining arrays
t = linspace(0, T*(N-1)/N, N); %[s] timespan
f = linspace(0, F_s*(N-1)/N, N); %[Hz] f-specter
%--------------------------------------------------------------%
%4: declaring waveletdiagram and storage of frequencies
WLd = zeros(DF,N); % matrix of DF rows and N columns for storing our wlt
f_store = zeros(1,DF); % horizontal array for storing DF frequencies
%--------------------------------------------------------------%
%5: for-loop over all frequencies:
for jj = 1:DF
o = (K/f_a)*(K/f_a); %factor sigma
Psi = exp(- 0*(f-f_a).*(f-f_a)); % FT(\psi) for 1 envelope
Psi = Psi - exp(-K*K)*exp(- o*(f.*f)); % correctional element
Psi = C*Psi; %factor. not set in stone
%next step fits 1 row in the WLd (3 alternatives)
%WLd(jj,:) = abs(ifft(Psi.*transpose(FT_y)));
WLd(jj,:) = sqrt(abs(ifft(Psi.*transpose(FT_y))));
%WLd(jj,:) = sqrt(abs(ifft(Psi.*FT_y))); %for different array sizes
%and emphasizes weaker parts.
%prep for next round
f_store (jj) = f_a; % storing used frequencies
f_a = f_a*f_step; % determines the next step
end;
%--------------------------------------------------------------%
%6: reducing file to manageable size by truncating time.
P = floor( (K*F_s) / (24*f_mx) );%24 not set in stone
using_every_P_point = P %printout to cmdline for monitoring
N_P = floor(N/P);
points_in_time = N_P %printout to cmdline for monitoring
% truncating WLd and time
WLd2 = zeros(DF,N_P);
for jj = 1:DF
for ii = 1:N_P
WLd2(jj,ii) = WLd(jj,ii*P);
end
end
t_P = zeros(1,N_P);
for ii = 1:N_P % set outside the initial loop to reduce redundancy
t_P(ii) = t(ii*P);
end
%--------------------------------------------------------------%
%7: marking plot to highlight boundary value problems
maxval = max(WLd2);%setting an intensity
mxv = max(maxval);
% marks in wl matrix
for jj= 1:DF
m = floor( K*F_s / (P*pi*f_store(jj)) ); %finding edges of envelope
WLd2(jj,m) = mxv/2; % lower limit
WLd2(jj,N_P-m) = mxv/2;% upper limit
end
%--------------------------------------------------------------%
%8: plotting waveletdiagram
figure;
imagesc(t_P, log10(f_store), WLd2, 'Ydata', [1 size(WLd2,1)]);
set(gca, 'Ydir', 'normal');
xlabel('Time [s]');
ylabel('log10(frequency [Hz])');
%title('wavelet power spectrum'); % for non-sqrt inensities
title('sqrt(wavelet power spectrum)'); %when calculating using sqrt
colorbar('location', 'southoutside');
msg = 'done.';
There are no error message, so I am uncertain what exactly I am doing wrong.
Hope I followed all the guidelines. Otherwise, I apologize.
edit:
my calling program:
% establishing parameters
N = 2^(16); % | number of points to sample
F_s = 3.2e6; % Hz | samplings frequency
T_t = N/F_s; % s | length in seconds of sample time
f_c = 2.0e5; % Hz | carrying wave frequency
f_m = 8./T_t; % Hz | modulating wave frequency
w_c = 2pif_c; % Hz | angular frequency("omega") of carrying wave
w_m = 2pif_m; % Hz | angular frequency("omega") of modulating wave
% establishing parameter arrays
t = linspace(0, T_t, N);
% function variables
T_h = 2*f_m.*t; % dimless | 1/2 of the period for square signal
% combined carry and modulated wave
% y(t) eq. 1):
y_t = 0.5.*cos(w_c.*t).*(1+cos(w_m.*t));
% y(t) eq. 2):
% y_t = 0.5.*cos(w_c.*t)+0.25*cos((w_c+w_m).*t)+0.25*cos((w_c-w_m).*t);
%square wave
sq_t = cos(w_c.*t).*(1 - mod(floor(t./T_h), 2)); % sq(t)
% the following can be exchanged between sq(t) and y(t)
plot(t, y_t)
% plot(t, sq_t)
xlabel('time [s]');
ylabel('signal amplitude');
title('plot of harmonically modulated signal with carrying wave');
% title('plot of square modulated signal with carrying wave');
figure()
hold on
% Fourier transform and plot of freq-image
FT_y = mile01_fftplot(y_t, N, F_s);
% FT_sq = mile01_fftplot(sq_t, N, F_s);
% Morlet wavelet transform and plot of WLdiagram
%determining K, check t-image
K_h = 57*4; % approximation based on 1/4 of an envelope, harmonious
%determining f min and max, from f-image
f_m = 1.995e5; % minimum frequency. chosen to showcase all relevant f
f_M = 2.005e5; % maximum frequency. chosen to showcase all relevant f
%calling wlt function.
name = 'mile'
msg = mile01_wlt(FT_y, f_m, f_M, K_h, N, F_s)
siz = size(FT_y);
if (siz(2)>siz(1))
FT_y = transpose(FT_y);
end;
name = 'arnt'
msg = arnt_wltransf(FT_y, f_m, f_M, K_h, N, F_s)
The time image has a constant frequency, but the amplitude oscillates resempling a gaussian curve. My code returns a sharply segmented image over time, where each point in time holds only 1 frequency. It should reflect a change in intensity across the spectra over time.
hope that helps and thanks!
I found the error. There is a 0 rather than an o in the first instance of Psi. Thinking I'll maybe rename the value as sig or something. besides this the code works. sorry for the trouble there