Converting hex string (delimited with colons) to decimal array: Matlab/Octave - matlab

I am extracting some data form a file, including strings like:
n ={[1,1] = 0:7:80:bc:eb:64
[2,1] = 0:7:80:bc:eb:69
[3,1] = 0:7:80:bc:eb:69
[4,1] = 0:7:80:bc:eb:69
}
I need to change the '0' to '00', and the '7' to '07'. Then use the function hex2dec to convert it into decimal numbers.
I'm using the following code:
r=strrep(0:7:80:bc:eb:69 , ':', '');
m= hex2dec(r)
Maybe there is a better way to do it?

You can just split each string on : using strsplit. That gives a cell array of strings (char vectors) that you can directly pass to hex2dec; no need for zero-padding:
n = {'0:7:80:bc:eb:64';
'0:7:80:bc:eb:69';
'0:7:80:bc:eb:69';
'0:7:80:bc:eb:69'}; % data: cell array of strings
k = 1; % select one cell
t = strsplit(n{k}, ':');
result = hex2dec(t);
This gives
t =
'0' '7' '80' 'bc' 'eb' '64'
result =
0
7
128
188
235
100
To get the numbers from all strings as a matrix, join the strings of the cell array using strjoin, apply the above, and then apply reshape:
n = {'0:7:80:bc:eb:64';
'0:7:80:bc:eb:69';
'0:7:80:bc:eb:69';
'0:7:80:bc:eb:69'}; % data: cell array of strings
nj = strjoin(n, ':');
t = strsplit(nj, ':');
result = hex2dec(t);
result = reshape(result, [], numel(n)).';
This gives
result =
0 7 128 188 235 100
0 7 128 188 235 105
0 7 128 188 235 105
0 7 128 188 235 105

strsplit and hex2dec work fine as the above answer suggested. I am providing a simpler and faster solution by sscanf:
n = {'0:7:80:bc:eb:64';
'0:7:80:bc:eb:69';
'0:7:80:bc:eb:69';
'0:7:80:bc:eb:69'}; % data: cell array of strings
t = sscanf(n{1}, '%x:')'
t =
0 7 128 188 235 100

Related

MATLAB write string and then table to file

I need to write a string and a table to one text file. The string contains a description of the data in the table, but is not the headers for the table. I am using R2019a which I guess means the "Append" writetable option does not work? Please see my example data below:
% Load data
load cereal.mat;
table = table(Calories, Carbo, Cups, Fat, Fiber, Mfg, Name, Potass);
string = {'This is a string about the cereal table'};
filename = "dummyoutput.sfc";
% How I tried to do this (which does not work!)
fid = fopen(filename, 'w', 'n');
fprintf(fid, '%s', cell2mat(string))
fclose(fid);
writetable(table, filename, 'FileType', 'text', 'WriteVariableNames', 0, 'Delimiter', 'tab', 'WriteMode', 'Append')
I get this error:
Error using writetable (line 155)
Wrong number of arguments.
Does anyone have a suggestion as to how to proceed?
Thanks!
A bit hacky, but here's an idea.
Convert your existing table to a cell array with table2cell.
Prepend a row of cells which consists of your string, followed by empty cells.
Convert the cell array back to a table with cell2table, and write the new table to the file.
load cereal.mat;
table = table(Calories, Carbo, Cups, Fat, Fiber, Mfg, Name, Potass);
s = {'This is a string about the cereal table'};
filename = "dummyoutput.sfc";
new_table = cell2table([[s repmat({''},1,size(table,2)-1)] ; table2cell(table)]);
writetable(new_table,filename,'FileType','text','WriteVariableNames',0,'Delimiter','tab');
>> !head dummyoutput.sfc
This is a string about the cereal table
70 5 0.33 1 10 N 100% Bran 280
120 8 -1 5 2 Q 100% Natural Bran 135
70 7 0.33 1 9 K All-Bran 320
50 8 0.5 0 14 K All-Bran with Extra Fiber 330
110 14 0.75 2 1 R Almond Delight -1
110 10.5 0.75 2 1.5 G Apple Cinnamon Cheerios 70
110 11 1 0 1 K Apple Jacks 30
130 18 0.75 2 2 G Basic 4 100
90 15 0.67 1 4 R Bran Chex 125

