Reading sections of data from repeating text file

9 views (last 30 days)
I have a text file which produces an output of data at different time stamps. Data is linked to cartesian co-ordinates from an FE model. I want to retrieve values of mass flow from another column between certain co-ordinates such as when x and z = 107.6 and 82.0 respectively and the interim values up to and including when x and z = 100.0 and 82.0 respectively. I use find get the indices, is there a better way? Text file of similar style data attached.
I've never used regexp but am interested in finding the most elegant solution.
  3 Comments
dpb
dpb on 4 Aug 2014
Yeah, you gots it this time... :)
Anyway, looks to me like simplest way would be to read each section and then just to a logical selection of the region(s) of interest. I tend to write the logic for such things as when x ... = 107.6 ... up to and including when x ... = 100.0... as
ix=iswithin(x,100,107.6);
x=x(ix,:);
where iswithin is
function flg=iswithin(x,lo,hi)
% returns T for values within range of input
% SYNTAX:
% [log] = iswithin(x,lo,hi)
% returns T for x between lo and hi values, inclusive
flg= (x>=lo) & (x<=hi);
It's only "syntactic sugar" but removing the complexity of the test logic to a lower and sometimes the addition of the intermediate logical array can maek the higher level code much simpler to write and debug. In your case you'd be looking at combining such logicals to meet the double criteria I demonstrated with only one variable.

Sign in to comment.

Answers (1)

Nade Sritanyaratana
Nade Sritanyaratana on 4 Aug 2014
I think you want to read in this large text file, and for each time point, access the table of data, and then find indices to access rows that fit a certain criteria. Is this correct?
One possible approach is to obtain the matrix of values at each time point by using the high-level function textscan. At each call of textscan, MATLAB will continue reading where it last left off, so subsequent calls to textscan will eventually bring MATLAB to the end of the text file.
This matrix of values can then be processed with the criteria you specified, and at this point, dpb's iswithin function can really come in handy.
The strategy here is to use textscan, keeping note of the time point at each table. When a certain time is reached, stop reading further.
Here is some example code:
% Open the file, and continuously read until at the end of the file
fid = fopen('text.txt');
% Initialize
t = 0;
% Continuously read file until you get to the last specified time
while t<147570
t = textscan(fid,'Time:%f',2); t = t{1};
A = cell2mat(textscan(fid,'%f%f%f%f%f%f%f%f%f%f',281,'HeaderLines',3));
% xrange and zrange are logical indices that can be used to access
% a matrix.
xrange = (A(:,3)>=100)&(A(:,3)<=107.6);
zrange = (A(:,4)>=82.0)&(A(:,4)<=82.0);
mysubarr = A(xrange&zrange,:);
% Do any desired data processing on mysubarr
v_sub = mysubarr(:,7); % Grab v values that fall within xrange and zrange
end
fclose(fid);
As I mentioned above, dpb's solution is great for creating logical indices within a range, and can also be applied here when defining xrange and yrange. For example, the following is an alternative way to define xrange and yrange:
% xrange and zrange are logical indices that can be used to access a matrix.
xrange = iswithin(A(:,3),100,107.6);
zrange = iswithin(A(:,4),82,82);
When defining xrange and zrange like this, make sure that the iswithin custom function is included in MATLAB's path.
Looking closer at your text file, I am wondering if you want the rows where x is between 100 and 107.6, and z is greater than or equal to 82.0 only within the "humps" of z. If so, I would redefine zrange using medfilt1, which can remove small regions of 1's:
% xrange and zrange are logical indices that can be used to access a matrix.
xrange = (A(:,3)>=100)&(A(:,3)<=107.6);
zrange = (A(:,4)>=82.0);
zrange = logical(medfilt1(zrange*1,5));

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!