bin2mat running slow need a faster solution - matlab

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....

Related

"Not enough input arguments" when publishing MATLAB commands

I've written the following code:
function [a1,b1,a0,b0] = Conformal_2D(x_input,y_input,X_output,Y_output)
%%
% Calculates parameters $a,b,a_0,b_0$ in the following equation using least
% squares
%%
%
% $$X=a_1x+b_1y+a_0$$
%
% $$X=-b_1x+a_1y+b_0$$
%%
% *Arguments:*
%
% x_input is a $n\times 1$ matrix containing x coordinate of control points
% in the input space
%
% y_input is a $n\times 1$ matrix containing y coordinate of control points
% in the input space
%
% x_output is a $n\times 1$ matrix containing x coordinate of control points
% in the output space
%
% y_output is a $n\times 1$ matrix containing y coordinate of control points
% in the output space
%%
NumberOfPoints = size(x_input,1);
A = zeros(2*NumberOfPoints,1); % Coefficient matrix in AX = L
L = zeros(2*NumberOfPoints,1); % Right-hand matrix in AX = L
for i = 1:NumberOfPoints
A(2*i-1,1:4) = [x_input(i,1) y_input(i,1) 1 0];
end
end
When I press 'Publish' button, I get:
What's the problem with that line?
Not sure if this is the best workaround, but I managed to publish the function with the following script. Of course, you will use your own entries for x_input, y_inpyt, etc. Make sure that you save the following script in a file not named Conformal_2D.m.
Conformal_2D([3;2;1],[5;6;7],[11;12;13],[14;15;16]);
function [a1,b1,a0,b0] = Conformal_2D(x_input,y_input,X_output,Y_output)
%%
% Calculates parameters $a,b,a_0,b_0$ in the following equation using least
% squares
%%
%
% $$X=a_1x+b_1y+a_0$$
%
% $$X=-b_1x+a_1y+b_0$$
%%
% *Arguments:*
%
% x_input is a $n\times 1$ matrix containing x coordinate of control points
% in the input space
%
% y_input is a $n\times 1$ matrix containing y coordinate of control points
% in the input space
%
% x_output is a $n\times 1$ matrix containing x coordinate of control points
% in the output space
%
% y_output is a $n\times 1$ matrix containing y coordinate of control points
% in the output space
%%
NumberOfPoints = size(x_input,1);
A = zeros(2*NumberOfPoints,1); % Coefficient matrix in AX = L
L = zeros(2*NumberOfPoints,1); % Right-hand matrix in AX = L
for i = 1:NumberOfPoints
A(2*i-1,1:4) = [x_input(i,1) y_input(i,1) 1 0];
end
end
When publishing, MATLAB runs the code by default. Of course, your function has input arguments that will not be set in this case (see this other question).
There are a few ways around this. Juanchito's answer illustrates one: don't publish a function, publish a script.
Alternatively, publish the function without executing it:
publish('Conformal_2D.m','evalCode',false)
Or, give MATLAB the right declarations to evaluate before executing the function's content:
publish('Conformal_2D.m','codeToEvaluate','x_input=1; y_input=2; X_output=3; Y_output=4')
(do adjust those values, of course).

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})

SNR plot and rectangular fit (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).

frequency spectrum of sinc function in matlab shows me nothing

since i don't have sinc function in my MATLAB,
I implemented that function as shown below
%% time specificactions:
Fs=10000; dt=1/Fs; t=(-0.1:dt:0.1-dt)'; N=size(t,1);
%message signal
mt=(sin(pi*100*t))./(pi*100*t);
%% frequency specifications
dF=Fs/N;
f=-Fs/2:dF:Fs/2-dF;
M=fftshift(fft(mt));
plot(f,abs(M)/N);
but the figure shows me nothing but blank, so i looked up the variable table and it is filled with NaN.
One thing I don't understand that is that the exactly same procedure worked pretty well when the function i want to fourier transform was just cosine function.
You have a wrongly defined sinc function, as when t=0 it outputs NaN.
you can check that doing any(isnan(mt)) in your code.
To define properly the function do
mt(find(t==0))=1;
That will make your code output
You may want to reconsider the parameters in order to see better the square wave.
the source code of sinc function in Matlab:
function y=sinc(x)
%SINC Sin(pi*x)/(pi*x) function.
% SINC(X) returns a matrix whose elements are the sinc of the elements
% of X, i.e.
% y = sin(pi*x)/(pi*x) if x ~= 0
% = 1 if x == 0
% where x is an element of the input matrix and y is the resultant
% output element.
%
% % Example of a sinc function for a linearly spaced vector:
% t = linspace(-5,5);
% y = sinc(t);
% plot(t,y);
% xlabel('Time (sec)');ylabel('Amplitude'); title('Sinc Function')
%
% See also SQUARE, SIN, COS, CHIRP, DIRIC, GAUSPULS, PULSTRAN, RECTPULS,
% and TRIPULS.
% Author(s): T. Krauss, 1-14-93
% Copyright 1988-2004 The MathWorks, Inc.
% $Revision: 1.7.4.1 $ $Date: 2004/08/10 02:11:27 $
i=find(x==0);
x(i)= 1; % From LS: don't need this is /0 warning is off
y = sin(pi*x)./(pi*x);
y(i) = 1;

