function cobra(OutFileBase,anat_file,angle_file,ecc_file, ...
               xfm_file,invxfm_file,var_file);
%function cobra(OutFileBase,anat_file,angle_file,ecc_file, ...
%               xfm_file,invxfm_file,var_file);
%
% Program to automatically identify the visual field signs (VFS).
%
% ----------------------------------------------------------------------
% Input : OutFileBase    : output name base,
%         anat_file      : anatomy (either t1 or classified white matter only),
%         angle_file     : fMRI file(s) with angular stimulation,
%         ecc_file       : fMRI file(s) with eccentricity stimulation,
%         xfm_file       : tranformation file from native to talairach,
%                          one or same number as angle_files
%                          [default = []],
%         invxfm_file    : inverse of previous one [default = []],
%         var_file       : file containing variables used; 
%                          edit according to your needs.
%                          [default = 'RetinoGlobals']
%                          
%
% ----------------------------------------------------------------------
% Output: OutFileBase_VFS.mnc  : volume with Visual Field Signs for each voxel,
%         OutFileBase_mVFS.mnc : same as previous one weighted by the
%                                magnitude of the signal in each voxel,
%         OutFileBase_avg_fft_magnitude.mnc
%		               : average magnitude of signal in polar angle
%                                and eccentricity data,
% Optional outputs:
%         OutFileBase_{ecc/pol}_fft_phase.mnc
%                              : eccentricity/polar angle phase map, 
%         OutFileBase_{ecc/pol}_fft_magnitude.mnc
%                              : eccentricity/polar magnitude phase map, 
%         OutFileBase_{ecc/pol}_dspear_tmap.mnc
%                              : t-statistical map of signal in polar angle
%                                and eccentricity data,
%         OutFileBase_avg_dspear_tmap.mnc
%		               : average t-statistical map of signal 
%                                in polar angle and eccentricity data, 
%         OutFileBase_tVFS.mnc : same as mVFS.mnc one, now 
%                                weighted by the t-statistical value 
%                                of the signal in each voxel,
%         OutFileBase_Qs.mnc   : volume with visual quadrants identified.
%
% ----------------------------------------------------------------------
%

% ---------------------------------
% Copyright (c) 2003 Serge Dumoulin
% This program is free software; you can redistribute it and/or
% modify it under the terms of the GNU General Public License version 2
% as published by the Free Software Foundation.
% ---------------------------------

%-----------------------------------------------------------------------
% program structure (main functions used):
%  -RetinoGlobals           (define parameters to be used)
%  -CreateTMPdir            (create unique tmp-dir)
%  -RetPhaseAnalysis        (get phase and magnitude data)
%    phase_fit
%    [fm_resample2          (if(FAST), use fm_resample2 to prevent artifacts)]
%  -PhaseShift              (shift phase data)
%  [GetVisualQuadrants      (get visual quadrants if requested)]       
%  -GetDerivatives2         (compute derivatives phase data sets)
%    RetAvg2                 
%  -RetAvg2                 (combine derivatives)
%  -RetAnatPreProcess       (get resolution matched derivatives anatomy file)
%  -calc_vfs                (calculate visual field signs)
%
% minc-functions called:
%  mincblur
%  mincmath
%  mincresample
%  mincaverage
%  (evt.) xfminvert
%-----------------------------------------------------------------------

%-----------------------------------------------------------------------
% known bugs: (to be fixed sometime)
%  -does not crash gracefully
%  -cannot start or stop halfway 
%   (copying and pasting into matlab will work though ---
%    making sure all the variables are there, ie load variables.mat
%    from the temporary directory)
%  -program could be sped up quite a lot,
%   however i'm not sure about the trade off's (so left it that way)
%-----------------------------------------------------------------------

%-----------------------------------------------------------------------
%--- input checks and path stuff
%-----------------------------------------------------------------------

if nargin < 4,
   help(mfilename);
   return;
