function ExtractVideoCNNFeature_ucf(layer,scale,gpu_id, tag, ind)
addpath /home/lmwang/code/caffe_data_parallel/caffe/matlab
sizes =[480,640; 340,454; 240,320; 170,227; 120,160];
path_org = '/nfs/lmwang/lmwang/Data/UCF101/ucf101_org/';
folderlist = dir(path_org);
foldername = {folderlist(:).name};
foldername = setdiff(foldername,{'.','..'});

% FLOW
if  strcmp(tag,'flow')
    path2 = ['/media/RAID0/lmwang/data/UCF/ucf101_tvl1_flow_conv5_scale_',num2str(scale),'/'];
    path3 = ['/media/RAID0/lmwang/data/UCF/ucf101_tvl1_flow_conv4_scale_',num2str(scale),'/'];
    path4 = ['/media/RAID0/lmwang/data/UCF/ucf101_tvl1_flow_conv3_scale_',num2str(scale),'/'];
    path5 = ['/media/RAID0/lmwang/data/UCF/ucf101_tvl1_flow_pool2_scale_',num2str(scale),'/'];
    path_flow =  '/media/RAID0/lmwang/data/UCF/ucf101_flow_img_tvl1_gpu/';

    model_def_file = [ 'models/flow_',layer,'_scale_',num2str(scale),'_new.prototxt'];
    model_file = '10_flow_iter_90000_new.caffemodel';
    caffe.reset_all();
    caffe.set_mode_gpu();
    caffe.set_device(gpu_id);
    net = caffe.Net(model_def_file, model_file, 'test');

    for i = ind
        if ~exist([path2,foldername{i}],'dir')
            mkdir([path2,foldername{i}]);
        end
        if ~exist([path3,foldername{i}],'dir')
            mkdir([path3,foldername{i}]);
        end
        if ~exist([path4,foldername{i}],'dir')
            mkdir([path4,foldername{i}]);
        end
        if ~exist([path5,foldername{i}],'dir')
            mkdir([path5,foldername{i}]);
        end
        filelist = dir([path_org,foldername{i},'/*.avi']);
        for j = 1:length(filelist)
            filename = [path_flow,foldername{i},'/',filelist(j).name(1:end-4),'/'];
            if  ~exist([path5,foldername{i},'/',filelist(j).name(1:end-4),'.mat'],'file')
                tic;
                [feature_c5, feature_c4, feature_c3, feature_p2] = TemporalCNNFeature(filename, net, sizes(scale,1), sizes(scale,2));
                toc;
                tic;
                feature = feature_c5;
                save([path2,foldername{i},'/',filelist(j).name(1:end-4),'.mat'],'feature','-v7.3');
                feature = feature_c4;
                save([path3,foldername{i},'/',filelist(j).name(1:end-4),'.mat'],'feature','-v7.3');
                feature = feature_c3;
                save([path4,foldername{i},'/',filelist(j).name(1:end-4),'.mat'],'feature','-v7.3');
                feature = feature_p2;
                save([path5,foldername{i},'/',filelist(j).name(1:end-4),'.mat'],'feature','-v7.3');
                toc;
            end
        end
        i
    end
    caffe.reset_all();
end


imOut = '/biac3/wandell4/data/reading_longitude/betCheck';
baseDir = {'/biac3/wandell4/data/reading_longitude/dti_y1',...
		   '/biac3/wandell4/data/reading_longitude/dti_y2',...
		   '/biac3/wandell4/data/reading_longitude/dti_y3',...
		   '/biac3/wandell4/data/reading_longitude/dti_y4'};
bet = 'bet2';
% fractional intensity threshold (0->1); default=0.5;
% smaller values give larger brain outline estimates
betF = {'0.35','0.40','0.45','0.55','0.60','0.65'};

for(jj=1:length(baseDir))
  d = dir(fullfile(baseDir{jj},'*0*'));
  for(ii=1:length(d))
    subCodes{ii} = d(ii).name;
    files{ii} = fullfile(baseDir{jj},d(ii).name,'t1','t1');
  end

  if(~exist(imOut,'dir')), mkdir(imOut); end
  N = length(files);
  doThese = [1:N];
  for(ii=doThese)
	if(~exist([files{ii} '.nii.gz'],'file'))
	  disp(['Skipping ' subCodes{ii} '...']);
	else
	  fprintf('Processing %s (%d of %d)...\n', files{ii}, ii, length(doThese));
	  t1 = niftiRead([files{ii} '.nii.gz']);
	  slices = [1:3:t1.dim(3)-6];
	  im = double(makeMontage(t1.data, slices));
	  clear t1;
	  im = mrAnatHistogramClip(im, 0.4, 0.99);
	  im = uint8(im./max(im(:)).*255+0.5);
	  for(jj=1:length(betF))
		outName = [files{ii} '_' betF{jj}];
		betCmd = [bet ' ' files{ii} ' ' outName ' -mnf ' betF{jj}];
		disp(['   running BET: ' betCmd '...']);
		unix(['export FSLOUTPUTTYPE=NIFTI_GZ ; ' betCmd]);
		mask = niftiRead([outName '_mask.nii.gz']);
		mask = logical(makeMontage(mask.data, slices));
		skull = im; skull(mask) = 0;
		brain = im; brain(~mask) = 0;
		rgb(:,:,1) = brain;
		rgb(:,:,2) = skull+brain;
		rgb(:,:,3) = brain;
		imwrite(rgb, fullfile(imOut, [subCodes{ii} '_betF' betF{jj}(end-2:end) '.png']));
	  end
	end
  end
end


function spm_run_bms_vis(varargin)
% Show results for Bayesian Model Selection Maps
% SPM job execution function
% takes a harvested job data structure (or no input) and calls SPM
% functions to show results from Bayesian Model Selection of
% Log. Evidence Maps
%
% Input:
% Varargin - can be harvested job data structure (see matlabbatch help).
% Output:
% No output.
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Maria Joao Rosa
% $Id: spm_run_bms_vis.m 7577 2019-04-24 08:59:56Z guillaume $

% Input
% -------------------------------------------------------------------------
if isempty(varargin)
   job.file{1}=''; job.img{1}=''; job.thres = []; job.scale = []; job.k=[];
else
   job = varargin{1};
end
file_str = length(job.file{1});
image    = length(job.img{1});
thres_b  = length(job.thres);
odds_b   = length(job.scale);
ext_thre = length(job.k);

% Initialise SPM Interactive window
% -------------------------------------------------------------------------
[Finter,F,CmdLine] = spm('FnUIsetup','SPM BMC Toolbox: Visualise options',0);
F = spm_figure('FindWin','Graphics');
spm('Clear',Finter);
WS = spm('WinScale');
FS = spm('FontSizes');

% Select results image from BMS Maps
% -------------------------------------------------------------------------
if file_str
   file_fname = job.file{1};
else
   file_fname = spm_select(1,'mat','Load BMS file (.mat)');
end

% Load BMS
load(file_fname);
wd = fileparts(file_fname);

% Select results image from BMS Maps
% -------------------------------------------------------------------------
if image
   post = job.img{1};
else
   post = spm_select(1,'image','Select BMS Maps results (ex: ppm, alpha or epm image)',[],wd);
end

% Select threshold to apply to image
% -------------------------------------------------------------------------
if thres_b
   threshold = job.thres;
else
   threshold = spm_input('Probability Threshold:', '+1', 'r', '0.5', [1, inf]);
end

% Extent threshold
% -------------------------------------------------------------------------
if ext_thre
   k = job.k;
else
   k = spm_input('& extent threshold {voxels}','+1','r',0,1,[0,Inf]);
end

% Select scale
% -------------------------------------------------------------------------
if odds_b
   odds = job.scale;
else
   odds = spm_input('Change scale to Log-Odds?', '+1', 'y/n', [1,0], 2);
end

% Image dimensions
% -------------------------------------------------------------------------
V             = spm_vol(post);
M             = V.mat;
iM            = inv(M);
vox           = sqrt(sum(M(1:3,1:3).^2));
DIM           = V.dim(1:3)';
xdim          = DIM(1); ydim  = DIM(2); zdim  = DIM(3);
[xords,yords] = ndgrid(1:xdim,1:ydim);
xords         = xords(:)';  yords = yords(:)';
I             = 1:xdim*ydim;
zords_init    = ones(1,xdim*ydim);
svol          = xdim*ydim*zdim;

% Legend of results being plotted
% -------------------------------------------------------------------------
[pathstr,name_image] = fileparts(V.fname);
undersc              = find(name_image=='_');

if ~isempty(undersc) && length(undersc)>1
    res_name             = name_image(undersc(end)+1);
    subset_model         = name_image(1:undersc(end-1)-1);
else
    res_name = '';
end

% Show results being displayed on graphics window
switch res_name
       case 'a'
            xSPM.str = sprintf('Alphas: %s',subset_model);
       case 'p'
            xSPM.str = sprintf('PPM: %s',subset_model);
       case 'x'
            xSPM.str = sprintf('PPM: %s',subset_model);
       case 'e'
            xSPM.str = sprintf('EPM: %s',subset_model);
       otherwise
            xSPM.str = '';
end

% Loop over slices (get voxels above threshold)
% -------------------------------------------------------------------------
xyz_above = [];
z_above   = [];
xyz_total = [];

for z = 1:zdim,

    zords = z*zords_init;
    xyz   = [xords(I); yords(I); zords(I)];
    zvals = spm_get_data(V,xyz);
    above = find(zvals>threshold);
    if ~isempty(above)
        xyz_above = [xyz_above,xyz(:,above)];
        z_above   = [z_above,zvals(above)];
    end
    xyz_total = [xyz_total,xyz];
end

% SPM figure: SPM, MIP and GUI
% -------------------------------------------------------------------------
if ~isempty(z_above)

    z_orig = z_above;
    % Log odds transform
    if odds
       z_odds = log(z_above./(ones(1,length(z_above))-z_above));
       if isempty(find(z_odds == Inf))  % Data don't contain Infs
          z_above = z_odds;
        else
          odds = 0;                     % Don't plot odds
        end
    end

    % Calculate extent threshold filtering
    % ---------------------------------------------------------------------
    A     = spm_clusters(xyz_above);
    Q     = [];
    for i = 1:max(A)
        j = find(A == i);
        if length(j) >= k; Q = [Q j]; end
    end

    % ...eliminate voxels
    %----------------------------------------------------------------------
    Z     = z_above(:,Q);
    XYZ   = xyz_above(:,Q);
    z_ps  = z_orig(:,Q);
    if isempty(Q)
        warning(sprintf('No voxels survive extent threshold k=%0.2g',k))
    end

    % Save data in xSPM structure
    voxels_mm         = M*[XYZ;ones(1,size(XYZ,2))];
    voxels_mm         = voxels_mm(1:3,:);
    xSPM.swd          = file_fname;
    xSPM.STAT         = '';
    xSPM.Z            = Z;
    xSPM.XYZ          = XYZ;
    xSPM.XYZmm        = voxels_mm;
    xSPM.xVol.M       = M;
    xSPM.xVol.DIM     = DIM;
    xSPM.SPM.xVol.XYZ = xyz_total;
    xSPM.SPM.xVol.S   = svol;
    xSPM.SPM.xVol.M   = M;
    xSPM.SPM.xVol.DIM = DIM;
    xSPM.DIM          = DIM;
    xSPM.M            = M;
    xSPM.iM           = iM;
    xSPM.n            = 1;
    xSPM.k            = k;
    xSPM.df           = [];
    xSPM.u            = threshold;
    xSPM.FWHM         = 10;                    % arbritary value
    xSPM.STAT         = '';
    xSPM.VOX          = vox;
    xSPM.thres        = threshold;
    xSPM.vols         = post;
    xSPM.scale        = odds;
    xSPM.units        = {'mm'  'mm'  'mm'};
    xSPM.Ps           = [];
    xSPM.S            = 0;
    xSPM.z_ps         = z_ps;
    xSPM.VRpv         = [];
    xSPM.Vspm         = [];
    BMS.xSPM          = xSPM;

    % Display on workspace
    assignin('base','BMS',BMS);
    assignin('base','xSPM',xSPM);

    % Display results
    hReg = spm_bms_display(BMS,'Init');

    assignin('base','hReg',hReg);

