Array's length in Matlab - arrays

How I could determine the number of elements from an array in Matlab, without using functions such as length(), size(), etc. ?
Thanks you !

The logic is to iterate over the cells until an empty cell is encountered. I have taken two variables for iteration namely, i and j. i is for rows and j is for columns.
Initially set the value of i and j as i=1 and j=1. Now in a while loop iterate by incrementing j and keeping i = 1 as constant.
** First try to copy that cell in a variable x. If that cell is an empty cell an error will pop up. Aim is to take advantage of this error using try/catch statements.
Scince the statement x = vec(i,j); is written in the try block so on encountering an empty cell instead of try the catch block will be executed where flag = 0 makes the flag 0, this will cause the while loop to end.
So, we have the number of columns stored in j and the while loop terminates on encountering an empty cell.
flag = 1;
i = 1;
j = 1;
while(flag==1) % loop will continue till flag is 1 (or say flag is HIGH)
try
x = vec(i,j); % Try to copy this cell of array vec in x
j = j+1; % if successful to copy then increment value of j else catch block is executed
catch
flag = 0; % Set flag = 0 (or low) to end the while loop
end
end
j = j - 1; % The value of j comes out to be one greater than number of columns hence decrementing by 1
%
% WE HAVE THE NUMBER OF COLUMNS !!
%
% WE WILL PERFORM SAME THING TO GET THE NUMBER OF ROWS BY INCREMENTING i AND
% KEEPING j AS CONSTANT
flag=1;
while(flag==1)
try
x = vec(i,j);
i = i+1;
catch
flag = 0;
end
end
i = i - 1;
% i is the number of rows in the matrix or array
% j is the number of columns in the matrix
dim = [i,j] % vector named dim(or say matrix named dim) contains the required output
dim contains the size of vec

Related

Finding peaks of an array and creating a sequence of bits (without using findpeaks)

Given an array V, which is the numerical solution of a system of differential equations, I want to determine the local, positive peaks of this array. Every time I have such a peak whose value is greater than 0 I code a bit equal to 1 and every time I have a peak with a negative value I code a bit equal to 0(I cannot use findpeaks).
I have tried the following:
function Suite_bits = message_digital(V)
j = 1;
bit(1) = 0;
for i=2:numel(V)-1
if V(i-1)<V(i) && V(i+1)<V(i)
if V(i)>0
bit(j) = 1;
j = j + 1;
else
bit(j) = 0;
j = j + 1;
end
end
Suite_bits = bit;
end
But due to some minor anomalies in the vector V, fluctuations of the values between steps (remember V is the solution of a numerically solved ode system with a step h = 0.1), I get more peaks than actually appear in the graph. Any ideas how I could fix this?
Fluctuations of V vector can be avoided by use of the 'smooth' function provided by MATLAB. By default this function smooths data using a 5 point moving average. You can change the arguments of this function so that the moving average includes more or less than 5 points. Thus, depending on the magnitude of the fluctuations, this argument can be arranged so that fluctuations are smoothed and ignored by the algorithm. This is an example of code that could work:
function Suite_bits = message_digital(V)
j = 1;
V = smooth(V, 15);
bit(1) = 0;
for i=2:numel(V)-1
if V(i)>V(i-1) && V(i)>V(i+1)
if V(i)>0
bit(j) = 1;
j = j + 1;
else
bit(j) = 0;
j = j + 1;
end
end
Suite_bits = bit;
end
end

Comparing individual matrix elements in MATLAB?

I need to compare a value in a multidimentional array and according to this comparison, I need to assign a value of another matrix in the same index to a new matrix of the same size in the same index. Can you give me an idea on how to do this?
Here's the code below using the for loop, but I need to do this without using a for loop.
for i = 1:sizeOfMatrix(1, 1)
for j = 1:sizeOfMatrix(1, 2)
if grayImage(i, j) > t
result(i, j) = 0;
else
result(i, j) = grayImage(i, j);
end
end
end
where t is the value that I need to compare with.
Use logical indexing:
result = zeros(size(grayImage));
result(grayImage <= t) = grayImage(grayImage <= t);
This is a much faster and cleaner way to access matrix elements conditionally.
Alternatively, you can do:
result = grayImage;
result(grayImage > t) = 0;

Variable dimensions in file don't match with dimension of indexing subscript if one dimension is singleton

