matlab/octave plot a mesh - matlab

t=0:0.01:2;
alpha=linspace(0, 1, 41);
r=linspace(0,1,41);
[aa,rr] = meshgrid(alpha,r);
At each point of (aa, rr), for each t there is a value t^aa+rr^2, then those values are summed up:
sum = (t1^aa+rr^2) + (t2^aa+rr^2) + ...
Thus for each point of (aa,rr), there is a number of sum. How do you plot that mesh?

You can reshape t into the third dimension to generate all triples of aa, rr and t via implicit expansion, and then sum over that dimension to get the desired result:
t3 = reshape(t, 1, 1, []);
s = sum(t3.^aa + rr.^2, 3);
mesh(aa, rr, s)
In your example, this produces

Related

How can I find the nearest matrix element value to a range in MATLAB?

I have a 3D matrix and I need to find the nearest value to [0 to 1] range. For example, I have [-2.3 -1.87 -0.021 1.1 1.54] and -0.021 should be selected as it is the nearest value to the range.
EDITED: There would be zero or one value within the range. If there is one, that should be returned and if there is nothing, the nearest value should be returned
EDITED: This is the part of code which I'm trying to work correctly:
rt = zeros(size(audio_soundIntervals, 1), size(prtcpnt.audioAttention_ToM.sound_eventTime, 1), size(prtcpnt.audioAttention_ToM.sound_eventTime, 2));
for r = 1:size(prtcpnt.audioAttention_ToM.sound_eventTime, 1)
for t = 1:size(prtcpnt.audioAttention_ToM.sound_eventTime, 2)
for b = 1:size(audio_soundIntervals, 1)
% here, I want to find the nearest element of audio_eventReshape(:, r, t) to the range [audio_soundIntervals(b, r, t), audio_soundIntervals(b, r, t) + 1]
end
end
end
The value nearest the center of the range is always the one you are looking for. I suggest you try out a few examples on paper to convince yourself of this.
The center of the range [a,b] is (b-a)/2. In your case this is 0.5.
Thus, finding the minimum of abs(A-0.5) will give you your answer. If A is a matrix, then A(:) is a vector you can apply your operation to. So we have:
[~,indx] = min(abs(A(:)-0.5));
Or more generally:
[~,indx] = min(abs(A(:)-(b-a)/2));
indx is the linear index into A for the element you are looking for, get the value with A(indx).
You can use this function to find the nearest value of A to the range range:
function out = near_range(A, range)
[m1, idx1] = min(A - range(1), [], 'all', 'ComparisonMethod', 'abs');
if abs(m1) >= diff(range)
out = A(idx1);
return
end
[m2, idx2] = min(A - range(2), [], 'all', 'ComparisonMethod', 'abs');
if abs(m1) < abs(m2)
out = A(idx1);
else
out = A(idx2);
end
end
Usage:
result = near_range([-2.3 -1.87 -0.021 1.1 1.54], [0 1]);
EDIT:
The 'ComparisonMethod' option of function min is available starting from MATLAB R2021b. For older versions here is a way with dsearchn:
[k, dst] = dsearchn(A(:), range(:));
result = A(k(1 + (diff(dst) < 0)));
EDIT2:
I packaged the second method as a function:
function out = near_range(A, range)
[k, dst] = dsearchn(A(:), range(:));
out = A(k(1 + (diff(dst) < 0)));
end
Usage:
rt(b, r, t) = near_range(audio_eventReshape(:, r, t), [audio_soundIntervals(b, r, t), audio_soundIntervals(b, r, t) + 1]);

How to compare elements in multiple vectors (of different sizes) against each other?

