Can I create an artificial CTF dataset using MATLAB?

Q: Is there a way to create an artificial CTF dataset using Matlab or one of the CTF utilities or alternatively take a real dataset and replace just the channel data with my simulated data?

A: Yes, there is, see below.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% function ft_write_data(filename, dat, varargin)

% FT_WRITE_DATA exports electrophysiological data to a file
%
% Use as ft_write_data(filename, dat, ...)
%
% The specified filename can already contain the filename extention,
% but that is not required since it will be added automatically.
%
% Additional options should be specified in key-value pairs and can be
%   'header'         header structure, see READ_FCDC_HEADER
%   'dataformat'     string, see below
%   'chanindx'       1xN array

% ...

% get the options
dataformat    = keyval('dataformat',    varargin); if isempty(dataformat), dataformat = ft_filetype(filename); end
chanindx      = keyval('chanindx',      varargin);
hdr           = keyval('header',        varargin);

% determine the data size (input is dataformat as it is returned by preprocessing, should be in ntrials x nchannels x nsamples)
[nchans, nsamples] = size(dat.trial{1});

switch dataformat
  case 'ctf_ds'
      id = find(filename == '.');
      filename = [filename '/' filename(1:id) 'meg4'];
      dataformat = ft_filetype(filename);
        
  case 'ctf_meg4'  

      % reshaping the data size
      if isfield(dat, 'trial'), 
         for i = 1:size(dat.trial,2)
            data(i,:,:) = dat.trial{i};
         end
      end

      ntrldat   = size(data,1);
      nsmpdat   = size(data,3);
      nchandat  = size(data,2);
      ntrlorig  = hdr.nTrials;
      nchanorig = hdr.nChans;
      nsmporig = hdr.nSamples;
    
      % In case more trials/channels/samples are present in data compared to
      % header, error message. No fix.
      if ntrldat>ntrlorig
          error('More trials in dataset than header indicates');
      elseif nchandat>nchanorig
          error('More channels in dataset than header indicates');
      elseif nsmpdat>nsmporig
          error('More samples in dataset than header indicates');
      end
    
      % compare label to orig.label
      [count, index] = vec_match(dat.label,hdr.label);
      if find(index == 0)
         error('Channelnames do not match');    
      end
    
      % If the dat.label contains the same channels (no more), or a
      % subset of existing channels of orig.label, the order of the channels
      % should be checked, and if the nr of channels in the new dataset is
      % smaller than in the header, the rest will be zeropadded.
    
      NZ_index = nonzeros(index);
      AV = check_asc(NZ_index);
      if length(NZ_index) == length(hdr.label) && AZ == 1
          return
      else
          NewLabel = cell(length(hdr.label),1);
          NewDat = zeros(ntrlorig, nchanorig, nsmpdat); 
          for i = 1:length(NZ_index)
             NewLabel(NZ_index(i),:) = dat.label(i);
             NewDat(1:ntrldat,NZ_index(i),:) = data(:,i,:);
          end
          if count < length(hdr.label)
              fprintf('Less channels in dataset than header indicates, data padded with zeros');
          end
      end
    
      dat.label = NewLabel;
      data = NewDat;
    
      % Since the size of dat may have changed, new values for trl,smp and
      % chan should be defined
      ntrldat   = size(data,1);
      nsmpdat   = size(data,3);
      nchandat  = size(data,2);
    
      % Opening the filename and writing the header
      fid = fopen(filename, 'wb', 'ieee-be');
      buf = [77 69 71 52 49 67 80 0]; % 'MEG41CP', null-terminated
      fwrite(fid, buf, 'char');

      if isempty(chanindx) && length(hdr.label)==nchandat
         chanindx = 1:nchandat;
      end

      % Check number of bytes needed to write the data
      nr_bytes = 8 + (ntrldat*nsmpdat*nchandat*4);
      if nr_bytes > 1e9
         error ('this code is not capable of writing datasets larger than 1Gb')
      end

      for i=1:ntrldat
         datorig = zeros(nchanorig,nsmporig); % size 'original' = header data
         if i<=ntrldat
           datorig(chanindx,1:nsmpdat) = data(i,:,:); % Padding with zeros in case nsmpdat<nsmporig
           datorig = transpose(sparse(diag(1./hdr.orig.gainV)) * datorig);
           if any(datorig(:)>intmax('int32')) || any(datorig(:)<intmin('int32'))
              warning('Data reaches limits int32, border values are clipped');
              datorig(datorig>intmax('int32')) = intmax('int32');
              datorig(datorig<intmin('int32')) = intmin('int32');
           end
           datorig = int32(datorig);
         else
            datorig = int32(transpose(datorig));
         end
         fwrite(fid, datorig, 'int32');
      end

      fclose(fid);
      
  end % switch dataformat

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                           Function vec_match
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [count, index] = vec_match(vec1, vec2)

count = 0;
for i = 1:size(vec1,1)
    id = strmatch(vec1(i,:), vec2);
    if size(id,1) == 0
        continue
    else 
        count = count + 1;
        index(i) = id;
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                           Function check_asc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function AZ = check_asc(index)

max = 0;
for i = 1:length(index)
    if max < index(i)
        max = index(i);
        AZ = 1;
    else 
        AZ = 0;
        break;
    end
end