I want to test a function func(par1,par2,par3) with all combinations of the parameters par1, par2 and par3 and store the output in a .mat file. My code looks like this at the moment:
n1 = 3;
n2 = 1;
n3 = 2;
parList1 = rand(1,n1); % n1,n2,n3 is just some integer
parList2 = rand(1,n2); % the lists are edited by hand in the actual script
parList3 = rand(1,n3);
saveFile = matfile('file.mat','Writable',true);
% allocate memory
saveFile.output = NaN(numel(parList1),numel(parList2),numel(parList3));
counter1 = 0;
for par1 = parList1
counter1 = counter1 + 1;
counter2 = 0; % reset inner counter
for par2 = parList2
counter2 = counter2 + 1;
counter3 = 0; % reset inner counter
for par3 = parList3
counter3 = counter3 + 1;
saveFile.output(counter1,counter2,counter3) = sum([par1,par2,par3]);
end
end
end
This works except if parList3 has only one item, i.e. if n3 = 1. Then the saveFile.output has singleton dimensions and I get the error
Variable 'output' has 2 dimensions in the file, this does not match the 3 dimensions in the indexing subscripts.
Is there a elegant way to fix this?
The expression in the for statement needs to be a row array, not a column array as in your example. The loops will exit after the first value with your code. Set a breakpoint on the saveFile.output command to see what I mean. With a column array, par1 will not be a scalar as desired, but the whole parList1 column. With a row array, par1 will iterate through each value of parList1 as intended
Another thing is that you need to reset your inner counters (counter2 and counter2) or your second and third dimensions will blow up larger than you expected.
The n3=1 problem is expected behavior because matfile defines the variables with fixed number of dimensions and it will treat saveFile.output as 2D. Once you have fixed those issues, you can solve the n3=1 problem by changing the line,
saveFile.output(counter1,counter2,counter3) = sum([par1,par2,par3]);
to
if n3==1, saveFile.output(counter1,counter2) = sum([par1,par2,par3]);
else saveFile.output(counter1,counter2,counter3) = sum([par1,par2,par3]);
end
By now I realized that actually in matfiles all the singleton dimensions, except for the first two are removed.
In my actual programm I decided to save the data in the file linearly and circumvent matfile's lack of linear indexing capability by using the functions sub2ind and ind2sub.

Basic MATLAB variable manipulation

I have a dwc = [3001 x 2 double] which more or less is a sin function, I have a for loop finding top values in dwc(:,2). Lets say that there is a top value in dwc(531,2) which way is best way or what is easy to take dwc(531,1) and dwc(531,2) and make an M = [num_of_top_points x 2 double]?
For the following loop, what do I do?
j = 0;
for i = 2:size(dwcL01,1)-1
if dwcL01(i,2) > dwcL01(i-1,2) && dwcL01(i,2) > dwcL01(i+1,2)
j = j+1;
?? = dwcL01(i,:);
end
end
This is how you complete your loop
j = 0;
M = [];
for i = 2:size(dwcL01,1)-1
if dwcL01(i,2) > dwcL01(i-1,2) && dwcL01(i,2) > dwcL01(i+1,2)
j = j+1;
M(j, :) = dwcL01(i, :);
end
end
But you could do this much more efficiently by vectorizing
%//Some example data
x = -4*pi:0.5:4*pi;
y = cos(x);
dwcL01 = [x(:), y(:)]; %// (:) just makes it a column
%// Finding the peaks using diff and sign. Note that I add the first element to the beginning as diff reduces the size by one so this prevents offsetting
F = diff(sign(diff([dwcL01(1,2);dwcL01(:,2)]))) < 0;
M = [dwcL01(F,:)', dwcL01(F,:)'];
plot(x, y, M(:,1), M(:,2), '*r')
How that works is first we find the difference of each element consecutive element pair. Now when the sign changes, that means we've hit a max or min. If the sign change is negative then the gradient went from positive to negative which is a max. So I use diff(sign()) to find the points where the sign changes and then > 0 to create a logical matrix with false everywhere expect for the max. Then I use logical indexing to extract the max.
You could append it to a matrix (let's call it dwcL01_max) - this isn't the fastest way because the matrix size changes each loop but it works:
dwcL01_max = [dwcL01_max dwcL01(i,:)];
The other option would be to use the builtin findpeaks (from the signal proc toolbox)
[~, dwcL01_peaks] = findpeaks(dwcL01(:,2));
dwcL01_max = dwcL01(dwcL01_peaks, :);

Finding common elements in two arrays of different size

I have to find the best way to get common elements of two arrays of different size.
The arrays are unordered; the common elements are in different position, but in the same order (if in the array A common element b came after a, the same happens in array B) and with max distance N.
I can't use more additional space of O(N).
Actually I extract N elements from array A, order them with mergesort and perform a dicotomic search using N elements of array B. Then I get the next N elements from the position of the match I found and do another cycle.
The cost of this should be, using m as length of array B, O(m N log N)
I have tried using an hashtable, but to manage collisions I have to implement a List, and efficiency goes down.
There is a better way?
Assuming you can have "holes" in your matched sequence (A = [1,3,2] AND B = [1,4,2] Then MatchSet = {1,2})
Maybe I am wrong but you could try this pseudo code:
i <- 0; j <- 0; jHit <- -1
matchSet <- Empty
While i < Length(A) AND j < Length(B):
If A[i] == B[j] Then
matchSet.add(A[i])
i <- i+1
jHit <- j
End If
j <- j+1
If j == Length(B) Then
i <- i+1
j <- jHit+1
End If
End Loop
The first index (i) points to the next element of A not found in B whereas (j) is used to look for the next element of B (after the last element found in A).
This yould give you a time complexity of O(mN) and space usage of O(N).
Here you have an implementation in Python:
def match(A,B):
i = 0
j = 0
jHit = -1
res = []
while i < len(A) and j < len(B):
if A[i] == B[j]:
res.append(A[i])
i += 1
jHit = j
j += 1
if j == len(B):
i += 1
j = jHit+1
return res

Resources