1 | function [header_mat, data_mat] = mhdrload_bis(file)
|
---|
2 | %MHDRLOAD Load data from an ASCII file containing multiple text
|
---|
3 | % headers throughout the file.
|
---|
4 | % [header, data] = MHDRLOAD('filename.ext') reads a data file
|
---|
5 | % called 'filename.ext', which contains a text header. There
|
---|
6 | % is no default extension; any extensions must be explicitly
|
---|
7 | % supplied.
|
---|
8 | %
|
---|
9 | % The first output, HEADER, is the header information, returned
|
---|
10 | % as a text array.
|
---|
11 | % The second output, DATA, is the data matrix. This data matrix
|
---|
12 | % has the same dimensions as the data in the file, one row per
|
---|
13 | % line of ASCII data in the file. If the data is not regularly
|
---|
14 | % spaced (i.e., each line of ASCII data does not contain the
|
---|
15 | % same number of points), the data is returned as a column
|
---|
16 | % vector.
|
---|
17 | %
|
---|
18 | % Limitations: No lines of the text header can begin with
|
---|
19 | % a number. The header must come before the data.
|
---|
20 | %
|
---|
21 | % MODIFIED from hdrload.m: Dec 20, 2002 Jeff Daniels, NSWCCD - ARD
|
---|
22 | %
|
---|
23 | % See also LOAD, SAVE, SPCONVERT, FSCANF, FPRINTF, STR2MAT, HDRLOAD.
|
---|
24 | % See also the IOFUN directory.
|
---|
25 | %
|
---|
26 | % EXAMPLE:
|
---|
27 | % If example_data.txt is:
|
---|
28 | % Recorded Data: 12/15/2001
|
---|
29 | % header 1
|
---|
30 | % rows = 2 cols = 2
|
---|
31 | % 12 23
|
---|
32 | % 34 21
|
---|
33 | % header 2
|
---|
34 | % rows = 3 cols = 3
|
---|
35 | % 19 73 13
|
---|
36 | % 33 32 47
|
---|
37 | % 34 12 68
|
---|
38 | %
|
---|
39 | % MHDRLOAD returns:
|
---|
40 | % header(:,:,1) =
|
---|
41 | %
|
---|
42 | % Recorded Data: 12/15/2001
|
---|
43 | % header 1
|
---|
44 | % rows = 2 cols = 2
|
---|
45 | %
|
---|
46 | % header(:,:,2) =
|
---|
47 | %
|
---|
48 | % header 2
|
---|
49 | % rows = 3 cols = 3
|
---|
50 | %
|
---|
51 | % data(:,:,1) =
|
---|
52 | %
|
---|
53 | % 12 23 0
|
---|
54 | % 34 21 0
|
---|
55 | % 0 0 0
|
---|
56 | %
|
---|
57 | % data(:,:,2) =
|
---|
58 | %
|
---|
59 | % 19 73 13
|
---|
60 | % 33 32 47
|
---|
61 | % 34 12 68
|
---|
62 |
|
---|
63 | % check number and type of arguments
|
---|
64 | if nargin < 1
|
---|
65 | error('Function requires one input argument');
|
---|
66 | elseif ~ischar(file)
|
---|
67 | error('Input argument must be a string representing a filename');
|
---|
68 | end
|
---|
69 |
|
---|
70 | % Open the file. If this returns a -1, we did not open the file
|
---|
71 | % successfully.
|
---|
72 | fid = fopen(file);
|
---|
73 | if fid==-1
|
---|
74 | error('File not found or permission denied.');
|
---|
75 | end
|
---|
76 |
|
---|
77 | % Initialize loop variables
|
---|
78 | % We store the number of lines in the header, and the maximum length
|
---|
79 | % of any one line in the header. These are used later in assigning
|
---|
80 | % the 'header' output variable.
|
---|
81 | no_lines = 0;
|
---|
82 | max_line = 0;
|
---|
83 |
|
---|
84 | % We also store the number of columns in the data we read. This way
|
---|
85 | % we can compute the size of the output based on the number of
|
---|
86 | % columns and the total number of data points.
|
---|
87 | ncols = 0;
|
---|
88 |
|
---|
89 | % Finally, we initialize the data to [].
|
---|
90 | data = [];
|
---|
91 | j=1;
|
---|
92 |
|
---|
93 | % Start processing.
|
---|
94 | line = fgetl(fid);
|
---|
95 | if ~ischar(line)
|
---|
96 | disp('Warning: file contains no header and no data')
|
---|
97 | end;
|
---|
98 |
|
---|
99 | while line~=-1,
|
---|
100 | [data, ncols, errmsg, nxtindex] = sscanf(line, '%f');
|
---|
101 | % One slight problem, pointed out by Peter VanderWal: If the first
|
---|
102 | % character of the line is 'e', then this will scan as 0.00e+00.
|
---|
103 | % We can trap this case specifically by using the 'next index'
|
---|
104 | % output: in the case of a stripped 'e' the next index is one,
|
---|
105 | % indicating zero characters read. See the help entry for 'sscanf'
|
---|
106 | % for more information on this output parameter.
|
---|
107 | % We loop through the file one line at a time until we find some
|
---|
108 | % data. After that point we stop checking for header information.
|
---|
109 | % This part of the program takes most of the processing time, because
|
---|
110 | % fgetl is relatively slow (compared to fscanf, which we will use
|
---|
111 | % later).
|
---|
112 | while isempty(data)|(nxtindex==1)
|
---|
113 | no_lines = no_lines+1;
|
---|
114 | max_line = max([max_line, length(line)]);
|
---|
115 | % Create unique variable to hold this line of text information.
|
---|
116 | % Store the last-read line in this variable.
|
---|
117 | eval(['line', num2str(no_lines), '=line;'])
|
---|
118 | line = fgetl(fid);
|
---|
119 | if ~ischar(line)
|
---|
120 | disp('Warning: file contains no data')
|
---|
121 | break
|
---|
122 | end;
|
---|
123 | [data, ncols, errmsg, nxtindex] = sscanf(line, '%f');
|
---|
124 | end % while
|
---|
125 |
|
---|
126 | % Create header output from line information. The number of lines and
|
---|
127 | % the maximum line length are stored explicitly, and each line is
|
---|
128 | % stored in a unique variable using the 'eval' statement within the
|
---|
129 | % loop. Note that, if we knew a priori that the headers were 10 lines
|
---|
130 | % or less, we could use the STR2MAT function and save some work.
|
---|
131 | % First, initialize the header to an array of spaces.
|
---|
132 | header_mat(1:no_lines,1:max_line,j) = setstr(' '*ones(no_lines,max_line));
|
---|
133 | for i = 1:no_lines,
|
---|
134 | if length(eval(['line' num2str(i)])),
|
---|
135 | varname = eval(['line' num2str(i)]);
|
---|
136 | else
|
---|
137 | varname = ['line',num2str(i)];
|
---|
138 | end
|
---|
139 | % Note that we only assign this line variable to a subset of this
|
---|
140 | % row of the header array. We thus ensure that the matrix sizes in
|
---|
141 | % the assignment are equal.
|
---|
142 | %eval(['header(i, 1:length(' varname ')) = ' varname ';']);
|
---|
143 | header_mat(i,1:length(varname),j)=varname;
|
---|
144 | end
|
---|
145 |
|
---|
146 | % Now that we have read in the first line of data, we can skip the
|
---|
147 | % processing that stores header information, and just read in the
|
---|
148 | % rest of the data.
|
---|
149 | data = [data; fscanf(fid, '%f')];
|
---|
150 | % Resize output data, based on the number of columns (as returned
|
---|
151 | % from the sscanf of the first line of data) and the total number of
|
---|
152 | % data elements. Since the data was read in row-wise, and MATLAB
|
---|
153 | % stores data in columnwise format, we have to reverse the size
|
---|
154 | % arguments and then transpose the data. If we read in irregularly
|
---|
155 | % spaced data, then the division we are about to do will not work.
|
---|
156 | % Therefore, we will trap the error with an EVAL call; if the reshape
|
---|
157 | % fails, we will just return the data as is.
|
---|
158 | eval('data_mat(1:length(data)/ncols,1:ncols,j) = reshape(data,ncols, length(data)/ncols)'';', '')
|
---|
159 | line = fgetl(fid);
|
---|
160 | j=j+1;
|
---|
161 | no_lines = 0;
|
---|
162 | end
|
---|
163 |
|
---|
164 | fclose(fid);
|
---|
165 | % And we're done!
|
---|
166 |
|
---|
167 | end |
---|