From 1ce974716dd014a08f69194b3c32378f7b4c4f1d Mon Sep 17 00:00:00 2001
From: Michele Marin <michele.marin@epfl.ch>
Date: Mon, 14 Oct 2024 11:49:33 +0200
Subject: [PATCH 01/11] Add possibility of choosing cxrs systems for raw data

---
 matlab/TCV_IMAS/tcv2ids.m                   |  2 ++
 matlab/TCV_IMAS/tcv2ids2database.m          |  2 ++
 matlab/TCV_IMAS/tcv_get_ids_core_profiles.m | 17 +++++++++++++++++
 3 files changed, 21 insertions(+)

diff --git a/matlab/TCV_IMAS/tcv2ids.m b/matlab/TCV_IMAS/tcv2ids.m
index 83662207..85f6a664 100644
--- a/matlab/TCV_IMAS/tcv2ids.m
+++ b/matlab/TCV_IMAS/tcv2ids.m
@@ -54,6 +54,8 @@ p.addOptional('nverbose', 1, @(x) isempty(x) || isnumeric(x) );
 p.addOptional('time_out', [], @(x) isempty(x) || isnumeric(x) );
 p.addOptional('trialindx', [], @(x) isempty(x) || isnumeric(x) );
 p.addOptional('liuqe', [], @(x) isempty(x) || isnumeric(x) );
+p.addOptional('cxrs_source_ti', [], @(x) isempty(x) || isnumeric(x) );
+p.addOptional('cxrs_source_ni', [], @(x) isempty(x) || isnumeric(x) );
 
 params_not_for_gdat_params = {'shot','ids_names'};
 
