Newer
Older

Olivier Sauter
committed
function [gdat_data,gdat_params,error_status,varargout] = gdat_imas(shot,data_request,varargin)
%
% function [gdat_data,gdat_params,error_status,varargout] = gdat(shot,data_request,varargin)
%
% Aim: get data from a given machine using full path or keywords.
% data_request are and should be case independent (transformed in lower case in the function and outputs)
%
% If no inputs are provided, return the list of available pre-defined data_request in gdat_data and default parameters gdat_params
%
% IMAS means assume access data from IDS database ala IMAS with run_number, database_user, tokamak_name, data_major_version and using imas_open_env and ids_get calls

Olivier Sauter
committed
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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
% Should be the same on ITER hpc and gateway, to be checked
%
% At first only "ids" request implemented, but keywords like ip etc should relate to specific IDS as for any machine
%
% Inputs:
%
% no inputs: return default parameters in a structure form in gdat_params
% shot: shot number (if empty uses 'idx_imas_open_env' in params from previous call or input param)
% data_request: keyword (like 'ip') or trace name or structure containing all parameters but shot number
% varargin{i},varargin{i+1},i=1:nargin-2: additional optional parameters given in pairs: param_name, param_value
% The optional parameters list might depend on the data_request
% examples of optional parameters:
% 'plot',1 (plot is set by default to 0)
% 'machine','IMAS' (the default machine is the local machine)
%
%
% Outputs:
%
% gdat_data: structure containing the data, the time trace if known and other useful information
% gdat_data.t : time trace
% gdat_data.data: requested data values
% gdat_data.dim : values of the various coordinates related to the dimensions of .data(:,:,...)
% note that one of the dim is the time, replicated in .t for clarity
% gdat_data.dimunits : units of the various dimensions, 'dimensionless' if dimensionless
% gdat_data.error_bar : if provided
% gdat_data.gdat_call : list of parameters provided in the gdat call (so can be reproduced)
% gdat_data.shot: shot number
% gdat_data.machine: machine providing the data
% gdat_data.gdat_request: keyword for gdat if relevant
% gdat_data.data_fullpath: full path to the data node if known and relevant, or relevant expression called if relevant
% gdat_data.gdat_params: copy gdat_params for completeness (gdat_params contains a .help structure detailing each parameter)
% gdat_data.xxx: any other relevant information
%
% gdat_params contains the options relevant for the called data_request. It also contains a help structure for each option
% eg.: param1 in gdat_params.param1 and help in gdat_params.help.param1
%
% Note for liuqe parameter: At this time we have liuqe_fortran (which used to be the default) and liuqe_matlab (which is new and now becomes/is the default)
% We still have liuqe1, 2 and 3 nodes for either of them, so you can choose:
% 'liuqe',1 (2 or 3): to get the default liuqe 1, 2 or 3 (which is now the matlab version)
% 'liuqe',11 (12 or 13): to get liuqe_fortran nodes 1, 2 or 3
% 'liuqe',21 (22 or 23): to get liuqe_matlab nodes 1, 2 or 3 (may be needed if we set the default to liuqe_fortran for old shots)
% 'liuqe',-1 : to get FBTE result
%
% Examples:
% (should add working examples for various machines (provides working shot numbers for each machine...))
%
% to get the list of ids: aa=gdat([],'ids','machine','imas'); aa.gdat_params.sources_available
% to get an empty ids: aa=gdat([],'ids','machine','imas','source','core_profiles'); aa.core_profiles
%
% [a1,a2]=gdat;
% a2.data_request = 'ids'; a2.source='equilibrium'; a2.machine = 'imas';
% a3=gdat(48836,a2); % gives input parameters as a structure, allows to call the same for many shots
% a4=gdat('opt1',123,'opt2',[1 2 3],'shot',48832,'data_request','Ip','opt3','aAdB'); % all in pairs
% a5=gdat(48836,'ids','source','core_profiles'); % standard call for a given IDS core_profiles, use {'',''} for a list of IDSs
% a6=gdat(48836,'ip'); % standard call for a specific keyword
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Comments for local developer:
% gdat is just a "header routine" calling the gdat for the specific machine gdat_`machine`.m which can be called
% directly, thus which should be able to treat the same type of input arguments
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Prepare some variables, etc
varargout{1}=cell(1,1);
error_status=1;
% construct main default parameters structure
gdat_params.data_request = '';
default_machine = 'imas';
gdat_params.machine=default_machine;
gdat_params.doplot = 0;
gdat_params.nverbose = 1;
gdat_params.run = []; % should be defined by user to make sure
gdat_params.occurence = 0; % default/usual value
% special case need to treat here if params given as structure in data_request:
if isstruct(data_request)
gdat_params = data_request;
end
% construct list of keywords from global set of keywords and specific IMAS set
% get data_request names from centralized table
%%% data_request_names = get_data_request_names; % do not use xlsx anymore but scan respective machine_requests_mapping.m files
data_request_names = get_data_request_names_from_gdat_xxx(default_machine);
% add IMAS specific to all:
if ~isempty(data_request_names.imas)
imas_names = fieldnames(data_request_names.imas);
for i=1:length(imas_names)
data_request_names.all.(imas_names{i}) = data_request_names.imas.(imas_names{i});
end
end
data_request_names_all = sort(fieldnames(data_request_names.all));
% construct default output structure
gdat_data.data = [];
gdat_data.units = [];
gdat_data.dim = [];
gdat_data.dimunits = [];
gdat_data.t = [];
gdat_data.x = [];
gdat_data.shot = [];
gdat_data.gdat_request = [];
gdat_data.gdat_params = gdat_params;
gdat_data.data_fullpath = [];
% Treat inputs:
ivarargin_first_char = 3;
data_request_eff = '';
if nargin>=2
if ischar(data_request);
data_request_eff = data_request;
data_request = data_request; % should not lower until see if keyword
elseif isstruct(data_request)
data_request_eff = data_request.data_request;
end
end
gdat_data.gdat_request = data_request_names_all; % so if return early gives list of possible request names
gdat_data.gdat_params.help = imas_help_parameters(fieldnames(gdat_data.gdat_params));
gdat_params = gdat_data.gdat_params;
% no inputs
if nargin==0
% return defaults and list of keywords
return
end
do_mdsopen_mdsclose = 1;
% treat 1st arg
if nargin>=1
if isempty(shot)
% if shot already open, will use idx from gdat_params, otherwise returns
do_mdsopen_mdsclose = 0;
if ~isfield(gdat_data.gdat_params,'idx_imas_open_env')
if ~strcmp(data_request_eff,'ids'); return; end % empty shot return empty ids so valid command
end
elseif isnumeric(shot)
gdat_data.shot = shot;
elseif ischar(shot)
ivarargin_first_char = 1;
else
if gdat_params.nverbose>=1; warning('type of 1st argument unexpected, should be numeric or char'); end
error_status=2;
return
end
if nargin==1
% Only shot number given. If there is a default data_request set it and continue, otherwise return
return
end
end
% 2nd input argument if not part of pairs
if nargin>=2 && ivarargin_first_char~=1
if isempty(data_request)
return
end
% 2nd arg can be a structure with all options except shot_number, or a string for the pathname or keyword, or the start of pairs string/value for the parameters
if isstruct(data_request)
if ~isfield(data_request,'data_request')
if gdat_params.nverbose>=1; warning('expects field data_request in input parameters structure'); end
error_status=3;
return
end
data_request_eff = data_request.data_request;
% some request are case sensitive because mds names can be like \magnetics::ipol[*,"OH_001"]
data_request.data_request = data_request.data_request;
gdat_params = data_request;
else
% since data_request is char check from nb of args if it is data_request or a start of pairs
if mod(nargin-1,2)==0
ivarargin_first_char = 2;
else
ivarargin_first_char = 3;
data_request_eff = data_request;
end
end
end
if ~isstruct(data_request)
gdat_params.data_request = data_request_eff;
end
% if start pairs from shot or data_request, shift varargin
if ivarargin_first_char==1
varargin_eff{1} = shot;
varargin_eff{2} = data_request;
varargin_eff(3:nargin) = varargin(:);
elseif ivarargin_first_char==2
varargin_eff{1} = data_request;
varargin_eff(2:nargin-1) = varargin(:);
else
varargin_eff(1:nargin-2) = varargin(:);
end
% extract parameters from pairs of varargin:
if (nargin>=ivarargin_first_char)
if mod(nargin-ivarargin_first_char+1,2)==0
for i=1:2:nargin-ivarargin_first_char+1
if ischar(varargin_eff{i})
gdat_params.(lower(varargin_eff{i})) = varargin_eff{i+1}; % cannot enforce lower(params value) if filename or else are case sensitive
else
if gdat_params.nverbose>=1; warning(['input argument nb: ' num2str(i) ' is incorrect, expects a character string']); end
error_status=401;
return
end
end
else
if gdat_params.nverbose>=1; warning('number of input arguments incorrect, cannot make pairs of parameters'); end
error_status=402;
return
end
end
% if it is a request_keyword copy it:
if ischar(data_request_eff) || length(data_request_eff)==1
ij=strmatch(lower(data_request_eff),data_request_names_all,'exact');
else
ij=[];
end
if ~isempty(ij);
gdat_data.gdat_request = data_request_names_all{ij};
gdat_params.data_request = gdat_data.gdat_request;
if isfield(data_request_names.all.(data_request_names_all{ij}),'description') && ~isempty(data_request_names.all.(data_request_names_all{ij}).description)
% copy description of keyword
gdat_data.request_description = data_request_names.all.(data_request_names_all{ij}).description;
end
end
% special treatment if shot and data_request given within pairs
if isfield(gdat_params,'shot')
shot = gdat_params.shot; % should use only gdat_params.shot but change shot to make sure
gdat_data.shot = gdat_params.shot;
gdat_params=rmfield(gdat_params,'shot');
end
if ~isfield(gdat_params,'data_request') || isempty(gdat_params.data_request)
% warning('input for ''data_request'' missing from input arguments') % might be correct, asking for list of requests
error_status=5;
return
end
gdat_data.gdat_params = gdat_params; % This means that before here it is gdat_params which should be updated
clear gdat_params; % to make sure one uses gdat_data.gdat_params now
% re-assign main variables to make sure use the one in gdat_data structure
shot = gdat_data.shot;
data_request_eff = gdat_data.gdat_params.data_request;
if ~isfield(gdat_data.gdat_params,'database_user')
gdat_data.gdat_params.database_user = getenv('USER');
if gdat_data.gdat_params.nverbose >= 3; disp('set database_user to username as default since not provided'); end
end
if ~isfield(gdat_data.gdat_params,'tokamak_name')
gdat_data.gdat_params.tokamak_name = gdat_data.gdat_params.machine;
if gdat_data.gdat_params.nverbose >= 3; disp('set tokamak_name to machine as default since not provided'); end
end
if ~isfield(gdat_data.gdat_params,'data_major_version')
gdat_data.gdat_params.data_major_version = '3';
if gdat_data.gdat_params.nverbose >= 3; disp('set data_major_version to ''3'' as default since not provided'); end
end
error_status = 6; % at least reached this level
gdat_params = gdat_data.gdat_params;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Specifications on how to get the data provided in imas_requests_mapping
mapping_for_imas = imas_requests_mapping(data_request_eff,shot);
gdat_data.label = mapping_for_imas.label;
ishot=NaN;
if do_mdsopen_mdsclose
if ~isfield(gdat_data.gdat_params,'run') || isempty(gdat_data.gdat_params.run)
warning('run number not provided, cannot continue')
return
end
try
gdat_data.gdat_params.idx_imas_open_env = imas_open_env('ids', shot, gdat_data.gdat_params.run,gdat_data.gdat_params.database_user, ...
gdat_data.gdat_params.tokamak_name,gdat_data.gdat_params.data_major_version);
disp('')
catch ME
warning('could not imas_open_env with following gdat_data.gdat_params:');
gdat_data.gdat_params
rethrow(ME)
end
if gdat_data.gdat_params.idx_imas_open_env < 0
if gdat_data.gdat_params.nverbose>=1
warning(['idx < 0, shot/run not opened properly with gdat_data.gdat_params:']);
gdat_data.gdat_params
end
return
end
else
if isfield(gdat_data.gdat_params,'idx_imas_open_env')
if gdat_data.gdat_params.idx_imas_open_env < 0
if gdat_data.gdat_params.nverbose>=1
warning(['idx < 0, shot/run not opened properly with gdat_data.gdat_params:']);
gdat_data.gdat_params
end
return
end
else
if ~isempty(shot)
if gdat_data.gdat_params.nverbose>=1
warning(['no idx in gdat_params, cannot open shot with gdat_data.gdat_params:']);
gdat_data.gdat_params
end
return
end
end
end
gdat_params = gdat_data.gdat_params;
% fill again at end to have full case, but here to have present status in case of early return
gdat_data.gdat_params.help = imas_help_parameters(fieldnames(gdat_data.gdat_params));
gdat_data.mapping_for.imas = mapping_for_imas;
gdat_params = gdat_data.gdat_params;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if strcmp(mapping_for_imas.method,'expression')
% method="expression"
% assume expression contains an expression to evaluate and which creates a local structure into variable gdat_tmp
% we copy the structure, to make sure default nodes are defined and to avoid if return is an closed object like tdi
% eval_expr = [mapping_for_imas.expression ';'];
eval([mapping_for_imas.expression ';']);
if isempty(gdat_tmp) || (~isstruct(gdat_tmp) & ~isobject(gdat_tmp))
if (gdat_params.nverbose>=1); warning(['expression does not create a gdat_tmp structure: ' mapping_for_imas.expression]); end
error_status=801;
return
end
tmp_fieldnames = setdiff(fieldnames(gdat_tmp),{'gdat_request','label'}); % could/should also remove label in any case
if sum(strcmp(tmp_fieldnames,'data'))==0 % note: cannot do isfield since gdat_tmp might be an object
if (gdat_params.nverbose>=1); warning(['expression does not return a child name ''data'' for ' data_request_eff]); end
end
for i=1:length(tmp_fieldnames)
gdat_data.(tmp_fieldnames{i}) = gdat_tmp.(tmp_fieldnames{i});
end
% add .t and .x in case only dim is provided
% do not allow shifting of timedim since should be treated in the relevant expression
ijdim=find(strcmp(tmp_fieldnames,'dim')==1);
if ~isempty(ijdim)
nbdims = length(gdat_data.dim);
if mapping_for_imas.timedim==-1;
mapping_for_imas.timedim = nbdims;
if (size(gdat_data.data,nbdims)==1 && nbdims>1); mapping_for_imas.timedim = nbdims-1; end
end
dim_nontim = setdiff([1:nbdims],mapping_for_imas.timedim);
ijt=find(strcmp(tmp_fieldnames,'t')==1);
if isempty(ijt)
gdat_data.t = gdat_data.dim{mapping_for_imas.timedim};
end
ijx=find(strcmp(tmp_fieldnames,'x')==1);
if isempty(ijx)
if ~isempty(dim_nontim)
% since most cases have at most 2d, copy as array if data is 2D and as cell if 3D or more
if length(dim_nontim)==1
gdat_data.x = gdat_data.dim{dim_nontim(1)};
else
gdat_data.x = gdat_data.dim(dim_nontim);
end
end
end
gdat_data.data_fullpath=mapping_for_imas.expression;
if isfield(gdat_tmp,'help')
gdat_data.help = gdat_tmp.help;
else
gdat_data.help = [];
end
if isfield(gdat_data.gdat_params,'time_out') && ~isempty(gdat_data.gdat_params.time_out)
[gdat_data] = gdat2time_out(gdat_data,1);
end
end
% end of method "expression"
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif strcmp(mapping_for_imas.method,'switchcase')
switch data_request_eff % not lower(...) since data_request_eff should be lower case already at this stage
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% First the request names valid for "all" machines:
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
case {'ids'}
ids_empty_path = fullfile(fileparts(mfilename('fullpath')),'..','IMAS_IMAS','ids_empty');
params_eff = gdat_data.gdat_params;
if isfield(params_eff,'source') && ~isempty(params_eff.source)
ids_top_names = params_eff.source;
if ischar(ids_top_names); ids_top_names = {ids_top_names}; end

