function [lf] = ft_compute_leadfield(dippos, sens, headmodel, varargin)

% FT_COMPUTE_LEADFIELD computes a forward solution for a dipole in a a volume
% conductor model. The forward solution is expressed as the leadfield
% matrix (Nchan*3), where each column corresponds with the potential or field
% distributions on all sensors for one of the x,y,z-orientations of the
% dipole.
%
% Use as
%   [lf] = ft_compute_leadfield(dippos, sens, headmodel, ...)
% with input arguments
%   dippos    = position dipole (1*3 or Ndip*3)
%   sens      = structure with gradiometer or electrode definition
%   headmodel = structure with volume conductor definition
%
% The headmodel represents a volume conductor model, its contents
% depend on the type of model. The sens structure represents a sensor
% array, i.e. EEG electrodes or MEG gradiometers.
%
% It is possible to compute a simultaneous forward solution for EEG and MEG
% by specifying sens and grad as two cell-arrays, e.g.
%   sens       = {senseeg, sensmeg}
%   headmodel  = {voleeg,  volmeg}
% This results in the computation of the leadfield of the first element of
% sens and headmodel, followed by the second, etc. The leadfields of the
% different imaging modalities are subsequently concatenated.
%
% Additional input arguments can be specified as key-value pairs, supported
% optional arguments are
%   'reducerank'      = 'no' or number
%   'normalize'       = 'no', 'yes' or 'column'
%   'normalizeparam'  = parameter for depth normalization (default = 0.5)
%   'weight'          = number or 1xN vector, weight for each dipole position to compensate for the size of the corresponding patch (default = 1)
%   'backproject'     = 'yes' (default) or 'no', in the case of a rank reduction this parameter determines whether the result will be backprojected onto the original subspace
%
% The leadfield weight may be used to specify a (normalized)
% corresponding surface area for each dipole, e.g. when the dipoles
% represent a folded cortical surface with varying triangle size.
%
% Depending on the specific input arguments for the sensor and volume, this
% function will select the appropriate low-level EEG or MEG forward model.
% The leadfield matrix for EEG will have an average reference over all the
% electrodes.
%
% The supported forward solutions for MEG are
%   infinite homogenous medium
%   single sphere (Cuffin and Cohen, 1977)
%   multiple spheres with one sphere per channel (Huang et al, 1999)
%   realistic single shell using superposition of basis functions (Nolte, 2003)
%   leadfield interpolation using a precomputed sourcemodel
%   boundary element method (BEM)
%
% The supported forward solutions for EEG are
%   infinite homogenous medium
%   infinite halfspace homogenous medium
%   single sphere
%   multiple concentric spheres (up to 4 spheres)
%   leadfield interpolation using a precomputed sourcemodel
%   boundary element method (BEM)
%
% See also FT_PREPARE_VOL_SENS, FT_HEADMODEL_ASA, FT_HEADMODEL_BEMCP,
% FT_HEADMODEL_CONCENTRICSPHERES, FT_HEADMODEL_DIPOLI, FT_HEADMODEL_HALFSPACE,
% FT_HEADMODEL_INFINITE, FT_HEADMODEL_LOCALSPHERES, FT_HEADMODEL_OPENMEEG,
% FT_HEADMODEL_SINGLESHELL, FT_HEADMODEL_SINGLESPHERE,
% FT_HEADMODEL_HALFSPACE

% Copyright (C) 2004-2016, 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$

if iscell(sens) && iscell(headmodel) && numel(sens)==numel(headmodel)
  % this represents combined EEG, ECoG and/or MEG
  % use recursion to compute all leadfields
  lf = cell(1, numel(sens));
  for i=1:length(sens)
    lf{i} = ft_compute_leadfield(dippos, sens{i}, headmodel{i}, varargin{:});
  end
  lf = cat(1, lf{:});
  return;
end

% get the optional input arguments
reducerank      = ft_getopt(varargin, 'reducerank'); % default is handled below
backproject     = ft_getopt(varargin, 'backproject', 'yes');
normalize       = ft_getopt(varargin, 'normalize' , 'no');
normalizeparam  = ft_getopt(varargin, 'normalizeparam', 0.5);
weight          = ft_getopt(varargin, 'weight');
chanunit        = ft_getopt(varargin, 'chanunit');   % this is something like V, T, or T/m
dipoleunit      = ft_getopt(varargin, 'dipoleunit'); % this is something like nA*m

if any(strcmp(varargin(1:2:end), 'unit'))
  ft_error('the ''unit'' option is not supported any more, please use ''chanunit''');
end
if any(strcmp(varargin(1:2:end), 'units'))
  ft_error('the ''units'' option is not supported any more, please use ''chanunit''');
end

if ~isstruct(sens) && size(sens, 2)==3
  % definition of electrode positions only, restructure it
  sens = struct('elecpos', sens);
end

% ft_prepare_vol_sens should be called prior to ft_compute_leadfield
% to ensure that the sens and headmodel are up to date, since the backward
% compatibility check should not be performed for each dipole location
% sens       = ft_datatype_sens(sens);
% headmodel  = ft_datatype_headmodel(headmodel);

% determine whether it is EEG or MEG
iseeg = ft_senstype(sens, 'eeg');
ismeg = ft_senstype(sens, 'meg');

% determine the default for this option
if isempty(reducerank)
  if iseeg
    reducerank = 'no';    % for EEG
  elseif ismeg && ft_headmodeltype(headmodel, 'infinite')
    reducerank = 'no';    % for MEG with a magnetic dipole, e.g. a HPI coil
  else
    reducerank = 'yes';   % for MEG with a current dipole in a volume conductor
  end
end

% multiple dipoles can be represented either as a 1x(N*3) vector or as a
% as a Nx3 matrix, i.e. [x1 y1 z1 x2 y2 z2] or [x1 y1 z1; x2 y2 z2]
Ndipoles = numel(dippos)/3;
if all(size(dippos)==[1 3*Ndipoles])
  dippos = reshape(dippos, 3, Ndipoles)';
end

if isfield(headmodel, 'unit') && isfield(sens, 'unit') && ~strcmp(headmodel.unit, sens.unit)
  ft_error('inconsistency in the units of the volume conductor and the sensor array');
end

if ismeg && iseeg
  % this is something that could be implemented relatively easily
  ft_error('simultaneous EEG and MEG not supported');

elseif ~ismeg && ~iseeg
  ft_error('the input does not look like EEG, nor like MEG');