diff --git a/matlab/TCV_IMAS/tcv2ids2database.m b/matlab/TCV_IMAS/tcv2ids2database.m
index 916ec438..2c7de5b6 100644
--- a/matlab/TCV_IMAS/tcv2ids2database.m
+++ b/matlab/TCV_IMAS/tcv2ids2database.m
@@ -63,6 +63,8 @@ p.addOptional('b0sign_out', 0, @(x) isempty(x) || (isscalar(x) && (x==0 || x==-1
 p.addOptional('nverbose', 1, @(x) isempty(x) || isnumeric(x) );
 p.addOptional('time_out', [], @(x) isempty(x) || isnumeric(x) );
 p.addOptional('trialindx', [], @(x) isempty(x) || isnumeric(x) );
+p.addOptional('cxrs_source_ti', [], @(x) isempty(x) || isnumeric(x) );
+p.addOptional('cxrs_source_ni', [], @(x) isempty(x) || isnumeric(x) );
 
 p.parse;
 defaults_tcv2ids2database = p.Results; % to keep track of defaults
diff --git a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
index e31c6fad..00b87105 100644
--- a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
+++ b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
@@ -244,11 +244,20 @@ end
 %% ion struct
 % assume only D if no CXRS (need to ask how to check if H...)
 params_eff_fit1.data_request = 'cxrs';
+
+% Extract ti here
+if  isfield(gdat_params, 'cxrs_source_ti')
+  params_eff_fit1.source = gdat_params.cxrs_source_ti;
+else
+  params_eff_fit1.source = [1,2,3];
+end
+
 try
   temp_1d.cxrs_rho = gdat(params_cores_profiles.shot,params_eff_fit1);
   temp_1d_desc.cxrs_rho = params_eff_fit1.data_request;
 catch
   temp_1d.cxrs_rho.data = [];
+  temp_1d.cxrs_rho.error_bar = [];
   temp_1d_desc.cxrs_rho = ['Problem with gdat ' params_eff_fit1.data_request ' ; no data'];
 end
 params_eff_fit1.data_request = 'results.conf:ti';
@@ -275,6 +284,14 @@ temp_1d_desc.ti.raw = data_fullpath_fit;
 temp_1d.ti.fit = temp_1d.ti_conf_rho;
 temp_1d.ti.fit =get_grids_1d(temp_1d.ti.fit,1,1);
 temp_1d_desc.ti.fit = temp_1d_desc.ti_conf_rho;
+
+% Extract ni here
+if  isfield(gdat_params, 'cxrs_source_ni')
+  params_eff_fit1.source = gdat_params.cxrs_source_ni;
+else
+  params_eff_fit1.source = [1,2,3];
+end
+
 temp_1d.ni.fit = temp_1d.ni_conf_rho;
 temp_1d.ni.fit =get_grids_1d(temp_1d.ni.fit,1,1);
 temp_1d_desc.ni.fit = temp_1d_desc.ni_conf_rho;
-- 
GitLab


From f2d882cad1444f2c96be03cb52dee9f33cfa3aa6 Mon Sep 17 00:00:00 2001
From: Michele Marin <michele.marin@epfl.ch>
Date: Mon, 14 Oct 2024 11:53:40 +0200
Subject: [PATCH 02/11] Add check for disrupted shot

---
 matlab/TCV_IMAS/tcv2ids.m | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/matlab/TCV_IMAS/tcv2ids.m b/matlab/TCV_IMAS/tcv2ids.m
index 85f6a664..90752abd 100644
--- a/matlab/TCV_IMAS/tcv2ids.m
+++ b/matlab/TCV_IMAS/tcv2ids.m
@@ -123,6 +123,13 @@ for i=1:length(gdat_params_fields)
   end
 end
 gdat_params.data_request = 'ids';
+
+%Check that the shot did not disrupt very early.
+t_disrupted = gdat(shot,'time_disrupted()');
+if t_disrupted.data <= 0.04 | t_disrupted.data > 128
+  error('the shot disrupted')
+end
+
 for i=1:length(params_tcv2ids.ids_names)
   ids_to_get = params_tcv2ids.ids_names{i};
   gdat_params.source = ids_to_get;
-- 
GitLab


From 401210d1caa9f134fecc78bd7082ecb2b5125847 Mon Sep 17 00:00:00 2001
From: Michele Marin <michele.marin@epfl.ch>
Date: Tue, 18 Feb 2025 19:19:17 +0100
Subject: [PATCH 03/11] Add errorbars for ion temperature and impurity density

---
 matlab/TCV_IMAS/tcv_get_ids_core_profiles.m | 81 +++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
index 00b87105..92a735ff 100644
--- a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
+++ b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
@@ -292,6 +292,25 @@ else
   params_eff_fit1.source = [1,2,3];
 end
 
+params_eff_fit1.data_request = 'results.conf:ni';
+temp_1d.ni_conf_rho = gdat(params_cores_profiles.shot,params_eff_fit1);
+temp_1d_desc.ni_conf_rho = params_eff_fit1.data_request;
+if ~isempty(temp_1d.cxrs_rho.data)
+  data_fullpath_raw = 'ni(C sometimes B) from cxrs system 1 to 3';
+  temp_1d.ni.raw = temp_1d.cxrs_rho.ni.raw;
+  temp_1d.ni.raw.shot = temp_1d.cxrs_rho.shot;temp_1d.ni.raw.gdat_params = temp_1d.cxrs_rho.gdat_params;
+  temp_1d.ni.raw.x =temp_1d.cxrs_rho.ni.raw.rho; temp_1d.ni.raw.t =temp_1d.cxrs_rho.t;
+  if ~isempty(temp_1d.cxrs_rho.ni.raw.data)
+    data_fullpath_fit = 'ni from fit from cxrs thus ni(C)';
+    temp_1d.ni.raw =get_grids_1d(temp_1d.ni.raw,2,1);
+  else
+    data_fullpath_fit = 'ni from fit in CONF node';
+  end
+else
+  data_fullpath_fit = 'ni from fit in CONF node';
+end
+
+
 temp_1d.ni.fit = temp_1d.ni_conf_rho;
 temp_1d.ni.fit =get_grids_1d(temp_1d.ni.fit,1,1);
 temp_1d_desc.ni.fit = temp_1d_desc.ni_conf_rho;
@@ -353,6 +372,68 @@ if ~isempty(temp_1d.cxrs_rho.data) && ~isempty(temp_1d.cxrs_rho.ti.fit.data)
   end
 end
 
+if ~isempty(temp_1d.cxrs_rho.error_bar)
+  switch error_bar
+   case 'delta'
+     for it=1:length(ids_core_profiles.time)
+       ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured_error_upper = temp_1d.cxrs_rho.ti.raw.error_bar(:,it_raw(it));
+       ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured_error_upper = temp_1d.cxrs_rho.ti.raw.error_bar(:,it_raw(it));
+       ids_core_profiles.profiles_1d{it}.t_i_average_fit.rho_tor_norm = temp_1d.cxrs_rho.ti.raw.rho(:,it_raw(it));
+       ids_core_profiles.profiles_1d{it}.t_i_average_fit.rho_tor_norm_error_upper = temp_1d.cxrs_rho.ti.raw.error_bar_rho(:,it_raw(it));
+       ids_core_profiles.profiles_1d{it}.t_i_average_fit.time_measurement = temp_1d.ti.raw.t(it_raw(it));
+     end
+   case 'delta_with_lower'
+     for it=1:length(ids_core_profiles.time)
+       ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured_error_upper = temp_1d.cxrs_rho.error_bar(:,it_thom(it));
+       ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured_error_lower = ...
+           ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured_error_upper;
+       ids_core_profiles.profiles_1d{it}.t_i_average_fit.time_measurement = temp_1d.ti.raw.t(it_raw(it));
+     end
+   case 'added'
+     for it=1:length(ids_core_profiles.time)
+       ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured_error_upper = ...
+           ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured ...
+           + temp_1d.cxrs_rho.error_bar(:,it_thom(it));
+       ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured_error_lower = ...
+           ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured ...
+           - temp_1d.cxrs_rho.error_bar(:,it_thom(it));
+       ids_core_profiles.profiles_1d{it}.t_i_average_fit.time_measurement = temp_1d.ti.raw.t(it_raw(it));
+     end
+   otherwise
+     error(['tcv_ids_cxrs_extraction: error_bar option not known: ' error_bar])
+  end
+  switch error_bar
+   case 'delta'
+     for it=1:length(ids_core_profiles.time)
+       ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured_error_upper = temp_1d.cxrs_rho.ni.raw.error_bar(:,it_raw(it));
+       ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured_error_upper = temp_1d.cxrs_rho.ni.raw.error_bar(:,it_raw(it));
+       ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.rho_tor_norm = temp_1d.cxrs_rho.ni.raw.rho(:,it_raw(it));
+       ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.rho_tor_norm_error_upper = temp_1d.cxrs_rho.ni.raw.error_bar_rho(:,it_raw(it));
+       ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.time_measurement = temp_1d.ni.raw.t(it_raw(it));
+     end
+   case 'delta_with_lower'
+     for it=1:length(ids_core_profiles.time)
+       ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured_error_upper = temp_1d.cxrs_rho.error_bar(:,it_thom(it));
+       ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured_error_lower = ...
+           ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured_error_upper;
+       ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.time_measurement = temp_1d.ni.raw.t(it_raw(it));
+     end
+   case 'added'
+     for it=1:length(ids_core_profiles.time)
+       ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured_error_upper = ...
+           ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured ...
+           + temp_1d.cxrs_rho.error_bar(:,it_thom(it));
+       ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured_error_lower = ...
+           ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured ...
+           - temp_1d.cxrs_rho.error_bar(:,it_thom(it));
+       ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.time_measurement = temp_1d.ni.raw.t(it_raw(it));
+     end
+   otherwise
+     error(['tcv_ids_cxrs_extraction: error_bar option not known: ' error_bar])
+  end
+end
+
+
 %% q profile and magnetic shear
 params_eff.data_request = 'q_rho';
 temp_1d.q = gdat(params_cores_profiles.shot,params_eff);
-- 
GitLab


From f1617a0ceead352331cc21c03c50286e2a6f118b Mon Sep 17 00:00:00 2001
From: Michele Marin <michele.marin@epfl.ch>
Date: Tue, 18 Mar 2025 19:23:45 +0100
Subject: [PATCH 04/11] draft start improvements

---
 matlab/TCV_IMAS/tcv_get_ids_core_profiles.m | 62 +++++++++++++++++++--
 1 file changed, 57 insertions(+), 5 deletions(-)

diff --git a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
index 92a735ff..cd43b682 100644
--- a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
+++ b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
@@ -260,12 +260,10 @@ catch
   temp_1d.cxrs_rho.error_bar = [];
   temp_1d_desc.cxrs_rho = ['Problem with gdat ' params_eff_fit1.data_request ' ; no data'];
 end
+
 params_eff_fit1.data_request = 'results.conf:ti';
 temp_1d.ti_conf_rho = gdat(params_cores_profiles.shot,params_eff_fit1);
 temp_1d_desc.ti_conf_rho = params_eff_fit1.data_request;
-params_eff_fit1.data_request = 'results.conf:ni';
-temp_1d.ni_conf_rho = gdat(params_cores_profiles.shot,params_eff_fit1);
-temp_1d_desc.ni_conf_rho = params_eff_fit1.data_request;
 if ~isempty(temp_1d.cxrs_rho.data)
   data_fullpath_raw = 'Ti(C sometimes B) from cxrs system 1 to 3';
   temp_1d.ti.raw = temp_1d.cxrs_rho.ti.raw;
@@ -292,6 +290,15 @@ else
   params_eff_fit1.source = [1,2,3];
 end
 
+try
+  temp_1d.cxrs_rho = gdat(params_cores_profiles.shot,params_eff_fit1);
+  temp_1d_desc.cxrs_rho = params_eff_fit1.data_request;
+catch
+  temp_1d.cxrs_rho.data = [];
+  temp_1d.cxrs_rho.error_bar = [];
+  temp_1d_desc.cxrs_rho = ['Problem with gdat ' params_eff_fit1.data_request ' ; no data'];
+end
+
 params_eff_fit1.data_request = 'results.conf:ni';
 temp_1d.ni_conf_rho = gdat(params_cores_profiles.shot,params_eff_fit1);
 temp_1d_desc.ni_conf_rho = params_eff_fit1.data_request;
@@ -348,6 +355,7 @@ for it=1:length(ids_core_profiles.time)
   ids_core_profiles.profiles_1d{it}.ion{2}.z_ion = 6.;
   ids_core_profiles.profiles_1d{it}.ion{2}.multiple_states_flag = 0;
   ids_core_profiles.profiles_1d{it}.ion{2}.temperature = ids_core_profiles.profiles_1d{it}.ion{1}.temperature;
+
   ids_core_profiles.profiles_1d{it}.ion{2}.density = (ids_core_profiles.profiles_1d{it}.electrons.density - ids_core_profiles.profiles_1d{it}.ion{1}.density) ./ ids_core_profiles.profiles_1d{it}.ion{2}.z_ion;
   ids_core_profiles.profiles_1d{it}.ion{2}.density_thermal = ids_core_profiles.profiles_1d{it}.ion{2}.density;
   ids_core_profiles.profiles_1d{it}.ion{2}.pressure_thermal = 1.6022e-19.*ids_core_profiles.profiles_1d{it}.ion{2}.density_thermal ...
@@ -365,13 +373,48 @@ end
 if ~isempty(temp_1d.cxrs_rho.data) && ~isempty(temp_1d.cxrs_rho.ti.fit.data)
   it_raw = iround_os(temp_1d.ti.raw.t,ids_core_profiles.time);
   for it=1:length(ids_core_profiles.time)
-    % ids_core_profiles.profiles_1d{it}.ion{1}.temperature_fit = temp_1d.ti.fit(:,it_ti(it));
-    ids_core_profiles.profiles_1d{it}.ion{1}.density_fit.source = {'from Zeff and ne profile'};
+    % ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit.measured = temp_1d.ti.fit(:,it_ti(it));
+    ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit.measured = temp_1d.ti.raw.data(:,it_raw(it));
+    ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit.source = {'from CXRS on C usually'};
+    ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured = temp_1d.ni.fit(:,it_ti(it));
+    ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.source = {'from CXRS on C usually'};
+
+    ids_core_profiles.profiles_1d{it}.ion{1}.temperature_fit = ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit
+    ids_core_profiles.profiles_1d{it}.ion{1}.density_fit.source = {'from CXRS on C usually, same as C temperature'};
+
     ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured = temp_1d.ti.raw.data(:,it_raw(it));
     ids_core_profiles.profiles_1d{it}.t_i_average_fit.source = {'from CXRS on C usually'};
   end
 end
 
+
+time_measurement_slice_method
+time_measurement_slice_method.name='exact' or 'local'
+time_measurement_slice_method.index=0
+time_measurement_slice_method.description='using Thomson scattering measurement at the given time'
+time_measurement_width
+
+time_measurement_slice_method
+time_measurement_slice_method.name='exact' or 'local'
+time_measurement_slice_method.index=0
+time_measurement_slice_method.description='using Thomson scattering measurement at the given time'
+local = 1
+chi_squared = \tcv_shot::top.results.proffit.avg_time:teft_chi2
+
+time_measurement_width(:) = gdat(84927,'\tcv_shot::top.results.proffit.avg_time:time_avg','doplot',1); % nargout = 1
+
+
+% I am guessing that in gdat params_eff.fit_type = 'avg' takes the data from the avg_time and not local_time proffit nodes?
+name='exact' or 'local'
+index=0
+description='using Thomson scattering measurement at the given time'
+(if only one TS laser time was used )
+or may be:
+name='avg' or 'average'
+index=-1
+description='average with TS at this time and other TS within +-delta_t' (delta_t is provided in the proffit:local tree), conf should know if nodes from local or avg
+
+
 if ~isempty(temp_1d.cxrs_rho.error_bar)
   switch error_bar
    case 'delta'
@@ -434,6 +477,15 @@ if ~isempty(temp_1d.cxrs_rho.error_bar)
 end
 
 
+%For the time integration of the Charge Exchange
+timer_nodes = String2Struct(mdsdata('\ATLAS::CXRS_00X.ACQ:TIMING'));
+mdsdata(timer_nodes.PeriodName)
+
+
+
+
+
+
 %% q profile and magnetic shear
 params_eff.data_request = 'q_rho';
 temp_1d.q = gdat(params_cores_profiles.shot,params_eff);
-- 
GitLab


From 0580b1639c366634a6e3015a8c595501f48b813f Mon Sep 17 00:00:00 2001
From: Michele Marin <michele.marin@epfl.ch>
Date: Wed, 19 Mar 2025 22:37:08 +0100
Subject: [PATCH 05/11] work in progress

---
 matlab/TCV_IMAS/tcv_get_ids_core_profiles.m | 28 +++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
index cd43b682..5041dde7 100644
--- a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
+++ b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
@@ -162,6 +162,34 @@ for ir=1:length(temp_1d.area.x) % map tmp_1d.area to core_profiles.time
   area_cpt(ir,:) = interpos(temp_1d.area.t,temp_1d.area.data(ir,:),ids_core_profiles.time,tens_time);
 end
 
+
+%% ----------------------------- WORK IN PROGRESS ----------------------------------
+
+% Need to check if the temperature is local or averaged. Best way is to check the data themselves
+
+te_local_time = gdat(params_cores_profiles.shot, /'proffit:local_time:teft');
+te_avg_time = gdat(params_cores_profiles.shot, /'proffit:avg_time:teft');
+
+te_conf = gdat(params_cores_profiles.shot, /'results::conf:te');
+
+% Getting the call done to get the data in the description
+
+te_info = gdat(params_cores_profiles.shot, '\results::proffit:subcall:trial');
+te_profit_calls = te_info.data;
+te_profit_standard_call = te_profit_calls{2};
+
+
+
+
+%% ----------------------------- WORK IN PROGRESS ---------------------------------
+
+[aa, bb] = hldsi(shot);
+
+
+
+
+
+
 it_thom = iround_os(temp_1d.te_rho.t,ids_core_profiles.time);
 for it=1:length(ids_core_profiles.time)
   % fill grid
-- 
GitLab


From 51de653bd7839441e30e30a9a92a2e4fb506d04f Mon Sep 17 00:00:00 2001
From: Michele Marin <michele.marin@epfl.ch>
Date: Fri, 11 Apr 2025 12:09:05 +0200
Subject: [PATCH 06/11] adding work in progress sections

---
 matlab/TCV_IMAS/tcv_get_ids_core_profiles.m | 50 +++++++++++----------
 1 file changed, 26 insertions(+), 24 deletions(-)

diff --git a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
index 5041dde7..54fe0b3c 100644
--- a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
+++ b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
@@ -167,10 +167,10 @@ end
 
 % Need to check if the temperature is local or averaged. Best way is to check the data themselves
 
-te_local_time = gdat(params_cores_profiles.shot, /'proffit:local_time:teft');
-te_avg_time = gdat(params_cores_profiles.shot, /'proffit:avg_time:teft');
+te_local_time = gdat(params_cores_profiles.shot, '\proffit:local_time:teft');
+te_avg_time = gdat(params_cores_profiles.shot, '\proffit:avg_time:teft');
 
-te_conf = gdat(params_cores_profiles.shot, /'results::conf:te');
+te_conf = gdat(params_cores_profiles.shot, '\results::conf:te');
 
 % Getting the call done to get the data in the description
 
@@ -185,7 +185,9 @@ te_profit_standard_call = te_profit_calls{2};
 
 [aa, bb] = hldsi(shot);
 
-
+aa
+bb
+return
 
 
 
@@ -416,31 +418,31 @@ if ~isempty(temp_1d.cxrs_rho.data) && ~isempty(temp_1d.cxrs_rho.ti.fit.data)
 end
 
 
-time_measurement_slice_method
-time_measurement_slice_method.name='exact' or 'local'
-time_measurement_slice_method.index=0
-time_measurement_slice_method.description='using Thomson scattering measurement at the given time'
-time_measurement_width
+%time_measurement_slice_method
+%time_measurement_slice_method.name='exact' or 'local'
+%time_measurement_slice_method.index=0
+%time_measurement_slice_method.description='using Thomson scattering measurement at the given time'
+%time_measurement_width
 
-time_measurement_slice_method
-time_measurement_slice_method.name='exact' or 'local'
-time_measurement_slice_method.index=0
-time_measurement_slice_method.description='using Thomson scattering measurement at the given time'
-local = 1
-chi_squared = \tcv_shot::top.results.proffit.avg_time:teft_chi2
+%time_measurement_slice_method
+%time_measurement_slice_method.name='exact' or 'local'
+%time_measurement_slice_method.index=0
+%time_measurement_slice_method.description='using Thomson scattering measurement at the given time'
+%local = 1
+%chi_squared = \tcv_shot::top.results.proffit.avg_time:teft_chi2
 
-time_measurement_width(:) = gdat(84927,'\tcv_shot::top.results.proffit.avg_time:time_avg','doplot',1); % nargout = 1
+%time_measurement_width(:) = gdat(84927,'\tcv_shot::top.results.proffit.avg_time:time_avg','doplot',1); % nargout = 1
 
 
 % I am guessing that in gdat params_eff.fit_type = 'avg' takes the data from the avg_time and not local_time proffit nodes?
-name='exact' or 'local'
-index=0
-description='using Thomson scattering measurement at the given time'
-(if only one TS laser time was used )
-or may be:
-name='avg' or 'average'
-index=-1
-description='average with TS at this time and other TS within +-delta_t' (delta_t is provided in the proffit:local tree), conf should know if nodes from local or avg
+%name='exact' or 'local'
+%index=0
+%description='using Thomson scattering measurement at the given time'
+%(if only one TS laser time was used )
+%or may be:
+%name='avg' or 'average'
+%index=-1
+%description='average with TS at this time and other TS within +-delta_t' (delta_t is provided in the proffit:local tree), conf should know if nodes from local or avg
 
 
 if ~isempty(temp_1d.cxrs_rho.error_bar)
-- 
GitLab


From 8d12cdd3992c6c1e66f3cf93afd156ae707043c5 Mon Sep 17 00:00:00 2001
From: Michele Marin <michele.marin@epfl.ch>
Date: Tue, 15 Apr 2025 16:09:47 +0200
Subject: [PATCH 07/11] First draft checks on cxrs dependencies

---
 matlab/TCV_IMAS/tcv2ids.m                   |  1 +
 matlab/TCV_IMAS/tcv2ids2database.m          |  5 ++
 matlab/TCV_IMAS/tcv_get_ids_core_profiles.m | 51 +++++++++++++--------
 3 files changed, 38 insertions(+), 19 deletions(-)

diff --git a/matlab/TCV_IMAS/tcv2ids.m b/matlab/TCV_IMAS/tcv2ids.m
index 90752abd..b06f247a 100644
--- a/matlab/TCV_IMAS/tcv2ids.m
+++ b/matlab/TCV_IMAS/tcv2ids.m
@@ -56,6 +56,7 @@ p.addOptional('trialindx', [], @(x) isempty(x) || isnumeric(x) );
 p.addOptional('liuqe', [], @(x) isempty(x) || isnumeric(x) );
 p.addOptional('cxrs_source_ti', [], @(x) isempty(x) || isnumeric(x) );
 p.addOptional('cxrs_source_ni', [], @(x) isempty(x) || isnumeric(x) );
+p.addOptional('ignore_dependencies', [], @(x) isempty(x) || isnumeric(x) );
 
 params_not_for_gdat_params = {'shot','ids_names'};
 
diff --git a/matlab/TCV_IMAS/tcv2ids2database.m b/matlab/TCV_IMAS/tcv2ids2database.m
index 2c7de5b6..57a1e6f0 100644
--- a/matlab/TCV_IMAS/tcv2ids2database.m
+++ b/matlab/TCV_IMAS/tcv2ids2database.m
@@ -24,6 +24,9 @@ function [ids_from_tcv,varargout] = tcv2ids2database(shot,run_out,varargin);
 %           'time_out': if 2 values provided: get all time data within that time interval
 %                       otherwise get values at these times provided in time_out (with linear interpolation and cst extrapolation)
 %           'trialindx': trial_indx for relevant nodes, in particular CONF kinetic profiles nodes
+%           'cxrs_source_ti': specify which sources to use for the charge exchange data and fits of ion temperature. Default all (1,2,3)
+%	    'cxrs_source_ni': specify which sources to use for the charge exchange data and fits of impurity density. Default all (1,2,3)
+%           'ignore_dependencies': ignore unfulfilled dependencies in extracting cxrs data
 %
 % example:
 %   ids_from_tcv = tcv2ids2database(62745,9999,'ids_names',{'pf_active'},'error_bar','added'); % to test only one ids
@@ -65,6 +68,8 @@ p.addOptional('time_out', [], @(x) isempty(x) || isnumeric(x) );
 p.addOptional('trialindx', [], @(x) isempty(x) || isnumeric(x) );
 p.addOptional('cxrs_source_ti', [], @(x) isempty(x) || isnumeric(x) );
 p.addOptional('cxrs_source_ni', [], @(x) isempty(x) || isnumeric(x) );
+p.addOptional('ignore_dependencies', [], @(x) isempty(x) || isnumeric(x) );
+
 
 p.parse;
 defaults_tcv2ids2database = p.Results; % to keep track of defaults
diff --git a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
index 54fe0b3c..87b39f1c 100644
--- a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
+++ b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
@@ -167,28 +167,19 @@ end
 
 % Need to check if the temperature is local or averaged. Best way is to check the data themselves
 
-te_local_time = gdat(params_cores_profiles.shot, '\proffit:local_time:teft');
-te_avg_time = gdat(params_cores_profiles.shot, '\proffit:avg_time:teft');
-
-te_conf = gdat(params_cores_profiles.shot, '\results::conf:te');
-
-% Getting the call done to get the data in the description
-
-te_info = gdat(params_cores_profiles.shot, '\results::proffit:subcall:trial');
-te_profit_calls = te_info.data;
-te_profit_standard_call = te_profit_calls{2};
-
+%te_local_time = gdat(params_cores_profiles.shot, '\proffit:local_time:teft');
+%te_avg_time = gdat(params_cores_profiles.shot, '\proffit:avg_time:teft');
 
+%te_local_time.t
+%te_avg_time.t
 
+%te_conf = gdat(params_cores_profiles.shot, '\results::conf:te');
 
-%% ----------------------------- WORK IN PROGRESS ---------------------------------
-
-[aa, bb] = hldsi(shot);
-
-aa
-bb
-return
+% Getting the call done to get the data in the description
 
+%te_info = gdat(params_cores_profiles.shot, '\results::proffit:subcall:trial');
+%te_profit_calls = te_info.data;
+%te_profit_standard_call = te_profit_calls{2};
 
 
 
@@ -275,8 +266,29 @@ end
 % assume only D if no CXRS (need to ask how to check if H...)
 params_eff_fit1.data_request = 'cxrs';
 
+% Check that CXRS exists and that the fits are updated. Stop the generation if action should be taken.
+[index_hldsi, info_hldsi] = hldsi(params_cores_profiles.shot);
+
+if isfield(info_hldsi.CXRS, 'timefilled')
+  date_CXRS = datetime(info_hldsi.CXRS.timefilled, 'InputFormat', 'dd-MMM-yyyy HH:mm:ss.SS');
+  date_CONF = datetime(info_hldsi.CONF.timefilled, 'InputFormat', 'dd-MMM-yyyy HH:mm:ss.SS');
+
+  if date_CXRS > date_CONF
+    if (info_hldsi.CONF.trialindex{2}.index == 1) &&  strcmpi(info_hldsi.CONF.trialindex{2}.user{1}, 'ANANOCD_ANASRV ')
+      warning('Fits in conf nodes are not up to date with CXRS analysis.')
+      disp('Please run [status, info] = anaprofs_standard_no_currentdrive(shot,username,global_option);')
+    else
+      warning('Fits in conf nodes are not up to date with CXRS analysis.')
+      disp(strjoin({'The analysis was not automatic. Contact', info_hldsi.CONF.trialindex{2}.user{1}, 'for more info'}, ' '))
+    end
+    if ~isfield(gdat_params, 'ignore_dependencies')
+      error('Use the ignore_dependencies flag to extract the data anyway');
+    end
+  end
+end
+
 % Extract ti here
-if  isfield(gdat_params, 'cxrs_source_ti')
+if isfield(gdat_params, 'cxrs_source_ti')
   params_eff_fit1.source = gdat_params.cxrs_source_ti;
 else
   params_eff_fit1.source = [1,2,3];
@@ -314,6 +326,7 @@ temp_1d.ti.fit =get_grids_1d(temp_1d.ti.fit,1,1);
 temp_1d_desc.ti.fit = temp_1d_desc.ti_conf_rho;
 
 % Extract ni here
+params_eff_fit1.data_request = 'cxrs';
 if  isfield(gdat_params, 'cxrs_source_ni')
   params_eff_fit1.source = gdat_params.cxrs_source_ni;
 else
-- 
GitLab


From 8dabc3fbf0956d363edef892f04bd6e196d08259 Mon Sep 17 00:00:00 2001
From: Michele Marin <michele.marin@epfl.ch>
Date: Tue, 15 Apr 2025 20:19:06 +0200
Subject: [PATCH 08/11] Improve description of cxrs data origin

---
 matlab/TCV_IMAS/tcv_get_ids_core_profiles.m | 50 ++++++++++++---------
 1 file changed, 28 insertions(+), 22 deletions(-)

diff --git a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
index 87b39f1c..cd139436 100644
--- a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
+++ b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
@@ -285,6 +285,8 @@ if isfield(info_hldsi.CXRS, 'timefilled')
       error('Use the ignore_dependencies flag to extract the data anyway');
     end
   end
+else
+  warning('CXRS analysis was not performed. Please rerun if data is available')
 end
 
 % Extract ti here
@@ -305,9 +307,9 @@ end
 
 params_eff_fit1.data_request = 'results.conf:ti';
 temp_1d.ti_conf_rho = gdat(params_cores_profiles.shot,params_eff_fit1);
-temp_1d_desc.ti_conf_rho = params_eff_fit1.data_request;
+temp_1d_desc.ti_conf_rho = [params_eff_fit1.data_request, ' which took data from ', temp_1d.ti_conf_rho.help];
 if ~isempty(temp_1d.cxrs_rho.data)
-  data_fullpath_raw = 'Ti(C sometimes B) from cxrs system 1 to 3';
+  data_fullpath_raw = ['Ti(C sometimes B) from cxrs system(s) ', char(strjoin(string(params_eff_fit1.source), ', '))];
   temp_1d.ti.raw = temp_1d.cxrs_rho.ti.raw;
   temp_1d.ti.raw.shot = temp_1d.cxrs_rho.shot;temp_1d.ti.raw.gdat_params = temp_1d.cxrs_rho.gdat_params;
   temp_1d.ti.raw.x =temp_1d.cxrs_rho.ti.raw.rho; temp_1d.ti.raw.t =temp_1d.cxrs_rho.t;
@@ -315,15 +317,17 @@ if ~isempty(temp_1d.cxrs_rho.data)
     data_fullpath_fit = 'Ti from fit from cxrs thus Ti(C)';
     temp_1d.ti.raw =get_grids_1d(temp_1d.ti.raw,2,1);
   else
-    data_fullpath_fit = 'Ti from fit in CONF node';
+    data_fullpath_fit = ['Ti from fit in CONF node, from call ', temp_1d_desc.ti_conf_rho];
   end
 else
-  data_fullpath_fit = 'Ti from fit in CONF node';
+  data_fullpath_fit = ['Ti from fit in CONF node, from call ', temp_1d_desc.ti_conf_rho];
 end
-temp_1d_desc.ti.raw = data_fullpath_fit;
+
 temp_1d.ti.fit = temp_1d.ti_conf_rho;
 temp_1d.ti.fit =get_grids_1d(temp_1d.ti.fit,1,1);
-temp_1d_desc.ti.fit = temp_1d_desc.ti_conf_rho;
+temp_1d_desc.ti.raw = data_fullpath_raw;
+temp_1d_desc.ti.fit = data_fullpath_fit;
+temp_1d_desc.ti.tot = ['Raw data taken from ', data_fullpath_raw, ' and fits taken from ', data_fullpath_fit];
 
 % Extract ni here
 params_eff_fit1.data_request = 'cxrs';
@@ -344,9 +348,9 @@ end
 
 params_eff_fit1.data_request = 'results.conf:ni';
 temp_1d.ni_conf_rho = gdat(params_cores_profiles.shot,params_eff_fit1);
-temp_1d_desc.ni_conf_rho = params_eff_fit1.data_request;
+temp_1d_desc.ni_conf_rho = [params_eff_fit1.data_request, ' which took data from ', temp_1d.ni_conf_rho.help];
 if ~isempty(temp_1d.cxrs_rho.data)
-  data_fullpath_raw = 'ni(C sometimes B) from cxrs system 1 to 3';
+  data_fullpath_raw = ['ni(C sometimes B) from cxrs system(s) ', char(strjoin(string(params_eff_fit1.source), ', '))];
   temp_1d.ni.raw = temp_1d.cxrs_rho.ni.raw;
   temp_1d.ni.raw.shot = temp_1d.cxrs_rho.shot;temp_1d.ni.raw.gdat_params = temp_1d.cxrs_rho.gdat_params;
   temp_1d.ni.raw.x =temp_1d.cxrs_rho.ni.raw.rho; temp_1d.ni.raw.t =temp_1d.cxrs_rho.t;
@@ -354,16 +358,17 @@ if ~isempty(temp_1d.cxrs_rho.data)
     data_fullpath_fit = 'ni from fit from cxrs thus ni(C)';
     temp_1d.ni.raw =get_grids_1d(temp_1d.ni.raw,2,1);
   else
-    data_fullpath_fit = 'ni from fit in CONF node';
+    data_fullpath_fit = ['ni from fit in CONF node, from call ', temp_1d_desc.ni_conf_rho];
   end
 else
-  data_fullpath_fit = 'ni from fit in CONF node';
+  data_fullpath_fit = ['ni from fit in CONF node, from call ', temp_1d_desc.ni_conf_rho];
 end
-
-
+temp_1d_desc.ni.raw = data_fullpath_fit;
 temp_1d.ni.fit = temp_1d.ni_conf_rho;
 temp_1d.ni.fit =get_grids_1d(temp_1d.ni.fit,1,1);
 temp_1d_desc.ni.fit = temp_1d_desc.ni_conf_rho;
+temp_1d_desc.ni.tot = ['Raw data taken from ', data_fullpath_raw, ' and fits taken from ', data_fullpath_fit];
+
 it_ti = iround_os(temp_1d.ti.fit.t,ids_core_profiles.time);
 % assumed 1 impurity with Zp=6
 Zp = 6.;
@@ -416,17 +421,18 @@ end
 if ~isempty(temp_1d.cxrs_rho.data) && ~isempty(temp_1d.cxrs_rho.ti.fit.data)
   it_raw = iround_os(temp_1d.ti.raw.t,ids_core_profiles.time);
   for it=1:length(ids_core_profiles.time)
-    % ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit.measured = temp_1d.ti.fit(:,it_ti(it));
     ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit.measured = temp_1d.ti.raw.data(:,it_raw(it));
-    ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit.source = {'from CXRS on C usually'};
-    ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured = temp_1d.ni.fit(:,it_ti(it));
-    ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.source = {'from CXRS on C usually'};
+    ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit.source = temp_1d_desc.ti.tot;
+    temp_1d_desc.ti.tot
+    return
+    ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured = temp_1d.ni.raw.data(:,it_raw(it));
+    ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.source = temp_1d_desc.ni.tot;
 
-    ids_core_profiles.profiles_1d{it}.ion{1}.temperature_fit = ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit
-    ids_core_profiles.profiles_1d{it}.ion{1}.density_fit.source = {'from CXRS on C usually, same as C temperature'};
+    ids_core_profiles.profiles_1d{it}.ion{1}.temperature_fit = ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit;
+    ids_core_profiles.profiles_1d{it}.ion{1}.density_fit.source = {'Same as C temperature'};
 
-    ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured = temp_1d.ti.raw.data(:,it_raw(it));
-    ids_core_profiles.profiles_1d{it}.t_i_average_fit.source = {'from CXRS on C usually'};
+    ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured = ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit;
+    ids_core_profiles.profiles_1d{it}.t_i_average_fit.source = {'Same as C temperature'};
   end
 end
 
@@ -521,8 +527,8 @@ end
 
 
 %For the time integration of the Charge Exchange
-timer_nodes = String2Struct(mdsdata('\ATLAS::CXRS_00X.ACQ:TIMING'));
-mdsdata(timer_nodes.PeriodName)
+%timer_nodes = String2Struct(mdsdata('\ATLAS::CXRS_00X.ACQ:TIMING'));
+%mdsdata(timer_nodes.PeriodName)
 
 
 
-- 
GitLab


From d729dffe2a9f2ff938bbbe6ccefce538f29bbdf6 Mon Sep 17 00:00:00 2001
From: Michele Marin <michele.marin@epfl.ch>
Date: Wed, 30 Apr 2025 11:27:36 +0200
Subject: [PATCH 09/11] adding widths and extra descriptions for experimental
 data. Add errorbars for version > 2

---
 matlab/TCV_IMAS/tcv_get_ids_core_profiles.m | 179 +++++++++++++-------
 1 file changed, 121 insertions(+), 58 deletions(-)

diff --git a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
index cd139436..23c36b37 100644
--- a/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
+++ b/matlab/TCV_IMAS/tcv_get_ids_core_profiles.m
@@ -23,6 +23,16 @@ machine = 'tcv';
 tens_time = -1;
 tens_rho = -0.1;
 
+% Extract imas version
+imas_version_path = which('ids_gen');
+tokens = regexp(imas_version_path, 'IMAS/(\d+)', 'tokens');
+
+if ~isempty(tokens)
+    imas_major_version = str2double(tokens{1}{1});
+else
+    error('Problems loading IMAS');
+end
+
 if exist('gdat_params','var')
   [ids_core_profiles, params_cores_profiles] = ...
     tcv_ids_headpart(shot,ids_equil_empty,'cores_profiles','gdat_params',gdat_params,varargin{:});
@@ -35,6 +45,23 @@ end
 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)
 
+
+% Find the times for cxrs integration for the various cxrs systems
+system_ref = '\\ATLAS::CXRS_%03d.ACQ:TIMING'; %or '\tcv_shot::top.atlas.acquired.cxrs.system_001.acq:timing'
+times_cxrs_integration = [];
+for ii = 1:12
+  system_names = sprintf(system_ref, ii);
+  warning('off');
+  timings_cxrs = gdat(params_cores_profiles.shot,system_names);
+  warning('off');
+  if timings_cxrs.data
+    period_name = regexp(timings_cxrs.data, 'PeriodName=''([^'']*)''', 'tokens', 'once');
+    time = gdat(params_cores_profiles.shot, period_name);
+    times_cxrs_integration = [times_cxrs_integration,time.data*1e-6];
+  end
+end
+
+
 % initialize description
 ids_core_profiles_description = [];
 
@@ -162,26 +189,31 @@ for ir=1:length(temp_1d.area.x) % map tmp_1d.area to core_profiles.time
   area_cpt(ir,:) = interpos(temp_1d.area.t,temp_1d.area.data(ir,:),ids_core_profiles.time,tens_time);
 end
 
-
-%% ----------------------------- WORK IN PROGRESS ----------------------------------
-
+%% Extracting info about Thomson data
 % Need to check if the temperature is local or averaged. Best way is to check the data themselves
+te_local_time = gdat(params_cores_profiles.shot, '\proffit:local_time:teft');
+te_avg_time = gdat(params_cores_profiles.shot, '\proffit:avg_time:teft');
+te_conf = gdat(params_cores_profiles.shot, '\results::conf:te');
+
+if isequal(te_local_time.t, te_conf.t) || isequal(te_local_time.t, te_avg_time.t)
+  thomson_description = 'using Thomson scattering measurement at the given time';
+elseif isequal(te_avg_time.t, te_conf.t)
+  thomson_description = 'using Thomson scattering measurement averaged over respective width';
+else
+  thomson_description = 'unrecongnized';
+  warning('Time series for Thomson not recognized. Check CONF nodes')
+end
 
-%te_local_time = gdat(params_cores_profiles.shot, '\proffit:local_time:teft');
-%te_avg_time = gdat(params_cores_profiles.shot, '\proffit:avg_time:teft');
-
-%te_local_time.t
-%te_avg_time.t
-
-%te_conf = gdat(params_cores_profiles.shot, '\results::conf:te');
-
-% Getting the call done to get the data in the description
-
-%te_info = gdat(params_cores_profiles.shot, '\results::proffit:subcall:trial');
-%te_profit_calls = te_info.data;
-%te_profit_standard_call = te_profit_calls{2};
+% Dimension is larger but times are the same, data exists after the end of the shot till end of acquisition.
+% This is for now not used anywhere. The IDS chi_squared is for each datapoint, this is for the whole profile
+% To calculate individual chi_squared the weights are needed. Where are they stored?
+params_eff.data_request = '\tcv_shot::top.results.proffit.avg_time:teft_chi2';
+temp_1d.te_rho.chi_squared = gdat(params_cores_profiles.shot, params_eff);
+temp_1d_desc.te_rho_chi_squared = params_eff.data_request;
 
 
+time_measurement_width_all = gdat(params_cores_profiles.shot,'\tcv_shot::top.results.proffit.avg_time:time_avg');
+time_measurement_width_thomson = time_measurement_width_all.data(1) - time_measurement_width_all.data(2);
 
 it_thom = iround_os(temp_1d.te_rho.t,ids_core_profiles.time);
 for it=1:length(ids_core_profiles.time)
@@ -206,6 +238,13 @@ for it=1:length(ids_core_profiles.time)
       size(ids_core_profiles.profiles_1d{it}.electrons.temperature_fit.measured));
   ids_core_profiles.profiles_1d{it}.electrons.temperature_fit.rho_tor_norm = temp_1d.te_rho.grids_1d.rhotornorm(:,it_thom(it));
   ids_core_profiles.profiles_1d{it}.electrons.temperature_fit.source = {'Thomson, interpos fit'};
+  ids_core_profiles.profiles_1d{it}.electrons.temperature_fit.time_measurement_slice_method.name='local';
+  ids_core_profiles.profiles_1d{it}.electrons.temperature_fit.time_measurement_slice_method.index=0;
+  ids_core_profiles.profiles_1d{it}.electrons.temperature_fit.time_measurement_slice_method.description= thomson_description;
+  ids_core_profiles.profiles_1d{it}.electrons.temperature_fit.local = 1;
+  %ids_core_profiles.profiles_1d{it}.electrons.temperature_fit.chi_squared = 
+  ids_core_profiles.profiles_1d{it}.electrons.temperature_fit.time_measurement_width = time_measurement_width_thomson;
+
   ids_core_profiles.profiles_1d{it}.electrons.density = temp_1d.fit.ne_rho.data(:,it);
   ids_core_profiles.profiles_1d{it}.electrons.density_thermal = ids_core_profiles.profiles_1d{it}.electrons.density;
   ids_core_profiles.profiles_1d{it}.electrons.density_fit.measured = temp_1d.ne_rho.data(:,it_thom(it));
@@ -213,6 +252,14 @@ for it=1:length(ids_core_profiles.time)
       size(ids_core_profiles.profiles_1d{it}.electrons.density_fit.measured));
   ids_core_profiles.profiles_1d{it}.electrons.density_fit.rho_tor_norm = temp_1d.ne_rho.grids_1d.rhotornorm(:,it_thom(it));
   ids_core_profiles.profiles_1d{it}.electrons.density_fit.source = {'Thomson, interpos fit'};