Olivier Sauter
committed
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
else
ids_top_name = [];
warning('gdat:EmptyIDSName','Need an ids name in ''source'' parameter\n check substructure gdat_params.sources_available for an ids list');
addpath(ids_empty_path);
assert(~~exist('ids_list','file'),'could not find ids_list.m in %s',ids_empty_path);
gdat_data.gdat_params.sources_available = ids_list;
rmpath(ids_empty_path);
return
end
ids_gen_ok = ~~exist('ids_gen','file');
if ~isfield(gdat_data.gdat_params,'error_bar') || isempty(gdat_data.gdat_params.error_bar)
gdat_data.gdat_params.error_bar = 'delta';
end
if ~isfield(gdat_data.gdat_params,'cocos_in') || isempty(gdat_data.gdat_params.cocos_in)
gdat_data.gdat_params.cocos_in = 11;
end
if ~isfield(gdat_data.gdat_params,'cocos_out') || isempty(gdat_data.gdat_params.cocos_out)
gdat_data.gdat_params.cocos_out = 11;
end
if ~isfield(gdat_data.gdat_params,'ipsign_out') || isempty(gdat_data.gdat_params.ipsign_out)
gdat_data.gdat_params.ipsign_out = 0;
end
if ~isfield(gdat_data.gdat_params,'b0sign_out') || isempty(gdat_data.gdat_params.b0sign_out)
gdat_data.gdat_params.b0sign_out = 0;
end
if ~isfield(gdat_data.gdat_params,'ipsign_in') || isempty(gdat_data.gdat_params.ipsign_in)
if gdat_data.gdat_params.ipsign_out~=0
gdat_data.gdat_params.ipsign_in = -1;

