function [ids_equilibrium,ids_equilibrium_description,varargout] = ...
  tcv_get_ids_equilibrium(shot,ids_equil_empty,gdat_params,varargin)
%
% [ids_equilibrium,ids_equilibrium_description,varargout] = ...
%     tcv_get_ids_equilibrium(shot,ids_equil_empty,gdat_params,varargin);
%
%
% gdat_params: gdat_data.gdat_params to get all params passed from original call, 
% in particular error_bar and cocos_out options
%

if exist('gdat_params','var')
  [ids_equilibrium, params_equilibrium] = ...
    tcv_ids_headpart(shot,ids_equil_empty,'equilibrium','gdat_params',gdat_params,varargin{:});
else
  [ids_equilibrium, params_equilibrium] = ...
    tcv_ids_headpart(shot,ids_equil_empty,'equilibrium',varargin{:});
  aa=gdat_tcv;
  gdat_params = aa.gdat_params; % to get default params
end

% As a general rule, for a new substructure under the main ids, construct a local structure like:
% "global_quantities" with subfields being the relevant data to get and a local structure:
% "global_quantities_desc" which contains the same subfields themselves containing the gdat string aftre shot used
%
% vacuum_toroidal_field and time, using homogeneous
%
%% liuqe.m at this stage is missing correction 0.996, so use std source by time of default liuqe to make sure
params_eff_ref = gdat_params; params_eff_ref.doplot=0;
try params_eff_ref=rmfield(params_eff_ref,'source');catch;end % make sure no source (from ids def)

