diff --git a/crpptbx/AUG/aug_requests_mapping.m b/crpptbx/AUG/aug_requests_mapping.m new file mode 100644 index 0000000000000000000000000000000000000000..15b98dd61e0063c58bb5c8662cd6c503e6a8b8d0 --- /dev/null +++ b/crpptbx/AUG/aug_requests_mapping.m @@ -0,0 +1,169 @@ +function mapping = aug_requests_mapping(data_request) + +% Defaults +mapping = struct(... + 'label', '', ... + 'method', '', ... + 'expression','', ... + 'timedim', -1, ... % dim which is the time, to copy in .t, the other dims are in .x (-1 means last dimension) + 'new_timedim',0, ... % if need to reshape data and dim orders to have timedim as new_timedim (shifting time to new_timedim) + 'min', -inf, ... + 'max', inf); + +if ~exist('data_request') || isempty(data_request) + return +end + +% default label: data_request keyword itself +mapping.label = data_request; + +% for AUG, following choices are set so far: +% method = 'tdi' and then expression is the string within tdi (usual case when there is a direct link to an existing signal) +% with tdi, if expression cell array, call tdi(cell{1},cell{2},...) +% method = 'function', then expression is the funtion to call which should return the correct structure +% method = 'switchcase', then there will be a specific case within gdat_aug (usual case when not directly a signal) +% +% label is used for plotting +switch lower(data_request) + case 'b0' + mapping.label = 'B_0'; + mapping.method = 'switchcase'; + mapping.expression = ''; + case 'betan' + mapping.label = '\beta_N'; + mapping.method = 'switchcase'; + mapping.expression = ''; + case 'betap' + mapping.label = '\beta_p'; + mapping.method = 'tdi'; + mapping.expression = '\results::beta_pol'; + case 'cxrs' + mapping.label = 'cxrs'; + mapping.method = 'switchcase'; + mapping.expression = ''; + case 'delta' + mapping.method = 'tdi'; + mapping.expression = '\results::delta_edge'; + mapping.method = 'function'; + mapping.expression = ['tdi(''\results::q_psi'');']; + case 'delta_top' + mapping.label = 'delta\_top'; + mapping.method = 'tdi'; + mapping.expression = '\results::delta_ed_top'; + case 'delta_bottom' + mapping.label = 'delta\_bottom'; + mapping.method = 'tdi'; + mapping.expression = '\results::delta_ed_bot'; + case 'ece' + mapping.method = 'switchcase'; + mapping.expression = ''; + case 'eqdsk' + mapping.method = 'switchcase'; % could use function make_eqdsk directly? + mapping.expression = ''; + case 'halpha' + mapping.label = 'Halpha'; + mapping.method = 'tdi'; + mapping.expression = '\base::pd:pd_011'; + case 'ioh' + mapping.label = 'I ohmic transformer'; + mapping.method = 'tdi'; + mapping.expression = [{'\magnetics::ipol[*,$1]'} {'OH_001'}]; + case 'ip' + mapping.label = 'Plasma current'; + mapping.method = 'tdi'; + mapping.expression = '\magnetics::iplasma:trapeze'; + case 'kappa' + mapping.method = 'tdi'; + mapping.expression = '\results::kappa_edge'; + case 'mhd' + mapping.label = 'n=1,2, etc'; + mapping.method = 'switchcase'; + mapping.expression = ''; + case 'ne' + mapping.method = 'switchcase'; + case 'neint' + mapping.label = 'line integrated el. density'; + mapping.method = 'tdi'; + mapping.expression = '\results::fir:lin_int_dens'; + case 'nel' + mapping.label = 'line-averaged el. density'; + mapping.method = 'tdi'; + mapping.expression = '\results::fir:n_average'; + case 'nerho' + mapping.label = 'ne'; + mapping.method = 'switchcase'; + case 'neterho' + mapping.label = 'ne and Te'; + mapping.method = 'switchcase'; + case 'ni' + mapping.method = 'switchcase'; % especially since might have option fit, etc + case 'powers' + mapping.label = 'various powers'; + mapping.method = 'switchcase'; + case 'q0' + mapping.method = 'tdi'; + mapping.expression = '\results::q_zero'; + case 'q95' + mapping.method = 'tdi'; + mapping.expression = '\results::q_95'; + case 'qedge' + mapping.method = 'tdi'; + mapping.expression = '\results::q_edge'; + case 'qrho' + mapping.label = 'q'; + mapping.method = 'switchcase'; + case 'rgeom' + mapping.label = 'Rgeom'; + mapping.method = 'switchcase'; + case 'rhovol' + mapping.label = 'rhovol\_norm'; + mapping.method = 'switchcase'; % from conf if exist otherwise computes it + case 'rmag' + mapping.label = 'R\_magaxis'; + mapping.method = 'tdi'; + mapping.expression = '\results::r_axis'; + case 'sxr' + mapping.method = 'switchcase'; + case 'te' + mapping.label = 'Te'; + mapping.method = 'switchcase'; + case 'terho' + mapping.label = 'Te'; + mapping.method = 'switchcase'; + case 'ti' + mapping.label = 'Ti'; + mapping.method = 'switchcase'; + case 'transp' + mapping.label = 'transp output'; + mapping.method = 'switchcase'; + case 'vloop' + mapping.label = ''; + mapping.method = 'tdi'; + mapping.expression = ''; + case 'vol' + mapping.label = 'Volume'; + mapping.method = 'switchcase'; + % mapping.expression = '\results::psitbx:vol'; (if exists for liuqe2 and 3 as well) + case 'zeff' + mapping.label = 'zeff from Ip-Ibs'; + mapping.method = 'tdi'; + mapping.expression = '\results::ibs:z_eff'; + case 'zgeom' + mapping.label = 'Zgeom'; + mapping.method = 'switchcase'; + case 'zmag' + mapping.label = 'Zmagaxis'; + mapping.method = 'tdi'; + mapping.expression = '\results::z_axis'; +% $$$ case '' +% $$$ mapping.label = ''; +% $$$ mapping.method = 'tdi'; +% $$$ mapping.expression = ''; + otherwise + mapping.label = data_request; + mapping.method = 'tdi'; % assume a full tracename is given, so just try with tdi (could check there are some ":", etc...) + mapping.expression = data_request; + +end + + diff --git a/crpptbx/AUG/gdat_aug.m b/crpptbx/AUG/gdat_aug.m new file mode 100644 index 0000000000000000000000000000000000000000..f070e344b769bc1899c876c9521ebcf19883fdd3 --- /dev/null +++ b/crpptbx/AUG/gdat_aug.m @@ -0,0 +1,426 @@ +function [gdat_data,gdat_params,error_status,varargout] = gdat_aug(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 +% +% Inputs: +% +% no inputs: return default parameters in a structure form in gdat_params +% shot: shot number +% 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','AUG' (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 expression, or relevant function called if relevant +% gdat_data.gdat_params: copy gdat_params for completeness +% gdat_data.xxx: any other relevant information +% +% +% Examples: +% (should add working examples for various machines (provides working shot numbers for each machine...)) +% +% [a1,a2]=gdat; +% a2.data_request = 'Ip'; +% 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,'ip'); % standard call +% a6=gdat(48836,'ip','Opt1',123,'Doplot',1,'opt2','Abc'); % standard call with a few options (note all lowercase in output) + +% +% Comments for local developer: +% This 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 default parameters structure +gdat_params.data_request = ''; +default_machine = 'aug'; + +gdat_params.machine=default_machine; +gdat_params.doplot = 0; + +% construct list of keywords from global set of keywords and specific AUG set +% get data_request names from centralized function +data_request_names = get_data_request_names; + +% add AUG specific to all: +if ~isempty(data_request_names.aug) + aug_names = fieldnames(data_request_names.aug); + for i=1:length(aug_names) + data_request_names.all.(aug_names{i}) = data_request_names.aug.(aug_names{i}); + end +end +data_request_names_all = fieldnames(data_request_names.all); + +% $$$ data_request_names_all= [{'ip'} {'b0'} {'zmag'} {'rmag'} {'rcont'} {'zcont'} {'vol'} {'rhovol'} {'qrho'} {'q95'} {'kappa'} ... +% $$$ {'delta'} {'deltatop'} {'deltabot'} {'neint'} {'nel'} ... +% $$$ {'ne'} {'te'} {'nerho'} {'terho'} {'ne_edge'} {'te_edge'} {'nerho_edge'} {'terho_edge'} {'nerhozshift'} {'terhozshift'} {'profnerho'} {'profterho'} ... +% $$$ {'neft'} {'teft'} {'neftav'} {'teftav'} {'neft:trial'} {'teft:trial'} {'neftav:trial'} {'teftav:trial'} ... +% $$$ {'sxr'} {'sxr'} {'ece'} {'mpx'} {'ioh'} {'vloop'} {'pgyro'} {'jtor'} {'vi_tor'} {'vi_torfit'} {'vi_pol'} {'vi_polfit'} {'ti'} {'tifit'} {'ni'} {'nifit'} {'zeffcxrs'} {'zeffcxrsfit'}]; + +% 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 && ischar(data_request); data_request = lower(data_request); end + +gdat_data.gdat_request = data_request_names_all; % so if return early gives list of possible request names +% 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) + % means mdsopen(shot) already performed + shot = mdsipmex(2,'$SHOT'); + gdat_data.shot = shot; + do_mdsopen_mdsclose = 0; + elseif isnumeric(shot) + gdat_data.shot = shot; + elseif ischar(shot) + ivarargin_first_char = 1; + else + warning('type of 1st argument unexpected, should be numeric or char') + 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') + warning('expects field data_request in input parameters structure') + error_status=3; + return + end + data_request.data_request = lower(data_request.data_request); + data_request_eff = 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}) + % enforce lower case for any character driven input + if ischar(varargin_eff{i+1}) + gdat_params.(lower(varargin_eff{i})) = lower(varargin_eff{i+1}); + else + gdat_params.(lower(varargin_eff{i})) = varargin_eff{i+1}; + end + else + warning(['input argument nb: ' num2str(i) ' is incorrect, expects a character string']) + error_status=401; + return + end + end + else + warning('number of input arguments incorrect, cannot make pairs of parameters') + error_status=402; + return + end +end +data_request_eff = gdat_params.data_request; % in case was defined in pairs + +% if it is a request_keyword copy it: +ij=strmatch(data_request_eff,data_request_names_all,'exact'); +if ~isempty(ij); + gdat_data.gdat_request = data_request_names_all{ij}; + 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; + +% 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; +error_status = 6; % at least reached this level + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Specifications on how to get the data provided in aug_requests_mapping +mapping_for_aug = aug_requests_mapping(data_request_eff); +gdat_data.label = mapping_for_aug.label; + +ishot=NaN; +if do_mdsopen_mdsclose + mdsdefaultserver aug1.epfl.ch; % should be in aug general path, but set-it in the meantime... + ishot = mdsopen(shot); % if ishot equal to shot, then mdsclose at the end + if ishot~=shot + warning(['cannot open shot= ' num2str(shot)]) + return + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% 1st treat the simplest method: "tdi" +if strcmp(mapping_for_aug.method,'tdi') + % need to treat liuqe2, model, etc from options.... + if iscell(mapping_for_aug.expression) + if length(mapping_for_aug.expression)>0 + % series of arguments for tdi given in each cell + eval_expr = ['aatmp=tdi(''' mapping_for_aug.expression{1} '''']; + for i=2:length(mapping_for_aug.expression) + eval_expr = [eval_expr ',''' mapping_for_aug.expression{i} '''']; + end + eval_expr = [eval_expr ');']; + eval(eval_expr); + else + % empty or wrong expression + error_status=701; + return + end + else + eval_expr = ['aatmp=tdi(''' mapping_for_aug.expression ''');']; + eval(eval_expr); + end + gdat_data.data = aatmp.data; + gdat_data.dim = aatmp.dim; + nbdims = length(gdat_data.dim); + if mapping_for_aug.timedim==-1; + mapping_for_aug.timedim = nbdims; + if (size(gdat_data.data,nbdims)==1 && nbdims>1); mapping_for_aug.timedim = nbdims-1; end + end + dim_nontim = setdiff([1:nbdims],mapping_for_aug.timedim); + 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 + gdat_data.t = gdat_data.dim{mapping_for_aug.timedim}; + gdat_data.units = aatmp.units; + gdat_data.dimunits = aatmp.dimunits; + if mapping_for_aug.new_timedim>0 && mapping_for_aug.new_timedim ~= mapping_for_aug.timedim + % shift timedim to new_timedim data(i,j,...itime,k,...) -> data(i,inewtime,j,...,k,...) + % note that this means that gdat_data.x and gdat_data.t are same and correct, + % only .data, .dim and .dimunits need to be changed + iprev=[1:nbdims]; + ij=find(dim_nontim>mapping_for_aug.new_timedim-1); + inew=[1:mapping_for_aug.new_timedim-1 mapping_for_aug.timedim dim_nontim(ij)]; + data_sizes = size(aatmp.data); + gdat_data.data = NaN*ones(data_sizes(inew)); + abcol=ones(1,nbdims)*double(':'); abcomma=ones(1,nbdims)*double(','); + dimstr_prev=['(' repmat(':,',1,mapping_for_aug.timedim-1) 'it,' ... + repmat(':,',1,nbdims-mapping_for_aug.timedim-1) ':)']; + dimstr_new=['(' repmat(':,',1,mapping_for_aug.new_timedim-1) 'it,' ... + repmat(':,',1,nbdims-mapping_for_aug.new_timedim-1) ':)']; + % eval gdat_data.data(;,:,...,it,...) = aatmp.data(:,:,:,it,...); + for it=1:size(aatmp.data,mapping_for_aug.timedim) + shift_eval = ['gdat_data.data' dimstr_new ' = aatmp.data' dimstr_prev ';']; + eval(shift_eval); + end + gdat_data.dim = aatmp.dim(inew); + gdat_data.dimunits = aatmp.dimunits(inew); + end + gdat_data.data_fullpath=mapping_for_aug.expression; + % end of method "tdi" + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif strcmp(mapping_for_aug.method,'function') + % 2nd: method="function" + % assume expression contains function to call and which returns a structure + % we copy the structure, to make sure default nodes are defined and to avoid if return is an closed object like tdi + eval_expr = ['aatmp=' mapping_for_aug.expression ';']; + eval(eval_expr); + if isempty(aatmp) || (~isstruct(aatmp) & ~isobject(aatmp)) + warning(['function expression does not return a structure: ' eval_expr]) + error_status=801; + return + end + tmp_fieldnames = fieldnames(aatmp); + if sum(strcmp(tmp_fieldnames,'data'))==0 % note: cannot do isfield since aatmp might be an object + warning(['function does not return a child name ''data'' for ' data_request_eff]) + end + for i=1:length(tmp_fieldnames) + gdat_data.(tmp_fieldnames{i}) = aatmp.(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 function + ijdim=find(strcmp(tmp_fieldnames,'dim')==1); + if ~isempty(ijdim) + nbdims = length(gdat_data.dim); + if mapping_for_aug.timedim==-1; + mapping_for_aug.timedim = nbdims; + if (size(gdat_data.data,nbdims)==1 && nbdims>1); mapping_for_aug.timedim = nbdims-1; end + end + dim_nontim = setdiff([1:nbdims],mapping_for_aug.timedim); + ijt=find(strcmp(tmp_fieldnames,'t')==1); + if isempty(ijt) + gdat_data.t = gdat_data.dim{mapping_for_aug.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_aug.expression; + end + % end of method "function" + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif strcmp(mapping_for_aug.method,'switchcase') + switch data_request_eff % not lower(...) since data_request_eff should be lower case already at this stage + case {'ne','te'} + % ne or Te from Thomson data on raw z mesh vs (z,t) + mdsopen(shot); + nodenameeff=['\results::thomson:' data_request_eff]; + tracetdi=tdi(nodenameeff); + tracestd=tdi(['\results::thomson:' data_request_eff ':error_bar']); + trace_fir_rat=tdi('\results::thomson:fir_thom_rat'); + gdat_data.data=tracetdi.data'; % Thomson data as (t,z) + gdat_data.error_bar=tracestd.data'; + gdat_data.data_fullpath=[nodenameeff]; + % add correct dimensions + try + time=mdsdata('\results::thomson:times'); + catch + warning('Problems with \results::thomson:times') + disp(['!!!!!!!!!!!!!!!!!!!!!!!!! cannot continue with ' data_request_eff]) + return + end + if isempty(time) || ischar(time) + thomsontimes=time + warning('!!!!!!!!!!!!!!!!!!!!!!!!!\results::thomson:times is empty? Check') + disp(['!!!!!!!!!!!!!!!!!!!!!!!!! cannot continue with ' data_request_eff]) + return + end + if strcmp(data_request_eff(1:2),'ne') + tracefirrat_data = get_fir_thom_rat_data('thomson',time); + gdat_data.data_abs = gdat_data.data * diag(tracefirrat_data); + gdat_data.error_bar_abs = gdat_data.error_bar * diag(tracefirrat_data); + gdat_data.firrat=tracefirrat_data; + gdat_data.data_fullpath=[gdat_data.data_fullpath ' ; _abs includes *firrat']; + end + z=mdsdata('\diagz::thomson_set_up: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 + + + case 'nerho' + + + otherwise + warning(['switchcase= ' data_request_eff ' not known in gdat_aug']) + error_status=901; + return + end + +else + warning(['AUG method=' mapping_for_aug.method ' not known yet, contact Olivier.Sauter@epfl.ch']) + error_status=602; + return +end + +if ishot==shot; mdsclose; end + +gdat_data.mapping_for_aug = mapping_for_aug; +error_status=0; + +return + diff --git a/crpptbx/TCV/gdat_tcv.m b/crpptbx/TCV/gdat_tcv.m new file mode 100644 index 0000000000000000000000000000000000000000..269a3fb267f4063d1e9cd217304970e5da76d21f --- /dev/null +++ b/crpptbx/TCV/gdat_tcv.m @@ -0,0 +1,1170 @@ +function [gdat_data,gdat_params,error_status,varargout] = gdat_tcv(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 +% +% Inputs: +% +% no inputs: return default parameters in a structure form in gdat_params +% shot: shot number +% 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','TCV' (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 expression, or relevant function called if relevant +% gdat_data.gdat_params: copy gdat_params for completeness +% gdat_data.xxx: any other relevant information +% +% +% Examples: +% (should add working examples for various machines (provides working shot numbers for each machine...)) +% +% [a1,a2]=gdat; +% a2.data_request = 'Ip'; +% 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,'ip'); % standard call +% a6=gdat(48836,'ip','Opt1',123,'Doplot',1,'opt2','Abc'); % standard call with a few options (note all lowercase in output) + +% +% Comments for local developer: +% This 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; +nverbose = 1; + +% construct default parameters structure +gdat_params.data_request = ''; +default_machine = 'tcv'; + +gdat_params.machine=default_machine; +gdat_params.doplot = 0; +gdat_params.liuqe = 1; + +% construct list of keywords from global set of keywords and specific TCV set +% get data_request names from centralized function +data_request_names = get_data_request_names; +% add TCV specific to all: +if ~isempty(data_request_names.tcv) + tcv_names = fieldnames(data_request_names.tcv); + for i=1:length(tcv_names) + data_request_names.all.(tcv_names{i}) = data_request_names.tcv.(tcv_names{i}); + end +end +data_request_names_all = fieldnames(data_request_names.all); + +% $$$ data_request_names_all= [{'ip'} {'b0'} {'zmag'} {'rmag'} {'rcont'} {'zcont'} {'vol'} {'rhovol'} {'qrho'} {'q95'} {'kappa'} ... +% $$$ {'delta'} {'deltatop'} {'deltabot'} {'neint'} {'nel'} ... +% $$$ {'ne'} {'te'} {'nerho'} {'terho'} {'ne_edge'} {'te_edge'} {'nerho_edge'} {'terho_edge'} {'nerhozshift'} {'terhozshift'} {'profnerho'} {'profterho'} ... +% $$$ {'neft'} {'teft'} {'neftav'} {'teftav'} {'neft:trial'} {'teft:trial'} {'neftav:trial'} {'teftav:trial'} ... +% $$$ {'sxr'} {'sxr'} {'ece'} {'mpx'} {'ioh'} {'vloop'} {'pgyro'} {'jtor'} {'vi_tor'} {'vi_torfit'} {'vi_pol'} {'vi_polfit'} {'ti'} {'tifit'} {'ni'} {'nifit'} {'zeffcxrs'} {'zeffcxrsfit'}]; + +% 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 && ischar(data_request); data_request = lower(data_request); end + +gdat_data.gdat_request = data_request_names_all; % so if return early gives list of possible request names +% 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) + % means mdsopen(shot) already performed + shot = mdsipmex(2,'$SHOT'); + gdat_data.shot = shot; + do_mdsopen_mdsclose = 0; + elseif isnumeric(shot) + gdat_data.shot = shot; + elseif ischar(shot) + ivarargin_first_char = 1; + else + warning('type of 1st argument unexpected, should be numeric or char') + 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') + warning('expects field data_request in input parameters structure') + error_status=3; + return + end + data_request.data_request = lower(data_request.data_request); + data_request_eff = 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}) + % enforce lower case for any character driven input + if ischar(varargin_eff{i+1}) + gdat_params.(lower(varargin_eff{i})) = lower(varargin_eff{i+1}); + else + gdat_params.(lower(varargin_eff{i})) = varargin_eff{i+1}; + end + else + warning(['input argument nb: ' num2str(i) ' is incorrect, expects a character string']) + error_status=401; + return + end + end + else + warning('number of input arguments incorrect, cannot make pairs of parameters') + error_status=402; + return + end +end +data_request_eff = gdat_params.data_request; % in case was defined in pairs + +% if it is a request_keyword copy it: +ij=strmatch(data_request_eff,data_request_names_all,'exact'); +if ~isempty(ij); + gdat_data.gdat_request = data_request_names_all{ij}; + 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; + +% 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; +error_status = 6; % at least reached this level + +liuqe_version = 1; +if isfield(gdat_data.gdat_params,'liuqe') && ~isempty(gdat_data.gdat_params.liuqe) + liuqe_version = gdat_data.gdat_params.liuqe; +end +substr_liuqe = ''; +if liuqe_version==2 || liuqe_version==3 + substr_liuqe = ['_' num2str(liuqe_version)]; +end + +% special treatment for model shot=-1 or preparation shot >=100'000 +begstr = ''; +if shot==-1 || shot>=100000 + % requires FBTE + liuqe_version = -1; + begstr = 'tcv_eq( "'; + substr_liuqe = '", "FBTE" )'; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Specifications on how to get the data provided in tcv_requests_mapping +mapping_for_tcv = tcv_requests_mapping(data_request_eff); +gdat_data.label = mapping_for_tcv.label; + +ishot=NaN; +if do_mdsopen_mdsclose + % mdsdefaultserver tcv1.epfl.ch; % should be in tcv general path, but set-it in the meantime... + if liuqe_version==-1 + ishot = mdsopen('pcs', shot); + else + ishot = mdsopen(shot); % if ishot equal to shot, then mdsclose at the end + end + if ishot~=shot + warning(['cannot open shot= ' num2str(shot)]) + return + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% 1st treat the simplest method: "tdi" (and tdiliuqe) +if strcmp(mapping_for_tcv.method(1:3),'tdi') + % need to treat liuqe2, model, etc from options.... + substr_tdi = ''; + if strcmp(mapping_for_tcv.method,'tdiliuqe'); substr_tdi = substr_liuqe; end + if iscell(mapping_for_tcv.expression) + if length(mapping_for_tcv.expression)>0 + % series of arguments for tdi given in each cell + eval_expr = ['tdi(''' mapping_for_tcv.expression{1} substr_tdi '''']; + for i=2:length(mapping_for_tcv.expression) + eval_expr = [eval_expr ',''' mapping_for_tcv.expression{i} '''']; + end + eval_expr = [eval_expr ');']; + aatmp = eval(eval_expr); + else + % empty or wrong expression + error_status=701; + return + end + else + if liuqe_version==-1 + mapping_for_tcv_expression_eff = mapping_for_tcv.expression; + if strcmp(lower(mapping_for_tcv.expression(1:8)),'\results') + mapping_for_tcv_expression_eff = mapping_for_tcv.expression(11:end); + end + eval_expr = ['tdi(''' begstr mapping_for_tcv_expression_eff substr_liuqe ''');'] + else + eval_expr = ['tdi(''' mapping_for_tcv.expression substr_tdi ''');']; + end + aatmp=eval(eval_expr); + end + if isempty(aatmp.data) || isempty(aatmp.dim) % || ischar(aatmp.data) (to add?) + if (nverbose>=3); warning(['problems loading data for ' eval_expr ' for data_request= ' data_request_eff]); end + return + end + gdat_data.data = aatmp.data; + gdat_data.dim = aatmp.dim; + nbdims = length(gdat_data.dim); + if mapping_for_tcv.timedim==-1; + mapping_for_tcv.timedim = nbdims; + if (size(gdat_data.data,nbdims)==1 && nbdims>1); mapping_for_tcv.timedim = nbdims-1; end + end + dim_nontim = setdiff([1:nbdims],mapping_for_tcv.timedim); + 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 + gdat_data.t = gdat_data.dim{mapping_for_tcv.timedim}; + gdat_data.units = aatmp.units; + gdat_data.dimunits = aatmp.dimunits; + if mapping_for_tcv.gdat_timedim>0 && mapping_for_tcv.gdat_timedim ~= mapping_for_tcv.timedim + % shift timedim to gdat_timedim data(i,j,...itime,k,...) -> data(i,inewtime,j,...,k,...) + % note that this means that gdat_data.x and gdat_data.t are same and correct, + % only .data, .dim and .dimunits need to be changed + iprev=[1:nbdims]; + ij=find(dim_nontim>mapping_for_tcv.gdat_timedim-1); + inew=[1:mapping_for_tcv.gdat_timedim-1 mapping_for_tcv.timedim dim_nontim(ij)]; + data_sizes = size(aatmp.data); + gdat_data.data = NaN*ones(data_sizes(inew)); + abcol=ones(1,nbdims)*double(':'); abcomma=ones(1,nbdims)*double(','); + dimstr_prev=['(' repmat(':,',1,mapping_for_tcv.timedim-1) 'it,' ... + repmat(':,',1,nbdims-mapping_for_tcv.timedim-1) ':)']; + dimstr_new=['(' repmat(':,',1,mapping_for_tcv.gdat_timedim-1) 'it,' ... + repmat(':,',1,nbdims-mapping_for_tcv.gdat_timedim-1) ':)']; + % eval gdat_data.data(;,:,...,it,...) = aatmp.data(:,:,:,it,...); + for it=1:size(aatmp.data,mapping_for_tcv.timedim) + shift_eval = ['gdat_data.data' dimstr_new ' = aatmp.data' dimstr_prev ';']; + eval(shift_eval); + end + gdat_data.dim = aatmp.dim(inew); + gdat_data.dimunits = aatmp.dimunits(inew); + else + mapping_for_tcv.gdat_timedim = mapping_for_tcv.timedim; + end + gdat_data.data_fullpath=[mapping_for_tcv.expression substr_tdi]; + + % end of method "tdi" + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif strcmp(mapping_for_tcv.method,'expression') + % 2nd: method="expression" + % assume expression contains function to call and which returns a 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_tcv.expression ';']; + eval([mapping_for_tcv.expression ';']); + if isempty(gdat_tmp) || (~isstruct(gdat_tmp) & ~isobject(gdat_tmp)) + warning(['function expression does not return a structure: ' mapping_for_tcv.expression]) + error_status=801; + return + end + tmp_fieldnames = fieldnames(gdat_tmp); + if sum(strcmp(tmp_fieldnames,'data'))==0 % note: cannot do isfield since gdat_tmp might be an object + warning(['function does not return a child name ''data'' for ' data_request_eff]) + 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 function + ijdim=find(strcmp(tmp_fieldnames,'dim')==1); + if ~isempty(ijdim) + nbdims = length(gdat_data.dim); + if mapping_for_tcv.timedim==-1; + mapping_for_tcv.timedim = nbdims; + if (size(gdat_data.data,nbdims)==1 && nbdims>1); mapping_for_tcv.timedim = nbdims-1; end + end + dim_nontim = setdiff([1:nbdims],mapping_for_tcv.timedim); + ijt=find(strcmp(tmp_fieldnames,'t')==1); + if isempty(ijt) + gdat_data.t = gdat_data.dim{mapping_for_tcv.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_tcv.expression; + end + % end of method "function" + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif strcmp(mapping_for_tcv.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 {'a_minor','rgeom'} + % compute average minor or major radius (on z=zaxis normally) + nodenameeff=['\results::r_max_psi' substr_liuqe]; + rmaxpsi=tdi(nodenameeff); + nodenameeff2=['\results::r_min_psi' substr_liuqe]; + rminpsi=tdi(nodenameeff2); + ij=find(rmaxpsi.data<0.5 | rmaxpsi.data>1.2); + if ~isempty(ij); rmaxpsi.data(ij)=NaN; end + ij=find(rminpsi.data<0.5 | rminpsi.data>1.2); + if ~isempty(ij); rminpsi.data(ij)=NaN; end + if strcmp(data_request_eff,'a_minor') + gdat_data.data=0.5.*(rmaxpsi.data(end,:) - rminpsi.data(end,:)); + gdat_data.data_fullpath=[nodenameeff ' - ' nodenameeff2 ' /2']; + elseif strcmp(data_request_eff,'rgeom') + gdat_data.data=0.5.*(rmaxpsi.data(end,:) + rminpsi.data(end,:)); + gdat_data.data_fullpath=[nodenameeff ' + ' nodenameeff2 ' /2']; + else + disp(['should not be in this case with data_request_eff = ' data_request_eff]) + return + end + gdat_data.dim = rmaxpsi.dim(2); + gdat_data.t = gdat_data.dim{1}; + if any(strcmp(fieldnames(rmaxpsi),'units')) + gdat_data.units = rmaxpsi.units; + end + gdat_data.dimunits = rmaxpsi.dimunits(2); + + case {'zgeom'} + % compute average minor or major radius (on z=zaxis normally) + nodenameeff=['\results::z_contour' substr_liuqe]; + zcontour=tdi(nodenameeff); + if strcmp(data_request_eff,'zgeom') + gdat_data.data=0.5.*(max(zcontour.data,[],1) + min(zcontour.data,[],1)); + gdat_data.data_fullpath=['(max+min)/2 of ' nodenameeff]; + gdat_data.dim{1} = zcontour.dim{2}; + gdat_data.dimunits{1} = zcontour.dimunits{2}; + else + disp(['should not be in this case with data_request_eff = ' data_request_eff]) + return + end + gdat_data.t = gdat_data.dim{mapping_for_tcv.gdat_timedim}; + if any(strcmp(fieldnames(zcontour),'units')) + gdat_data.units = zcontour.units; + end + + case {'b0'} + % B0 at R0=0.88 + R0EXP=0.88; + if liuqe_version==-1 + nodenameeff = 'tcv_eq("BZERO","FBTE")'; + tracetdi=tdi(nodenameeff); + gdat_data.data = tracetdi.data; + else + nodenameeff=['\magnetics::iphi']; + tracetdi=tdi(nodenameeff); + gdat_data.data=192.E-07 * 0.996 *tracetdi.data/R0EXP; + end + if isempty(tracetdi.data) || isempty(tracetdi.dim) % || ischar(tracetdi.data) (to add?) + warning(['problems loading data for ' nodenameeff ' for data_request= ' data_request_eff]) + return + end + gdat_data.data_fullpath=[nodenameeff]; + gdat_data.dim = tracetdi.dim; + gdat_data.t = gdat_data.dim{1}; + if any(strcmp(fieldnames(tracetdi),'units')) + gdat_data.units = tracetdi.units; + end + gdat_data.dimunits = tracetdi.dimunits; + gdat_data.request_description = ['vacuum magnetic field at R0=' num2str(R0EXP) 'm; COCOS=17']; + + case {'betan'} + % 100*beta / |Ip[MA] * B0[T]| * a[m] + % get B0 from gdat_tcv, without re-opening the shot and using the same parameters except data_request + % easily done thanks to structure call for options + params_eff = gdat_data.gdat_params; + params_eff.data_request='b0'; + b0=gdat_tcv([],params_eff); % note: no need to set .doplot=0 since gdat_tcv does not call gdat_plot in any case + params_eff.data_request='ip'; + ip=gdat_tcv([],params_eff); + params_eff.data_request='beta'; + beta=gdat_tcv([],params_eff); + params_eff.data_request='a_minor'; + a_minor=gdat_tcv([],params_eff); + % use beta as time base + if isempty(b0.data) || isempty(b0.dim) || isempty(ip.data) || isempty(ip.dim) || isempty(a_minor.data) || isempty(a_minor.dim) || isempty(beta.data) || isempty(beta.dim) + warning(['problems loading data for ' nodenameeff ' for data_request= ' data_request_eff]) + return + end + gdat_data.dim = beta.dim; + gdat_data.t = beta.dim{1}; + gdat_data.data = beta.data; + ij=find(~isnan(ip.data)); + ip_t = interp1(ip.dim{1}(ij),ip.data(ij),gdat_data.t); + ij=find(~isnan(b0.data)); + b0_t = interp1(b0.dim{1}(ij),b0.data(ij),gdat_data.t); + ij=find(~isnan(a_minor.data)); + a_minor_t = interp1(a_minor.dim{1}(ij),a_minor.data(ij),gdat_data.t); + gdat_data.data = 100.*beta.data ./ abs(ip_t).*1.e6 .* abs(b0_t) .* a_minor_t; + gdat_data.data_fullpath='100*beta/ip*1e6*b0*a_minor, each from gdat_tcv'; + gdat_data.units = ''; + gdat_data.dimunits{1} = 's'; + + case {'cxrs'} + %not yet finished, just started + return + % load typical data from cxrs, Ti, ni, vtori and vpoli (if available), as well as zeff from cxrs + % if 'fit' option is added: 'fit',1, then the fitted profiles are returned + % + sub_nodes = {'Ti','vi_tor','vi_pol','ni','zeff'}; % first node is also copied into data, choose "default' one + % sub_nodes_fit = {'Tifit','vi_torfit','vi_polfit','nifit','zefffit'}; + params_eff = gdat_data.gdat_params; + % use A. Karpushov routine to get profiles and then copy the data or the fitted profiles + param_cxrs.k_plot=0; param_cxrs.k_debug=0; + cxrs_profiles = CXRS_get_profiles(48836,[],[],param_cxrs); + if isfield(params_eff,'fit') && params_eff.fit>0 + sub_nodes_eff = sub_nodes_fit; + else + sub_nodes_eff = sub_nodes; + end + + + gdat_data.dim = beta.dim; + gdat_data.t = beta.dim{1}; + gdat_data.data = beta.data; + ij=find(~isnan(ip.data)); + ip_t = interp1(ip.dim{1}(ij),ip.data(ij),gdat_data.t); + ij=find(~isnan(b0.data)); + b0_t = interp1(b0.dim{1}(ij),b0.data(ij),gdat_data.t); + ij=find(~isnan(a_minor.data)); + a_minor_t = interp1(a_minor.dim{1}(ij),a_minor.data(ij),gdat_data.t); + gdat_data.data = 100.*beta.data ./ abs(ip_t).*1.e6 .* abs(b0_t) .* a_minor_t; + gdat_data.data_fullpath='100*beta/ip*1e6*b0*a_minor, each from gdat_tcv'; + gdat_data.units = ''; + gdat_data.dimunits = beta.dimunits; + + case {'eqdsk'} + % + time=1.; % default time + if isfield(gdat_data.gdat_params,'time') && ~isempty(gdat_data.gdat_params.time) + time = gdat_data.gdat_params.time; + else + disp(['"time" is expected as an option, choose default time = ' num2str(time)]); + end + gdat_data.gdat_params.time = time; + gdat_data.t = time; + zshift = 0.; + if isfield(gdat_data.gdat_params,'zshift') && ~isempty(gdat_data.gdat_params.zshift) + zshift = gdat_data.gdat_params.zshift; + end + gdat_data.gdat_params.zshift = zshift; + for itime=1:length(time) + time_eff = time(itime); + % use read_results updated to effectively obtain an eqdsk with sign correct with COCOS=2 + [fnames_readresults]=read_results_for_chease(shot,time_eff,liuqe_version,3,[],[],[],zshift,0,1); + eqdskval=read_eqdsk(fnames_readresults{4},7,0,[],[],1); % LIUQE is 17 but read_results divided psi by 2pi thus 7 + for i=1:length(fnames_readresults) + unix(['rm ' fnames_readresults{i}]); + end + % transform to cocos=2 since read_results originally assumed it was cocos=2 + cocos_in = 2; + [eqdsk_cocos_in, eqdsk_cocosout_IpB0pos,cocos_inout]=eqdsk_cocos_transform(eqdskval,[7 cocos_in]); + fnamefull = fullfile(['/tmp/' getenv('USER')],['EQDSK_' num2str(shot) 't' num2str(time_eff,'%.4f')]); + % We still write COCOS=2 case, since closer to standard (in /tmp) + write_eqdsk(fnamefull,eqdsk_cocos_in,cocos_in,[],[],[],1); + % Now gdat_tcv should return the convention from LIUQE which is COCOS=17, except if specified in option + % create standard filename name from shot, time_eff (cocos will be added by write_eqdsk) + cocos_out = 17; + if isfield(gdat_data.gdat_params,'cocos') && ~isempty(gdat_data.gdat_params.cocos) + cocos_out = gdat_data.gdat_params.cocos; + end + [eqdsk_cocosout, eqdsk_cocosout_IpB0pos,cocos_inout]=eqdsk_cocos_transform(eqdsk_cocos_in,[cocos_in cocos_out]); + % for several times, use array of structure for eqdsks, + % cannot use it for psi(R,Z) in .data and .x since R, Z might be different at different times, + % so project psi(R,Z) on Rmesh, Zmesh of 1st time + if length(time) > 1 + gdat_data.eqdsk{itime} = write_eqdsk(fnamefull,eqdsk_cocosout,cocos_out); + if itime==1 + gdat_data.data(:,:,itime) = gdat_data.eqdsk{itime}.psi; + gdat_data.dim{1} = gdat_data.eqdsk{itime}.rmesh; + gdat_data.dim{2} = gdat_data.eqdsk{itime}.zmesh; + else + aa=interpos2Dcartesian(gdat_data.eqdsk{itime}.rmesh,gdat_data.eqdsk{itime}.zmesh, ... + gdat_data.eqdsk{itime}.psi,repmat(gdat_data.dim{1}',1,129),repmat(gdat_data.dim{2},129,1),-1,-1); + gdat_data.data(:,:,itime) = aa; + end + else + gdat_data.eqdsk = write_eqdsk(fnamefull,eqdsk_cocosout,cocos_out); + gdat_data.data = gdat_data.eqdsk.psi; + gdat_data.dim{1} = gdat_data.eqdsk.rmesh; + gdat_data.dim{2} = gdat_data.eqdsk.zmesh; + end + end + gdat_data.dim{3} = gdat_data.t; + gdat_data.x = gdat_data.dim(1:2); + gdat_data.data_fullpath=['psi(R,Z) and eqdsk from read_eqdsk from LIUQE' num2str(liuqe_version) ';zshift=' num2str(zshift)]; + gdat_data.units = 'T m^2'; + gdat_data.dimunits = {'m','m','s'}; + gdat_data.request_description = ['data=psi, x=(R,Z), eqdsk contains eqdsk structure with which ' ... + 'plot_eqdsk, write_eqdsk, read_eqdsk can be used']; + + case {'mhd'} + % load n=1, 2 and 3 Bdot from magnetic measurements + n1=tdi('abs(mhdmode("LFS",1,1))'); + n2=tdi('abs(mhdmode("LFS",2,1))'); + n3=tdi('abs(mhdmode("LFS",3,1))'); + if ~isempty(n1.data) + gdat_data.data(:,1) = reshape(n1.data,length(n1.data),1); + if length(n2.data)==length(n1.data); gdat_data.data(:,2) = reshape(n2.data,length(n2.data),1); end + if length(n3.data)==length(n1.data); gdat_data.data(:,3) = reshape(n3.data,length(n3.data),1); end + gdat_data.dim{1} = n1.dim{1}; + gdat_data.t = gdat_data.dim{1}; + gdat_data.dim{2} = [1; 2; 3]; + gdat_data.dimunits{1} = n1.dimunits{1}; + gdat_data.dimunits{2} = 'n number'; + gdat_data.units = 'T/s'; + gdat_data.data_fullpath='abs(mhdmode("LFS",n,1))'; + gdat_data.request_description = 'delta_Bdot from magnetic probes to get n=1, 2 and 3'; + end + + case {'ne','te'} + % ne or Te from Thomson data on raw z mesh vs (z,t) + edge_str_ = ''; + edge_str_dot = ''; + if isfield(gdat_data.gdat_params,'edge') && ~isempty(gdat_data.gdat_params.edge) && ... + gdat_data.gdat_params.edge>0 + edge_str_ = '_edge'; + edge_str_dot = '.edge'; + end + nodenameeff=['\results::thomson' edge_str_dot ':' data_request_eff]; + tracetdi=tdi(nodenameeff); + tracestd=tdi(['\results::thomson' edge_str_dot ':' data_request_eff ':error_bar']); + gdat_data.data=tracetdi.data'; % Thomson data as (t,z) + gdat_data.error_bar=tracestd.data'; + gdat_data.data_fullpath=[nodenameeff]; + % add correct dimensions + try + time=mdsdata('\results::thomson:times'); + catch + warning('Problems with \results::thomson:times') + disp(['!!!!!!!!!!!!!!!!!!!!!!!!! cannot continue with ' data_request_eff]) + return + end + if isempty(time) || ischar(time) + thomsontimes=time + warning('!!!!!!!!!!!!!!!!!!!!!!!!!\results::thomson:times is empty? Check') + disp(['!!!!!!!!!!!!!!!!!!!!!!!!! cannot continue with ' data_request_eff]) + return + end + if strcmp(data_request_eff(1:2),'ne') + tracefirrat_data = get_fir_thom_rat_data(shot,['thomson' edge_str_],time); + gdat_data.data_abs = gdat_data.data * diag(tracefirrat_data); + gdat_data.error_bar_abs = gdat_data.error_bar * diag(tracefirrat_data); + gdat_data.firrat=tracefirrat_data; + gdat_data.data_fullpath=[gdat_data.data_fullpath ' ; _abs includes *firrat']; + end + z=mdsdata('\diagz::thomson_set_up: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 + + case {'ne_rho', 'te_rho', 'nete_rho'} + try + time=mdsdata('\results::thomson:times'); + catch + warning('Problems with \results::thomson:times') + warning(['!!!!!!!!!!!!!!!!!!!!!!!!! cannot continue with ' data_request_eff]) + return + end + if isempty(time) || ischar(time) + thomsontimes=time + warning('!!!!!!!!!!!!!!!!!!!!!!!!!\results::thomson:times is empty? Check') + disp(['!!!!!!!!!!!!!!!!!!!!!!!!! cannot continue with ' data_request_eff]) + return + end + zshift = 0.; + if isfield(gdat_data.gdat_params,'zshift') && ~isempty(gdat_data.gdat_params.zshift) + zshift = gdat_data.gdat_params.zshift; + else + gdat_data.gdat_params.zshift = zshift; + end + edge_str_ = ''; + edge_str_dot = ''; + if isfield(gdat_data.gdat_params,'edge') && ~isempty(gdat_data.gdat_params.edge) && ... + gdat_data.gdat_params.edge>0 + edge_str_ = '_edge'; + edge_str_dot = '.edge'; + end + % if nete_rho, do first ne, then Te later (so fir stuff already done) + if strcmp(data_request_eff,'ne_rho') || strcmp(data_request_eff,'nete_rho') + nodenameeff=['\results::thomson' edge_str_dot ':ne']; + tracetdi=tdi(nodenameeff); + nodenameeff=['\results::thomson' edge_str_dot ':ne; error_bar ; fir_thom_rat; (ne,std)*fir_thom_rat']; + tracestd=tdi(['\results::thomson' edge_str_dot ':ne:error_bar']); + tracefirrat_data = get_fir_thom_rat_data(shot,['thomson' edge_str_],time); + else + nodenameeff=['\results::thomson' edge_str_dot ':te']; + tracetdi=tdi(nodenameeff); + nodenameeff=['\results::thomson' edge_str_dot ':te; error_bar']; + tracestd=tdi(['\results::thomson' edge_str_dot ':te:error_bar']); + end + gdat_data.data=tracetdi.data'; % Thomson data as (t,z) + gdat_data.error_bar=tracestd.data'; + gdat_data.data_fullpath=nodenameeff; + if strcmp(data_request_eff,'ne_rho') || strcmp(data_request_eff,'nete_rho') + gdat_data.firrat=tracefirrat_data; + gdat_data.data_abs=gdat_data.data*diag(tracefirrat_data); + gdat_data.error_bar_abs=gdat_data.error_bar*diag(tracefirrat_data); + gdat_data.data_fullpath=[gdat_data.data_fullpath ' ; _abs includes *firrat']; + end + % add correct dimensions + % construct rho mesh + psi_max=tdi(['\results::thomson' edge_str_dot ':psi_max' substr_liuqe]); + psiscatvol=tdi(['\results::thomson' edge_str_dot ':psiscatvol' substr_liuqe]); + if abs(zshift)>1e-5 + % calculate new psiscatvol + psitdi=tdi(['\results::psi' substr_liuqe]); + rmesh=psitdi.dim{1}; + zmesh=psitdi.dim{2}; + zthom=mdsdata('dim_of(\thomson:te,1)'); + zeffshift=zshift; + % set zeffshift time array same as psitdi + switch length(zeffshift) + case 1 + zeffshift=zeffshift * ones(size(psitdi.dim{3})); + case length(psitdi.dim{3}) + % ok + case length(psiscatvol.dim{1}) + zeffshift=interp1(psiscatvol.dim{1},zeffshift,psitdi.dim{3}); + otherwise + disp(' bad time dimension for zshift') + disp(['it should be 1 or ' num2str(length(psiscatvol.dim{1})) ' or ' num2str(length(psitdi.dim{3}))]) + end + for it=1:length(psiscatvol.dim{1}) + itpsitdi=iround(psitdi.dim{3},psiscatvol.dim{1}(it)); + psirz=psitdi.data(:,:,itpsitdi); + psiscatvol0=griddata(rmesh,zmesh,psirz',0.9*ones(size(zthom)),zthom-zeffshift(itpsitdi)); + psiscatvol.data(it,:)=psiscatvol0; + end + end + if ~isempty(psiscatvol.data) && ~ischar(psiscatvol.data) && ~isempty(psi_max.data) && ~ischar(psi_max.data) + for ir=1:length(psiscatvol.dim{2}) + rho(ir,:)= sqrt(1.-psiscatvol.data(:,ir)./psi_max.data(:))'; + end + else + rho=NaN; + end + gdat_data.dim=[{rho};{time}]; + gdat_data.dimunits=[{'sqrt(psi)'} ; {'time [s]'}]; + gdat_data.x=rho; + gdat_data.t=time; + if any(strcmp(fieldnames(tracetdi),'units')) + gdat_data.units=tracetdi.units; + end + %%%%%%%%%%% add fitted profiles if 'fit'>=1 + if isfield(gdat_data.gdat_params,'fit') && ~isempty(gdat_data.gdat_params.fit) && ... + gdat_data.gdat_params.fit>0 + % default is from proffit:avg_time + def_proffit = '\results::proffit.avg_time'; + if isfield(gdat_data.gdat_params,'fit_type') && ~isempty(gdat_data.gdat_params.fit_type) + if strcmp(gdat_data.gdat_params.fit_type,'local') + def_proffit = '\results::proffit.local_time'; + else + gdat_data.gdat_params.fit_type = 'avg'; + end + else + gdat_data.gdat_params.fit_type = 'avg'; + end + if strcmp(data_request_eff(1:2),'ne') + nodenameeff = [def_proffit ':neft_abs']; % do first ne if nete asked for + elseif strcmp(data_request_eff(1:2),'te') + nodenameeff = [def_proffit ':teft']; + else + disp(['should not be here: data_request_eff, data_request_eff(1:2)= ',data_request_eff, data_request_eff(1:2)]); + end + if isfield(gdat_data.gdat_params,'trialindx') && ~isempty(gdat_data.gdat_params.trialindx) && ... + gdat_data.gdat_params.trialindx>=0 + nodenameeff=[nodenameeff ':trial']; + trialindx = gdat_data.gdat_params.trialindx; + else + gdat_data.gdat_params.trialindx = []; + trialindx = []; + end + tracetdi=tdi(nodenameeff); + if isempty(trialindx) + gdat_data.fit.data = tracetdi.data; + else + if ~isempty(tracetdi.data) && size(tracetdi.data,3)>=trialindx+1 + gdat_data.fit.data = tracetdi.data(:,:,trialindx+1); + else + gdat_data.fit.data = []; + gdat_data.fit.data_fullpath = [nodenameeff ' with trialindx=' num2str(trialindx) ' is empty']; + return + end + end + gdat_data.fit.x=tracetdi.dim{1}; + gdat_data.fit.t=tracetdi.dim{2}; + if mapping_for_tcv.timedim~=2 | mapping_for_tcv.gdat_timedim~=2 + disp(['unexpected timedim in fit: data_request_eff= ' data_request_eff ... + ', mapping_for_tcv.timedim= ' mapping_for_tcv.timedim ... + ', mapping_for_tcv.gdat_timedim= ' mapping_for_tcv.gdat_timedim]); + end + gdat_data.dim=tracetdi.dim(1:2); + gdat_data.dimunits=tracetdi.dimunits(1:2); + if any(strcmp(fieldnames(tracetdi),'units')) + gdat_data.fit.units=tracetdi.units; + end + gdat_data.fit.data_fullpath = nodenameeff; + % do te as well if nete asked for + if strcmp(data_request_eff(1:4),'nete') + gdat_data.fit.ne.data = gdat_data.fit.data; + gdat_data.fit.ne.units = gdat_data.fit.units; + nodenameeff = [def_proffit ':teft']; + if ~isempty(trialindx); nodenameeff=[nodenameeff ':trial']; end + tracetdi=tdi(nodenameeff); + if isempty(trialindx) + gdat_data.fit.te.data = tracetdi.data; + else + if ~isempty(tracetdi.data) && size(tracetdi.data,3)>=trialindx+1 + gdat_data.fit.te.data = tracetdi.data(:,:,trialindx+1); + else + return + end + end + if any(strcmp(fieldnames(tracetdi),'units')) + gdat_data.fit.te.units=tracetdi.units; + end + % construct pe=1.6022e-19*ne*te + gdat_data.fit.data = 1.6022e-19.*gdat_data.fit.ne.data .* gdat_data.fit.te.data; + gdat_data.fit.units = 'N/m^2; 1.6022e-19 ne Te'; + gdat_data.fit.data_fullpath = [gdat_data.fit.data_fullpath ' ; ' nodenameeff ' and pe in data']; + end + else + gdat_data.gdat_params.fit = 0; + end + %%%%%%%%%%% + % if nete_rho, copy data as .ne, get .te and put pe=e ne Te in data: + if strcmp(data_request_eff(1:4),'nete') + gdat_data.ne.data = gdat_data.data_abs; + gdat_data.ne.error_bar = gdat_data.error_bar_abs; + gdat_data.ne.firrat=gdat_data.firrat; + gdat_data.ne.units = 'm^{-3}'; + gdat_data = rmfield(gdat_data,{'firrat','data_abs','error_bar_abs'}); + % + nodenameeff=['\results::thomson' edge_str_dot ':te']; + tracetdi=tdi(nodenameeff); + nodenameeff=['\results::thomson' edge_str_dot ':te; error_bar']; + tracestd=tdi(['\results::thomson' edge_str_dot ':te:error_bar']); + gdat_data.te.data=tracetdi.data'; + gdat_data.te.error_bar=tracestd.data'; + gdat_data.te.units = tracetdi.units; + gdat_data.data_fullpath=['pe=1.6e-19*ne*Te in data, .ne, .te from \results::thomson' ... + edge_str_dot ':ne and te and projected on rhopol\_norm']; + gdat_data.units='N/m^2; 1.6022e-19 ne Te'; + gdat_data.data = 1.6022e-19 .* gdat_data.ne.data .* gdat_data.te.data; + gdat_data.error_bar = 1.6022e-19 .* (gdat_data.ne.data .* gdat_data.te.error_bar ... + + gdat_data.te.data .* gdat_data.ne.error_bar); + end + + case {'powers'} + % note: same time array for all main, ec, ohm, nbi, ... + % At this stage fill just ech, later add nbi + nodenameeff='\results::toray.input:p_gyro'; + tracetdi=tdi(nodenameeff); + gdat_data.ec.data = tracetdi.data*1e3; % at this stage p_gyro is in kW' + gdat_data.ec.units = 'W'; + gdat_data.ec.dim=tracetdi.dim; + gdat_data.ec.dimunits=tracetdi.dimunits; + gdat_data.ec.t=tracetdi.dim{1}; + gdat_data.ec.x=tracetdi.dim{2}; + gdat_data.ec.data_fullpath=[nodenameeff]; + gdat_data.ec.label='P_{EC}'; + % set ec time as reference + gdat_data.t = gdat_data.ec.t; + gdat_data.dim{1} = gdat_data.t; + gdat_data.dimunits{1} = 's'; + gdat_data.units = 'W'; + + % get ohmic power simply from vloop*Ip (minus sign for TCV) + ip=gdat([],'ip'); + vloop=gdat([],'vloop'); + tension = -1e5; + vloop_smooth=interpos(vloop.t,vloop.data,gdat_data.t,tension); + ip_t = interp1(ip.t,ip.data,gdat_data.t); + gdat_data.ohm.data = -vloop_smooth.*ip_t; + gdat_data.ohm.units = 'W'; + gdat_data.ohm.dim=gdat_data.dim; + gdat_data.ohm.dimunits=gdat_data.dimunits; + gdat_data.ohm.t=gdat_data.t; + gdat_data.ohm.x=[]; + gdat_data.ohm.data_fullpath=['-vloop(tens=' num2str(tension,'%.0e') ')*ip, from gdat']; + gdat_data.ohm.label='P_{OHM}'; + + % total power from each and total + gdat_data.data(:,1) = gdat_data.ohm.data; + gdat_data.data(:,2) = gdat_data.ec.data(:,10); + gdat_data.data(:,3) = gdat_data.ec.data(:,10) + gdat_data.ohm.data; + gdat_data.dim{2} = [1:3]; + gdat_data.dimunits{2} = 'Pohm;Pec;Ptot'; + gdat_data.data_fullpath=['tot power from EC and ohm']; + gdat_data.label = 'P_{ohm};P_{EC};P_{tot}'; + + case {'q_rho'} + % q profile on psi from liuqe + nodenameeff=['\results::q_psi' substr_liuqe]; + if liuqe_version==-1 + nodenameeff=[begstr 'q_psi' substr_liuqe]; + end + tracetdi=tdi(nodenameeff); + gdat_data.data = tracetdi.data; + gdat_data.dim = tracetdi.dim; + gdat_data.t = gdat_data.dim{2}; + gdat_data.data_fullpath=[nodenameeff ' on rhopol']; + rhopol_eff = ones(size(tracetdi.dim{1})); + rhopol_eff(:) = sqrt(linspace(0,1,length(tracetdi.dim{1}))); + gdat_data.dim{1} = rhopol_eff; + gdat_data.x = gdat_data.dim{1}; + gdat_data.dimunits{1} = ''; + gdat_data.dimunits{2} = 's'; + gdat_data.units = ''; + gdat_data.request_description = 'q(rhopol\_norm)'; + + case {'psi_edge'} + % psi at edge, 0 by construction in Liuqe, thus not given + nodenameeff=['\results::psi_axis' substr_liuqe]; + if liuqe_version==-1 + nodenameeff=[begstr 'q_psi' substr_liuqe]; + end + tracetdi=tdi(nodenameeff); + gdat_data.data = tracetdi.data.*0; + gdat_data.dim = tracetdi.dim; + gdat_data.t = gdat_data.dim{1}; + gdat_data.data_fullpath=[' zero ']; + gdat_data.dimunits = tracetdi.dimunits; + gdat_data.units = tracetdi.units; + gdat_data.request_description = '0 since LIUQE construct psi to be zero at LCFS'; + + case {'rhotor_edge','rhotor'} + % Phi(LCFS) = int(Bphi dSphi), can use Eq.(11) of "Tokamak coordinate conventions: COCOS" paper: + % O. Sauter, S.Yu. Medvedev, Comput. Phys. Commun. 184 (2013) 293–302 + % since cocos=17 for LIUQE we get: + % q = -dPhi/dpsi => Phi = - int(q*dpsi) which should always have the sign of B0 + params_eff = gdat_data.gdat_params; + params_eff.data_request='q_rho'; + q_rho=gdat_tcv([],params_eff); + params_eff.data_request='psi_axis'; % psi_edge=0 with LIUQE + psi_axis=gdat_tcv([],params_eff); + params_eff.data_request='b0'; % psi_edge=0 with LIUQE + b0=gdat_tcv([],params_eff); + b0tpsi = interp1(b0.t,b0.data,psi_axis.t); %q_rho on same time base as psi_axis + if isempty(psi_axis.data) || isempty(psi_axis.dim) || isempty(q_rho.data) || isempty(q_rho.dim) + warning(['problems loading data for ' nodenameeff ' for data_request= ' data_request_eff]) + return + end + rhoequal = linspace(0,1,length(q_rho.dim{1})); + if strcmp(data_request,'rhotor_edge') + gdat_data.data = psi_axis.data; % to have the dimensions correct + gdat_data.dim = psi_axis.dim; + gdat_data.t = gdat_data.dim{1}; + gdat_data.data_fullpath='phi from q_rho, psi_axis and integral(-q dpsi)'; + gdat_data.units = 'T m^2'; + gdat_data.dimunits{1} = 's'; + elseif strcmp(data_request,'rhotor') + gdat_data.data = q_rho.data; % to have the dimensions correct + gdat_data.dim{1} = ones(size(q_rho.dim{1})); + gdat_data.dim{1}(:) = rhoequal; + gdat_data.dim{2} = q_rho.dim{2}; + gdat_data.t = gdat_data.dim{2}; + gdat_data.data_fullpath='sqrt(phitor/phitor_edge), rhotor_edge=sqrt(phitor/B0/pi)'; + gdat_data.units = ''; + gdat_data.dimunits{1} = 'rhopol\_norm'; + gdat_data.dimunits{2} = 's'; + end + for it=1:length(psi_axis.data) + ij=find(~isnan(q_rho.data(:,it))); + if ~isempty(ij) + [qfit,~,~,phi]=interpos(q_rho.x(ij).^2,q_rho.data(ij,it),rhoequal.^2); + dataeff = sqrt(phi .* psi_axis.data(it) ./ b0tpsi(it) ./ pi) ; % Delta_psi = -psi_axis + else + dataeff = NaN; + end + if strcmp(data_request,'rhotor_edge') + gdat_data.data(it) = dataeff(end); + elseif strcmp(data_request,'rhotor') + gdat_data.data(:,it) = dataeff./dataeff(end); + gdat_data.rhotor_edge(it) = dataeff(end); + end + gdat_data.b0 = b0tpsi(it); + end + + case {'rhovol','volume_rho','volume'} + % volume_rho = vol(rho); volume = vol(LCFS) = vol(rho=1); + % rhovol = sqrt(vol(rho)/vol(rho=1)); + nodenameeff='\results::psitbx:vol'; + if liuqe_version==-1 + nodenameeff=[begstr 'vol' substr_liuqe]; + end + tracetdi=tdi(nodenameeff); + if isempty(tracetdi.data) || isempty(tracetdi.dim) + return + end + gdat_data.units = tracetdi.units; + if strcmp(data_request,'volume') + gdat_data.data = tracetdi.data(end,:); + gdat_data.dim{1} = tracetdi.dim{2}; + gdat_data.data_fullpath=['\results::psitbx:vol(end,:)']; + gdat_data.dimunits{1} = tracetdi.dimunits{2}; + gdat_data.request_description = 'volume(LCFS)=volume(rhopol=1)'; + else + gdat_data.data = tracetdi.data; + gdat_data.dim = tracetdi.dim; + gdat_data.dimunits = tracetdi.dimunits; + if strcmp(data_request,'volume_rho') + gdat_data.data_fullpath=['\results::psitbx:vol']; + gdat_data.request_description = 'volume(rho)'; + elseif strcmp(data_request,'rhovol') + gdat_data.volume_edge = gdat_data.data(end,:); + gdat_data.data = sqrt(gdat_data.data./repmat(reshape(gdat_data.volume_edge,1,size(gdat_data.data,2)),size(gdat_data.data,1),1)); + gdat_data.data_fullpath='sqrt(\results::psitbx:vol/vol_edge)'; + gdat_data.request_description = 'sqrt(volume(rho)/volume(edge))'; + else + disp(['should not be here in vol cases with data_request = ' data_request_eff]); + return + end + end + gdat_data.t = gdat_data.dim{mapping_for_tcv.gdat_timedim}; + + case {'sxr'} + % sxr from Xtomo by default or dmpx if 'camera','dmpx' is provided + + case {'profnerho','profterho'} + % for backward compatibility but corresponds to ne_rho with param.fit_type='auto' (TCV special) + % + nodenameeff=['\results::THOMSON.PROFILES.AUTO:' data_request_eff(5:6)]; + nodenameeff_vers = [nodenameeff ':version_num']; + avers = tdi(nodenameeff_vers); + if avers.data==0 + % may be because nodes not yet filled in, so call once a node + ab=tdi(nodenameeff); + avers = tdi(nodenameeff_vers); + end + if avers.data>0 + tracetdi=tdi(nodenameeff); + if avers.data < 2.99 + % for earlier version the bug made it to have logically (rho,t) + gdat_data.data=tracetdi.data; + if ~isempty(tracetdi.dim) && ~ischar(tracetdi.data) + gdat_data.x=tracetdi.dim{1}; + gdat_data.t=tracetdi.dim{2}; + error_status=0; + else + error_status=2; + gdat_data.x=[]; + gdat_data.t=[]; + end + else + gdat_data.data=tracetdi.data'; % error in dimensions for autofits + if ~isempty(tracetdi.dim) && ~ischar(tracetdi.data) + if nverbose>=3; disp('assumes dim{2} for x in THOMSON.PROFILES.AUTO'); end + gdat_data.x=tracetdi.dim{2}; + gdat_data.t=tracetdi.dim{1}; + error_status=0; + else + gdat_data.x=[]; + gdat_data.t=[]; + error_status=2; + end + end + else + tracetdi=avers; + gdat_data.x=[]; + gdat_data.t=[]; + end + gdat_data.dim=[{gdat_data.x};{gdat_data.t}]; + gdat_data.dimunits=[{'sqrt(psi\_norm)'} ; {'time [s]'}]; + if ~isempty(gdat_data.t) && any(strcmp(fieldnames(tracetdi),'units')) + gdat_data.units=tracetdi.units; + end + gdat_data.request_description = 'quick autofits within thomson nodes, using version'; + gdat_data.fullpath = ['Thomson autfits from ' nodenameeff]; + + otherwise + warning(['switchcase= ' data_request_eff ' not known in gdat_tcv']) + error_status=901; + return + end + +else + warning(['TCV method=' mapping_for_tcv.method ' not known yet, contact Olivier.Sauter@epfl.ch']) + error_status=602; + return +end + +if ishot==shot; mdsclose; end + +gdat_data.mapping_for.tcv = mapping_for_tcv; +error_status=0; + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [firthomratio] = get_fir_thom_rat_data(shot,maintracename,timebase); +% +% 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) + disp('need a timebase in get_fir_thom_rat_data') + 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) + disp('problem with \results::thomson.profiles.auto:fir_thom_rat: empty, use thomson:fir_thom_rat') + tracefirrat=tdi('\results::thomson:fir_thom_rat'); + end + else + tracefirrat=tdi('\results::thomson:fir_thom_rat'); + if isempty(tracefirrat.data) || ischar(tracefirrat.data) + disp('problem with \results::thomson:fir_thom_rat: empty') + 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) + disp('problem with \results::thomson.profiles.auto:fir_thom_rat: empty, use thomson:fir_thom_rat') + tracefirrat=tdi('\results::thomson:fir_thom_rat'); + end + else + tracefirrat=tdi('\results::thomson_edge:fir_thom_rat'); + if isempty(tracefirrat.data) || ischar(tracefirrat.data) + disp('problem with \results::thomson_edge:fir_thom_rat: empty') + end + end +else + disp('bad input in get_fir_thom_rat_data') + return +end + +if ~isempty(tracefirrat.data) || ischar(tracefirrat.data) + firthomratio = interp1(tracefirrat.dim{1},tracefirrat.data,timebase); +end + diff --git a/crpptbx/TCV/tcv_requests_mapping.m b/crpptbx/TCV/tcv_requests_mapping.m new file mode 100644 index 0000000000000000000000000000000000000000..94fe43f84ec911e3a1ac24f2eb73dcf8a9b20ad6 --- /dev/null +++ b/crpptbx/TCV/tcv_requests_mapping.m @@ -0,0 +1,275 @@ +function mapping = tcv_requests_mapping(data_request) +% +% Information pre-defined for gdat_tcv, you can add cases here to match official cases in gdat_tcv, allowing backward compatibility +% + +% Defaults +mapping = struct(... + 'label', '', ... + 'method', '', ... + 'expression','', ... + 'timedim', -1, ... % dim which is the time is the database, to copy in .t, the other dims are in .x (-1 means last dimension) + 'gdat_timedim',[], ... % if need to reshape data and dim orders to have timedim as gdat_timedim (shifting time to gdat_timedim) + 'min', -inf, ... + 'max', inf); +% Note that gdat_timedim is set to timedim at end of this function if empty +% gdat_timedim should have effective index of the time dimension in gdat + +if ~exist('data_request') || isempty(data_request) + return +end + +% default label: data_request keyword itself +mapping.label = data_request; + +% for TCV, following choices are set so far: +% method = 'tdi' and then expression is the string within tdi (usual case when there is a direct link to an existing signal) +% with tdi, if expression cell array, call tdi(cell{1},cell{2},...) +% method = 'tdiliuqe': same as tdi but adds "_2" or "_3" if 'liuqe',2 or 3 is asked for in options +% method = 'expression', then expression is executed and it should provide the structure gdat_tmp, which fields are copied to gdat_data +% method = 'switchcase', then there will be a specific case within gdat_tcv (usual case when not directly a signal) +% +% label is used for plotting +switch lower(data_request) + case 'a_minor' + mapping.timedim = 1; + mapping.label = 'a(LCFS)'; + mapping.method = 'switchcase'; + mapping.expression = ''; + case 'b0' + mapping.timedim = 1; + mapping.label = 'B_0'; + mapping.method = 'switchcase'; + mapping.expression = ''; + case 'beta' + mapping.timedim = 1; + mapping.label = '\beta'; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::beta_tor'; + case 'betan' + mapping.timedim = 1; + mapping.label = '\beta_N'; + mapping.method = 'switchcase'; + mapping.expression = ''; + case 'betap' + mapping.timedim = 1; + mapping.label = '\beta_p'; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::beta_pol'; + case 'cxrs' + mapping.timedim = 2; + mapping.label = 'cxrs'; + mapping.method = 'switchcase'; + mapping.expression = ''; + case 'delta' + mapping.timedim = 1; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::delta_edge'; + % mapping.method = 'expression'; + % mapping.expression = ['tdi(''\results::q_psi'');']; % for tests + case 'delta_bottom' + mapping.timedim = 1; + mapping.label = 'delta\_bottom'; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::delta_ed_bot'; + case 'delta_top' + mapping.timedim = 1; + mapping.label = 'delta\_top'; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::delta_ed_top'; + case 'ece' + mapping.timedim = 2; + mapping.method = 'switchcase'; + mapping.expression = ''; + case 'eqdsk' + mapping.timedim = 0; + mapping.method = 'switchcase'; % could use function make_eqdsk directly? + mapping.expression = ''; + case 'halpha' + mapping.timedim = 1; + mapping.label = 'Halpha'; + mapping.method = 'tdi'; + mapping.expression = '\base::pd:pd_011'; + case 'ioh' + mapping.timedim = 1; + mapping.label = 'I ohmic transformer'; + mapping.method = 'tdi'; + mapping.expression = [{'\magnetics::ipol[*,$1]'} {'OH_001'}]; + case 'ip' + mapping.timedim = 1; + mapping.label = 'Plasma current'; + mapping.method = 'tdi'; + mapping.expression = '\magnetics::iplasma:trapeze'; + case 'kappa' + mapping.timedim = 1; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::kappa_edge'; + case 'mhd' + mapping.timedim = 1; + mapping.label = 'n=1,2, etc'; + mapping.method = 'switchcase'; + mapping.expression = ''; + case 'ne' + mapping.timedim = 2; + mapping.method = 'switchcase'; + case 'neint' + mapping.timedim = 1; + mapping.label = 'line integrated el. density'; + mapping.method = 'tdi'; + mapping.expression = '\results::fir:lin_int_dens'; + case 'nel' + mapping.timedim = 1; + mapping.label = 'line-averaged el. density'; + mapping.method = 'tdi'; + mapping.expression = '\results::fir:n_average'; + case 'ne_rho' + mapping.timedim = 2; + mapping.label = 'ne'; + mapping.method = 'switchcase'; + case 'neft' + mapping.timedim = 2; + mapping.label = 'ne'; + mapping.method = 'expression'; + mapping.expression = ['params_eff = gdat_data.gdat_params;params_eff.data_request=''ne_rho''; ' ... + 'params_eff.fit=1;params_eff.fit_type=''avg'';gdat_tmp=gdat_tcv([],params_eff);']; + case 'nete_rho' + mapping.timedim = 2; + mapping.label = 'ne and Te'; + mapping.method = 'switchcase'; + case 'ni' + mapping.timedim = 2; + mapping.method = 'switchcase'; % especially since might have option fit, etc + case 'powers' + mapping.timedim = 1; + mapping.label = 'various powers'; + mapping.method = 'switchcase'; + case 'psi_axis' + mapping.timedim = 1; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::psi_axis'; + case 'psi_edge' + mapping.timedim = 1; + mapping.method = 'switchcase'; % is set to zero, so not in tree nodes + mapping.label = 'psi\_edge'; + case 'q0' + mapping.timedim = 1; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::q_zero'; + case 'q95' + mapping.timedim = 1; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::q_95'; + case 'qedge' + mapping.timedim = 1; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::q_edge'; + case 'q_rho' + mapping.timedim = 2; + mapping.label = 'q'; + mapping.method = 'switchcase'; + case 'r_contour' + mapping.timedim = 1; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::r_contour'; + case 'rgeom' + mapping.timedim = 1; + mapping.label = 'Rgeom'; + mapping.method = 'switchcase'; + case 'rhotor_edge' + mapping.timedim = 1; + mapping.label = 'rhotor\_edge=sqrt(Phi/pi/B0)'; + mapping.method = 'switchcase'; % from conf if exist otherwise computes it + case 'rhotor' + mapping.timedim = 2; + mapping.label = 'rhotor\_norm'; + mapping.method = 'switchcase'; % from conf if exist otherwise computes it + case 'rhovol' + mapping.timedim = 2; + mapping.label = 'rhovol\_norm'; + mapping.method = 'switchcase'; % from conf if exist otherwise computes it + case 'rmag' + mapping.timedim = 1; + mapping.label = 'R\_magaxis'; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::r_axis'; + case 'sxr' + mapping.timedim = 2; + mapping.method = 'switchcase'; + case 'te' + mapping.timedim = 2; + mapping.label = 'Te'; + mapping.method = 'switchcase'; + case 'te_rho' + mapping.timedim = 2; + mapping.label = 'Te'; + mapping.method = 'switchcase'; + case 'teft' + mapping.timedim = 2; + mapping.label = 'ne'; + mapping.method = 'expression'; + mapping.expression = ['params_eff = gdat_data.gdat_params;params_eff.data_request=''te_rho''; ' ... + 'params_eff.fit=1;params_eff.fit_type=''avg'';gdat_tmp=gdat_tcv([],params_eff);']; + case 'ti' + mapping.timedim = 2; + mapping.label = 'Ti'; + mapping.method = 'switchcase'; + case 'transp' + mapping.label = 'transp output'; + mapping.method = 'switchcase'; + case 'vloop' + mapping.timedim = 1; + mapping.label = 'Vloop'; + mapping.method = 'tdi'; + mapping.expression = [{'\magnetics::vloop[*,$1]'} {'001'}]; + case 'volume' + mapping.timedim = 1; + mapping.label = 'Volume\_LCFS'; + mapping.method = 'switchcase'; + case 'volume_rho' + mapping.timedim = 2; + mapping.label = 'Volume(\rho)'; + mapping.method = 'switchcase'; + % mapping.expression = '\results::psitbx:vol'; (if exists for liuqe2 and 3 as well) + case 'z_contour' + mapping.timedim = 1; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::z_contour'; + case 'zeff' + mapping.timedim = 1; + mapping.label = 'zeff from Ip-Ibs'; + mapping.method = 'tdi'; + mapping.expression = '\results::ibs:z_eff'; + case 'zgeom' + mapping.timedim = 1; + mapping.label = 'Zgeom'; + mapping.method = 'switchcase'; + case 'zmag' + mapping.timedim = 1; + mapping.label = 'Zmagaxis'; + mapping.method = 'tdiliuqe'; + mapping.expression = '\results::z_axis'; + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % extra TCV cases (not necessarily in official data_request name list) + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + case {'profnerho','profterho'} + mapping.timedim = 1; + mapping.label = data_request; + mapping.method = 'switchcase'; + mapping.expression = ''; + +% $$$ case '' +% $$$ mapping.timedim = 1; +% $$$ mapping.label = data_request; +% $$$ mapping.method = 'tdi'; +% $$$ mapping.expression = ''; + otherwise + mapping.label = data_request; + mapping.method = 'tdi'; % assume a full tracename is given, so just try with tdi (could check there are some ":", etc...) + mapping.expression = data_request; + +end + +if isempty(mapping.gdat_timedim) + mapping.gdat_timedim = mapping.timedim; +end diff --git a/crpptbx/gdat.m b/crpptbx/gdat.m index 2b718b38224b5c4f7f95e7b90a12a981adf94fe4..5b4804f92047887a358ae9e08a254817341d9e6c 100644 --- a/crpptbx/gdat.m +++ b/crpptbx/gdat.m @@ -1,206 +1,181 @@ -function [trace,error,varargout] = gdat(shot,data_type,varargin) +function [gdat_data,gdat_params,error_status,varargout] = gdat(shot,data_request,varargin) % -% function [trace,error,varargout] = gdat(shot,data_type,varargin) +% function [gdat_data,gdat_params,error_status,varargout] = gdat(shot,data_request,varargin) % -% new: no args or with shot=-9 to get keywords relevant for the related experiment -% keywordlist=gdat; (for the default machine) -% keywordlist=gdat(-9,[],'machine'); (for the specific machine) +% Aim: get data from a given machine using full path or keywords. +% Keywords should be the same for different machines, otherwise add "_machinname" to the keyword if specific +% Keywords are and should be case independent (transformed in lower case in the function and outputs) % -% varargin{1}: 0 => no plot (default), 1 => plot (see special case for old JET style below) -% varargin{2}: machine name 'AUG', 'JET' , 'TCV' (default: depending on where implemented) +% If no inputs are provided, return the list of available keywords in gdat_data and default parameters gdat_params % -% list of data_type currently available: +% Inputs: % -% (almost) All machines -% 'Ip' = current -% 'zmag' = vertical position of the center of the plasma (magnetic axis) -% 'rmag' = radial position of the center of the plasma -% 'rcont' = R of plama boundary vs time -% 'zcont' = Z of plama boundary vs time -% 'vol' = volume of flux surfaces vs rho=sqrt(psi) -% 'qrho' = q profile on rho mesh -% 'q95' = q95 vs time -% 'kappa', 'elon' = edge elongation vs time -% 'delta', 'triang' = edge averaged triangularity vs time -% 'deltatop', 'triangtop' = edge upper (top) triangularity vs time -% 'deltabot', 'triangbot' = edge lower (bottom) triangularity vs time -% 'neint' = line-integrated electron density [m/m^3] -% 'ne'= ne raw profile on (z,t). ADD error bars in .std -% 'te'= Te raw profile on (z,t). ADD error bars in .std -% 'nerho'= ne profile on (rho=sqrt(psi),time) mesh.Note rho is a 2D array as depends on time. ADD error bars in .std -% 'terho'= Te profile on (rho=sqrt(psi),time) mesh.Note rho is a 2D array as depends on time. ADD error bars in .std -% 'ece' = electron cyclotron emission -% 'sxr' = soft x-ray emission -% 'sxR' = soft x-ray emission with varargout{1} option (requires varargin{5}!) -% 'Halpha' = H(D)-alpha trace +% no inputs: return default parameters in a structure form in gdat_params +% shot: shot number +% 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','TCV' (the default machine is the local machine) % -% specific to TCV (see help loadTCVdata for more information) -% 'xx_2 or xx_3' for Liuqe2 or 3: same as above for xx related to equilibrium -% 'vol' = volume of flux surfaces -% 'profnerho' = ne smoothed or fitted , vs (rho,t) (from Thomson fit) -% 'profterho' = te smoothed or fitted , vs (rho,t) (from Thomson fit) -% 'neft' = ne fitted from data on rho mesh (from proffit.local_time:neft) -% 'teft' = te fitted from data on rho mesh (from proffit.local_time:teft) -% 'neftav' = ne fitted from averaged over time data on rho mesh (from proffit.avg_time:neft) -% 'teftav' = te fitted from averaged over time data on rho mesh (from proffit.avg_time:teft) -% 'ece' = electron cyclotron emission -% 'sxr' = soft x-ray emission -% 'sxR' = soft x-ray emission with varargout{1} option (requires varargin{4}!) -% 'MPX' = soft x-ray from wire chambers -% 'vtor' = toroidal rotation, raw data and arror bars -% 'vtorfit' = fitted toroidal rotation profiles (and error bars) -% 'vpol' = poloidal rotation, raw data and arror bars -% 'vpolfit' = fitted poloidal rotation profiles (and error bars) -% 'Ti' (or Tc), 'Tifit', 'ni' (or nC), 'nifit', 'zeffcxrs', 'zeffcxrsfit': similar to 'vtor' from CXRS % -% JET -% Special case compatible with old gdat.m allows (JET related): gdat(51994,'ppf','efit/xip',1) +% Outputs: % -% INPUT: +% 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 expression, or relevant function called if relevant +% gdat_data.gdat_params: copy gdat_params for completeness +% gdat_data.xxx: any other relevant information % -% shot: shot number -% data_type: type of the required data.( see above) -% -% optional arguments valid for all values of data_type (not passed on to loadMACHINEdata function): -% -% Additional input arguments for specific traces (passed on to loadMACHINEdata function) -% -% data_type=sxr or ece: -% varargin{3}: [i1 i2] : if not empty, assumes need many chords from i1 to i2 -% varargin{4}: channel status 1= unread yet, 0= read -% (for traces with many channel, enables to load additional channels, -% like SXR, ECE, etc.) -% varargin{5}: zmag for varargout{1} computation -% -% OUTPUT: -% -% trace: structure containing data and meshes (compatible with tdi main structure) -% trace.data: data -% trace.t: time of reference -% trace.x: space of reference -% trace.dim: cell array of grids, trace.dim{1}, {2}, ... -% trace.dimunits: units of dimensions -% trace.std: if error bars are available -% -% error: error in loading signal (0=> OK, >=1 => error) -% -% Additional Output arguments depending on data_type -% -% data_type=sxR: -% varargout{1}: intersection of the view lines with magnetic axis -% data_type=MPX: (specific to TCV) -% varargout{1}: see help loadTCVdata -% -% -% functions needed: loadAUGdata, loadJETdata, loadTCVdata -% % % Examples: -% [zmag,error]=gdat(shot,'zmag',1); % gets zmag from TCV and plot -% [zmag,error]=gdat(shot,'zmag',1,'JET'); % idem but from JET -% [zmag,error]=gdat(shot,'ppf','efit/zmag',1); as above for JET +% (should add working examples for various machines (provides working shot numbers for each machine...)) +% +% [a1,a2]=gdat; +% a2.data_request = 'Ip'; +% 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,'ip'); % standard call +% a6=gdat(48836,'ip','Opt1',123,'Doplot',1,'opt2','Abc'); % standard call with a few options (all lowercase in output) + + % -% keywordlist=gdat(-9,[],[],machine); % to get examples and the keywords defined for the relevant machine -% keywordlist=gdat; % to get examples and the keywords defined for the local machine +% Comments for local developer: +% This 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 % -gdatpaths +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Prepare some variables, etc -nargineff=nargin; -if nargineff>=3 & ischar(varargin{1}) -% $$$ if isempty(strmatch(upper(varargin{1}),[{'TCV'} {'JET'} {'AUG'}])) - % old JET way with second part of data structure in varagin{1} - data_type={data_type ; varargin{1}}; - if nargineff>=4; - varargin{1}=varargin{2}; - else - varargin{1}=0; - nargineff=4; +% for backward compatibility (with most recent simple call ala: gdat(shot,'data_request',doplot,machine) ) +% if nargin<=4 and >2 and 1st and 3rd are numeric, assume this is an old call and transform it to: +% gdat(shot,'data_request','doplot',doplot','machine',machine) +% and a warning +if nargin>2 + varargin_eff = varargin; + if nargin>=3 && nargin<=4 && isnumeric(shot) && isnumeric(varargin{1}) + % assume old call: gdat(shot,'data_request',doplot[,machine]) + varargin_eff{1} = 'doplot'; + varargin_eff{end+1} = varargin{1}; + if nargin==4 + varargin_eff{end+1} = 'machine'; + varargin_eff{end+1} = varargin{2}; + end end - varargin{2}='JET'; -% $$$ end -end - -% SETTING MACHINE -doplot=0; -if (nargineff>=3 & ~isempty(varargin{1})); doplot=varargin{1}; end -a=which('gdat'); -if ~isempty(findstr('ipp',a)) | ~isempty(findstr('/u/osauter',a)); - machine='AUG'; - global usemdsplus; % so far from AUG, do not use mdsplus - usemdsplus=0; -elseif ~isempty(findstr('/home/osauter',a)); - machine='JET'; -elseif ~isempty(findstr('/home/sauter',a)); - machine='TCV'; -elseif ~isempty(findstr('/u/sauter',a)); - machine='D3D'; -end -if ~exist('machine') - % disp('did not find machine, set it to TCV') - machine='TCV'; end -if (nargineff>=4 & ~isempty(varargin{2})); machine=varargin{2}; end -%machine -% load data from specified machine -if ~exist('data_type'); data_type=[]; end -if ~exist('shot') || isempty(shot); shot=-9; end -if nargineff<=4 - eval(['[trace,error,varargout] = load' machine 'data(shot,data_type);']); +% construct default parameters structure +gdat_params.data_request = ''; +fusion_machine_defaultname=getenv('FUSION_MACHINE_DEFAULTNAME'); +default_machine = ''; +if ~isempty(fusion_machine_defaultname) + default_machine = lower(fusion_machine_defaultname); else - eval(['[trace,error,varargout] = load' machine 'data(shot,data_type,varargin{3:end});']); + hostname=getenv('HOSTNAME'); + if ~isempty(regexpi(hostname,'epfl')) + default_machine = 'tcv'; + elseif ~isempty(regexpi(hostname,'rzg.mpg')) + default_machine = 'aug'; + end end +machine_eff = default_machine; -% PLOT DATA (if required) -if doplot~=0; set_defaults_matlab; end -if doplot==1 && isfield(trace,'data') && length(trace.data)>1 && ~ischar(trace.data) - try - figure;zoom on - if length(size(trace.data))<=2 - hhh=plot(trace.t,trace.data); - ylabel(data_type) - else - for idim=1:length(trace.dim) - if length(trace.t)==length(trace.dim{idim}); idim_t=idim; end - end - if idim_t<=2 - hhh=plot(trace.t,trace.data(:,:,floor(end/2))); - ylabel([data_type '(:,:,floor(end/2))']) - elseif idim_t==3; - hhh=plot(trace.t,reshape(trace.data(:,floor(end/2),:),length(trace.dim{1}),length(trace.t))); - ylabel([data_type '(:,floor(end/2),:)']) +% do not treat inputs here but in subsequent gdat_machine.m function, however, need to extract machine name if provided: +if nargin>=2 % need at least 2 inputs to have 'machine','aug' as arguments (to ask specific list of requests) + % in case start directly with pairs of options + if ischar(shot) && ischar(data_request) + machine_eff = data_request; + elseif isstruct(shot) && isfield(shot,'machine') + machine_eff = shot.machine; + elseif isstruct(data_request) && isfield(data_request,'machine') + machine_eff = data_request.machine; + elseif nargin>=3 + imachine=[]; + for i=1:length(varargin_eff) + if ischar(varargin_eff{i}) + ii = strmatch(varargin_eff{i},'machine','exact'); + if ~isempty(ii); imachine = i; end end end - xlabel('time [s]') - title([machine ' ' num2str(shot)]) - grid on - catch - disp(' error in plotting part, most probably because could not guess time dimension correctly. To check') + if ~isempty(imachine) && length(varargin_eff)>=imachine+1 && ~isempty(varargin_eff{imachine+1}) + machine_eff = varargin_eff{imachine+1}; + end + end +end + +% add paths to each machine which are in subdirectory of gdat and working +% add only given machine directory using machine_eff... +gdat_path = mfilename('fullpath'); +eval(['addpath ' gdat_path(1:end-4) upper(machine_eff)]); + +% copy gdat present call: +if nargin==0 + subcall=['gdat;']; +elseif nargin>=1 + if isnumeric(shot) + subcall=['gdat(' num2str(shot) ]; + elseif ischar(shot) + subcall=['gdat(' shot ]; + else + warning('type of 1st argument unexpected, should be numeric or char') + gdat_data.gdat_call = []; + return end -elseif doplot==-1 - try - hold all - child_h=get(gca,'child'); - nbplot=length(child_h); - if length(size(trace.data))<=2 - hhh=plotos(trace.t,trace.data,'-',[],[],colos(mod(nbplot,12)+1,:)); + if nargin>=2 + if isempty(data_request) + subcall = [subcall ',[]']; else - hhh=plot(trace.t,trace.data(:,:,1),'--'); + substring = subcall_all2str(data_request); + subcall = [subcall substring]; + end + if nargin>=3 + substring = subcall_all2str(varargin_eff{:}); + subcall = [subcall substring]; end - catch - disp(' error in plotting part, most probably because could not guess time dimension correctly. To check') end + % ... to continue + subcall = [subcall ');']; end +% Note: would need to check nargout to make call consistent, but to avoid this, each gdat_xxx should return at least an empty varargout: varargout{1}=cell(1); try - if exist('hhh') && ishandle(hhh(end)); set(hhh(end),'Tag',['gdat: ' num2str(shot)]); end + if nargin==0 + eval(['[gdat_data,gdat_params,error_status,varargout] = gdat_' lower(machine_eff) ';']); + elseif nargin==1 + eval(['[gdat_data,gdat_params,error_status,varargout] = gdat_' lower(machine_eff) '(shot);']); + elseif nargin==2 + eval(['[gdat_data,gdat_params,error_status,varargout] = gdat_' lower(machine_eff) '(shot,data_request);']); + else + eval(['[gdat_data,gdat_params,error_status,varargout] = gdat_' lower(machine_eff) '(shot,data_request,varargin_eff{:});']); + end catch + warning(['problems calling gdat_' lower(machine_eff)]); + return end -if doplot~=0 - h2=findobj(gca,'-regexp','Tag','gdat:*'); - if ~isempty(h2); - legend(get(sort(h2),'Tag')); +% copy subcall here so is last subnode +gdat_data.gdat_call = [subcall ' % nargout = ' num2str(nargout)]; + +if ~isfield(gdat_data.gdat_params,'doplot') + gdat_data.gdat_params.doplot = 0; +end + +if gdat_data.gdat_params.doplot + % plot gdat_data versus 1st dim by default, if nb_dims<=2, otherwise do not plot + if length(varargout)==0 || isempty(varargout{1}) + varargout{1} = gdat_plot(gdat_data); % return handle to figure + else + varargout{end+1} = gdat_plot(gdat_data); % return handle to figure end end diff --git a/crpptbx/gdat_data_request_names_rho.xlsx b/crpptbx/gdat_data_request_names_rho.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..74f47e6263dadbe5c0879ab7e22d0c00441094c4 Binary files /dev/null and b/crpptbx/gdat_data_request_names_rho.xlsx differ diff --git a/crpptbx/gdat_plot.m b/crpptbx/gdat_plot.m new file mode 100644 index 0000000000000000000000000000000000000000..04a3c9b4c4a07e91d50ea8400cd1ccfc36019fb7 --- /dev/null +++ b/crpptbx/gdat_plot.m @@ -0,0 +1,41 @@ +function [fighandle]=gdat_plot(gdat_data,varargin); +% +% choices from doplot in gdat_data.gdat_params.doplot: +% doplot = 0: no plot +% = 1: new figure created +% = -1: add to current figure (with hold all) +% > 1: create new figure with this number, adding clf +% <-1: add to figure number abs(doplot) (with hold all) +% +if ~isfield(gdat_data.gdat_params,'doplot') || gdat_data.gdat_params.doplot ==0 + return +end + +fighandle = get(0,'CurrentFigure'); + +if prod(isfield(gdat_data,{'data','t'})) && ~isempty(gdat_data.data) && ~isempty(gdat_data.t) + if gdat_data.gdat_params.doplot == 1 + fighandle = figure; + elseif gdat_data.gdat_params.doplot > 1 + fighandle = figure(gdat_data.gdat_params.doplot); + clf; + elseif gdat_data.gdat_params.doplot == -1 + hold all + elseif gdat_data.gdat_params.doplot < -1 + fighandle = figure(abs(gdat_data.gdat_params.doplot)); + hold all + end + if any(find(size(gdat_data.data)==length(gdat_data.t))) + plot(gdat_data.t,gdat_data.data); + title([gdat_data.gdat_params.machine ' #' num2str(gdat_data.shot)]); + if isfield(gdat_data,'mapping_for') + xlabel(['time [' gdat_data.dimunits{gdat_data.mapping_for.(gdat_data.gdat_params.machine).gdat_timedim} ']']); + else + xlabel(['time']); + end + ylabel([gdat_data.label '[' gdat_data.units ']']); + zoom on; + end +else + disp('cannot plot gdat_data, has empty data or t field') +end