else

    % No voxels for selected threshold
    disp('No voxels above threshold!');
    uicontrol(Finter,'Style','Text','String','No voxels above threshold!',...
            'Position',[020 010 200 020].*WS,...
            'FontAngle','Italic',...
            'FontSize',FS(12),...
            'HorizontalAlignment','Left',...
            'ForegroundColor','w')
    do_results = spm_input('Return to Results?', '+1', 'y/n', [1,0], 2);

    % Go back to BMS Maps (Results)
    if do_results

        % Return to display routine
        spm_run_bms_vis;

    else

        spm('Clear',Finter); % Clear Finter window
        return               % Finish

    end

end


%-------------------------------------------------------------------------------------------------------------------%
%
% IB2d is an Immersed Boundary Code (IB) for solving fully coupled non-linear
% 	fluid-structure interaction models. This version of the code is based off of
%	Peskin's Immersed Boundary Method Paper in Acta Numerica, 2002.
%
% Author: Nicholas A. Battista
% Email:  battistn@tcnj.edu
% Date Created: October 8th, 2018
% Institution: TCNJ
%
% This code is capable of creating Lagrangian Structures using:
% 	1. Springs
% 	2. Beams (*torsional springs / non-invariant beams *)
% 	3. Target Points
%	4. Muscle-Model (combined Force-Length-Velocity model, "HIll+(Length-Tension)")
%
% One is able to update those Lagrangian Structure parameters, e.g., spring constants, resting lengths, etc
%
% There are a number of built in Examples, mostly used for teaching purposes.
%
% If you would like us %to add a specific muscle model, please let Nick (battistn@tcnj.edu) know.
%
%--------------------------------------------------------------------------------------------------------------------%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: provides data from previous .vtk information for restarting a
%           simulation that has ended because of power failure, etc.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [current_time,cter,ctsave,U,V,xLag,yLag,xLag_P,yLag_P] = pass_Back_Data_For_Restart(dt,ctsave,print_dump,path_to_data);

%
% Automated
%
cter = ctsave * print_dump; % Total # of time-steps thus far up to and included last data point saved
current_time = cter * dt;   % Current time in simulation when last time-step was saved

%
% Read in LAGRANGIAN data for last and second to last timepoint for U,V,mVelocity,F_Poro, xLag,yLag,xLag_P,yLag_P
%
[xLag,yLag,xLag_P,yLag_P] = please_Give_Saved_Lag_Point_Info(ctsave,path_to_data);

%
% Read in EULERIAN data for last timepoint for U,V
%
[U,V] = please_Give_Saved_Eulerian_Info(ctsave,path_to_data);

%
% Update for next iteration (*pretends data from last timepoint was just saved*)
%
ctsave = ctsave + 1;                % Update for next ctsave number (always increases by 1 after data is saved)
current_time = current_time + dt;   % Update for next time-step
cter = cter + 1;                    % Update for next time-step

cd ../ % Go back into Example Directory

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: passes back EULERIAN data from last saved timepoint
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [U,V] = please_Give_Saved_Eulerian_Info(ctsave,path_to_data)

    % Points to desired data viz_IB2d data file for CURRENT time-step
    if ctsave<10
       numSim = ['000', num2str(ctsave) ];
    elseif ctsave<100
       numSim = ['00', num2str(ctsave) ];
    elseif ctsave<1000
       numSim = ['0', num2str(ctsave)];
    else
       numSim = num2str(ctsave);
    end

    % Imports (x,y) grid values and ALL EULERIAN DATA %
    %                      DEFINITIONS
    %          x: x-grid                y: y-grid
    %       Omega: vorticity           P: pressure
    %    uMag: mag. of velocity
    %    uX: mag. of x-Velocity   uY: mag. of y-Velocity
    %    U: x-directed velocity   V: y-directed velocity
    %    Fx: x-directed Force     Fy: y-directed Force
    %
    %  Note: U(j,i): j-corresponds to y-index, i to the x-index
    %
    %
    Eulerian_Flags(1) = 0;   % OMEGA
    Eulerian_Flags(2) = 0;   % PRESSURE
    Eulerian_Flags(3) = 0;   % uMAG
    Eulerian_Flags(4) = 0;   % uX (mag. x-component of velocity)
    Eulerian_Flags(5) = 0;   % uY (mag. x-component of velocity)
    Eulerian_Flags(6) = 1;   % uVEC (vector components of velocity: U,V)
    Eulerian_Flags(7) = 0;   % Fx (x-component of force )
    Eulerian_Flags(8) = 0;   % Fy (y-component of force)
    %
    [~,~,~,~,~,~,~,U,V,~,~] = import_Eulerian_Data(path_to_data,numSim,Eulerian_Flags);

    % TURNS OUT UNNECESSARY
    %U = U'; % For IB2d convention from .vtk
    %V = V'; % For IB2d convention from .vtk

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: passes back LAGRANGIAN data from last two saved timepoints
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [xLag,yLag,xLag_P,yLag_P] = please_Give_Saved_Lag_Point_Info(ctsave,path_to_data)

    iP = ctsave - 1; % Previous time-point

    % Points to desired data viz_IB2d data file for CURRENT time-step
    if ctsave<10
       numSim = ['000', num2str(ctsave) ];
    elseif ctsave<100
       numSim = ['00', num2str(ctsave) ];
    elseif ctsave<1000
       numSim = ['0', num2str(ctsave)];
    else
       numSim = num2str(ctsave);
    end

    % Points to desired data viz_IB2d data file for PREVIOUS time-step data
    if iP<10
       numSim_Prev = ['000', num2str(iP) ];
    elseif iP<100
       numSim_Prev = ['00', num2str(iP) ];
    elseif iP<1000
       numSim_Prev = ['0', num2str(iP)];
    else
       numSim_Prev = num2str(iP);
    end

    % Imports immersed boundary positions %
    [xLag,yLag] = give_Lag_Positions(path_to_data,numSim);
    [xLag_P,yLag_P] = give_Lag_Positions(path_to_data,numSim_Prev);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: gives (x,y) positions of the immersed boundary at a single step
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [xLag,yLag] = give_Lag_Positions(path,numSim)

[xLag,yLag] = read_Lagrangian_Data_From_vtk(path,numSim);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: Reads in (x,y) positions of the immersed boundary from .vtk
%           format
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [xLag,yLag] = read_Lagrangian_Data_From_vtk(path,simNums)

cd(path);

filename = ['lagsPts.' num2str(simNums) '.vtk'];  % desired lagsPts.xxxx.vtk file

fileID = fopen(filename);
if ( fileID== -1 )
    error('\nCANNOT OPEN THE FILE!');
end

str = fgets(fileID); %-1 if eof
if ~strcmp( str(3:5),'vtk');
    error('\nNot in proper VTK format');
end

% read in the header info %
str = fgets(fileID);
str = fgets(fileID);
str = fgets(fileID);
str = fgets(fileID);
str = fgets(fileID); % Up to white space in previous lagsPts.X files (pre June 2021)

% Check whether VTK file has time info. This is a VTK file with time,
%       need to read the next 3 lines to have read in appropriate
%       number of header lines.
if ~strcmp( str(1), 'P')
	str = fgets(fileID);
    str = fgets(fileID);
    str = fgets(fileID);
end

% stores # of Lagrangian Pts. as stated in .vtk file
numLagPts = sscanf(str,'%*s %f %*s',1);

% read in the vertices %
[mat,count] = fscanf(fileID,'%f %f %f',3*numLagPts);
if count ~= 3*numLagPts
   error('\nProblem reading in Lagrangian Pts.');
end

mat = reshape(mat, 3, count/3); % Reshape vector -> matrix (every 3 entries in vector make into matrix row)
vertices = mat';              % Store vertices in new matrix

fclose(fileID);               % Closes the data file.

xLag = vertices(:,1);         % x-Lagrangian Pts.
yLag = vertices(:,2);         % y-Lagrangian Pts.

%---------------------------------------------------------------
% NEEDS TO BE COMMENTED OUT!
% (when compared to other file in data analysis toolbox)
%---------------------------------------------------------------
%cd ..;                        % Change directory back to ../viz_IB2d/ directory

clear mat str filename fileID count;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: imports all Eulerian Data at a single step
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [x,y,Omega,P,uMag,uX,uY,U,V,Fx,Fy] = import_Eulerian_Data(path,numSim,Eulerian_Flags)

    %
    % EULERIAN FLAGS FOR WHAT GETS SPIT OUT %
    %
    %Eulerian_Flags(1):   OMEGA
    %Eulerian_Flags(2):   PRESSURE
    %Eulerian_Flags(3):   uMAG
    %Eulerian_Flags(4):   uX (mag. x-component of velocity)
    %Eulerian_Flags(5):   uY (mag. x-component of velocity)
    %Eulerian_Flags(6):   uVEC (x,y-components of velocity: U,V)
    %Eulerian_Flags(7):   Fx (x-component of force )
    %Eulerian_Flags(8):   Fy (y-component of force)
    %

%analysis_path = pwd

% read in Vorticity %
if Eulerian_Flags(1)
    strChoice = 'Omega'; first = 1;
    [Omega,x,y] = read_Eulerian_Data_From_vtk(path,numSim,strChoice,first);
else
    Omega=[];
end

% read in Pressure %
if Eulerian_Flags(2)
    strChoice = 'P'; first = 1;
    [P,x,y] = read_Eulerian_Data_From_vtk(path,numSim,strChoice,first);
else
    P=[];
end

% read in Velocity Magnitude %
if Eulerian_Flags(3)
    strChoice = 'uMag'; first = 1;
    [uMag,x,y] = read_Eulerian_Data_From_vtk(path,numSim,strChoice,first);
else
    uMag=[];
end

% read in x-directed Velocity Magnitude %
if Eulerian_Flags(4)
    strChoice = 'uX'; first = 1;
    [uX,x,y] = read_Eulerian_Data_From_vtk(path,numSim,strChoice,first);
else
    uX=[];
end

% read in y-directed Velocity Magnitude %
if Eulerian_Flags(5)
    strChoice = 'uY'; first = 1;
    [uY,x,y] = read_Eulerian_Data_From_vtk(path,numSim,strChoice,first);
else
    uY=[];
end

% read in x-directed Forces %
if Eulerian_Flags(7)
    strChoice = 'Fx'; first = 1;
    [Fx,x,y] = read_Eulerian_Data_From_vtk(path,numSim,strChoice,first);
else
    Fx=[];
end

% read in y-directed Forces %
if Eulerian_Flags(8)
    strChoice = 'Fy'; first = 1;
    [Fy,x,y] = read_Eulerian_Data_From_vtk(path,numSim,strChoice,first);
else
    Fy=[];
end

% read in Velocity Field %
if Eulerian_Flags(6)
    [U,V] = read_Eulerian_Velocity_Field_vtk(path,numSim);
else
    U=[];
    V=[];
end

% Default for x,y values
if max(Eulerian_Flags([1:5,7,8]))==0
    x=[];
    y=[];
end

%cd(analysis_path);

clear analysis_path;

clear strChoice first;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: Reads in the velocity data field from .vtk format
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%s

function [U,V] = read_Eulerian_Velocity_Field_vtk(path,simNums)

analysis_path = pwd; % Store path to analysis folder!

cd(path);

