I've been making a multi-channel steaming DAQ system in Labview.
And, I bring the saved binary file into Matlab for post-processing.
I need to sort the file data, according to channels.
An example is below.
with 3 multiple channel acquisition and 5Hz sampling rate
First channel voltage : 1V(constant)
Second channel voltage : 2V(constant)
Third channel voltage : 3V(constant)
if I acquire signals for 4 seconds with this condition, the saved data will be like below, because the system saves the signal in buffer, once in a second, on a single file.
ch1=[1 1 1 1 1];
ch2=[2 2 2 2 2];
ch3=[3 3 3 3 3];
B=[ch1 ch2 ch3 ch1 ch2 ch3 ch1 ch2 ch3 ch1 ch2 ch3];
I want to rearrange the data like below.
desiredB=[ch1 ch1 ch1 ch1; ch2 ch2 ch2 ch2; ch3 ch3 ch3 ch3];
In order to rearrange B I made a code like below with two for loop.
fs=5; %sampling frequency
nCh=3; %number of channels
nB=length(B);
C=zeros(nB/fs,fs);
for i=1:nB/fs;
temp=B((i-1)*fs+1:fs*i);
C(i,1:fs)=temp;
end
sizeC=size(C);
T=sizeC(1)/nCh;
D=zeros(nCh,fs*T);
for j=1:T
temp2=C(3*(j-1)+1:3*j,:);
D(:,(j-1)*fs+1:j*fs)=temp2;
end
t_axis=0:1/fs:T-1/fs;
plot(t_axis,D','linewidth',2),grid on
axis([0 3.8 0 5])
xlabel('time(sec)')
ylabel('voltage(V)')
legend('first channel','second channel','third channel')
It worked, but when I read a big size data, it's slow.
Are there any nice ways to reshape this kind of data?
I think this does what you want:
fs=5; %sampling frequency
nCh=3; %number of channels
ch1=[11 12 13 14 15];
ch2=[21 22 23 24 25];
ch3=[31 32 33 34 35];
B=[ch1 ch2 ch3 ch1 ch2 ch3 ch1 ch2 ch3 ch1 ch2 ch3];
C = reshape(B, fs, nCh, []);
D = permute(C, [1, 3, 2]);
E = reshape(D, [], nCh).'
E =
11 12 13 14 15 11 12 13 14 15 11 12 13 14 15 11 12 13 14 15
21 22 23 24 25 21 22 23 24 25 21 22 23 24 25 21 22 23 24 25
31 32 33 34 35 31 32 33 34 35 31 32 33 34 35 31 32 33 34 35
Related
I have a p-by-p-by-n tensor. I want to extract diagonal element for each p-by-p slice. Are there anyone know how to do this without looping?
Thank you.
Behold the ever mighty and ever powerful bsxfun for vectorizing MATLAB problems to do this task very efficiently using MATLAB's linear indexing -
diags = A(bsxfun(#plus,[1:p+1:p*p]',[0:n-1]*p*p))
Sample run with 4 x 4 x 3 sized input array -
A(:,:,1) =
0.7094 0.6551 0.9597 0.7513
0.7547 0.1626 0.3404 0.2551
0.2760 0.1190 0.5853 0.5060
0.6797 0.4984 0.2238 0.6991
A(:,:,2) =
0.8909 0.1493 0.8143 0.1966
0.9593 0.2575 0.2435 0.2511
0.5472 0.8407 0.9293 0.6160
0.1386 0.2543 0.3500 0.4733
A(:,:,3) =
0.3517 0.9172 0.3804 0.5308
0.8308 0.2858 0.5678 0.7792
0.5853 0.7572 0.0759 0.9340
0.5497 0.7537 0.0540 0.1299
diags =
0.7094 0.8909 0.3517
0.1626 0.2575 0.2858
0.5853 0.9293 0.0759
0.6991 0.4733 0.1299
Benchmarking
Here's few runtime tests comparing this bsxfun based approach against repmat + eye based approach for big datasizes -
***** Datasize: 500 x 500 x 500 *****
----------------------- With BSXFUN
Elapsed time is 0.008383 seconds.
----------------------- With REPMAT + EYE
Elapsed time is 0.163341 seconds.
***** Datasize: 800 x 800 x 500 *****
----------------------- With BSXFUN
Elapsed time is 0.012977 seconds.
----------------------- With REPMAT + EYE
Elapsed time is 0.402111 seconds.
***** Datasize: 1000 x 1000 x 500 *****
----------------------- With BSXFUN
Elapsed time is 0.017058 seconds.
----------------------- With REPMAT + EYE
Elapsed time is 0.690199 seconds.
One suggestion I have is to create a p x p logical identity matrix, replicate this n times in the third dimension, and then use this matrix to access your tensor. Something like this, supposing that your tensor was stored in A:
ind = repmat(logical(eye(p)), [1 1 n]);
out = A(ind);
Example use:
>> p = 5; n = 3;
>> A = reshape(1:75, p, p, n)
A(:,:,1) =
1 6 11 16 21
2 7 12 17 22
3 8 13 18 23
4 9 14 19 24
5 10 15 20 25
A(:,:,2) =
26 31 36 41 46
27 32 37 42 47
28 33 38 43 48
29 34 39 44 49
30 35 40 45 50
A(:,:,3) =
51 56 61 66 71
52 57 62 67 72
53 58 63 68 73
54 59 64 69 74
55 60 65 70 75
>> ind = repmat(logical(eye(p)), [1 1 n]);
>> out = A(ind)
out =
1
7
13
19
25
26
32
38
44
50
51
57
63
69
75
You'll notice that we grab the diagonals of the first slice, followed by the diagonals of the second slice, etc. up until the last slice. These values are all concatenated into a single vector.
Just reading Divakar's answer and trying to understand why he again is roughly 10 times faster than my idea I put together code mixing both, and ended up with code which is faster:
A=reshape(A,[],n);
diags2 = A(1:p+1:p*p,:);
For a 500x500x500 tensor I get 0.008s for Divakar's solution and 0.005s for my solution using Matlab 2013a. Probably plain indexing is the only way to beat bsxfun.
I'm trying to implement the Baker map.
Is there a function that would allow one to divide a 8 x 8 matrix by providing, for example, a sequence of divisors 2, 4, 2 and rearranging pixels in the order as shown in the matrices below?
X = reshape(1:64,8,8);
After applying divisors 2,4,2 to the matrix X one should get a matrix like A shown below.
A=[31 23 15 7 32 24 16 8;
63 55 47 39 64 56 48 40;
11 3 12 4 13 5 14 6;
27 19 28 20 29 21 30 22;
43 35 44 36 45 37 46 38;
59 51 60 52 61 53 62 54;
25 17 9 1 26 18 10 2;
57 49 41 33 58 50 42 34]
The link to the document which I am working on is:
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.39.5132&rep=rep1&type=pdf
This is what I want to achieve:
Edit: a little more generic solution:
%function Z = bakermap(X,divisors)
function Z = bakermap()
X = reshape(1:64,8,8)'
divisors = [ 2 4 2 ];
[x,y] = size(X);
offsets = sum(divisors)-fliplr(cumsum(fliplr(divisors)));
if any(mod(y,divisors)) && ~(sum(divisors) == y)
disp('invalid divisor vector')
return
end
blocks = #(div) cell2mat( cellfun(#mtimes, repmat({ones(x/div,div)},div,1),...
num2cell(1:div)',...
'UniformOutput',false) );
%create index matrix
I = [];
for ii = 1:numel(divisors);
I = [I, blocks(divisors(ii))+offsets(ii)];
end
%create Baker map
Y = flipud(X);
Z = [];
for jj=1:I(end)
Z = [Z; Y(I==jj)'];
end
Z = flipud(Z);
end
returns:
index matrix:
I =
1 1 3 3 3 3 7 7
1 1 3 3 3 3 7 7
1 1 4 4 4 4 7 7
1 1 4 4 4 4 7 7
2 2 5 5 5 5 8 8
2 2 5 5 5 5 8 8
2 2 6 6 6 6 8 8
2 2 6 6 6 6 8 8
Baker map:
Z =
31 23 15 7 32 24 16 8
63 55 47 39 64 56 48 40
11 3 12 4 13 5 14 6
27 19 28 20 29 21 30 22
43 35 44 36 45 37 46 38
59 51 60 52 61 53 62 54
25 17 9 1 26 18 10 2
57 49 41 33 58 50 42 34
But have a look at the if-condition, it's just possible for these cases. I don't know if that's enough. I also tried something like divisors = [ 1 4 1 2 ] - and it worked. As long as the sum of all divisors is equal the row-length and the modulus as well, there shouldn't be problems.
Explanation:
% definition of anonymous function with input parameter: div: divisor vector
blocks = #(div) cell2mat( ... % converts final result into matrix
cellfun(#mtimes, ... % multiplies the next two inputs A,B
repmat(... % A...
{ones(x/div,div)},... % cell with a matrix of ones in size
of one subblock, e.g. [1,1,1,1;1,1,1,1]
div,1),... % which is replicated div-times according
to actual by cellfun processed divisor
num2cell(1:div)',... % creates a vector [1,2,3,4...] according
to the number of divisors, so so finally
every Block A gets an increasing factor
'UniformOutput',false...% necessary additional property of cellfun
));
Have also a look at this revision to have a simpler insight in what is happening. You requested a generic solution, thats the one above, the one linked was with more manual inputs.
I have a matrix of measured angles between M planes
0 52 77 79
52 0 10 14
77 10 0 3
79 14 3 0
I have a list of known angles between planes, which is an N-by-N matrix which I name rho. Here's is a subset of it (it's too large to display):
0 51 68 75 78 81 82
51 0 17 24 28 30 32
68 17 0 7 11 13 15
75 24 7 0 4 6 8
78 28 11 4 0 2 4
81 30 13 6 2 0 2
82 32 15 8 4 2 0
My mission is to find the set of M planes whose angles in rho are nearest to the measured angles.
For example, the measured angles for the planes shown above are relatively close to the known angles between planes 1, 2, 4 and 6.
Put differently, I need to find a set of points in a distance matrix (which uses cosine-related distances) which matches a set of distances I measured. This can also be thought of as matching a pattern to a mold.
In my problem, I have M=5 and N=415.
I really tried to get my head around it but have run out of time. So currently I'm using the simplest method: iterating over every possible combination of 3 planes but this is slow and currently written only for M=3. I then return a list of matching planes sorted by a matching score:
function [scores] = which_zones(rho, angles)
N = size(rho,1);
scores = zeros(N^3, 4);
index = 1;
for i=1:N-2
for j=(i+1):N-1
for k=(j+1):N
found_angles = [rho(i,j) rho(i,k) rho(j,k)];
score = sqrt(sum((found_angles-angles).^2));
scores(index,:)=[score i j k];
index = index + 1;
end
end;
end
scores=scores(1:(index-1),:); % was too lazy to pre-calculate #
scores=sortrows(scores, 1);
end
I have a feeling pdist2 might help but not sure how. I would appreciate any help in figuring this out.
There is http://www.mathworks.nl/help/matlab/ref/dsearchn.html for closest point search, but that requires same dimensionality. I think you have to bruteforce find it anyway because it's just a special problem.
Here's a way to bruteforce iterate over all unique combinations of the second matrix and calculate the score, after that you can find the one with the minimum score.
A=[ 0 52 77 79;
52 0 10 14;
77 10 0 3;
79 14 3 0];
B=[ 0 51 68 75 78 81 82;
51 0 17 24 28 30 32;
68 17 0 7 11 13 15;
75 24 7 0 4 6 8;
78 28 11 4 0 2 4;
81 30 13 6 2 0 2;
82 32 15 8 4 2 0];
M = size(A,1);
N = size(B,1);
% find all unique permutations of `1:M`
idx = nchoosek(1:N,M);
K = size(idx,1); % number of combinations = valid candidates for matching A
score = NaN(K,1);
idx_triu = triu(true(M,M),1);
Atriu = A(idx_triu);
for ii=1:K
partB = B(idx(ii,:),idx(ii,:));
partB_triu = partB(idx_triu);
score = norm(Atriu-partB_triu,2);
end
[~, best_match_idx] = min(score);
best_match = idx(best_match_idx,:);
The solution of your example actually is [1 2 3 4], so the upperleft part of B and not [1 2 4 6].
This would theoretically solve your problem, and I don't know how to make this algorithm any faster. But it will still be slow for large numbers. For example for your case of M=5 and N=415, there are 100 128 170 583 combinations of B which are a possible solution; just generating the selector indices is impossible in 32-bit because you can't address them all.
I think the real optimization here lies in cutting away some of the planes in the NxN matrix in a preceding filtering part.
I'm trying get a basic circular temperature contour graph in MATLAB.
Instead, I'm getting a straight line and doesn't resemble at all to
MATLAB's examples for contour maps. I want 4 circular zones
representing 90 degrees, 80 degrees, 70 degrees, and 60 degrees.
Here is my code:
long = [0 1 2 3; 4 5 6 7; 8 9 10 11; 12 13 14 15];
lat = [15 16 17 18; 19 20 21 22; 23 24 25 26; 27 28 29 30];
temp = [98 95 94 92; 85 82 81 80; 72 75 74 71; 65 62 61 69];
figure;
contour(long,lat,temp,4)
The problem is that you've only provided a line of data and not a matrix. You need to provide a temperature for each pair of long and lat. So if long and lat are both 1x15 then temp should be 15x15.
For example:
x = 1:3
y = 1:3
z = [1 2 1; 2 3 2; 1 2 1];
contour(x,y,z);
Assume we have the following data:
H_T = [36 66 21 65 52 67 73; 31 23 19 33 36 39 42]
P = [40 38 39 40 35 32 37]
Using MATLAB 7.0, I want to create three new matrices that have the following properties:
The matrix H (the first part in matrix H_T) will be divided to 3 intervals:
Matrix 1: the 1st interval contains the H values between 20 to 40
Matrix 2: the 2nd interval contains the H values between 40 to 60
Matrix 3: the 3rd interval contains the H values between 60 to 80
The important thing is that the corresponding T and P will also be included in their new matrices meaning that H will control the new matrices depending on the specifications defined above.
So, the resultant matrices will be:
H_T_1 = [36 21; 31 19]
P_1 = [40 39]
H_T_2 = [52; 36]
P_2 = [35]
H_T_3 = [66 65 67 73; 23 33 39 42]
P_3 = [38 40 32 37]
Actually, this is a simple example and it is easy by looking to create the new matrices depending on the specifications, BUT in my values I have thousands of numbers which makes it very difficult to do that.
Here's a quick solution
[~,bins] = histc(H_T(1,:), [20 40 60 80]);
outHT = cell(3,1);
outP = cell(3,1);
for i=1:3
idx = (bins == i);
outHT{i} = H_T(:,idx);
outP{i} = P(idx);
end
then you access the matrices as:
>> outHT{3}
ans =
66 65 67 73
23 33 39 42
>> outP{3}
ans =
38 40 32 37