Matlab: delete complete line in txt-file if there is a non-ascii-character - matlab

I'm currently writing a Matlab code to plot measurement data. Unfortunately there is a hardware problem with serial communication and sometimes i receive just gibberish. My code works only for defined data, so this gibberish has to be removed. I want something like this pseudo code:
for eachLine
if currentLineContainsNonASCII
delete completeLine
end if
end for
the data is read like this
rawdataInputFilename = 'measurementData.txt';
fileID = fopen(rawdataInputFilename);
% load data as string
DataCell = textscan(fileID,'%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s','HeaderLines', 1);
I was thinking about first creating a new 'clean' file with only ASCII chars and then reading that file with my actual plotting code.
Where I stuck is how to identify a non ASCII and then deleting the whole line, not only overwriting that single char.
Some example data, 1. and 3. line are 'clean' and can be handled with the current code. Second Line has non ASCIIs in it and therefore kills my code. Whitespace characters are windows linefeed, tab and space.
61 380 Module03 Slot02 27.01.2015 13:47:13 450 3587 1175 84 101.83 22.30 5.20 1 1
62 386 Module03 Slot03 27.01.2015 13:47:18 450ÆădzШШ 106.83 22.30 25.20 1 1
63 391 Module03 Slot04 27.01.2015 13:47:24 ERROR dgsf 5643332 103.26 22.40 25.20 1 1

You can just check if the received character is in the range [32, 127], otherwise skip it.
The following function will tell you if there is any non-printable character in a given string:
function R = has_non_printable_characters(str)
% Remove non-printable characters
str2 = str(31<str & str<127);
% check if length of resulting string is the same than input string
R = (lenght(str) > length(str2))
end;
If instead of just skipping the entire string you want to remove non-printable characters keeping the printable ones, modify the function and return str2. (And change the function name so it matches the new behaviour)