+  ids_core_profiles.profiles_1d{it}.electrons.density_fit.time_measurement_slice_method.name='local';
+  ids_core_profiles.profiles_1d{it}.electrons.density_fit.time_measurement_slice_method.index=0;
+  ids_core_profiles.profiles_1d{it}.electrons.density_fit.time_measurement_slice_method.description= thomson_description;
+  ids_core_profiles.profiles_1d{it}.electrons.density_fit.local = 1;
+  %ids_core_profiles.profiles_1d{it}.electrons.density_fit.chi_squared = 
+  ids_core_profiles.profiles_1d{it}.electrons.density_fit.time_measurement_width = time_measurement_width_thomson;
+
+
   ids_core_profiles.profiles_1d{it}.electrons.pressure_thermal = 1.6022e-19.*ids_core_profiles.profiles_1d{it}.electrons.density_thermal ...
       .* ids_core_profiles.profiles_1d{it}.electrons.temperature;
   % fill zeff
@@ -220,6 +267,7 @@ for it=1:length(ids_core_profiles.time)
       ones(size(ids_core_profiles.profiles_1d{it}.electrons.density));
 end
 
+if imas_major_version > 2
 zeff_error = 0.5;
 switch error_bar
  case 'delta'
@@ -261,6 +309,7 @@ switch error_bar
  otherwise
   error(['tcv_ids_bpol_loop: error_bar option not known: ' error_bar])
 end
