function [dat] = read_fcdc_data(datafile, hdr, begsample, endsample, chanindx, continuous);

% READ_FCDC_DATA 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.
% See http://biosig.sourceforge.net for details.
%
% Use as
%   dat = read_fcdc_data(datfile, hdr, begsample, endsample, chanindx, continuous)
%
% where the header is obtained from READ_FCDC_)HEADER.
%
% The beginsample and endsample are counted from the beginning of the raw
% data, starting at 1.
%
% The argument "chanindx" is optional, the default is to read all channels.
%
% The argument "continuous" is optional, the default is check to whether
% the data is continuous and, if not, check whether the requested datasegment
% does not extend over a trial boundary. If continuous=1, this check
% is not performed (usefull for pseudo-continuous data).
%
% See also READ_FCDC_HEADER

% Copyright (C) 2003-2005, Robert Oostenveld, F.C. Donders Centre
%
% $Log: read_fcdc_data.m,v $
% Revision 1.15  2005/03/31 07:05:58  roboos
% implemented support for besa_avr using my own read_besa_avr
%
% Revision 1.14  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.13  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.12  2005/02/11 07:39:22  roboos
% added support for Plexon *.nex files (only continuous data)
%
% Revision 1.11  2005/02/07 12:46:31  jansch
% small modification for the handling of continuous neuroscan-data, so that
% a subset of channels can be specified in the configuration.
%
% Revision 1.10  2005/02/03 17:14:13  roboos
% fixed bug for neuromag data (beginepoch not defined)
%
% Revision 1.9  2005/01/25 14:03:58  roboos
% implemented check for datasegment extending beyound trial boundaries
% default is to determine continuous/epoched datatype by looking at the header
% added extra boolean argument for (pseudo)continuous data in which case boundary check is skipped
%
% Revision 1.8  2004/12/06 13:03:32  roboos
% added support for input string with ctf dataset instead of res4/meg4 file
%
% Revision 1.7  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.6  2004/03/30 07:17:57  roberto
% fixed bug in chanindx due to incorrect number of input arguments
%
% Revision 1.5  2004/03/29 15:07:25  roberto
% added support for EEProbe *.avg and Brainvision *.dat (exported from BVA)
%
% Revision 1.4  2004/03/11 10:20:45  roberto
% implemeted default chanindx argument for all channels + some code changes to reflect that
% added extra comment on loadcnt importer originating from EEGLAB
%
% Revision 1.3  2004/03/10 14:05:27  roberto
% fixed a potential bug in reading multiple epochs of a Neuroscan *.eeg file
% added support for Neuromag *.fif files
%
% 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.4  2003/12/04 09:01:00  roberto
% made ns_eeg consistent with other formats by changing hdr.nSample into samples per trial
%
% 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 data file
if filetype(datafile, 'ctf_ds')
  [path, file, ext] = fileparts(datafile);
  datafile = fullfile(datafile, [file '.meg4']);
end

if nargin<5 | isempty(chanindx)
  chanindx = 1:hdr.nChans;
end

if nargin<6 | isempty(continuous)
  % default is to assume that the data is NOT continuous, and hence that it
  % should be checked whether the requested segment extends over a trial boundary
  continuous = 0;
end

if ~continuous & hdr.nTrials>1
  % test whether the requested data segment does not extend over a discontinuous trial boundary
  begtrl = floor((begsample-1)/hdr.nSamples) + 1;
  endtrl = floor((endsample-1)/hdr.nSamples) + 1;
  if begtrl~=endtrl
    error('requested data segment extends over a discontinuous trial boundary');
  end
end

if filetype(datafile, 'ctf_meg4')
  try
    % try to read it using the default CTF importer that originates from CTF and the FCDC
    dat = read_ctf_meg4(datafile, hdr, begsample, endsample, chanindx);
    ctferror = 0;
  catch
    ctferror = 1;
  end
  if ctferror & haseegsf
    % try to read it using the CTF importer from the NIH and Daren Weber
    try
      % determine the trial containing the begin and end sample
      begtrial = floor((begsample-1)/hdr.nSamples)+1;
      endtrial = floor((endsample-1)/hdr.nSamples)+1;
      tmp = ctf_read_meg4(fileparts(datafile), hdr.orig, chanindx, 'all', begtrial:endtrial);
      % convert the data into the format that FieldTrip expects, i.e. continuous Nchans X Nsamples
      dat = permute(tmp.data, [2 1 3]);
      dat = reshape(dat, length(chanindx), length(begtrial:endtrial)*hdr.nSamples);
      begsample = begsample - (begtrial-1)*hdr.nSamples;
      endsample = endsample - (begtrial-1)*hdr.nSamples;
      dat = dat(:, begsample:endsample);
      ctferror = 0;
    catch
      ctferror = 1;
    end
  end
  if ctferror
    error('could not read CTF meg4 data file');
  end