else,
   %--- add absolute path to name
   OutFileBase=makepathabs(OutFileBase);
   anat_file  =makepathabs(anat_file);
   
   new_angle_file=[];
   for n=1:size(angle_file,1),
      tmp=makepathabs(angle_file(n,:));
      new_angle_file=strvcat(new_angle_file,tmp);
   end;
   angle_file=new_angle_file;

   new_ecc_file=[];
   for n=1:size(ecc_file,1),
      tmp=makepathabs(ecc_file(n,:));
      new_ecc_file=strvcat(new_ecc_file,tmp);
   end;
   ecc_file=new_ecc_file;
   clear new_angle_file new_ecc_file tmp;   
end;
if nargin < 5,
   xfm_file = [];
else,
   new_xfm_file=[];
   for n=1:size(xfm_file,1),
      tmp=makepathabs(xfm_file(n,:));
      new_xfm_file=strvcat(new_xfm_file,tmp);
   end;
   xfm_file=new_xfm_file;
   clear new_xfm_file tmp;
end;
if nargin < 6,
   invxfm_file=[];
else,
   new_invxfm_file=[];
   for n=1:size(invxfm_file,1),
      tmp=makepathabs(invxfm_file(n,:));
      new_invxfm_file=strvcat(new_invxfm_file,tmp);
   end;
   invxfm_file=new_invxfm_file;
   clear new_xfm_file tmp;
end;
if nargin < 7,
   var_file='RetinoGlobals';
end;

%--- number of input file checks
if size(angle_file,1)~=size(ecc_file,1),
   disp(sprintf(['Warning: not the same amount of ' ...
                 'polar-angle files (%d) and eccentricity files (%d)'], ...
                 size(angle_file,1),size(ecc_file,1)));
end;
if ~isempty(xfm_file),
   if size(angle_file,1)~=size(xfm_file,1) & size(xfm_file,1)~=1,
      disp(sprintf(['Error: unequal amount of ' ...
                    'polar-angle files (%d) and xfm_files (%d)'], ...
                    size(angle_file,1),size(xfm_file,1)));
      return;
   end;
   if ~isempty(invxfm_file),
      if size(xfm_file,1)~=size(invxfm_file,1),
         disp(sprintf(['Error: unequal amount of ' ...
                       'xfm files (%d) and inverse xfm_files (%d)'], ...
                       size(xfm_file,1),size(invxfm_file,1)));
         return;
      end;
   end;
end;


%-----------------------------------------------------------------------
%--- load variables
%-----------------------------------------------------------------------

%--- timing
starttime=clock;
startcpu =cputime;

%--- reset errors
lasterr('');

%--- load variables
eval(var_file);
disp(sprintf('[%s]: using variables defined in: %s',mfilename,var_file)); 

%--- create tmp-dir
[RET_TMP_SUBDIR]=CreateTMPdir(RET_TMP_DIR,mfilename);

if isempty(RET_LIKE_FILE),
   RET_LIKE_FILE=[anat_file];
end;

if isempty(DERIVATIVES_KERNEL),
   [dimSteps]=GetMincDims([angle_file;ecc_file  ]);
   % order the steps in descending order: large to small
   which_dimSteps = fliplr(get_values(dimSteps)); 
   DERIVATIVES_KERNEL=which_dimSteps(:,1);
end;

%--- save all variables in tmpdir
if ~isempty(RET_TMP_SUBDIR),
   MySaveName=[RET_TMP_SUBDIR '/variables.mat'];
else,
   MySaveName='variables.mat';
end;
save(MySaveName);

%--- allow for different stimulus freq. for polar-angle and eccentricity
if prod(size(RET_STIM_CYCLES))==1,
   RET_STIM_CYCLES = [RET_STIM_CYCLES; RET_STIM_CYCLES];
elseif prod(size(RET_STIM_CYCLES)) > 2,
   disp(sprintf('Warning: too many variables (%d) for RET_STIM_CYCLES',...
                prod(size(RET_STIM_CYCLES))));
end;

%--- same for RET_BLANKS
if size(RET_BLANKS,1)==1,
   RET_BLANKS(2,:)=RET_BLANKS(1,:);
end;

   
%-----------------------------------------------------------------------
%---start actual analysis
%-----------------------------------------------------------------------
cd(RET_TMP_SUBDIR);

