How to make vectors be of same length in my Matlab script? - matlab

I am trying to plot some data. The script I wrote below has worked fine before, but now I have no idea why it's not working.
Here is the code:
x = [335,41,14,18,15,9,7,9,20607,5,5,143,3,5,72,134,2,28,172,3,72,173,280,186,20924,1,1,22,3,3,1,2,13,1,3,2,11,66,12983,176,123,192,64,258,182,123,299,58,198,7,113,342,72,8376,122,20,19,2,3,28,8,36,8,56,43,2,48,127,395,4664,186,46,236,219,258,69,203,189,169,72,100,78,109,46,112,3929,272,40,4,31,2,97,36,5,35,56,2,237,1672,256,224,28,163,341,151,263,157,397,94,380,173,75,87,272,1194,133,6,112,1,6,2,26,25,64,8,40,57,106,525,150,248,125,269,264,256,357,153,64,152,283,1,2,2,454,154,39,1,1,64,151,242,1,18,99,1,36,607,55,54,110,225,108,37,1,144,162,137,107,21,360,362,18,51,25,43,1,3,6,1,27,7,45,326,32,103,50,124,155,39,180,143,33,116,46,7,151,120,19,4,2,4,110,2,7,4,9,4,27,216,323,148,1,1,2,1,47,113,150,1,2,144,16,4827,1,1,1,14];
size = length(x);
disp(size);
z = 0;
for i = 1:size
z = z + 1;
y(i) = z;
end
scatter(x,y);
This code should ensure that y is of same length as x as we are only filling in y as long as x is (since we are using a for loop from 1 through to size, where size is basically the number of indices in x), but I keep getting this error. I checked with disp and it turns out that my x and y vectors have different lengths, x is 227 and y is 256. Can anyone help me out with this trivial issue?

This is most likely because y was created to be a different size before you ran that piece of code you showed us. Somewhere in your script before you call this piece of code, y was created to be a 256 element vector and now you are reusing this variable in this part of the code by populating elements in the y vector. The variable x has 227 elements and the loop you wrote will change y's first 227 elements as you have looped for as many times as there are elements in x. However, the remaining 29 elements are still there from before. The reusing of the variable y is probably why your script is failing as now the sizes between both variables are not the same. As such, explicitly recreate y before calling scatter.
Actually, that for loop is not needed at all. The purpose of the loop is to create an increasing array from 1 up to as many elements as you have in x.
Just do this instead:
y = 1:size;
I also do not like that you are creating a variable called size. It is overshadowing the function size, which finds the number of elements in each dimension that the input array contains.
With the recommendations I've stated above, replace your entire code with this:
x = [335,41,14,18,15,9,7,9,20607,5,5,143,3,5,72,134,2,28,172,3,72,173,280,186,20924,1,1,22,3,3,1,2,13,1,3,2,11,66,12983,176,123,192,64,258,182,123,299,58,198,7,113,342,72,8376,122,20,19,2,3,28,8,36,8,56,43,2,48,127,395,4664,186,46,236,219,258,69,203,189,169,72,100,78,109,46,112,3929,272,40,4,31,2,97,36,5,35,56,2,237,1672,256,224,28,163,341,151,263,157,397,94,380,173,75,87,272,1194,133,6,112,1,6,2,26,25,64,8,40,57,106,525,150,248,125,269,264,256,357,153,64,152,283,1,2,2,454,154,39,1,1,64,151,242,1,18,99,1,36,607,55,54,110,225,108,37,1,144,162,137,107,21,360,362,18,51,25,43,1,3,6,1,27,7,45,326,32,103,50,124,155,39,180,143,33,116,46,7,151,120,19,4,2,4,110,2,7,4,9,4,27,216,323,148,1,1,2,1,47,113,150,1,2,144,16,4827,1,1,1,14];
numX = numel(x);
y = 1 : numX;
scatter(x,y);
The vector y is now explicitly created instead of reusing the variable that was created with a previous size in the past. It also uses the colon operator to explicitly create this sequence instead of using a for loop. That for loop is just not needed. numel determines the total number of elements for an input matrix. I don't like using length as a personal preference because it finds the number of elements in the largest dimension. This may work fine for vectors, but it has really made some hard to spot bugs in code that I've written in the past.

Related