Olivier Sauter
committed
else
gdat_data.gdat_params.ipsign_in = 0;

Olivier Sauter
committed
end
end
if ~isfield(gdat_data.gdat_params,'b0sign_in') || isempty(gdat_data.gdat_params.b0sign_in)
if gdat_data.gdat_params.b0sign_out~=0
gdat_data.gdat_params.b0sign_in = -1;

Olivier Sauter
committed
else
gdat_data.gdat_params.b0sign_in = 0;

Olivier Sauter
committed
end
end
for i=1:length(ids_top_names)
ids_top_name = ids_top_names{i};
if ids_gen_ok
ids_empty = ids_gen(ids_top_name); % generate ids from ids_gen
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
else
% load empty ids structure from template file
fname = sprintf('ids_empty_%s',ids_top_name);
try
assert(~~exist(ids_empty_path,'dir'),'folder %s not found',ids_empty_path);
addpath(ids_empty_path);
assert(~~exist(fname,'file'),'file %s does not exist in %s',fname,ids_empty_path);
ids_empty = eval(fname);
disp(['use structure in .mat file: ' ids_empty_path '/' fname]);
rmpath(ids_empty_path);
catch ME
fprintf('Could not load empty template for %s\n',ids_top_name);
fprintf('Available templates:\n');
disp(dir(ids_empty_path));
rmpath(ids_empty_path);
rethrow(ME);
end
end
% load data
try
if isfield(gdat_data.gdat_params,'idx_imas_open_env') && gdat_data.gdat_params.idx_imas_open_env >= 0
if gdat_data.gdat_params.occurence == 0
ids_top = ids_get(gdat_data.gdat_params.idx_imas_open_env,ids_top_name);
else
ids_top = ids_get(gdat_data.gdat_params.idx_imas_open_env,[ids_top_name '/' num2str(gdat_data.gdat_params.occurence)]);
end
gdat_data.(ids_top_name) = ids_top;

