How to skip lines in a txt file using Matlab? - matlab

I am working on a GUI program that involves uploading a txt file. The first 80 lines of the file contains information I do not need, it is a mix of numeric and text data. For example here is a few lines of the data I do not want to use;
vertical_line_flag;0
vertical_line_ratio;0
laser_wavelength;0
laser_powerlevel;0
overlay_js;0
Relative Intensity Correction Flag;0
Pixel;Wavelength;Wavenumber;Raman Shift;Dark;Reference;Raw data #1;Dark Subtracted #1;%TR #1;Absorbance #1;Irradiance (lumen) #1;
0;165.98;60247.73;-60247.73;0.0000;65535.0000;1125.0000;31.0000;0.0000;0.0000;0.0000;
1;166.38;60103.59;-60103.59;0.0000;65535.0000;549.0000;-545.0000;0.0000;0.0000;0.0000;
2;166.78;59960.14;-59960.14;0.0000;65535.0000;0.0000;-1094.0000;0.0000;0.0000;0.0000;
3;167.18;59817.38;-59817.38;0.0000;65535.0000;998.0000;-96.0000;0.0000;0.0000;0.0000;
4;167.57;59675.31;-59675.31;0.0000;65535.0000;1046.0000;-48.0000;0.0000;0.0000;0.0000;
5;167.97;59533.90;-59533.90;0.0000;65535.0000;1020.0000;-74.0000;0.0000;0.0000;0.0000;
6;168.37;59393.17;-59393.17;0.0000;65535.0000;1003.0000;-91.0000;0.0000;0.0000;0.0000;
7;168.77;59253.11;-59253.11;0.0000;65535.0000;1051.0000;-43.0000;0.0000;0.0000;0.0000;
8;169.17;59113.71;-59113.71;0.0000;65535.0000;1024.0000;-70.0000;0.0000;0.0000;0.0000;
9;169.56;58974.97;-58974.97;0.0000;65535.0000;1045.0000;-49.0000;0.0000;0.0000;0.0000;
10;169.96;58836.88;-58836.88;0.0000;65535.0000;1091.0000;-3.0000;0.0000;0.0000;0.0000;
11;170.36;58699.44;-58699.44;0.0000;65535.0000;1064.0000;-30.0000;0.0000;0.0000;0.0000;
12;170.76;58562.65;-58562.65;0.0000;65535.0000;1019.0000;-75.0000;0.0000;0.0000;0.0000;
The point where the numbers begin, as in the line after (lumen) #1; is the data that I want to use in my program.
I have tried using this code to skip the first 80 lines of the file
[FileName,PathName]= uigetfile('*.txt*','Files to Study');
file =fullfile(PathName,FileName);
fid = fopen(file);
A = textscan(fid,'%f' ,'HeaderLines',80);
but this results in A= [0x1 double]
Any suggestions on how to resolve this would be greatly appreciated.

The problem with your current use of textscan is that ; is not a default delimiter. So this will work:
fid = fopen(file);
A = textscan(fid,'%f' ,'HeaderLines',80,'Delimiter',';');
But if the rest of the file is 100% numerical then you can just use dlmread and set row and column values at which to start reading (note: unlike pretty much everything else in MATLAB, these start at zero).
For your test data:
A = dlmread('test.txt',';',7,0);
For the real data with 80 lines of header:
A = dlmread(filename,';',80,0);

Try this code:
A = [];
tline = fgets(fid);
while ischar(tline)
parts = textscan(tline, '%d;');
if numel(parts{1}) > 0
A = [ A ; parts{:}' ];
end
tline = fgets(fid);
end
fclose(fid);
Basically, it looks for lines with numerical values in the text file. For each one of these lines, scan the values and attach them as rows in matrix A.
The output I get with your text is:
A =
0 166 60248 -60248 0 65535 1125 31 0 0 0
1 166 60104 -60104 0 65535 549 -545 0 0 0
2 167 59960 -59960 0 65535 0 -1094 0 0 0
3 167 59817 -59817 0 65535 998 -96 0 0 0
4 168 59675 -59675 0 65535 1046 -48 0 0 0
5 168 59534 -59534 0 65535 1020 -74 0 0 0
...
Hope that it helps, Regards.

Related

Search and replace for a specific string in multiple lines of a text file in matlab

I have a text file in which I want to search for the number 255 in every line to replace it with the number 0. It is to be noted that the number are written in the text file as strings. I want to skip the first 13 lines, since there is text in these 13 lines.
A part of the text file is shown below:
F2G_DIM 3
F2G_VERSION 1
F2G_LOCATION 0 0 0.5
F2G_ROTATION 0
F2G_ORIGIN 0 0 0
F2G_NB_NODES 300 150 50
F2G_LAGS 10 10 1
F2G_ORDER +Y +X +Z
F2G_NB_VARIABLES 1
F2G_VARIABLE_1 Facies
F2G_UNDEFINED_1 255
F2G_VALUES
2
1
2
255
2
255
2
2
5
9
How can I solve this problem?
For your first questions you can use logical indexing to find and substitute the 255
pattern = 255; %Number to find
array = randi(10,10,1); %Some array
array([4,8,9]) = 255;
array(array==pattern) = 0; %Substitute values
For the second question, you can use dlmread to load in the data. It allows you to specify a header to ignore.
data = dlmread('file.csv',' ',13,0);
where 13 is the number of rows to ignore and 0 is the number of columns to ignore.
In total you have something like:
pattern = 255; %Pattern
data = dlmread('file.csv',' ',13,0); %Load
data(data==pattern) = 0; %Substitute values

How to rediagonalize the diagonal of a matrix in MATLAB?

I have a 5x5 matrix, V1, with values and a classification in both the first row and first column. If you wanted to, you could think of sectors in an economy that have a classification. The first two sectors have a 3-digit classification, the last two have a 4-digit classification.
V1 =
0 101 111 1234 1111
101 4 0 7 0
111 5 8 0 0
1234 6 0 6 2
1111 0 0 4 9
Now, I want to rediagonalize all columns that have a 4-digit code using MATLAB. That means in four-digit columns the values should be summed up over the whole column and shifted to the diagonal. In particular, the code should perform the following steps:
If the classification code has four digits AND the classification code is equal in both the first row AND the first column, then sum up the whole column (excl. the first value of the column, which is the classification code itself)
Elseif the classification code has three digits in the column, then leave the value as is
Else assign a zero.
The resulting matrix should look like this:
V1 =
0 101 111 1234 1111
101 4 0 0 0
111 5 8 0 0
1234 6 0 17 0
1111 0 0 0 11
I have tried the following code, but it didn't work:
[vrow vcol] = size(V1)
for c = 2:vcol;
for r = 2:vrow;
if all([ V1(1,c) == V1(r,1), numel(num2str(V1(1,c))) > 3, numel(num2str(V1(r,1))) > 3 ]) ;
V1(r,c) = sum(V1(2:end,c)) ;
elseif numel(num2str(V1(1,c))) == 3;
V1(r,c) = V1(r,c);
else
V1(r,c) = 0;
end
end
end
With the above code, I got the following result, which is sort of close to the desired result, only the column summations do not work yet:
V1 =
0 101 111 1234 1111
101 4 0 0 0
111 5 8 0 0
1234 6 0 10 0
1111 0 0 0 9
Thank you for any hints!
Since you're changing elements of V1 as the code executes, but also relying on values in V1 to get your answer (when you sum columns), you'll have errors if you set a value to 0 before it's needed in a sum. Below, I've fixed that issue by initializing a second matrix V2 as your output. I've also gone ahead and removed a few unneeded lines, as explained in the comments
[vrow vcol] = size(V1);
V2 = zeros(vrow, vcol);
for c = 2:vcol;
for r = 2:vrow;
if all([ V1(1,c) == V1(r,1), numel(num2str(V1(1,c))) > 3]) ; %Third statement was redundant
V2(r,c) = sum(V1(2:end,c)) ;
elseif numel(num2str(V1(1,c))) == 3;
V2(r,c) = V1(r,c);
end %We intialized whole thing to 0, so we don't need to set elements to 0
end
end

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)