%-----------------------------------------------------------------------
%--- phase analysis files - if RET_FAST_METH == FALSE resample as well
%-----------------------------------------------------------------------
%--- polar angle phase map
RetPhaseAnalysis(angle_file,[], ...
                 xfm_file,RET_LIKE_FILE,RET_FFT_THRESH, ...
                 RET_STIM_CYCLES(1),RET_BLANKS(1,find(RET_BLANKS(1,:))),...
                 'phase2angle_',RET_INT_THRESH, ...
                 RET_FAST_METH,GET_TMAP);

%--- eccentricity phase map
RetPhaseAnalysis(ecc_file  ,[], ...
                 xfm_file,RET_LIKE_FILE,RET_FFT_THRESH, ...
                 RET_STIM_CYCLES(2),RET_BLANKS(2,find(RET_BLANKS(2,:))),...
                 'phase1ecc___',RET_INT_THRESH, ...
                 RET_FAST_METH,GET_TMAP);


if GET_TMAP == TRUE,
   %--- average the two t-maps together and (roughly) correct for the averaging process
   %average
   system(['mincaverage phase1ecc____dspear_tmap.mnc ' ...
         'phase2angle__dspear_tmap.mnc ' ...
         'phase_avg_dspear_tmap.mnc ']);
   system(['mincmath -mult -const 1.4142 ' ...
         'phase_avg_dspear_tmap.mnc ' ...
         OutFileBase '_avg_dspear_tmap.mnc']);
   %minmimum
    system(['mincmath -min ' 'phase1ecc____dspear_tmap.mnc ' ...
         'phase2angle__dspear_tmap.mnc ' ...
         OutFileBase '_min_dspear_tmap.mnc ']);
   if KEEP_INDIVIDUAL_MAPS == TRUE,
      copyfile(['phase1ecc____dspear_tmap.mnc'], ...
               [OutFileBase '_ecc_dspear_tmap.mnc']);
      copyfile(['phase2angle__dspear_tmap.mnc'], ...
               [OutFileBase '_pol_dspear_tmap.mnc']);
   end;
end;

if KEEP_INDIVIDUAL_MAPS == TRUE,
   copyfile(['phase1ecc____fft_phase.mnc'], ...
            [OutFileBase '_ecc_fft_phase.mnc']);
   copyfile(['phase2angle__fft_phase.mnc'], ...
            [OutFileBase '_pol_fft_phase.mnc']);  
   copyfile(['phase1ecc____fft_magnitude.mnc'], ...
            [OutFileBase '_ecc_fft_magnitude.mnc']);
   copyfile(['phase2angle__fft_magnitude.mnc'], ...
            [OutFileBase '_pol_fft_magnitude.mnc']);  
end;


%--- error check
if ~isempty(lasterr),
   disp(sprintf('Aborting due to error:\n%s',lasterr));
   cd(CUR_DIR);
   if KEEP_TMP == FALSE,
      delete(RET_TMP_SUBDIR);
   end;
   return;
end;

disp(sprintf('[%s]: Done creating phase-maps.',mfilename));
save(MySaveName);

%-----------------------------------------------------------------------
%--- phase shifting files
%-----------------------------------------------------------------------
files=getfiles([],'*phase.mnc');
[p Files2PhS]=getbase(files);

for n=1:size(Files2PhS,1),
   disp(sprintf('PhaseShifting file # %d of %d',n,size(Files2PhS,1)));
   PhaseShift(deblank(Files2PhS(n,:)),[],NUMBER_PHASE_SHIFTS);
end;

%--- get visual quadrants
if GET_VISUAL_QUADRANTS == TRUE,
   filename=[CUR_DIR filesep OutFileBase];
   GetVisualQuadrants2('phase2angle__fft_phase.mnc',Q_BORDER_SHIFT,filename);
end;

disp(sprintf('[%s]: Done creating phase-shifted files.',mfilename));
save(MySaveName);

%-----------------------------------------------------------------------
%--- get derivatives non-linear
%-----------------------------------------------------------------------
files=getfiles([],'*fft_phase*.mnc');
[p PhaseFiles]=getbase(files);

