function [hdr] = read_fcdc_header(headerfile);

% READ_FCDC_HEADER is a wrapper around different EEG/MEG file importers
% directly supported formats are CTF, Neuromag, EEP, BrainVision and Neuroscan.
%
% If you have the BIOSIG toolbox installed also EDF, BKR, CNT, BDF, GDF and
% other dataformats supported by that toolbox are supported by this function.
% See http://biosig.sourceforge.net for details.
%
% Use as
%   hdr = read_fcdc_header(headerfile);
%
% This returns a header structure with the following elements
%   hdr.Fs           sampling frequency
%   hdr.nChans       number of channels
%   hdr.nSamples     number of samples per trial
%   hdr.nSamplesPre  number of pre-trigger samples in each trial
%   hdr.nTrials      number of trials
%   hdr.label        cell-array with labels of each channel
%
% For continuous data, nSamplesPre=0 and nTrials=1.
%
% Depending on the filetype it may return other header information as well,
% such as sensor positions.
%
% See also READ_FCDC_DATA

% Copyright (C) 2003, F.C. Donders Centre
%
% $Log: read_fcdc_header.m,v $
% Revision 1.14  2005/03/31 07:05:58  roboos
% implemented support for besa_avr using my own read_besa_avr
%
% Revision 1.13  2005/03/15 17:44:29  roboos
% Implemented the option of reading CTF res4/meg4 files using the importers
% from Darren Webers EEG toolbox (also used in EEGLAB): first try to read it
% using CTF/FCDC code, then try to read it with the other code. Gradiometer
% information for forward computations is not yet converted/returned.
%
% Revision 1.12  2005/02/16 07:48:28  roboos
% replaced nex specific code by a call to read_nex_header and read_nex_data subfunctions in file_io
%
% Revision 1.11  2005/02/11 07:39:22  roboos
% added support for Plexon *.nex files (only continuous data)
%
% Revision 1.10  2004/12/06 13:03:32  roboos
% added support for input string with ctf dataset instead of res4/meg4 file
%
% Revision 1.9  2004/10/01 10:26:24  roboos
% made detection of external toolboxes consistent with read_fcdc_mri, i.e. hasXXX at the beginning
%
% Revision 1.8  2004/09/20 13:53:04  roboos
% moved gradiometer definition for Neuromag fif files into separate function
%
% Revision 1.7  2004/06/25 15:08:08  roberto
% fixed bug in the labels of Neuromag gradiometer definition
%
% Revision 1.6  2004/06/24 15:52:35  roberto
% added gradiometer information from Neuromag fif file (122 channel system)
%
% Revision 1.5  2004/03/29 15:11:44  roberto
% added support for EEProbe *.avg, removed original header structure from output hdr for biosig
%
% Revision 1.4  2004/03/11 10:22:12  roberto
% some changes to organization of neuroscan cnt header: its original elements are now tucked away in a separate (orig) field
%
% Revision 1.3  2004/03/10 14:04:26  roberto
% added support for Neuromag *.fif format
% changed newline from dos to unix
%
% Revision 1.2  2004/03/10 11:58:13  roberto
% added support for BIOSIG importers as the last (fallback) attempt
%
% Revision 1.1  2004/01/16 08:08:30  roberto
% moved from file_io toolbox to framework
%
% Revision 1.5  2003/12/05 11:05:46  roberto
% improved help, changed tmp into hdr so that it always returns as much
% header information as possible
%
% Revision 1.4  2003/12/02 12:51:55  roberto
% separated neuroscan eeg and cnt formats, both use different routine
%
% Revision 1.3  2003/11/28 16:36:43  roberto
% added support for Eric Maris' continuous neuroscan *.cnt files
%
% Revision 1.2  2003/10/23 11:11:25  roberto
% converted ascii text from dos to unix
%
% Revision 1.1  2003/10/23 11:10:10  roberto
% *** empty log message ***
%

% detect the external toolboxes that optionally can be used
hasbiosig = (exist('sopen') & exist('sread'));                 % see http://biosig.sourceforge.net/
hasmegpd  = (exist('rawdata') & exist('channames'));           % see http://www.kolumbus.fi/kuutela/programs/meg-pd/
haseegsf  = (exist('ctf_read_meg4') & exist('ctf_read_res4')); % see http://eeg.sourceforge.net/

% translate the name of the dataset directory into the name of the header file
if filetype(headerfile, 'ctf_ds')
  [path, file, ext] = fileparts(headerfile);
  headerfile = fullfile(headerfile, [file '.res4']);
end

if filetype(headerfile, 'ctf_res4')
  try
    % try to read it using the default CTF importer that originates from CTF and the FCDC
    hdr = read_ctf_res4(headerfile);
    ctferror = 0;
  catch
    ctferror = 1;
  end
  if ctferror & haseegsf
    % try to read it using the CTF importer from the NIH and Daren Weber
    try
      tmp = ctf_read_res4(fileparts(headerfile), 0);
      ctferror = 0;
      % convert the header into a structure that FieldTrip understands
      hdr              = [];
      hdr.Fs           = tmp.setup.sample_rate;
      hdr.nChans       = length(tmp.sensor.info);
      hdr.nSamples     = tmp.setup.number_samples;
      hdr.nSamplesPre  = tmp.setup.pretrigger_samples;
      hdr.nTrials      = tmp.setup.number_trials;
      for i=1:length(tmp.sensor.info)
        hdr.label{i}   = tmp.sensor.info(i).label;
      end
      hdr.label        = hdr.label(:);
      % also store the original header, so that it can be reused by read_fcdc_data
      hdr.orig         = tmp;
    catch
      ctferror = 1;
    end
  end
  if ctferror
    error('could not read CTF res4 header file');
  end

