Interpn - changing output - matlab

I have 4 grids:
kgrid which is [77x1]
x which is [15x1]
z which is [9x1]
s which is [2x1]
Then I have a function:
kprime which is [77x15x9x2]
I want to interpolate kprime at some points ksim (750 x 1) and zsim (750 x 1) (xsim is a scalar). I am doing:
[ks, xs, zs, ss] = ndgrid(kgrid, x, z, [1;2]);
Output = interpn(ks, xs, zs, ss, kprime, ksim, xsim, zsim, 1,'linear');
The problem with this interpolation is that the output given is for all combinations of ksim and zsim, meaning that the output is 750x750. I actually need an output of 750x1, meaning that instead of interpolation at all combinations of ksim and zsim I only need to interpolate at ksim(1,1) and zsim(1,1), then ksim(2,1) and zsim(2,1), then ksim(3,1) and zsim(3,1), etc.
In other words, after getting Output I am doing:
Output = diag(squeeze(Output));
I know I can use this output and then just pick the numbers I want, but this is extremely inefficient as it actually interpolates on all other points which I actually do not need. Any help appreciated.

tl;dr: Change xsim and (ssim) from scalars to vectors of the same size as ksim and zsim
Output = interpn (ks, xs, zs, ss, ...
kprime, ...
ksim, ...
repmat(xsim, size(ksim)), ... % <-- here
zsim, ...
repmat(1, size(ksim)), ... % <-- and here
'linear');
Explanation:
The ksim, xsim, zsim, and ssim inputs all need to have the same shape, so that at each common position in that shape, each input acts as an "interpolated subscript" component to the interpolated object. Note that while they all need to have the same shape, this shape can be arbitrary in terms of size and dimensions.
Conversely, if you pass vectors of different sizes (after all, a scalar is a vector of length 1), these get interpreted as the components of an ndgrid construction instead. So you were actually telling interpn to evaluate all interpolations on a grid defined by the vectors ksim, and zsim (and your singletons xsim and ssim). Which is why you got a 2D-grid-looking output.
Note that the same scheme applies with the constructing vectors as well (i.e. ks, xs, zs and ss) i.e. you could have used "vector syntax" instead of "common shape" syntax to define the grid instead, i.e.
Output = interpn(kgrid, x, z, s, kprime, % ...etc etc
and you would have gotten the same result.

From the documents:
Query points, specified as a real scalars, vectors, or arrays.
If Xq1,Xq2,...,Xqn are scalars, then they are the coordinates of a single query point in Rn.
If Xq1,Xq2,...,Xqn are vectors of different orientations, then Xq1,Xq2,...,Xqn are treated as grid vectors in Rn.
If Xq1,Xq2,...,Xqn are vectors of the same size and orientation, then Xq1,Xq2,...,Xqn are treated as scattered points in Rn.
If Xq1,Xq2,...,Xqn are arrays of the same size, then they represent either a full grid of query points (in ndgrid format) or scattered points in Rn.
Answer
You want the usage highlighted in bold. As such, you have to make sure that xsim and ssim ('1' in your code sample) are of size 750x1 also. Then all the query vectors are same length and orientation, such that it can be recognized as a vector of scattered points in Rn. The output will then be a 750x1 vector as needed.

This is to elaborate on #tvo/#Tasos answers, to test the fastest way to create a vector from a scalar:
function create_vector(n)
x = 5;
repm_time = timeit(#()repm(x,n))
repe_time = timeit(#()repe(x,n))
vrep_time = timeit(#()vrep(x,n))
onesv_time = timeit(#()onesv(x,n))
end
function A = repm(x,n)
for k = 1:10000
A = repmat(x,[n 1]);
end
end
function A = repe(x,n)
for k = 1:10000
A = repelem(x,n).';
end
end
function A = vrep(x,n)
v = ones(n,1);
for k = 1:10000
A = x*v;
end
end
function A = onesv(x,n)
for k = 1:10000
A = x*ones(n,1);
end
end
And the results are (for n = 750):
repm_time =
0.049847
repe_time =
0.044188
vrep_time =
0.0041342
onesv_time =
0.0024869
which means that the fastest way to create a vector from a scalar is simply writing x*ones(n,1).

Related

Quadtree decomposition in MATLAB: qtdecomp function input

Does anyone have experience with defining an input function as threshold criterion for the qtdecomp function in MATLAB? I tried the following but it did not work:
MyFunc = #(A,threshold) std2(A)>threshold;
S = qtdecomp(Image,MyFunc,threshold);
Somehow, for some threshold values, only the leftmost quarter of the quadtree is divided into new pieces. Could this maybe be an error in the qtdecomp code itself or is there something wrong with my function input?
See the attached image for details. I get this regardless of the threshold I choose:
The problem is that the image is passed to your anonymous function as an m x m x k array representing the image decomposed into k blocks. The function must return a vector of length k, but std2 only looks at the first block and returns a scalar. I'm still trying to come up with a vectorized approach to this, but for now here's a simple loop in a standalone function:
function v = Std2Func(A, threshold)
s = size(A,3);
v = zeros(1,s);
for k = 1:s
v(k) = std2(A(:,:,k))>threshold;
end
end
This iterates through the k planes of the input array, applying std2 to each 2d plane and putting the results into the output vector. Then you just call qtdecomp using a handle to the new function:
S = qtdecomp(Image,#Std2Func,threshold);

Understanding Non-homogeneous Poisson Process Matlab code

I have found the following Matlab code to simulate a Non-homogeneous Poisson Process
function x = nonhomopp(intens,T)
% example of generating a
% nonhomogeneousl poisson process on [0,T] with intensity function intens
x = 0:.1:T;
m = eval([intens 'x']);
m2 = max(m); % generate homogeneouos poisson process
u = rand(1,ceil(1.5*T*m2));
y = cumsum(-(1/m2)*log(u)); %points of homogeneous pp
y = y(y<T); n=length(y); % select those points less than T
m = eval([intens 'y']); % evaluates intensity function
y = y(rand(1,n)<m/m2); % filter out some points
hist(y,10)
% then run
% t = 7 + nonhomopp('100-10*',5)
I am new to Matlab and having trouble understanding how this works. I have read the Mathworks pages on all of these functions and am confused in four places:
1) Why is the function defined as x and then the intervals also called x? Like is this an abuse of notation?
2) How does the square brackets affect eval,
eval([intens 'x'])
and why is x in single quotations?
3) Why do they use cumsum instead of sum?
4) The given intensity function is \lambda (t) = 100 - 10*(t-7) with 7 \leq t \leq 12 How does t = 7 + nonhomopp('100-10*',5) represent this?
Sorry if this is so much, thank you!
To answer 2). That's a unnecessary complicated piece of code. To understand it, evaluate only the squared brackets and it's content. It results in the string 100-10*x which is then evaluated. Here is a version without eval, using an anonymous function instead. This is how it should have been implemented.
function x = nonhomopp(intens,T)
% example of generating a
% nonhomogeneousl poisson process on [0,T] with intensity function intens
x = 0:.1:T;
m = intens(x);
m2 = max(m); % generate homogeneouos poisson process
u = rand(1,ceil(1.5*T*m2));
y = cumsum(-(1/m2)*log(u)); %points of homogeneous pp
y = y(y<T); n=length(y); % select those points less than T
m = intens(y); % evaluates intensity function
y = y(rand(1,n)<m/m2); % filter out some points
hist(y,10)
Which can be called like this
t = 7 + honhomopp(#(x)(100-10*x),5)
the function is not defined as x: x is just the output variable. In Matlab functions are declared as function [output variable(s)] = <function name>(input variables). If the function has only one output, the square brackets can be omitted (like in your case). The brackets around the input arguments are, as instead, mandatory, no matter how many input arguments there are. It is also good practice to end the body of a function with end, just like you do with loops and if/else.
eval works with a string as input and the square brackets apprently are concatenating the string 'intens' with the string 'x'. x is in quotes because, again, eval works with input in string format even if it's referring to variables.
cumsum and sum act differently. sum returns a scalar that is the sum of all the elements of the array whereas cumsum returns another array which contains the cumulative sum. If our array is [1:5], sum([1:5]) will return 15 because it's 1+2+3+4+5. As instead cumsum([1:5]) will return [1 3 6 10 15], where every element of the output array is the sum of the previous elements (itself included) from the input array.
what the command t = 7 + nonhomopp('100-10*',5) returns is simply the value of time t and not the value of lambda, indeed by looking at t the minimum value is 7 and the maximum value is 12. The Poisson distribution itself is returned via the histogram.

add constant c to each element of specific part of matrix, avoiding loop

I have an mxn matrix X of return values, where I want to add a constant term c for each element of the following sub matrix Y of my original matrix X.
Y = X(end-4:end,:)
Is there a possibility avoiding a loop?
Thanks for any help!
Generate some sample data
X = rand(6,6)
X =
0.9696054 0.7389534 0.7440913 0.2781074 0.0622399 0.0154607
0.8043438 0.8845991 0.1999374 0.2341657 0.6345166 0.8774855
0.0092971 0.1108798 0.1118406 0.6249466 0.3932468 0.4050876
0.6970928 0.1084640 0.0937833 0.8243776 0.7633255 0.0650740
0.3161001 0.4452197 0.1290970 0.5837050 0.5709813 0.2331514
0.0739229 0.5626630 0.8300330 0.9590604 0.0852536 0.0225583
I do Y=X so that that X and Y will have the same dimensions and it can easily be seen where the addition occured. It's for display purposes, really.
Y=X;
Add the constant to the elements you want, element-wise
Y(end-4:end,:) = X(end-4:end,:)+4
Y =
0.969605 0.738953 0.744091 0.278107 0.062240 0.015461
4.804344 4.884599 4.199937 4.234166 4.634517 4.877485
4.009297 4.110880 4.111841 4.624947 4.393247 4.405088
4.697093 4.108464 4.093783 4.824378 4.763326 4.065074
4.316100 4.445220 4.129097 4.583705 4.570981 4.233151
4.073923 4.562663 4.830033 4.959060 4.085254 4.022558
The relevant elements are now four times larger than they originally were.

Is there a builtin way to flip the i-th dimension of an nd-array?

Basically, I'm looking for a generalization of flipud and fliplr to flip the i-th dimension of an nd-array.
When the dimension to be flipped is the first one, I guess I can use
function flipped = flipfirst(ndarr)
sz = size(ndarr);
flipped = reshape(flipud(reshape(ndarr, sz(1), [])), sz);
end
Likewise, if the dimension to be flipped is the last one, I could use
function flipped = fliplast(ndarr)
sz = size(ndarr);
flipped = reshape(fliplr(reshape(ndarr, [], sz(end))), sz);
end
I'm sure that I can code something more general, with calls to permute and whatnot, but is there anything built-in for this?
I'm not sure how expensive it is to do all the reshape-ing above, but if it is, I'd also be interested in more efficient non-built-in approaches.
If you have R2013b+ you should use the new flip function:
A = rand(2,2,2);
B = flip(A,3);
For older versions you can use flipdim:
A = rand(2,2,2);
B = flipdim(A,3);
Type edit flipdim in your command window to see the clever code for flipdim.
You can also flip an array by using the time reversal property of the Discrete Fourier Transform. The code below works for any number of dimensions, but we demonstrate it with a 2D array because it's easier to examine the results.
A = magic(8);
d = 1; % dimension along which to flip
% Create frequency array w, we need it to go along dimension d
sz = size(A, d);
w = 2*pi * (0:sz-1) / sz;
w = shiftdim(w(:), 1-d);
% The actual time reversal property:
B = ifft( conj(fft(A, [], d)) .* exp(1j*w), [], d, 'symmetric');
(yes, this is overly complicated and ridiculously expensive compared to flip, but it's fun!)
From flipdim:
Flip array along specified dimension
Mostly for fun too...
This uses a comma-separated list generated from a cell array, together with the not very well known fact that you can use ':' as an index:
A = rand(3,4,5); % input array
dim = 2; % dimension to flip along
c = repmat({':'}, 1, ndims(A));
c{dim} = size(A, dim):-1:1;
B = A(c{:});

How can I plot data to a “best fit” cos² graph in Matlab?

I’m currently a Physics student and for several weeks have been compiling data related to ‘Quantum Entanglement’. I’ve now got to a point where I have to plot my data (which should resemble a cos² graph - and does) to a sort of “best fit” cos² graph. The lab script says the following:
A more precise determination of the visibility V (this is basically how 'clean' the data is) follows from the best fit to the measured data using the function:
f(b) = A/2[1-Vsin(b-b(center)/P)]
Granted this probably doesn’t mean much out of context, but essentially A is the amplitude, b is an angle and P is the periodicity. Hence this is also a “wave” like the experimental data I have found.
From this I understand, as previously mentioned, I am making a “best fit” curve. However, I have been told that this isn’t possible with Excel and that the best approach is Matlab.
I know intermediate JavaScript but do not know Matlab and was hoping for some direction.
Is there a tutorial I can read for this? Is it possible for someone to go through it with me? I really have no idea what it entails, so any feed back would be greatly appreciated.
Thanks a lot!
Initial steps
I guess we should begin by getting a representation in Matlab of the function that you're trying to model. A direct translation of your formula looks like this:
function y = targetfunction(A,V,P,bc,b)
y = (A/2) * (1 - V * sin((b-bc) / P));
end
Getting hold of the data
My next step is going to be to generate some data to work with (you'll use your own data, naturally). So here's a function that generates some noisy data. Notice that I've supplied some values for the parameters.
function [y b] = generateData(npoints,noise)
A = 2;
V = 1;
P = 0.7;
bc = 0;
b = 2 * pi * rand(npoints,1);
y = targetfunction(A,V,P,bc,b) + noise * randn(npoints,1);
end
The function rand generates random points on the interval [0,1], and I multiplied those by 2*pi to get points randomly on the interval [0, 2*pi]. I then applied the target function at those points, and added a bit of noise (the function randn generates normally distributed random variables).
Fitting parameters
The most complicated function is the one that fits a model to your data. For this I use the function fminunc, which does unconstrained minimization. The routine looks like this:
function [A V P bc] = bestfit(y,b)
x0(1) = 1; %# A
x0(2) = 1; %# V
x0(3) = 0.5; %# P
x0(4) = 0; %# bc
f = #(x) norm(y - targetfunction(x(1),x(2),x(3),x(4),b));
x = fminunc(f,x0);
A = x(1);
V = x(2);
P = x(3);
bc = x(4);
end
Let's go through line by line. First, I define the function f that I want to minimize. This isn't too hard. To minimize a function in Matlab, it needs to take a single vector as a parameter. Therefore we have to pack our four parameters into a vector, which I do in the first four lines. I used values that are close, but not the same, as the ones that I used to generate the data.
Then I define the function I want to minimize. It takes a single argument x, which it unpacks and feeds to the targetfunction, along with the points b in our dataset. Hopefully these are close to y. We measure how far they are from y by subtracting from y and applying the function norm, which squares every component, adds them up and takes the square root (i.e. it computes the root mean square error).
Then I call fminunc with our function to be minimized, and the initial guess for the parameters. This uses an internal routine to find the closest match for each of the parameters, and returns them in the vector x.
Finally, I unpack the parameters from the vector x.
Putting it all together
We now have all the components we need, so we just want one final function to tie them together. Here it is:
function master
%# Generate some data (you should read in your own data here)
[f b] = generateData(1000,1);
%# Find the best fitting parameters
[A V P bc] = bestfit(f,b);
%# Print them to the screen
fprintf('A = %f\n',A)
fprintf('V = %f\n',V)
fprintf('P = %f\n',P)
fprintf('bc = %f\n',bc)
%# Make plots of the data and the function we have fitted
plot(b,f,'.');
hold on
plot(sort(b),targetfunction(A,V,P,bc,sort(b)),'r','LineWidth',2)
end
If I run this function, I see this being printed to the screen:
>> master
Local minimum found.
Optimization completed because the size of the gradient is less than
the default value of the function tolerance.
A = 1.991727
V = 0.979819
P = 0.695265
bc = 0.067431
And the following plot appears:
That fit looks good enough to me. Let me know if you have any questions about anything I've done here.
I am a bit surprised as you mention f(a) and your function does not contain an a, but in general, suppose you want to plot f(x) = cos(x)^2
First determine for which values of x you want to make a plot, for example
xmin = 0;
stepsize = 1/100;
xmax = 6.5;
x = xmin:stepsize:xmax;
y = cos(x).^2;
plot(x,y)
However, note that this approach works just as well in excel, you just have to do some work to get your x values and function in the right cells.