filename = ['u.' num2str(simNums) '.vtk'];  % desired EULERIAN-DATA.xxxx.vtk file

fileID = fopen(filename);
if ( fileID== -1 )
    error('\nCANNOT OPEN THE FILE!');
end

str = fgets(fileID); %-1 if eof
if ~strcmp( str(3:5),'vtk')
    error('\nNot in proper VTK format');
end

% read in the header info %
str = fgets(fileID);
str = fgets(fileID);
str = fgets(fileID);
str = fgets(fileID);
str = fgets(fileID);

% Check whether VTK file has time info. This is a VTK file with time,
%       need to read the next 3 lines to have read in appropriate
%       number of header lines.
if ~strcmp( str(1:3), 'DIM')
	str = fgets(fileID);
    str = fgets(fileID);
    str = fgets(fileID);
end

% Store grid info
Nx = sscanf(str,'%*s %f %*f %*s',1);
Ny = sscanf(str,'%*s %*f %f %*s',1);

% bypass lines in header %
str = fgets(fileID);
str = fgets(fileID);
str = fgets(fileID);
str = fgets(fileID);
str = fgets(fileID);
str = fgets(fileID);
str = fgets(fileID);

% get formatting for reading in data from .vtk in fscanf %
strVec = '%f';
for i=2:3*Nx
    strVec = [strVec ' %f'];
end

% read in the vertices %
[e_Data,count] = fscanf(fileID,strVec,3*Nx*Ny);
if count ~= 3*Nx*Ny
   error('Problem reading in Eulerian Data.');
end

% reshape the matrix into desired data type %
e_Data = reshape(e_Data, 3, count/3); % Reshape (3*Nx*Nx,1) vector to (Nx*Nx,3) matrix
e_Data = e_Data';                     % Store vertices in new matrix

U = e_Data(:,1);       % Store U data
V = e_Data(:,2);       % Store V data

U = reshape(U,Nx,Ny)';  % Reshape (Nx*Nx,1) matrix to  (Nx,Nx)
V = reshape(V,Nx,Ny)';  % Reshape (Nx*Nx,1) matrix to  (Nx,Nx)

fclose(fileID);         % Closes the data file.

cd ..;                  % Change directory back to ../viz_IB2d/ directory

cd(analysis_path);      % Change directory back to Data Analysis Folder

clear filename fileID str strVec count analysis_path e_Data Nx;


function rez = fullMPMU(rez, DATA)

ops = rez.ops;

Nfilt   = ops.Nfilt;
lam =  ones(Nfilt, 1, 'single');
lam(:)    = ops.lam(3);

[W, U, mu, UtU, nu] = decompose_dWU(ops, rez.dWU, ops.Nrank,rez.ops.kcoords);

pm = exp(-ops.momentum(2));
Params = double([ops.NT ops.Nfilt ops.Th(3) ops.maxFR 10 ops.Nchan ops.Nrank pm ops.epu ops.nt0]);

Params(3) = ops.Th(3);
Params(4) = 50000;
Params(5) = 50;

if ops.GPU
    U0 = gpuArray(U);
else
    U0 = U;
end
%%
nt0     = rez.ops.nt0;
Nrank   = ops.Nrank;
WtW     = zeros(Nfilt,Nfilt,2*nt0-1, 'single');
for i = 1:Nrank
    for j = 1:Nrank
        utu0 = U0(:,:,i)' * U0(:,:,j);
        if ops.GPU
            wtw0 =  gather_try(mexWtW2(Params, W(:,:,i), W(:,:,j), utu0));
        else
            wtw0 =  getWtW2(Params, W(:,:,i), W(:,:,j), utu0);
            wtw0 = permute(wtw0, [2 3 1]);
        end
        WtW = WtW + wtw0;
        clear wtw0 utu0
%         wtw0 = squeeze(wtw(:,i,:,j,:));

    end
end

mWtW = max(WtW, [], 3);
WtW = permute(WtW, [3 1 2]);

if ops.GPU
    WtW = gpuArray(WtW);
end
%%
Nbatch_buff = rez.temp.Nbatch_buff;
Nbatch      = rez.temp.Nbatch;
Nchan       = ops.Nchan;
if ~ops.GPU
   fW = rez.fW; % load fft-ed templates
end
% mWtW = mWtW - diag(diag(mWtW));

% rez.WtW = gather_try(WtW);
%
clear wtw0 utu0 U0
%
clear nspikes2
st3 = [];
rez.st3 = [];

if ops.verbose
   fprintf('Time %3.0fs. Running the final template matching pass...\n', toc)
end

if Nbatch_buff<Nbatch
    fid = fopen(ops.fproc, 'r');
end
msg = [];

