diff --git a/matlab/TCV_IMAS/tcv2ids.m b/matlab/TCV_IMAS/tcv2ids.m
index 920948939d219aef3ffa9835a4a9e63e4ac3eb1b..d6e2ecc92e2228686768659bcac239296e5ebafe 100644
--- a/matlab/TCV_IMAS/tcv2ids.m
+++ b/matlab/TCV_IMAS/tcv2ids.m
@@ -32,8 +32,9 @@ function [ids_from_tcv,varargout] = tcv2ids(shot,varargin);
 p = inputParser;
 % no required inputs here so one can call with empty args and get defaults parameters
 % effectively required inputs should have defaults as empty
+ids_names = {'equilibrium', 'magnetics', 'pf_active','wall', 'tf','core_profiles','ec_launchers','nbi', 'thomson_scattering'};
 p.addOptional('shot', [], @(x) (isnumeric(x) && isscalar(x) && (x == round(x)))); % integer
-p.addOptional('ids_names', {'equilibrium', 'magnetics', 'pf_active','wall', 'tf','core_profiles','ec_launchers','nbi'}, @(x) isempty(x) || iscell(x) ); % char or cell array
+p.addOptional('ids_names', ids_names, @(x) isempty(x) || iscell(x) ); % char or cell array
 p.addOptional('error_bar', 'delta', @(x) isempty(x) || ischar(x) ); % char or cell array
 p.addOptional('cocos_out', 11, @(x) isempty(x) || isnumeric(x) ); % char
 p.addOptional('ipsign_out', 0, @(x) isempty(x) || (x==0 | x==-1 | x==+1) ); % char
