-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathaedes_readjcamp.m
242 lines (195 loc) · 5.36 KB
/
aedes_readjcamp.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
function jdx = aedes_readjcamp(filename)
% AEDES_READJCAMP - Read JCAMP DX format files (Bruker parameter files)
%
%
% Synopsis:
% jdx=aedes_readjcamp(filename)
%
% Description:
% The function reads the JCAMP DX files and returns a
% structure with parameters as structure fields. The input
% argument is a string containing the full path to the file.
%
% Examples:
% jdx=aedes_readjcamp('C:\path\to\jcamp_dx_file')
%
% See also:
% AEDES_READBRUKER, AEDES_DATA_READ, AEDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Tuomainen, TV 2019: ADDED try-catch to line 175 onward: aedes could not reshape
%the file from bruker PV 6.01 ZTE/UTE(3D) files. This "fix" does not really
%do much else, as all the info is obtained from acqp, method etc. files so
%the reco file may not be that necessary.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%addd change to
jdx = [];
% Prompt for a file if not given as an input argument
if nargin == 0
[fn,fp] = uigetfile({'*.*','All Files (*.*)'},'Open a JCAMP DX file');
if isequal(fn,0)
return
end
filename = [fp,fn];
elseif nargin > 1
error('Too many input arguments.');
end
% Open the file for reading
fid = fopen(filename,'r');
if fid < 0
error('Could not open file "%s" for reading.',filename);
end
% Check that the file is a JCAMP DX file
str = fread(fid,20,'char=>char');
if isempty(regexp(str.','^\s*##TITLE'))
fclose(fid);
error('File "%s" is not a valid JCAMP DX file.',filename)
end
fseek(fid,0,-1); % Rewind file
C = fread(fid,inf,'char');
fclose(fid);
% Remove carriage returns
C(C==13)=[];
% Convert to string
C = char(C.');
% Remove comment lines
C = regexprep(C,'\$\$([^\n]*)\n','');
% Remove unnecessary line breaks
f = @l_RemoveLineBreaks;
C=regexprep(C,'^(\s*[^#].*?)(?=\n\s*#)','${f($1)}','lineanchors');
C=regexprep(C,'(\([^\)]+?)\n(.*?\))','${f([$1,$2])}','lineanchors');
CC = regexp(C,'\s*##','split');
CC(1)=[];
% Parse the file line-by-line
for ii=1:length(CC)
str = CC{ii};
if strncmp(str,'END=',4)
continue
end
% The commented regexp sometimes fails with long strings...
%param = regexp(str,'^(.*)=','tokens','once');
ind = find(str==61); % Find '=' chars...
if isempty(ind)
param='';
else
param=str(1:ind(1)-1);
end
%param = strrep(param{1},'$','');
param = strrep(param,'$','');
param = l_CheckParameter(param);
if any(str==sprintf('\n'))
% Get size
sz = regexp(str,'=\s*\((.*?)\)\s*\n','tokens','once');
sz = str2num(['[',sz{1},']']);
% Parse value
value = regexp(str,'\n(.*)$','tokens','once');
value = value{1};
value = l_CheckValue(value,sz);
else
value = regexp(str,'=\s*(.*)','tokens','once');
value = value{1};
value = l_CheckValue(value);
end
% Add to structure
jdx.(param) = value;
end
% ==========================
% - Subfunctions -
% ==========================
% - Remove linebreaks
function out = l_RemoveLineBreaks(str)
out = strrep(str,sprintf('\n'),'');
% - Check parameter value --------------------------
function out = l_CheckValue(val,sz)
if nargin == 1
sz = 0;
end
% Remove insignificant whitespace
val = strtrim(val);
if isempty(val)
out = val;
return
end
% Handle strings and string lists
if val(1) == '<' && val(end) == '>'
val(val=='<')='''';
val(val=='>')='''';
out = eval(['{',val,'}']);
if length(out) == 1
out = out{1};
end
return
end
% Handle cell matrices
if val(1) == '(' && val(end) == ')'
nRows = length(find(val==')'));
% Nested tables are not supported. This is a workaround for nested tables
% and everything is read in a single lined table...
if nRows ~= sz && sz>0
nRows=sz;
end
val(1) = '';
val(end) = '';
val(val=='(')='';
val(val==')')=',';
val(val=='<')='';
val(val=='>')='';
% Split using the commas
val_split = regexp(val,',\s+','split');
val_out = cell(size(val_split));
% Try to convert to numbers
for ii = 1:length(val_split)
num = str2double(val_split{ii});
if isnan(num)
val_out{ii} = val_split{ii};
else
val_out{ii} = num;
end
end
try %TT2019 fix for reco files, as there might be some multiline tables (or other stuff) that mess-up the file-read.
out = reshape(val_out,[],nRows).';
catch
%caused an error, not divisible
out = ''; %make it just empty, does nothing?
end
return
end
% Check if the string contains only numbers before tryin to convert to a
% number. str2num uses eval command and if the string matches to a
% function name strange things can happen...
tmp2 = regexp(val,'[^\d\.\seE-+]');
if ~isempty(tmp2)
out = val;
return
end
% Convert value to numeric if possible
tmp = str2num(val);
if ~isempty(tmp) && isreal(tmp)
if length(sz)>1
tmp = reshape(tmp,sz(2),sz(1),[]);
tmp = permute(tmp,[2 1 3]);
end
out = tmp;
return
end
out = val;
% - Check parameter strings -------------------------
function out = l_CheckParameter(param)
alphabets = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
numbers = '1234567890';
% Remove insignificant whitespace
param = strtrim(param);
if isempty(param)
out = 'EMPTY_PARAM';
return
end
% Check parameter starts with a valid structure field character
if ~any(param(1)==alphabets)
param = ['PAR_',param];
end
% Check that the parameter string does not contain any illegal characters
% (for Matlab structure fields)
ind = ~ismember(param,[alphabets,numbers,'_']);
if any(ind)
param(ind) = '_';
end
out = param;