+end
 
 %% ion struct
 % assume only D if no CXRS (need to ask how to check if H...)
@@ -290,10 +339,12 @@ else
 end
 
 % Extract ti here
+all_sources = [1,2,3,4,7];
+
 if isfield(gdat_params, 'cxrs_source_ti')
   params_eff_fit1.source = gdat_params.cxrs_source_ti;
 else
-  params_eff_fit1.source = [1,2,3];
+  params_eff_fit1.source = all_sources;
 end
 
 try
@@ -334,7 +385,7 @@ params_eff_fit1.data_request = 'cxrs';
 if  isfield(gdat_params, 'cxrs_source_ni')
   params_eff_fit1.source = gdat_params.cxrs_source_ni;
 else
-  params_eff_fit1.source = [1,2,3];
+  params_eff_fit1.source = all_sources;
 end
 
 try
@@ -346,6 +397,48 @@ catch
   temp_1d_desc.cxrs_rho = ['Problem with gdat ' params_eff_fit1.data_request ' ; no data'];
 end
 
+% Extract sources to find integration time for each data
+mask_sources = zeros(size(temp_1d.cxrs_rho.ti.raw.data));
+
+% Retrive the source for each datapoint
+for isource = all_sources
+  try
+    params_eff_fit1.source = [isource];
+    temp_1d.cxrs_rho_partial = gdat(params_cores_profiles.shot,params_eff_fit1);
+    [isCommon, idxA] = ismember(temp_1d.cxrs_rho.ti.raw.data, temp_1d.cxrs_rho_partial.ti.raw.data);
+    isCommon = isource*isCommon;
+    mask_sources(isCommon ~= 0) = isCommon(isCommon ~= 0);
+  end
+end
+
+% Find the times for cxrs integration for the various cxrs systems
+system_ref = '\\ATLAS::CXRS_%03d.ACQ:TIMING'; %or '\tcv_shot::top.atlas.acquired.cxrs.system_001.acq:timing'
+times_cxrs_integration = [];
+for ii = 1:12
+  system_names = sprintf(system_ref, ii);
+  warning('off');
+  timings_cxrs = gdat(params_cores_profiles.shot,system_names);
+  warning('off');
+  if timings_cxrs.data
+    period_name = regexp(timings_cxrs.data, 'PeriodName=''([^'']*)''', 'tokens', 'once');
+    bursts_name = regexp(timings_cxrs.data, 'BurstsName=''([^'']*)''', 'tokens', 'once');
+
+    %period = gdat(params_cores_profiles.shot, period_name);
+    %bursts = gdat(params_cores_profiles.shot, bursts_name);
+    %time_aquisition = period.data * bursts.data;  %This is the total acquisition time in a shot.
+    time_acquisition = gdat(params_cores_profiles.shot, period_name);
+    times_cxrs_integration = [times_cxrs_integration,time_acquisition.data.*1e-6];
+  else
+    times_cxrs_integration = [times_cxrs_integration,0];
+  end
+end
+
+% Assign widths of integration time 
+widths = zeros(size(temp_1d.cxrs_rho.ti.raw.data));
+for isource = all_sources
+  widths(mask_sources == isource) = times_cxrs_integration(isource);
+end
+
 params_eff_fit1.data_request = 'results.conf:ni';
 temp_1d.ni_conf_rho = gdat(params_cores_profiles.shot,params_eff_fit1);
 temp_1d_desc.ni_conf_rho = [params_eff_fit1.data_request, ' which took data from ', temp_1d.ni_conf_rho.help];