params_eff = params_eff_ref;
params_eff.data_request='b0'; params_eff.source='liuqe'; % to get liuqe time array
bb = gdat(params_equilibrium.shot,params_eff);
params_eff = rmfield(params_eff,'source'); % to get original magnetics data
vacuum_toroidal_field.b0=gdat(params_equilibrium.shot,params_eff);
ij_ok = isfinite(vacuum_toroidal_field.b0.data);
vacuum_toroidal_field.b0.data = interpos(21,vacuum_toroidal_field.b0.t(ij_ok),vacuum_toroidal_field.b0.data(ij_ok),bb.t);
vacuum_toroidal_field.b0.t = bb.t;
vacuum_toroidal_field.b0.dim = {vacuum_toroidal_field.b0.t};
vacuum_toroidal_field_desc.b0 = ['''b0'',''timing source'',''liuqe=' num2str(gdat_params.liuqe) ''''];
vacuum_toroidal_field_desc.r0 = '.r0 subfield from: [''b0'',''source'',''liuqe'']';
ids_equilibrium.vacuum_toroidal_field.r0 = vacuum_toroidal_field.b0.r0;
ids_equilibrium.vacuum_toroidal_field.b0 = vacuum_toroidal_field.b0.data;
ids_equilibrium_description.vacuum_toroidal_field = vacuum_toroidal_field_desc;

ids_equilibrium.time = vacuum_toroidal_field.b0.t;
ids_equilibrium_description.time = '.t subfield from: [''b0'',''source'',''liuqe'']';
ntime = numel(ids_equilibrium.time);

ids_equilibrium.time_slice(1:ntime) = ids_equilibrium.time_slice(1);

% load time array data to copy to time_slices

% global_quantities data into local global_quantities.* structure with correct end names and global_quantities_desc.* with description. Use temp.* and temp_desc.* structures for temporary data

% brute force solution load all eqdsks
% $$$ for it=1:ntime
% $$$   ids_equilibrium.time(it)
% $$$   temp.eqdsks{it}=gdat(params_equilibrium.shot,'eqdsk','time',ids_equilibrium.time(it),'write',0,'machine',gdat_params.machine);
% $$$ end
% $$$ temp_desc.eqdsks{1} = '''eqdsk'',''time'',ids_equilibrium.time(it)';

params_eff = params_eff_ref;
params_eff.data_request = 'area_edge';
global_quantities.area = gdat(params_equilibrium.shot,params_eff);
global_quantities_desc.area = params_eff.data_request;
params_eff.data_request = 'betan';
global_quantities.beta_normal = gdat(params_equilibrium.shot,params_eff);
global_quantities_desc.beta_normal = params_eff.data_request;
params_eff.data_request = 'betap';
global_quantities.beta_pol = gdat(params_equilibrium.shot,params_eff);
global_quantities_desc.beta_pol = params_eff.data_request;
params_eff.data_request = 'beta';
global_quantities.beta_tor = gdat(params_equilibrium.shot,params_eff);
global_quantities_desc.beta_tor = params_eff.data_request;
params_eff.data_request = 'w_mhd';
global_quantities.energy_mhd = gdat(params_equilibrium.shot,params_eff);
global_quantities_desc.energy_mhd = params_eff.data_request;
params_eff.data_request = 'ip';
global_quantities.ip = gdat(params_equilibrium.shot,params_eff);
global_quantities_desc.ip = params_eff.data_request;
% length_pol = gdat(params_equilibrium.shot,'length_pol','machine',gdat_params.machine); % to be added
params_eff.data_request = 'li';
global_quantities.li_3 = gdat(params_equilibrium.shot,params_eff);
global_quantities_desc.li_3 = params_eff.data_request;
params_eff.data_request = 'r_axis';
temp.r_magnetic_axis = gdat(params_equilibrium.shot,params_eff);
temp_desc.r_magnetic_axis = params_eff.data_request;
params_eff.data_request = 'z_axis';
temp.z_magnetic_axis = gdat(params_equilibrium.shot,params_eff);
temp_desc.z_magnetic_axis = params_eff.data_request;
params_eff.data_request = 'psi_axis';
temp.psi_axis = gdat(params_equilibrium.shot,params_eff); % needs to add psi_edge sincepsi_axis liuqe assuming 0 dege value
temp_desc.psi_axis = params_eff.data_request;
params_eff.data_request = 'psi_edge';
global_quantities.psi_boundary = gdat(params_equilibrium.shot,params_eff);
global_quantities_desc.psi_boundary = params_eff.data_request;
params_eff.data_request = 'q95';
global_quantities.q_95 = gdat(params_equilibrium.shot,params_eff);
global_quantities_desc.q_95 = params_eff.data_request;
params_eff.data_request = 'q0';
global_quantities.q_axis = gdat(params_equilibrium.shot,params_eff); % will be checked with q_rho?
global_quantities_desc.q_axis = params_eff.data_request;
params_eff.data_request = 'q_rho';
temp.q_rho = gdat(params_equilibrium.shot,params_eff);
temp_desc.q_rho = params_eff.data_request;
% surface = gdat(params_equilibrium.shot,'surface','machine',gdat_params.machine); % to be added
params_eff.data_request = 'volume';
global_quantities.volume = gdat(params_equilibrium.shot,params_eff);
global_quantities_desc.volume = params_eff.data_request;
params_eff.data_request = 'w_mhd';
global_quantities.w_mhd = gdat(params_equilibrium.shot,params_eff);
global_quantities_desc.w_mhd = params_eff.data_request;
ids_equilibrium_description.global_quantities = global_quantities_desc;

global_quantities_fieldnames = fieldnames(global_quantities);
special_fields = {'magnetic_axis', 'psi_axis', 'q_min'}; % fields needing non-automatic treatments
for it=1:ntime
  for i=1:numel(global_quantities_fieldnames)
    if ~any(strcmp(global_quantities_fieldnames{i},special_fields))
      if ~isstruct(ids_equilibrium.time_slice{it}.global_quantities.(global_quantities_fieldnames{i}))
        ids_equilibrium.time_slice{it}.global_quantities.(global_quantities_fieldnames{i}) = ...
            global_quantities.(global_quantities_fieldnames{i}).data(it);
      else
        special_fields{end+1} = global_quantities_fieldnames{i};
      end
    end
  end
end

% special case
for it=1:ntime
  ids_equilibrium.time_slice{it}.global_quantities.magnetic_axis.r = temp.r_magnetic_axis.data(it);
  ids_equilibrium.time_slice{it}.global_quantities.magnetic_axis.z = temp.z_magnetic_axis.data(it);
  ids_equilibrium.time_slice{it}.global_quantities.psi_axis = temp.psi_axis.data(it) + ...
      ids_equilibrium.time_slice{it}.global_quantities.psi_boundary;
  [zz,izz]=min(temp.q_rho.data(:,it));
  ids_equilibrium.time_slice{it}.global_quantities.q_min.value = zz;
  ids_equilibrium.time_slice{it}.global_quantities.q_min.rho_tor_norm = temp.q_rho.grids_1d.rhotornorm(izz);
end

% for boundary in addition to lcfs
% active_limiter_point = gdat(params_equilibrium.shot,'active_limiter_point','machine',gdat_params.machine);
params_eff.data_request = 'kappa';
boundary.elongation = gdat(params_equilibrium.shot,params_eff);
boundary_desc.elongation = params_eff.data_request;
% elongation_lower = gdat(params_equilibrium.shot,'elongation_lower','machine',gdat_params.machine);
% elongation_upper = gdat(params_equilibrium.shot,'elongation_upper','machine',gdat_params.machine);
params_eff.data_request = 'a_minor';
boundary.minor_radius = gdat(params_equilibrium.shot,params_eff);
boundary_desc.minor_radius = params_eff.data_request;
% squareness_lower_inner = gdat(params_equilibrium.shot,'squareness_lower_inner','machine',gdat_params.machine);
% squareness_lower_outer = gdat(params_equilibrium.shot,'squareness_lower_outer','machine',gdat_params.machine);
% squareness_upper_inner = gdat(params_equilibrium.shot,'squareness_upper_inner','machine',gdat_params.machine);
% squareness_upper_outer = gdat(params_equilibrium.shot,'squareness_upper_outer','machine',gdat_params.machine);
% strike_point = gdat(params_equilibrium.shot,'strike_point','machine',gdat_params.machine);
params_eff.data_request = 'delta';
boundary.triangularity = gdat(params_equilibrium.shot,params_eff);
boundary_desc.triangularity = params_eff.data_request;
params_eff.data_request = 'delta_bottom';
boundary.triangularity_lower = gdat(params_equilibrium.shot,params_eff);
boundary_desc.triangularity_lower = params_eff.data_request;
params_eff.data_request = 'delta_top';
boundary.triangularity_upper = gdat(params_equilibrium.shot,params_eff);
boundary_desc.triangularity_upper = params_eff.data_request;
params_eff.data_request = 'tcv_eq(''''n_xpts'''',''''liuqe.m'''')';
temp.n_x_point = gdat(params_equilibrium.shot,params_eff);
temp_desc.n_x_point = params_eff.data_request;
params_eff.data_request = 'tcv_eq(''''r_xpts'''',''''liuqe.m'''')';
temp.r_x_point = gdat(params_equilibrium.shot,params_eff);
temp_desc.r_x_point = params_eff.data_request;
params_eff.data_request = 'tcv_eq(''''z_xpts'''',''''liuqe.m'''')';
temp.z_x_point = gdat(params_equilibrium.shot,params_eff);
temp_desc.z_x_point = params_eff.data_request;
params_eff.data_request = 'rgeom';
temp.rgeom = gdat(params_equilibrium.shot,params_eff);
temp_desc.rgeom = params_eff.data_request;
params_eff.data_request = 'zgeom';
temp.zgeom = gdat(params_equilibrium.shot,params_eff);
temp_desc.zgeom = params_eff.data_request;
params_eff.data_request = 'r_contour_edge';
temp.r_lcfs = gdat(params_equilibrium.shot,params_eff);
temp_desc.r_lcfs = params_eff.data_request;
params_eff.data_request = 'z_contour_edge';
temp.z_lcfs = gdat(params_equilibrium.shot,params_eff);
temp_desc.z_lcfs = params_eff.data_request;

boundary_fieldnames = fieldnames(boundary);
special_fields = {'lcfs', 'geometric_axis', 'x_point'}; % fields needing non-automatic treatments
for it=1:ntime
  for i=1:numel(boundary_fieldnames)
    if ~any(strcmp(boundary_fieldnames{i},special_fields))
      if ~isstruct(ids_equilibrium.time_slice{it}.boundary.(boundary_fieldnames{i}))
        ids_equilibrium.time_slice{it}.boundary.(boundary_fieldnames{i}) = ...
            boundary.(boundary_fieldnames{i}).data(it);
      else
        special_fields{end+1} = boundary_fieldnames{i};
      end
    end
  end
end

% special cases
for it=1:ntime
  ids_equilibrium.time_slice{it}.boundary.outline.r = temp.r_lcfs.data(:,it);
  ids_equilibrium.time_slice{it}.boundary.outline.z = temp.z_lcfs.data(:,it);
  ids_equilibrium.time_slice{it}.boundary.lcfs.r = ids_equilibrium.time_slice{it}.boundary.outline.r;
  ids_equilibrium.time_slice{it}.boundary.lcfs.z = ids_equilibrium.time_slice{it}.boundary.outline.z;
  ids_equilibrium.time_slice{it}.boundary.geometric_axis.r = temp.rgeom.data(it);
  ids_equilibrium.time_slice{it}.boundary.geometric_axis.z = temp.zgeom.data(it);
  if temp.n_x_point.data(it) > 0
    % not that asking for time_out may lead to interpolated nb of X-points non integer, should included piece-wise constant interpolation for equil quantities...
    ids_equilibrium.time_slice{it}.boundary.x_point(1:fix(temp.n_x_point.data(it))) = ids_equilibrium.time_slice{it}.boundary.x_point(1);
    for i=1:fix(temp.n_x_point.data(it))
      ids_equilibrium.time_slice{it}.boundary.x_point{i}.r = temp.r_x_point.data(i,it);
      ids_equilibrium.time_slice{it}.boundary.x_point{i}.z = temp.z_x_point.data(i,it);
    end
  else
    ids_equilibrium.time_slice{it}.boundary.x_point = {};
  end
end
ids_equilibrium_description.boundary = boundary_desc;
ids_equilibrium_description.boundary_temp = temp_desc;

%% constraints

% Measured values
liuqe_time = ids_equilibrium.time; % Not necessarily magnetics time so far
mag_time   = mdsvalue('\magnetics::bpol_003:dim0');
itime = iround_os(mag_time, liuqe_time);
mag_time_req = mdscvt(mag_time(itime),'f');
bpol = mdsvalue('\magnetics::bpol_003[$1,*]',mag_time_req);
nbpol = size(bpol,2);
constraints_desc.bpol_probe.measured = sprintf('from %s i=1:%d','\magnetics::bpol_003[i,*]',nbpol);
flux = mdsvalue('tcv_idealloop("flux")[$1,*]',mag_time_req);
nflux = size(flux,2);
constraints_desc.flux_loop.measured = sprintf('from %s i=1:%d','tcv_idealloop("flux")[i,*]',nflux);
ip   = mdsvalue('\magnetics::iplasma:trapeze[$1]',mag_time_req);
constraints_desc.ip.measured = sprintf('from %s','\magnetics::iplasma:trapeze');
diam = mdsvalue('\results::dmlcor[$1]',mag_time_req);
constraints_desc.diamagnetic_flux.measured = sprintf('from %s','\results::dmlcor');
% Coil currents since dim of constraints pf_current is IDS:pf_active/coil
dim_pol = {'OH_001','OH_002','OH_002','OH_002','OH_002','OH_002','OH_002',...
           'E_001','E_002','E_003','E_004','E_005','E_006','E_007','E_008',...
           'F_001','F_002','F_003','F_004','F_005','F_006','F_007','F_008',...
           'G_001','G_001','G_001','G_001','G_001','G_001'};
ipol = mdsvalue('\magnetics::ipol[$1,$2]',mag_time_req,dim_pol);
ipol(:,27:29) = -ipol(:,27:29); % Bottom G-coils
dim_pol(30:32) = {'TOR_001'};
ipol(:,30:32) = 0; % TOR_001 is not used in LIUQE
nipol = size(ipol,2);
constraints_desc.pf_current.measured = sprintf('from %s, ii from %s','\magnetics::ipol[t,ii]',cell2str(dim_pol,15));

% Reconstructed values
ipol_liuqe_order = [18,19*ones(1,6),1:16,17*ones(1,6)]; % LIUQE order is E F G OH
bpol_liuqe = mdsvalue('tcv_eq("b_probe","liuqe.m")');
constraints_desc.bpol_probe.reconstructed = sprintf('%s','tcv_eq("b_probe","liuqe.m")');
flux_liuqe = mdsvalue('tcv_eq("psi_loop","liuqe.m")');
constraints_desc.flux_liuqe.reconstructed = sprintf('%s','tcv_eq("psi_loop","liuqe.m")');
ip_liuqe   = mdsvalue('tcv_eq("i_pl","liuqe.m")');
constraints_desc.ip.reconstructed = sprintf('%s','tcv_eq("i_pl","liuqe.m")');
diam_liuqe = mdsvalue('tcv_eq("tor_flux_dml","liuqe.m")');
constraints_desc.diamagnetic_flux.reconstructed = sprintf('%s','tcv_eq("tor_flux_dml","liuqe.m")');
ipol_liuqe = mdsvalue('tcv_eq("i_pol","liuqe.m")');
ipol_liuqe = ipol_liuqe(ipol_liuqe_order,:);
ipol_liuqe(27:29,:) = -ipol_liuqe(27:29,:); % Bottom G-coils
ipol_liuqe(30:32,:) = 0; % ... TOR
constraints_desc.ipol_liuqe.reconstructed = sprintf('%s','tcv_eq("i_pol","liuqe.m")');

% Weights (using old parameters tree for now)
bpol_err = mdsvalue('\results::parameters:berr')./mdsvalue('\results::parameters:vvv[0:37]');
constraints_desc.bpol_probe.weight = sprintf('(%s/%s)^2','\results::parameters:vvv[0:37]','\results::parameters:berr');
flux_err = mdsvalue('\results::parameters:ferr')./mdsvalue('\results::parameters:www[0:37]')*2*pi;
constraints_desc.flux_loop.weight = sprintf('(%s/%s)^2','\results::parameters:www[0:37]','\results::parameters:ferr');
ip_err   = mdsvalue('\results::parameters:plcerr')*1e3;
constraints_desc.ip.weight = sprintf('(1e-3/%s)^2','\results::parameters:plcerr');
diam_err = 0.13e-3./mdsvalue('\results::parameters:idml');
constraints_desc.diamagnetic_flux.weight = sprintf('(%s/0.13e-3)^2','\results::parameters:idml');
ipol_err = mdsvalue('\results::parameters:cerr')./mdsvalue('\results::parameters:uuu[0:18]')*1e3;
ipol_err = ipol_err(ipol_liuqe_order);
ipol_err(30:32) = NaN;
constraints_desc.pf_current.weight = sprintf('(1e-3*%s/%s)^2','\results::parameters:uuu[0:18]','\results::parameters:cerr');

if ntime > 0
  constraints_orig = ids_equilibrium.time_slice{1}.constraints;
  % Remove unused arrays
  ununsed_constraints = {'faraday_angle','mse_polarisation_angle','iron_core_segment',...
                         'n_e','n_e_line','pressure','q','x_point'};
  for name = ununsed_constraints, constraints_orig.(name{1})={}; end
  constraints_desc.ununsed_constraints = ununsed_constraints;
end
for it = 1:ntime
  constraints = constraints_orig;
  % bpol_probe
  bpol_probe(1:nbpol) = constraints.bpol_probe(1);
  for ib = 1:nbpol
    bpol_probe{ib}.measured = bpol(it,ib);
    bpol_probe{ib}.source = sprintf('IDS:equilibrium/../constraints/bpol_probe[%02d]',ib);
    bpol_probe{ib}.time_measurement = mag_time(itime(it));
    bpol_probe{ib}.exact = 0;
    bpol_probe{ib}.weight = 1/(bpol_err(ib)).^2;
    bpol_probe{ib}.reconstructed = bpol_liuqe(ib,it);
  end
  constraints.bpol_probe = bpol_probe;
  % flux_loop
  flux_loop(1:nflux) = constraints.flux_loop(1);
  for il = 1:nflux
    flux_loop{il}.measured = flux(it,il);
    flux_loop{il}.source = sprintf('IDS:equilibrium/../constraints/flux_loop[%02d]',il);
    flux_loop{il}.time_measurement = mag_time(itime(it));
    flux_loop{il}.exact = 0;
    flux_loop{il}.weight = 1/(flux_err(il)).^2;
    flux_loop{il}.reconstructed = flux_liuqe(il,it);
  end
  constraints.flux_loop = flux_loop;
  % ip
  constraints.ip.measured = ip(it);
  constraints.ip.source = 'IDS:equilibrium/../constraints/ip';
  constraints.ip.time_measurement = mag_time(itime(it));
  constraints.ip.exact = 0;
  constraints.ip.weight = 1/(ip_err).^2;
  constraints.ip.reconstructed = ip_liuqe(it);
  % diamagnetic_flux
  constraints.diamagnetic_flux.measured = diam(it);
  constraints.diamagnetic_flux.source = 'IDS:equilibrium/../constraints/diamagnetic_flux';
  constraints.diamagnetic_flux.time_measurement = mag_time(itime(it));
  constraints.diamagnetic_flux.exact = 0;
  constraints.diamagnetic_flux.weight = 1/(diam_err).^2;
  constraints.diamagnetic_flux.reconstructed = diam_liuqe(it);
  % pf_current
  pf_current(1:nipol) = constraints.pf_current(1);
  for ic = 1:nipol
    pf_current{ic}.measured = ipol(it,ic);
    pf_current{ic}.source = sprintf('IDS:equilibrium/../constraints/pf_current[%02d]',ic);
    pf_current{ic}.time_measurement = mag_time(itime(it));
    if strcmp(dim_pol{ic},'TOR_001')
      pf_current{ic}.source = [pf_current{ic}.source,' replaced with 0'];
      pf_current{ic}.exact = 1;
    else
      pf_current{ic}.exact = 0;
      pf_current{ic}.weight = 1/(ipol_err(ic)).^2;
      pf_current{ic}.reconstructed = ipol_liuqe(ic,it);
    end
  end
  constraints.pf_current = pf_current;

  ids_equilibrium.time_slice{it}.constraints = constraints;
end

ids_equilibrium_description.constraints = constraints_desc;

%
%% profiles_1d (cannot use eqdsk since not same radial mesh)
%
% area = gdat(params_equilibrium.shot,'area','machine',gdat_params.machine);
% b_average = gdat(params_equilibrium.shot,'b_average','machine',gdat_params.machine);
% beta_pol = gdat(params_equilibrium.shot,'beta_pol','machine',gdat_params.machine);
% b_field_average = gdat(params_equilibrium.shot,'b_field_average','machine',gdat_params.machine);
% b_field_max = gdat(params_equilibrium.shot,'b_field_max','machine',gdat_params.machine);
% b_field_min = gdat(params_equilibrium.shot,'b_field_min','machine',gdat_params.machine);
% b_max = gdat(params_equilibrium.shot,'b_max','machine',gdat_params.machine);
% b_min = gdat(params_equilibrium.shot,'b_min','machine',gdat_params.machine);
% darea_dpsi = gdat(params_equilibrium.shot,'darea_dpsi','machine',gdat_params.machine);
% darea_drho_tor = gdat(params_equilibrium.shot,'darea_drho_tor','machine',gdat_params.machine);
params_eff.data_request = 'pprime';
profiles_1d.dpressure_dpsi = gdat(params_equilibrium.shot,params_eff);
profiles_1d_desc.dpressure_dpsi = params_eff.data_request;
% dpsi_drho_tor = gdat(params_equilibrium.shot,'dpsi_drho_tor','machine',gdat_params.machine);
% dvolume_dpsi = gdat(params_equilibrium.shot,'dvolume_dpsi','machine',gdat_params.machine);
% dvolume_drho_tor = gdat(params_equilibrium.shot,'dvolume_drho_tor','machine',gdat_params.machine);
% elongation = gdat(params_equilibrium.shot,'elongation','machine',gdat_params.machine);
params_eff.data_request = 'ttprime';
profiles_1d.f_df_dpsi = gdat(params_equilibrium.shot,params_eff);
profiles_1d_desc.f_df_dpsi = [params_eff.data_request '* 0.996^2'];
params_eff.data_request = 'rbphi_rho';
profiles_1d.f = gdat(params_equilibrium.shot,params_eff);
profiles_1d_desc.f = [params_eff.data_request '* 0.996'];
profiles_1d.f.data = 0.996 * profiles_1d.f.data;
profiles_1d.f_df_dpsi.data = 0.996.^2 .* profiles_1d.f_df_dpsi.data;
% geometric_axis = gdat(params_equilibrium.shot,'geometric_axis','machine',gdat_params.machine);
% gm1 = gdat(params_equilibrium.shot,'gm1','machine',gdat_params.machine);
% gm2 = gdat(params_equilibrium.shot,'gm2','machine',gdat_params.machine);
% gm3 = gdat(params_equilibrium.shot,'gm3','machine',gdat_params.machine);
% gm4 = gdat(params_equilibrium.shot,'gm4','machine',gdat_params.machine);
% gm5 = gdat(params_equilibrium.shot,'gm5','machine',gdat_params.machine);
% gm6 = gdat(params_equilibrium.shot,'gm6','machine',gdat_params.machine);
% gm7 = gdat(params_equilibrium.shot,'gm7','machine',gdat_params.machine);
% gm8 = gdat(params_equilibrium.shot,'gm8','machine',gdat_params.machine);
% gm9 = gdat(params_equilibrium.shot,'gm9','machine',gdat_params.machine);
% j_parallel = gdat(params_equilibrium.shot,'j_parallel','machine',gdat_params.machine);
% j_tor = gdat(params_equilibrium.shot,'j_tor','machine',gdat_params.machine);
% magnetic_shear = gdat(params_equilibrium.shot,'magnetic_shear','machine',gdat_params.machine);
% mass_density = gdat(params_equilibrium.shot,'mass_density','machine',gdat_params.machine);
params_eff.data_request = 'phi_tor';
profiles_1d.phi = gdat(params_equilibrium.shot,params_eff);
profiles_1d.phi.data = 0.996 * profiles_1d.phi.data;
profiles_1d_desc.phi = [params_eff.data_request '* 0.996'];
params_eff.data_request = 'pressure';
profiles_1d.pressure = gdat(params_equilibrium.shot,params_eff);
profiles_1d_desc.pressure = params_eff.data_request;
% psi = gdat(params_equilibrium.shot,'psi_rho','machine',gdat_params.machine); % (could take from .x of any like rhotor and psi_axis, psi_edge from global_quantities)
params_eff.data_request = 'q_rho';
profiles_1d.q = gdat(params_equilibrium.shot,params_eff);
profiles_1d_desc.q = params_eff.data_request;
params_eff.data_request = 'rhotor';
profiles_1d.rho_tor = gdat(params_equilibrium.shot,params_eff);
profiles_1d_desc.rho_tor = params_eff.data_request;
%rho_tor_norm = gdat(params_equilibrium.shot,'rhotor_norm','machine',gdat_params.machine); % from rho_tor
params_eff.data_request = 'rhovol';
profiles_1d.rho_volume_norm = gdat(params_equilibrium.shot,params_eff);
profiles_1d_desc.rho_volume_norm = params_eff.data_request;
% r_inboard = gdat(params_equilibrium.shot,'r_inboard','machine',gdat_params.machine);
% r_outboard = gdat(params_equilibrium.shot,'r_outboard','machine',gdat_params.machine);
% squareness_lower_inner = gdat(params_equilibrium.shot,'squareness_lower_inner','machine',gdat_params.machine);
% squareness_lower_outer = gdat(params_equilibrium.shot,'squareness_lower_outer','machine',gdat_params.machine);
% squareness_upper_inner = gdat(params_equilibrium.shot,'squareness_upper_inner','machine',gdat_params.machine);
% squareness_upper_outer = gdat(params_equilibrium.shot,'squareness_upper_outer','machine',gdat_params.machine);
% surface = gdat(params_equilibrium.shot,'surface','machine',gdat_params.machine);
% trapped_fraction = gdat(params_equilibrium.shot,'trapped_fraction','machine',gdat_params.machine);
% triangularity_lower = gdat(params_equilibrium.shot,'triangularity_lower','machine',gdat_params.machine);
% triangularity_upper = gdat(params_equilibrium.shot,'triangularity_upper','machine',gdat_params.machine);
params_eff.data_request = 'volume_rho';
profiles_1d.volume = gdat(params_equilibrium.shot,params_eff);
profiles_1d_desc.volume = params_eff.data_request;

liuqe_opt = gdat_params.liuqe; % default at this stage but could take from gdat params like error bar
switch liuqe_opt
 case {-1},   psitbx_str='FBTE';
 case {1,21}, psitbx_str='LIUQE.M';
 case {11},   psitbx_str='LIUQE';
 case {2, 3, 22, 23}, psitbx_str=['LIUQE.M' num2str(mod(liuqe_opt,10))];
 case {12,13}, psitbx_str=['LIUQE' num2str(mod(liuqe_opt,10))];
 otherwise, error(['Unknown LIUQE version, liuqe = ' num2str(liuqe_opt)]);
end
fsd = psitbxtcv2(shot,profiles_1d.volume.t,'FS',psitbx_str,false); % will get automatically the correct time interval
grho_metric_3D = metric(fsd,-1);
% Introduced new anonymous function to compute FS average ...
metric_FS = metric(grho_metric_3D.grid,[2,3]);
denom=sum(metric_FS./grho_metric_3D,[2,3]);
FS_av = @(x) sum(x.*metric_FS./grho_metric_3D,[2,3])./denom;
R=metric(fsd,3);
Rm2av=FS_av(1./R.^2);
profiles_1d.gm1.data = Rm2av.x;
profiles_1d_desc.gm1 = ['psitbxtcv2 with ' psitbx_str ' then Rm2av=FS_av(1./R.^2)'];
%tmp_gm = FS_av(grho_metric_3D.^2./R.^2); % this gives (grad rhopol/R)^2 not gm2 which is grad rhotor^2
%profiles_1d.gm2.data = tmp_gm.x;
tmp_gm = FS_av(1./R.^1);
profiles_1d.gm9.data = tmp_gm.x;
profiles_1d_desc.gm9 = 'FS_av(1./R.^1)';

tmp_gm = FS_av(grho_metric_3D.^2./R.^2); % grad rhopol^2 to get <grad psi^2>
nrho = numel(profiles_1d.rho_tor.x);
gradpsi_over_R_sq = NaN(nrho,ntime);
for it=1:ntime
  gradpsi_over_R_sq(:,it) = tmp_gm.x(:,it) .* 4 .* profiles_1d.volume.x.^2 .* ...
      (ids_equilibrium.time_slice{it}.global_quantities.psi_boundary-ids_equilibrium.time_slice{it}.global_quantities.psi_axis).^2;
end
mu0 = 4.e-7 * pi;
% Eq. (30) cocos paper cocos=17
% j_tor=<jphi/R>/<1/R>=-sigma_Bp (2pi)^e_Bp dp/dpsi / <1/R> - sigma_Bp (2pi)^e_Bp F dF/dpsi / mu0 <1/R^2> / <1/R>
% simaBp=-1 and eBp=1 for cocos=17 from TCV LIUQE
profiles_1d.j_tor.data = - (-1.) .* 2.*pi .* profiles_1d.dpressure_dpsi.data ./ profiles_1d.gm9.data ...
    - (-1.) .* 2.*pi .* profiles_1d.gm1.data ./ profiles_1d.gm9.data .* profiles_1d.f_df_dpsi.data ./ mu0;
%
% <j.B> = - sigma_Bp (2pi)^e_Bp dp/dpsi F - sigma_Bp F dF/dpsi / mu0 [ (2pi)^e_Bp F <1/R^2> + 1/(2pi)^e_Bp * <|grad psi|^2/R^2> / F ]
% simaBp=-1 and eBp=1 for cocos=17 from TCV LIUQE
%
j_par = - (-1.) .* 2*pi .* profiles_1d.dpressure_dpsi.data .* profiles_1d.f.data ...
        - (-1.) .* profiles_1d.f_df_dpsi.data ./ mu0 .* ...
        ( (2.*pi) .* profiles_1d.f.data .* profiles_1d.gm1.data + 1./(2.*pi) .* gradpsi_over_R_sq ./ profiles_1d.f.data);
profiles_1d.j_parallel.data = j_par./repmat(ids_equilibrium.vacuum_toroidal_field.b0',size(profiles_1d.f.data,1),1);

profiles_1d_fieldnames = fieldnames(profiles_1d);
special_fields = {'geometric_axis', 'rho_tor_norm', 'psi'}; % fields needing non-automatic treatments
for it=1:ntime
  for i=1:numel(profiles_1d_fieldnames)
    if ~any(strcmp(profiles_1d_fieldnames{i},special_fields))
      if ~isstruct(ids_equilibrium.time_slice{it}.profiles_1d.(profiles_1d_fieldnames{i}))
        if ~ischar(profiles_1d.(profiles_1d_fieldnames{i}).data) && ~isempty(profiles_1d.(profiles_1d_fieldnames{i}).data) ...
              && size(profiles_1d.(profiles_1d_fieldnames{i}).data,2)>=it
          ids_equilibrium.time_slice{it}.profiles_1d.(profiles_1d_fieldnames{i}) = ...
              profiles_1d.(profiles_1d_fieldnames{i}).data(:,it);
        end
      else
        special_fields{end+1} = profiles_1d_fieldnames{i};
      end
    end
  end
end

ids_equilibrium_description.profiles_1d = profiles_1d_desc;

% special cases
for it=1:ntime
  ids_equilibrium.time_slice{it}.global_quantities.magnetic_axis.b_field_tor = ids_equilibrium.time_slice{it}.profiles_1d.f(1) ...
      ./ids_equilibrium.time_slice{it}.global_quantities.magnetic_axis.r;
  ids_equilibrium.time_slice{it}.global_quantities.magnetic_axis.b_tor = ids_equilibrium.time_slice{it}.global_quantities.magnetic_axis.b_field_tor;
  ids_equilibrium.time_slice{it}.profiles_1d.rho_tor_norm = ids_equilibrium.time_slice{it}.profiles_1d.rho_tor./ ...
      ids_equilibrium.time_slice{it}.profiles_1d.rho_tor(end);
  ids_equilibrium.time_slice{it}.profiles_1d.psi = ids_equilibrium.time_slice{it}.global_quantities.psi_axis + ...
      profiles_1d.rho_tor.x.^2 .* ...
      (ids_equilibrium.time_slice{it}.global_quantities.psi_boundary- ids_equilibrium.time_slice{it}.global_quantities.psi_axis);
end

%
%% profiles_2d{1} ala eqdsk, only this one thus grid_type=1
%
% b_field_r = gdat(params_equilibrium.shot,'b_field_r','machine',gdat_params.machine);
% b_field_tor = gdat(params_equilibrium.shot,'b_field_tor','machine',gdat_params.machine);
% b_field_z = gdat(params_equilibrium.shot,'b_field_z','machine',gdat_params.machine);
% b_r = gdat(params_equilibrium.shot,'b_r','machine',gdat_params.machine);
% b_tor = gdat(params_equilibrium.shot,'b_tor','machine',gdat_params.machine);
% b_z = gdat(params_equilibrium.shot,'b_z','machine',gdat_params.machine);
% grid = gdat(params_equilibrium.shot,'grid','machine',gdat_params.machine); % special
profiles_2d.grid_type.name = 'rectangular';
profiles_2d.grid_type.index = 1;
profiles_2d.grid_type.description = 'Cylindrical R,Z ala eqdsk';
% j_parallel = gdat(params_equilibrium.shot,'j_parallel','machine',gdat_params.machine);
% j_tor = gdat(params_equilibrium.shot,'j_tor','machine',gdat_params.machine);
% phi = gdat(params_equilibrium.shot,'phi','machine',gdat_params.machine);
params_eff.data_request = 'psi';
profiles_2d.psi = gdat(params_equilibrium.shot,params_eff); % add psi_bound in a second step in special cases
profiles_2d_desc.psi = [params_eff.data_request ' adding psi_bound in a 2nd step'];
%profiles_2d.r = profiles_2d.psi;
profiles_2d.r.data = repmat(repmat(profiles_2d.psi.dim{1},1,numel(profiles_2d.psi.dim{2})),1,1,numel(profiles_2d.psi.dim{3}));
profiles_2d_desc.r = 'from dim{1} of ''psi'' repeated';
profiles_2d.z.data = repmat(repmat(profiles_2d.psi.dim{2}',numel(profiles_2d.psi.dim{1}),1),1,1,numel(profiles_2d.psi.dim{3}));
profiles_2d_desc.z = 'from dim{2} of ''psi'' repeated';

% theta = gdat(params_equilibrium.shot,'theta','machine',gdat_params.machine);

profiles_2d_fieldnames = fieldnames(profiles_2d);
special_fields = {'grid', 'grid_type'}; % fields needing non-automatic treatments
for it=1:ntime
  for i=1:numel(profiles_2d_fieldnames)
    if ~any(strcmp(profiles_2d_fieldnames{i},special_fields))
      if ~isstruct(ids_equilibrium.time_slice{it}.profiles_2d{1}.(profiles_2d_fieldnames{i}))
        if ~ischar(profiles_2d.(profiles_2d_fieldnames{i}).data) && ~isempty(profiles_2d.(profiles_2d_fieldnames{i}).data) ...
              && size(profiles_2d.(profiles_2d_fieldnames{i}).data,3)>=it
          ids_equilibrium.time_slice{it}.profiles_2d{1}.(profiles_2d_fieldnames{i}) = ...
              profiles_2d.(profiles_2d_fieldnames{i}).data(:,:,it);
        end
      else
        special_fields{end+1} = profiles_2d_fieldnames{i};
      end
    end
  end
end

% special cases
for it=1:ntime
  ids_equilibrium.time_slice{it}.profiles_2d{1}.grid_type.name = profiles_2d.grid_type.name;
  ids_equilibrium.time_slice{it}.profiles_2d{1}.grid_type.index = profiles_2d.grid_type.index;
  ids_equilibrium.time_slice{it}.profiles_2d{1}.grid_type.description = profiles_2d.grid_type.description;
  ids_equilibrium.time_slice{it}.profiles_2d{1}.grid.dim1 = profiles_2d.psi.dim{1};
  ids_equilibrium.time_slice{it}.profiles_2d{1}.grid.dim2 = profiles_2d.psi.dim{2};
  ids_equilibrium.time_slice{it}.profiles_2d{1}.psi(:,:) = ids_equilibrium.time_slice{it}.profiles_2d{1}.psi(:,:) + ...
      global_quantities.psi_boundary.data(it);
end

ids_equilibrium_description.profiles_2d = profiles_2d_desc;

% make arrays not filled in empty:
ids_equilibrium.grids_ggd = {};
for it=1:numel(ids_equilibrium.time_slice)
  ids_equilibrium.time_slice{it}.ggd = {};
  ids_equilibrium.time_slice{it}.boundary.strike_point = {};
  ids_equilibrium.time_slice{it}.boundary_separatrix.x_point = {};
  ids_equilibrium.time_slice{it}.boundary_separatrix.strike_point = {};
end

% special test matrix cocos transform
% $$$ ldim1=129;
% $$$ ldim2=257;
% $$$ it=1;
% $$$ ids_equilibrium.time_slice{it}.coordinate_system.grid_type.index = 13;
% $$$ ids_equilibrium.time_slice{it}.coordinate_system.grid.dim1 = linspace(0,1,ldim1)';
% $$$ ids_equilibrium.time_slice{it}.coordinate_system.grid.dim2 = linspace(0,2*pi,ldim2);
% $$$ ids_equilibrium.time_slice{it}.coordinate_system.tensor_contravariant = 2.*ones(ldim1,ldim2,3,3);
% $$$ ids_equilibrium.time_slice{it}.coordinate_system.tensor_covariant = 0.5*ones(ldim1,ldim2,3,3);
% $$$ ids_equilibrium.time_slice{it}.coordinate_system.g13_contravariant = 13.*ones(ldim1,ldim2,3,3);
% $$$ ids_equilibrium.time_slice{it}.coordinate_system.g13_contravariant_error_upper = 14.*ones(ldim1,ldim2,3,3);
% $$$ ids_equilibrium.time_slice{it}.coordinate_system.g13_contravariant_error_lower = 12.*ones(ldim1,ldim2,3,3);
% $$$ for it=1:2100
% $$$   ids_equilibrium.time_slice{it}.coordinate_system.g11_contravariant = 11.*ones(ldim1,ldim2,3,3);
% $$$   ids_equilibrium.time_slice{it}.coordinate_system.tensor_covariant = 0.5*ones(ldim1,ldim2,3,3);
% $$$   ids_equilibrium.time_slice{it}.profiles_2d{2}.grid_type.name = profiles_2d.grid_type.name;
% $$$   ids_equilibrium.time_slice{it}.profiles_2d{2}.grid_type.index = 11;
% $$$   ids_equilibrium.time_slice{it}.profiles_2d{2}.grid_type.description = profiles_2d.grid_type.description;
% $$$   ids_equilibrium.time_slice{it}.profiles_2d{2}.grid.dim1 = linspace(0,1,ldim1)';
% $$$   ids_equilibrium.time_slice{it}.profiles_2d{2}.grid.dim1_error_upper = 1.2.*linspace(0,1,ldim1)';
% $$$   ids_equilibrium.time_slice{it}.profiles_2d{2}.grid.dim1_error_lower = 0.8.*linspace(0,1,ldim1)';
% $$$   ids_equilibrium.time_slice{it}.profiles_2d{2}.grid.dim2 = linspace(0,2*pi,ldim2);
% $$$   ids_equilibrium.time_slice{it}.profiles_2d{2}.psi(:,:) = 11.*ones(ldim1,ldim2);
% $$$   ids_equilibrium.time_slice{it}.profiles_2d{2}.psi_error_upper(:,:) = 12.*ones(ldim1,ldim2);
% $$$   ids_equilibrium.time_slice{it}.profiles_2d{2}.psi_error_lower(:,:) = 10.*ones(ldim1,ldim2);
% $$$ end

% cocos automatic transform
if ~isempty(which('ids_generic_cocos_nodes_transformation_symbolic'))
  [ids_equilibrium,cocoscoeff]=ids_generic_cocos_nodes_transformation_symbolic(ids_equilibrium,'equilibrium',gdat_params.cocos_in, ...
          gdat_params.cocos_out,gdat_params.ipsign_out,gdat_params.b0sign_out,gdat_params.ipsign_in,gdat_params.b0sign_in, ...
          gdat_params.error_bar,gdat_params.nverbose);
end