for n=1:size(PhaseFiles,1),
   disp(sprintf('Getting derivatives of file # %d of %d',n,size(PhaseFiles,1)));
   GetDerivatives2(deblank(PhaseFiles(n,:)),DERIVATIVES_KERNEL,ADD);
end;

disp(sprintf('[%s]: Done creating derivatives.',mfilename));
save(MySaveName);

%-----------------------------------------------------------------------
%--- combining phaseshifted derivatives
%-----------------------------------------------------------------------
files=getfiles([],'phase*dx.mnc');
[p fileDx]=getbase(files);
files=getfiles([],'phase*dy.mnc');
[p fileDy]=getbase(files);
files=getfiles([],'phase*dz.mnc');
[p fileDz]=getbase(files);

for n=1:1+NUMBER_PHASE_SHIFTS:size(fileDx,1)-NUMBER_PHASE_SHIFTS,
   [path,name,base,baseid]=getbase(deblank(fileDx(n+NUMBER_PHASE_SHIFTS,:)));
   base2=base(1,1:(size(base,2)-3));
   base=[base2 '_avgdx.mnc'];
   RetAvg2(fileDx(n:n+NUMBER_PHASE_SHIFTS,:),base,0,1,0,ADD);
    
   [path,name,base,baseid]=getbase(deblank(fileDy(n+NUMBER_PHASE_SHIFTS,:)));
   base2=base(1,1:(size(base,2)-3));
   base=[base2 '_avgdy.mnc'];
   RetAvg2(fileDy(n:n+NUMBER_PHASE_SHIFTS,:),base,0,1,0,ADD);

   [path,name,base,baseid]=getbase(deblank(fileDz(n+NUMBER_PHASE_SHIFTS,:)));
   base2=base(1,1:(size(base,2)-3));
   base=[base2 '_avgdz.mnc'];
   RetAvg2(fileDz(n:n+NUMBER_PHASE_SHIFTS,:),base,0,1,0,ADD);
   disp(sprintf('Done avg-phs-der set %d of %d', ...
        (n+NUMBER_PHASE_SHIFTS)/(1+NUMBER_PHASE_SHIFTS), ...
        size(fileDx,1)/(1+NUMBER_PHASE_SHIFTS)));

   % first cleaning up stage
%    if KEEP_TMP == FALSE,
%       delete(deblank(fileDx(n,:)));
%       delete(deblank(fileDx(n+1,:)));
%       delete(deblank(fileDy(n,:)));
%       delete(deblank(fileDy(n+1,:)));
%       delete(deblank(fileDz(n,:)));
%       delete(deblank(fileDz(n+1,:)));
%    end;
end;

disp(sprintf('[%s]: Done combining derivatives.',mfilename));
save(MySaveName);

%--- blurring of derivative files
files=getfiles([],'*avgd*');
[p Der2Blur]=getbase(files);