@@ -423,48 +516,27 @@ if ~isempty(temp_1d.cxrs_rho.data) && ~isempty(temp_1d.cxrs_rho.ti.fit.data)
   for it=1:length(ids_core_profiles.time)
     ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit.measured = temp_1d.ti.raw.data(:,it_raw(it));
     ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit.source = temp_1d_desc.ti.tot;
-    temp_1d_desc.ti.tot
-    return
     ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.measured = temp_1d.ni.raw.data(:,it_raw(it));
     ids_core_profiles.profiles_1d{it}.ion{2}.density_fit.source = temp_1d_desc.ni.tot;
+    ids_core_profiles.profiles_1d{it}.ion{2}.rho_tor_norm = temp_1d.cxrs_rho.ti.raw.rho(:,it_raw(it));
+    ids_core_profiles.profiles_1d{it}.ion{2}.time_measurement = temp_1d.ti.raw.t(it_raw(it));
+    ids_core_profiles.profiles_1d{it}.ion{2}.time_measurement_slice_method.name = 'local';
+    ids_core_profiles.profiles_1d{it}.ion{2}.time_measurement_slice_method.index = 0;
+    ids_core_profiles.profiles_1d{it}.ion{2}.time_measurement_slice_method.description = 'Using cxrs at given time';
+    ids_core_profiles.profiles_1d{it}.ion{2}.time_measurement_width = widths(:,it_raw(it));
 
     ids_core_profiles.profiles_1d{it}.ion{1}.temperature_fit = ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit;
     ids_core_profiles.profiles_1d{it}.ion{1}.density_fit.source = {'Same as C temperature'};
 
     ids_core_profiles.profiles_1d{it}.t_i_average_fit.measured = ids_core_profiles.profiles_1d{it}.ion{2}.temperature_fit;
     ids_core_profiles.profiles_1d{it}.t_i_average_fit.source = {'Same as C temperature'};