diff --git a/matlab/TCV_IMAS/tcv_get_ids_thomson_scattering.m b/matlab/TCV_IMAS/tcv_get_ids_thomson_scattering.m
new file mode 100644
index 0000000000000000000000000000000000000000..e0fdcdbc7d55390cf928b92eb9ea9799ff0e303f
--- /dev/null
+++ b/matlab/TCV_IMAS/tcv_get_ids_thomson_scattering.m
@@ -0,0 +1,118 @@
+function [ids_thomson_scattering,ids_thomson_scattering_description] =  tcv_get_ids_thomson_scattering(shot, ids_thomson_scattering_empty, gdat_params,varargin)
+%
+% [ids_thomson_scattering] =  tcv_get_ids_thomson_scattering(shot, ids_thomson_scattering_empty,varargin);
+%
+% Get the thomson scattering diagnostics data
+%
+% ids_thomson_scattering_empty should at least be the empty thomson_scattering ids structure in input
+%
+% gdat_params: gdat_data.gdat_params to get all params passed from original call, in particular error_bar options
+%
+
+error_bar = 'delta';
+if exist('gdat_params','var') && isfield(gdat_params,'error_bar') && ~isempty(gdat_params.error_bar)
+  error_bar = gdat_params.error_bar;
+end
+
+if exist('gdat_params','var')
+  [ids_thomson_scattering, ~] = tcv_ids_headpart(shot, ids_thomson_scattering_empty,'thomson_scattering','homogeneous_time',0,'gdat_params',gdat_params,varargin{:});
+  % Main system
+  params_eff = gdat_params;
+  params_eff.edge         = 0;
+  params_eff.data_request = 'ne';
+  ne0 = gdat_tcv(shot,params_eff);
+  params_eff.data_request = 'te';
+  te0 = gdat_tcv(shot,params_eff);
+  % Edge system
+  params_eff = gdat_params;
+  params_eff.edge         = 1;
+  params_eff.data_request = 'ne';
+  ne1 = gdat_tcv(shot,params_eff);
+  params_eff.data_request = 'te';
+  te1 = gdat_tcv(shot,params_eff);
+else
+  [ids_thomson_scattering, ~] = tcv_ids_headpart(shot, ids_thomson_scattering_empty,'thomson_scattering','homogeneous_time',0,varargin{:});
+  % Main system
+  ne0 = gdat_tcv(shot, 'ne', 'edge',0);
+  te0 = gdat_tcv(shot, 'te', 'edge',0);
+  % Edge system
+  ne1 = gdat_tcv(shot, 'ne', 'edge',1);
+  te1 = gdat_tcv(shot, 'te', 'edge',1);
+end
+ids_thomson_scattering_description = struct();
+
+status = ~ischar(ne0.data) & ~ischar(te0.data) & ~ischar(ne1.data) & ~ischar(te1.data);
+
+if status
+  nchannel0 = size(ne0.data_raw,1);
+  nchannel1 = size(ne1.data_raw,1);
+  nchannel = nchannel0 + nchannel1;
+  ids_thomson_scattering.channel(1:nchannel) = ids_thomson_scattering.channel(1);
+  for system = {'main','edge'}
+    switch system{1}
+      case 'main', nchannel = nchannel0; offset = 0;         ne = ne0; te = te0; edge_str = ')';
+      case 'edge', nchannel = nchannel1; offset = nchannel0; ne = ne1; te = te1; edge_str = ',''edge'',1';
+    end
+    for ii = 1:nchannel
+      jj = ii+offset;
+      ids_thomson_scattering.channel{jj}.name = sprintf('%s %03d',system{1},ii);
+      ids_thomson_scattering_description.channel{jj}.name = sprintf('TS system %s, index from order in \results::thomson tree',system{1});
+      ids_thomson_scattering.channel{jj}.identifier = sprintf('Z=%+5.3gm',ne.x(ii));
+      ids_thomson_scattering_description.channel{jj}.identifier = 'Identifier from Vertical position';
+      ids_thomson_scattering.channel{jj}.position.r = 0.9;
+      ids_thomson_scattering_description.channel{jj}.position.r = 'Fixed R=0.9m';
+      ids_thomson_scattering.channel{jj}.position.z = ne.x(ii);
+      ids_thomson_scattering_description.channel{jj}.position.z = ['Vertical position ne.x from gdat_tcv(shot,''ne'',',edge_str,')'];
+      ids_thomson_scattering.channel{jj}.t_e.data = reshape(te.data(ii,:),[],1);
+      ids_thomson_scattering_description.channel{jj}.t_e.data = ['te.data from gdat_tcv(shot,''te'',',edge_str,')'];
+      if (ids_thomson_scattering.ids_properties.homogeneous_time == 0)
+        ids_thomson_scattering.channel{jj}.t_e.time = reshape(te.t,[],1);
+        ids_thomson_scattering_description.channel{jj}.t_e.time = ['te.t from gdat_tcv(shot,''te'',',edge_str,')'];
+      end
+      ids_thomson_scattering.channel{jj}.n_e.data = reshape(ne.data_raw(ii,:),[],1);
+      ids_thomson_scattering_description.channel{jj}.n_e.data = ['ne.data_raw from gdat_tcv(shot,''ne'',',edge_str,')'];
+      if (ids_thomson_scattering.ids_properties.homogeneous_time == 0)
+        ids_thomson_scattering.channel{jj}.n_e.time = reshape(ne.t,[],1);
+        ids_thomson_scattering_description.channel{jj}.n_e.time = ['ne.t from gdat_tcv(shot,''ne'',',edge_str,')'];
+      end
+      switch error_bar
+        case 'delta'
+          ids_thomson_scattering.channel{jj}.t_e.data_error_upper = reshape(abs(te.error_bar(ii,:)),[],1);
+          ids_thomson_scattering_description.channel{jj}.t_e.data_error_upper = ['abs(te.error_bar) from gdat_tcv(shot,''te'',',edge_str,') for case ',error_bar];
+          ids_thomson_scattering.channel{jj}.n_e.data_error_upper = reshape(abs(ne.error_bar(ii,:)),[],1);
+          ids_thomson_scattering_description.channel{jj}.n_e.data_error_upper = ['abs(ne.error_bar) from gdat_tcv(shot,''ne'',',edge_str,') for case ',error_bar];
+        case 'delta_with_lower'
+          ids_thomson_scattering.channel{jj}.t_e.data_error_upper = reshape(abs(te.error_bar(ii,:)),[],1);
+          ids_thomson_scattering_description.channel{jj}.t_e.data_error_upper = ['abs(te.error_bar) from gdat_tcv(shot,''te'',',edge_str,') for case ',error_bar];
+          ids_thomson_scattering.channel{jj}.t_e.data_error_lower = reshape(abs(te.error_bar(ii,:)),[],1);
+          ids_thomson_scattering_description.channel{jj}.t_e.data_error_lower = ['abs(te.error_bar) from gdat_tcv(shot,''te'',',edge_str,') for case ',error_bar];
+          ids_thomson_scattering.channel{jj}.n_e.data_error_upper = reshape(abs(ne.error_bar(ii,:)),[],1);
+          ids_thomson_scattering_description.channel{jj}.n_e.data_error_upper = ['abs(ne.error_bar) from gdat_tcv(shot,''ne'',',edge_str,') for case ',error_bar];
+          ids_thomson_scattering.channel{jj}.n_e.data_error_lower = reshape(abs(ne.error_bar(ii,:)),[],1);
+          ids_thomson_scattering_description.channel{jj}.n_e.data_error_lower = ['abs(ne.error_bar) from gdat_tcv(shot,''ne'',',edge_str,') for case ',error_bar];
+        case 'added'
+          ids_thomson_scattering.channel{jj}.t_e.data_error_upper = reshape(te.data(ii,:)+abs(te.error_bar(ii,:)),[],1);
+          ids_thomson_scattering_description.channel{jj}.t_e.data_error_upper = ['te.data+abs(te.error_bar) from gdat_tcv(shot,''te'',',edge_str,') for case ',error_bar];
+          ids_thomson_scattering.channel{jj}.t_e.data_error_lower = reshape(te.data(ii,:)-abs(te.error_bar(ii,:)),[],1);
+          ids_thomson_scattering_description.channel{jj}.t_e.data_error_lower = ['te.data-abs(te.error_bar) from gdat_tcv(shot,''te'',',edge_str,') for case ',error_bar];
+          ids_thomson_scattering.channel{jj}.n_e.data_error_upper = reshape(ne.data(ii,:)+abs(ne.error_bar(ii,:)),[],1);
+          ids_thomson_scattering_description.channel{jj}.n_e.data_error_upper = ['ne.data+abs(ne.error_bar) from gdat_tcv(shot,''ne'',',edge_str,') for case ',error_bar];
+          ids_thomson_scattering.channel{jj}.n_e.data_error_lower = reshape(ne.data(ii,:)-abs(ne.error_bar(ii,:)),[],1);
+          ids_thomson_scattering_description.channel{jj}.n_e.data_error_lower = ['ne.data-abs(ne.error_bar) from gdat_tcv(shot,''ne'',',edge_str,') for case ',error_bar];
+      end
+    end
+  end
+  if (ids_thomson_scattering.ids_properties.homogeneous_time == 1)
+    ids_thomson_scattering.time = ne0.time(:);
+    ids_thomson_scattering_description.time = 'ne.t from gdat_tcv(shot,''ne'')';
+  end
+end
+
+% make arrays not filled in empty
+
+% cocos automatic transform
+if false && exist('ids_generic_cocos_nodes_transformation_symbolic','file') % Disabled until added to COCOStransform
+  [ids_thomson_scattering,~]=ids_generic_cocos_nodes_transformation_symbolic(ids_thomson_scattering,'thomson_scattering',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