I have three vectors in Matlab that are possibly of different sizes. I want to compare the values in each vector against all the other values in the other vectors and only keep values that are 'close' in 2 out of 3 of the vectors. And by 'keep', I mean take the average of the close values.
For example:
a = [10+8i, 20];
b = [10+9i, 30, 40+3i, 55];
c = [10, 60, 41+3i];
If I set a closeness tolerance such that only values that are within, say, a magnitude of 1.5 of each other are kept, then the following values should be marked as close:
10 + 8i and 10 + 9i
40 + 3i and 41 + 3i
Then the routine should return a vector of length that contains the average of each of these sets of numbers:
finalVec = [10+8.5i,40.5+3i];
What is the most efficient way to do this in Matlab? Is there a better way than just straightforward looping over all elements?
Building on this solution:
a = [10+8i, 20];
b = [10+9i, 30, 40+3i, 55];
c = [10, 60, 41+3i];
M1 = compare_vectors(a , b);
M2 = compare_vectors(a , c);
M3 = compare_vectors(b , c);
finalVec = [M1, M2 , M3]
function M = compare_vectors(a , b)
% All combinations of vectors elements
[A,B] = meshgrid(a,b);
C = cat(2,A',B');
D = reshape(C,[],2);
% Find differences lower than tolerance
tolerance = 1.5
below_tolerance = abs(D(:,1) - D(:,2)) < tolerance ;
% If none, return empty
if all(below_tolerance== 0)
M = [];
return
end
% Calculate average of returned values
M = mean(D(below_tolerance,:));
end
% your data
a = [10+8i, 20];
b = [10+9i, 30, 40+3i, 55];
c = [10, 60, 41+3i];
tol = 1.5;
% call the function with each combination of vectors and concatenate the results
finalVec = cell2mat(cellfun(#closepoints, {a, a, b}, {b, c, c}, {tol, tol, tol}, 'Uni', 0))
function p = closepoints(a, b, tol)
% find the pairs of indexes of close points
% the bsxfun() part calculates the distance between all combinations of elements of the two vectors
[ii,jj] = find(abs(bsxfun(#minus, a, b.')) < tol);
% calculate the mean
p = (a(jj) + b(ii))/2;
end
Note that cellfun() isn't really faster than calling the function multiple times in a row or using a for loop. But it would be easier to add more vectors than the former and is IMO nicer to look at than the latter.

Sort 2d matrix in Matlab

I have a 2d matrix, the first column is numeric, second is string and third is string, I want to sort by the first column. Here is my code used to create the loop.
Thanks
for i = 1:length(queries)
for j = 1:length(textures)
results{i * j, 1} = HI(queries{i, 2}, textures{j, 2});
results{i * j, 2} = textures{j, 3};
results{i * j, 3} = queries{i, 3};
end
results = sort(results, 1);
end
Use sortrows:
c = {0.608920898437500 'D1.gif' 'D106.gif'
0.803334960937500 'D1.gif' 'D109.gif'
0.831228027343750 'D1.gif' 'D26.gif'}; %// example data
cSorted = sortrows(c,1); %// sort rows according to first column
The result is
cSorted =
[0.6089] 'D1.gif' 'D106.gif'
[0.8033] 'D1.gif' 'D109.gif'
[0.8312] 'D1.gif' 'D26.gif'

How to apply an affine transformation (4x4 matrix) to ndgrid/meshgrid results?

M is an affine transformation matrix that can transform coordinates from one coordinate system to another as follows:
v_old = [ x_old y_old z_old 1];
v_new = M * v_old;
% v_new contains [ x_new y_new z_new 1 ]
Now, I've got coordinates on the form of ndgrid/meshgrid:
[ X_old Y_old Z_old ] = ndgrid( 0:15 ); % for instance
How can I convert these to X_new etc?
I could do it with three for-loops loop (X_old(i,j,k) corresponds to x_old above) but there must be a better solution.
You just have to rearrange the values so that each point has its four coordinates in one row:
result = [X_old(:) Y_old(:) Z_old(:) ones(numel(X_old),1)] * M;
Each row of result gives the new coordinates of each point.
Note that this works because multiplying matrix A times matrix B is the same as multiplying each row of A times B.
Or, if you can't afford to build the above matrix (because of memory limitations), use
result = X_old(:)*M(1,:) + Y_old(:)*M(2,:) + Z_old(:)*M(3,:) + ones(numel(X_old),1)*M(4,:);
In either case, if you want to rearrange the result so that it has the same size as X_old, Y_old, Z_old, use this as a last step:
s = size(X_old);
X_new = reshape(result(:,1), s);
Y_new = reshape(result(:,2), s);
Z_new = reshape(result(:,3), s);

How do I multiply all the elements in each row of a given matrix with corresponding elements of a given vector and sum them in MATLAB?

For example, given a matrix randn(3,2) - 3 rows, 2 columns and a vector of multipliers randn(1,2)) 2 columns, I want to get a vector of size (3, 1) in which each row would represent a sum of per element multiplication of the matrix's row elements and the given multipliers like
row_element_1*mul_element_1 + row_element_2*mul_element_2
Sounds like you want a matrix-vector multiplication.
1> x = randn(3, 2)
x =
0.62055 -1.08060
-0.24064 -2.56097
-0.53202 -0.49712
2> y = randn(1, 2)
y =
-1.26010 -0.25200
3> x * y'
ans =
-0.50964
0.94860
0.79567
Note the transposition y'.
I think you can do this with a combination of bsxfun and sum, like so:
a = rand(3,2);
b = rand(1,2);
result = sum(bsxfun(#times,a,b),2)
result =
0.333379034494579
0.613480382112731
0.093702948350719
Note dimension argument to SUM to sum along each row (rather than the default, which is down columns). BSXFUN applies a binary function with scalar expansion, which is ideal for the multiplication part here.
A = randn(3, 2);
B = randn(1, 2);
C = A(:, 1) * B(1) + A(:, 2) * B(2); % size(C) = [3, 1]
If you have to scale to a much larger array with lots more columns and didn't want to write out the equation for C in full, you can use repmat and element-wise multiplication
A = randn(300, 200);
B = randn(1, 200);
C = sum(A .* repmat(B, 300, 1), 2);