+    ids_core_profiles.profiles_1d{it}.t_i_average_fit.rho_tor_norm = ids_core_profiles.profiles_1d{it}.ion{2}.rho_tor_norm;
+    ids_core_profiles.profiles_1d{it}.t_i_average_fit.time_measurement = ids_core_profiles.profiles_1d{it}.ion{2}.time_measurement;
+
   end
 end
 
-
-%time_measurement_slice_method
-%time_measurement_slice_method.name='exact' or 'local'
-%time_measurement_slice_method.index=0
-%time_measurement_slice_method.description='using Thomson scattering measurement at the given time'
-%time_measurement_width
-
-%time_measurement_slice_method
-%time_measurement_slice_method.name='exact' or 'local'
-%time_measurement_slice_method.index=0
-%time_measurement_slice_method.description='using Thomson scattering measurement at the given time'
-%local = 1
-%chi_squared = \tcv_shot::top.results.proffit.avg_time:teft_chi2
-
-%time_measurement_width(:) = gdat(84927,'\tcv_shot::top.results.proffit.avg_time:time_avg','doplot',1); % nargout = 1
-
-
-% I am guessing that in gdat params_eff.fit_type = 'avg' takes the data from the avg_time and not local_time proffit nodes?
-%name='exact' or 'local'
-%index=0
-%description='using Thomson scattering measurement at the given time'
-%(if only one TS laser time was used )
-%or may be:
-%name='avg' or 'average'
-%index=-1
-%description='average with TS at this time and other TS within +-delta_t' (delta_t is provided in the proffit:local tree), conf should know if nodes from local or avg
-
-
-if ~isempty(temp_1d.cxrs_rho.error_bar)
+if ~isempty(temp_1d.cxrs_rho.error_bar) && imas_major_version > 2
   switch error_bar
    case 'delta'
      for it=1:length(ids_core_profiles.time)