Olivier Sauter
committed
else
gdat_data.(ids_top_name) = ids_empty;

Olivier Sauter
committed
end
catch ME_imas_ids_get
disp(['there is a problem with: imas_get_ids_' ids_top_name ...
' , may be check if it exists in your path or test it by itself'])
gdat_data.(ids_top_name) = ids_empty;
gdat_data.([ids_top_name '_help']) = getReport(ME_imas_ids_get);
rethrow(ME_imas_ids_get)
end

Olivier Sauter
committed
% check homogeneous
switch gdat_data.(ids_top_name).ids_properties.homogeneous_time
case -999999999
warning([ids_top_name '.ids_properties.homogeneous_time is not defined']);
if isempty(gdat_data.(ids_top_name).time)
gdat_data.(ids_top_name).ids_properties.homogeneous_time = 0;
warning([ids_top_name '.ids_properties.homogeneous_time set to 0 since .time empty']);
elseif isfinite(gdat_data.(ids_top_name).time)
gdat_data.(ids_top_name).ids_properties.homogeneous_time = 1;
warning([ids_top_name '.ids_properties.homogeneous_time set to 1 since .time finite']);
end
case 0
if ~isempty(gdat_data.(ids_top_name).time)
disp([ids_top_name '.ids_properties.homogeneous_time=0 but .time not empty, to check'])
end
case 1
if isempty(gdat_data.(ids_top_name).time)
disp([ids_top_name '.ids_properties.homogeneous_time=1 but .time empty, to check'])
end
otherwise
warning([ids_top_name '.ids_properties.homogeneous_time = ' num2str(gdat_data.(ids_top_name).ids_properties.homogeneous_time) ...
' not sure what to check'])
end
% Perform cocos transformation if cocos_out ~= cocos_in
if gdat_data.gdat_params.cocos_in ~= gdat_data.gdat_params.cocos_out
[ids_out,cocoscoeff]=ids_generic_cocos_nodes_transformation_symbolic(gdat_data.(ids_top_name),ids_top_name, ...
gdat_data.gdat_params.cocos_in, gdat_data.gdat_params.cocos_out, gdat_data.gdat_params.ipsign_out,gdat_data.gdat_params.b0sign_out, ...
gdat_data.gdat_params.ipsign_in, gdat_data.gdat_params.b0sign_in);

