Concatenating binary bits into a number - matlab

I want to concatenate last four bits of binary into a number i have tried the following code
x8=magic(4)
x8_n=dec2bin(x8)
m=x8_n-'0'
which gives me the following output
m =
1 0 0 0 0
0 0 1 0 1
0 1 0 0 1
0 0 1 0 0
0 0 0 1 0
0 1 0 1 1
0 0 1 1 1
0 1 1 1 0
0 0 0 1 1
0 1 0 1 0
0 0 1 1 0
0 1 1 1 1
0 1 1 0 1
0 1 0 0 0
0 1 1 0 0
0 0 0 0 1
now i want to take every last 4 bits it each row and convert it into an integer

n = 4; %// number of bits you want
result = m(:,end-n+1:end) * pow2(n-1:-1:0).'; %'// matrix multiplication
Anyway, it would be easier to use mod on x8 directly, without the intermediate step of m:
result = mod(x8(:), 2^n);
In your example:
result =
0
5
9
4
2
11
7
14
3
10
6
15
13
8
12
1

This could be another approach -
n = 4; %%// number of bits you want
out = bin2dec(num2str(m(:,end-n+1:end)))
Output -
out =
0
5
9
4
2
11
7
14
3
10
6
15
13
8
12
1

Related

find longest sequence of non nan values but allow for threshold