if SMOOTH_DERIVATIVES > 0,
   %--- blurring of derivative files
   if sum(size(DERIVATIVES_KERNEL))==2, % 1 by 1 matrix
      mykernel=sprintf(' %d %d %d ', ...
         DERIVATIVES_KERNEL,DERIVATIVES_KERNEL,DERIVATIVES_KERNEL);
   else, % assume 1 by 3 matrix
      [m,n] = size(DERIVATIVES_KERNEL);
      if m == 1,       % If a row, turn into column vector
         DERIVATIVES_KERNEL = DERIVATIVES_KERNEL(:);
      end;
      mykernel=sprintf(' %d %d %d ', ...
         DERIVATIVES_KERNEL(1),DERIVATIVES_KERNEL(2),DERIVATIVES_KERNEL(3));
   end;

   % choose weighting type
   if WEIGHT_DERIVATIVES == TRUE,
      if GET_TMAP == TRUE,
         system(['mincmath -clamp -const2 0 9999 ' ...
               'phase1ecc____dspear_tmap.mnc ' ...
               'phase1ecc____clp_dspear_tmap.mnc ']);
         system(['mincmath -clamp -const2 0 9999 ' ...
               'phase2angle__dspear_tmap.mnc ' ...
               'phase2angle__clp_dspear_tmap.mnc ']);
         weigth_ext = '_clp_dspear_tmap.mnc';
      else,
         weigth_ext = '_fft_magnitude.mnc';
      end;
   end;
   
   for n=1:size(Der2Blur,1),
      [path,name,base,baseid]=getbase(deblank(Der2Blur(n,:)));
      base2=base(1,1:(size(base,2)-1));
      
      % do weighting first if required
      if WEIGHT_DERIVATIVES == TRUE,
         file_to_blur=[base '_tmp.mnc'];
         system(['mincmath -clob -mult ' Der2Blur(n,:) ' ' ...
               base(1,1:12) weigth_ext ' ' ...
               file_to_blur]);
      else,
         file_to_blur=deblank(Der2Blur(n,:));
      end;
      
      if GET_SECOND_DERS == FALSE,
         system(['mincblur -gaussian -3dfwhm ' ...
               mykernel file_to_blur ' ' base2]);
         copyfile([base2 '_blur.mnc'],[base2 '_blur_d' ...
               base(1,(size(base,2)-1):size(base,2)) '.mnc']);
         delete([base2 '_blur.mnc']);
      else,
         system(['mincblur -gaussian -partial -3dfwhm ' ...
            mykernel file_to_blur ' ' base2]);
         copyfile([base2 '_blur.mnc'],[base2 '_blur_d' ...
             base(1,(size(base,2)-1):size(base,2)) '.mnc']);
         delete([base2 '_blur.mnc']);
         copyfile([base2 '_dxyz.mnc'],[base2 '_2ndxyz_d' ...
             base(1,(size(base,2)-1):size(base,2)) '.mnc']);
         delete([base2 '_dxyz.mnc']);
         % remove unwanted partial derivative files
         delete([base2 '_dx.mnc']);
         delete([base2 '_dy.mnc']);
         delete([base2 '_dz.mnc']);
      end;
      disp(sprintf('Done blurring-der %d of %d',n,size(Der2Blur,1)));

      % second cleaning up
      if KEEP_TMP == FALSE,
         delete(deblank(Der2Blur(n,:)));
      end;
   end;
   disp(sprintf('[%s]: Done blurring derivatives.',mfilename));
   save(MySaveName);
else,
   for n=1:size(Der2Blur,1),
      [path,name,base,baseid]=getbase(deblank(Der2Blur(n,:)));
      base2=base(1,1:(size(base,2)-1));
      copyfile(deblank(Der2Blur(n,:)),[base2 '_blur_d' ...
           base(1,(size(base,2)-1):size(base,2)) '.mnc']);
   end;
end;


%-----------------------------------------------------------------------
%--- pre-processing of anatomy files
%-----------------------------------------------------------------------
if isempty(invxfm_file),
   if ~isempty(xfm_file),
      invxfm_file=[];
      invxfm_file_base='tmpinvxfmfile';
      
      for n=1:size(xfm_file,1),
         system(['xfminvert ' xfm_file ' ' invxfm_file_base ...
               sprintf('%d',n) '.xfm']);
         invxfm_file=strvcat(invxfm_file,...
                             [invxfm_file_base ...
                              sprintf('%d',n) '.xfm']);
      end;
   else,
      invxfm_file=[];
   end;
end;
%--- actual pre-processing
RetAnatPreProcess(angle_file, ...
                  anat_file, ...
                  xfm_file, ...
                  invxfm_file, ...
                  PREPROC_BLUR_KERNEL, ANAT_DER_KERNEL, [],...
                  RET_LIKE_FILE, 'anatomy',SMOOTH_DERIVATIVES);

disp(sprintf('[%s]: Done preprocessing anatomy file.',mfilename));
save(MySaveName);

%-----------------------------------------------------------------------
%--- VFS calculation
%-----------------------------------------------------------------------
calc_vfs2('anatomy_toFMRI_blur_toRet_', ...
          'phase1ecc____fft_magnitude.mnc', ...
          'phase1ecc____fft_phase_avgd_blur_d', ...
          'phase2angle__fft_magnitude.mnc', ...
          'phase2angle__fft_phase_avgd_blur_d', ...
           GRAD_THRESH, FFT_MAG_THRESH, OutFileBase, ...
           GET_GRADIENT_MAP);

