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};

      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');
      % compare label to orig.label
      [count, index] = vec_match(dat.label,hdr.label);
      if find(index == 0)
         error('Channelnames do not match');    
      % 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
          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,:);
          if count < length(hdr.label)
              fprintf('Less channels in dataset than header indicates, data padded with zeros');
      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;

      % 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')

      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');
           datorig = int32(datorig);
            datorig = int32(transpose(datorig));
         fwrite(fid, datorig, 'int32');

  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
        count = count + 1;
        index(i) = id;

%                           Function check_asc

function AZ = check_asc(index)

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