Is it possible to find the non nan values of a vector but also allowing n number of nans? For example, if I have the following data:
X = [18 3 nan nan 8 10 11 nan 9 14 6 1 4 23 24]; %// input array
thres = 1; % this is the number of nans to allow
and I would like to only keep the longest sequence of values with non nans but allow 'n' number of nans to be kept in the data. So, say that I am willing to keep 1 nan I would have an output of
X_out = [8 10 11 nan 9 14 6 1 4 23 24]; %// output array
Thats is, the two nans at the beginning have been removed becuase they exceed the values in 'thres' above, but the third nan is on its own thus can be kept in the data. I would like to develop a method where thres can be defined as any value.
I can find the non nan values with
Y = ~isnan(X); %// convert to zeros and ones
Any ideas?
In order to find the longest sequence containing at most threshold times NaN we must find the start and the end of said sequence(s).
To generate all possible start points, we can use hankel:
H = hankel(X)
H =
18 3 NaN NaN 8 10 11 NaN 9 14 6 1 4 23 24
3 NaN NaN 8 10 11 NaN 9 14 6 1 4 23 24 0
NaN NaN 8 10 11 NaN 9 14 6 1 4 23 24 0 0
NaN 8 10 11 NaN 9 14 6 1 4 23 24 0 0 0
8 10 11 NaN 9 14 6 1 4 23 24 0 0 0 0
10 11 NaN 9 14 6 1 4 23 24 0 0 0 0 0
11 NaN 9 14 6 1 4 23 24 0 0 0 0 0 0
NaN 9 14 6 1 4 23 24 0 0 0 0 0 0 0
9 14 6 1 4 23 24 0 0 0 0 0 0 0 0
14 6 1 4 23 24 0 0 0 0 0 0 0 0 0
6 1 4 23 24 0 0 0 0 0 0 0 0 0 0
1 4 23 24 0 0 0 0 0 0 0 0 0 0 0
4 23 24 0 0 0 0 0 0 0 0 0 0 0 0
23 24 0 0 0 0 0 0 0 0 0 0 0 0 0
24 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Now we need to find the last valid element in each row.
To do so, we can use cumsum:
C = cumsum(isnan(H),2)
C =
0 0 1 2 2 2 2 3 3 3 3 3 3 3 3
0 1 2 2 2 2 3 3 3 3 3 3 3 3 3
1 2 2 2 2 3 3 3 3 3 3 3 3 3 3
1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
The end point for each row is the one, where the corresponding element in C is at most threshold:
threshold = 1;
T = C<=threshold
T =
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
The last valid element is found using:
[~,idx]=sort(T,2);
lastone=idx(:,end)
lastone =
3 2 1 4 15 15 15 15 15 15 15 15 15 15 15
We must make sure that the actual length of each row is respected:
lengths = length(X):-1:1;
real_length = min(lastone,lengths);
[max_length,max_idx] = max(real_length)
max_length =
11
max_idx =
5
In case there are more sequences of equal maximum length, we just take the first and display it:
selected_max_idx = max_idx(1);
H(selected_max_idx, 1:max_length)
ans =
8 10 11 NaN 9 14 6 1 4 23 24
full script
X = [18 3 nan nan 8 10 11 nan 9 14 6 1 4 23 24];
H = hankel(X);
C = cumsum(isnan(H),2);
threshold = 1;
T = C<=threshold;
[~,idx]=sort(T,2);
lastone=idx(:,end)';
lengths = length(X):-1:1;
real_length = min(lastone,lengths);
[max_length,max_idx] = max(real_length);
selected_max_idx = max_idx(1);
H(selected_max_idx, 1:max_length)
Approach 1: convolution
One possible approach is to convolve Y = double(~isnan(X)); with a window of n ones, where n is decreased by until an acceptable subsequence is found. "Acceptable" means that the subsequence contains at least n-thres ones, that is, the convolution gives at least n-thres.
Y = double(~isnan(X));
for n = numel(Y):-1:1 %// try all possible sequence lengths
w = find(conv(Y,ones(1,n),'valid')>=n-thres); %// is there any acceptable subsequence?
if ~isempty(w)
break
end
end
result = X(w:w+n-1);
Aproach 2: cumulative sum
Convolving Y with a window of n ones (as in approach 1) is equivalent to computing a cumulative sum of Y and then taking differences with n spacing. This is more efficient in terms of number of operations.
Y = double(~isnan(X));
Z = cumsum(Y);
for n = numel(Y):-1:1
w = find([Z(n) Z(n+1:end)-Z(1:end-n)]>=n-thres);
if ~isempty(w)
break
end
end
result = X(w:w+n-1);
Approach 3: 2D convolution
This essentially computes all iterations of the loop in approach 1 at once.
Y = double(~isnan(X));
z = conv2(Y, tril(ones(numel(Y))));
[nn, ww] = find(bsxfun(#ge, z, (1:numel(Y)).'-thres)); %'
[n, ind] = max(nn);
w = ww(ind)-n+1;
result = X(w:w+n-1);
Let's try my favorite tool: RLE. Matlab doesn't have a direct function, so use my "seqle" posted to exchange central. Seqle's default is to return run length encoding. So:
>> foo = [ nan 1 2 3 nan nan 4 5 6 nan 5 5 5 ];
>> seqle(isnan(foo))
ans =
run: [1 3 2 3 1 3]
val: [1 0 1 0 1 0]
The "run" indicates the length of the current run; "val" indicates the value. In this case, val==1 indicates the value is nan and val==0 indicates numeric values. You can see it'll be relatively easy to extract the longest sequence of "run" values meeting the condition val==0 | run < 2 to get no more than one nan in a row. Then just grab the cumulative indices of that run and that's the subset of foo you want.
EDIT:
sadly, what's trivial to find by eye may not be so easy to extract via code. I suspect there's a much faster way to use the indices identified by longrun to get the desired subsequence.
>> foo = [ nan 1 2 3 nan nan 4 5 6 nan nan 5 5 nan 5 nan 4 7 4 nan ];
>> sfoo= seqle(isnan(foo))
sfoo =
run: [1 3 2 3 2 2 1 1 1 3 1]
val: [1 0 1 0 1 0 1 0 1 0 1]
>> longrun = sfoo.run<2 |sfoo.val==0
longlong =
run: [2 1 1 1 6]
val: [1 0 1 0 1]
% longrun identifies which indices might be part of a run
% longlong identifies the longest sequence of valid run
>> longlong = seqle(longrun)
>> lfoo = find(sfoo.run<2 |sfoo.val==0);
>> sbar = seqle(lfoo,1);
>> maxind=find(sbar.run==max(sbar.run),1,'first');
>> getlfoo = lfoo( sum(sbar.run(1:(maxind-1)))+1 );
% first value in longrun , which is part of max run
% getbar finds end of run indices
>> getbar = getlfoo:(getlfoo+sbar.run(maxind)-1);
>> getsbar = sfoo.run(getbar);
% retrieve indices of input vector
>> startit = sum(sfoo.run(1:(getbar(1)-1))) +1;
>> endit = startit+ ((sum(sfoo.run(getbar(1):getbar(end ) ) ) ) )-1;
>> therun = foo( startit:endit )
therun =
5 5 NaN 5 NaN 4 7 4 NaN
Hmmm, who doesn't like challenges, my solution is not as good as m.s.'s, but it is an alternative.
X = [18 3 nan nan 8 10 11 nan 9 14 6 1 4 23 24]; %// input array
thresh =1;
X(isnan(X))= 0 ;
for i = 1:thresh
Y(i,:) = circshift(X',-i); %//circular shift
end
For some reason, the Matlab invert " ' " makes the formatting looks weird.
D = X + sum(Y,1);
Discard = find(D==0)+thresh; %//give you the index of the part that needs to be discarded
chunk = find(X==0); %//Segment the Vector into segments delimited by NaNs
seriesOfZero = circshift(chunk',-1)' - chunk;
bigchunk =[1 chunk( find(seriesOfZero ~= 1)) size(X,2)]; %//Convert series of NaNs into 1 chunk
[values,DiscardChunk] = intersect(bigchunk,Discard);
DiscardChunk = sort(DiscardChunk,'descend')
for t = 1:size(DiscardChunk,2)
X(bigchunk(DiscardChunk(t)-1):bigchunk(DiscardChunk(t))) = []; %//Discard the data
end
X(X == 0) = NaN
%//End of Code
8 10 11 NaN 9 14 6 1 4 23 24
When:
X = [18 3 nan nan nan 8 10 11 nan nan 9 14 6 1 nan nan nan 4 23 24]; %// input array
thresh =2;
8 10 11 NaN 4 23 24

Calculating a partial cumulative sum for a square matrix

Let's say I have a square matrix M:
M = [0 0 0 0 0 1 9; 0 0 0 0 0 4 4; 0 0 1 1 6 1 1; 0 1 2 9 2 1 0; 2 1 8 3 2 0 0; 0 8 1 1 0 0 0; 14 2 0 1 0 0 0]
0 0 0 0 0 1 9
0 0 0 0 0 4 4
0 0 1 1 6 1 1
M = 0 1 2 9 2 1 0
2 1 8 3 2 0 0
0 8 1 1 0 0 0
14 2 0 1 0 0 0
Now I'd like to calculate two different cumulative sums: One that goes from the top of each column to the element of the column, that is a diagonal element of the matrix, and one that goes from the bottom of the column to the same diagonal element.
The resulting matrix M'should therefore be the following:
0 0 0 0 0 1 9
0 0 0 0 0 4 5
0 0 1 1 6 2 1
M' = 0 1 3 9 4 1 0
2 2 8 5 2 0 0
2 8 1 2 0 0 0
14 2 0 1 0 0 0
I hope the explanation of what I'm trying to achieve is comprehensible enough. Since my matrices are much larger than the one in this example, the calculation should be efficient as well...but so far I couldn't even figure out how to calculate it "inefficiently".
In one line using some flipping and the upper triangular function triu:
Mp = fliplr(triu(fliplr(cumsum(M)),1)) ...
+flipud(triu(cumsum(flipud(M)),1)) ...
+flipud(diag(diag(flipud(M))));
The following will do the job:
Mnew = fliplr(triu(cumsum(triu(fliplr(M)),1))) + flipud(triu(cumsum(triu(flipud(M)),1)));
Mnew = Mnew - fliplr(diag(diag(fliplr(Mnew)))) + fliplr(diag(diag(fliplr(M))));
But is it the fastest method?
I think logical indexing might get you there faster

read data and save it in a single matrix

i have below .dat file, i want matlab reads data in the 'REQUESTS/DURATIONS:' part and save them in a single matrix in size (32,7). i don't know which function to use ,i don't know how to do it. please help me.
file with basedata : j30_17.bas
initial value random generator: 79602564
projects : 1
jobs (incl. supersource/sink ): 32
horizon : 141
RESOURCES
- renewable : 4 R
- nonrenewable : 0 N
- doubly constrained : 0 D
REQUESTS/DURATIONS:
jobnr. mode duration R 1 R 2 R 3 R 4
------------------------------------------------------------------------
1 1 0 0 0 0 0
2 1 1 0 0 0 5
3 1 1 0 3 0 0
4 1 1 8 0 0 0
5 1 7 0 0 2 0
6 1 6 0 0 0 3
7 1 4 1 0 0 0
8 1 5 0 0 10 0
9 1 8 0 0 3 0
10 1 7 0 0 0 1
11 1 8 9 0 0 0
12 1 1 7 0 0 0
13 1 2 0 3 0 0
14 1 3 0 0 0 6
15 1 10 0 7 0 0
16 1 10 3 0 0 0
17 1 2 0 0 3 0
18 1 10 0 0 4 0
19 1 1 0 0 0 3
20 1 1 0 0 7 0
21 1 7 0 2 0 0
22 1 9 0 0 0 10
23 1 9 0 0 7 0
24 1 4 0 4 0 0
25 1 4 0 3 0 0
26 1 1 0 0 4 0
27 1 1 9 0 0 0
28 1 8 0 0 0 9
29 1 1 0 0 0 1
30 1 2 0 8 0 0
31 1 7 0 4 0 0
32 1 0 0 0 0 0
************************************************************************
RESOURCEAVAILABILITIES:
R 1 R 2 R 3 R 4
10 8 13 12
************************************************************************
If you skip the header, textscan() will stop reading the file once the actual type of data does not correspond to the one specified in format, i.e. when all those asterisks begin:
fid = fopen('C:\...\test.txt');
data = textscan(fid, '%f%f%f%f%f%f%f','HeaderLines',15);
fclose(fid);
I'm not sure about older versions, but 2013a can import text files by right clicking a file under the "Current Folder" panel and selecting "Import Data...". The import wizard will open up and allow you to select the range of data to import. Select the matrix option, and click "Import Selection."
To save your matrix, just use the save command.
This approach works well for single files that you just need to read quickly, but not for a large repetetive task.

profile of circular image - more efficient way to do it?

I need to get a 1-D profile of a circular image, for example 256x256 sin(R) image
I've written a matlab function for the task but it turns out to be very un-efficient.
the function averages over radius intervals of the original images.
matlab profiler reveals that the first line in the for-loop [indxs=find(...)]
takes ~86% of the running time.
i need to run the function on a some thousands of simulated images (some larger then 256x256) and it takes very long time to complete.
does anyone knows how can i make this code run faster?
maybe someone has another, more efficient way to do the task??
i also tried to convert to function into C++ & mex file using matlab coder
but it took longer (x3) to perform the task, might be because the sub-function- "findC"
uses some 2D-ffts to find the center of the image.
Thanks you All,
Dudas
My Matlab function:
function [sig R_axis Center]= Im2Polar (imR,ch,Center_Nblock)
% Converts Circular image to 1-D sig
% based on true image values w/o interpolation
% Input -
% imR - circular sinuns image
% ch - number of data-points in output signal (sig)
% Center_Nblock - a varible related to the image center finding method
% Output -
% sig - 1D vector of the circular image profile
% R_axis - axis data-points for sig
% Center - image center in pixels
[Mr Nr] = size(imR); % size of rectangular image
[Center]=findC(imR,Center_Nblock);
Xc=Center(1);
Yc=Center(2);
rMax=sqrt((Mr/2)^2 + (Nr/2)^2);
x=[0:1:Mr-1]-Xc+1;
y=[0:1:Nr-1]-Yc+1;
[X,Y]=meshgrid(x,y);
[TH,R] = cart2pol(X,Y);
% Assembling 1-D signal
sig=single([]);
ii=1;
dr=floor(rMax)/ch;
V=dr:dr:floor(rMax);
for v=V
indxs=find((v-dr)<=R & R<v);**
sig(ii)=mean(imR(indxs));
Nvals(ii)=length(indxs);
ii=ii+1;
end %for v
R_axis=V-dr/2;
end % of function
Following from the comments here's an example of something I might try. Let's work with a 9x9 example. Suppose you have the following annulus.
A =
0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 0 0
0 1 1 1 0 1 1 1 0
0 1 1 0 0 0 1 1 0
0 1 0 0 0 0 0 1 0
0 1 1 0 0 0 1 1 0
0 1 1 1 0 1 1 1 0
0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0
Then the indices of your sort of mask are, lets say [k n]
>> [k n]
ans =
3 2
4 2
5 2
6 2
7 2
2 3
3 3
4 3
6 3
7 3
8 3
2 4
3 4
7 4
8 4
2 5
8 5
2 6
3 6
7 6
8 6
2 7
3 7
4 7
6 7
7 7
8 7
3 8
4 8
5 8
6 8
7 8
Now have a 9x9 matrix of zeroes on hand called B, we can shift the whole thing over to the left by one pixel as follows using the formula (i+9*(j-1)) to convert double index to a single index.
>> B=zeros(9,9);
>> B((k)+9*(n-2))=1
B =
0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 0 0 0
1 1 1 0 1 1 1 0 0
1 1 0 0 0 1 1 0 0
1 0 0 0 0 0 1 0 0
1 1 0 0 0 1 1 0 0
1 1 1 0 1 1 1 0 0
0 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0
Or move down and to the right as follows
>> B=zeros(9,9);
>> B((k+1)+9*(n-0))=1
B =
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 0
0 0 1 1 1 0 1 1 1
0 0 1 1 0 0 0 1 1
0 0 1 0 0 0 0 0 1
0 0 1 1 0 0 0 1 1
0 0 1 1 1 0 1 1 1
0 0 0 1 1 1 1 1 0
As long as it doesn't go out of bounds you should be able to shift a single annular mask around with a simple addition to put the center at the image center.

How to get the unique slices of a matrix?

In matlab, if you have a matrix A you can find the matrix B containing all of the unique rows of A as follows:
B = unique(A,'rows');
What I have is a 3d matrix, with rows and columns as the first two dimensions, and one additional dimension ('slices').
How can I get the 3d matrix containing all the unique slices in a matrix A? Here's an example of the kind of functionality I want:
>> A % print out A
A(:,:,1) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A(:,:,2) =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
A(:,:,3) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A(:,:,4) =
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
>> unique(A,'slices'); % get unique slices
A(:,:,1) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A(:,:,2) =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
A(:,:,3) =
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
I would begin by reshaping A so each slice becomes a row (with the reshape command). Then use unique(A, 'rows'). Finally, reshape the unique rows back to the same shape the slices.
For example:
% transforming so each row is a slice in row form
reshaped_A = reshape(A, [], size(A, 3))';
% getting unique rows
unique_rows = unique(reshaped_A, 'rows');
% reshaping back
unique_slices = reshape(unique_rows', size(A, 1), size(A, 2), []);
Or all in one line:
reshape(unique(reshape(A, [], size(A, 3))', 'rows')', size(A, 1), size(A, 2), [])
I haven't checked this above code so use with caution! But it should give the idea.
EDIT
Here it is working on your data (also fixed little bug in above code):
>> reshaped_A = reshape(A, [], size(A, 3))'
reshaped_A =
Columns 1 through 11
16 5 9 4 2 11 7 14 3 10 6
1 0 0 0 0 1 0 0 0 0 1
16 5 9 4 2 11 7 14 3 10 6
0 0 0 1 0 0 1 0 0 1 0
Columns 12 through 16
15 13 8 12 1
0 0 0 0 1
15 13 8 12 1
0 1 0 0 0
Each of these ^^ rows is one of the original slices
>> unique_rows = unique(reshaped_A, 'rows')
unique_rows =
Columns 1 through 11
0 0 0 1 0 0 1 0 0 1 0
1 0 0 0 0 1 0 0 0 0 1
16 5 9 4 2 11 7 14 3 10 6
Columns 12 through 16
0 1 0 0 0
0 0 0 0 1
15 13 8 12 1
These ^^ are the unique slices, but in the wrong shape.
>> unique_slices = reshape(unique_rows', size(A, 1), size(A, 2), [])
unique_slices(:,:,1) =
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
unique_slices(:,:,2) =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
unique_slices(:,:,3) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A very simple and scalable solution would be:
A = cat(3, [16 2 3 13;5 11 10 8;9 7 6 12;4 14 15 1], [1 0 0 0;0 1 0 0;0 0 1 0;0 0 0 1], [16 2 3 13;5 11 10 8;9 7 6 12;4 14 15 1], [0 0 0 1;0 0 1 0;0 1 0 0;1 0 0 0])
[n,m,p] = size(A);
a = reshape(A,n,[],1);
b = reshape(a(:),n*m,[])';
c = unique(b,'rows', 'stable')'; %If the 'stable' option is supported by your version.
%If the 'stable' option is not supported, but it's still required, use the index vector option, as required.
%i.e.,
%[c,I,J] = unique(b,'rows');
unique_A = reshape(c,n,m,[])
Results:
A(:,:,1) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A(:,:,2) =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
A(:,:,3) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A(:,:,4) =
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
unique_A(:,:,1) =
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
unique_A(:,:,2) =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
unique_A(:,:,3) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
Source: How to find unique pages in a 3d matrix?