Reconstructing time series from FFT in MATLAB

I am trying to reconstruct the sunspots signal from the FFT, the time series and periodogram are in the following site http://www.mathworks.com/help/matlab/examples/using-fft.html . I wrote the following code but the result were not similar to original wave:
YY=Y(1:floor(n/2))
% magnitude
mag_fft = 2*abs(YY)/length(Y);
% phase angle
ang_fft = angle(YY);
[new_mag,new_i]=sort(mag_fft,'descend');
new_ang=ang_fft(new_i);
new_freq=freq(new_i)
wave=zeros(1,length(YY));
wave=new_mag(1);
t=1:length(YY)
for(i=1:70)
wave=wave+new_mag(i).*sin(2*pi*new_freq(i)*t+new_ang(i));
end
wave=wave-mag_fft(1)
figure;plot(year(t),wave,'-b')
hold on;plot(year(t),relNums(t),'-r')
any ideas?
%http://www.mathworks.com/help/matlab/examples/using-fft.html
% sunspots
% sunspots have period of 10 years
%%
clc;clear all;close all;
load sunspot.dat
year=sunspot(:,1);
relNums=sunspot(:,2);
figure;plot(year,relNums)
title('Sunspot Data')
plot(year(1:50),relNums(1:50),'b.-');
yfft = fft(relNums);%figure;plot(ifft(yfft)-data1d,'r')
%yfft = fft(data1d); iyfft=ifft(yfft);
[sum(relNums) yfft(1)]
yfft(1)=[]; % we grid rid of the first value as it corresponeding to zero frequency.
N=length(yfft)+1;
yfft=yfft.*2./N;
%%
power_fft = abs(yfft);power1_fft = sqrt(yfft.*conj(yfft));
figure;plot(power_fft,'-b');hold on;plot(power_fft,'rO')
ang_fft = angle(yfft);real_fft= real(yfft);imag_fft= imag(yfft);
figure;plot(real_fft);hold on;plot(imag_fft,'-r')
figure;plot(angle(yfft))
ph = (180/pi)*unwrap(ang_fft); % phase in degrees
% Now the total length of the per and all other powers should be N-1 because there is no
% more corresponding poweres and phases, and the number of frequencies before the nequiest is
Nneq=length(N./(1:N/2));
Nm1=N-1; per=N./(1:Nm1); freq=1./per;
[per'/12 power_fft(1:Nm1)/100 ] % so as to display the period in years
%% ytyt
ndat=length(relNums);
x=0:ndat-1;
sumharmony1(1:Nneq,1:ndat)=0;
sumharmony2(1:Nneq,1:ndat)=0;
for i=1:Nneq
% those two forms are equal, the last one is called the cos form.
% sumharmony1(i,:)=sumharmony1(i,:)+real_fft(i)*cos(2*pi*x/(per(i)))- imag_fft(i)*sin(2*pi*x/(per(i)));
sumharmony1(i,:)=sumharmony1(i,:)+power_fft(i)*cos(2*pi*x./(per(i))+ang_fft(i));
end
y1 =sum(relNums)/N+ sum(sumharmony1);
%y2 =sum(tmp)/N+ sum(sumharmony2);
figure;plot(relNums);hold on; plot( y1, 'r');
figure;plot((relNums-y1')) % However, the excellent results, we couldnot yet reach to the that of the built in function ifft.
figure;plot(relNums(1:100),'-ob');hold on; plot( y1(1:100), 'r');
% note that we multiply by 2 because of using the window hanning.enter code here