elseif ismeg
  switch ft_headmodeltype(headmodel)

    case 'singlesphere'
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % MEG single-sphere volume conductor model
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      coilpos = sens.coilpos; % position of each coil
      coilori = sens.coilori; % orientation of each coil

      if isfield(headmodel, 'o')
        % shift dipole and magnetometers to origin of sphere
        dippos  = dippos  - repmat(headmodel.o, Ndipoles, 1);
        coilpos = coilpos - repmat(headmodel.o, size(coilpos, 1), 1);
      end

      if Ndipoles>1
        % loop over multiple dipoles
        lf = zeros(size(coilpos, 1), 3*Ndipoles);
        for i=1:Ndipoles
          lf(:, (3*i-2):(3*i)) = meg_leadfield1(dippos(i, :), coilpos, coilori);
        end
      else
        % only single dipole
        lf = meg_leadfield1(dippos, coilpos, coilori);
      end

      if isfield(sens, 'tra')
        % this appears to be the modern complex gradiometer definition
        % construct the channels from a linear combination of all magnetometers
        lf = sens.tra * lf;
      end

    case 'localspheres'
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % MEG multiple overlapping sphere volume conductor model
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      ncoils = length(sens.coilpos);

      if size(headmodel.r, 1)~=ncoils
        ft_error('number of spheres is not equal to the number of coils')
      end

      if size(headmodel.o, 1)~=ncoils
        ft_error('number of spheres is not equal to the number of coils');
      end

      lf = zeros(ncoils, 3*Ndipoles);
      for coil=1:ncoils
        for dip=1:Ndipoles
          % shift dipole and magnetometer coil to origin of sphere
          tmppos  = dippos(dip, :) - headmodel.o(coil, :);
          coilpos = sens.coilpos(coil, :) - headmodel.o(coil, :);
          tmp = meg_leadfield1(tmppos, coilpos, sens.coilori(coil, :));
          lf(coil, (3*dip-2):(3*dip)) = tmp;
        end
      end

      if isfield(sens, 'tra')
        % this appears to be the modern complex gradiometer definition
        % construct the channels from a linear combination of all magnetometers
        lf = sens.tra * lf;
      end

    case 'neuromag'
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % use external Neuromag toolbox for forward computation
      % this requires that "megmodel" is initialized, which is done in PREPARE_VOL_SENS
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % compute the forward model for all channels
      % tmp1 = ones(1, Ndipoles);
      % tmp2 = 0.01*dippos'; %convert to cm
      % lf = megfield([tmp2 tmp2 tmp2], [[1 0 0]'*tmp1 [0 1 0]'*tmp1 [0 0 1]'*tmp1]);
      for dip=1:Ndipoles
        R = 0.01*dippos(dip, :)'; % convert from cm to m
        Qx = [1 0 0];
        Qy = [0 1 0];
        Qz = [0 0 1];
        lf(:, (3*(dip-1)+1)) = megfield(R, Qx);
        lf(:, (3*(dip-1)+2)) = megfield(R, Qy);
        lf(:, (3*(dip-1)+3)) = megfield(R, Qz);
      end
      % select only those channels from the forward model that are part of the gradiometer definition
      lf = lf(headmodel.chansel, :);

    case 'singleshell'
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % use code from Guido Nolte for the forward computation
      % this requires that "meg_ini" is initialized, which is done in PREPARE_VOL_SENS
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % the dipole position and orientation should be combined in a single matrix
      % furthermore, here I want to compute the leadfield for each of the
      % orthogonal x/y/z directions
      dippar = zeros(Ndipoles*3, 6);
      for i=1:Ndipoles
        dippar((i-1)*3+1, :) = [headmodel.forwpar.scale*dippos(i, :) 1 0 0]; % single dipole with unit strength, x-orientation
        dippar((i-1)*3+2, :) = [headmodel.forwpar.scale*dippos(i, :) 0 1 0]; % single dipole with unit strength, y-orientation
        dippar((i-1)*3+3, :) = [headmodel.forwpar.scale*dippos(i, :) 0 0 1]; % single dipole with unit strength, z-orientation
      end
      % compute the leadfield for each individual coil
      lf = meg_forward(dippar, headmodel.forwpar);
      % the leadfield is computed for cm units, convert it to the desired units
      lf = lf*headmodel.forwpar.scale^2;
      if isfield(sens, 'tra')
        % compute the leadfield for each gradiometer (linear combination of coils)
        lf = sens.tra * lf;
      end

    case 'openmeeg'
        % OpenMEEG lead field already computed in ft_prepare_leadfield;
        % load here so any post-processing options (e.g. normalization) may
        % be applied
        lf = ft_getopt(varargin, 'lf');

    case {'infinite_magneticdipole', 'infinite'}
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % magnetic dipole instead of electric (current) dipole in an infinite vacuum
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      coilpos = sens.coilpos; % position of each coil
      coilori = sens.coilori; % orientation of each coil

      if Ndipoles>1
        % loop over multiple dipoles
        lf = zeros(size(coilpos, 1), 3*Ndipoles);
        for i=1:Ndipoles
          lf(:, (3*i-2):(3*i)) = magnetic_dipole(dippos(i, :), coilpos, coilori);
        end
      else
        % only single dipole
        lf = magnetic_dipole(dippos, coilpos, coilori);
      end

      if isfield(sens, 'tra')
        % construct the channels from a linear combination of all magnetometer coils
        lf = sens.tra * lf;
      end

    case {'infinite_currentdipole'}
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % current dipole in an infinite homogenous conducting medium
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      coilpos = sens.coilpos; % position of each coil
      coilori = sens.coilori; % orientation of each coil

      if Ndipoles>1
        % loop over multiple dipoles
        lf = zeros(size(coilpos, 1), 3*Ndipoles);
        for i=1:Ndipoles
          lf(:, (3*i-2):(3*i)) = current_dipole(dippos(i, :), coilpos, coilori);
        end
      else
        % only single dipole
        lf = current_dipole(dippos, coilpos, coilori);
      end

      if isfield(sens, 'tra')
        % construct the channels from a linear combination of all magnetometer coils
        lf = sens.tra * lf;
      end

    otherwise
      ft_error('unsupported volume conductor model for MEG');
  end % switch type for MEG

elseif iseeg
  switch ft_headmodeltype(headmodel)

    case 'multisphere'
      % Based on the approximation of the potential due to a single dipole in
      % a multishell sphere by three dipoles in a homogeneous sphere, code
      % contributed by Punita Christopher. Note that this one should not get
      % confused with the MEG localspheres model.

      Nelec    = size(sens.elecpos, 1);
      Nspheres = length(headmodel.r);

      % the center of the spherical volume conduction model does not have
      % to be in the origin, therefore shift the spheres, the electrodes
      % and the dipole
      if isfield(headmodel, 'o')
        center = headmodel.o;
      else
        center = [0 0 0];
      end

      % sort the spheres from the smallest to the largest
      % furthermore, the radius should be one (?)
      [radii, indx] = sort(headmodel.r/max(headmodel.r));
      sigma = headmodel.cond(indx);
      r = (sens.elecpos-repmat(center, Nelec, 1))./max(headmodel.r);
      dippos = dippos./max(headmodel.r);

      if Ndipoles>1
        % loop over multiple dipoles
        lf = zeros(Nelec, 3*Ndipoles);
        for i=1:Ndipoles
          rq = dippos(i, :) - center;
          % compute the potential for each dipole ortientation
          % it would be much more efficient to change the punita function
          q1 = [1 0 0]; lf(:, (3*i-2)) = multisphere(Nspheres, radii, sigma, r, rq, q1);
          q1 = [0 1 0]; lf(:, (3*i-1)) = multisphere(Nspheres, radii, sigma, r, rq, q1);
          q1 = [0 0 1]; lf(:, (3*i )) = multisphere(Nspheres, radii, sigma, r, rq, q1);
        end
      else
        % only single dipole
        lf = zeros(Nelec, 3);
        rq = dippos - center;
        % compute the potential for each dipole ortientation
        % it would be much more efficient to change the punita function
        q1 = [1 0 0] ; lf(:, 1) = multisphere(Nspheres, radii, sigma, r, rq, q1);
        q1 = [0 1 0] ; lf(:, 2) = multisphere(Nspheres, radii, sigma, r, rq, q1);
        q1 = [0 0 1] ; lf(:, 3) = multisphere(Nspheres, radii, sigma, r, rq, q1);
      end

    case {'singlesphere', 'concentricspheres'}
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % EEG spherical volume conductor model
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      % FIXME, this is not consistent between spherical and BEM
      % sort the spheres from the smallest to the largest
      [headmodel.r, indx] = sort(headmodel.r);
      headmodel.cond = headmodel.cond(indx);

      Nspheres = length(headmodel.cond);
      if length(headmodel.r)~=Nspheres
        ft_error('the number of spheres in the volume conductor model is ambiguous');
      end

      if isfield(headmodel, 'o')
        % shift the origin of the spheres, electrodes and dipole
        sens.elecpos = sens.elecpos - repmat(headmodel.o, size(sens.elecpos, 1), 1);
        dippos = dippos - repmat(headmodel.o, Ndipoles, 1);
      end

      switch Nspheres
        case 1
          funnam = 'eeg_leadfield1';
        case 2
          headmodel.r = [headmodel.r(1) headmodel.r(2) headmodel.r(2) headmodel.r(2)];
          headmodel.cond = [headmodel.cond(1) headmodel.cond(2) headmodel.cond(2) headmodel.cond(2)];
          funnam = 'eeg_leadfield4';
        case 3
          headmodel.r = [headmodel.r(1) headmodel.r(2) headmodel.r(3) headmodel.r(3)];
          headmodel.cond = [headmodel.cond(1) headmodel.cond(2) headmodel.cond(3) headmodel.cond(3)];
          funnam = 'eeg_leadfield4';
        case 4
          headmodel.r = [headmodel.r(1) headmodel.r(2) headmodel.r(3) headmodel.r(4)];
          headmodel.cond = [headmodel.cond(1) headmodel.cond(2) headmodel.cond(3) headmodel.cond(4)];
          funnam = 'eeg_leadfield4';
        otherwise
          ft_error('more than 4 concentric spheres are not supported')
      end

      lf = zeros(size(sens.elecpos, 1), 3*Ndipoles);
      for i=1:Ndipoles
        lf(:, (3*i-2):(3*i)) = feval(funnam, dippos(i, :), sens.elecpos, headmodel);
      end

    case {'bem', 'dipoli', 'asa', 'bemcp'}
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % EEG boundary element method volume conductor model
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      lf = eeg_leadfieldb(dippos, sens.elecpos, headmodel);

    case 'openmeeg'
        % OpenMEEG lead field already computed in ft_prepare_leadfield;
        % load here so any post-processing options (e.g. normalization) may
        % be applied
        lf = ft_getopt(varargin, 'lf');

    case {'infinite_currentdipole' 'infinite'}
      lf = eeg_infinite_dipole(dippos, sens.elecpos, headmodel);

    case 'halfspace'
      lf = eeg_halfspace_dipole(dippos, sens.elecpos, headmodel);

    case 'infinite_monopole'
      lf = eeg_infinite_monopole(dippos, sens.elecpos, headmodel);

    case 'halfspace_monopole'
      lf = eeg_halfspace_monopole(dippos, sens.elecpos, headmodel);

    case 'slab_monopole'
      lf = eeg_slab_monopole(dippos, sens.elecpos, headmodel);

    case 'simbio'
      ft_hastoolbox('simbio', 1);
      % note that the electrode information is contained in the headmodel (thanks to ft_prepare_vol_sens)
      lf = leadfield_simbio(dippos, headmodel);

    case 'metufem'
      p3 = zeros(Ndipoles * 3, 6);
      for i = 1:Ndipoles
        p3((3*i - 2) : (3 * i), 1:3) = [dippos(i, :); dippos(i, :); dippos(i, :)];
        p3((3*i - 2) : (3 * i), 4:6) = [1 0 0; 0 1 0; 0 0 1];
      end
      lf = metufem('pot', p3', 'interp');

    case 'metubem'
      session = headmodel.session;
      p3 = zeros(Ndipoles * 3, 6);
      for i = 1:Ndipoles
        p3((3*i - 2) : (3 * i), 1:3) = [dippos(i, :); dippos(i, :); dippos(i, :)];
        p3((3*i - 2) : (3 * i), 4:6) = [1 0 0; 0 1 0; 0 0 1];
      end
      [lf, session] = bem_solve_lfm_eeg(session, p3);

    case 'fns'
      % note that the electrode information is contained in the headmodel
      % tolerance = 1e-8;
      lf = leadfield_fns(dippos, headmodel);

    case 'interpolate'
      % note that the electrode information is contained in the headmodel
      lf = leadfield_interpolate(dippos, headmodel);
      % the leadfield is already correctly referenced, i.e. it represents the
      % channel values rather than the electrode values. Prevent that the
      % referencing is done once more.
      sens.tra = speye(length(headmodel.filename));

    otherwise
      ft_error('unsupported volume conductor model for EEG');

  end % switch type for EEG

  % the forward model potential is computed on the electrodes relative to
  % an unknown reference, not on the channels. Therefore the data has to be
  % explicitly referenced here.
  if isfield(sens, 'tra')
    % apply the correct montage to the leadfield
    lf = sens.tra*lf;
  else
    % compute average reference for EEG leadfield
    for i=1:size(lf,2)
      lf(:,i) = lf(:,i) - mean(lf(:,i));
    end
  end

end % iseeg or ismeg

% optionally apply leadfield rank reduction
switch reducerank
  case 'yes'
    reducerank = 2;
  case 'no'
    reducerank = 3;
  otherwise
    % assume that it is specified as a number, keep it like this
end

if reducerank<size(lf,2)
  % decompose the leadfield
  for ii=1:Ndipoles
    tmplfd=lf(:, (3*ii-2):(3*ii));
    [u, s, v] = svd(tmplfd);
    r = diag(s);
    s(:) = 0;
    for j=1:reducerank
      s(j, j) = r(j);
    end

    if istrue(backproject)
      % recompose the leadfield with reduced rank
      lf(:, (3*ii-2):(3*ii)) = u * s * v';
    else
      % if not backprojected, the new leadfield has a different dimension
      if ii==1
        newlf    = zeros(size(lf,1), Ndipoles*reducerank);
        origrank = size(lf,2)./Ndipoles;
      end
      newlf(:, reducerank*(ii-1) + (1:reducerank)) = lf(:, origrank*(ii-1) + (1:origrank))*v(:,1:reducerank);
    end
  end

  if ~istrue(backproject)
    lf = newlf;
  end
  clear newlf;
end

% optionally apply leadfield normalization
switch normalize
  case 'yes'
    for ii=1:Ndipoles
      tmplf = lf(:, (3*ii-2):(3*ii));
      if normalizeparam==0.5
        % normalize the leadfield by the Frobenius norm of the matrix
        % this is the same as below in case normalizeparam is 0.5
        nrm = norm(tmplf, 'fro');
      else
        % normalize the leadfield by sum of squares of the elements of the leadfield matrix to the power "normalizeparam"
        % this is the same as the Frobenius norm if normalizeparam is 0.5
        nrm = sum(tmplf(:).^2)^normalizeparam;
      end
      if nrm>0
        tmplf = tmplf ./ nrm;
      end
      lf(:, (3*ii-2):(3*ii)) = tmplf;
    end
  case 'column'
    % normalize each column of the leadfield by its norm
    for ii=1:Ndipoles
      tmplf = lf(:, (3*ii-2):(3*ii));
      for j=1:size(tmplf, 2)
        nrm = sum(tmplf(:, j).^2)^normalizeparam;
        tmplf(:, j) = tmplf(:, j)./nrm;
      end
      lf(:, (3*ii-2):(3*ii)) = tmplf;
    end
end

% optionally apply a weight to the leadfield for each dipole location
if ~isempty(weight)
  for i=1:Ndipoles
    lf(:, 3*(i-1)+1) = lf(:, 3*(i-1)+1) * weight(i); % the leadfield for the x-direction
    lf(:, 3*(i-1)+2) = lf(:, 3*(i-2)+1) * weight(i); % the leadfield for the y-direction
    lf(:, 3*(i-1)+3) = lf(:, 3*(i-3)+1) * weight(i); % the leadfield for the z-direction
  end
end

if ~isempty(chanunit) || ~isempty(dipoleunit)
  assert(strcmp(headmodel.unit,  'm'), 'unit conversion only possible for SI input units');
  assert(strcmp(sens.unit, 'm'), 'unit conversion only possible for SI input units');
end

if ~isempty(chanunit)
  assert(all(strcmp(sens.chanunit, 'V') | strcmp(sens.chanunit, 'V/m') | strcmp(sens.chanunit, 'T') | strcmp(sens.chanunit, 'T/m')), 'unit conversion only possible for SI input units');
  % compute conversion factor and multiply each row of the matrix
  scale = cellfun(@ft_scalingfactor, sens.chanunit(:), chanunit(:));
  lf = bsxfun(@times, lf, scale(:));
  % prior to this conversion, the units might be  (T/m)/(A*m) for planar gradients or   (V/m)/(A*m) for bipolar EEG
  % after this conversion, the units will be     (T/cm)/(A*m)                      or (uV/mm)/(A*m)
end

if ~isempty(dipoleunit)
  scale = ft_scalingfactor('A*m', dipoleunit); % compue the scaling factor from A*m to the desired dipoleunit
  lf    = lf/scale;                         % the leadfield is expressed in chanunit per dipoleunit, i.e. chanunit/dipoleunit
end


classdef DesignVarMonitor_LevelSet < DesignVarMonitor_Abstract

    properties (Access = protected, Abstract)
        unfittedType
        meshIncludeBoxContour
    end

    properties (Access = protected)
        designVarName = 'Level Set - \phi';
        meshUnfitted
    end

    methods (Access = public)

        function obj = DesignVarMonitor_LevelSet(cParams)
            obj@DesignVarMonitor_Abstract(cParams);
        end

        function plot(obj)
            obj.refreshFigure();
        end

    end

    methods (Access = protected)

        function initPlotting(obj)
             set(obj.axes,'CLim',[0, 1],'XTick',[],'YTick',[]);
        end

    end

    methods (Access = protected, Static)

        function color = getColor()
            color = [1 0 0];
        end

    end

    methods (Access = private)

        function refreshFigure(obj)
            figure(obj.figHandle.Number)
            cla reset;
            hold on
            uMesh = obj.designVar.getUnfittedMesh;
            uMesh.plot();
        end

    end

end


function [nCoords, nDim, nVTMode, c] = plx_vt_interpret(ts, sv);
% plx_vt_interpret - interpret CinePlex video tracking data
%
% [nCoords, nDim, nVTMode, c] = plx_vt_interpret(ts, sv);
%
% INPUT:
%   ts - array of timestamps (in seconds) (see plx_event_ts.m)
%   sv - array of strobed event values (see plx_event_ts.m)
%
% OUTPUT:
%   nCoords - number of produced coordinates
%   nDim    - number of elemnts in produced coordinates
%             nDim = 3 for CENTROID, LED_1, LED_2, LED3
%             nDim = 4 for CENTROID_WITH_MOTION
%             nDim = 5 for LED_12, LED_23, LED_13
%             nDim = 7 for LED_123
%   nVTMode - VT mode:
%              0 = UNKNOWN
%              1 = CENTROID                // 1 set of coordinates, no motion
%              2 = CENTROID_WITH_MOTION    // 1 set of coordinates, with motion
%              3 = LED_1                   // 1 set of coordinates
%              4 = LED_2
%              5 = LED_3
%              6 = LED_12                  // 2 sets of coordinates
%              7 = LED_13
%              8 = LED_23
%              9 = LED_123                 // 3 sets of coordinates
%   c       - nCoords by nDim matrix of produced coordinates
%             c(:, 1) - timestamp
%             c(:, 2) - x1
%             c(:, 3) - y1
%             c(:, 4) - x2 or motion (if present)
%             c(:, 5) - y2 (if present)
%             c(:, 6) - x3 (if present)
%             c(:, 7) - y3 (if present)
%

if nargin < 2
    error 'Expected 2 input arguments';
end

[nCoords, nDim, nVTMode, c] = mexPlex(21, '', ts, sv);


% function cl = enlarge(cl)
%
% enlarge cluster

function cl = enlarge_cluster(cl)

    XYZ = cl.XYZ;
    XYZnew = XYZ;

    for i = 1:3
        Xtmp = XYZ;
        Xtmp(i, :) = Xtmp(i, :) + 1;
        XYZnew = [XYZnew Xtmp];         % add to dim
        Xtmp(i, :) = Xtmp(i, :) - 2;
        XYZnew = [XYZnew Xtmp];      % subtract 1 from dim
    end

    XYZnew = unique(round(XYZnew)', 'rows')';
    cl.XYZ = XYZnew;
    cl.XYZmm = voxel2mm(XYZnew, cl.M);
    cl.Z = ones(1, size(cl.XYZ, 2));

    cl.numVox = size(cl.XYZmm, 2);
end


% io_loadspec_niimrs.m
% Georg Oeltzschner, Johns Hopkins University 2021
%
% USAGE:
% out = io_loadspec_niimrs(filename);
%
% DESCRIPTION:
% Reads in MRS data stored according to the NIfTI MRS format.
% See the specification under
% https://docs.google.com/document/d/1tC4ugzGUPLoqHRGrWvOcGCuCh_Dogx_uu0cxKub0EsM/edit
%
% io_loadspec_niimrs outputs the data in structure format, with fields
% corresponding to time scale, fids, frequency scale, spectra, and header
% fields containing information about the acquisition. The resulting matlab
% structure can be operated on by the other functions in this MRS toolbox.
%
% This function is currently work-in-progress and is being tested on more
% and more datasets. Please contact the FID-A developers for help with a
% particular NIfTI-MRS file that you might encounter problems with when
% using this function.
%
% Currently, this function is limited to single-voxel MRS data. It is
% planned to develop it for full compatibility with 2D and 3D multi-voxel
% and spectroscopic imaging data.
%
% DEPENDENCIES:
% This function requires the dcm2nii toolbox (Xiangrui Li) to be on the
% MATLAB path
% https://github.com/xiangruili/dicm2nii
%
% INPUTS:
% filename   = filename of NIfTI MRS file (*.nii) to load.
%
% OUTPUTS:
% out        = Input dataset in FID-A structure format.

function out = io_loadspec_niimrs(filename)

% Read in the data using the dicm2nii toolbox
% (https://github.com/xiangruili/dicm2nii)
try
    nii = nii_tool('load', filename);
catch ME
    switch ME.identifier
        case 'MATLAB:UndefinedFunction'
            error(['Cannot find the function ''nii_tool.m''.' ...
                ' Please ensure that you have downloaded the required', ...
                ' dcm2nii toolbox (https://github.com/xiangruili/dicm2nii)', ...
                ' and added it to your MATLAB path.']);
        otherwise
            rethrow(ME);
    end
end

% Extract the header and header extensions
hdr = nii.hdr;
hdr_ext = jsondecode(nii.ext.edata_decoded);

% Extract the time-domain data
fids = nii.img;

% Extract spectrometer frequency and dwell time
f0 = hdr_ext.SpectrometerFrequency;
dt = hdr.pixdim(5);
sw = 1/dt;

% Specify dimensions
% In NIfTI MRS, the three spatial dimensions and the time dimension occupy
% fixed indices in the (maximum) 7-D array
dims.x = 1;
dims.y = 2;
dims.z = 3;
dims.t = 4;

% There are some pre-defined dimension names according to the FID-A
% convention. These dimensions may or may not be stored in the NIfTI MRS
% header, so we'll initialize them as 0.
dims.coils = 0;
dims.averages = 0;
dims.subSpecs = 0;
dims.extras = 0;

% The NIfTI MRS standard reserves the remaining 3 dimensions, which are
% then explicitly specified in the JSON header extension fields dim_5,
% dim_6 and dim_7.
if isfield(hdr_ext, 'dim_5')
    dim_number = 5;
    switch hdr_ext.dim_5
        case 'DIM_COIL'
            dims.coils      = dim_number;
        case 'DIM_DYN'
            dims.averages   = dim_number;
        case 'DIM_INDIRECT_0'
            dims.extras     = dim_number;
        case 'DIM_INDIRECT_1'
            dims.extras     = dim_number;
        case 'DIM_INDIRECT_2'
            dims.extras     = dim_number;
        case 'DIM_PHASE_CYCLE'
            dims.extras     = dim_number;
        case 'DIM_EDIT'
            dims.subSpecs   = dim_number;
        case 'DIM_MEAS'
            dims.extras     = dim_number;
        case 'DIM_USER_0'
            dims.extras     = dim_number;
        case 'DIM_USER_1'
            dims.extras     = dim_number;
        case 'DIM_USER_2'
            dims.extras     = dim_number;
        case 'DIM_ISIS'
            dims.subSpecs   = dim_number;
        otherwise
            error('Unknown dimension value specified in dim_5: %s', hdr_ext.dim_5);
    end

end
if isfield(hdr_ext, 'dim_6')
        dim_number = 6;
    switch hdr_ext.dim_6
        case 'DIM_COIL'
            dims.coils      = dim_number;
        case 'DIM_DYN'
            dims.averages   = dim_number;
        case 'DIM_INDIRECT_0'
            dims.extras     = dim_number;
        case 'DIM_INDIRECT_1'
            dims.extras     = dim_number;
        case 'DIM_INDIRECT_2'
            dims.extras     = dim_number;
        case 'DIM_PHASE_CYCLE'
            dims.extras     = dim_number;
        case 'DIM_EDIT'
            dims.subSpecs   = dim_number;
        case 'DIM_MEAS'
            dims.extras     = dim_number;
        case 'DIM_USER_0'
            dims.extras     = dim_number;
        case 'DIM_USER_1'
            dims.extras     = dim_number;
        case 'DIM_USER_2'
            dims.extras     = dim_number;
        case 'DIM_ISIS'
            dims.subSpecs   = dim_number;
        otherwise
            error('Unknown dimension value specified in dim_6: %s', hdr_ext.dim_6);
    end
end
if isfield(hdr_ext, 'dim_7')
        dim_number = 7;
    switch hdr_ext.dim_7
        case 'DIM_COIL'
            dims.coils      = dim_number;
        case 'DIM_DYN'
            dims.averages   = dim_number;
        case 'DIM_INDIRECT_0'
            dims.extras     = dim_number;
        case 'DIM_INDIRECT_1'
            dims.extras     = dim_number;
        case 'DIM_INDIRECT_2'
            dims.extras     = dim_number;
        case 'DIM_PHASE_CYCLE'
            dims.extras     = dim_number;
        case 'DIM_EDIT'
            dims.subSpecs   = dim_number;
        case 'DIM_MEAS'
            dims.extras     = dim_number;
        case 'DIM_USER_0'
            dims.extras     = dim_number;
        case 'DIM_USER_1'
            dims.extras     = dim_number;
        case 'DIM_USER_2'
            dims.extras     = dim_number;
        case 'DIM_ISIS'
            dims.subSpecs   = dim_number;
        otherwise
            error('Unknown dimension value specified in dim_7: %s', hdr_ext.dim_7);
    end
end

% Parse the NIfTI hdr.dim field:
allDims = hdr.dim(2:end); % all dimensions (including singletons)

% Find the number of points
nPts = allDims(dims.t);

% Find the number of averages.  'averages' will specify the current number
% of averages in the dataset as it is processed, which may be subject to
% change.  'rawAverages' will specify the original number of acquired
% averages in the dataset, which is unchangeable.
if dims.subSpecs ~= 0
    if dims.averages ~= 0
        averages = allDims(dims.averages)*allDims(dims.subSpecs);
        rawAverages = averages;
    else
        averages = allDims(dims.subSpecs);
        rawAverages = 1;
    end
else
    if dims.averages ~= 0
        averages = allDims(dims.averages);
        rawAverages = averages;
    else
        averages = 1;
        rawAverages = 1;
    end
end

% FIND THE NUMBER OF SUBSPECS
% 'subspecs' will specify the current number of subspectra in the dataset
% as it is processed, which may be subject to change. 'rawSubspecs' will
% specify the original number of acquired  subspectra in the dataset, which
% is unchangeable.
if dims.subSpecs ~=0
    subspecs = allDims(dims.subSpecs);
    rawSubspecs = subspecs;
else
    subspecs = 1;
    rawSubspecs = subspecs;
end

% ORDERING THE DATA AND DIMENSIONS
% The FID-A array ordering conventions differ from the NIfTI MRS
% convention. Most importantly, FID-A is primarily tailored towards
% single-voxel data. We will start designing this function towards this
% purpose, and later adapt the formalism proposed in the csi_mod branch of
% the FID-A GitHub repository.

if allDims(1)*allDims(2)*allDims(3) == 1 % x=y=z=1
    dims.x = 0;
    dims.y = 0;
    dims.z = 0;
    fids = squeeze(fids);

    %Now that we've indexed the dimensions of the data array, we now need to
    %permute it so that the order of the dimensions is standardized:  we want
    %the order to be as follows:
    %   1) time domain data.
    %   2) coils.
    %   3) averages.
    %   4) subSpecs.
    %   5) extras.

    % Adjust dimension indices for the fact that we have collapsed the
    % three spatial dimensions (which we don't need for SVS data)
    sqzDims = {};
    dimsFieldNames = fieldnames(dims);
    for rr = 1:length(dimsFieldNames)
        if dims.(dimsFieldNames{rr}) ~= 0
            % Subtract 3 (x, y, z) from the dimension indices
            dims.(dimsFieldNames{rr}) = dims.(dimsFieldNames{rr}) - 3;
            sqzDims{end+1} = dimsFieldNames{rr};
        end
    end

    if length(sqzDims)==5
        fids=permute(fids,[dims.t dims.coils dims.averages dims.subSpecs dims.extras]);
        dims.t=1;dims.coils=2;dims.averages=3;dims.subSpecs=4;dims.extras=5;
    elseif length(sqzDims)==4
        if dims.extras==0
            fids=permute(fids,[dims.t dims.coils dims.averages dims.subSpecs]);
            dims.t=1;dims.coils=2;dims.averages=3;dims.subSpecs=4;dims.extras=0;
        elseif dims.subSpecs==0
            fids=permute(fids,[dims.t dims.coils dims.averages dims.extras]);
            dims.t=1;dims.coils=2;dims.averages=3;dims.subSpecs=0;dims.extras=4;
        elseif dims.averages==0
            fids=permute(fids,[dims.t dims.coils dims.subSpecs dims.extras]);
            dims.t=1;dims.coils=2;dims;averages=0;dims.subSpecs=3;dims.extras=4;
        elseif dims.coils==0
            fids=permute(fids,[dims.t dims.averages dims.subSpecs dims.extras]);
            dims.t=1;dims.coils=0;dims.averages=2;dims.subSpecs=3;dims.extras=4;
        end
    elseif length(sqzDims)==3
        if dims.extras==0 && dims.subSpecs==0
            fids=permute(fids,[dims.t dims.coils dims.averages]);
            dims.t=1;dims.coils=2;dims.averages=3;dims.subSpecs=0;dims.extras=0;
        elseif dims.extras==0 && dims.averages==0
            fids=permute(fids,[dims.t dims.coils dims.subSpecs]);
            dims.t=1;dims.coils=2;dims.averages=0;dims.subSpecs=3;dims.extras=0;
        elseif dims.extras==0 && dims.coils==0
            fids=permute(fids,[dims.t dims.averages dims.subSpecs]);
            dims.t=1;dims.coils=0;dims.averages=2;dims.subSpecs=3;dims.extras=0;
        end
    elseif length(sqzDims)==2
        if dims.extras==0 && dims.subSpecs==0 && dims.averages==0
            fids=permute(fids,[dims.t dims.coils]);
            dims.t=1;dims.coils=2;dims.averages=0;dims.subSpecs=0;dims.extras=0;
        elseif dims.extras==0 && dims.subSpecs==0 && dims.coils==0
            fids=permute(fids,[dims.t dims.averages]);
            dims.t=1;dims.coils=0;dims.averages=2;dims.subSpecs=0;dims.extras=0;
        elseif dims.extras==0 && dims.averages==0 && dims.coils==0
            fids=permute(fids,[dims.t dims.subSpecs]);
            dims.t=1;dims.coils=0;dims.averages=0;dims.subSpecs=2;dims.extras=0;
        end
    elseif length(sqzDims)==1
        dims.t=1;dims.coils=0;dims.averages=0;dims.subSpecs=0;dims.extras=0;
    end

    %Now get the size of the data array:
    sz=size(fids);

    %Compared to NIfTI MRS, FID-A needs the conjugate
    fids = conj(fids);

    %Now take fft of time domain to get fid:
    specs=fftshift(ifft(fids,[],dims.t),dims.t);

end

% Fill in additional FID-A format variables
% Nucleus (new field)
out.nucleus = hdr_ext.ResonantNucleus;
% Calculate B0 from spectrometer frequency depending on nucleus
% Gamma from Wikipedia article "Gyromagnetic ratio" (3 signif. digits)
for rr = 1:length(out.nucleus)
    switch out.nucleus{rr}
        case '1H'
            gamma = 42.577;
        case '2H'
            gamma = 6.536;
        case '3HE'
            gamma = -32.434;
        case '7LI'
            gamma = 16.546;
        case '13C'
            gamma = 10.708;
        case '19F'
            gamma = 40.052;
        case '23NA'
            gamma = 11.262;
        case '31P'
            gamma = 17.235;
        case '129XE'
            gamma = -11.777;
    end
    Bo(rr) = f0(rr) ./ gamma;
end

% Calculate t and ppm arrays using the calculated parameters:
f   =[(-sw/2) + (sw/(2*nPts)) : sw/(nPts) : (sw/2) - (sw/(2*nPts))];
ppm = -f / (Bo(1)*42.577);
ppm = ppm + 4.65;
t   = [0 : dt : (nPts-1)*dt];

% MANDATORY FIELDS
% Data & dimensions
out.fids = fids;
out.specs = specs;
out.sz = sz;
out.dims = dims;
out.Bo = Bo;
out.averages = averages;
out.rawAverages = rawAverages;
out.subspecs = subspecs;
out.rawSubspecs = rawSubspecs;

% Echo/repetition time
out.te = hdr_ext.EchoTime;
out.tr = hdr_ext.RepetitionTime;

% time and frequency axis
out.t   = t;
out.ppm = ppm;

% Dwell time & spectral width & field strength
out.spectralwidth = sw;
out.dwelltime = dt;
out.txfrq  = f0 * 10^6;
out.date = '';

% NIfTI-MRS-SPECIFIC FIELDS
% Save the NIfTI header
out.nii_mrs.hdr = hdr;
% Save the header extension
out.nii_mrs.hdr_ext = hdr_ext;
if isfield(hdr_ext, 'SequenceName')
    out.seq = hdr_ext.SequenceName;
end

%FILLING IN THE FLAGS
out.flags.writtentostruct=1;
out.flags.gotparams=1;
out.flags.leftshifted=0;
out.flags.filtered=0;
out.flags.zeropadded=0;
out.flags.freqcorrected=0;
out.flags.phasecorrected=0;
if out.dims.averages==0
    out.flags.averaged=1;
else
    out.flags.averaged=0;
end
if out.dims.coils==0
    out.flags.addedrcvrs=1;
else
    out.flags.addedrcvrs=0;
end
out.flags.subtracted=0;
out.flags.writtentotext=0;
out.flags.downsampled=0;
if out.dims.subSpecs==0
    out.flags.isFourSteps=0;
else
    out.flags.isFourSteps=(out.sz(out.dims.subSpecs)==4);
end

end


function writePOLY_tetgen(filename,V,F,H,varargin)
  % WRITEPOLY_TETGEN prints vertices and planar facets to a .poly file for
  % tetgen
  %
  % writePOLY_tetgen(filename,V,F,H)
  %
  % Input
  %   filename:  name of output file as string (caution! will clobber
  %                    existing)
  %   V  #V by dim list of vertex positions
  %   F  #F struct containing polygon information arrays
  %     .facets  a #facets list of facets, each facet is a again a list of
  %       polygons
  %      ** Note: contrary to writePOLY_pyramid, here facets index V directly
  %     .boundary_markers a #facets list of boundary_markers
  %     .holes  a #facets list of holes, each holes entry is again a list for
  %       each facet
  %    or
  %   F  #F by uniform_facet_size list of facets into V
  %   H  #H by dim list of volume hole positions
  %   Optional:
  %     'BoundaryMarkers' followed by #facets list of boundary markers
  %     'BoundaryMarkersNodes' followed by #facets list of boundary markers
  %     'RegionList' followed by #regions list of region vertex positions and (optional) region numbers and attributes
  %
  % Example:
  %   % constrained Delaunay tetrahedralization of a triangle mesh
  %   [V,F] = load_mesh('gargoyle.obj');
  %   % constrained Delaunay tetrahedralization of just points
  %   D = DelaunayTri(V);
  %   % Faces on boundary of convex hull
  %   BF = boundary_faces(D.Triangulation);
  %   % avoid dupicate faces
  %   FmBF = setdiff(sort(F,2),sort(BF,2),'rows');
  %   Facets = [];
  %   Facets.facets = mat2cell([BF;FmBF],ones(size(BF,1)+size(FmBF,1),1),[3]);
  %   Facets.boundary_marker = [ones(size(BF,1),1);-ones(size(FmBF,1),1)];
  %   Facets.holes = cell(numel(Facets.facets),1);
  %   writePOLY_tetgen('temp.poly',V,Facets,[]);
  %   % -p: we're giving PLC, -g: output .mesh, -Y: no steiners
  %   !/usr/local/bin/tetgen -pgY ~/Documents/volume/temp.poly
  %   [VV,TT,FF] = readMESH('temp.1.mesh');
  %
  % Copyright 2011, Alec Jacobson (jacobson@inf.ethz.ch)
  %
  % See also: cdt, tetgen, writePOLY_triangle, writePOLY_pyramid
  %

  v = 1;
  BM = [];
  BMN = [];
  RL = [];
  while v <= numel(varargin)
    switch varargin{v}
    case 'BoundaryMarkers'
      assert((v+1)<=numel(varargin));
      v = v+1;
      BM = varargin{v};
    case 'BoundaryMarkersNodes'
      assert((v+1)<=numel(varargin));
      v = v+1;
      BMN = varargin{v};
    case 'RegionList'
      assert((v+1)<=numel(varargin));
      v = v+1;
      RL = varargin{v};
    otherwise
      error(['Unsupported parameter: ' varargin{v}]);
    end
    v=v+1;
  end

  % open file for writing
  poly_file_handle = fopen(filename,'w');

  % dimensions in V, should be 3
  dim = size(V,2);
  if isempty(V)
    dim = 3;
  end

  if dim ~= 3
    error('writePOLY_tetgen is for 3d meshes. Try writePOLY_triangle etc.');
  end

  % vertices section
  fprintf(poly_file_handle,'# vertices\n');
  fprintf(poly_file_handle,'# Part 1 - node list\n');
  fprintf(poly_file_handle,'%d %d 0 %d\n', size(V,1),size(V,2),~isempty(BMN));
  format = '%d %.17g %.17g %.17g\n';
  if ~isempty(V)
      if ~isempty(BMN)
          assert(numel(BMN)==size(V,1));
          formatV = '%d %.17g %.17g %.17g %d\n';
          fprintf(poly_file_handle,formatV,[1:size(V,1);V';BMN']);
      else
          formatV=format;
          fprintf(poly_file_handle,formatV,[1:size(V,1);V']);

      end
  end

  fprintf(poly_file_handle,'# Part 2 - facet list\n');
  % Try to print all at once if facets are all the same size
  if ~isstruct(F)
    fprintf(poly_file_handle,'%d %d\n',size(F,1),~isempty(BM));
    assert(numel(BM)==size(F,1) || isempty(BM));
    % build format
    fformat = '1 0';
    if ~isempty(BM)
      fformat = [fformat ' %d'];
    end
    fformat = [fformat '\n' num2str(size(F,2))];
    for p=1:size(F,2)
      fformat = [fformat ' %d']; %#ok<AGROW>
    end
    fformat = [fformat '\n'];
    % print all at once
    fprintf(poly_file_handle,fformat,[BM F]');
  else
    fprintf(poly_file_handle,'%d %d\n',numel(F.facets),1);
    % irregular face valences
    for f=1:numel(F.facets)
      % [num polygons] [num holes] [boundary marker]
      fprintf(poly_file_handle,'%d %d %d\n', ...
        numel(F.facets{f}),size(F.holes{f},1),F.boundary_marker(f));
      % loop over polygons
      for p=1:numel(F.facets{f})
        % [num corners] [corner 1] [corner 2] ...
        fprintf(poly_file_handle,' %d',numel(F.facets{f}{p}));
        fprintf(poly_file_handle,' %d',F.facets{f}{p});
        fprintf(poly_file_handle,'\n');
      end
      % [hole #] [hole x] [hole y] [hole z]
      if ~isempty(F.holes{f})
        assert(size(F.holes{f},2) == size(V,2));
        fprintf(poly_file_handle,format,[1:size(F.holes{f},1);F.holes{f}']);
      end
    end
  end

  % [num holes]
  fprintf(poly_file_handle,'# Part 3 - hole list\n');
  fprintf(poly_file_handle,'%d\n',size(H,1));
  if ~isempty(H)
    assert(isempty(V) || size(H,2) == size(V,2));
    fprintf(poly_file_handle,format,[1:size(H,1);H']);
  end
  % [num regions]
  fprintf(poly_file_handle,'# Part 4 - region list\n');
  fprintf(poly_file_handle,'%d\n',size(RL,1));
  if ~isempty(RL)
    % [region #] [region x] [region y] [region z] [region attribute] and/or [region number]
    formatRL = ['%d' repmat(' %.17g',1,size(RL,2)) '\n'];
    fprintf(poly_file_handle,formatRL,[1:size(RL,1);RL']);
  end
  fprintf(poly_file_handle,'\n');
  fclose(poly_file_handle);
end


function g = kernDiagGradient(kern, x, covDiag)

% KERNDIAGGRADIENT Compute the gradient of the kernel's parameters for the diagonal.
% FORMAT
% DESC computes the gradient of functions of the diagonal of the
% kernel matrix with respect to the parameters of the kernel. The
% parameters' gradients are returned in the order given by the
% kernExtractParam command.
% ARG kern : the kernel structure for which the gradients are computed.
% ARG x : the input data for which the gradient is being computed.
% ARG factors : partial derivatives of the function of interest
% with respect to the diagonal elements of the kernel matrix.
% RETURN g : gradients of the relevant function with respect to each of the parameters. Ordering should match the ordering given in kernExtractParam.
%
% SEEALSO : kernDiagGradient, kernExtractParam, kernGradient

% KERN

fileName = [kern.type 'KernDiagGradient'];
if exist(fileName) == 2
  fhandle = str2func(fileName);
  g = fhandle(kern, x, covDiag);
else
  fhandle = str2func([kern.type 'KernGradient']);
  g = zeros(1, kern.nParams);
  for i = 1:size(x, 1)
    g = g ...
        + fhandle(kern, x(i, :), covDiag(i));
  end
end
% Check if parameters are being optimised in a transformed space.
factors = kernFactors(kern, 'gradfact');
g(factors.index) = g(factors.index).*factors.val;


Eat = [E.Longitude.*111, E.Latitude.*111, E.Depth];
Eatlon = newt2.Longitude.*111;
Eatran = ran(:,1).*111;
Eattim = newt2.Date;
incr = a.Date;
eat = [((Eat(:,1).^2 + Eat(:,2).^2 + Eat(:,3)).^0.5)];
%
%
%
p = min(a.Date);

tim2 = [];
tim3 = [];

tim1 = [];
tic;
for p = min(a.Date):0.0000011:max(a.Date)

    match1 = find(a.Date< (p + 0.0000005) & a.Date> (p - 0.0000005));
    tim1 = [tim1; match1];

end
toc;

time = a(tim1,3);
Eatlon = [a(tim1,:)]; %[a(tim,1), a(tim,2), a(tim,7)];

for p = min(a.Date):0.001+0.01:max(a.Date)
    match2 = find(a.Date< (p + 0.0001) & a.Date> (p - 0.0001));
    tim2 = [tim2; match2];
end
Eat2 = [eat(tim2)];

for p = min(a.Date):0.001+0.02:max(a.Date)
    match3 = find(a.Date< (p + 0.0001) & a.Date> (p - 0.0001));
    tim3 = [tim3; match3];
end
Eat3 = [eat(tim3)];

Eat = [Eat1 Eat2 Eat3];

for m = 0:6

    time1(1:3202,(m+1)) = (decyear(E.Date)+ 0.005*m);
    %Eat(1:3202,(m)) = [Eat(:,1) eat(:,2)+0.005*m;
end

ea = find(decyear(E.Date)>min(decyear(E.Date))+0.05*4);
E = E(ea,:);

%
%
%

m = 1:5:2435; %size(pairdist,1);
figure;
%plot3(eat (m-2), eat(m-1,:), eat(m,:), 'k.', 'Markersize', 0.5);
%plot3(a((m+40),3), a(m+20,3), a(m,3), 'k.', 'Markersize', 0.5);
u = plot3(eat(m),eat(m+10),eat(m+20));%,'k.');
clear m;
%
%
%

k = 1:798;
u = [eat(k),eat(k+0.75),eat(k+1.5)];%,eat(k+2.25),eat(k+3),eat(k+3.75)];
figure;
%plot3(u(:,1),u(:,2), u(:,3), 'k.', 'Markersize', 0.5);%u(m-2,:)
xlabel('kt');
ylabel('kt+T');
zlabel('kt+2T');

k = 1:10:3012245;
figure;
plot3(pairdist(k),pairdist(k+20), pairdist(k+40));%,'k.', 'Markersize', 0.5);

%plot(E(n-1,1), E(n,1),'k.', 'Markersize', 0.5);
%plot(E(n-1,2), E(n,2),'k.', 'Markersize', 0.5);
%plot(E(n-1,7), E(n,7),'k.', 'Markersize', 0.5);

k = 1:1:3193;
E = [Eatlon(k),Eatlon(k+2),Eatlon(k+3), Eatlon(4), Eatlon(k+5), Eatlon(6), Eatlon(k+7), Eatlon(k+8)];

mEatlon = sum(Eatlon,1)/3202;
Eatlon = Eatlon-mEatlon;
HSig = figure;
plot(Eattim, Eatlon);
axis([2500 3000 -10 -15]);

[ps,freq] = spectrum(Eatlon,256,0,[],0.0634);
Hpws = figure;
plot(freq,ps(:,1));
axis([0 0.01 0 30]);
spectrum(Eatlon);


% std_plotcurve() - plot ERP or spectral traces for a STUDY component
%                   or channel cluster
% Usage:
%          >> std_plotcurve( axvals, data, 'key', 'val', ...)
% Inputs:
%  axvals - [vector or cell array] axis values for the data.
%  data  -  [cell array] mean data for each subject group and/or data
%           condition. For example, to plot mean ERPs from a STUDY
%           for epochs of 800 frames in two conditions from three groups
%           of 12 subjects:
%
%           >> data = { [800x12] [800x12] [800x12];... % 3 groups, cond 1
%                       [800x12] [800x12] [800x12] };  % 3 groups, cond 2
%           >> std_plotcurve(erp_ms,data);
%
%           By default, parametric statistics are computed across subjects
%           in the three groups. (group,condition) ERP averages are plotted.
%           See below and >> help statcond
%           for more information about the statistical computations.
%
% Optional display parameters:
%  'datatype'    - ['erp'|'spec'] data type {default: 'erp'}
%  'titles'      - [cell array of string] titles for each of the subplots.
%                  { default: none}
%
% Statistics options:
%  'groupstats'  - [cell] One p-value array per group {default: {}}
%  'condstats'   - [cell] One p-value array per condition {default: {}}
%  'interstats'  - [cell] Interaction p-value arrays {default: {}}
%  'threshold'   - [NaN|real<<1] Significance threshold. NaN -> plot the
%                  p-values themselves on a different figure. When possible,
%                  significance regions are indicated below the data.
%                  {default: NaN}
%
% Curve plotting options (ERP and spectrum):
%  'plotgroups'  - ['together'|'apart'] 'together' -> plot mean results
%                  for subject groups in the same figure panel in different
%                  colors. 'apart' -> plot group results on different figure
%                  panels {default: 'apart'}
%  'plotconditions' - ['together'|'apart'] 'together' -> plot mean results
%                  for data conditions on the same figure panel in
%                  different
%                  colors. 'apart' -> plot conditions on different figure
%                  panel. Note: 'plotgroups' and 'plotconditions' arguments
%                  cannot both be 'together' {default: 'apart'}
%  'legend'      - ['on'|'off'] turn plot legend on/off {default: 'off'}
%  'plotdiff'    - ['on'|'off'] plot difference between two groups
%                  or conditions plotted together.
%  'plotstderr'  - ['on'|'off'|'diff'|'nocurve'|'diffnocurve'] plots in
%                  a surface indicating the standard error. 'diff' only
%                  does it for the difference (requires 'plotdiff' 'on'
%                  above). 'nocurve' does not plot the mean. This functionality
%                  does not work for all data configuration {default: 'off'}
%  'figure'      - ['on'|'off'] creates a new figure ('on'). The 'off' mode
%                  plots all of the groups and conditions on the same pannel.
% 'plotsubjects' - ['on'|'off'] overplot traces for individual components
%                  or channels {default: 'off'}
% 'singlesubject' - ['on'|'off'] set to 'on' to plot single subject.
%                  {default: 'off'}
% 'ylim'         - [min max] ordinate limits for ERP and spectrum plots
%                  {default: all available data}
%
% Scalp map plotting options:
%  'chanlocs'    - [struct] channel locations structure
%
% Author: Arnaud Delorme, CERCO, CNRS, 2006-
%
% See also: pop_erspparams(), pop_erpparams(), pop_specparams(), statcond()

function std_plotcurve(allx, data, varargin)

pgroup = [];
pcond  = [];
pinter = [];
if nargin < 2
    help std_plotcurve;
    return;
end;

opt = finputcheck( varargin, { 'ylim'          'real'   []              [];
                               'filter'        'real'   []              [];
                               'threshold'     'real'   []              NaN;
                               'unitx'         'string' []              'ms';
                               'chanlocs'      'struct' []              struct('labels', {});
                               'plotsubjects'  'string' { 'on' 'off' }  'off';
                               'condnames'     'cell'   []              {}; % just for legends
                               'groupnames'    'cell'   []              {}; % just for legends
                               'groupstats'    'cell'   []              {};
                               'condstats'     'cell'   []              {};
                               'interstats'    'cell'   []              {};
                               'titles'        'cell'   []              {};
                               'figure'        'string' { 'on' 'off' }   'on';
                               'plottopo'      'string' { 'on' 'off' }   'off';
                               'plotstderr'    'string' { 'on' 'off' 'diff' 'nocurve' }   'off';
                               'plotdiff'      'string' { 'on' 'off' }   'off';
                               'legend'        { 'string' 'cell' } { { 'on' 'off' } {} }  'off';
                               'datatype'      'string' { 'ersp' 'itc' 'erp' 'spec' }    'erp';
                               'plotgroups'    'string' { 'together' 'apart' }  'apart';
                               'plotmode'      'string' { 'test' 'condensed' }  'test'; % deprecated
                               'plotconditions'    'string' { 'together' 'apart' }  'apart' }, 'std_plotcurve');

% opt.figure =  'off'; % test by nima
if isstr(opt), error(opt); end;
opt.singlesubject = 'off';
if strcmpi(opt.plottopo, 'on') && size(data{1},3) == 1, opt.singlesubject = 'on'; end;
%if size(data{1},2) == 1,                              opt.singlesubject = 'on'; end;
if all(all(cellfun('size', data, 2)==1))               opt.singlesubject = 'on'; end;
if any(any(cellfun('size', data, 2)==1)), opt.groupstats = {}; opt.condstats = {}; end;
if strcmpi(opt.datatype, 'spec'), opt.unit = 'Hz'; end;
if strcmpi(opt.plotsubjects, 'on')
    opt.plotgroups      = 'apart';
    opt.plotconditions  = 'apart';
end;
if strcmpi(opt.plotconditions, 'together') &&  ~isempty(opt.groupstats), opt.plotconditions = 'apart'; end;
if strcmpi(opt.plotgroups,     'together') &&  ~isempty(opt.condstats) , opt.plotgroups     = 'apart'; end;
if isstr(opt.legend), opt.legend = {}; end;
if isempty(opt.titles), opt.titles = cell(10,10); opt.titles(:) = { '' }; end;
if length(data(:)) == length(opt.legend(:)),
    opt.legend = reshape(opt.legend, size(data))';
    opt.legend(cellfun(@isempty, data)) = [];
    opt.legend = (opt.legend)';
end;

% plot
% ----
% if strcmpi(opt.figure, 'on'),
% else
%     % all groups and conditions in the same figureopt.chanlocs
%     ncol = size(tmpdata,3);
%     if ncol == 1, ncol = size(tmpdata,1); end;
%     tmpcol = col(colcount:colcount+ncol-1);
%     colcount = mod(colcount+ncol-1, length(col))+1;
%     %if strcmpi(opt.plotgroups, 'together') && isempty(tmpdata{1})
%
% end;
%

% color matrix
% -----------------------
onecol  = { 'b' 'b' 'b' 'b' 'b' 'b' 'b' 'b' 'b' 'b' };
manycol = { 'b' 'g' 'm' 'c' 'r' 'b' 'g' 'c' 'm' 'r' 'b' 'g' 'c' 'm' 'r' 'b' ...
                   'g' 'c' 'm' 'r' 'b' 'g' 'c' 'm' 'r' 'b' 'g' 'c' 'm' 'r' 'b' 'g' 'c' 'm' };
if strcmpi(opt.plotgroups, 'together') || strcmpi(opt.plotconditions, 'together') || strcmpi(opt.figure, 'off')
     col = manycol;
else col = onecol;
end;
nonemptycell = find(~cellfun(@isempty, data));
maxdim = max(length(data(:)), size(data{nonemptycell(1)}, ndims(data{nonemptycell(1)})));
tmpcol = col;
if strcmpi(opt.plotsubjects, 'off')
    coldata = col(mod([0:maxdim-1], length(col))+1);
    coldata = reshape(coldata(1:length(data(:))), size(data));
else
    coldata = cell(size(data));
end;

% remove empty entries
% --------------------
datapresent = ~cellfun(@isempty, data);
if size(data,1) > 1, for c = size(data,1):-1:1, if sum(datapresent(c,:)) == 0, data(c,:) = []; coldata(c,:) = []; if ~strcmpi(opt.plotconditions, 'together') opt.titles(c,:) = []; end; if ~isempty(opt.groupstats), opt.groupstats(c) = []; end; end; end; end;
if size(data,2) > 1, for g = size(data,2):-1:1, if sum(datapresent(:,g)) == 0, data(:,g) = []; coldata(:,g) = []; if ~strcmpi(opt.plotgroups    , 'together') opt.titles(:,g) = []; end; if ~isempty(opt.condstats ), opt.condstats( g) = []; end; end; end; end;
if strcmpi(opt.plotsubjects, 'off'), tmpcol = coldata'; tmpcol = tmpcol(:)'; end;

% number of columns and rows to plot
% ----------------------------------
nc = size(data,1);
ng = size(data,2);
if strcmpi(opt.plotgroups, 'together'),      ngplot = 1; else ngplot = ng; end;
if strcmpi(opt.plotconditions,  'together'), ncplot = 1; else ncplot = nc; end;
if nc >= ng, opt.subplot = 'transpose';
else         opt.subplot = 'normal';
end;
if isempty(opt.condnames)
    for c=1:nc, opt.condnames{c} = sprintf('Cond. %d', c); end;
    if nc == 1, opt.condnames = { '' }; end;
end;
if isempty(opt.groupnames)
    for g=1:ng, opt.groupnames{g} = sprintf('Group. %d', g); end;
    if ng == 1, opt.groupnames = { '' }; end;
end;

% plotting paramters
% ------------------
if ng > 1 && ~isempty(opt.groupstats), addc = 1; else addc = 0; end;
if nc > 1 && ~isempty(opt.condstats ), addr = 1; else addr = 0; end;
if strcmpi(opt.singlesubject, 'off') ...
        && ( ~isempty(opt.condstats) || ~isempty(opt.groupstats) ) % only for curves
    plottag = 0;
    if strcmpi(opt.plotgroups, 'together') && isempty(opt.condstats) && ~isempty(opt.groupstats) && ~isnan(opt.threshold), addc = 0; plottag = 1; end;
    if strcmpi(opt.plotconditions , 'together') && ~isempty(opt.condstats) && isempty(opt.groupstats) && ~isnan(opt.threshold), addr = 0; plottag = 1; end;
    if ~isnan(opt.threshold) && plottag == 0 && strcmpi(opt.figure, 'on')
        disp('Warning: cannot plot condition/group on the same panel while using a fixed');
        disp('         threshold, unless you only compute statistics for ether groups or conditions');
        opt.plotgroups = 'apart';
        opt.plotconditions  = 'apart';
    end;
end;

% compute significance mask
% --------------------------
if ~isempty(opt.interstats), pinter = opt.interstats{3}; end;

if ~isnan(opt.threshold) && ( ~isempty(opt.groupstats) || ~isempty(opt.condstats) )
    pcondplot  = opt.condstats;
    pgroupplot = opt.groupstats;
    pinterplot = pinter;
    maxplot = 1;
else
    warning off;
    for ind = 1:length(opt.condstats),  pcondplot{ind}  = -log10(opt.condstats{ind}); end;
    for ind = 1:length(opt.groupstats), pgroupplot{ind} = -log10(opt.groupstats{ind}); end;
    if ~isempty(pinter), pinterplot = -log10(pinter); end;
    maxplot = 3;
    warning on;
end;

% labels
% ------
if strcmpi(opt.unitx, 'ms'), xlab = 'Time (ms)';      ylab = 'Potential (\muV)';
else                         xlab = 'Frequency (Hz)'; ylab = 'Power (10*log_{10}(\muV^{2}/Hz))';
end;
if ~isnan(opt.threshold), statopt = {  'xlabel' xlab };
else                      statopt = { 'logpval' 'on' 'xlabel' xlab 'ylabel' '-log10(p)' 'ylim' [0 maxplot] };
end;

% adjust figure size
% ------------------
if strcmpi(opt.figure, 'on')
    figure('color', 'w');
    pos = get(gcf, 'position');
    basewinsize = 200/max(nc,ng)*3;
    if strcmpi(opt.plotgroups, 'together') pos(3) = 200*(1+addc);
    else                                   pos(3) = 200*(ng+addc);
    end;
    if strcmpi(opt.plotconditions , 'together') pos(4) = 200*(1+addr);
    else                                        pos(4) = 200*(nc+addr);
    end;
    if strcmpi(opt.subplot, 'transpose'), set(gcf, 'position', [ pos(1) pos(2) pos(4) pos(3)]);
    else                                  set(gcf, 'position', pos);
    end;
else
    opt.subplot = 'noplot';
end;

tmplim = [Inf -Inf];
colcount = 1; % only when plotting all conditions on the same figure
for c = 1:ncplot
    for g = 1:ngplot
        if strcmpi(opt.plotgroups, 'together'),         hdl(c,g)=mysubplot(ncplot+addr, ngplot+addc, 1 + (c-1)*(ngplot+addc), opt.subplot); ci = g;
        elseif strcmpi(opt.plotconditions, 'together'), hdl(c,g)=mysubplot(ncplot+addr, ngplot+addc, g, opt.subplot); ci = c;
        else                                            hdl(c,g)=mysubplot(ncplot+addr, ngplot+addc, g + (c-1)*(ngplot+addc), opt.subplot); ci = 1;
        end;

        if ~isempty(data{c,g})

            % read all data from one condition or group
            % -----------------------------------------
            dimreduced_sizediffers = 0;
            if ncplot ~= nc && ngplot ~= ng
                maxdim = max(max(cellfun(@(x)(size(x, ndims(x))), data)));
                for cc = 1:size(data,1)
                    for gg = 1:size(data,2)
                        tmptmpdata = real(data{cc,gg});
                        if ndims(tmptmpdata) == 3,
                            if cc == 1 && gg == 1, tmpdata = NaN*zeros([size(tmptmpdata,1) size(tmptmpdata,2) maxdim length(data(:))]); end;
                            tmpdata(:,:,1:size(tmptmpdata,3),gg+((cc-1)*ng)) = tmptmpdata;
                        else
                            if cc == 1 && gg == 1, tmpdata = NaN*zeros([size(tmptmpdata,1) maxdim length(data(:))]); end;
                            tmpdata(:,1:size(tmptmpdata,2),gg+((cc-1)*ng))   = tmptmpdata;
                        end;
                    end;
                end;
            elseif ncplot ~= nc % plot conditions together
                for ind = 2:size(data,1), if any(size(data{ind,1}) ~= size(data{1})), dimreduced_sizediffers = 1; end; end;
                for cc = 1:nc
                    tmptmpdata = real(data{cc,g});
                    if dimreduced_sizediffers
                        tmptmpdata = nan_mean(tmptmpdata,ndims(tmptmpdata));
                    end;
                    if cc == 1, tmpdata = zeros([size(tmptmpdata) nc]); end;
                    if ndims(tmptmpdata) == 3, tmpdata(:,:,:,cc) = tmptmpdata;
                    else                       tmpdata(:,:,cc)   = tmptmpdata;
                    end;
                end;
            elseif ngplot ~= ng % plot groups together
                for ind = 2:size(data,2), if any(size(data{1,ind}) ~= size(data{1})), dimreduced_sizediffers = 1; end; end;
                for gg = 1:ng
                    tmptmpdata = real(data{c,gg});
                    if dimreduced_sizediffers
                        tmptmpdata = nan_mean(tmptmpdata,ndims(tmptmpdata));
                    end;
                    if gg == 1, tmpdata = zeros([size(tmptmpdata) nc]); end;
                    if ndims(tmptmpdata) == 3, tmpdata(:,:,:,gg) = tmptmpdata;
                    else                       tmpdata(:,:,gg)   = tmptmpdata;
                    end;
                end;
            else tmpdata = real(data{c,g});
                % nothing
            end;

            % plot difference
            % ---------------
            if ~strcmpi(opt.plotdiff, 'off')
                if ngplot ~= ng || ncplot ~= nc
                    if size(tmpdata,3) == 2
                        tmpdata(:,:,end+1) = tmpdata(:,:,2)-tmpdata(:,:,1);
                        opt.legend{end+1} = [ opt.legend{2} '-' opt.legend{1} ];
                    elseif size(tmpdata,4) == 2
                        tmpdata(:,:,:,end+1) = tmpdata(:,:,:,2)-tmpdata(:,:,:,1);
                        opt.legend{end+1} = [ opt.legend{2} '-' opt.legend{1} ];
                    else
                        disp('Cannot plot difference, more than 2 indep. variable values');
                    end;
                else
                    disp('Cannot plot difference, indep. variable value must be plotted together');
                end;
            end;

            if ~isempty(opt.filter), tmpdata = myfilt(tmpdata, 1000/(allx(2)-allx(1)), 0, opt.filter); end;

            % plotting options
            % ----------------
            plotopt = { allx };
            if ~dimreduced_sizediffers
                if strcmpi(opt.plottopo, 'on'),
                    if strcmpi(opt.plotsubjects, 'off') tmpstd = squeeze(real(std(tmpdata,[],3)))/sqrt(size(tmpdata,3)); tmpstd = squeeze(permute(tmpstd, [2 1 3])); tmpdata = squeeze(real(nan_mean(tmpdata,3))); end;
                elseif strcmpi(opt.plotsubjects, 'off') tmpstd = squeeze(real(std(tmpdata,[],2)))/sqrt(size(tmpdata,2)); tmpstd = squeeze(permute(tmpstd, [2 1 3])); tmpdata = squeeze(real(nan_mean(tmpdata,2)));
                end;
            end;
            tmpdata = squeeze(permute(tmpdata, [2 1 3]));
            if strcmpi(opt.plottopo, 'on'), highlight = 'background'; else highlight = 'bottom'; end;
            if strcmpi(opt.plotgroups, 'together') &&  isempty(opt.condstats) && ...
                             ~isnan(opt.threshold) && ~isempty(opt.groupstats)
                plotopt = { plotopt{:} 'maskarray' };
                tmpdata = { tmpdata pgroupplot{c}' };
            elseif strcmpi(opt.plotconditions, 'together') &&  isempty(opt.groupstats) && ...
                                     ~isnan(opt.threshold) && ~isempty(opt.condstats)
                plotopt = { plotopt{:} 'maskarray' };
                tmpdata = { tmpdata pcondplot{g}' };
            end;
            plotopt = { plotopt{:} 'highlightmode', highlight };
            if strcmpi(opt.plotsubjects, 'on')
                plotopt = { plotopt{:} 'plotmean' 'on' 'plotindiv' 'on' };
            else
                plotopt = { plotopt{:} 'plotmean' 'off' };
            end;
            plotopt = { plotopt{:} 'ylim' opt.ylim 'xlabel' xlab 'ylabel' ylab };
            if ncplot ~= nc || ngplot ~= ng
                plotopt = { plotopt{:} 'legend' opt.legend };
            end;

%             % plot
%             % ----
%             if strcmpi(opt.figure, 'on'),
%                 tmpcol = col;
%             else
%                 % all groups and conditions in the same figureopt.chanlocs
%                 ncol = size(tmpdata,3);
%                 if ncol == 1, ncol = size(tmpdata,1); end;
%                 tmpcol = col(colcount:colcount+ncol-1);
%                 colcount = mod(colcount+ncol-1, length(col))+1;
%                 %if strcmpi(opt.plotgroups, 'together') && isempty(tmpdata{1})
%
%             end;
%
            if strcmpi(opt.plottopo, 'on') && length(opt.chanlocs) > 1
                metaplottopo(tmpdata, 'chanlocs', opt.chanlocs, 'plotfunc', 'plotcurve', ...
                    'plotargs', { plotopt{:} }, 'datapos', [2 3], 'title', opt.titles{c,g});
            elseif iscell(tmpdata)
                plotcurve( allx, tmpdata{1}, 'colors', tmpcol, 'maskarray', tmpdata{2}, plotopt{3:end}, 'title', opt.titles{c,g});
            else
                if isempty(findstr(opt.plotstderr, 'nocurve'))
                    plotcurve( allx, tmpdata, 'colors', tmpcol, plotopt{2:end}, 'title', opt.titles{c,g});
                end;
                if ~strcmpi(opt.plotstderr, 'off')
                    if ~dimreduced_sizediffers
                        if ~isempty(findstr(opt.plotstderr, 'diff')), begind = 3; else begind = 1; end;
                        set(gcf, 'renderer', 'OpenGL')
                        for tmpi = begind:size(tmpdata,1)
                            hold on; chandle = fillcurves( allx, tmpdata(tmpi,:)-tmpstd(tmpi,:), tmpdata(tmpi,:)+tmpstd(tmpi,:), tmpcol{tmpi}); hold on;
                            numfaces = size(get(chandle(1), 'Vertices'),1);
                            set(chandle(1), 'FaceVertexCData', repmat([1 1 1], [numfaces 1]), 'Cdatamapping', 'direct', 'facealpha', 0.3, 'edgecolor', 'none');
                        end;
                    else
                        disp('Some conditions have more subjects than others, cannot plot standard error');
                    end;
                end;
            end;
        end;

        if strcmpi(opt.plottopo, 'off'), % only non-topographic
            xlim([allx(1) allx(end)]); hold on;
            if isempty(opt.ylim)
                tmp = ylim;
                tmplim = [ min(tmplim(1), tmp(1)) max(tmplim(2), tmp(2)) ];
            else
                ylim(opt.ylim);
            end;
        end;

        % statistics accross groups
        % -------------------------
        if g == ngplot && ng > 1 && ~isempty(opt.groupstats)
            if ~strcmpi(opt.plotgroups, 'together') || ~isempty(opt.condstats) || isnan(opt.threshold)
                if strcmpi(opt.plotgroups, 'together'),         mysubplot(ncplot+addr, ngplot+addc, 2 + (c-1)*(ngplot+addc), opt.subplot); ci = g;
                elseif strcmpi(opt.plotconditions, 'together'), mysubplot(ncplot+addr, ngplot+addc, ngplot + 1, opt.subplot); ci = c;
                else                                            mysubplot(ncplot+addr, ngplot+addc, ngplot + 1 + (c-1)*(ngplot+addc), opt.subplot); ci = 1;
                end;
                if strcmpi(opt.plotconditions, 'together'), condnames = 'Conditions'; else condnames = opt.condnames{c}; end;
                if ~isnan(opt.threshold)
                     if strcmpi(opt.plottopo, 'on'),
                          metaplottopo({zeros(size(pgroupplot{c}')) pgroupplot{c}'}, 'chanlocs', opt.chanlocs, 'plotfunc', 'plotcurve', ...
                              'plotargs', { allx 'maskarray' statopt{:} }, 'datapos', [2 3], 'title', opt.titles{c, g+1});
                     else plotcurve(allx, zeros(size(allx)), 'maskarray', mean(pgroupplot{c},2), 'ylim', [0.1 1], 'title', opt.titles{c, g+1}, statopt{:});
                     end;
                else
                     if strcmpi(opt.plottopo, 'on'),
                          metaplottopo(pgroupplot{c}', 'chanlocs', opt.chanlocs, 'plotfunc', 'plotcurve', ...
                              'plotargs', { allx statopt{:} }, 'datapos', [2 3], 'title', opt.titles{c, g+1});
                     else plotcurve(allx, mean(pgroupplot{c},2), 'title', opt.titles{c, g+1}, statopt{:});
                     end;
                end;
            end;
        end;
    end;
end;

for g = 1:ng
    % statistics accross conditions
    % -----------------------------
    if ~isempty(opt.condstats) && nc > 1
        if ~strcmpi(opt.plotconditions, 'together') || ~isempty(opt.groupstats) || isnan(opt.threshold)
            if strcmpi(opt.plotgroups, 'together'),         mysubplot(ncplot+addr, ngplot+addc, 1 + c*(ngplot+addc), opt.subplot); ci = g;
            elseif strcmpi(opt.plotconditions, 'together'), mysubplot(ncplot+addr, ngplot+addc, g + ngplot+addc, opt.subplot); ci = c;
            else                                            mysubplot(ncplot+addr, ngplot+addc, g + c*(ngplot+addc), opt.subplot); ci = 1;
            end;
            if strcmpi(opt.plotgroups, 'together'), groupnames = 'Groups'; else groupnames = opt.groupnames{g}; end;
            if ~isnan(opt.threshold)
                 if strcmpi(opt.plottopo, 'on'),
                      metaplottopo({zeros(size(pcondplot{g}')) pcondplot{g}'}, 'chanlocs', opt.chanlocs, 'plotfunc', 'plotcurve', ...
                          'plotargs', { allx 'maskarray' statopt{:} }, 'datapos', [2 3], 'title', opt.titles{end, g});
                 else plotcurve(allx, zeros(size(allx)), 'maskarray', mean(pcondplot{g},2), 'ylim', [0.1 1], 'title', opt.titles{end, g}, statopt{:});
                 end;
            else
                 if strcmpi(opt.plottopo, 'on'),
                      metaplottopo(pcondplot{g}', 'chanlocs', opt.chanlocs, 'plotfunc', 'plotcurve', ...
                          'plotargs', { allx statopt{:} }, 'datapos', [2 3], 'title', opt.titles{end, g});
                 else plotcurve(allx, mean(pcondplot{g},2), 'title',  opt.titles{end, g}, statopt{:});
                 end;
            end;
        end;
    end;
end;

% statistics accross group and conditions
% ---------------------------------------
if ~isempty(opt.groupstats) && ~isempty(opt.condstats) && ng > 1 && nc > 1
    mysubplot(ncplot+addr, ngplot+addc, ngplot + 1 + ncplot*(ngplot+addr), opt.subplot);
    if ~isnan(opt.threshold)
         if strcmpi(opt.plottopo, 'on'),
              metaplottopo({zeros(size(pinterplot')) pinterplot'}, 'chanlocs', opt.chanlocs, 'plotfunc', 'plotcurve', ...
                  'plotargs', { allx 'maskarray' statopt{:} }, 'datapos', [2 3], 'title', opt.titles{end, end});
         else plotcurve(allx, zeros(size(allx)), 'maskarray', mean(pinterplot,2), 'ylim', [0.1 1], 'title', opt.titles{end, end}, statopt{:});
              xlabel(xlab); ylabel('-log10(p)');
        end;
    else
         if strcmpi(opt.plottopo, 'on'),
              metaplottopo(pinterplot', 'chanlocs', opt.chanlocs, 'plotfunc', 'plotcurve', ...
                  'plotargs', { allx statopt{:} }, 'datapos', [2 3], 'title', opt.titles{end, end});
         else plotcurve(allx, mean(pinterplot,2), 'title', opt.titles{end, end}, statopt{:});
         end;
    end;
end;

% axis limit
% ----------
for c = 1:ncplot
    for g = 1:ngplot
        if isempty(opt.ylim) && strcmpi(opt.plottopo, 'off')
            set(hdl(c,g), 'ylim', tmplim);
        end;
    end;
end;

if strcmpi(opt.plottopo, 'off') && length(hdl(:)) > 1
    axcopy;
    % remove axis labels (for most but not all)
    % ------------------
    if strcmpi(opt.subplot, 'transpose')
        for c = 1:size(hdl,2)
            for g = 1:size(hdl,1)
                axes(hdl(g,c));
                if c ~= 1 && size(hdl,2) ~=1, xlabel(''); legend off; end;
                if g ~= 1 && size(hdl,1) ~= 1, ylabel(''); legend off; end;
            end;
        end;
    else
        for c = 1:size(hdl,1)
            for g = 1:size(hdl,2)
                axes(hdl(c,g));
                if g ~= 1 && size(hdl,2) ~=1, ylabel(''); legend off; end;
                if c ~= size(hdl,1) && size(hdl,1) ~= 1, xlabel(''); legend off; end;
            end;
        end;
    end;
end;

% mysubplot (allow to transpose if necessary)
% -------------------------------------------
function hdl = mysubplot(nr,nc,ind,subplottype);

    r = ceil(ind/nc);
    c = ind -(r-1)*nc;
    if strcmpi(subplottype, 'transpose'),  hdl = subplot(nc,nr,(c-1)*nr+r);
    elseif strcmpi(subplottype, 'normal'), hdl = subplot(nr,nc,(r-1)*nc+c);
    elseif strcmpi(subplottype, 'noplot'), hdl = gca;
    else error('Unknown subplot type');
    end;

% rapid filtering for ERP
% -----------------------
function tmpdata2 = myfilt(tmpdata, srate, lowpass, highpass)

    tmpdata2 = reshape(tmpdata, size(tmpdata,1), size(tmpdata,2)*size(tmpdata,3)*size(tmpdata,4));
    tmpdata2 = eegfiltfft(tmpdata2',srate, lowpass, highpass)';
    tmpdata2 = reshape(tmpdata2, size(tmpdata,1), size(tmpdata,2), size(tmpdata,3), size(tmpdata,4));


function chEOG=identify_eog_channels(fn,x);
% IDENTIFY_EOG_CHANNELS returns bipolar EOG channels for
%  correcting of EOG artifacts using regression analysis
%
%  EOGchan = IDENTIFY_EOG_CHANNELS(...)
%
% EOGchan is a sparse matrix of size number_of_channels x 2.
% The sparsity ensures that missing samples of unrelated channels
% do not affect the data.
%
%  [...] = IDENTIFY_EOG_CHANNELS(filename)
%  [...] = IDENTIFY_EOG_CHANNELS(HDR)
%	filename or HDR struct can be used
%  [...] = IDENTIFY_EOG_CHANNELS(...,'x')
%     looks for EOG channels whos Label start with x
%
% see also: GET_REGRESS_EOG, SLOAD
%
% Reference(s):
% [1] Schlogl A, Keinrath C, Zimmermann D, Scherer R, Leeb R, Pfurtscheller G.
%	A fully automated correction method of EOG artifacts in EEG recordings.
%	Clin Neurophysiol. 2007 Jan;118(1):98-104. Epub 2006 Nov 7.
% 	http://dx.doi.org/10.1016/j.clinph.2006.09.003
%       http://pub.ist.ac.at/~schloegl/publications/schloegl2007eog.pdf

%	$Id: identify_eog_channels.m 2649 2011-03-09 09:52:44Z schloegl $
%	Copyright (C) 2006,2007,2009,2010 by Alois Schloegl
%    	This is part of the BIOSIG-toolbox http://biosig.sf.net/

% Biosig is free software; you can redistribute it and/or
% modify it under the terms of the GNU Library General Public
% License as published by the Free Software Foundation; either
% Version 3 of the License, or (at your option) any later version.
%
% This library 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
% Library General Public License for more details.
%
% You should have received a copy of the GNU Library General Public
% License along with this library; if not, write to the
% Free Software Foundation, Inc., 59 Temple Place - Suite 330,
% Boston, MA  02111-1307, USA.

if ischar(fn),
	HDR=sopen(fn);
	HDR=sclose(HDR);
elseif isstruct(fn)
	HDR=fn;
end;

% graz
g1 = strmatch('EOG-left',HDR.Label);
g2 = strmatch('EOG-central',HDR.Label);
g3 = strmatch('EOG-right',HDR.Label);
if isempty([g1,g2,g3])
	g1 = strmatch('EOG:ch01',HDR.Label);
	g2 = strmatch('EOG:ch02',HDR.Label);
	g3 = strmatch('EOG:ch03',HDR.Label);
end;

% berlin
if nargin<2,
	v1 = strmatch('eogv1',lower(HDR.Label));
	v2 = strmatch('eogv2',lower(HDR.Label));
	v0 = strmatch('eogv',lower(HDR.Label));
	v3 = strmatch('eogvp',lower(HDR.Label));
	v4 = strmatch('eogvn',lower(HDR.Label));

	h1 = strmatch('eogh1',lower(HDR.Label));
	h2 = strmatch('eogh2',lower(HDR.Label));
	h0 = strmatch('eogh' ,lower(HDR.Label));
	h3 = strmatch('eoghp',lower(HDR.Label));
	h4 = strmatch('eoghn',lower(HDR.Label));
else
	v1 = [];
	v2 = [];
	v0 = [];
	v3 = strmatch('xeogvp',lower(HDR.Label));
	v4 = strmatch('xeogvn',lower(HDR.Label));

	h1 = [];
	h2 = [];
	h0 = [];
	h3 = strmatch('xeoghp',lower(HDR.Label));
	h4 = strmatch('xeoghn',lower(HDR.Label));
end;

g = [g1;g2;g3];
v = [v1,v2,v3,v4];
if isempty(v), v=v0; end;
h = [h1,h2,h3,h4];
if isempty(h), h=h0; end;
if length(g)==3,
	chEOG = sparse([g1,g2,g2,g3],[1,1,2,2],[1,-1,1,-1],HDR.NS,2);
elseif length(g)==2,
	chEOG = sparse([g1,g2,g3],[1,1],[1,-1],HDR.NS,1);
else
	c = (length(v)>0);
	sz2 = (length(v)>0) + (length(h)>0);
	if length(v)==1,
		chEOG = sparse(v,c,1,HDR.NS,sz2);
	elseif length(v)==2,
		chEOG = sparse(v,[c,c],[1,-1],HDR.NS,sz2);
	else
		chEOG = 0;
	end;
	if length(h)==1,
		chEOG = chEOG+sparse(h,1+c,1,HDR.NS,1+c);
	elseif length(h)==2,
		chEOG = chEOG+sparse(h,[1,1]+c,[1,-1],HDR.NS,1+c);
	end;
end;

if size(chEOG,2)<2,
	warning('EOG channels are missing, or were not recognized');
end;


function u = pend_control(x)

load('pend_data', 'K', 'U', 'domain');

p = [x(2) x(4)];
u = tpcontroller(p, x, K, U, domain);


%% subfunction: split nii components into multiple nii
function nii = split_components(nii, s)
fld = 'ComplexImageComponent';
if ~strcmp(tryGetField(s, fld, ''), 'MIXED'), return; end

if ~isfield(s, 'Volumes') % PAR file and single-frame file have this
    nSL = nii.hdr.dim(4); nVol = nii.hdr.dim(5);
    iFrames = 1:nSL:nSL*nVol;
    if isfield(s, 'SortFrames'), iFrames = s.SortFrames(iFrames); end
    s1 = struct(fld, {cell(1, nVol)}, 'MRScaleSlope', nan(1,nVol), ...
            'RescaleSlope', nan(1,nVol), 'RescaleIntercept', nan(1,nVol));
    s.Volumes = dicm_hdr(s, s1, iFrames);
end
if ~isfield(s, 'Volumes'), return; end

% suppose scl not applied in set_nii_hdr, since MRScaleSlope is not integer
flds = {'EchoTimes' 'CardiacTriggerDelayTimes'}; % to split
s1 = s.Volumes;
nii0 = nii;
% [c, ia] = unique(s.Volumes.(fld), 'stable'); % since 2013a?
[~, ia] = unique(s1.(fld));
ia = sort(ia);
c = s1.(fld)(ia);
for i = 1:numel(c)
    nii(i) = nii0;
    ind = strcmp(c{i}, s1.(fld));
    nii(i).img = nii0.img(:,:,:,ind);
    slope = s1.RescaleSlope(ia(i)); if isnan(slope), slope = 1; end
    inter = s1.RescaleIntercept(ia(i)); if isnan(inter), inter = 0; end
    if ~isnan(s1.MRScaleSlope(ia(i)))
        inter = inter / (slope * s1.MRScaleSlope(ia(i)));
        slope = 1 / s1.MRScaleSlope(ia(i));
    end
    nii(i).hdr.scl_inter = inter;
    nii(i).hdr.scl_slope = slope;
    nii(i).hdr.file_name = [s.NiftiName '_' lower(c{i})];
    nii(i) = nii_tool('update', nii(i));

    for j = 1:numel(flds)
        if ~isfield(nii(i).json, flds{j}), continue; end
        nii(i).json.(flds{j}) = nii(i).json.(flds{j})(ind);
    end
end


%*******************************************************************
%Summary: This file runs the specified model and logs the data from the listed signals
%and plots the results.
%
%In this file you specify the name of the signal
%that you want to log.  You can also specify a decimation for the logged
%signals.  This models uses a variation of the Simulink Demo model named
%'sldemo_househeat'
% JAD - 1/6/06
%*********************************************************************

%**********Prepare workspace************
    clear
    clc
    close all
    name_mod='sldemo_househeat1'; %Name of model to simulate
%***************end***************************

    % Simulation Time Calculationss *******

    Sub_Sample_Time=3; % Log every third value

%Structure file that will contain the name of the signals to log
%Comment all names to disable signal logging

    log_struct{1}='Set_Temp';
    log_struct{2}='blower_cmd';
    log_struct{3}='Tout';
    log_struct{4}='Temp_in';
    log_struct{5}='Heat_Cost';
    log_struct{6}='Tout2';
    log_struct{7}='time';  %The time value can also be obtained from the logged Structure

    log_struct{8}='House/Sub_Temp';
%     log_struct{9}='';
%     log_struct{10}='';
%     log_struct{11}='';
%     log_struct{12}='';
%     log_struct{13}='';
%
%     log_struct{14}='';
%     log_struct{15}='';
%     log_struct{16}='';
%     log_struct{17}='';
%     log_struct{18}='';
%     log_struct{19}='';

    %Turn on logging for specified signals in the model
    if exist('log_struct')
                   %log_signals(name of model,name_of_log_var, enable_decimation, decimation_time)
        signal_name=log_signals(name_mod,log_struct,'off',Sub_Sample_Time);
    end

    % ********* Run Sim  ***********************************************
    tic
     sim(name_mod)
    toc
%***************end***************************

%*************Save logged values in the workspace************************
if exist('log_struct')

    for i=1:length(log_struct)
        index=findstr(log_struct{i},'/');

        if isempty(index)
           temp=[signal_name{i},'=logsout.',signal_name{i},'.Data;'];
           eval(temp);

        elseif (length(index)>1) % If this signal is in a subsystem
            sys_name=log_struct{i}(1:index(1)-1); %Grab the name of the system
            sub_sys_name=log_struct{i}(index(1)+1:index(2)-1); %Grab the name of the subsystem
            temp=[signal_name{i},'=logsout.(''',sys_name,''').',sub_sys_name,'.',signal_name{i},'.Data;'];
            eval(temp);
        else  %This signal is not in a subsystem
           temp1=log_struct{i}(1:index(1)-1); %Grab the name of the system
           temp=[signal_name{i},'=logsout.(''',temp1,''').',signal_name{i},'.Data;'];
           eval(temp);
        end
    end
end
%***************end***************************

%Close model and do not save model changes
%       close_system(name_mod,0);
 %Plot results

    figure(1)
    subplot(2,1,1)
    plot(time,Tout,time,Tout2)
    subplot(2,1,2)
    plot(Heat_Cost,time)


function [study,xmesh,ymesh,zmesh,tags]=dicomrt_d2c_coordsystem(study,xmesh,ymesh,zmesh,tags)
% dicomrt_d2c_coordsystem(study,xmesh,ymesh,zmesh,tags)
%
% Convert DICOM data from native coordinate system to RTOG coordinate system
%
% Copyright (C) 2002 Emiliano Spezi (emiliano.spezi@physics.org)
% LM 04/28/2006 DK
%         Fix for dose x-coordinates when patient position is FFS.

% Check input data
% PatientPosition is N/A in VOI hence it must be defined previously
% and stored in tags.dicomPatientPosition if we are dealing with VOI
if ~isfield(tags,'dicomPatientPosition') || isempty(tags(1).dicomPatientPosition)
    [study,type,dummylabel,PatientPosition]=dicomrt_checkinput(study);
    %tags.dicomPatientPosition=PatientPosition;
    for i=1:length(tags)
        tags(i).('dicomPatientPosition') = PatientPosition;
    end
else
    [study,type,dummylabel]=dicomrt_checkinput(study);
    PatientPosition=tags.dicomPatientPosition;
end

% Get DICOM-RT toolbox dataset info
study_pointer=study{1,1};
study_array=study{2,1};

% Accounting for different coordinate system between DICOM and RTOG
%
% NOTE: The origin of the RTOG coordinate system is defined as the coordinates of
% the geometrical center of the image. Offsets along the x- and y-direction
% are calculated from the DICOM original data.
%
if strcmpi('VOI',type)~=1                       % Separate case if study is a VOI
    if PatientPosition==1                       % HFS
        study_array                 = flipdim(study_array,3);
        tags.hio                    = 'IN';
        tags.pos                    = 'NOSE UP';
        if strcmpi('CT',type)~=1
            xmesh                       = xmesh;
            ymesh                       = -ymesh;
            zmesh                       = -zmesh;
            zmesh                       = flipdim(zmesh,1);
            %zmesh                       = zmesh-zmesh(1); % set origin to the first image transmitted
            tags.coord1OFFirstPoint     = xmesh(1);
            tags.coord2OFFirstPoint     = ymesh(1);
            temp_diff_x                 = diff(xmesh);
            temp_diff_y                 = diff(ymesh);
            tags.horizontalGridInterval = temp_diff_x(1);
            tags.verticalGridInterval   = temp_diff_y(1);
        else
            tags.originalCTxmesh        = xmesh;
            tags.originalCTymesh        = ymesh;
            tags.originalCTzmesh        = zmesh;
            xmesh                       = xmesh;
            ymesh                       = -ymesh;
            zmesh                       = -zmesh;
            zmesh                       = flipdim(zmesh,1);
            %zmesh                       = zmesh-zmesh(1); % set origin to the first image transmitted
            tags.xOffset                = xmesh(1) + sqrt(power((xmesh(1)-xmesh(end)),2))./2;
            tags.yOffset                = ymesh(1) - sqrt(power((ymesh(1)-ymesh(end)),2))./2;
            temp_diff_x                 = diff(xmesh);
            temp_diff_y                 = diff(ymesh);
            tags.grid1Units             = abs(temp_diff_x(1));
            tags.grid2Units             = abs(temp_diff_y(1));
        end
        tags.xcoordOfNormaliznPoint = '';
        tags.ycoordOfNormaliznPoint = '';
        tags.zcoordOfNormaliznPoint = '';
    elseif PatientPosition==2                   % FFS
        study_array                 = flipdim(study_array,3);
        tags.hio                    = 'OUT';
        tags.pos                    = 'NOSE UP';
        if strcmpi('CT',type)~=1
%             xmesh                       = xmesh;
            xmesh                       = -xmesh;%DK
            ymesh                       = -ymesh;
            zmesh                       = -zmesh;
            zmesh                       = flipdim(zmesh,1);
            %zmesh                       = zmesh-zmesh(1); % set origin to the first image transmitted
%             tags.coord1OFFirstPoint     = xmesh(1);
            tags.coord1OFFirstPoint     = -xmesh(1);%DK
            tags.coord2OFFirstPoint     = ymesh(1);
            temp_diff_x                 = diff(xmesh);
            temp_diff_y                 = diff(ymesh);
            tags.horizontalGridInterval = temp_diff_x(1);
            tags.verticalGridInterval   = temp_diff_y(1);
        else
            tags.originalCTxmesh        = xmesh;
            tags.originalCTymesh        = ymesh;
            tags.originalCTzmesh        = zmesh;
            xmesh                       = xmesh;
            ymesh                       = -ymesh;
            zmesh                       = -zmesh;
            zmesh                       = flipdim(zmesh,1);
            %zmesh                       = zmesh-zmesh(1); % set origin to the first image transmitted
            tags.xOffset                = xmesh(1) + sqrt(power((xmesh(1)-xmesh(end)),2))./2;
            tags.yOffset                = ymesh(1) - sqrt(power((ymesh(1)-ymesh(end)),2))./2;
            temp_diff_x                 = diff(xmesh);
            temp_diff_y                 = diff(ymesh);
            tags.grid1Units             = abs(temp_diff_x(1));
            tags.grid2Units             = abs(temp_diff_y(1));
        end
        tags.xcoordOfNormaliznPoint = '';
        tags.ycoordOfNormaliznPoint = '';
        tags.zcoordOfNormaliznPoint = '';
    elseif PatientPosition==3                   % HFP
        study_array                 = flipdim(study_array,3);
        tags.hio                    = 'IN';
        tags.pos                    = 'NOSE DOWN';
        if strcmpi('CT',type)~=1
            xmesh                       = -xmesh;
            ymesh                       = ymesh;
            zmesh                       = -zmesh;
            zmesh                       = flipdim(zmesh,1);
            %zmesh                       = zmesh-zmesh(1); % set origin to the first image transmitted
            tags.coord1OFFirstPoint     = xmesh(1);
            tags.coord2OFFirstPoint     = ymesh(1);
            temp_diff_x                 = diff(xmesh);
            temp_diff_y                 = diff(ymesh);
            tags.horizontalGridInterval = temp_diff_x(1);
            tags.verticalGridInterval   = temp_diff_y(1);
        else
            tags.originalCTxmesh        = xmesh;
            tags.originalCTymesh        = ymesh;
            tags.originalCTzmesh        = zmesh;
            xmesh                       = -xmesh;
            ymesh                       = ymesh;
            zmesh                       = -zmesh;
            zmesh                       = flipdim(zmesh,1);
            %zmesh                       = zmesh-zmesh(1); % set origin to the first image transmitted
            tags.xOffset                = xmesh(1) + sqrt(power((xmesh(1)-xmesh(end)),2))./2;
            tags.yOffset                = ymesh(1) - sqrt(power((ymesh(1)-ymesh(end)),2))./2;
            temp_diff_x                 = diff(xmesh);
            temp_diff_y                 = diff(ymesh);
            tags.grid1Units             = abs(temp_diff_x(1));
            tags.grid2Units             = abs(temp_diff_y(1));
        end
        tags.xcoordOfNormaliznPoint = '';
        tags.ycoordOfNormaliznPoint = '';
        tags.zcoordOfNormaliznPoint = '';
    else                                        % FFP
        study_array                 = flipdim(study_array,3);
        tags.hio                    = 'OUT';
        tags.pos                    = 'NOSE DOWN';
        if strcmpi('CT',type)~=1
            xmesh                       = -xmesh;
            ymesh                       = ymesh;
            zmesh                       = -zmesh;
            zmesh                       = flipdim(zmesh,1);
            %zmesh                       = zmesh-zmesh(1); % set origin to the first image transmitted
            tags.coord1OFFirstPoint     = xmesh(1);
            tags.coord2OFFirstPoint     = ymesh(1);
            temp_diff_x                 = diff(xmesh);
            temp_diff_y                 = diff(ymesh);
            tags.horizontalGridInterval = temp_diff_x(1);
            tags.verticalGridInterval   = temp_diff_y(1);
        else
            tags.originalCTxmesh        = xmesh;
            tags.originalCTymesh        = ymesh;
            tags.originalCTzmesh        = zmesh;
            xmesh                       = -xmesh;
            ymesh                       = ymesh;
            zmesh                       = -zmesh;
            zmesh                       = flipdim(zmesh,1);
            %zmesh                       = zmesh-zmesh(1); % set origin to the first image transmitted
            tags.xOffset                = xmesh(1) + sqrt(power((xmesh(1)-xmesh(end)),2))./2;
            tags.yOffset                = ymesh(1) - sqrt(power((ymesh(1)-ymesh(end)),2))./2;
            temp_diff_x                 = diff(xmesh);
            temp_diff_y                 = diff(ymesh);
            tags.grid1Units             = abs(temp_diff_x(1));
            tags.grid2Units             = abs(temp_diff_y(1));
        end
        tags.xcoordOfNormaliznPoint = '';
        tags.ycoordOfNormaliznPoint = '';
        tags.zcoordOfNormaliznPoint = '';
    end
else
    if PatientPosition==1                       % HFS flip dimensions
        xmesh                       = xmesh;
        ymesh                       = -ymesh;
        zmesh                       = -zmesh;
        for jj=1:size(study_array,1)            % loop though the number of VOIs
            for kk=1:size(study_array{jj,2},1)  % loop though the number of sections
                % reverse Z
                study_array{jj,2}{kk}(:,3)=-study_array{jj,2}{kk}(:,3);
                % reverse Y
                study_array{jj,2}{kk}(:,2)=-study_array{jj,2}{kk}(:,2);
            end
        end
    elseif PatientPosition==2                   % FFS flip dimensions
        xmesh                       = xmesh;
        ymesh                       = -ymesh;
        zmesh                       = -zmesh;
        for jj=1:size(study_array,1)            % loop though the number of VOIs
            for kk=1:size(study_array{jj,2},1)  % loop though the number of sections
                % reverse Z
                study_array{jj,2}{kk}(:,3)=-study_array{jj,2}{kk}(:,3);
                % reverse Y
                study_array{jj,2}{kk}(:,2)=-study_array{jj,2}{kk}(:,2);
            end
        end
    elseif PatientPosition==3                   % HFP nothing to do
        xmesh                       = -xmesh;
        ymesh                       = ymesh;
        zmesh                       = -zmesh;
        for jj=1:size(study_array,1)            % loop though the number of VOIs
            for kk=1:size(study_array{jj,2},1)  % loop though the number of sections
                % reverse Z
                study_array{jj,2}{kk}(:,3)=-study_array{jj,2}{kk}(:,3);
                % reverse X
                study_array{jj,2}{kk}(:,1)=-study_array{jj,2}{kk}(:,1);
            end
        end
    else
        xmesh                       = -xmesh;
        ymesh                       = ymesh;
        zmesh                       = -zmesh;
        for jj=1:size(study_array,1)            % loop though the number of VOIs
            for kk=1:size(study_array{jj,2},1)  % loop though the number of sections
                % reverse Z
                study_array{jj,2}{kk}(:,3)=-study_array{jj,2}{kk}(:,3);
                % reverse X
                study_array{jj,2}{kk}(:,1)=-study_array{jj,2}{kk}(:,1);
            end
        end
    end
end

% Return data
study{2,1}=study_array;