disp(sprintf('[%s]: Done VFS calculation.',mfilename));
save(MySaveName);

%--- combining phase and mag maps
% average
MagAvg=[OutFileBase '_avg_fft_magnitude.mnc'];
system([' mincaverage phase1ecc____fft_magnitude.mnc ' ...
      ' phase2angle__fft_magnitude.mnc ' MagAvg]);
system(['mincmath -mult ' MagAvg ' ' OutFileBase '_VFS.mnc ' ...
       OutFileBase '_mVFS.mnc']);
% minimums
MagAvg=[OutFileBase '_min_fft_magnitude.mnc'];
system([' mincmath -min phase1ecc____fft_magnitude.mnc ' ...
        ' phase2angle__fft_magnitude.mnc ' MagAvg]);
system(['mincmath -mult ' MagAvg ' ' OutFileBase '_VFS.mnc ' ...
        OutFileBase '_min_mVFS.mnc']);
if GET_GRADIENT_MAP,
   system(['mincmath -min ' OutFileBase '_grada.mnc ' ...
           OutFileBase '_gradp.mnc ' ...
           OutFileBase '_grade.mnc ' ...
           OutFileBase '_min_grad.mnc ']);
   system(['mincmath -mult ' OutFileBase '_min_mVFS.mnc ' ...
           OutFileBase '_min_grad.mnc ' ...
           OutFileBase '_min_mgVFS.mnc ']);
end;

         
if GET_TMAP,
   %--- clip tmap to only have pos values
   system(['mincmath -clamp -const2 0 9999 ' ...
           OutFileBase '_avg_dspear_tmap.mnc ' ...
           'phase_clp_avg_dspear_tmap.mnc ']);
   system(['mincmath -clamp -const2 0 9999 ' ...
           OutFileBase '_min_dspear_tmap.mnc ' ...
           'phase_clp_min_dspear_tmap.mnc ']);
   %--- combining phase and t maps
   system(['mincmath -mult ' OutFileBase '_VFS.mnc ' ...
           'phase_clp_avg_dspear_tmap.mnc ' ...
           OutFileBase '_tVFS.mnc ']);
   system(['mincmath -mult ' OutFileBase '_VFS.mnc ' ...
           'phase_clp_min_dspear_tmap.mnc ' ...
           OutFileBase '_min_tVFS.mnc ']);
   if GET_GRADIENT_MAP,
      system(['mincmath -mult ' OutFileBase '_min_tVFS.mnc ' ...
              OutFileBase '_min_grad.mnc ' ...
              OutFileBase '_min_tgVFS.mnc ']);
   end;  
end;


%-----------------------------------------------------------------------
%--- clean up
%-----------------------------------------------------------------------
save(MySaveName);

cd(CUR_DIR);
if KEEP_TMP == FALSE,
   delfiles=getfiles(RET_TMP_SUBDIR);
   for n=1:size(delfiles,1),
      delete(deblank(delfiles(n,:)));
   end;
   delete(RET_TMP_SUBDIR);
end;

if ~isempty(lasterr),
   disp(sprintf('\nLast error encountered:\n%s',lasterr));
end;

elapsedtime.tmin=round(etime(clock,starttime)/60); %minutes
elapsedcpu.tmin =round((cputime-startcpu)/60);
elapsedtime.hrs =floor(elapsedtime.tmin/60);
elapsedcpu.hrs  =floor(elapsedcpu.tmin /60);
elapsedtime.min =floor(elapsedtime.tmin-(60*elapsedtime.hrs));
elapsedcpu.min  =floor(elapsedcpu.tmin -(60*elapsedcpu.hrs ));

disp(sprintf('[%s]: Finished in %d hours and %d minutes (cpu: %d, %d)',mfilename, ...
             elapsedtime.hrs,elapsedtime.min,...
             elapsedcpu.hrs ,elapsedcpu.min));

%-----------------------------------------------------------------------
%--- end
%-----------------------------------------------------------------------