if ~isempty(ops.nNeigh)
    nNeigh    = ops.nNeigh;

    rez.cProj = zeros(5e6, nNeigh, 'single');

    % sort pairwise templates
    nsp = sum(rez.nspikes,2);
    vld = single(nsp>100);
    cr    = mWtW .* (vld * vld');
    cr(isnan(cr)) = 0;
    [~, iNgsort] = sort(cr, 1, 'descend');

    % save full similarity score
    rez.simScore = cr;
    maskTT = zeros(Nfilt, 'single');
    rez.iNeigh = iNgsort(1:nNeigh, :);
    for i = 1:Nfilt
        maskTT(rez.iNeigh(:,i),i) = 1;
    end
end
if ~isempty(ops.nNeighPC)
    nNeighPC  = ops.nNeighPC;
    load PCspikes
    ixt = round(linspace(1, size(Wi,1), ops.nt0));
    Wi = Wi(ixt, 1:3);
    rez.cProjPC = zeros(5e6, 3*nNeighPC, 'single');

    % sort best channels
    [~, iNch]       = sort(abs(U(:,:,1)), 1, 'descend');
    maskPC          = zeros(Nchan, Nfilt, 'single');
    rez.iNeighPC    = iNch(1:nNeighPC, :);
    for i = 1:Nfilt
        maskPC(rez.iNeighPC(:,i),i) = 1;
    end
    maskPC = repmat(maskPC, 3, 1);
end

irun = 0;
i1nt0 = int32([1:nt0])';
%%
LAM = lam .* (20./mu).^2;

NT = ops.NT;
batchstart = 0:NT:NT*(Nbatch-Nbatch_buff);

for ibatch = 1:Nbatch
    if ibatch>Nbatch_buff
        offset = 2 * ops.Nchan*batchstart(ibatch-Nbatch_buff); % - ioffset;
        fseek(fid, offset, 'bof');
        dat = fread(fid, [NT ops.Nchan], '*int16');
    else
       dat = DATA(:,:,ibatch);
    end
    if ops.GPU
        dataRAW = gpuArray(dat);
    else
        dataRAW = dat;
    end
    dataRAW = single(dataRAW);
    dataRAW = dataRAW / ops.scaleproc;

    % project data in low-dim space
    if ops.GPU
        data    = gpuArray.zeros(NT, Nfilt, Nrank, 'single');
    else
        data   = zeros(NT, Nfilt, Nrank, 'single');
    end
    for irank = 1:Nrank
        data(:,:,irank) = dataRAW * U(:,:,irank);
    end
    data                = reshape(data, NT, Nfilt*Nrank);

    if ops.GPU
        [st, id, x, errC, PCproj] ...
                        = mexMPmuFEAT(Params,data,W,WtW, mu, lam .* (20./mu).^2, nu);
    else
         [st, id, x, errC, PCproj]= cpuMPmuFEAT(Params,data,fW,WtW, mu, lam .* (20./mu).^2, nu, ops);
    end

    if ~isempty(st)
        if ~isempty(ops.nNeighPC)
            % PCA coefficients
            inds            = repmat(st', nt0, 1) + repmat(i1nt0, 1, numel(st));
            try  datSp      = dataRAW(inds(:), :);
            catch
                datSp       = dataRAW(inds(:), :);
            end
            datSp           = reshape(datSp, [size(inds) Nchan]);
            coefs           = reshape(Wi' * reshape(datSp, nt0, []), size(Wi,2), numel(st), Nchan);
            coefs           = reshape(permute(coefs, [3 1 2]), [], numel(st));
            coefs           = coefs .* maskPC(:, id+1);
            iCoefs          = reshape(find(maskPC(:, id+1)>0), 3*nNeighPC, []);
            rez.cProjPC(irun + (1:numel(st)), :) = gather_try(coefs(iCoefs)');
        end
        if ~isempty(ops.nNeigh)
            % template coefficients
            % transform coefficients
            PCproj          = bsxfun(@rdivide, ...
                bsxfun(@plus, PCproj, LAM.*mu), sqrt(1+LAM));

            PCproj          = maskTT(:, id+1) .* PCproj;
            iPP             = reshape(find(maskTT(:, id+1)>0), nNeigh, []);
            rez.cProj(irun + (1:numel(st)), :) = PCproj(iPP)';
        end
        % increment number of spikes
        irun            = irun + numel(st);

        if ibatch==1;
            ioffset         = 0;
        else
            ioffset         = ops.ntbuff;
        end
        st                  = st - ioffset;

        %     nspikes2(1:size(W,2)+1, ibatch) = histc(id, 0:1:size(W,2));
        STT = cat(2, ops.nt0min + double(st) +(NT-ops.ntbuff)*(ibatch-1), ...
            double(id)+1, double(x), ibatch*ones(numel(x),1));
        st3             = cat(1, st3, STT);
    end
    if rem(ibatch,100)==1
%         nsort = sort(sum(nspikes2,2), 'descend');
        fprintf(repmat('\b', 1, numel(msg)));
        msg             = sprintf('Time %2.2f, batch %d/%d,  NTOT %d\n', ...
            toc, ibatch,Nbatch, size(st3,1));
        fprintf(msg);

    end
end
%%
[~, isort]      = sort(st3(:,1), 'ascend');
st3             = st3(isort,:);

rez.st3         = st3;
if ~isempty(ops.nNeighPC)
    % re-sort coefficients for projections
    rez.cProjPC(irun+1:end, :)  = [];
    rez.cProjPC                 = reshape(rez.cProjPC, size(rez.cProjPC,1), [], 3);
    rez.cProjPC                 = rez.cProjPC(isort, :,:);
    for ik = 1:Nfilt
        iSp                     = rez.st3(:,2)==ik;
        OneToN                  = 1:nNeighPC;
        [~, isortNeigh]         = sort(rez.iNeighPC(:,ik), 'ascend');
        OneToN(isortNeigh)      = OneToN;
        rez.cProjPC(iSp, :,:)   = rez.cProjPC(iSp, OneToN, :);
    end

    rez.cProjPC                 = permute(rez.cProjPC, [1 3 2]);
end
if ~isempty(ops.nNeigh)
    rez.cProj(irun+1:end, :)    = [];
    rez.cProj                   = rez.cProj(isort, :);

    % re-index the template coefficients
    for ik = 1:Nfilt
        iSp                     = rez.st3(:,2)==ik;
        OneToN                  = 1:nNeigh;
        [~, isortNeigh]         = sort(rez.iNeigh(:,ik), 'ascend');
        OneToN(isortNeigh)      = OneToN;
        rez.cProj(iSp, :)       = rez.cProj(iSp, OneToN);
    end
end

%%
% rez.ops             = ops;
rez.W               = W;
rez.U               = U;
rez.mu              = mu;

rez.t2p = [];
for i = 1:Nfilt
    wav0            = W(:,i,1);
    wav0            = my_conv(wav0', .5)';
   [~, itrough]     = min(wav0);
    [~, t2p]        = max(wav0(itrough:end));
    rez.t2p(i,1)    = t2p;
    rez.t2p(i,2)    = itrough;
end

rez.nbins           = histc(rez.st3(:,2), .5:1:Nfilt+1);

[~, rez.ypos]       = max(rez.U(:,:,1), [], 1);
if Nbatch_buff<Nbatch
    fclose(fid);
end

% center the templates
rez.W               = cat(1, zeros(nt0 - (ops.nt0-1-ops.nt0min), Nfilt, Nrank), rez.W);
rez.WrotInv         = (rez.Wrot/200)^-1;
%%
Urot = U;
for k = 1:size(U,3)
   Urot(:,:,k)  = rez.WrotInv' * Urot(:,:,k);
end
for n = 1:size(U,2)
    rez.Wraw(:,:,n) = mu(n) * sq(Urot(:,n,:)) * sq(rez.W(:,n,:))';
end
%


function [dat, dimord] = read_shm_data(hdr, chanindx, begtrial, endtrial)

% READ_SHM_DATA reads the data in real-time from shared memory
% this is a helper function for READ_DATA

% Copyright (C) 2007-2009, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

% this persistent variable is used for caching the 600 packets
% which inproves the throughput when reading overlapping data segments
persistent ctf_shm

% read the data from shared memory, first the meta information only
[msgType msgId sampleNumber numSamples numChannels] = read_ctf_shm;

if isempty(ctf_shm)
  ctf_shm.msgType      = nan(size(msgType));
  ctf_shm.msgId        = nan(size(msgId));
  ctf_shm.sampleNumber = nan(size(sampleNumber));
  ctf_shm.numSamples   = nan(size(numSamples));
  ctf_shm.numChannels  = nan(size(numChannels));
  ctf_shm.data = {};
  ctf_shm.hit   = 0;
  ctf_shm.mis   = 0;
end

% there seems to be a bug in Acq, causing the messageId to wrap around
% hence it cannot be used as index into the packets, so construct a new trial numbering vector
trlNum = nan(size(msgId));
trlNum(msgType==1) = sampleNumber(msgType==1)./numSamples(msgType==1) + 1;

% allocate memory for the data, fill with NaNs
dat = nan(length(chanindx), hdr.nSamples, endtrial-begtrial+1);

% determine which trials/packets to read
sel = find((trlNum>=begtrial) & (trlNum<=endtrial));

% this is for calibrating the integer values to physical values
if isfield(hdr, 'orig') && isfield(hdr.orig, 'gainV')
  gain = diag(hdr.orig.gainV(chanindx));
elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'res4')
  gain = diag([hdr.orig.res4.senres(chanindx).gain]);
end

if length(chanindx)>1
  % this speeds up the multiplication, but would result in a sparse matrix when nchans=1
  gain = sparse(gain);
end

for i=1:length(sel)
  % nchan = numChannels(i);
  % nsmp  = numSamples(i);
  nchan = hdr.nChans;
  nsmp  = hdr.nSamples;
  % buf = read_ctf_shm(sel(i));
  % buf = buf(1:nchan*nsmp);
  if all([msgType(sel(i)) msgId(sel(i)) sampleNumber(sel(i)) numSamples(sel(i)) numChannels(sel(i))] ==  [ctf_shm.msgType(sel(i)) ctf_shm.msgId(sel(i)) ctf_shm.sampleNumber(sel(i)) ctf_shm.numSamples(sel(i)) ctf_shm.numChannels(sel(i))])
    % get the data from the cache
    buf = ctf_shm.data{sel(i)};
    ctf_shm.hit = ctf_shm.hit+1;
  else
    % read the data from shared memory, update the cache
    buf = read_ctf_shm(sel(i),nchan*nsmp);
    ctf_shm.data{sel(i)}         = buf;
    ctf_shm.msgType(sel(i))      = msgType(sel(i));
    ctf_shm.msgId(sel(i))        = msgId(sel(i));
    ctf_shm.sampleNumber(sel(i)) = sampleNumber(sel(i));
    ctf_shm.numSamples(sel(i))   = numSamples(sel(i));
    ctf_shm.numChannels(sel(i))  = numChannels(sel(i));
    ctf_shm.mis                  = ctf_shm.mis+1;
  end
  buf = reshape(buf, nchan, nsmp);
  thistrial = trlNum(sel(i));
  % apply calibration to the selected channels
  dat(:,:,thistrial-begtrial+1) = gain * double(buf(chanindx,:));
end

% if any(isnan(dat(:)))
%   ft_warning('data has been padded with NaNs');
%   fprintf('trials present   = %d - %d\n', min(trlNum), max(trlNum));
%   fprintf('trials requested = %d - %d\n', begtrial, endtrial);
% end

dimord = 'chans_samples_trials';


function [data] = ft_megrealign(cfg, data)

% FT_MEGREALIGN interpolates MEG data towards standard gradiometer locations by
% projecting the individual timelocked data towards a coarse source reconstructed
% representation and computing the magnetic field on the standard gradiometer
% locations.
%
% Use as
%   [interp] = ft_megrealign(cfg, data)
%
% Required configuration options:
%   cfg.template
%   cfg.inwardshift
%
% The new gradiometer definition is obtained from a template dataset,
% or can be constructed by averaging the gradiometer positions over
% multiple datasets.
%   cfg.template       = single dataset that serves as template
%   cfg.template(1..N) = datasets that are averaged into the standard
%
% The realignment is done by computing a minumum norm estimate using a
% large number of dipoles that are placed in the upper layer of the brain
% surface, followed by a forward computation towards the template
% gradiometer array. This requires the specification of a volume conduction
% model of the head and of a source model.
%
% A volume conduction model of the head should be specified with
%   cfg.headmodel   = structure, see FT_PREPARE_HEADMODEL
%
% A source model (i.e. a superficial layer with distributed sources) can be
% constructed from a headshape file, or from inner surface of the volume conduction
% model using FT_PREPARE_SOIURCEMODEL using the following options
%   cfg.spheremesh  = number of dipoles in the source layer (default = 642)
%   cfg.inwardshift = depth of the source layer relative to the headshape
%                     surface or volume conduction model (no default
%                     supplied, see below)
%   cfg.headshape   = a filename containing headshape, a structure containing a
%                     single triangulated boundary, or a Nx3 matrix with surface
%                     points
%
% If you specify a headshape and it describes the skin surface, you should specify an
% inward shift of 2.5 cm.
%
% For a single-sphere or a local-spheres volume conduction model based on the skin
% surface, an inward shift of 2.5 cm is reasonable.
%
% For a single-sphere or a local-spheres volume conduction model based on the brain
% surface, you should probably use an inward shift of about 1 cm.
%
% For a realistic single-shell volume conduction model based on the brain surface, you
% should probably use an inward shift of about 1 cm.
%
% Other options are
% cfg.pruneratio  = for singular values, default is 1e-3
% cfg.verify      = 'yes' or 'no', show the percentage difference (default = 'yes')
% cfg.feedback    = 'yes' or 'no' (default = 'no')
% cfg.channel     =  Nx1 cell-array with selection of channels (default = 'MEG'),
%                      see FT_CHANNELSELECTION for details
% cfg.trials      = 'all' or a selection given as a 1xN vector (default = 'all')
%
% This implements the method described by T.R. Knosche, Transformation
% of whole-head MEG recordings between different sensor positions.
% Biomed Tech (Berl). 2002 Mar;47(3):59-62. For more information and
% related methods, see Stolk et al., Online and offline tools for head
% movement compensation in MEG. NeuroImage, 2012.
%
% To facilitate data-handling and distributed computing you can use
%   cfg.inputfile   =  ...
%   cfg.outputfile  =  ...
% If you specify one of these (or both) the input data will be read from a *.mat
% file on disk and/or the output data will be written to a *.mat file. These mat
% files should contain only a single variable, corresponding with the
% input/output structure.
%
% See also FT_PREPARE_LOCALSPHERES, FT_PREPARE_SINGLESHELL

% Copyright (C) 2004-2014, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

% these are used by the ft_preamble/ft_postamble function and scripts
ft_revision = '$Id$';
ft_nargin   = nargin;
ft_nargout  = nargout;

% do the general setup of the function
ft_defaults
ft_preamble init
ft_preamble debug
ft_preamble loadvar data
ft_preamble provenance data
ft_preamble trackconfig

% the ft_abort variable is set to true or false in ft_preamble_init
if ft_abort
  return
end

% check if the input cfg is valid for this function
cfg = ft_checkconfig(cfg, 'renamed',    {'plot3d',      'feedback'});
cfg = ft_checkconfig(cfg, 'renamedval', {'headshape',   'headmodel', []});
cfg = ft_checkconfig(cfg, 'required',   {'inwardshift', 'template'});
cfg = ft_checkconfig(cfg, 'renamed',    {'hdmfile',     'headmodel'});
cfg = ft_checkconfig(cfg, 'renamed',    {'vol',         'headmodel'});
cfg = ft_checkconfig(cfg, 'renamed',    {'grid',        'sourcemodel'});

% set the default configuration
cfg.headshape  = ft_getopt(cfg, 'headshape', []);
cfg.pruneratio = ft_getopt(cfg, 'pruneratio', 1e-3);
cfg.spheremesh = ft_getopt(cfg, 'spheremesh', 642);
cfg.verify     = ft_getopt(cfg, 'verify',     'yes');
cfg.feedback   = ft_getopt(cfg, 'feedback',   'yes');
cfg.trials     = ft_getopt(cfg, 'trials',     'all', 1);
cfg.channel    = ft_getopt(cfg, 'channel',    'MEG');
cfg.topoparam  = ft_getopt(cfg, 'topoparam',  'rms');

% store original datatype
dtype = ft_datatype(data);

% check if the input data is valid for this function
data = ft_checkdata(data, 'datatype', 'raw', 'feedback', 'yes', 'hassampleinfo', 'yes', 'ismeg', 'yes');

% do realignment per trial
pertrial = all(ismember({'nasX';'nasY';'nasZ';'lpaX';'lpaY';'lpaZ';'rpaX';'rpaY';'rpaZ'}, data.label));

% put the low-level options pertaining to the dipole grid in their own field
cfg = ft_checkconfig(cfg, 'renamed', {'tightgrid', 'tight'}); % this is moved to cfg.sourcemodel.tight by the subsequent createsubcfg
cfg = ft_checkconfig(cfg, 'renamed', {'sourceunits', 'unit'}); % this is moved to cfg.sourcemodel.unit by the subsequent createsubcfg

% put the low-level options pertaining to the sourcemodel in their own field
cfg = ft_checkconfig(cfg, 'createsubcfg', {'sourcemodel'});
% move some fields from cfg.sourcemodel back to the top-level configuration
cfg = ft_checkconfig(cfg, 'createtopcfg', {'sourcemodel'});

if isstruct(cfg.template)
  % this should be a cell-array
  cfg.template = {cfg.template};
end

% retain only the MEG channels in the data and temporarily store
% the rest, these will be added back to the transformed data later.

% select trials and channels of interest
tmpcfg = [];
tmpcfg.trials  = cfg.trials;
tmpcfg.channel = setdiff(data.label, ft_channelselection(cfg.channel, data.label));
rest = ft_selectdata(tmpcfg, data);

tmpcfg.channel = ft_channelselection(cfg.channel, data.label);
data = ft_selectdata(tmpcfg, data);

% restore the provenance information
[cfg, data] = rollback_provenance(cfg, data);

Ntrials = length(data.trial);

% cfg.channel = ft_channelselection(cfg.channel, data.label);
% dataindx = match_str(data.label, cfg.channel);
% restindx = setdiff(1:length(data.label),dataindx);
% if ~isempty(restindx)
%   fprintf('removing %d non-MEG channels from the data\n', length(restindx));
%   rest.label = data.label(restindx);    % first remember the rest
%   data.label = data.label(dataindx);    % then reduce the data
%   for i=1:Ntrials
%     rest.trial{i} = data.trial{i}(restindx,:);  % first remember the rest
%     data.trial{i} = data.trial{i}(dataindx,:);  % then reduce the data
%   end
% else
%   rest.label = {};
%   rest.trial = {};
% end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% construct the average template gradiometer array
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
template = struct([]); % initialize as 0x0 empty struct array with no fields
for i=1:length(cfg.template)
  if ischar(cfg.template{i})
    fprintf('reading template sensor position from %s\n', cfg.template{i});
    tmp = ft_read_sens(cfg.template{i}, 'senstype', 'meg');
  elseif isstruct(cfg.template{i}) && isfield(cfg.template{i}, 'coilpos') && isfield(cfg.template{i}, 'coilori') && isfield(cfg.template{i}, 'tra')
    tmp = cfg.template{i};
  elseif isstruct(cfg.template{i}) && isfield(cfg.template{i}, 'pnt') && isfield(cfg.template{i}, 'ori') && isfield(cfg.template{i}, 'tra')
    % it seems to be a pre-2011v1 type gradiometer structure, update it
    tmp = ft_datatype_sens(cfg.template{i});
  else
    ft_error('unrecognized template input');
  end
  % prevent "Subscripted assignment between dissimilar structures" error
  template = appendstruct(template, tmp); clear tmp
end

grad = ft_average_sens(template);

% construct the final template gradiometer definition
template = [];
template.grad = grad;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FT_PREPARE_VOL_SENS will match the data labels, the gradiometer labels and the
% volume model labels (in case of a localspheres model) and result in a gradiometer
% definition that only contains the gradiometers that are present in the data.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

volcfg = [];
volcfg.headmodel = cfg.headmodel;
volcfg.grad      = data.grad;
volcfg.channel   = data.label; % this might be a subset of the MEG channels
gradorig         = data.grad;  % this is needed later on for plotting. As of
% yet the next step is not entirely correct, because it does not keep track
% of the balancing of the gradiometer array. FIXME this may require some
% thought because the leadfields are computed with low level functions and
% do not easily accommodate for matching the correct channels with each
% other (in order to compute the projection matrix).
[volold, data.grad] = prepare_headmodel(volcfg);

% note that it is necessary to keep the two volume conduction models
% separate, since the single-shell Nolte model contains gradiometer specific
% precomputed parameters. Note that this is not guaranteed to result in a
% good projection for local sphere models.
volcfg.grad    = template.grad;
volcfg.channel = 'MEG'; % include all MEG channels
[volnew, template.grad] = prepare_headmodel(volcfg);

if strcmp(ft_senstype(data.grad), ft_senstype(template.grad))
  [id, it] = match_str(data.grad.label, template.grad.label);
  fprintf('mean distance towards template gradiometers is %.2f %s\n', mean(sum((data.grad.chanpos(id,:)-template.grad.chanpos(it,:)).^2, 2).^0.5), template.grad.unit);
else
  % the projection is from one MEG system to another MEG system, which makes a comparison of the data difficult
  cfg.feedback = 'no';
  cfg.verify = 'no';
end

% copy all options that are potentially used in ft_prepare_sourcemodel
tmpcfg           = keepfields(cfg, {'sourcemodel', 'mri', 'headshape', 'symmetry', 'smooth', 'threshold', 'spheremesh', 'inwardshift', 'xgrid' 'ygrid', 'zgrid', 'resolution', 'tight', 'warpmni', 'template', 'showcallinfo'});
tmpcfg.headmodel = volold;
tmpcfg.grad      = data.grad;
% create the source positions on which the data will be projected
sourcemodel = ft_prepare_sourcemodel(tmpcfg);
pos = sourcemodel.pos;

% sometimes some of the dipole positions are nan, due to problems with the headsurface triangulation
% remove them to prevent problems with the forward computation
sel = find(any(isnan(pos(:,1)),2));
pos(sel,:) = [];

% compute the forward model for the new gradiometer positions
fprintf('computing forward model for %d dipoles\n', size(pos,1));
lfnew = ft_compute_leadfield(pos, template.grad, volnew);
if ~pertrial
  %this needs to be done only once
  lfold = ft_compute_leadfield(pos, data.grad, volold);
  [realign, noalign, bkalign] = computeprojection(lfold, lfnew, cfg.pruneratio, cfg.verify);
else
  %the forward model and realignment matrices have to be computed for each trial
  %this also goes for the singleshell volume conductor model
  %x = which('rigidbodyJM'); %this function is needed
  %if isempty(x)
  %  ft_error('you are trying out experimental code for which you need some extra functionality which is currently not in the release version of FieldTrip. if you are interested in trying it out, contact Jan-Mathijs');
  %end
end

% interpolate the data towards the template gradiometers
for i=1:Ntrials
  fprintf('realigning trial %d\n', i);
  if pertrial
    %warp the gradiometer array according to the motiontracking data
    sel   = match_str(rest.label, {'nasX';'nasY';'nasZ';'lpaX';'lpaY';'lpaZ';'rpaX';'rpaY';'rpaZ'});
    hmdat = rest.trial{i}(sel,:);
    if ~all(hmdat==repmat(hmdat(:,1),[1 size(hmdat,2)]))
      ft_error('only one position per trial is at present allowed');
    else
      %M    = rigidbodyJM(hmdat(:,1))
      M    = ft_headcoordinates(hmdat(1:3,1),hmdat(4:6,1),hmdat(7:9,1));
      grad = ft_transform_geometry(M, data.grad);
    end

    volcfg.grad = grad;
    %compute volume conductor
    [volold, grad] = prepare_headmodel(volcfg);
    %compute forward model
    lfold = ft_compute_leadfield(pos, grad, volold);
    %compute projection matrix
    [realign, noalign, bkalign] = computeprojection(lfold, lfnew, cfg.pruneratio, cfg.verify);
  end
  data.realign{i} = realign * data.trial{i};
  if strcmp(cfg.verify, 'yes')
    % also compute the residual variance when interpolating
    [id,it]   = match_str(data.grad.label, template.grad.label);
    rvrealign = rv(data.trial{i}(id,:), data.realign{i}(it,:));
    fprintf('original -> template             RV %.2f %%\n', 100 * mean(rvrealign));
    datnoalign = noalign * data.trial{i};
    datbkalign = bkalign * data.trial{i};
    rvnoalign = rv(data.trial{i}, datnoalign);
    rvbkalign = rv(data.trial{i}, datbkalign);
    fprintf('original             -> original RV %.2f %%\n', 100 * mean(rvnoalign));
    fprintf('original -> template -> original RV %.2f %%\n', 100 * mean(rvbkalign));
  end
end

% plot the topography before and after the realignment
if strcmp(cfg.feedback, 'yes')

  ft_warning('showing MEG topography (RMS value over time) in the first trial only');
  Nchan = length(data.grad.label);
  [id,it]   = match_str(data.grad.label, template.grad.label);
  pos1 = data.grad.chanpos(id,:);
  pos2 = template.grad.chanpos(it,:);
  prj1 = elproj(pos1); tri1 = delaunay(prj1(:,1), prj1(:,2));
  prj2 = elproj(pos2); tri2 = delaunay(prj2(:,1), prj2(:,2));

  switch cfg.topoparam
    case 'rms'
      p1 = sqrt(mean(data.trial{1}(id,:).^2, 2));
      p2 = sqrt(mean(data.realign{1}(it,:).^2, 2));
    case 'svd'
      [u, s, v] = svd(data.trial{1}(id,:)); p1 = u(:,1);
      [u, s, v] = svd(data.realign{1}(it,:)); p2 = u(:,1);
    otherwise
      ft_error('unsupported cfg.topoparam');
  end

  X = [pos1(:,1) pos2(:,1)]';
  Y = [pos1(:,2) pos2(:,2)]';
  Z = [pos1(:,3) pos2(:,3)]';

  % show figure with old an new helmets, volume model and source positions
  figure
  hold on
  ft_plot_headmodel(volold);
  plot3(sourcemodel.pos(:,1),sourcemodel.pos(:,2),sourcemodel.pos(:,3),'b.');
  plot3(pos1(:,1), pos1(:,2), pos1(:,3), 'r.') % original positions
  plot3(pos2(:,1), pos2(:,2), pos2(:,3), 'g.') % template positions
  line(X,Y,Z, 'color', 'black');
  view(-90, 90);

  % show figure with data on old helmet location
  figure
  hold on
  plot3(pos1(:,1), pos1(:,2), pos1(:,3), 'r.') % original positions
  plot3(pos2(:,1), pos2(:,2), pos2(:,3), 'g.') % template positions
  line(X,Y,Z, 'color', 'black');
  axis equal; axis vis3d
  bnd1 = [];
  bnd1.pos = pos1;
  bnd1.tri = tri1;
  ft_plot_mesh(bnd1,'vertexcolor',p1,'edgecolor','none')
  title('RMS, before realignment')
  view(-90, 90)

  % show figure with data on new helmet location
  figure
  hold on
  plot3(pos1(:,1), pos1(:,2), pos1(:,3), 'r.') % original positions
  plot3(pos2(:,1), pos2(:,2), pos2(:,3), 'g.') % template positions
  line(X,Y,Z, 'color', 'black');
  axis equal; axis vis3d
  bnd2 = [];
  bnd2.pos = pos2;
  bnd2.tri = tri2;
  ft_plot_mesh(bnd2,'vertexcolor',p2,'edgecolor','none')
  title('RMS, after realignment')
  view(-90, 90)
end

% store the realigned data in a new structure
interp.label   = template.grad.label;
interp.grad    = template.grad;   % replace with the template gradiometer array
interp.trial   = data.realign;    % remember the processed data
interp.fsample = data.fsample;
interp.time    = data.time;

% add the rest channels back to the data, these were not interpolated
if ~isempty(rest.label)
  fprintf('adding %d non-MEG channels back to the data (', length(rest.label));
  fprintf('%s, ', rest.label{1:end-1});
  fprintf('%s)\n', rest.label{end});
  for trial=1:length(rest.trial)
    interp.trial{trial} = [interp.trial{trial}; rest.trial{trial}];
  end
  interp.label = [interp.label; rest.label];
end

% copy the trial specific information into the output
if isfield(data, 'trialinfo')
  interp.trialinfo = data.trialinfo;
end

% copy the sampleinfo field as well
if isfield(data, 'sampleinfo')
  interp.sampleinfo = data.sampleinfo;
end

% convert back to input type if necessary
switch dtype
  case 'timelock'
    interp = ft_checkdata(interp, 'datatype', 'timelock');
  otherwise
    % keep the output as it is
end

% do the general cleanup and bookkeeping at the end of the function
ft_postamble debug
ft_postamble trackconfig
ft_postamble previous data

% rename the output variable to accomodate the savevar postamble
data = interp;

ft_postamble provenance data
ft_postamble history    data
ft_postamble savevar    data

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% subfunction that computes the projection matrix(ces)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [realign, noalign, bkalign] = computeprojection(lfold, lfnew, pruneratio, verify)

% compute this inverse only once, although it is used twice
tmp = prunedinv(lfold, pruneratio);
% compute the three interpolation matrices
fprintf('computing interpolation matrix #1\n');
realign = lfnew * tmp;
if strcmp(verify, 'yes')
  fprintf('computing interpolation matrix #2\n');
  noalign = lfold * tmp;
  fprintf('computing interpolation matrix #3\n');
  bkalign = lfold * prunedinv(lfnew, pruneratio) * realign;
else
  noalign = [];
  bkalign = [];
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% subfunction that computes the inverse using a pruned SVD
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [lfi] = prunedinv(lf, r)
[u, s, v] = svd(lf);
if r<1
  % treat r as a ratio
  p = find(s<(s(1,1)*r) & s~=0);
else
  % treat r as the number of spatial components to keep
  diagels = 1:(min(size(s))+1):(min(size(s)).^2);
  p       = diagels((r+1):end);
end
fprintf('pruning %d from %d, i.e. removing the %d smallest spatial components\n', length(p), min(size(s)), length(p));
s(p) = 0;
s(find(s~=0)) = 1./s(find(s~=0));
lfi = v * s' * u';


% EEGTHRESH -  reject trials with out-of-bounds channel values within a
%                specified epoch time range.
%
% Usage:
%   >> [Iin, Iout, newsignal, elec] = eegthresh( signal, frames, ...
%                elecs, negthresh, posthresh, timerange, starttime,endtime);
%
% Required inputs:
%   signal     - 2-D data matrix [channels, frames*sweeps],
%                or 3-D data matrix [channels, frames, sweeps]
%   frames     - number of points per epoch
%   elecs      - [int vector] electrode indices to reject on
%   negthresh  - minimum rejection threshold(s) in uV. This can be an array
%                of values for individual electrodes. If fewer values than
%                electrodes, the last value is used for the remaining
%                electrodes.
%   posthresh  - maximum rejection threshold(s) in uV (same syntax as for
%                negthresh)
%   timerange  - [mintime maxtime] time range limits of the signal
%   starttime  - Starting limit (in seconds or Hz) of range to perform
%                rejection (same syntax  as negthresh)
%   endtime    - Ending limit (in seconds or Hz) of range to perform
%                rejection (same syntax  as negthresh)
%
% Outputs:
%   Iin        - Indexes of epochs accepted
%   Iout       - Indexes of epochs rejected
%   newsignal  - input data after epoch rejection
%   elec       - electrode that triggered the rejections (array of 0s
%                and 1s with the same number of columns as Iout
%                and number of rows = number of electrodes).
%
% Author: Arnaud Delorme, CNL / Salk Institute, 2001
%
% See also: POP_EEGTHRESH, EEGLAB

% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

function [Iin, Iout, newsignal, elec] = eegthresh( signal, pnts, electrodes, negthresh, posthresh, timerange, starttime, endtime)

if nargin < 7
	help eegthresh;
	return;
end

if starttime < timerange(1)
	disp('eegthresh: starting point out of range, adjusted');
    starttime = timerange(1);
end
if endtime > timerange(2)
	disp('eegthresh: ending point out of range, adjusted');
    endtime = timerange(2);
end
if isempty(electrodes)
    electrodes = 1:size(signal,1);
end

% complete thresholds values if necessary
%----------------------------------------
if size(posthresh,2) < size(electrodes,2)
	posthresh = [ posthresh posthresh(end)*ones(1,size(electrodes,2)-size(posthresh,2))];
end
if size(negthresh,2) < size(electrodes,2)
	negthresh = [ negthresh negthresh(end)*ones(1,size(electrodes,2)-size(negthresh,2))];
end

% complete timeselect values if necessary
%----------------------------------------
if size(starttime,2) < size(electrodes,2)
	starttime = [ starttime starttime(end)*ones(1,size(electrodes,2)-size(starttime,2))];
end
if size(endtime,2) < size(electrodes,2)
	endtime = [ endtime endtime(end)*ones(1,size(electrodes,2)-size(endtime,2))];
end

% find the maximum for each trial
%--------------------------------
sweeps = size(signal(1,:),2)/pnts;
signal = reshape(signal(electrodes,:), size(electrodes(:),1), pnts, sweeps);

% reject the selected trials
%---------------------------
elec = zeros(size(electrodes(:),1), sweeps);
allelec = zeros(1, sweeps);
for indexe = 1:size(electrodes(:),1)
	% transform the time range
	% ------------------------
	framelowlimit  = max(1,floor((starttime(indexe)-timerange(1))/(timerange(2)-timerange(1))*(pnts-1))+1);
	framehighlimit = floor((endtime(indexe)  -timerange(1))/(timerange(2)-timerange(1))*(pnts-1))+1;

	% remove outliers
	% ---------------
	sigtmp = squeeze(signal(indexe,framelowlimit:framehighlimit,:));
    if size(signal,3) == 1, sigtmp = sigtmp'; end
	sigmax = max(sigtmp, [], 1);
	sigmin = min(sigtmp, [], 1);
	elec(indexe,:) = ( sigmin < negthresh(indexe) ) | ( sigmax > posthresh(indexe) );
	allelec = allelec | elec(indexe,:);
end
Iout = find( allelec == 1 );
Iin  = find( allelec == 0 );
elec = elec(:,Iout);

% reject the selected trials
%---------------------------
newsignal = reshape(signal, size(signal,1), pnts, sweeps);
if ~isempty(Iin)
	newsignal = newsignal(:,:,Iin);
	if ndims(signal) == 2
		newsignal = newsignal(:,:);
	end
else
	newsignal = [];
end
return;


% eeg_getica() - get ICA component activation. Recompute if necessary.
%
% >> mergelocs = eeg_getica(EEG, comp);
%
% Inputs:
%     EEG     - EEGLAB dataset structure
%     comp    - component index
%
% Output:
%     icaact  - ICA component activity
%
% Author: Arnaud Delorme, 2006

% Copyright (C) Arnaud Delorme, CERCO, 2006, arno@salk.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function icaact = eeg_getica(EEG, comp)

  if nargin < 1
    help eeg_getica;
    return;
  end;
  if nargin < 2
    comp = 1:size(EEG.icaweights,1);
  end;

  if ~isempty(EEG.icaact)
    icaact = EEG.icaact(comp,:,:);
  else
    disp('Recomputing ICA activations');
    if isempty(EEG.icachansind)
        EEG.icachansind = 1:EEG.nbchan;
        disp('Channels indices are assumed to be in regular order and arranged accordingly');
    end
    icaact = (EEG.icaweights(comp,:)*EEG.icasphere)*reshape(EEG.data(EEG.icachansind,:,:), length(EEG.icachansind), EEG.trials*EEG.pnts);
    icaact = reshape( icaact, size(icaact,1), EEG.pnts, EEG.trials);
  end;


function  [image_data,vlat,vlon] = mygrid_sand2(region,ssfname)
%  MYGRID_SAND2  Read bathymetry data from Sandwell Database
%    [Z,LAT,LON] = MYGRID_SAND2(REGION) extracts data from
%    the Sandwell and Smith bathymetry, which is now at 1-minute
%    resolution.
%
%
% WARNING: change ssfname and ssversion to the correct one for
%          your machine
%
%                                               Catherine de Groot-Hedlin
%                                               modified Rich Pawlowicz
%
% latitudes must be between -80.738 and 80.738;
%       input:
%               REGION =[west east south north];
%       output:
%               Z - matrix of sandwell bathymetry/topography
%               LAT - vector of latitudes associated with image_data
%               LON - vector of longitudes
%
%  An odd Z value of say -2001m signifies that this pixel was constrained
%  by a real depth sounding while an even depth of say -2000m is
%  a predicted depth.  Plot rem(Z,2) to see this.
%
%  Changes  Jan/18 - modified to work with post v9 database versions
%                    also order of arguments, and various other
%                    things that bothered me.

if nargin<1
    region=[-140 -121 46 52];
end

if nargin<2
  %ssfname='/ocean/rich/more/mmapbase/s_and_s/topo_8.2.img';
  %ssversion=8.2;
  ssfname='/ocean/rich/more/mmapbase/s_and_s/topo_18.1.img';
  ssversion=18.1;
end

%------no changes below here-------------

% determine the requested region
wlon = region(1);
elon = region(2);
blat = region(3);
tlat = region(4);

% Setup the parameters for reading Sandwell data version
if ssversion<9
   db_res         = 2/60;          % 2 minute resolution
   db_loc         = [-72.006 72.006 0.0 360-db_res];
   db_size        = [6336 10800];
else
   db_res         = 1/60;          % 1 minute resolution
   db_loc         = [-80.738  80.738 0.0 360-db_res];
   db_size        = [17280 21600];
end
nbytes_per_lat = db_size(2)*2;  % 2-byte integers

% Check ranges

if blat<db_loc(1)
    blat=db_loc(1);
end
if tlat>db_loc(2)
    tlat=db_loc(2);
end

% Determine if the database needs to be read twice (overlapping prime meridian)
if ((wlon<0)&&(elon>=0))
      wlon      = [wlon           0];
      elon      = [360-db_res  elon];
end

% Calculate number of "records" down to start (latitude) (0 to db_size(1)-1)
% (mercator projection)
rad=pi/180;

arg1=log(tand(45+db_loc(1)/2));
arg2=log(tand(45+blat/2));
iblat = fix(db_size(1) +1 - (arg2-arg1)/(db_res*rad));

arg2=log(tand(45+tlat/2));
itlat = fix(db_size(1) +1 - (arg2-arg1)/(db_res*rad));

if (iblat < 0 ) || (itlat > db_size(1)-1)
        errordlg([' Requested latitude is out of file coverage ']);
end

% Go ahead and read the database
% Open the data file
fid = fopen( ssfname, 'r','b');
if (fid < 0)
        error(['Could not open database: '  ssfname],'Error');
end

image_data     = [];
for i = 1:length(wlon)

        % Make sure the longitude data goes from 0 to 360
        if wlon(i) < 0
                wlon(i) = 360 + wlon(i);
        end

        if elon(i) < 0
                elon(i) = 360 + elon(i);
        end

        % Calculate the longitude indices into the matrix (0 to db_size(1)-1)
        iwlon(i) = fix((wlon(i)-db_loc(3))/db_res);
        ielon(i) = fix((elon(i)-db_loc(3))/db_res);
        if (iwlon(i) < 0 ) || (ielon(i) > db_size(2)-1)
               error([' Requested longitude is out of file coverage ']);
        end

        % allocate memory for the data
        data = zeros(iblat-itlat+1,ielon(i)-iwlon(i)+1);

        % Skip into the appropriate spot in the file, and read in the data
        disp('Reading in bathymetry data');
        for ilat = itlat:iblat
                offset = ilat*nbytes_per_lat + iwlon(i)*2;
                status = fseek(fid, offset, 'bof');
                data(iblat-ilat+1,:)=fread(fid,[1,ielon(i)-iwlon(i)+1],'integer*2');
        end

        % put the two files together if necessary
        if (i>1)
                image_data = [image_data data];
        else
                image_data = data;
        end
end
% close the file
fclose(fid);

% Determine the coordinates of the image_data
vlat=zeros(1,iblat-itlat+1);
arg2 = log(tand(45+db_loc(1)/2.));
for ilat=itlat+1:iblat+1
        arg1 = rad*db_res*(db_size(1)-ilat+0.5);
        term=exp(arg1+arg2);
        vlat(iblat-ilat+2)=2*atand(term)-90;
end
vlon=db_res*((iwlon+1:ielon+1)-0.5);

% to plot it up

if nargout==0
  [xx,yy]=meshgrid(vlon,vlat);
  pcolor(xx,yy,image_data),shading flat,colormap(jet),colorbar('vert')
  xlabel('longitude'),ylabel('latitude'),title('Smith and Sandwell bathymetry Example')
  clear image_data vlon vlat
end


function rgb = brain

% returns a predefined color as [red green blue] values
%
% skin_surface         = [255 213 119]/255;
% outer_skull_surface  = [140  85  85]/255;
% inner_skull_surface  = [202 100 100]/255;
% cortex = [255 213 119]/255;
% black  = [0   0   0  ]/255;
% white  = [255 255 255]/255;
% red    = [255 0   0  ]/255;
% green  = [0   192 0  ]/255;
% blue   = [0   0   255]/255;
% yellow = [255 255 0  ]/255;
% cortex_light = [199 194 169]/255;
% cortex_dark  = [100 97 85]/255;

rgb = [202 100 100]/255;


% COVAREP parallel feature formant extraction function
%
% Description
%  This function performs COVAREP_feature_formant_extraction
%  on all .wav files in the specified folder in parallel
%
% Input
%  in_dir [directory path] : Path to directory containing wav files to be analysed
%  options:     Struct with optional arguments (applied to all files in folder).
%
% Output
%  None
%
% 'options' can have the following fields:
%  feature_fs:  Sampling rate of the returned features (default: 0.01ms)
%  gender:      Used for vowelSpace (0: female (default); 1: male; 2: child)
%  features:    The list of features to be extracted (default: all).
%               Possible features are: 'f0', 'F', 'VUV', 'NAQ', 'QOQ',
%               'H1H2', 'PSP', 'MDQ', 'HRF', 'peakSlope', 'Rd', 'Rd_conf',
%               'MCEP', 'HMPDM', 'HMPDD', 'vowelSpace', 'VAD'
%  mcep_order:  Order of the MCEPs (default: 24)
%  hmpdm_order:	Order of the HMPDMs (default: 24)
%  hmpdd_order:	Order of the HMPDDs (default: 12)
%  channel:     If the audio file has multiple channels (default: 1)
%  save_mat:    Save the results as a MAT file (default: false)
%  save_csv:    Save the results as a CSV file (default: true)
%                   If 'save_mat' or 'save_csv' are strings, they are
%                   interpreted as paths to the file to be created.
% Author
%   Florian Helmhold <Florian@Helmhold.de> based on
%   COVAREP_feature_formant_extraction_perfile (Torsten Wörtwein <twoertwe@cs.cmu.edu>)
%   COVAREP_feature_extraction.m (John Kane <kanejo@.tcd.ie>)
%   COVAREP_formant_extraction.m (Stefan Scherer <scherer@ict.usc.edu>)

function COVAREP_feature_formant_extraction(in_dir, options)

%% Default settings
if nargin < 2
    options = struct; % Default empty options struct
end

%% Sanity check options
if isfield(options, 'save_mat') && ~islogical(options.save_mat)
    warning('Non boolean save_mat options will overwrite the output file.')
end

if isfield(options, 'save_csv') && ~islogical(options.save_csv)
    warning('Non boolean save_csv options will overwrite the output file.')
end

% Analysis settings
fileList=dir([in_dir filesep '*.wav']);
N=length(fileList);

if N==0
    disp('No wav files in inputted directory!!!')
end

if(hasParallelComputing)
    parfor n=1:N
        basename=regexp(fileList(n).name,'\.wav','split');
        basename=char(basename(1));
        disp(['Analysing file: ' basename])
        try
            COVAREP_feature_formant_extraction_perfile([in_dir filesep basename '.wav'], options)
            disp([basename ' successfully analysed'])
        catch err
            warning(['An error occurred while analysing ' basename ': ' getReport(err)])
        end
    end
else
    for n=1:N
        basename=regexp(fileList(n).name,'\.wav','split');
        basename=char(basename(1));
        disp(['Analysing file: ' basename])
        try
            COVAREP_feature_formant_extraction_perfile([in_dir filesep basename '.wav'], options)
            disp([basename ' successfully analysed'])
        catch err
            warning(['An error occurred while analysing ' basename ': ' getReport(err)])
        end
    end
end

%% Helper functions

function has_parallel = hasParallelComputing
% get all installed toolbox names
v = ver;
% collect the names in a cell array
[installedToolboxes{1:length(v)}] = deal(v.Name);

% check
has_parallel = all(ismember({'Parallel Computing Toolbox'},installedToolboxes));


function [ obj ] = estimate( obj, varargin )
% Estimate parameters of the HUGE model.
%
% INPUTS:
%   obj - A tapas_Huge object containing fMRI time series.
%
% OPTIONAL INPUTS:
%   This function accepts optional name-value pair arguments. For a list of
%   valid name-value pairs, see the user manual or type 'help
%   tapas_huge_property_names'.
%
% OUTPUTS:
%   obj - A tapas_Huge object containing the estimation result in the
%         'posterior' property.
%
% EXAMPLES:
%   [obj] = ESTIMATE(obj)    Invert the HUGE model stored in obj.
%
%   [obj] = ESTIMATE(obj, 'K', 2)    Set the number of clusters to 2 and
%       invert the HUGE model stored in obj.
%
%   [obj] = ESTIMATE(obj, 'Verbose', true)    Print progress of estimation
%       to command line.
%
%   [obj] = ESTIMATE(obj, 'Dcm', dcms, 'OmitFromClustering', 1)    Import
%       data stored in 'dcms' and omit self-connections from clustering.
%
% See also TAPAS_HUGE_DEMO
%

% Author: Yu Yao (yao@biomed.ee.ethz.ch)
% Copyright (C) 2019 Translational Neuromodeling Unit
%                    Institute for Biomedical Engineering,
%                    University of Zurich and ETH Zurich.
%
% This file is part of TAPAS, which is released under the terms of the GNU
% General Public Licence (GPL), version 3. For further details, see
% <https://www.gnu.org/licenses/>.
%
% This software is provided "as is", without warranty of any kind, express
% or implied, including, but not limited to the warranties of
% merchantability, fitness for a particular purpose and non-infringement.
%
% This software is intended for research only. Do not use for clinical
% purpose. Please note that this toolbox is under active development.
% Considerable changes may occur in future releases. For support please
% refer to:
% https://github.com/translationalneuromodeling/tapas/issues
%

%% process and check input
obj = obj.optional_inputs(varargin{:});
assert(obj.N > 0, 'TAPAS:HUGE:NoData', 'Cannot estimate without data.')

tapas_huge_compile( );

% save random number generator seed
seed = rng();

% check if filename for storing result is valid
filename = obj.options.nvp.saveto;
if ~isempty(filename)
    [pathStr, fileStr, extStr] = fileparts(filename);
    if ~strcmpi(extStr,'.mat')
        filename = [filename '.mat'];
        [pathStr, fileStr, extStr] = fileparts(filename);
    end
    if isempty(fileStr)
        fileStr = ['huge' datestr(now,'-yyyymmdd-HHMMSS')];
    end
    filename = fullfile(pathStr, [fileStr, extStr]);
    save(filename, obj);
end

% decide how to treat confounds
switch lower(obj.options.nvp.confoundsvariant)
    case 'default'
        obj.options.confVar = double(obj.M > 0);
    case 'none'
        obj.options.confVar = 0;
    case 'global'
        obj.options.confVar = 1;
    case 'cluster'
        obj.options.confVar = 2;
end
if obj.options.confVar && ~obj.M
    obj.options.confVar = 0;
    warning('TAPAS:HUGE:MissingConfounds',...
        ['HUGE is configured to use group-level confounds, but no values ' ...
         'for confounds were supplied. Proceeding without confounds.']);
end

if obj.K > obj.N
    warning('TAPAS:HUGE:LargeK',...
        'Number of clusters K exceeds number of subjects N.');
end

% check priors
obj.prior = build_prior(obj);

% starting values
obj = prepare_starting_values(obj);

%% model inversion
obj.aux = struct();
fprintf('Inverting HUGE with %u cluster', obj.K);
if obj.K > 1
    fprintf('s');
end
fprintf(' using %s.\n', obj.options.nvp.method);

switch obj.options.nvp.method
    case 'VB'
        obj = obj.vb_invert( );
    case 'MH'
        obj = obj.mh_invert( );
end

%% post processing
obj.aux = [];
obj.options.start = rmfield(obj.options.start, {'subjects', 'clusters'});

% if working with simulated data, calculate balanced purity
obj.posterior.bPurity = [];
if ~isempty(obj.model)
    model = obj.model;
    [~, labels] = max(model.d, [], 2);
    obj.posterior.bPurity = tapas_huge_bpurity(labels, obj.posterior.q_nk);
end
% save additional information
obj.posterior.method = obj.options.nvp.method;
obj.posterior.version = obj.version;
obj.posterior.seed = seed;

% save result
if ~isempty(filename)
    save(filename, obj);
    fprintf('Saved result to "%s".\n', filename);
end

end

function [ prior ] = build_prior( obj )

prior = struct();

% alpha_0
prior.alpha_0 = obj.options.prior.alpha_0;
if isscalar(prior.alpha_0)
    prior.alpha_0 = repmat(prior.alpha_0, obj.K, 1);
end
assert(size(prior.alpha_0, 1) == obj.K && size(prior.alpha_0, 2) == 1 && ...
    all(prior.alpha_0 > 0), 'TAPAS:HUGE:Prior', ...
    'Prior alpha0 must be positive column vector of length %u.', obj.K);

% S_0
prior.S_0 = obj.options.nvp.priorclustervariance;
if isscalar(prior.S_0)
    prior.S_0 = eye(obj.idx.P_c)*prior.S_0;
end
assert(size(prior.S_0, 1) == obj.idx.P_c, 'TAPAS:HUGE:Prior',...
     'PriorClusterVariance must be of size %ux%u.', obj.idx.P_c, obj.idx.P_c);

% m_0
prior.m_0 = obj.options.nvp.priorclustermean;
if isscalar(prior.m_0)
    prior.m_0 = repmat(prior.m_0, 1, obj.idx.P_c);
end
assert(numel(prior.m_0) == obj.idx.P_c, 'TAPAS:HUGE:Prior', ...
       'PriorClusterMean must be row vector of length %u.', obj.idx.P_c);
prior.m_0 = prior.m_0(:)';

% nu_0
prior.nu_0 = obj.options.nvp.priordegree;
assert(all(prior.nu_0(:) > 0), 'TAPAS:HUGE:Prior', ...
    'PriorDegree must be positive scalar.');

% tau_0
prior.tau_0 = obj.options.nvp.priorvarianceratio;
assert(all(prior.tau_0(:) > 0), 'TAPAS:HUGE:Prior', ...
    'PriorCovarianceRatio must be positive scalar.');

% mu_h
prior.mu_h = obj.options.prior.mu_h;
if isscalar(prior.mu_h)
    prior.mu_h = repmat(prior.mu_h, 1, obj.idx.P_h);
end
assert(size(prior.mu_h, 2) == obj.idx.P_h && ...
       size(prior.mu_h, 1) == 1, 'TAPAS:HUGE:Prior', ...
    'Prior homogenous mean must be row vector of length %u.', obj.idx.P_h);

% Sigma_h
prior.Sigma_h = obj.options.prior.Sigma_h;
if isscalar(prior.Sigma_h)
    prior.Sigma_h = eye(obj.idx.P_h)*prior.Sigma_h;
elseif isvector(prior.Sigma_h)
    assert(length(prior.Sigma_h)>=4, 'TAPAS:HUGE:Prior', ...
        'Prior homogenous covariance must be a vector of length 4.')
    A = double(obj.dcm.a - diag(diag(obj.dcm.a)))*prior.Sigma_h(2) + ...
        eye(obj.R)*prior.Sigma_h(1);
    tmp = double([obj.dcm.b(:);obj.dcm.c(:);obj.dcm.d(:)])*prior.Sigma_h(3);
    tmp = [A(:); tmp; ones(2*obj.R+1,1)*prior.Sigma_h(4)];
    prior.Sigma_h = diag(tmp(obj.idx.homogenous));
end
try
    assert(size(prior.Sigma_h, 1) == obj.idx.P_h && ...
        issymmetric(prior.Sigma_h), '', '');
    chol(prior.Sigma_h);
catch
    error('TAPAS:HUGE:Prior', ['Prior hemodynamic covariance must ' ...
        'be symmetric, positive definite matrix of size %u.'], obj.idx.P_h);
end

% mean and variance of lambda
prior.mu_lambda = obj.options.prior.mu_lambda;
assert(prior.mu_lambda > 0, 'TAPAS:HUGE:Prior', ...
    'Prior mean of noise precision must be positive scalar.');
prior.s2_lambda = obj.options.prior.s2_lambda;
assert(prior.s2_lambda > 0, 'TAPAS:HUGE:Prior', ...
    'Prior variance of noise precision must be positive scalar.');

% m_beta_0
prior.m_beta_0 = obj.options.prior.m_beta_0;
if isscalar(prior.m_beta_0)
    prior.m_beta_0 = repmat(prior.m_beta_0, obj.M, 1);
end
assert(size(prior.m_beta_0, 1) == obj.M && ...
       size(prior.m_beta_0, 2) == 1, 'TAPAS:HUGE:Prior', ...
    'Prior confound mean must be column vector of length %u.', obj.M);

% S_beta_0
prior.S_beta_0 = obj.options.prior.S_beta_0;
if isscalar(prior.S_beta_0)
    prior.S_beta_0 = eye(obj.M)*prior.S_beta_0;
end
try
    assert(size(prior.S_beta_0, 1) == obj.M && ...
        issymmetric(prior.S_beta_0), '', '');
    chol(prior.S_beta_0);
catch
    error('TAPAS:HUGE:Prior', ['Prior confound covariance must ' ...
        'be symmetric, positive definite matrix of size %u.'], obj.M);
end

end

function [ obj ] = prepare_starting_values( obj )
% subject-level
% initialize starting values to prior mean
stVal1 = repmat([obj.prior.m_0, obj.prior.mu_h], obj.N, 1);

if ~isempty(obj.options.nvp.startingvaluedcm) && ...
        isnumeric(obj.options.nvp.startingvaluedcm) % custom starting values
    stVal1 = obj.options.nvp.startingvaluedcm;
    [stN, stP] = size(stVal1);
    assert(stN == obj.N && stP == obj.idx.P_c + obj.idx.P_h,...
        'TAPAS:HUGE:StartingValues',...
        'Size of subject-level starting values does not agree with model.')
elseif strcmpi(obj.options.nvp.startingvaluedcm, 'spm') % use SPM estimates
    for n = 1:obj.N
        try
            tmp = [obj.data(n).spm.A(:); obj.data(n).spm.B(:); ...
                obj.data(n).spm.C(:); obj.data(n).spm.D(:); ...
                obj.data(n).spm.transit(:); obj.data(n).spm.decay(:);...
                obj.data(n).spm.epsilon(:)];
            stVal1(n,:) = full(tmp([obj.idx.clustering; obj.idx.homogenous]));
        catch
            fprintf('Missing or invalid SPM estimate for subject %u.' , n);
            fprintf(' Using prior as starting value instead.\n');
        end
    end
end

% randomize starting values
if obj.options.nvp.randomize && ~(strcmpi(obj.options.nvp.method, 'MH') && ...
        ~obj.options.mh.nSteps.dcm) %%% TODO remove exception and introduce new method for clustering only
    stVal1 = stVal1 + randn(size(stVal1)).*obj.options.start.dcm;
end

obj.options.start.subjects = stVal1;

% cluster-level
if ~isempty(obj.options.nvp.startingvaluegmm) && ...
        isnumeric(obj.options.nvp.startingvaluegmm) % custom starting values
    stVal2 = obj.options.nvp.startingvaluegmm;
    [stN, stP] = size(stVal2);
    assert(stN == obj.K && stP == obj.idx.P_c,...
        'TAPAS:HUGE:StartingValues',...
        'Size of cluster-level starting values does not agree with model.')
else
    stVal2 = repmat(obj.prior.m_0, obj.K, 1);
end

% randomize starting values
if obj.options.nvp.randomize && ~(strcmpi(obj.options.nvp.method, 'MH') && ...
        ~obj.options.mh.nSteps.clusters)
    stVal2 = stVal2 + randn(size(stVal2)).*obj.options.start.gmm;
end

obj.options.start.clusters = stVal2;

end


function output = callecos(yalmipmodel)
originalModel = yalmipmodel;
% Fix ECOS options
options = yalmipmodel.options;
options.ecos.verbose = options.verbose~=0;
if ~isempty(yalmipmodel.binary_variables)
    options.ecos.bool_vars_idx = yalmipmodel.binary_variables;
end
if ~isempty(yalmipmodel.integer_variables)
    options.ecos.int_vars_idx = yalmipmodel.integer_variables;
end
model.opts = options.ecos;

if ~isempty(yalmipmodel.ub)
    [yalmipmodel.F_struc,yalmipmodel.K] = addStructureBounds(yalmipmodel.F_struc,yalmipmodel.K,yalmipmodel.ub,yalmipmodel.lb);
end

% Write nonlinear functions using exponential cone operators, if possible
[yalmipmodel,output] = normalizeExponentialCone(yalmipmodel);
if output.problem
    return
end

% Map to ECOS syntax
cones = [];
cones.f = yalmipmodel.K.f;
cones.l = yalmipmodel.K.l;
cones.q = yalmipmodel.K.q;
cones.s = yalmipmodel.K.s;
cones.ep = yalmipmodel.K.e;
model.c = full(yalmipmodel.c);
model.A = -yalmipmodel.F_struc(1:cones.f,2:end);if isempty(model.A);model.A = [];end
model.b = full(yalmipmodel.F_struc(1:cones.f,1));if isempty(model.b);model.b = [];end
model.G = -yalmipmodel.F_struc(1+cones.f:end,2:end);if isempty(model.G);model.G = [];end
model.h = full(yalmipmodel.F_struc(1+cones.f:end,1));if isempty(model.h);model.h = [];end
if nnz(cones.l) > 0
    model.dims.l = cones.l;
end
if nnz(cones.q) > 0
    model.dims.q = cones.q;
end
if nnz(cones.ep) > 0
    model.dims.e = cones.ep;
    tempG = model.G(1:model.dims.l+sum(cones.q),:);
    temph = model.h(1:model.dims.l+sum(cones.q));
    top = 1+model.dims.l+sum(cones.q);
    for i = 1:model.dims.e
        tempG = [tempG;model.G(top + [0;2;1],:)];
        temph = [temph;model.h(top + [0;2;1],:)];
        top = top  + 3;
    end
    model.G = tempG;
    model.h = temph;
end

if options.savedebug
    save ecosdebug model
end

if options.showprogress;showprogress(['Calling ' yalmipmodel.solver.tag],options.showprogress);end
if isempty(model.A)
    solvertime = tic;
    [x,y,info,s,z] = ecos(model.c,model.G,model.h,model.dims,model.opts);
    solvertime = toc(solvertime);
else
    solvertime = tic;
    [x,y,info,s,z] = ecos(model.c,model.G,model.h,model.dims,model.A,model.b,model.opts);
    solvertime = toc(solvertime);
end

% Internal format, only keep original variablesop
if ~isempty(x)
    Primal = x(1:length(originalModel.c));
else
    Primal = nan(length(originalModel.c),1);
end
if ~isempty(yalmipmodel.evalMap)
    % No support for duals when exponential cones yet
    Dual = [];
else
    Dual   = [y;z];
end

switch info.exitflag
    case 0
        problem = 0;
    case 1
        problem = 1;
    case 2
        problem = 2;
    case -1
        problem = 3;
    case {-2,-3}
        problem = 4;
    case -7
        problem = 9;
    case {10,11}
        problem = 4;
    otherwise
        problem = 9;
end

% Save ALL data sent to solver
if options.savesolverinput
    solverinput.model = model;
else
    solverinput = [];
end

% Save ALL data from the solution?
if options.savesolveroutput
    solveroutput.x = x;
    solveroutput.y = y;
    solveroutput.info = info;
    solveroutput.s = s;
    solveroutput.z = z;
else
    solveroutput = [];
end

% Standard interface
output = createOutputStructure(Primal,Dual,[],problem,yalmipmodel.solver.tag,solverinput,solveroutput,solvertime);


function [isrc, idet, measure, channel_type] = nst_unformat_channel(channel_label, warn_bad_channel)
% NST_UNFORMAT_CHANNEL extract source, dectector and measure information from channel label.
%
%   [ISRC, IDET, MEAS, CHAN_TYPE] = NST_UNFORMAT_CHANNEL(CHANNEL_LABEL)
%       CHANNEL_LABEL (str):
%           formatted as 'SxDyWLz' or 'SxDyHbt', where:
%               x: source index
%               y: detector index
%               z: wavelength
%               t: Hb type (O, R, T).
%           Examples: S1D2WL685, S01D7WL830, S3D01HbR
%
%        ISRC (int): extracted source index
%        IDET (int): extracted detector index
%        MEAS (int | str): extracted measure value
%        CHAN_TYPE (int): extracted channel type.
%
%        If channel cannot be unformatted then all returned values are nan
%
%   See also NST_UNFORMAT_CHANNELS, NST_CHANNEL_TYPES, NST_FORMAT_CHANNEL
assert(ischar(channel_label));

if nargin < 2
    warn_bad_channel = 0;
end

CHAN_RE = '^S([0-9]+)D([0-9]+)(WL\d+|HbO|HbR|HbT)$';
toks = regexp(channel_label, CHAN_RE, 'tokens');
if isempty(toks)
    if warn_bad_channel
        warning('NIRSTORM:MalformedChannelLabel', ...
            ['Malformed channel label:', channel_label, ...
            '. Should be SxDyWLz or SxDyHb(O|R|T)']);
    end
    isrc = nan;
    idet = nan;
    measure = nan;
    channel_type = nan;
else
    isrc = str2double(toks{1}{1});
    idet = str2double(toks{1}{2});
    measure = toks{1}{3};

    measure_types = nst_measure_types();
    if ~isempty(strfind(measure, 'WL'))
        channel_type = measure_types.WAVELENGTH;
        measure = str2double(measure(3:end));
    else
        channel_type = measure_types.HB;
    end
end

end


function fgOut=dtiGetFibersConnectingGM(fg, dt, minDist, showFig)
%Select fibers with both endpoints located near grey matter.
%
%  fg=dtiFibersConnectingGM(fg, dt, [minDist=1.74])
%
% Returns a fibers structure which is a subset of fibers from the original
% fiber group, keeping only the fibers whose both endpoints terminate near
% grey matter or the most inferior axial plane (the latter to trap
% cortico-spinal fibers). Relies on spm to perform tissue segmentation of b0.
% Grey matter mask is rather generous: anything with probability(gm)>0.
%
% Input parameters:
% minDist  - maximum distance from a fiber endpoint to Gm mask.
% showFig  - 'true', will show Gm mask; 'false', will save the mask.
%
% HISTORY:
% 07/31/2009 ER wrote it

if ~exist('showFig', 'var') || isempty(showFig)
showFig=false;
end

if ~exist('minDist','var') || isempty(minDist)
    minDist=1.74;
end

[wm, gm, csf] = mrAnatSpmSegment(dt.b0, dt.xformToAcpc, 'mniepi'); gm=gm>=127;

% Only fibers whose both endpoints are within the gray matter (roi prepared) will be considered.
[x1,y1,z1] = ind2sub(size(gm), find(gm));

%fill up the most inferior nonzero slice & below with "gray matter" voxels -- to make
%sure corticospinal fibers will not be eliminated when retaining only
%"gray matter connecting" voxels.
gm_withcst=gm;
gm_withcst(:, :, min(z1))=1;

[x1_withcst,y1_withcst,z1_withcst] = ind2sub(size(gm_withcst), find(gm_withcst));
roi4cst= dtiNewRoi('mrAnatSpmSegment_gm');
roi4cst.coords = mrAnatXformCoords(dt.xformToAcpc, [x1_withcst,y1_withcst,z1_withcst]);

[fgOut] = dtiIntersectFibersWithRoi([], {'and', 'both_endpoints'}, minDist, roi4cst, fg);

if showFig
    showMontage(gm_withcst);
else
    imwrite(makeMontage(gm_withcst), fullfile(fileparts(dt.dataFile), 'bin', 'gmMask.png'));
end