Up-/Downsampling of a logical vector (not with zeros) - matlab

I hope you can help with a little problem I am having.
I want to upsample and downsample a vector with zeros and ones. We have the functions upsample and downsample for that, however, the upsample function in Matlab only adds zeros to the vector. I would like to repeat the value, instead of just putting in zeros.
Unfortunately the upsample function does not do that. Thus, I tried to use repmat (in the third dimension) and then reshape to get back to the old format. I know it must be possible with these functions, but if I simply use them, the vector just gets duplicated and added to the end.
An example:
The input vector is: [1 0 0 1 0 1 0 1 1 1 0 0] (these should be random).
Now I want to upsample (say) by a factor of 2. Then I want to get:
[1 1 0 0 0 0 1 1 0 0 1 1 0 0 1 1 1 1 1 1 0 0 0 0].
Thanks in advance for any help!

You can use repelem:
>> repelem([1 0 1],2)
ans =
1 1 0 0 1 1
Or using repmat and reshape when input is a column vector:
>> input = [1 0 1];
>> reshape(repmat(input, 2, 1), 1, [])
ans =
1 1 0 0 1 1

Related

Acces 3D Matrix with 2D index and 1D vector

I have a 3D matrix A (size m*n*k) where m=latitude, n*longitude and k=time.
I want only specific values from first and second dimension, specified by a logical matrix B (size m*n), and I want only the timesteps specified by vector C (size k).
In the end this should become a 2D matrix D, since the first two dimesions will colapse to one.
What is the most easy approach to do this?
And also is it possible to combine logical with linear indizes here? For example B is logical and C is linear?
Sample code with rand:
A=rand(10,10,10);
B=randi([0 1], 10,10);
C=randi([0 1], 10,1);
D=A(B,C) %This would be my approach which doesnt work. The size of D should be sum(B)*sum(c)
Another example without rand:
A=reshape([1:27],3,3,3);
B=logical([1,0,0;1,0,0;0,0,0]);
C=(1,3); %get data from timestep 1 and 5
D=A(B,C);%What I want to do, but doesnÄt work that way
D=[1,19;2,20];%Result should look like this! First dimension is now all data from dimesion 1 and 2. New dimesion 2 is now the time.
A = rand(4,4,4);
B = randi([0 1], 4,4)
B =
1 1 0 1
1 0 1 1
0 0 1 0
1 0 1 1
>> C = randi([0 1],1,1,4);
>> C(:)
ans =
0
1
1
0
Then use bsxfun or implicit expansion expansion whith .* if newer Matlab version to generate a matrix of logical for you given coordinates.
>> idx = logical(bsxfun(#times,B,C))
idx(:,:,1) =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
idx(:,:,2) =
1 1 0 1
1 0 1 1
0 0 1 0
1 0 1 1
idx(:,:,3) =
1 1 0 1
1 0 1 1
0 0 1 0
1 0 1 1
idx(:,:,4) =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
Then your output is D = A(idx). However, note that this D is now an Nx1 array. Where N is number of true elements is B times number of true elements in C. 10x True in B and 2x True in C:
>> size(D)
ans =
20 1
An easy way to do it is to first reshape A into an m*n-by-k matrix, then do your indexing:
result = reshape(A, [], size(A, 3));
result = result(B, C);
In this case C can be either a logical vector or vector of indices.

Matlab matrix save 1 positions for large matrices

I have a sparse matrix in Matlab. I would like to save the positions of 1's in the matrix row-wise and column-wise.
For example consider the below matrix:
0 1 0 1 0
0 0 0 1 0
0 0 0 0 0
0 0 1 0 0
1 0 0 0 0
I would like two files written as:
row-wise.csv:
1,2
1,4
2,4
4,3
5,1
column-wise.csv:
5,1
1,2
4,3
1,4
2,4
I know I can run a loop row-wise or column-wise and save element by element using fprintf, but is there a better way?
I'm dealing with very large matrices and I'm wondering what an efficient way is to do this?
You're going to want to use find to perform this task. Then to write them out to a csv file, you can simply use dlmwrite.
For the column-wise, you can use the two outputs of find which are the row index and column index of each 1 (in column-major order).
data = [0 1 0 1 0
0 0 0 1 0
0 0 0 0 0
0 0 1 0 0
1 0 0 0 0];
[row, col] = find(data);
M = [row, col];
dlmwrite('column-wise.csv', M);
Then to obtain the row-wise result, you can just sort your column-wise result by rows and then columns using sortrows.
dlmwrite('row-wise.csv', sortrows(M))
The alternative to this, is to perform find again on the transpose of your data (to force row-major ordering) but I would think that the sortrows approach is faster.
[col, row] = find(data.');
dlmwrite('row-wise.csv', [row, col])

Generate truth table in MatLab

I want to create a truth table in MatLab with i columns and i2 rows. For example, if i=2, then
T =
[0 0]
[1 0]
[0 1]
[1 1]
Code to do this has already been created here
This is part of a larger project, which requires i large. Efficiency is a concern. Is there more efficient code to create a truth table? Does MatLab have a built in function to do this?
Edit: Sorry about the formatting!
Something like this?
n=2;
d=[0:2^n-1].';
T=dec2bin(d,n)
T =
00
01
10
11
dec2bin will give you a character array, which you can convert to logical, if needed. There's also de2bi that gives you a numeric array directly, but you need a newer version of Matlab and the ordering of the bits is reversed.
Here's Luis Mendo's speedup, which replicates dec2bin (n and d are as above):
T=rem(floor(d*pow2(1-n:0)),2);
ndgrid is very much your friend here:
function t = truthTable(n)
dims = repmat({[false, true]}, 1, n);
[grids{1:n}] = ndgrid(dims{:});
grids = cellfun(#(g)g(:), grids, 'UniformOutput',false);
t = [grids{:}];
First you need to create grids for the number of dimensions in your truth table. Once you have those you can columnize them to get the column vectors you need and you can horizontally concatenate those column vectors to get your truth table.
I imagine the performance of this will be quite competitive.
>> truthTable(2)
ans =
0 0
1 0
0 1
1 1
>> truthTable(4)
ans =
0 0 0 0
1 0 0 0
0 1 0 0
1 1 0 0
0 0 1 0
1 0 1 0
0 1 1 0
1 1 1 0
0 0 0 1
1 0 0 1
0 1 0 1
1 1 0 1
0 0 1 1
1 0 1 1
0 1 1 1
1 1 1 1
>>
>> timeit(#() truthTable(20))
ans =
0.030922626777
EDIT: Use reshape instead of column dereferencing for further performance improvement
function t = truthTable(n)
dims = repmat({[false, true]}, 1, n);
[grids{1:n}] = ndgrid(dims{:});
grids = cellfun(#(g) reshape(g,[],1), grids, 'UniformOutput',false);
t = [grids{:}];
>> timeit(#() truthTable(20))
ans =
0.016237298777
I know this question has been dead a while, but I was wondering the same thing and found a solution I like a lot. Thought I'd share it here:
fullfact(ones(1, i) + 1) - 1

Count the number of the first zero elements

I would line to find the number of the first consecutive zero elements. For example in [0 0 1 -5 3 0] we have two zero consecutive elements that appear first in the vector.
could you please suggest a way without using for loops?
V=[0 0 1 -5 3 0] ;
k=find(V);
Number_of_first_zeros=k(1)-1;
Or,
Number_of_first_zeros=find(V,1,'first')-1;
To solve #The minion comment (if that was the purpose):
Number_of_first_zeros=find(V(find(~V,1,'first'):end),1,'first')-find(~V,1,'first');
Use a logical array to find the zeros and then look at where the zeros and ones are alternating.
V=[1 2 0 0 0 3 5123];
diff(V==0)
ans =
0 1 0 0 -1 0
Create sample data
V=[1 2 0 0 0 3 5123];
Find the zeros. The result will be a logical array where 1 represents the location of the zeros
D=V==0
D =
0 0 1 1 1 0 0
Take the difference of that array. 1 would then represent the start and -1 would represent the end.
T= diff(D)
ans =
0 1 0 0 -1 0
find(T==1) would give you the start and find(T==-1) would give you the end. The first index+1 of T==1 would be the start of the first set of zeros and the first index of T==-1 would be the end of the first set of zeros.
You could find position the first nonzero element using find.
I=find(A, 1);
The number of leading zeros is then I-1.
My solution is quite complex yet it doesn't use the loops and it does the trick. I am pretty sure, that there is a more direct approach.
Just in case no one else posts a working solution here my idea.
x=[1 2 4 0 20 0 10 1 23 45];
x1=find(x==0);
if numel(x1)>1
x2=[x1(2:end), 0];
x3=x2-x1;
y=find(x3~=1);
y(1)
elseif numel(x1)==1
display(1)
else
display('No zero found')
end
x is the dataset. x1 contains the index of all zero elements. x2 contains all those indices except the first one (because matrix dimensions must agree, one zero is added. x3 is the difference between the index and the previous index of zeros in your dataset. Now I find all those differences which are not 1 (do not correspond to sequences of zeros) and the first index (of this data is the required result. The if case is needed in case you have only one or no zero at all.
I'm assuming your question is the following: for the following vector [0 0 1 -5 3 0], I would like to find the index of the first element of a pair of 0 values. Is this correct? Therefore, the desired output for your vector would be '1'?
To extend the other answers to find any such pairs, not just 0 0 (eg. 0 1, 0 2, 3 4 etc), then this might help.
% define the pattern
ptrn = [ 0 0 ];
difference = ptrn(2) - ptrn(1)
V = [0 0 1 -5 3 0 0 2 3 4 0 0 1 0 0 0]
x = diff(V) == difference
indices = find(x)
indices =
1 6 11 14 15

Matlab PRBS 4 waveform generation

I have a variable which has values of PRBS 4 sequence.
Output = [0 0 0 1 0 0 1 1 0 1 0 1 1 1 1];
I want to plot this in Matlab. I know I have to use idinput() function to generate prbs sequences. But I am using an old version of Matlab and this function is not available for me. Just by using plot(Output) will not give me the PRBS signal, since in the transition from 0 to 1 and 1 to 0, it will be like a triangle. I need to have a square waveform for PRBS.
Also, I want to make this signal 1 Gbps signal. Is this possible to do?
Best Regards,
nkp.
You can repeat each of output bit by some number and then plot.
For example: output = [0 0 1 0];
Then you repeat each bit by some number (let say 4), so the output vector is
[0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0].