elseif filetype(datafile, 'plextor_nex')
   dat = read_nex_data(datafile, hdr, begsample, endsample, chanindx);

elseif filetype(datafile, 'brainvision_eeg')
  dat = read_brainvision_eeg(datafile, hdr, begsample, endsample);
  dat = dat(chanindx,:);	% select the desired channels

elseif filetype(datafile, 'brainvision_dat')
  dat = read_brainvision_eeg(datafile, hdr, begsample, endsample);
  dat = dat(chanindx,:);	% select the desired channels

elseif filetype(datafile, 'brainvision_seg')
  dat = read_brainvision_seg(datafile, hdr, begsample, endsample);
  dat = dat(chanindx,:);	% select the desired channels

elseif filetype(datafile, 'eep_cnt')
  dat = read_eep_cnt(datafile, begsample, endsample);
  dat = dat.data(chanindx,:);	% select the desired channels

elseif filetype(datafile, 'eep_avr')
  dat = read_eep_avr(datafile);
  dat = dat.data(chanindx,begsample:endsample);	% select the desired channels and samples

elseif filetype(datafile, 'ns_eeg')
  % Neuroscan epoched file
  begepoch  = floor((begsample-1)/hdr.npnt) + 1;  % determine epoch with the requested samples
  tmp       = read_ns_eeg(datafile, begepoch);
  begsample = begsample - (begepoch-1)*hdr.npnt;  % correct for the number of bytes that were skipped
  endsample = endsample - (begepoch-1)*hdr.npnt;  % correct for the number of bytes that were skipped
  dat = tmp.data(chanindx, begsample:endsample);

elseif filetype(datafile, 'ns_cnt')
  % Neuroscan continuous data
  sample1    = begsample-1;
  ldnsamples = endsample-begsample+1; % number of samples to read
  ldchan     = 1:hdr.nChans;          % must be row vector
  chanoi     = chanindx(:)';          % channels of interest
  if sample1<0
    error('begin sample cannot be for the beginning of the file');
  end
  % read_ns_cnt originates from the EEGLAB package (loadcnt.m) but is
  % an old version since the new version is not compatible any more
  % all data is read, and only the relevant data is kept.
  tmp = read_ns_cnt(datafile, 'sample1', sample1, 'ldnsamples', ldnsamples, 'ldchan', ldchan);
  dat = tmp.dat(chanoi,:);

elseif filetype(datafile, 'besa_avr')
  % BESA average data
  orig = read_besa_avr(datafile);
  dat  = orig.data(chanindx, begsample:endsample);

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

  begtime = (begsample-1)/hdr.Fs;
  begepoch = floor((begsample-1)/hdr.nSamples) + 1;
  endepoch = floor((endsample-1)/hdr.nSamples) + 1;
  rawdata('any',datafile);
  rawdata('goto', begtime);
  dat = [];
  for i=begepoch:endepoch
    [buf, status] = rawdata('next');
    if ~strcmp(status, 'ok')
      error('error reading selected data from fif-file');
    end
    dat = [dat buf(chanindx,:)];
  end
  rawdata('close');
  begsample = begsample - (begepoch-1)*hdr.nSamples;  % correct for the number of bytes that were skipped
  endsample = endsample - (begepoch-1)*hdr.nSamples;  % correct for the number of bytes that were skipped
  dat = dat(:, begsample:endsample);

elseif hasbiosig & ~isempty(hdr)
  % Try reading the data with the BIOSIG import filters if they are available.
  % This only needs to be attempted if the READ_FCDC_HEADER file was able to
  % extract header information out of the file, otherwise the file cannot
  % be recognized anyway.
  try
    % use the wrapper that I made around the biosig functions
    dat = read_biosig_data(datafile, hdr, begsample, endsample, chanindx);
  catch
    error('error reading data using BIOSIG toolbox, see http://biosig.sourceforge.net/');
  end
end

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