3D matrix Indexing using 2D matrix

Could anyone shed some light on how this for loop can be replaced by a single command in MATLAB?
for i = 1 : size(w,3)
x=w(:,:,i);
w1(i,:)=x(B(i),:);
end
clear x
Here, w is a 3D (x by y by z) matrix and B (1 by z) is a vector containing rows pertaining to each layer in w. This for loop takes about 150 seconds to execute when w is 500000 layers deep. I tried using,
Q = w(B,:,:);
Q = reshape(Q(1,:),[500000,2])';
This creates a matrix Q of size 500000 X 2 X 500000 and MATLAB threw me an error saying memory out of bound. Any help would be appreciated!
You are creating intermediate variables (such as x) and using a for loop. The core idea of the following approach is to first pre-populate the indices used and then use linear indexing to access all the elements at once. Then, we can reshape to get the desired result.
ind = [B(1)*ones(size(w,2),1) (1:size(w,2)).' 1*ones(size(w,2),1)];
ind = [ind; [B(2)*ones(size(w,2),1) (1:size(w,2)).' 2*ones(size(w,2),1)]];
ind = [ind; [B(3)*ones(size(w,2),1) (1:size(w,2)).' 3*ones(size(w,2),1)]];
lin_ind = sub2ind(size(w), ind(:,1), ind(:,2), ind(:,3));
w1 = reshape(w(lin_ind),size(w,2),size(w,3)).'
On my system, this matches with w1 computed with the loop given in your question. Note that you may need to use a for loop to pre-populate the indices. I wrote three expressions since I was experimenting with small matrices. Actually, the first three lines can be written in such a way that you don't need loops at all and it still works with any size. I will leave that up to you.

Indexing issue in MATLAB (image processing)

I'm dealing with a predictive block-matching motion estimation algorithm. This means, the values of motion vectors are found using the previously found values and I am stuck with a really trivial thing.
I'm dealing with images divided into blocks, so I should have a motion vector for each block. I created a 2xN matrix motion_vectors, where N is the number of all blocks (blocks_in_the_first_row*blocks_in_the_first_column). The first row is the x coordinate and second row the y coordinate of the motion vector.
I have 2 predictors to help to estimate the motion vector of the current block.
If my current block is at position (i,j) then the positions of the predictors are (i, j-1) (the block "on top)" and (i-1, j) (the block on the left).
My problem is, that I can't figure out a way how to adress the predictor blocks (in for loops) in motion_vectors since the dimensions are different (one is a 2xN matrix, the other blocks_in_row x blocks_in_column). I also wouldn't like to change the dimensions of motion_vectors, since then I would need a two-"layer" array. One for the x coordinates and one for y, but that doesn't fit to the further design.
I hope I made myself understandable, if not, please let me know.
Thanks for any clues!
If you're accessing an element of motion_vectors, you're getting data about a corresponding block. That means that there's a system of translating between an index 1 through N, where N is blocks_in_row*blocks_in_column, and a specific block. If index 1 is the top-left block, index 2 is the block to its right, and you increment as reading a book (left-to-right and wrap to the next row), then you would translate as follows:
row_of_block = floor((index_in_motion_vector-1)/number_of_columns) + 1
col_of_block = mod((index_in_motion_vector-1), number_of_columns) + 1
(This is called row-major ordering.)
If instead index 1 is the top-left block and index 2 is the block below it, and you wrap to the top of the next column when done with one, then the conversion would be
row_of_block = mod((index_in_motion_vector-1), number_of_rows) + 1
col_of_block = floor((index_in_motion_vector-1)/number_of_rows) + 1
(This is called column-major ordering, and is what MATLAB uses by default.)
So, if you're iterating 1 to N, you can just use those conversions. If you'd like to iterate 1 through number_of_rows, and 1 through number_of_columns you would do the opposite.
If you're using the book-like indexing of blocks (row-major ordering), the conversion to index of the motion vector would be
col_in_motion_vector = (row_of_block-1)*number_of_columns + column_of_block
If you're using the second, top-to-bottom-and-wrap method of indexing blocks (column-major ordering), the conversion would instead be
col_in_motion_vector = (column_of_block-1)*number_of_rows + row_of_block

(MATLAB) On drawing elements randomly from vectors and rows randomly from matrices without replacement in for loops

So, two related questions for code I'm writing for an experiment I'm building in MATLAB. Firstly, I have a 20 row column vector, called block1 (with a number in each of the 20 slots).
I want to draw a number randomly from the vector without replacement and repeat this until there are no numbers left in the vector (so 20 times total). I have the following line within a for loop (which is set to run for 20 iterations), which draws the random number from the vector and sets it equal to variable rand_num:
rand_num = randsample(block1,1,false)
It draws the random number just fine, but the problem is that the draw without replacement part doesn't work. Initially I thought this was because the vector was reset at the beginning of each iteration of the for loop. To make sure, I debugged and found that even when I stop the for loop before the first iteration finishes (and after the random number has been drawn), there are still 20 numbers in the vector (when there should be 19). Any ideas as to how I can fix this?
The second question is as follows. For the same experiment, I have a 20 by 6 matrix called pick_matrix. During each iteration of the same for loop as above, I want to pick one row at random from the matrix (including every element in that row; so 6 elements total for each row) without replacement and assign that row to variable random_row.
I figured out the code to pick a row at random and assign it to random_row, but I'm having the same problem as with the last question: the without replacement part isn't working.
randsample works fine, and exactly as expected. You just need to call it once before your loop rather than twenty times within the loop. Read the help carefully - randsample does not change anything about the input variable block1. Generally speaking (ignoring globals and such), input variables are not changed by Matlab functions, even if they are changed within a function, unless they are then explicitly output.
e.g. consider this:
function y = myfunc(x);
x = x*2;
y = x*3;
disp(x)
end
Within the function, x is doubled. Say I have a variable x in my workspace, value 10. If I call y = myfunc(2), I will see "4" displaced - and y will be output as 12, not 6. However, the x in my base workspace is never changed, which is exactly the expected behaviour.
If I want x to be changed, I have to set it explicitly as output to the function and deliberately call the function in such a way as to overwrite my variable x, e.g [x y] = myfunc(2);
As suggested in the comments, you could use randperm instead if you're taking every number, but a more generic example using randsample to take a random pick of 10 from 20:
% sampling without replacement is default
rand_nums = randsample(block1, 10);
rand_ind = randperm(20,10); % 10 numbers from 1:20
for n = 1:10
rand_num = rand_nums(n);
rand_row = pick_matrix(rand_ind(n),:);
% whatever you need to do with these things goes here
end

MATLAB: How to dynamically increase one of the column length of matrix

I declared a 3-dimension matrix like this , and later in the iteration, I need to dynamically expand the length of the third dimension.
Notice that currently, I only declare two dimensions but not the third dimension, so I will get an error like this:
Attempted to access bins(1,2,2); index out of bounds because
size(bins)=[2,22,1].
But the problem is, the Xk dimension is variable and I really cannot decide how it is needed. Is there anyway to declare a changeable matrix?
bins=zeros(2,size(Xtrain,2));
%Some for loop
bins(Y,k,Xk)=bins(Y,k,Xk)+1;
%end loop
You can use the end + k notation to dynamically expand the matrix as follows:
A = zeros(10,10,10);
size(A) %[10 10 10]
Xk = 5;
A(:,:,end+Xk) = 4;
size(A) %[10 10 15]
The size of A will have increased automatically and Matlab will automatically fill in-between values with zeros. However, resizing an array inside a loop is not a good way to program. You might want to rethink your method such that you aren't doing this.

modem.oqpskmod for BER

hi can anyone show how to use the modem.oqpskmod for BER. thanks!
h = modem.oqpskmod
y = modulate(h, values);
g = modem.oqpskdemod(h)
z = demodulate(g, y)
let's assume that i have array called values which contains only 1s and 0s.
my question is how would i calculate BER? of course if above my code is correct.
Based on this Wikipedia page, you simply have to compute the number of incorrect bits and divide by the total number of transferred bits to get the bit error rate (BER). If values is the unmodulated input signal and z is the output signal after modulation and demodulation, you can compute it like this:
BER = sum(logical(values(:)-z(:)))/numel(values);
EDIT: I modified the above code just in case you run into two situations:
If z has values other than 0 and 1.
If z is a different size than values (i.e. row vector versus column vector).
I don't know if you are ever likely to come across these two situations, but better safe than sorry. ;)