There are several ways to do it.
Save that to a text file named data.txt:
bla Header bla
61 380 Module03 Slot02 27.01.2015 13:47:13 450 3587 1175 84 101.83 22.30 5.20 1 1
62 386 Module03 Slot03 27.01.2015 13:47:18 450ÆădzШШ 106.83 22.30 25.20 1 1
63 391 Module03 Slot04 27.01.2015 13:47:24 ERROR dgsf 5643332 103.26 22.40 25.20 1 1
Method 1 (using textscan and cellfun):
Removing the non-ASCII line completely:
fileID = fopen('data.txt'); % open file
DataCell = textscan(fileID,'%s','delimiter','','HeaderLines', 1); % read a complete line of text, ignore the first line
fclose(fileID); % close file
DataCell = DataCell{1}; % there is only one string per line
DataCell(cellfun(#(x) any(x>127),DataCell)) = []; % remove line if there is any non-ASCII in it, adjust that to your liking, i.e (x>126 | x<32)
celldisp(DataCell)
DataCell{1} =
61 380 Module03 Slot02 27.01.2015 13:47:13 450 3587 1175 84 101.83 22.30 5.20 1 1
DataCell{2} =
63 391 Module03 Slot04 27.01.2015 13:47:24 ERROR dgsf 5643332 103.26 22.40 25.20 1 1
You could now loop over the cell array or, if you like, start all over again with the updated text (f.e. as input to textscan). To do that join the cells together to one big chunk of text:
strjoin(DataCell','\n')
ans =
61 380 Module03 Slot02 27.01.2015 13:47:13 450 3587 1175 84 101.83 22.30 5.20 1 1
63 391 Module03 Slot04 27.01.2015 13:47:24 ERROR dgsf 5643332 103.26 22.40 25.20 1 1
Method 2 (using regexprep):
I'm loading the whole text file at once and replacing any line with an empty string '', which does not contain a given set of characters.
s = fileread('data.txt');
snew = regexprep(s, '.*[^\w\s.:].*\n', '', 'dotexceptnewline')
snew =
61 380 Module03 Slot02 27.01.2015 13:47:13 450 3587 1175 84 101.83 22.30 5.20 1 1
63 391 Module03 Slot04 27.01.2015 13:47:24 ERROR dgsf 5643332 103.26 22.40 25.20 1 1
The [^\w\s.:] bit bascially translates to:
Match any chararcter which is not (the ^ means not):
alphabetic, numeric or underscore (\w)
whitespace (\s)
a dot . or
a colon :
If you want to exclude any other ASCII character, just add it (to within the brackets).

here is the code which creates a new txt-file whitout the lines with non-ASCII
%% read in via GUI
[inputFilename, inputPathname] = uigetfile('*.txt', ...
'Pick a .txt file from which you want to remove lines with non ASCII characters.');
if isequal(inputFilename, 0)
disp('User selected ''Cancel''')
else
disp(['User selected ', fullfile(inputPathname, inputFilename)])
inputFileID = fopen(fullfile(inputPathname, inputFilename)); %open/load file
end
tempCell = (strsplit(inputFilename,'.'));
inputFilenameWOextension = cell2mat(tempCell(1));
fileExtension = cell2mat(tempCell(2));
outputFileID = fopen([inputFilenameWOextension, '_ASCIIonly.', fileExtension], 'w'); %overwrite existing file
% get a single line of text
tline = fgetl(inputFileID);
while tline ~= -1
% get a single line of text
tline = fgetl(inputFileID);
% Remove non-printable characters
tempStr = tline(tline<127); % not really ASCII, but also tab
%tempStr = tline(31<tline & tline<127); % true ASCII
if (length(tempStr) < length(tline));
continue;
else
fprintf(outputFileID, '%s\r\n', tempStr);
end
end
fclose(inputFileID);
fclose(outputFileID);

Related

How to convert alphabets to numerical values with spaces and return it back to alphabets?

Want to convert the alphabet to numerical values and transform it back to alphabets using some mathematical techniques like fast Fourier transform in MATLAB.
Example:
The following is the text saved in "text2figure.txt" file
Hi how r u am fine take care of your health
thank u very much
am 2.0
Reading it in MATLAB:
data=fopen('text2figure.txt','r')
d=fscanf(data,'%s')
temp = fileread( 'text2figure.txt' )
temp = regexprep( temp, ' {6}', ' NaN' )
c=cellstr(temp(:))'
Now I wish to convert cell array with spaces to numerical values/integers:
coding = 'abcdefghijklmnñopqrstuvwxyz .,;'
str = temp %// example text
[~, result] = ismember(str, coding)
y=result
result =
Columns 1 through 18
0 9 28 8 16 24 28 19 28 22 28 1 13 28 6 9 14 5
Columns 19 through 36
28 21 1 11 5 28 3 1 19 5 28 16 6 28 26 16 22 19
Columns 37 through 54
28 8 5 1 12 21 8 28 0 0 21 8 1 14 11 28 22 28
Columns 55 through 71
23 5 19 26 28 13 22 3 8 0 0 1 13 28 0 29 0
Now I wish to convert the numerical values back to alphabets:
Hi how r u am fine take care of your health
thank u very much
am 2.0
How to write a MATLAB code to return the numerical values in the variable result to alphabets?
Most of the code in the question doesn't have any useful effects. These three lines are the ones that lead to result:
str = fileread('test2figure.txt');
coding = 'abcdefghijklmnñopqrstuvwxyz .,;';
[~, result] = ismember(str, coding);
ismember returns, in the second output argument, the indices into coding for each element of str. Thus, result are indices that we can use to index into coding:
out = coding(result);
However, this does not work because some elements of str do not occur in coding, and for those elements ismember returns 0, which is not a valid index. We can replace the zeros with a new character:
coding = ['*',coding];
out = coding(result+1);
Basically, we're shifting each code by one, adding a new code for 1.
One of the characters we're missing here is the newline character. Thus the three lines have become one line. You can add a code for the newline character by adding it to the coding table:
str = fileread('test2figure.txt');
coding = ['abcdefghijklmnñopqrstuvwxyz .,;',char(10)]; % char(10) is the newline character
[~, result] = ismember(str, coding);
coding = ['*',coding];
out = coding(result+1);
All of this is easier to achieve just using the ASCII code table:
str = fileread('test2figure.txt');
result = double(str);
out = char(result);

Concatenation of Matlab strings

I want to make a Matlab function that takes two matrices A and B (of the same size) and combines them in a certain way to give an output that can be used in Latex - table.
I want the first row of the output matrix to consist of the first row of matrix A, with ampersands (&) in between them, and that ends with an double backslash.
The second row should be the first row of B with parentheses around them, and ampersands in between. And so on for the rest of A and B.
If I let A=rand(1,2), I could do this by using [num2str(A(1)), ' & ', num2str(A(2)),' \\'] and so on.
But I want to be able to make a function that does this for any size of the matrix A. I guess I have to make cell structures in some way. But how?
This could be one approach -
%// First off, make the "mixed" matrix of A and B
AB = zeros(size(A,1)*2,size(A,2));
AB(1:2:end) = A;
AB(2:2:end) = B;
%// Convert all numbers of AB to characters with ampersands separating them
AB_amp_backslash = num2str(AB,'%1d & ');
%// Remove the ending ampersands
AB_amp_backslash(:,end-1:end) = [];
%// Append the string ` \\` and make a cell array for the final output
ABcat_char = strcat(AB_amp_backslash,' \\');
ABcat_cell = cellstr(ABcat_char)
Sample run -
A =
183 163 116 50
161 77 107 91
150 124 56 46
B =
161 108 198 4
198 18 14 137
6 161 188 157
ABcat_cell =
'183 & 163 & 116 & 50 \\'
'161 & 108 & 198 & 4 \\'
'161 & 77 & 107 & 91 \\'
'198 & 18 & 14 & 137 \\'
'150 & 124 & 56 & 46 \\'
' 6 & 161 & 188 & 157 \\'
You can use sprintf, it will repeat the format spec as many times as required until all input variables are processed:
%combine both to one matrix
C=nan(size(A).*[2,1]);
C(1:2:end)=A;
C(2:2:end)=B;
%print
sprintf('%f & %f \\\\\n',C.')
The transpose (.') is required to fix the ordering.

Is default '\n' line terminator can be changed?

Is default '\n' Matlab line terminator can be changed? Can I use ',' instead of '\n'? Because the serial port that will be reading it is programmed to terminate when ',' is read.Is it possible?
Any answers are highly appreciated! Thanks in advance!
use eg:
ser = serial('COM1'); % establish connection between Matlab and COM1
set(ser, 'Terminator', 'CR'); % set communication string to end on ASCII 13
and replace 'CR' with ','
See
http://www.swarthmore.edu/NatSci/ceverba1/Class/e5/E5MatlabExamples.html
http://www.mathworks.co.uk/help/matlab/matlab_external/terminator.html
A simple string in matlab is not terminated by \n or \0 since it is a simple array of chars, as seen here:
>> a = string('Hello World')
Warning: string is obsolete and will be discontinued.
Use char instead.
a =
Hello World
>> double(a)
ans =
72 101 108 108 111 32 87 111 114 108 100
to add a \0 to the end simply use:
>> a(end+1)=0;
>> a
a =
Hello World
>> double(a) %the zero is there, but not printable as seen here
ans =
72 101 108 108 111 32 87 111 114 108 100 0

How to arrange pixel address as order under certain condition?

I am currently doing map processing in matlab. Now i solved the maze and get the path of maze. Now i have turning point in map. But this address pixel are not in correct order. So i want to order the incorrect order of pixel address in to correct order.
INCORRECT ORDER:
shape(1).cen=[28;136];
shape(2).cen=[122;136];
shape(3).cen=[344;391];
shape(4).cen=[548;493];
shape(5).cen=[548;191];
shape(6).cen=[344;191];
shape(7).cen=[122;391];
CORRECT ORDR:
map(1).cen=[28;136];
map(2).cen=[122;136];
map(3).cen=[122;391];
map(4).cen=[344;391];
map(5).cen=[344;191];
map(6).cen=[548;191];
map(7).cen=[548;493];
My code is below:-
`map(1).cen=[28;136];
o=0; order=1;xflag=0;yflag=0;
k=length(shape); %indicates the total elements in shape.cen structure
for (j=1:k)
order=order+1; o=o+1;
if (j==1)
x=map(1).cen(1,1);
y=map(1).cen(2,1);
for(i=1:k)
xi=shape(i).cen(1,1);
yi=shape(i).cen(2,1);
if((x==xi)||(y==yi))
if(x==xi)
map(order).cen(1,1)=xi;
map(order).cen(2,1)=yi;
xflag=1;
break;
else
(y==yi)
map(order).cen(1,1)=xi;
map(order).cen(2,1)=yi;
yflag=1;
break;
end
end
end
end
x=map(o).cen(1,1);
y=map(o).cen(2,1);
for(i=1:k)
xi=shape(i).cen(1,1);
yi=shape(i).cen(2,1);
if(xflag==1)
if(y==yi)
map(order).cen(1,1)=xi;
map(order).cen(2,1)=yi;
xflag=0;
yflag=1;
break;
end
end
if (yflag==1)
if(x==xi)
map(order).cen(1,1)=xi;
map(order).cen(2,1)=yi;
xflag=1;
yflag=0;
break;
end
end
end
end
`
[shape.cen]' will give you the following array:
ans =
28 136
122 136
344 391
548 493
548 191
344 191
122 391
Now that it's a regular numerical array, you can use sortrows, like this.
map = sortrows([shape.cen]')
to get:
map =
28 136
122 136
122 391
344 191
344 391
548 191
548 493
If you don't want it as a numerical array, but a struct similar to shape, you can do:
[~, ID] = sortrows([shape.cen]')
map = shape(ID)'

Append data or values to csv file Column wise in matlab

suppose i have a .csv file And it has the values as follows:
A 23 45
B 69 84
C 48 78
D 12 34
so it has two columns. Now what i need to do is to add values staring from the 3rd column with out deleting the values in the 1st and 2nd columns..
i tried z code
fileID = fopen('exp.csv','A');
fprintf(fileID,' %12.4f\n',D);
fclose(fileID);
But the issue is that this is added all in one column like:
23
69
48
12
......
45
84
75
38
How can i do this...??
Use the csvread / csvwrite functions to load in the existing file, append a column, and write the new data.
data = csvread('exp.csv');
toadd = (1:4)';
newdata = [data toadd];
csvwrite('out.csv', newdata);