@@ -526,15 +598,6 @@ if ~isempty(temp_1d.cxrs_rho.error_bar)
 end
 
 
-%For the time integration of the Charge Exchange
-%timer_nodes = String2Struct(mdsdata('\ATLAS::CXRS_00X.ACQ:TIMING'));
-%mdsdata(timer_nodes.PeriodName)
-
-
-
-
-
-
 %% q profile and magnetic shear
 params_eff.data_request = 'q_rho';
 temp_1d.q = gdat(params_cores_profiles.shot,params_eff);
-- 
GitLab


From aaef687ec13915ceae05b1135916c0030735cb33 Mon Sep 17 00:00:00 2001
From: Michele Marin <michele.marin@epfl.ch>
Date: Fri, 23 May 2025 13:37:19 +0200
Subject: [PATCH 10/11] Do not check for disruption for planned shot

---
 matlab/TCV_IMAS/tcv2ids.m | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/matlab/TCV_IMAS/tcv2ids.m b/matlab/TCV_IMAS/tcv2ids.m
index b06f247a..0737d094 100644
--- a/matlab/TCV_IMAS/tcv2ids.m
+++ b/matlab/TCV_IMAS/tcv2ids.m
@@ -126,9 +126,11 @@ end
 gdat_params.data_request = 'ids';
 
 %Check that the shot did not disrupt very early.
