What's the concise expression for the following Matlab code - matlab

img is an image of a single color channel.
img_temp is defined as follows:
img_temp = zeros(size(img,1), size(img,2), N);
where N is an integer. Therefore, each entry of img_temp contains N values.
What's the concise way of expressing the following operation in Matlab?
for x=1:size(img,1)
for y=1:size(img,2)
img(x,y,1) = find(img_temp(x,y,:)==max(img_temp(x,y,:)));
end
end
I want to find the index of the largest value in the array img_temp(x,y,:) and store it in the corresponding place in img, namely, img(x,y,1)

The max function can operate along any dimension and return an index along with the max value. In your case, you only care about the index and want it stored in img(:,:,1), so try this:
[~, img(:,:,1)] = max(img_temp, [], 3);

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

Interpn - changing output

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

Matlab - storing data from a loop in a Matrix (not a vector)

as a part of a bigger script i want to store data from a while loop in a matrix. I want to save parts of the COG_Ton_Av matrix which is 1738x3 in a new matrix. The COG_Ton_Av changes within every loop so i want to store the results outside. I have found multiple entries on how to store the data in a vector, but nothing for a matrix. What i tried is :
valuesforts= zeros(1000,3);
yr =1
while Qn>0
yindex = Gmhk*100
zindex = round(gs*100)
ts = (COG_Ton_Av ((zindex:yindex),:))
valuesforts(yr)=ts
yr = yr+1
end
I just posted parts of the while loop to make the question easier, I hope it is sufficient to answer the question.
While trying this i get following error:
Subscripted assignment dimension mismatch.
Error in cutoff_work14_priceescalation_and_stockpiling (line 286)
valuesforts(yr)=ts
The error means that ts is a different size to valuesforts (and it is indexed with yr as a vector.
If dimensions of TS vary on each iteration of the loop then use cell notation:
valuesforts = cell(<number of years>);
...
valuesforts{yr} = ts;
then the dimensions of ts won't matter.
To extract data also use { } e.g.
meanValues(yr) = mean(valuesforts{yr});
Bear in mind that the matrix within each cell of valuesforts will have same distentions as ts when it was assigned.
Alternatively, if TS is always the same size the pre-allocate valuesforts as:
valuesforts = zeros(<number of years>,<expected length of ts>,3);
...
valuesforts(yr,:,:) = ts;
Then depends on what you want to do with valuesforts.. reshape it or plot it.
In the worst case (not recommended), you can let the valuesforts grow with every loop iteration.
initialise with empty:
valuesforts=[];
then vertically append ts to valuesforts:
valuesforts = [valuesforts; ts];
this would give you a matrix with 3 columns and number of years * number of rows in ts in each loop iteration.

Why Self-defined Matlab Function Return Empty Matrix

The function is supposed to return a value. However, when I type:
val(1d4)
it returns
ans =
[]
However, if I copied line by line, and set all parameters (V eps_today etc.), and run in the command window, it works fine...Have no clue where the problem is. Thanks:)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%This function calculates the value function of both small and big%
%investment %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function negval=val(k_next)
global V eps_today k_today eps_gv k_gv z_today delta xi
theta=0.5327; beta=0.95; rho=0.7675; sigma_eta=0.7704;
%identify the grid point that falls just below
klo=max(sum(k_next>k_gv),1);
%above
khi=klo+1;
%Linear Interpolation, effectively only on the dimension of k
if klo<size(k_gv,2)
V_temp=V(:,klo)+(k_next-k_gv(klo))/(k_gv(khi)-k_gv(klo))*(V(:,khi)-V(:,klo));
else
%when k_next> maximum point of k_gv
V_temp=V(:,size(k_gv,2));
end
EV=mean(V_temp,1);
negval=-(exp(z_today+eps_today)*k_today^theta-xi*k_today-(k_next-(1-delta)*k_today)+beta*EV);
end
I tried to replicate your problem but I couldn't. If I do not set the global variables Matlab shouts and refuses to proceed through the function. Setting some of them to empty values was the same (did not try them all). If I do set the globals then the function always gives me a value.
But I strongly suspect it has something to do with the globals anyway (can you show the code where they are initialized?). As I mentioned in the comment I would get rid of them, the code could look like this
Main programme
%set parameters
Pars.beta = beta=0.95;
Pars.theta = 0.5327;
Pars.rho=0.7675;
Pars.sigma_eta=0.7704;
Pars.delta = ...;
Pars.xi = ...;
%set grid
eps_gv = ...
k_gv = ...
ne = length(eps_gv);
nk = length(k_gv);
V = zeros(ne,nk);
k_next = ...;
value = val(k_next,V,eps_gv,k_gv,Pars);
Val function
negval = function val(k_next,V,eps_gv,k_gv,Pars)
theta=Pars.theta; beta=Pars.beta; rho=Pars.rho; etc.
You don't even need eps_today and k_today as these should be the values on the grid (ie eps_gv and k_gv). I don't know what z_today is but there should either be a grid for z or z_today should be a parameter, in which case it should be in Pars. Of course if you use eps_gv and k_gv instead of eps_today and k_today the negval = ... line needs to be modified to take account of them being arrays not scalars.
One last comment, there is a bug on the EV=mean(V_temp,1); line. The mean function calculates the average of (the columns of) V. To calculate the expected value you need to do a weighted average where you weight each row of V by the probability of eps being eps_gv(1) (ie sum(V(i,:)*prob_eps(i)), sum going over i) . What you did works only if all shocks have equal probability. Pointing out since I am not sure you are aware of that.

Matlab unique function

I'm struggling with determining the probability of occurrence of unique elements in thresh_strain matrix (which can be seen below as a 100 x 16). I was trying to use the code at the bottom to do this, but I get an equal probability of occurrence associated with each of the elements, whereas I want the probability of occurrence associated with unique elements in thresh_strain.
function [thresh_strain] = MCsolution()
no_iterations = 100;
thresh_strain = zeros(100, 16);
casechoice =input('Enter 1 for 1st Layup and 2 for 2nd layup:');
for i=1:no_iterations
for j=1:16
J = Nielsennew(casechoice);
thresh_strain(i,j) = J(1, j);
end
end
% [uniqueValues,~,uniqueIndex] = unique(thresh_strain);
% frequency = accumarray(uniqueIndex(:),1)./numel(thresh_strain);
Thanks
It is not really clear from the title and description, but I suppose you may be looking for something like this:
myUniqueValues = unique(myMatrix);
nelements = hist(myMatrix(:),myUniqueValues);
%plot(myUniqueValues,nelements)
Basically calculating how often each unique value occurs. From here getting the corresponding percentage is of course trivial.