Sum up two MAT files - matlab

I am trying to add/sum/merge two MAT files. Both the files contain only numeric values. Basically like this:
'file_1' contains
2 0 2 0 1 0...
3 0 9 0 2 0...
1 0 6 0 7 0...
...
'file_2.mat' contains
0 1 0 9 0 7 ...
0 5 0 5 0 8 ...
0 9 0 1 0 2 ...
...
i.e. in both files every alternate columns are zero. I want to merge them and form like this:
2 1 2 9 1 7...
3 5 9 5 2 8...
1 9 6 1 7 2...
...
and save this as a new mat file, 'file_3.mat'. And write this new file as an Image. How to do it?

Assuming that A contains the first matrix and B contains the second, you just need to do:
C = A + B
Example:
% create dummy values
A = magic(5);
A(:,1:2:5) = 0;
B = magic(5);
B(:,2:2:5) = 0;
C = A + B
This will output:
C =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9

Related

Bin interaction frequencies

I have 10 bins, and each bin contains a specific number of observations, e.g.:
a = [0,0,1,0,0,2,0,0,0,2]
I'd like to subsequently tally how many times any given pair of (non-zero) bins co-occur - based on the number of observations.
Given the above example, bin#3 = 1, bin#6 = 2 and bin#10 = 2.
This means that bin 3 and 6 co-occurred once, bin 3 and 10 co-occurred once, and bin 6 and 10 co-occurred twice (the minimum value of the pair is taken).
My desired output is a full matrix, listing every possible bin combination (columns 1-2) and the tally of what was observed (column 3):
1 2 0
1 3 0
1 4 0
1 5 0
1 6 0
1 7 0
1 8 0
1 9 0
1 10 0
2 3 0
2 4 0
2 5 0
2 6 0
2 7 0
2 8 0
2 9 0
2 10 0
3 4 0
3 5 0
3 6 1
3 7 0
3 8 0
3 9 0
3 10 1
4 5 0
4 6 0
4 7 0
4 8 0
4 9 0
4 10 0
5 6 0
5 7 0
5 8 0
5 9 0
5 10 0
6 7 0
6 8 0
6 9 0
6 10 2
7 8 0
7 9 0
7 10 0
8 9 0
8 10 0
9 10 0
Is there a short and/or fast way of doing this?
You can get all combinations of the bin numbers in many ways. I'll use combvec for ease.
Then it's relatively simple to vectorise this using min...
a = [0,0,1,0,0,2,0,0,0,2];
n = 1:numel(a);
% Use unique and sort to get rid of duplicate pairs when order doesn't matter
M = unique( sort( combvec( n, n ).', 2 ), 'rows' );
% Get rid of rows where columns 1 and 2 are equal
M( M(:,1) == M(:,2), : ) = [];
% Get the overlap count for bins
M( :, 3 ) = min( a(M), [], 2 );
Try this.
bin_output = [....];
bin_matrix = [0,0,1,0,0,2,0,0,0,2];
bin_nonzero = find(bin_matrix);
for j = 1:length(bin_nonzero);
if isequal(j,length(bin_nonzero))
break;
end
for k = (j+1):(length(bin_nonzero))
for m = 1:length(bin_output)
if isequal(bin_output(m,1),j) && isequal(bin_output(m,2),k)
bin_output(m,3) = bin_output(m,3) + min([bin_matrix(1,bin_nonzero(1,j)),bin_matrix(1,bin_nonzero(1,k))]);
end
end
end
end

How to separately compute the Euclidean Distance in different dimension?

I got a question when using pdist, it would be so many thanks if you could give me some advice. The pdist(D) usually gives the sum of the distance for the multiple dimension, however, I want to get the distance separately. For example I have a data set S which is a 10*2 matrix , I am using pdist(S(:,1)) and pdist(S(:,2)) to get the distance separately, but this seems very inefficient when the data has many dimensions. Is there any alternative way to achieve this more efficient? Thanks in advance!
Assuming you just want the absolute difference between the individual dimensions of the points then pdist is overkill. You can use the following simple function
function d = pdist_1d(S)
idx = nchoosek(1:size(S,1),2);
d = abs(S(idx(:,1),:) - S(idx(:,2),:));
end
which returns the absolute pairwise difference between all pairs of rows in S.
In this case
dist = pdist_1d(S)
gives the same result as
dist = cell2mat(arrayfun(#(dim)pdist(S(:,dim))',1:size(S,2),'UniformOutput',false));
Another option, since you're simply taking the absolute difference of the coordinates, is to use bsxfun:
>> D = randi(20, 10, 2) % generate sample data
D =
17 12
14 10
8 4
7 11
19 13
2 18
11 14
5 19
19 12
20 8
From here, we permute the data so that the coordinates (columns) extend into the 3rd dimension and the rows are in the 1st dimension for the 1st argument, and the 2nd dimension for the 2nd argument:
>> dist = bsxfun(#(x,y)abs(x-y), permute(D, [1 3 2]), permute(D, [3 1 2]))
dist =
ans(:,:,1) =
0 3 9 10 2 15 6 12 2 3
3 0 6 7 5 12 3 9 5 6
9 6 0 1 11 6 3 3 11 12
10 7 1 0 12 5 4 2 12 13
2 5 11 12 0 17 8 14 0 1
15 12 6 5 17 0 9 3 17 18
6 3 3 4 8 9 0 6 8 9
12 9 3 2 14 3 6 0 14 15
2 5 11 12 0 17 8 14 0 1
3 6 12 13 1 18 9 15 1 0
ans(:,:,2) =
0 2 8 1 1 6 2 7 0 4
2 0 6 1 3 8 4 9 2 2
8 6 0 7 9 14 10 15 8 4
1 1 7 0 2 7 3 8 1 3
1 3 9 2 0 5 1 6 1 5
6 8 14 7 5 0 4 1 6 10
2 4 10 3 1 4 0 5 2 6
7 9 15 8 6 1 5 0 7 11
0 2 8 1 1 6 2 7 0 4
4 2 4 3 5 10 6 11 4 0
This results in a 3-d symmetric matrix where
dist(p, q, d)
gives you the distance between points p and q in dimension d with
dist(p, q, d) == dist(q, p, d)
If you want the distances between p and q in all (or multiple) dimensions, you should use squeeze to put it in a vector:
>> squeeze(dist(3, 5, :))
ans =
11
9
Note that if you're using MATLAB 2016b or later (or Octave) you can create the same distance matrix without bsxfun:
dist = abs(permute(D, [1 3 2]) - permute(D, [3 1 2]))
The downside to this approach is that it creates the full symmetric matrix so you're generating each distance twice, which could potentially become a memory issue.

Setting a specified number of rows in each column and block of elements to zero

Is there any easy way to set a specified number of rows k in nth column to zero ? Its a bit tricky question to explain so I guess its best to look at the example.
Lets say I have:
A =
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
16 17 18
I wish to set rows, like this: [row1 col1] = 0; [row2 col1] = 0, and then [row3 col2]= 0; row4 col2]= 0 and so on, so my output is:
k = 2
B =
0 2 3
0 5 6
7 0 9
10 0 12
13 14 0
16 17 0
Do you have any suggestions/solutions how this could be solved with a for loop, or maybe there is another way?
and how this solution could be extend further to something like this:
A =
1 2 3 1 2 3
4 5 6 4 5 6
7 8 9 7 8 9
10 11 12 10 11 12
13 14 15 13 14 15
16 17 18 16 17 18
B =
0 0 3 1 2 3
0 0 6 4 5 6
7 8 0 0 8 9
10 11 0 0 3 1
13 14 15 13 0 0
16 17 18 16 0 0
One approach -
k = 2;
row1 = 1:size(A,1)
col1 = ceil([1:size(A,1)]./k)
A(sub2ind(size(A),row1,col1))=0
For the edited question, use kron like this -
k = 2;
a1 = eye(size(A)./k);
b1 = ones(k,k);
A(logical(kron(a1,b1)))=0
That isn't a problem. We can figure out exactly which rows and columns you want to set to 0 based on this value k, then use sub2ind to get a single index to access into your matrix. This will be in column-major format. Then you can use this and set all of your values to zero. Here is an example. We need to know the width and height of your matrix first before we do this:
rows = [row1 row2 row3];
cols = [col1 col2 col3];
%// Get column major indices
ind = sub2ind([height width], rows, cols);
%// Set the values in this matrix to 0.
B(ind) = 0;
Now with your example, we need to access all of the rows. However, for the columns, we need to access k elements in each column and ensuring they don't overlap. As such, we can do it like so:
k = 2;
B = reshape(1:18, 6, 3).';
rows = 1 : 6;
cols = ceil(rows / k);
ind = sub2ind([rows cols], rows, cols);
B(ind) = 0;
You would thus get:
B =
0 2 3
0 5 6
7 0 9
10 0 12
13 14 0
16 17 0
The following code is executable in matlab, and does what you want:
% Create A-matrix
A = reshape(1:18,6,3)
% Set specified datapoints to zero
A([1,2],[1,1]) = 0
Alternatively, you can set each element separately
A(1,1) = 0
A(1,2) = 0
And the most general way, with k and n:
A([1:k],n) = 0
For first question:
A(mod(0:numel(A)-1, size(A,1)+k) < k) = 0;
For second question, including first question as a particular case:
c = repmat({ones(k,size(B,2)/size(B,1)*k)}, size(B,1)/k, 1);
B = B.*~blkdiag(c{:})

Extracting portions of matrix into cell array

I have a pretty large matrix M and I am only interested in a few of the columns. I have a boolean vector V where a value of 1 represents a column that is of interest. Example:
-1 -1 -1 7 7 -1 -1 -1 7 7 7
M = -1 -1 7 7 7 -1 -1 7 7 7 7
-1 -1 7 7 7 -1 -1 -1 7 7 -1
V = 0 0 1 1 1 0 0 1 1 1 1
If multiple adjacent values of V are all 1, then I want the corresponding columns of M to be extracted into another matrix. Here's an example, using the matrices from before.
-1 7 7 -1 7 7 7
M1 = 7 7 7 M2 = 7 7 7 7
7 7 7 -1 7 7 -1
How might I do this efficiently? I would like all these portions of the matrix M to be stored in a cell array, or at least have an efficient way to generate them one after the other. Currently I'm doing this in a while loop and it is not as efficient as I'd like it to be.
(Note that my examples only include the values -1 and 7 just for clarity; this isn't the actual data I use.)
You can utilize the diff function for this, to break your V vector into blocks
% find where block differences exist
diffs = diff(V);
% move start index one value forward, as first value in
% diff represents diff between first and second in original vector
startPoints = find(diffs == 1) + 1;
endPoints = find(diffs == -1);
% if the first block begins with the first element diff won't have
% found start
if V(1) == 1
startPoints = [1 startPoints];
end
% if last block lasts until the end of the array, diff won't have found end
if length(startPoints) > length(endPoints)
endPoints(end+1) = length(V);
end
% subset original matrix into cell array with indices
results = cell(size(startPoints));
for c = 1:length(results)
results{c} = M(:,startPoints(c):endPoints(c));
end
The one thing I'm not sure of is if there's a better way to find the being_indices and end_indices.
Code:
X = [1 2 3 4 5 1 2 3 4 5
6 7 8 9 10 6 7 8 9 10
11 12 13 14 15 11 12 13 14 15
16 17 18 19 20 16 17 18 19 20
1 2 3 4 5 1 2 3 4 5
6 7 8 9 10 6 7 8 9 10
11 12 13 14 15 11 12 13 14 15
16 17 18 19 20 16 17 18 19 20];
V = logical([ 1 1 0 0 1 1 1 0 1 1]);
find_indices = find(V);
begin_indices = [find_indices(1) find_indices(find(diff(find_indices) ~= 1)+1)];
end_indices = [find_indices(find(diff(find_indices) ~= 1)) find_indices(end)];
X_truncated = mat2cell(X(:,V),size(X,1),[end_indices-begin_indices]+1);
X_truncated{:}
Output:
ans =
1 2
6 7
11 12
16 17
1 2
6 7
11 12
16 17
ans =
5 1 2
10 6 7
15 11 12
20 16 17
5 1 2
10 6 7
15 11 12
20 16 17
ans =
4 5
9 10
14 15
19 20
4 5
9 10
14 15
19 20

How to split 1xN vector into MxL vector and fill the rest with zeros?

I have a matrix
a = [1 2 3 4 5 6 7 8 9 10 11]
I need to split it into rows of 5 and fill the rest of the unset block with zeros like this:
transformed = [ 1 2 3 4 5 ;
6 7 8 9 10;
11 0 0 0 0 ]
You could first expand a to have the required number of elements like this;
a(15) = 0 % Matlab will automatically fill elements 12:14 with 0
then
transformed = reshape(a,[5,3])'
produces
ans =
1 2 3 4 5
6 7 8 9 10
11 0 0 0 0