-t_disrupted = gdat(shot,'time_disrupted()');
-if t_disrupted.data <= 0.04 | t_disrupted.data > 128
-  error('the shot disrupted')
+if shot != -1
+  t_disrupted = gdat(shot,'time_disrupted()');
+  if t_disrupted.data <= 0.04 | t_disrupted.data > 128
+    error('the shot disrupted')
+  end
 end
 
 for i=1:length(params_tcv2ids.ids_names)
-- 
GitLab


From 12b5147dfa1749a2de17165b31ae11ae78c100c4 Mon Sep 17 00:00:00 2001
From: Michele Marin <michele.marin@epfl.ch>
Date: Fri, 23 May 2025 14:06:29 +0200
Subject: [PATCH 11/11] minor bugfix on previous commit

---
 matlab/TCV_IMAS/tcv2ids.m | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/matlab/TCV_IMAS/tcv2ids.m b/matlab/TCV_IMAS/tcv2ids.m
index 0737d094..c94bea2b 100644
--- a/matlab/TCV_IMAS/tcv2ids.m
+++ b/matlab/TCV_IMAS/tcv2ids.m
@@ -126,9 +126,9 @@ end
 gdat_params.data_request = 'ids';
 
 %Check that the shot did not disrupt very early.
-if shot != -1
+if shot ~= -1
   t_disrupted = gdat(shot,'time_disrupted()');
-  if t_disrupted.data <= 0.04 | t_disrupted.data > 128
+  if t_disrupted.data <= 0.04 || t_disrupted.data > 128
     error('the shot disrupted')
   end
 end
-- 
GitLab