Olivier Sauter
committed
gdat_data.(ids_top_name) = ids_out;

Olivier Sauter
committed
end
end

Olivier Sauter
committed
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
otherwise
if (gdat_params.nverbose>=1); warning(['switchcase= ' data_request_eff ' not known in gdat_imas']); end
error_status=901;
return
end
else
if (gdat_params.nverbose>=1); warning(['IMAS method=' mapping_for_imas.method ' not known yet, contact Olivier.Sauter@epfl.ch']); end
error_status=602;
return
end
gdat_data.gdat_params.help = imas_help_parameters(fieldnames(gdat_data.gdat_params));
gdat_data.mapping_for.imas = mapping_for_imas;
gdat_params = gdat_data.gdat_params;
error_status=0;
return
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [firthomratio] = get_fir_thom_rat_data(shot,maintracename,timebase,nverbose);
%
% since depends on shot number for using auto fit and thomson or thomson edge, use tracename and function here
%
% maintracename = 'thomson' or 'thomson_edge
%
% return fir_to_thomson ratio on time=timebase
%
% normally should use "main" thomson one built from auto fit if possible
% take edge one if need be
%
% default: maintracename = "thomson"
%
maintracename_eff = 'thomson';
if exist('maintracename') && ~isempty(maintracename)
maintracename_eff = maintracename;
end
firthomratio = NaN;
if ~exist('timebase') || isempty(timebase)
if (nverbose>=1)
disp('need a timebase in get_fir_thom_rat_data')
end
return
end
firthomratio = NaN*ones(size(timebase));
if strcmp(maintracename_eff,'thomson')
if shot>=23801
tracefirrat=tdi('\results::thomson.profiles.auto:fir_thom_rat'); %time base not same!!
if isempty(tracefirrat.data) || ischar(tracefirrat.data)
if (nverbose>=1); disp('problem with \results::thomson.profiles.auto:fir_thom_rat: empty, use thomson:fir_thom_rat'); end
tracefirrat=tdi('\results::thomson:fir_thom_rat');
end
else
tracefirrat=tdi('\results::thomson:fir_thom_rat');
if isempty(tracefirrat.data) || ischar(tracefirrat.data)
if (nverbose>=1); disp('problem with \results::thomson:fir_thom_rat: empty'); end
end
end
elseif strcmp(maintracename_eff,'thomson_edge')
if shot>=23801
tracefirrat=tdi('\results::thomson.profiles.auto:fir_thom_rat'); %time base not same!!
if isempty(tracefirrat.data) || ischar(tracefirrat.data)
if (nverbose>=1); disp('problem with \results::thomson.profiles.auto:fir_thom_rat: empty, use thomson:fir_thom_rat'); end
tracefirrat=tdi('\results::thomson:fir_thom_rat');
end
else
tracefirrat=tdi('\results::thomson_edge:fir_thom_rat');
if isempty(tracefirrat.data) || ischar(tracefirrat.data)
if (nverbose>=1); disp('problem with \results::thomson_edge:fir_thom_rat: empty'); end
end
end
else
if (nverbose>=1); disp('bad input in get_fir_thom_rat_data'); end
return
end
if ~isempty(tracefirrat.data) && ~ischar(tracefirrat.data) && any(isfinite(tracefirrat.data)) ...
&& ~isempty(tracefirrat.dim) && ~isempty(tracefirrat.dim{1})
firthomratio = interp1(tracefirrat.dim{1},tracefirrat.data,timebase);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [gdat_data] = get_thomson_raw_data(shot,data_request_eff,gdat_data,doedge,nverbose);
%
try
time=mdsdata('\results::thomson:times');
catch
gdat_data.error_bar = [];
if strcmp(data_request_eff(1:2),'ne')
tracefirrat_data = [];
gdat_data.firrat=tracefirrat_data;
gdat_data.data_raw = gdat_data.data;
gdat_data.error_bar_raw = gdat_data.error_bar;
end
if (nverbose>=1) && shot<100000
warning('Problems with \results::thomson:times')
warning(['!!!!!!!!!!!!!!!!!!!!!!!!! cannot continue with ' data_request_eff])
end
return
end
if isempty(time) || ischar(time)
thomsontimes=time;
if (nverbose>=1) && shot<100000
warning('!!!!!!!!!!!!!!!!!!!!!!!!!\results::thomson:times is empty? Check')
disp(['!!!!!!!!!!!!!!!!!!!!!!!!! cannot continue with ' data_request_eff])
end
return
end
edge_str_ = '';
edge_str_dot = '';
if doedge
edge_str_ = '_edge';
edge_str_dot = '.edge';
end
nodenameeff = ['\results::thomson' edge_str_dot ':' data_request_eff(1:2)];
tracetdi=tdi(nodenameeff);
if isempty(tracetdi.data) || ischar(tracetdi.data) || isempty(tracetdi.dim)
gdat_data.error_bar = [];
gdat_data.firrat = [];
gdat_data.data_raw = [];
gdat_data.error_bar_raw = [];
return
end
gdat_data.data=tracetdi.data'; % Thomson data as (t,z)
tracestd=tdi(['\results::thomson' edge_str_dot ':' data_request_eff(1:2) ':error_bar']);
gdat_data.error_bar=tracestd.data';
gdat_data.data_fullpath=[nodenameeff '; error_bar'];
% add fir if ne requested
if strcmp(data_request_eff(1:2),'ne')
tracefirrat_data = get_fir_thom_rat_data(shot,['thomson' edge_str_],time,nverbose);
gdat_data.firrat=tracefirrat_data;
gdat_data.data_raw = gdat_data.data;
gdat_data.data = gdat_data.data_raw * diag(tracefirrat_data);
gdat_data.error_bar_raw = gdat_data.error_bar;
gdat_data.error_bar = gdat_data.error_bar_raw * diag(tracefirrat_data);
gdat_data.data_fullpath=[gdat_data.data_fullpath '; fir_thom_rat ; _raw without firrat'];
ij=find(isfinite(tracefirrat_data));
if isempty(ij)
gdat_data.data_fullpath=[gdat_data.data_fullpath ' WARNING use ne_raw since firrat has NaNs thus ne=NaNs; fir_thom_rat ; _raw without firrat'];
disp('***********************************************************************')
disp('WARNING: ne from Thomson has fir_thom_rat with Nans so only ne_raw can be used');
disp('***********************************************************************')
end
end
z=mdsdata(['\diagz::thomson_set_up' edge_str_dot ':vertical_pos']);
gdat_data.dim=[{z};{time}];
gdat_data.dimunits=[{'Z [m]'} ; {'time [s]'}];
gdat_data.x=z;
gdat_data.t=time;
% isfield does not work since tracetdi is not a 'struct' but a tdi object, thus use fieldnames
if any(strcmp(fieldnames(tracetdi),'units'))
gdat_data.units=tracetdi.units;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [psiscatvol,psi_max] = psi_scatvol_zshift(gdat_data, zshift, system_str_dot, psitbx_str, gdat_params )
% Input arguments:
% gdat_data: current structure containing TS data
% zshift: vertical shift of the equilibrium, can be a vector for time-dependent data
% system_str_dot: '' or '.edge' indicating thomson syste,
% psitbx_str: source for the equilibrium map, psitbx-style
% gdat_params: parameters for the gdat call % TODO: Why is it different from gdat_data.gdat_params?
% Use psitbx
t_th = gdat_data.t;
th_z = mdsdata(['dim_of(\thomson' system_str_dot ':te,1)']); % TODO: Isn't this gdat_data.dim{1}?
th_r = 0.9*ones(size(th_z));
ntt = numel(t_th);
nch = numel(th_z); % number of chords
[t_psi,status] = mdsvalue('dim_of(imas_eq("i_p",$))',psitbx_str); % TODO: replace with time_psi when imas_eq supports it
if ~rem(status,2)
warning('problem with getting equilibrium time base in gdat_imas')
display(t_psi);
return
end
zshifteff=zshift;
% set zshifteff time array same as t_psi
switch numel(zshifteff)
case 1
zshifteff=zshifteff * ones(size(t_th));
case numel(t_psi)
zshifteff=interp1(t_psi,zshifteff,t_th);
case numel(t_th)
% ok
otherwise
if (gdat_params.nverbose>=1)
disp(' bad time dimension for zshift')
disp(['it should be 1 or ' num2str(numel(t_th)) ' or ' num2str(numel(t_psi))])
return
end
end
% Get LIUQE times corresponding to TS times
t_eq = t_psi(iround(t_psi,t_th));
% Get PSI map
psi = psitbximas(gdat_data.shot,t_eq,'*0',psitbx_str);
% PSITBXIMAS will have removed duplicate times
i_psi = iround(psi.t,t_eq); % Mapping from psi times to TS times
% Define grid points where to evaluate PSI
if ~any(diff(zshifteff))
% Constant vector
pgrid = psitbxgrid('cylindrical','points',{th_r,th_z - zshifteff(1),0});
else
% We need as many time points in psi as TS times
psi = subs_time(psi,i_psi); % Now has ntt times
i_psi = 1:ntt; % Trivial mapping from psi times to TS times
% Time-varying vector
th_z_eff = repmat(th_z(:),1,ntt) - repmat(reshape(zshifteff,1,ntt),nch,1);
th_r_eff = repmat(th_r(:),1,ntt);
pgrid = psitbxgrid('cylindrical','time-points',{th_r_eff,th_z_eff,0});
end
% Compute psi at TS positions
psi_ts = psitbxf2f(psi,pgrid);
psiscatvol.data = squeeze(psi_ts.x(:,i_psi));
psiscatvol.dim{1} = gdat_data.x;
psiscatvol.dim{2} = t_th;
% NOTE: we should probably not include time points where equilibrium time is far from TS time.
% Compute psi_axis at TS times
% Do not use psi_axis node because:
% - For legacy LIUQE, psi_axis is not computed by psitbx, so we could get a
% different answer and cause complex numbers computing rho_psi
% - For MATLAB LIUQE, psi_axis is only the result of asxymex whereas the
% psitbx adds some Newton iterations so again complex numbers are possible
psi_norm = psitbxp2p(psi,'01');
psi_max.data = psi_norm.psimag(i_psi);
psi_max.dim = {t_th};