Writing on an existing mixed numeric and string text file with different field

I have a mixed numeric and string text file with different fields divided by [ ]. Some of its content is like:
[JUNCTIONS]
;ID Elev Demand Pattern
2 0 0 ;
9 0 0 ;
5 0 11 ;
6 0 20 ;
[RESERVOIRS]
;ID Head Pattern
1 5 ;
4 50 ;
[PIPES]
;ID Node1 Node2 Length Diameter Roughness MinorLoss Status
66 2 9 1000 250 100 0 Open ;
2 9 4 1000 150 100 0 Open ;
3 9 5 1000 150 100 0 Open ;
4 2 6 1000 150 100 0 Open ;
I want to overwrite numeric variables below the columns "Demand" and "Roughness" from MATLAB.
Would you please help me. I read about the performance of import and export commands of Matlab, but I couldn't find the solution.
Here is a small script that will read all your data into a cell array. Each cell is a column of data. As Divakar said, make your data is vertically aligned or textscan will stop when one of the lines is not the same as the last.
fid = fopen(file,'r');
while 1
line=fgetl(fid);
if ~strcmp(line,'')
if ~isempty(strfind(line,'['))
% //Let's check it
start = strfind(line,'[');
split = strfind(line,']');
category = line(start+1:split-1);
if strcmp(category,'PIPES')
break;
end
end
end
end
% //skip the header line
line=fgetl(fid);
% //So now we're on the right line, let's read in the table.
data = textscan(fid,'%d %d %d %d %d %d %d %s');
fclose(fid);

Grouping strings by matching substring

After running a SPICE simulation I get an .a2d file which I am parsing with Matlab. After parsing the file I get a cell array with the names of the variables
Ex: vars = {'s0';'s1';'s2';'a0';'a1'}
and a data matrix with the signals transitions, where each row represents the data of each signal and columns represent time. All the data is binary, i.e., it's only 0 or 1.
What I want to do is to create an algorithm that detects "words" based on the names stored in vars. For example, s0, s1, and s2 form a 3-bit word 's'; a0 and a1 a 2-bit word 'a'.
Finally, what I need is to break the data matrix into one array for each word (converting from binary to decimal).
I am doing that by hand, but I want to know if there is any way to do it by a script.
Here's a possible solution, putting the final values into the fields of a struct. I've used a regexp to extract the variable names and shifts as you didn't say how long they might be.
% fake data
vars = {'sums4', 'sums2', 'sums1', 'a0', 'a5'};
data(1,:) = logical([0 0 1 0 0 0 1]);
data(2,:) = logical([0 1 1 1 1 0 0]);
data(3,:) = logical([1 0 1 1 0 0 1]);
data(4,:) = logical([0 0 1 0 1 1 1]);
data(5,:) = logical([0 1 1 1 0 0 0]);
output = struct();
for i = 1:length(vars)
matches = regexp(vars{i}, '(\D+)(\d+)', 'tokens');
var = matches{1}{1};
shiftsize = str2num(matches{1}{2});
% initialise if not already present
if (~isfield(output, var))
output.(var) = zeros(1, size(data, 2));
end
% add apropriate shifted value to current values
output.(var) = output.(var) + (bitshift(1, shiftsize) * data(i, :));
end
output ends up with fields named after the string parts of vars
output =
sums: [2 4 22 6 4 0 18]
a: [0 32 33 32 1 1 1]