elseif filetype(headerfile, 'brainvision_vhdr')
  hdr = read_brainvision_vhdr(headerfile);

elseif filetype(headerfile, 'plextor_nex')
  hdr = read_nex_header(headerfile);

elseif filetype(headerfile, 'eep_cnt')
  % read the first sample from the continous data, which will also return the header
  hdr = read_eep_cnt(headerfile, 1, 1);
  hdr.Fs          = hdr.rate;
  hdr.nSamples    = hdr.nsample;
  hdr.nSamplesPre = 0;
  hdr.nChans      = hdr.nchan;
  hdr.nTrials     = 1;		% it can always be interpreted as continuous data

elseif filetype(headerfile, 'eep_avr')
  % read the whole average and keep only header info (it is a bit silly, but the easiest to do here)
  hdr = read_eep_avr(headerfile);
  hdr.Fs          = hdr.rate;
  hdr.nChans      = size(hdr.data,1);;
  hdr.nSamples    = size(hdr.data,2);
  hdr.nSamplesPre = hdr.xmin*hdr.rate/1000;
  hdr.nTrials     = 1;		% it can always be interpreted as continuous data
  % remove the data and variance if present
  hdr = rmfield(hdr, 'data');
  try, hdr = rmfield(hdr, 'variance'); end

elseif filetype(headerfile, 'ns_eeg')
  hdr = read_ns_hdr(headerfile);
  % do some reformatting/renaming of the header items
  hdr.Fs          = hdr.rate;
  hdr.nSamples    = hdr.npnt;
  hdr.nSamplesPre = hdr.rate*hdr.xmin/1000;
  hdr.nChans      = hdr.nchan;
  hdr.nTrials     = hdr.nsweeps;

elseif filetype(headerfile, 'ns_cnt')
  % read_ns_cnt originates from the EEGLAB package (loadcnt.m) but is
  % an old version since the new version is not compatible any more
  orig = read_ns_cnt(headerfile, 'ldheaderonly', 1);
  % do some reformatting/renaming of the header items
  hdr.Fs          = orig.rate;
  hdr.nChans      = orig.nchannels;
  hdr.nSamples    = orig.nsamples;
  hdr.nSamplesPre = 0;
  hdr.nTrials     = 1;
  for i=1:hdr.nChans
    hdr.label{i} = deblank(orig.chan.names(i,:));
  end

elseif filetype(headerfile, 'besa_avr')
  orig = read_besa_avr(headerfile);
  hdr.Fs          = 1000/orig.di;
  hdr.nChans      = size(orig.data,1);
  hdr.nSamples    = size(orig.data,2);
  hdr.nSamplesPre = -(hdr.Fs * orig.tsb/1000);   % convert from ms to samples
  hdr.nTrials     = 1;
  if isfield(orig, 'label') & iscell(orig.label)
    hdr.label = orig.label;
  elseif isfield(orig, 'label') & ischar(orig.label)
    hdr.label = tokenize(orig.label, ' ');
  else
    for i=1:hdr.nChans
      warning('creating fake channel names for besa_avr');
      hdr.label{i} = sprintf('%03d', i);
    end
  end

elseif filetype(headerfile, 'neuromag_fif')
  % Neuromag MEG data
  if ~hasmegpd
    error('cannot find Neuromag import routines, see http://boojum.hut.fi/~kuutela/meg-pd/');
  end

  % add the gradiometer definition to the output header
  hdr.grad = fif2grad(headerfile);

  [hdr.label, type, number] = channames(headerfile);
  rawdata('any',headerfile);
  hdr.Fs = rawdata('sf');
  hdr.nTrials = 0;
  rawdata('goto', 0);
  [buf, status] = rawdata('next');
  hdr.nChans   = size(buf,1);
  hdr.nSamples = size(buf,2);
  while strcmp(status, 'ok')
    hdr.nTrials = hdr.nTrials + 1;
    [buf, status] = rawdata('next');
  end
  % I don't know how to get this out of the file
  hdr.nSamplesPre  = 0;
  % this would give some information that I don't know how to use
  % [range, cal] = rawdata('range');
  % this would give the current latency
  % rawdata('t');
  rawdata('close');

elseif hasbiosig
  % as a final resort try reading the header with the BIOSIG import
  % filters if they are available
  try
    hdr = read_biosig_header(headerfile);
    if isfield(hdr, 'orig')
      % remove the original header information, since fieldtrip is not interested in it
      hdr = rmfield(hdr, 'orig');
    end
  catch
    error('error reading data using BIOSIG toolbox, see http://biosig.sourceforge.net/');
  end
end

if ~exist('hdr', 'var')
  % none of the importers above has been able to read the header
  error('unsupported fileformat for EEG/MEG data file');
end