how to group elements in matrix in matlab?

For eg. I have [1;1;0;0;1;0;0;0;1;1;1;0] this as column and I want output the group of four elements:
1100
1000
1110
How to do this? I tried it with accumarray() but it is not working.
Assuming your vector only contains the elements 0 and 1 and has n*4 elements:
bvec = [1;1;0;0;1;0;0;0;1;1;1;0];
bvec = char(reshape( bvec, 4, numel(bvec)/4 ) + '0').';
Let's break it down:
reshape( bvec, numel(bvec)/4, 4 );
breaks your column vector (could be row vector as well) into a matrix that has 4 rows (your 4 bit[?] groups), it is a 4*n matrix of type double,
+ '0' adds a numerical value of 48 to represent the ASCII character '0'; this translates all values of 0 to 48 (ASCII '0') and all values of 1 to 49 (ASCII '1')
char( ... ) converts your matrix to a character type matrix.
.' transposes the matrix in the very end to get a n*4 matrix.
Result:
bvec =
1100
1000
1110
how is this?
A = [1;1;0;0;1;0;0;0;1;1;1;0];
B = reshape(A,4,3)'; %//DONT FORGET THE `'` or your results would be wrong...
C = strcat(num2str(B)); %C is a char Array currently
C =
1 1 0 0
1 0 0 0
1 1 1 0
Remove the space:
you can do C(:,2:3) =[];C(:,3:4)=[];C(:,4:5)=[]; to create a 3 x 4 char Array:
C =
1100
1000
1110
but why would you right? So the better way is:
regexprep(cellstr(C),'[^\w'']',''); %//Now a cell Array. It is generally better practice to store strings as Cell Array instead of Char Array.
ans =
'1100'
'1000'
'1110'

Checking the repeated values and then finding mean

I m working on my project, where i have 2 images as Img1 and Img2.
As Img1 is the binary image so i have calculated all decimal values.
For Img2 i have taken the pixel values.
For convenience i have taken 10X10 matrix values from the entire image for the below operation.
[row,col] = size(Img1);
m = zeros(row,col);
w = [1 2 4 8; 16 32 64 128; 256 512 1024 2048; 4096 8192 16384 32768];
for i=2:10
for j=2:10
O = double(Img1(i-1:i+2,j-1:j+2));
m(i,j) = sum(sum(O.* w));
end;
end;
[row,col] = size(Img2);
count = row*col;
outMat = zeros(4,4,count);
l=0;
%m = zeros(row,col);delete
O = zeros(1,256);
for i=2:10
for j=2:10
l=l+1;
outMat(:,:,l) = Img2(i-1:i+2,j-1:j+2);
vec = outMat(3,3,:);
vec = vec(:);
end;
end;
Now, for Img2 , i have collected all pixel values, and need to store 2 col.as below.
Col1 col2 from Img2
from Img1
44128 162
54960 150
58320 119
31200 120
48240 180
54960 160
44128 163
51109 90
44128 56
Here, 44128 is repeated 3 times,now adding all correspong mapping values from col2 i.e.
162,163,56 add them all divide by 3(becos occurance of 44128 is 3 times) and same procedure
to be followed for all values.
44128 (162+163+56)/3
54960 (150+160)/2
58320 (119/1)
31200 (120/1)
48240 (180/1)
51109 (90/1)
Here, I want to create an array N of 1D 1X(size of col) which acts as a counter of Img1 decimal
values,repeated values and store the counter values inside N, and then finding mean by dividing corresponding counter values of N to the Img2 pixel values as above.
Please help:-( , how can i write the code further.
Here's a way doing it using sparse.
Accumulate sums and counts:
S = sparse(Img1, ones(size(Img1)), Img2);
N = sparse(Img1, ones(size(Img1)), ones(size(Img2)));
Determine which values actually occur:
ind = find(N)
Extract sums and counts for those values:
S = full(S(ind))
N = full(N(ind))
Compute corresponding means
M = S ./ N
For your example numbers, this gives
ind =
31200
44128
48240
51109
54960
58320
S =
120
381
180
90
310
119
N =
1
3
1
1
2
1
M =
120
127
180
90
155
119
Try this:
totals = sparse(1, Img1, Img2 );
denominators = sparse( 1, Img1, 1);
img1vals = find(totals);
averages = nonzeros(totals) ./ nonzeros(denominators);
[img1vals(:) averages(:)]

Matlab: Find a string in a text file

I've searched around, bud didn't find a proper solution. So I ask it again.
There many lines in the .txt file. Looks Like this:
PRINT CONTENTS OF SUPERELEMENT yg_bde
PRINT OPTION = 3
HEADER =
8 55 2 12 6
13 0 13 11 0
1 1 0 0 1
0 0 1 78 14014
0 1584 166 103 yg_b
de 1561 0
922 931 1105 1121 1144
1158 1323 1503 0 989
1047 110005225 0 0 3
0 0
419 0 0 0 0
0 0 0 0
HEADER SUMMARY:
NUMBER OF ROWS = 55
NUMBER OF MATRICES = 2
NUMBER OF EDGE PLOT LINES = 12
NUMBER OF DEGREES OF FREEDOM PER NODE = 6
NUMBER OF DEGREE OF FREEDOM INDICES = 13
NUMBER OF NODES = 11
NUMBER OF LOAD VECTORS = 1
NUMBER OF TRANSFORMATIONS = 0
BASE FILE NAME= yg_bde
I need to locate the NUMBER OF ROWS = 55 and get the row number.
I think what need to do is
1. find and locate the Number of ROWS
2. Turn this line into number, so I can get the 55 number
I tried strfind(file ,string), but it can't return the line number, just the index when the file is in one line.
So, How can I Locate the NUMBER OF ROWS?
UPDATE:
whos data
Name Size Bytes Class Attributes
data 1x1 3094 struct
Approach #1
importdata based approach -
%// Import text data as a cell array with each cell holding each row of text data
data = importdata(inputfile,'\n') %// Edit inputfile to the path of your text file
%// Find the row(s) that holds the string 'NUMBER OF ROWS'
row_idx = find(~cellfun('isempty',strfind(data,'NUMBER OF ROWS')))
%// Find the number(s) in that/those row(s)
num = arrayfun(#(x) regexp(data{x}, '\d+', 'match'),row_idx)
Output I got -
row_idx =
19
num =
'55'
Now, num is a cell array. If you would like to have a numeric array, wrap it with str2double -
num_array = str2double(num)
Note: This also works if you have multiple lines with the string 'NUMBER OF ROWS'.
Approach #2
Alternative fgetl based approach that works by reading the text file line-by-line -
fid = fopen(inputfile); %// Edit inputfile to the path of your text file
tline = fgetl(fid);
num = [];
while ischar(tline)
if ~isempty(strfind(tline,'NUMBER OF ROWS'))
num = [num regexp(tline, '\d+', 'match')]; %#ok<AGROW>
end
tline = fgetl(fid);
end
fclose(fid);
num_array = str2double(num)

Matlat function to convert cell array to text file in specific format

After running an algorithm, I got the output in cell array X,
>> X
X =
[5x1 double]
[5x1 double]
>> celldisp(X);
X{1} =
1
2
3
4
5
X{2} =
11
21
31
41
51
61
71
81
Please note that the dimension of the output is different. X{1} has length 5, while X{2} has length 8.
Now, I want to write this output of celldisp(X) to a txt file in the following format:
output.txt
1 2 3 4 5
11 21 31 41 51 61 71 81
How, can I do this? Is there a predefined function to achieve this goal OR do I need to write a custom defined function. Can someone help me with this problem ?
Simply do
dlmwrite('output.txt',horzcat(X{:})','delimiter',' ');
For the updated question, where the length of the arrays in the cell elements is not the same, I suggest you use a loop:
fid = fopen('output.txt', 'w');
for idx = 1:numel(X)
fprintf(fid,[repmat('%d ', 1, numel(X{idx})) '\n'], X{idx});
end
fclose(fid);
Yet another edit, this time to make it a function
function printCellArray(filename, cellarray)
fid = fopen(filename, 'w');
for idx = 1:numel(cellarray)
fprintf(fid,[repmat('%d ', 1, numel(cellarray{idx})) '\n'], cellarray{idx});
end
fclose(fid);
end