%% Exercise with cosmo_correlation_measure
% Split-half correlation analysis using cosmo_correlation_measure
%
% #   For CoSMoMVPA's copyright information and license terms,   #
% #   see the COPYING file distributed with CoSMoMVPA.           #

%% Single subject analysis over all categories in VT

% Set the data path
config=cosmo_config();
study_path=fullfile(config.tutorial_data_path,'ak6');

subject_id='s01';
mask_label='vt_mask';
data_path=fullfile(study_path,subject_id); % data from subject s01

% Define data locations and load data from even and odd runs
mask_fn=fullfile(data_path, [mask_label '.nii']); % whole brain

% Load data for odd runs
data_odd_fn=fullfile(data_path,'glm_T_stats_odd.nii');
ds_odd=cosmo_fmri_dataset(data_odd_fn,'mask',mask_fn,...
                            'targets',1:6,'chunks',1);

% Load data for even runs
data_even_fn=fullfile(data_path,'glm_T_stats_even.nii');
ds_even=cosmo_fmri_dataset(data_even_fn,'mask',mask_fn,...
                            'targets',1:6,'chunks',2);

% Combine even and odd runs into single dataset, store in ds_odd_even
% Hint: use cosmo_stack
% >@@>
ds_odd_even=cosmo_stack({ds_odd, ds_even});
% <@@<

% remove constant features (due to liberal masking)
ds_odd_even=cosmo_remove_useless_data(ds_odd_even);

% display dataset
fprintf('Dataset input:\n');
cosmo_disp(ds_odd_even);

% Part 1: compute correlation difference
% Hint: - apply cosmo_correlation_measure to ds_odd_even
%       - because correlation difference and split-half correlations
%         are the defaults, no second argument (options) is required
%         for cosmo_correlation_measure.
% >@@>
ds_corr=cosmo_correlation_measure(ds_odd_even);
% <@@<
fprintf('\nDataset output (correlation difference):\n');
cosmo_disp(ds_corr);

fprintf(['Average correlation difference between matching and '...
            'non-matching categories in %s for %s is %.3f\n'],...
            mask_label, subject_id, ds_corr.samples);

% Part 2: compute the raw Fisher-transformed correlation matrix,
% and store the results in 'c_raw'
%
% (Hint: use a struct 'args' with args.output='correlation' as second
% argument for cosmo_correlation_measure)
% >@@>
args=struct();
args.output='correlation';
c_raw=cosmo_correlation_measure(ds_odd_even,args);
% <@@<
fprintf('\nDataset output (Fisher-transformed correlations):\n');
cosmo_disp(c_raw)

% Because a measure returns .samples as a column vector, the
% confusion matrix is returned in a flattened form.
% The data can be put back in matrix form using cosmo_unflatten.
matrices=cosmo_unflatten(c_raw,1);
imagesc(matrices);
colorbar();

%% Group analysis over all categories in VT using correlation measure

% Compute correlation measure for each subject individually.
subject_ids={'s01','s02','s03','s04','s05','s06','s07','s08'};
nsubjects=numel(subject_ids);

mask_label='vt_mask';

% allocate a cell for the output of the measure for each subject
ds_corr_cell=cell(nsubjects,1);

% Apply correlation measure for each subject using
% cosmo_correlation_measure.
% - compute the correlation measure using cosmo_correlation_measure;
%   this should give a dataset structure with ds.samples of size 1x1
% - because statistics are computed later, add to the output:
%   * .sa.chunks : the subject number
%   * .sa.targets: 1 (for each subject)
% - store the result of the k-th subject in ds_corr_cell{k}

for subject_num=1:nsubjects
    subject_id=subject_ids{subject_num};

    % set path for this subject
    data_path=fullfile(study_path,subject_id);

    % Define data locations and load data from even and odd runs
    mask_fn=fullfile(data_path, [mask_label '.nii']); % whole brain

    data_odd_fn=fullfile(data_path,'glm_T_stats_odd.nii');
    ds_odd=cosmo_fmri_dataset(data_odd_fn,'mask',mask_fn,...
                                'targets',1:6,'chunks',1);

    data_even_fn=fullfile(data_path,'glm_T_stats_even.nii');
    ds_even=cosmo_fmri_dataset(data_even_fn,'mask',mask_fn,...
                                'targets',1:6,'chunks',2);

    % Combine even and odd runs
    ds_odd_even=cosmo_stack({ds_odd, ds_even});

    % remove constant features (due to liberal masking)
    ds_odd_even=cosmo_remove_useless_data(ds_odd_even);

    % apply correlation measure for this subject, and store
    % the result in 'ds_corr'
    % >@@>
    ds_corr=cosmo_correlation_measure(ds_odd_even);
    % <@@<
    % set targets and chunks for the output, so that cosmo_stat can be used
    % below
    ds_corr.sa.targets=1;
    ds_corr.sa.chunks=subject_num;

    % store result in the cell array 'ds_corr_cell' at the 'subject_num'-th
    % position
    % >@@>
    ds_corr_cell{subject_num}=ds_corr;
    % <@@<
end

% combine the data from all subjects (in 'ds_corr_cell') into one dataset
% using cosmo_stack, and assign the result to a variable 'ds_all'
% >@@>
ds_all=cosmo_stack(ds_corr_cell);
% <@@<

%% Compute group-level statistics

% run one-sample t-test again zero to compute the t-value and p-values
% against the null hypothesis of a mean of zero.
%
% hint: use matlab stats toolbox's ttest (if present), or
%       use cosmo_stat:
%       * for t-statistics, use 't' as second argument
%       * to convert a 't' to 'p' value, use 'p' as third argument
% >@@>
ds_t=cosmo_stat(ds_all,'t');     % t-test against zero
ds_p=cosmo_stat(ds_all,'t','p'); % convert to p-value

samples=ds_all.samples;

fprintf(['correlation difference in %s at group level: '...
           '%.3f +/- %.3f, %s=%.3f, p=%.5f (using cosmo_stat)\n'],...
            mask_label,mean(samples),std(samples),...
            ds_t.sa.stats{1},ds_t.samples,ds_p.samples);
% <@@<

% Using matlab's stat toolbox (if present)
if cosmo_check_external('@stats',false)
    % >@@>
    [h,p,ci,stats]=ttest(samples);
    fprintf(['correlation difference in %s at group level: '...
            '%.3f +/- %.3f, t_%d=%.3f, p=%.5f (using matlab stats '...
            'toolbox)\n'],...
            mask_label,mean(samples),std(samples),stats.df,stats.tstat,p);
    % <@@<
else
    fprintf('Matlab stats toolbox not found\n');
end


function y = all(x)

% ALL True if all elements of a vector are nonzero.
%
% For vectors, ALL(V) returns logical 1 (TRUE) if none of the elements
% of the vector are zero.  Otherwise it returns logical 0 (FALSE).  For
% matrices, ALL(X) operates on the columns of X, returning a row vector
% of logical 1's and 0's. For N-D arrays, ALL(X) operates on the first
% non-singleton dimension.

% Copyright (C) 2012, Donders Centre for Cognitive Neuroimaging, Nijmegen, NL
%
% 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 nargin>1
  error('this implementation is only supported with one input argument');
end

siz = size(x);
if numel(siz)>2
  error('this implementation is only supported with vector or matrix input');
end

if siz(1)==1 || siz(2)==1
  y = true;
  for i=1:prod(siz)
    if ~x(i)
      y = false;
      break
    end
  end

else
  y = true(1,siz(2));
  for j=1:siz(2)
    for i=1:siz(1)
      if ~x(i,j)
        y(1,j) = false;
        break
      end
    end
  end

end


function [Subcomponents,Population] = DividingDistanceVariables(Problem,NIA,DiverIndexes,ConverIndexes)
% Dividing distance variables

%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    %% Generate the initial population
    PopDec = zeros(Problem.N,Problem.D);
    % Generate the diverse variables by uniformly sampling method
    if sum(DiverIndexes) == 1
        PopDec(:,DiverIndexes) = (0:Problem.N-1)/(Problem.N-1);
    elseif sum(DiverIndexes) > 4
        PopDec(:,DiverIndexes) = rand(Problem.N,sum(DiverIndexes));
    else
        PopDec(:,DiverIndexes) = UDall(Problem.N,sum(DiverIndexes));
    end
    % Randomly generate the distance variables
    PopDec(:,ConverIndexes) = rand(Problem.N,sum(ConverIndexes));
    % Generate the initial population
    PopDec     = PopDec.*repmat(Problem.upper-Problem.lower,Problem.N,1) + repmat(Problem.lower,Problem.N,1);
    Population = Problem.Evaluation(PopDec);

    %% Interdependence analysis
    interaction = false(Problem.D);
    interaction(logical(eye(Problem.D))) = true;
    for i = 1 : Problem.D-1
        for j = i+1 : Problem.D
            drawnow('limitrate');
            for time2try = 1 : NIA
                % Detect whether the i-th and j-th decision variables are
                % interacting
                x    = randi(Problem.N);
                a2   = rand*(Problem.upper(i)-Problem.lower(i)) + Problem.lower(i);
                b2   = rand*(Problem.upper(j)-Problem.lower(j)) + Problem.lower(j);
                Decs = repmat(Population(x).dec,3,1);
                Decs(1,i) = a2;
                Decs(2,j) = b2;
                Decs(3,[i,j]) = [a2,b2];
                F = Problem.Evaluation(Decs);
                delta1 = F(1).obj - Population(x).obj;
                delta2 = F(3).obj - F(2).obj;
                interaction(i,j) = interaction(i,j) | any(delta1.*delta2<0);
                interaction(j,i) = interaction(i,j);
                % Update the solution
                if ConverIndexes(j) && all(F(2).obj <=Population(x).obj)
                    Population(x) = F(2);
                end
                if ConverIndexes(i) && all(F(1).obj <=Population(x).obj)
                    Population(x) = F(1);
                end
                if all(ConverIndexes([i,j])) && all(F(3).obj <=Population(x).obj)
                    Population(x) = F(3);
                end
            end
        end
    end

    %% Dividing distance variables
    Subcomponents = {};
    divided = false(1,Problem.D);
    while ~all(divided(ConverIndexes))
        x = find(~divided & ConverIndexes,1);
        while sum(any(interaction(x,ConverIndexes),1)) > length(x)
            x = find(any(interaction(x,:),1) & ConverIndexes);
        end
        Subcomponents = [Subcomponents,x];
        divided(x) = true;
    end
end


function net = gpunpak(net, hp)
%GPUNPAK Separates hyperparameter vector into components.
%
%	Description
%	NET = GPUNPAK(NET, HP) takes an Gaussian Process data structure NET
%	and  a hyperparameter vector HP, and returns a Gaussian Process data
%	structure  identical to the input model, except that the covariance
%	bias BIAS, output noise NOISE, the input weight vector INWEIGHTS and
%	the vector of covariance function specific parameters  FPAR have all
%	been set to the corresponding elements of HP.
%
%	See also
%	GP, GPPAK, GPFWD, GPERR, GPGRAD
%

%	Copyright (c) Ian T Nabney (1996-2001)

% Check arguments for consistency
errstring = consist(net, 'gp');
if ~isempty(errstring);
  error(errstring);
end
if net.nwts ~= length(hp)
  error('Invalid weight vector length');
end

net.bias = hp(1);
net.noise = hp(2);

% Unpack input weights
mark1 = 2 + net.nin;
net.inweights = hp(3:mark1);

% Unpack function specific parameters
net.fpar = hp(mark1 + 1:size(hp, 2));


function [ U, g ] = cgrid_uv2rho(ncRef, uname, vname, hname, aname,...
    itime, klev, jj, ii)
% CGRID_UV2RHO Get 2D slice of velocity from a C-grid model (e.g. ROMS)
% Usage:
%    [U,g] = cgrid_uv2rho(ncRef, uname, vname, hvar, avar, itime, klev, [jj], [ii]);
% Inputs:
%   ncRef = OpenDAP Data URL, Local file, or existing 'ncgeodataset' object
%   uname - u variable to slice
%   vname - v variable to slice
%   hname - rho-centered variable to slice (e.g. 'h')
%   aname - rho-centered angle variable (e.g. 'angle')
  %   itime = time step to extract data. Use -1 for last time step. (ignored for static variables)
  %   klev  = vertical level  Use -1 for last level. (ignored for 2d variables)
%   [jj] =  jindex range (subset) [optional, default is entire dimension]
%   [ii] =  iindex range (subset) [optional, default is entire dimension]
%
% Outputs:
%   U = 2D array of complex velocity
%   g  = grid structure containing lon,lat,z,time (Matlab datenum)
%
% Example:
% url='http://geoport.whoi.edu/thredds/dodsC/examples/bora_feb.nc';
% hname='h'; uname='u'; vname='v'; aname='angle';
% nc=ncgeodataset(url);
% itime=3; % 3rd time step
% klev=-1; % last (top) layer
%  % Whole domain:
% [ U,g ] = cgrid_uv2rho(nc,uname,vname,hname,aname,itime,klev);
% % Subset to jj,ii range:
% [ U,g ] = cgrid_uv2rho(nc,uname,vname,hname,aname,itime,klev,1:58,1:70);
% % 3D variable:
% hname='h'; uname='ubar'; vname='vbar'; aname='angle';
% [ U,g ] = cgrid_uv2rho(nc,uname,vname,hname,aname,itime,klev,1:58,1:70);
% pcolorjw(g.lon,g.lat,abs(U));colorbar;dasp(44);
% arrows(g.lon(1:2:end,1:2:end),g.lat(1:2:end,1:2:end),...
%     U(1:2:end,1:2:end),0.08,'black');
%  title(datestr(g.time));dasp(44);

% Note: this routine assumes that the C grid has variables arranged:
%
%       ---------------------------------
%       rho | u | rho | u | rho | u | rho
%       ---------------------------------
%        v  |   | {v} |   | {v} |   |  v
%       ---------------------------------
%       rho |{u}|(rho)|{u}|(rho)|{u}| rho
%       ---------------------------------
%        v  |   | {v} |   | {v} |   |  v
%       ---------------------------------
%       rho | u | rho | u | rho | u | rho
%       ---------------------------------
%
% .. so that size(rho)=ny,nx;  size(u)=ny,nx-1, size(v)=ny-1,nx)
% Also assumes coordinate dimensions are arranged (t, z, y, x)

if (isa(ncRef, 'ncgeodataset')) %check for ncgeodataset object
    nc = ncRef;
else
    % open CF-compliant dataset as ncgeodataset object
    nc = ncgeodataset(ncRef);
end

uvar = nc.geovariable(uname);
vvar = nc.geovariable(vname);
hvar = nc.geovariable(hname);
avar = nc.geovariable(aname);

% depth from uvar
if nargin < 7
    usize = size(uvar);
  if ( length(usize) == 4)
    klev = usize(2);
  else
    klev = 1;
  end
end

% get lon,lat size from hvar
if nargin < 8
    hsize = hvar.size;
    horder = hvar.getaxesorder;
    if horder.lat == horder.lon
        jj = 1:hsize(horder.lat);
        ii = 1:hsize(horder.lat  + 1);
    else
        %         ii = hsize(order.lat);
        %         jj = hsize(order.lon);
        error('order.lat != order.lon');
    end
else
    %pass
end
ujj = (jj(1) + 1):(jj(end) - 1);
uii = ii(1):ii(end) - 1;
vjj = jj(1):jj(end) - 1;
vii = (ii(1) + 1):(ii(end) - 1);

if (length(size(uvar))==4)
   u = double(squeeze(uvar.data(itime, klev, ujj, uii))); % get u
   v = double(squeeze(vvar.data(itime, klev, vjj, vii))); % get v
elseif (length(size(uvar))==3)
   u = double(squeeze(uvar.data(itime, ujj, uii))); % get u
   v = double(squeeze(vvar.data(itime, vjj, vii))); % get v
elseif (length(size(uvar))==2)
   u = double(squeeze(uvar.data(ujj, uii))); % get u
   v = double(squeeze(vvar.data(vjj, vii))); % get v
end
g = hvar.grid_interop(jj, ii); % get lon,lat from rho-point variable (like 'h' in ROMS)
ang = avar.data(jj, ii); % get angle
U = ones(size(g.lon)) * nan; % template for U at rho points
U(2:end-1, 2:end-1) = complex(av2(u.').', av2(v)); %average u,v to rho
U = U .* exp(sqrt(-1) * ang); % rotate

if nargout == 2
    tim = uvar.timewindowij( double(itime) );
    g.time = tim.time;
    g.klevel = klev;
    g.itime = itime;
end


%% triSurfSelfTriangulateBoundary
% Below is a demonstration of the features of the |triSurfSelfTriangulateBoundary| function

%%
clear; close all; clc;

%% Syntax
% |[F1,V1,ind1]=triSurfSelfTriangulateBoundary(F1,V1,ind1,angleThreshold,isClosedLoop);|

%% Description
% The |triSurfSelfTriangulateBoundary| function
%

%% Examples

%% Example 1: Self-triangulate the boundary of a surface by creating triangles at sharp boundary segments
% Create test data set
w=1;
[X,Y]=ndgrid(linspace(0,w,15));
Z=ones(size(X));
C=tril(Z);
[F,V,C]=surf2patch(X,Y,Z,C); %Quads
C=vertexToFaceMeasure(F,C)>0;

logicKeep=C>0;
F=F(logicKeep,:);
C=C(logicKeep,:);
[F,V]=patchCleanUnused(F,V);

F=[F(:,[1 2 3]);F(:,[3 4 1])]; %Triangles

%%
% Get boundary curve

Eb=patchBoundary(F);
indBoundaryCurve=edgeListToCurve(Eb);
indBoundaryCurve=indBoundaryCurve(1:end-1)'; %Start=End for closed curve so remove double entry

%%
% Self triangulate
angleThreshold=(100/180)*pi;
isClosedPath=1;
[F_new,V_new,indBoundaryCurve_new]=triSurfSelfTriangulateBoundary(F,V,indBoundaryCurve,angleThreshold,isClosedPath);

%%

cFigure;
subplot(1,2,1); hold on;
title('Original');
gpatch(F,V,'kw');
plotV(V(indBoundaryCurve,:),'k-','LineWidth',3);
axisGeom; view(2);

subplot(1,2,2); hold on;
title('Self-triangulated');
gpatch(F_new,V_new,'kw');
plotV(V_new(indBoundaryCurve_new,:),'k-','LineWidth',3);
axisGeom; view(2);

drawnow;

%% Example 2: Altered shape

V(:,1)=V(:,1)-V(:,2);

%%
% Calculate mesh path angles

[F_new,V_new,indBoundaryCurve_new]=triSurfSelfTriangulateBoundary(F,V,indBoundaryCurve,angleThreshold,isClosedPath);

%%

cFigure;
subplot(1,2,1); hold on;
title('Original');
gpatch(F,V,'kw');
plotV(V(indBoundaryCurve,:),'k-','LineWidth',3);
axisGeom; view(2);

subplot(1,2,2); hold on;
title('Self-triangulated');
gpatch(F_new,V_new,'kw');
plotV(V_new(indBoundaryCurve_new,:),'k-','LineWidth',3);
axisGeom; view(2);

drawnow;

%% Example 3: Self-triangulate a part of boundary surface

%%
% Create path segment
indBoundaryCurve=indBoundaryCurve(1:15);

%%
% Calculate mesh path angles
isClosedPath=0;
[F_new,V_new,indBoundaryCurve_new]=triSurfSelfTriangulateBoundary(F,V,indBoundaryCurve,angleThreshold,isClosedPath);

%%

cFigure;
subplot(1,2,1); hold on;
title('Original');
gpatch(F,V,'kw');
plotV(V(indBoundaryCurve,:),'k-','LineWidth',3);
axisGeom; view(2);

subplot(1,2,2); hold on;
title('Self-triangulated');
gpatch(F_new,V_new,'kw');
plotV(V_new(indBoundaryCurve_new,:),'k-','LineWidth',3);
axisGeom; view(2);

drawnow;

%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


function outputImage = imdilate(this, structureElement, nD)
% Dilates image clusters slice-wise; mimicks imdilate in matlab functionality
%
%   Y = MrImage()
%   dilatedY = Y.imdilate(structureElement, nD)
%
% This is a method of class MrImage.
%
% IN
%   structureElement
%           morphological structuring element for dilation, e.g.
%           strel('disk', 2) for a disk of radius 2
%           default: strel('disk', 2)
%   nD      dimensionality to perform operation
%           '2d' = slicewise application, separate 2d images
%           '3d' = as volume
%
% OUT
%   outputImage
%           MrImage where data matrix is inflated
%
% EXAMPLE
%   Y = MrImage();
%   dilatedY = Y.imdilate()
%   dilatedY = Y.imdilate(strel('disk', 5))
%
%
%   See also MrImage imdilate MrImage.imerode perform_unary_operation

% Author:   Saskia Klein & Lars Kasper
% Created:  2014-08-04
% Copyright (C) 2014 Institute for Biomedical Engineering
%                    University of Zurich and ETH Zurich
%
% This file is part of the TAPAS UniQC Toolbox, which is released
% under the terms of the GNU General Public Licence (GPL), version 3.
% You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version).
% For further details, see the file COPYING or
%  <http://www.gnu.org/licenses/>.

% update geometry-header with flipping left-right
if nargin < 2
    structureElement = strel('disk', 2);
end

if nargin < 3
    nD = '2d';
end

if isreal(this)
    outputImage = this.perform_unary_operation(...
        @(x) imdilate(x, structureElement), nD);
else
    outputImage = this.abs.perform_unary_operation(...
        @(x) imdilate(x, structureElement), nD);
end


function lineIdx = ...
  mrGeodesic(grayNodes,grayEdges,dimdist,radius,spacing,crit,seed1,seed2)
%
% lineIdx =
%    mrGeodesic(grayNodes,grayEdges,dimdist, ...
%        radius,spacing,crit,seed1,[seed2])
%
% AUTHOR:  Heeger, Wandell
% DATE:
% PURPOSE:
%   Find the gray node indices along a geodesic between seed1 and
% seed2.  The gray node indices are separated by spacing.
%
% grayNodes, grayEdges, dimdist:  These are the usual parameters
%      from the unfolding analysis.
%
% radius:  If one seed, choose the second near this radius
% spacing: Spacing of sample points along the geodesics
% crit:    Criterion level that determines how close does the
%           point have to be to satisfying the "on the line"
% seed1:   Starting point for one end of the geodesic
% [seed2:] Second point on the geodesic.
%
% TODO:
%   Order of arguments could be better.  I am not sure we handle
% to two seed case properly.  BW
%

errordlg('This function is obsolete.  Use the method described in mrManDist.  Then implement that method here.');

noVol = -1;

% Find the distances from seed1 and a second seed that is as far
% away as possible
%
dist1 = mrManDist(grayNodes, grayEdges, seed1, dimdist, noVol, radius + 1);

if (~exist('seed2'))
  [dist12 idx] = max(dist1);
  seed2 = idx;
else
  dist12 = dist1(seed2);
  if (radius < dist12)
    disp('Increasing radius')
    radius = dist12 + 1;
  end
end

% The points along a geodesic between 1 and 2 should have a
% distance from 1 and 2 that sums to the distance between 1 and 2
%
dist2 = ...
    mrManDist(grayNodes, grayEdges, seed2, dimdist, noVol,radius + 1);
between12 = find( abs(dist1 + dist2 - dist12) < crit);

% This finds the points spaced by an amount sep along the
% geodesic
%

sep = [spacing:spacing:dist12];
nSep = length(sep);
lineIdx = ones(nSep,1)*(-1);

for count = 1:nSep;
  [v idx] = min(abs(dist1(between12) - sep(count)));
  lineIdx(count) = between12(idx);
end

return;

% DEBUGGING:
% cd /usr/local/matlab/toolbox/stanford/mri/unfold/Example
% [grayNodes grayEdges] = readGrayGraph('Graph.gray');
% seed1 = 100
% radius = 30
% dimdist = [1.0667 1.0667 1.0000];
% spacing = 1;
% lineIdx = mrGeodesic(grayNodes,grayEdges,dimdist,radius,spacing,crit,seed1,seed2);
%
% grayNodes(1:3,lineIdx(1:nSep,1))
% To view this, we need to plot these points on top of the volume
% anatomy somehow.


function T = isotopes(varargin)
%ISOTOPES Returns NMR properties of the isotopes
% T = isotopes(i1, i2, ...)
%
% EXAMPLE
%     H = isotopes('1H'), T = isotopes('3H'), or if the atomic mass is not
%     specified, i.e. I = isotopes('H'), the function returns array of
%     structures with data for all isotopes of the specified element.
%     isotopes('n') returns NMR properties for neutron. Isotopes called
%     without arguments returns the whole table.
%
% The output structure has the following fields:
%     .name - element name;
%     .isotope - element symbol and mass number, i.e. 19F;
%     .Z - atomic number;
%     .mass - mass number;
%     .I - nuclear spin;
%     .gamma - magnetogyric ratio in rad/(T s) calculated from the resonant
%              frequency: 2*pi*F(@1T);
%     .ResFreq - resonant frequency in Hertz for an applied field B0 of 1 tesla
%                (in cgs units, 10 kilogauss);
%     .RelSensB - sensitivity relative to 1H (=1) assuming an equal number
%                 of nuclei, constant temperature, and constant B0:
%                 0.0076508(mu/mu_N)^3(I + 1)/I^2;
%     .RelSensF - sensitivity relative to 1H (=1) assuming an equal number
%                 of nuclei, constant temperature, and constant resonance
%                 frequency: O.23871(mu/mu_N)(I + 1);
%     .u - nuclear magnetic moment in units of the nuclear magneton, (mu/mu_N);
%     .Q - nuclear quadrupole moment in units of femtometers squared
%          (1 fm2 = 10^-2 barn)
%
%
% REFERENCES
% 1. "Nuclear spins, moments, and other data related to NMR spectroscopy" (9-93)
%    CRC Handbook of Chemistry and Physics, 83th Ed., CRC Press, Boca Raton, FL,
%    2002.
% 2. Stone, N. J., <www.nndc.bnl.gov/nndc/stone_moments/>
% 3. http://www.hbcpnetbase.com/

% Copyright (c) 2002 by Peter L. Volegov (volegov@unm.edu)
% All Rights Reserved.

%% Table of the Isotopes
% Element, Name, Z, AtomicMass, Spin, F@1T/MHz, RelSens(H), RelSens(F), mu/mu_N, Q/fm2
TheTable = {
'n', 'neutron', 1, 1, 1/2, 29.1647, 0.32139, 0.6850, -1.913042720, 0.0000; ...
'H', 'Hydrogen', 1, 1, 1/2, 42.5775, 1.00000, 1.0000, 2.792847337, 0.0000; ...
'H', 'Deuterium', 1, 2, 1, 6.5359, 0.00965, 0.4093, 0.857438228, 0.2860; ...
'H', 'Tritium', 1, 3, 1/2, 45.4148, 1.21354, 1.0666, 2.978962500, 0.0000; ...
'He', 'Helium', 2, 3, 1/2, 32.4360, 0.44212, 0.7618, -2.127624800, 0.0000; ...
'Li', 'Lithium', 3, 6, 1, 6.2661, 0.00850, 0.3925, 0.822046700, -0.0808; ...
'Li', 'Lithium', 3, 7, 3/2, 16.5483, 0.29356, 1.9433, 3.256440000, -4.0100; ...
'Be', 'Beryllium', 4, 9, 3/2, 5.9842, 0.01388, 0.7027, -1.177600000, 5.2880; ...
'B', 'Boron', 5, 10, 3, 4.5752, 0.01985, 1.7193, 1.800645000, 8.4590; ...
'B', 'Boron', 5, 11, 3/2, 13.6630, 0.16522, 1.6045, 2.688649000, 4.0590; ...
'C', 'Carbon', 6, 13, 1/2, 10.7084, 0.01591, 0.2515, 0.702411800, 0.0000; ...
'N', 'Nitrogen', 7, 14, 1, 3.0777, 0.00101, 0.1928, 0.403761000, 2.0440; ...
'N', 'Nitrogen', 7, 15, 1/2, 4.3173, 0.00104, 0.1014, -0.283188800, 0.0000; ...
'O', 'Oxygen', 8, 17, 5/2, 5.7742, 0.02910, 1.5822, -1.893790000, -2.5580; ...
'F', 'Fluorine', 9, 19, 1/2, 40.0776, 0.83400, 0.9413, 2.628868000, 0.0000; ...
'Ne', 'Neon', 10, 21, 3/2, 3.3631, 0.00246, 0.3949, -0.661797000, 10.1550; ...
'Na', 'Sodium', 11, 23, 3/2, 11.2688, 0.09270, 1.3233, 2.217522000, 10.4000; ...
'Mg', 'Magnesium', 12, 25, 5/2, 2.6083, 0.00268, 0.7147, -0.855450000, 19.9400; ...
'Al', 'Aluminum', 13, 27, 5/2, 11.1031, 0.20689, 3.0424, 3.641507000, 14.6600; ...
'Si', 'Silicon', 14, 29, 1/2, 8.4655, 0.00786, 0.1988, -0.555290000, 0.0000; ...
'P', 'Phosphorus', 15, 31, 1/2, 17.2515, 0.06652, 0.4052, 1.131600000, 0.0000; ...
'S', 'Sulfur', 16, 33, 3/2, 3.2717, 0.00227, 0.3842, 0.643821200, -6.7800; ...
'Cl', 'Chlorine', 17, 35, 3/2, 4.1765, 0.00472, 0.4905, 0.821874300, -8.1650; ...
'Cl', 'Chlorine', 17, 37, 3/2, 3.4765, 0.00272, 0.4083, 0.684123600, -6.4350; ...
'Ar', 'Argone', 18, 37, 3/2, 5.8190, 0.01276, 0.6833, 1.145000000, 0.0000; ...
'Ar', 'Argone', 18, 39, 7/2, 3.4600, 0.01130, 1.7079, -1.590000000, 0.0000; ...
'K', 'Potassium', 19, 39, 3/2, 1.9893, 0.00051, 0.2336, 0.391466200, 5.8500; ...
'K', 'Potassium', 19, 40, 4, 2.4737, 0.00523, 1.5493, -1.298100000, -7.3000; ...
'K', 'Potassium', 19, 41, 3/2, 1.0919, 8.00000, 0.1282, 0.214870100, 7.1100; ...
'Ca', 'Calcium', 20, 43, 7/2, 2.8688, 0.00642, 1.4150, -1.317260000, -4.0800; ...
'Sc', 'Scandium', 21, 45, 7/2, 10.3591, 0.30244, 5.1093, 4.756487000, -22.0000; ...
'Ti', 'Titanium', 22, 47, 5/2, 2.4041, 0.00210, 0.6587, -0.788480000, 30.2000; ...
'Ti', 'Titanium', 22, 49, 7/2, 2.4048, 0.00378, 1.1861, -1.104170000, 24.7000; ...
'V', 'Vanadium', 23, 50, 6, 4.2505, 0.05571, 5.5904, 3.345689000, 21.0000; ...
'V', 'Vanadium', 23, 51, 7/2, 11.2133, 0.38360, 5.5306, 5.148705700, -5.2000; ...
'Cr', 'Chromium', 24, 53, 3/2, 2.4115, 0.00091, 0.2832, -0.474540000, -15.0000; ...
'Mn', 'Manganese', 25, 55, 5/2, 10.5763, 0.17881, 2.8980, 3.468720000, 33.0000; ...
'Fe', 'Iron', 26, 57, 1/2, 1.3816, 0.00003, 0.0324, 0.090623000, 0.0000; ...
'Co', 'Cobalt', 27, 59, 7/2, 10.0770, 0.27841, 4.9702, 4.627000000, 42.0000; ...
'Ni', 'Nickel', 28, 61, 3/2, 3.8114, 0.00359, 0.4476, -0.750020000, 16.2000; ...
'Cu', 'Copper', 29, 63, 3/2, 11.2982, 0.09342, 1.3268, 2.223290000, -22.0000; ...
'Cu', 'Copper', 29, 65, 3/2, 12.1030, 0.11484, 1.4213, 2.381670000, -20.4000; ...
'Zn', 'Zinc', 30, 67, 5/2, 2.6694, 0.00287, 0.7314, 0.875479000, 15.0000; ...
'Ga', 'Gallium', 31, 69, 3/2, 10.2478, 0.06971, 1.2034, 2.016590000, 17.1000; ...
'Ga', 'Gallium', 31, 71, 3/2, 13.0208, 0.14300, 1.5291, 2.562270000, 10.7000; ...
'Ge', 'Germanium', 32, 73, 9/2, 1.4897, 0.00141, 1.1546, -0.879467700, -19.6000; ...
'As', 'Arsenic', 33, 75, 3/2, 7.3150, 0.02536, 0.8590, 1.439475000, 31.4000; ...
'Se', 'Selenium', 34, 77, 1/2, 8.1571, 0.00703, 0.1916, 0.535060000, 0.0000; ...
'Br', 'Bromine', 35, 79, 3/2, 10.7042, 0.07945, 1.2570, 2.106400000, 31.3000; ...
'Br', 'Bromine', 35, 81, 3/2, 11.5384, 0.09951, 1.3550, 2.270562000, 26.2000; ...
'Kr', 'Krypton', 36, 83, 9/2, 1.6442, 0.00190, 1.2744, -0.970669000, 25.9000; ...
'Rb', 'Rubidium', 37, 85, 5/2, 4.1254, 0.01061, 1.1304, 1.353030000, 27.6000; ...
'Rb', 'Rubidium', 37, 87, 3/2, 13.9811, 0.17703, 1.6418, 2.751240000, 13.3500; ...
'Sr', 'Strontium', 38, 87, 9/2, 1.8525, 0.00272, 1.4358, -1.093603000, 33.5000; ...
'Y', 'Yttrium', 39, 89, 1/2, 2.0949, 0.00012, 0.0492, -0.137415400, 0.0000; ...
'Zr', 'Zirconium', 40, 91, 5/2, 3.9748, 0.00949, 1.0891, -1.303620000, -17.6000; ...
'Nb', 'Niobium', 41, 93, 9/2, 10.4523, 0.48821, 8.1011, 6.170500000, -32.0000; ...
'Mo', 'Molybdenum', 42, 95, 5/2, 2.7874, 0.00327, 0.7638, -0.914200000, -2.2000; ...
'Mo', 'Molybdenum', 42, 97, 5/2, 2.8463, 0.00349, 0.7799, -0.933500000, 25.5000; ...
'Tc', 'Technetium', 43, 99, 9/2, 9.6294, 0.38174, 7.4633, 5.684700000, -12.9000; ...
'Ru', 'Ruthenium', 44, 99, 5/2, 1.9553, 0.00113, 0.5358, -0.641300000, 7.9000; ...
'Ru', 'Ruthenium', 44, 101, 5/2, 2.1916, 0.00159, 0.6005, -0.718800000, 45.7000; ...
'Rh', 'Rhodium', 45, 103, 1/2, 1.3477, 0.00003, 0.0317, -0.088400000, 0.0000; ...
'Pd', 'Palladium', 46, 105, 5/2, 1.9570, 0.00113, 0.5364, -0.642000000, 66.0000; ...
'Ag', 'Silver', 47, 107, 1/2, 1.7331, 0.00007, 0.0407, -0.113679600, 0.0000; ...
'Ag', 'Silver', 47, 109, 1/2, 1.9924, 0.00010, 0.0468, -0.130690600, 0.0000; ...
'Cd', 'Cadmium', 48, 111, 1/2, 9.0692, 0.00966, 0.2130, -0.594886100, 0.0000; ...
'Cd', 'Cadmium', 48, 113, 1/2, 9.4871, 0.01106, 0.2228, -0.622300900, 0.0000; ...
'In', 'Indium', 49, 113, 9/2, 9.3655, 0.35121, 7.2588, 5.528900000, 79.9000; ...
'In', 'Indium', 49, 115, 9/2, 9.3856, 0.35348, 7.2744, 5.540800000, 81.0000; ...
'Sn', 'Tin', 50, 115, 1/2, 14.0077, 0.03561, 0.3290, -0.918830000, 0.0000; ...
'Sn', 'Tin', 50, 117, 1/2, 15.2610, 0.04605, 0.3584, -1.001040000, 0.0000; ...
'Sn', 'Tin', 50, 119, 1/2, 15.9660, 0.05273, 0.3750, -1.047280000, 0.0000; ...
'Sb', 'Antimony', 51, 121, 5/2, 10.2551, 0.16302, 2.8100, 3.363400000, -36.0000; ...
'Sb', 'Antimony', 51, 123, 7/2, 5.5532, 0.04659, 2.7389, 2.549800000, -49.0000; ...
'Te', 'Tellurium', 52, 123, 1/2, 11.2349, 0.01837, 0.2639, -0.736947800, 0.0000; ...
'Te', 'Tellurium', 52, 125, 1/2, 13.5454, 0.03220, 0.3181, -0.888505100, 0.0000; ...
'I', 'Iodine', 53, 127, 5/2, 8.5778, 0.09540, 2.3504, 2.813273000, -71.0000; ...
'Xe', 'Xenon', 54, 129, 1/2, 11.8604, 0.02162, 0.2786, -0.777976300, 0.0000; ...
'Xe', 'Xenon', 54, 131, 3/2, 3.5159, 0.00282, 0.4129, 0.691861900, -11.4000; ...
'Cs', 'Cesium', 55, 133, 7/2, 5.6234, 0.04838, 2.7735, 2.582025000, -0.3430; ...
'Ba', 'Barium', 56, 135, 3/2, 4.2582, 0.00500, 0.5001, 0.837943000, 16.0000; ...
'Ba', 'Barium', 56, 137, 3/2, 4.7634, 0.00700, 0.5594, 0.937365000, 24.5000; ...
'La', 'Lanthanum', 57, 138, 5, 5.6615, 0.09404, 5.3188, 3.713646000, 45.0000; ...
'La', 'Lanthanum', 57, 139, 7/2, 6.0612, 0.06058, 2.9895, 2.783045500, 20.0000; ...
'Ce', 'Cerium', 58, 137, 3/2, 4.8800, 0.00752, 0.5729, 0.960000000, 0.0000; ...
'Ce', 'Cerium', 58, 139, 3/2, 5.3900, 0.01012, 0.6326, 1.060000000, 0.0000; ...
'Ce', 'Cerium', 58, 141, 7/2, 2.3700, 0.00364, 1.1708, 1.090000000, 0.0000; ...
'Pr', 'Praseodymium', 59, 141, 5/2, 13.0359, 0.33483, 3.5720, 4.275400000, -5.9000; ...
'Nd', 'Neodymium', 60, 143, 7/2, 2.3190, 0.00339, 1.1440, -1.065000000, -63.0000; ...
'Nd', 'Neodymium', 60, 145, 7/2, 1.4290, 0.00079, 0.7047, -0.656000000, -33.0000; ...
'Pm', 'Promethium', 61, 143, 5/2, 11.5900, 0.23510, 3.1748, 3.800000000, 0.0000; ...
'Pm', 'Promethium', 61, 147, 7/2, 5.6200, 0.04827, 2.7714, 2.580000000, 74.0000; ...
'Sm', 'Samarium', 62, 147, 7/2, 1.7748, 0.00152, 0.8753, -0.814900000, -26.0000; ...
'Sm', 'Samarium', 62, 149, 7/2, 14631.0000, 0.00085, 0.7216, -0.671800000, 7.4000; ...
'Eu', 'Europium', 63, 151, 5/2, 10.5856, 0.17929, 2.9006, 3.471800000, 90.3000; ...
'Eu', 'Europium', 63, 153, 5/2, 4.6745, 0.01544, 1.2809, 1.533100000, 241.0000; ...
'Gd', 'Gadolinium', 64, 155, 3/2, 1.3120, 0.00015, 0.1541, -0.258200000, 127.0000; ...
'Gd', 'Gadolinium', 64, 157, 3/2, 1.7200, 0.00033, 0.2020, -0.338500000, 135.0000; ...
'Tb', 'Terbium', 65, 159, 3/2, 10.2300, 0.06945, 1.2019, 2.014000000, 143.2000; ...
'Dy', 'Dysprosium', 66, 161, 5/2, 1.4654, 0.00048, 0.4015, -0.480600000, 250.7000; ...
'Dy', 'Dysprosium', 66, 163, 5/2, 2.0508, 0.00130, 0.5619, 0.672600000, 265.0000; ...
'Ho', 'Holmium', 67, 165, 7/2, 9.0883, 0.20423, 4.4825, 4.173000000, 358.0000; ...
'Er', 'Erbium', 68, 167, 7/2, 1.2281, 0.00050, 0.6057, -0.563900000, 356.5000; ...
'Tm', 'Thulium', 69, 169, 1/2, 3.5310, 0.00057, 0.0829, -0.231600000, 0.0000; ...
'Yb', 'Ytterbium', 70, 171, 1/2, 7.5261, 0.00552, 0.1768, 0.493670000, 0.0000; ...
'Yb', 'Ytterbium', 70, 173, 5/2, 2.0730, 0.00135, 0.5680, -0.679890000, 280.0000; ...
'Lu', 'Lutetium', 71, 175, 7/2, 4.8626, 0.03128, 2.3983, 2.232700000, 349.0000; ...
'Lu', 'Lutetium', 71, 176, 7, 3.4510, 0.03975, 6.0516, 3.169000000, 497.0000; ...
'Hf', 'Hafnium', 72, 177, 7/2, 1.7282, 0.00140, 0.8524, 0.793500000, 336.5000; ...
'Hf', 'Hafnium', 72, 179, 9/2, 1.0856, 0.00055, 0.8414, -0.640900000, 379.3000; ...
'Ta', 'Tantalum', 73, 180, 9, 4.0870, 0.10610, 11.5175, 4.825000000, 0.0000; ...
'Ta', 'Tantalum', 73, 181, 7/2, 5.1627, 0.03744, 2.5463, 2.370500000, 317.0000; ...
'W', 'Tungsten', 74, 183, 1/2, 1.7957, 0.00008, 0.0422, 0.117784800, 0.0000; ...
'Re', 'Rhenium', 75, 185, 5/2, 9.7176, 0.13870, 2.6627, 3.187100000, 218.0000; ...
'Re', 'Rhenium', 75, 187, 5/2, 9.8170, 0.14300, 2.6900, 3.219700000, 207.0000; ...
'Os', 'Osmium', 76, 187, 1/2, 0.9856, 0.00001, 0.0231, 0.064651890, 0.0000; ...
'Os', 'Osmium', 76, 189, 3/2, 3.3536, 0.00244, 0.3938, 0.659933000, 85.6000; ...
'Ir', 'Iridium', 77, 191, 3/2, 0.7658, 0.00003, 0.0899, 0.150700000, 81.6000; ...
'Ir', 'Iridium', 77, 191, 3/2, 0.8319, 0.00004, 0.0977, 0.163700000, 75.1000; ...
'Pt', 'Platinum', 78, 195, 1/2, 9.2922, 0.01039, 0.2182, 0.609520000, 0.0000; ...
'Au', 'Gold', 79, 197, 3/2, 0.7406, 0.00003, 0.0870, 0.145746000, 54.7000; ...
'Hg', 'Mercury', 80, 199, 1/2, 7.7123, 0.00594, 0.1811, 0.505885500, 0.0000; ...
'Hg', 'Mercury', 80, 201, 3/2, 2.8469, 0.00149, 0.3343, -0.560225700, 38.6000; ...
'Tl', 'Thallium', 81, 203, 1/2, 24.7316, 0.19598, 0.5809, 1.622257900, 0.0000; ...
'Tl', 'Thallium', 81, 205, 1/2, 24.9749, 0.20182, 0.5866, 1.638214600, 0.0000; ...
'Pb', 'Lead', 82, 207, 1/2, 9.0340, 0.00955, 0.2122, 0.592580000, 0.0000; ...
'Bi', 'Bismuth', 83, 209, 9/2, 6.9630, 0.14433, 5.3967, 4.110600000, 51.6000; ...
'Po', 'Polonium', 84, 209, 1/2, 11.7000, 0.02096, 0.2757, 0.770000000, 0.0000; ...
'Rn', 'Radon', 86, 211, 1/2, 9.1600, 0.00997, 0.2152, 0.601000000, 0.0000; ...
'Fr', 'Francium', 87, 223, 3/2, 5.9500, 0.01362, 0.6982, 1.170000000, 117.0000; ...
'Ra', 'Radium', 88, 223, 3/2, 1.3746, 0.00017, 0.1614, 0.270500000, 125.0000; ...
'Ra', 'Radium', 88, 225, 1/2, 11.1870, 0.01814, 0.2627, -0.733800000, 0.0000; ...
'Ac', 'Actinium', 89, 227, 3/2, 5.6000, 0.01131, 0.6564, 1.100000000, 170.0000; ...
'Th', 'Thorium', 90, 229, 5/2, 1.4000, 0.00042, 0.3843, 0.460000000, 430.0000; ...
'Pa', 'Protactinium', 91, 231, 3/2, 10.2000, 0.06903, 1.1995, 2.010000000, -172.0000; ...
'U', 'Uranium', 92, 235, 7/2, 0.8300, 0.00015, 0.4082, -0.380000000, 493.6000; ...
'Np', 'Neptunium', 93, 237, 5/2, 9.5700, 0.13264, 2.6234, 3.140000000, 388.6000; ...
'Pu', 'Plutonium', 94, 239, 1/2, 3.0900, 0.00038, 0.0727, 0.203000000, 0.0000; ...
'Am', 'Americium', 95, 243, 5/2, 4.6000, 0.01446, 1.2532, 1.500000000, 421.0000; ...
};

%% Find isotopes
if nargin == 0
    % Return the whole table
    T = GetDataFromTheTable(TheTable);

 else
    T = [];
    for j = 1:nargin
        curIn = varargin{j};
        if ischar(curIn)
            nn = isstrprop(curIn, 'alpha');
            curElem = curIn(nn);

            % Find the element symbol
            ie = strmatch(curElem, {TheTable{:, 1}}, 'exact');

            % Isotope mass number
            nn = isstrprop(curIn,  'digit');
            curMass = curIn;
            curMass(~nn) = ' ';
            curMass = strtok(curMass);
            if ~isempty(curMass)
                curMass = str2double(curMass);
                if ~isnan(curMass)
                    im = find(curMass == [TheTable{:, 4}]);
                    ie = intersect(ie, im);
                end
            end

            % Get the isotop(s) properties
            if isempty(ie)
                warning('MATLAB:isotopes:CanNotFindTheElement', ...
                        ['Can not find the element: ' curIn]);
                curT = GetDataFromTheTable;
                curT.name = '<< not found >>';
                curT.isotop = curIn;
                curT.mass = curMass;
                T = [T; curT(:)];
            else
                curT = GetDataFromTheTable(TheTable, ie);
                T = [T; curT(:)];
            end

        else
            error('Input argument(s) should be char, i.e. ''19F''');
        end
    end
end

%
function T = GetDataFromTheTable(TheTable, TblInd)
%Returns data in a structure

% Factor to Hz
fctHz = 1e6;

% Create the output structure template
StructTmpl = struct('name', '', 'isotop', '', 'Z', 0, 'mass', 0, 'I', 0, ...
                    'gamma', 0, 'ResFreq', 0, 'RelSensB', 0, ...
                    'RelSensF', 0, 'u', 0, 'Q', 0);
if nargin < 1
    T = StructTmpl;
    return;

elseif (nargin < 2)
    TblInd = (1:size(TheTable, 1));

elseif isempty(TblInd)
    T = StructTmpl;
    return;

end

nIndNum = length(TblInd);
T = repmat(StructTmpl, nIndNum, 1);
for i = 1:nIndNum
    j = TblInd(i);
    T(i).name = TheTable{j, 2};
    T(i).isotop = sprintf('%.0d%s', TheTable{j, 4}, TheTable{j, 1});
    T(i).Z = TheTable{j, 3};
    T(i).mass = TheTable{j, 4};
    T(i).I = TheTable{j, 5};
    T(i).gamma = 2*pi*fctHz*TheTable{j, 6};
    T(i).ResFreq = TheTable{j, 6}*fctHz;
    T(i).RelSensB = TheTable{j, 7};
    T(i).RelSensF = TheTable{j, 8};
    T(i).u = TheTable{j, 9};
    T(i).Q = TheTable{j, 10};
end


function [f,Ls]=ifilterbank(c,g,a,varargin)
%IFILTERBANK  Filter bank inversion
%   Usage:  f=ifilterbank(c,g,a);
%
%   `ifilterbank(c,g,a)` synthesizes a signal *f* from the coefficients *c*
%   using the filters stored in *g* for a channel subsampling rate of *a* (the
%   hop-size). The coefficients has to be in the format returned by
%   either |filterbank| or |ufilterbank|.
%
%   The filter format for *g* is the same as for |filterbank|.
%
%   If perfect reconstruction is desired, the filters must be the duals
%   of the filters used to generate the coefficients. See the help on
%   |filterbankdual|.
%
%   Additional parameters
%   ---------------------
%
%   'complex' (default), 'real'
%       The 'real' flag indicates that the filters *g* cover only the positive
%       frequencies and does `2*real(f)` to effectivelly mirror the filters to
%       cover also the negative frequencies.
%
%   See also: filterbank, ufilterbank, filterbankdual
%
%   References: bohlfe02

if nargin<3
  error('%s: Too few input parameters.',upper(mfilename));
end;

definput.import={'pfilt'};
definput.keyvals.Ls=[];
definput.flags.complex={'complex','real'};
[flags,kv,Ls]=ltfatarghelper({'Ls'},definput,varargin);

L=filterbanklengthcoef(c,a);

if iscell(c)
  M=numel(c);
else
  M=size(c,2);
end;

[g,asan]=filterbankwin(g,a,L,'normal');

if numel(g)~=M
  error(['%s: Number of filters must be equal to the number of channels ' ...
            'of coefficients.'],upper(mfilename));
end

 if size(a,1)>1
   if  size(a,1)~=M
     error(['%s: The number of entries in "a" must match the number of ' ...
            'filters.'],upper(mfilename));
   end;
 end;

g = comp_filterbank_pre(g,asan,L,kv.crossover);

% Handle ufilterbank output format here
if isnumeric(c)
   ctmp = c;
   c = cell(M,1);
   for m=1:M
      c{m}=squeeze(ctmp(:,m,:));
   end;
end

f = comp_ifilterbank(c,g,asan,L);

if flags.do_real
    f = 2*real(f);
end

% Cut or extend f to the correct length, if desired.
if ~isempty(Ls)
  f=postpad(f,Ls);
else
  Ls=L;
end;


%PRM Probabilistic RoadMap navigation class
%
% A concrete subclass of the abstract Navigation class that implements the
% probabilistic roadmap navigation algorithm over an occupancy grid.  This
% performs goal independent planning of roadmaps, and at the query stage
% finds paths between specific start and goal points.
%
% Methods::
%
% plan         Compute the roadmap
% path         Compute a path to the goal
% visualize    Display the obstacle map (deprecated)
% plot         Display the obstacle map
% display      Display the parameters in human readable form
% char         Convert to string
%
% Example::
%
%        load map1              % load map
%        goal = [50,30];        % goal point
%        start = [20, 10];      % start point
%        prm = PRM(map);        % create navigation object
%        prm.plan()             % create roadmaps
%        prm.path(start, goal)  % animate path from this start location
%
% References::
%
% - Probabilistic roadmaps for path planning in high dimensional configuration spaces,
%   L. Kavraki, P. Svestka, J. Latombe, and M. Overmars,
%   IEEE Transactions on Robotics and Automation, vol. 12, pp. 566-580, Aug 1996.
% - Robotics, Vision & Control, Section 5.2.4,
%   P. Corke, Springer 2011.
%
% See also Navigation, DXform, Dstar, PGraph.

% Copyright (C) 1993-2015, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com

% Peter Corke 8/2009.

classdef PRM < Navigation

    properties
        npoints         % number of sample points
        distthresh      % distance threshold, links between vertices
                        % must be less than this.

        graph           % graph Object representing random nodes

        vgoal           % index of vertex closest to goal
        vstart          % index of vertex closest to start
        localGoal       % next vertex on the roadmap
        localPath       % set of points along path to next vertex
        gpath           % list of vertices between start and goal
    end

    methods

        % constructor
        function prm = PRM(varargin)
            %PRM.PRM Create a PRM navigation object
            %
            % P = PRM(MAP, options) is a probabilistic roadmap navigation
            % object, and MAP is an occupancy grid, a representation of a
            % planar world as a matrix whose elements are 0 (free space) or 1
            % (occupied).
            %
            % Options::
            %  'npoints',N      Number of sample points (default 100)
            %  'distthresh',D   Distance threshold, edges only connect vertices closer
            %                   than D (default 0.3 max(size(occgrid)))
            %
            % Other options are supported by the Navigation superclass.
            %
            % See also Navigation.Navigation.

            % invoke the superclass constructor, it handles some options
            prm = prm@Navigation(varargin{:});

            % create an empty 2D graph
            prm.graph = PGraph(2);

            % parse out PRM specific options and save in the navigation object
            opt.npoints = 100;
            opt.distthresh = 0.3*max(size(prm.occgrid));
            [opt,args] = tb_optparse(opt, varargin);
            prm.npoints = opt.npoints;
            prm.distthresh = opt.distthresh;
        end

        function plan(prm)
        %PRM.plan Create a probabilistic roadmap
        %
        % P.plan() creates the probabilistic roadmap by randomly
        % sampling the free space in the map and building a graph with
        % edges connecting close points.  The resulting graph is kept
        % within the object.

        % build a graph over the free space
            prm.message('create the graph');

            prm.graph.clear();  % empty the graph
            create_roadmap(prm);  % build the graph
        end

        function p = path(prm, start, goal)
        %PRM.path Find a path between two points
        %
        % P.path(START, GOAL) finds and displays a path from START to GOAL
        % which is overlaid on the occupancy grid.
        %
        % X = P.path(START) returns the path (2xM) from START to GOAL.

            if nargin < 3
                error('must specify start and goal');
            end

            % set the goal coordinate
            prm.goal = goal;

            % invoke the superclass path function, which iterates on our
            % next method
            if nargout == 0
                path@Navigation(prm, start);
            else
                p = path@Navigation(prm, start);
            end
        end

        % Handler invoked by Navigation.path() to start the navigation process
        %
        %   - find a path through the graph
        %   - determine vertices closest to start and goal
        %   - find path to first vertex
        function navigate_init(prm, start)

            % find the vertex closest to the goal
            prm.vgoal = prm.graph.closest(prm.goal);

            % find the vertex closest to the start
            prm.vstart = prm.graph.closest(start);

            % are the vertices connected?
            if prm.graph.component(prm.vstart) ~= prm.graph.component(prm.vgoal)
                error('PRM:plan:nopath', 'PRM: start and goal not connected: rerun the planner');
            end

            % find a path through the graph
            prm.message('planning path through graph');
            prm.graph.goal(prm.vgoal);   % set the goal
            prm.gpath = prm.graph.path(prm.vstart);

            % the path is a list of nodes from vstart to vgoal
            % discard the first vertex, since we plan a local path to it
            prm.gpath = prm.gpath(2:end);

            % start the navigation engine with a path to the nearest vertex
            prm.graph.highlight_node(prm.vstart);

            prm.localPath = bresenham(start, prm.graph.coord(prm.vstart));
            prm.localPath = prm.localPath(2:end,:);
        end

        % Invoked for each step on the path by path() method.
        function n = next(prm, p)

            if all(p(:) == prm.goal)
                n = [];     % signal that we've arrived
                return;
            end

            % we take the next point from the localPath
            if numrows(prm.localPath) == 0
                % local path is consumed, move to next vertex
                if isempty(prm.gpath)
                    % we have arrived at the goal vertex
                    % make the path from this vertex to the goal coordinate
                    prm.localPath = bresenham(p, prm.goal);
                    prm.localPath = prm.localPath(2:end,:);
                    prm.localGoal = [];
                else
                    % set local goal to next vertex in gpath and remove it from the list
                    prm.localGoal = prm.gpath(1);
                    prm.gpath = prm.gpath(2:end);

                    % compute local path to the next vertex
                    prm.localPath = bresenham(p, prm.graph.coord(prm.localGoal));
                    prm.localPath = prm.localPath(2:end,:);
                    prm.graph.highlight_node(prm.localGoal);
                end
            end

            n = prm.localPath(1,:)';     % take the first point
            prm.localPath = prm.localPath(2:end,:); % and remove from the path
        end

        function s = char(prm)
        %PRM.char  Convert to string
        %
        % P.char() is a string representing the state of the PRM
        % object in human-readable form.
        %
        % See also PRM.display.

            % invoke the superclass char() method
            s = char@Navigation(prm);

            % add PRM specific stuff information
            s = char(s, sprintf('  graph size: %d', prm.npoints));
            s = char(s, sprintf('  dist thresh: %f', prm.distthresh));
            s = char(s, char(prm.graph) );
        end

        function plot(prm, varargin)
        %PRM.plot Visualize navigation environment
        %
        % P.plot() displays the occupancy grid with an optional distance field.
        %
        % Options::
        %  'goal'            Superimpose the goal position if set
        %  'nooverlay'       Don't overlay the PRM graph

            opt.nooverlay = false;
            [opt,args] = tb_optparse(opt, varargin);

            % display the occgrid
            plot@Navigation(prm, args{:});

            if ~opt.nooverlay
                hold on
                prm.graph.plot()%varargin{:});
                hold off
            end
        end

    end % method

    methods (Access='protected')
    % private methods
        % create the roadmap
        function create_roadmap(prm)

            for j=1:prm.npoints
                % pick a point not in obstacle
                while true
                    x = prm.randi(numcols(prm.occgrid));
                    y = prm.randi(numrows(prm.occgrid));
                    if prm.occgrid(y,x) == 0
                        break;
                    end
                end
                new = [x; y];

                vnew = prm.graph.add_node(new);

                [d,v] = prm.graph.distances(new);
                % test neighbours in order of increasing distance
                for i=1:length(d)
                    if v(i) == vnew
                        continue;
                    end
                    if d(i) > prm.distthresh
                        continue;
                    end
                    if ~prm.testpath(new, prm.graph.coord(v(i)))
                        continue;
                    end
                    prm.graph.add_edge(vnew, v(i));
                end
            end
        end

        % test the path from p1 to p2 is entirely in free space
        function c = testpath(prm, p1, p2)
            p = bresenham(p1, p2);

            for pp=p'
                if prm.occgrid(pp(2), pp(1)) > 0
                    c = false;
                    return;
                end
            end
            c = true;
        end

    end % private methods

end % classdef


function f_x = ParFor5(in1)
%PARFOR5
%    F_X = PARFOR5(IN1)

%    This function was generated by the Symbolic Math Toolbox version 8.2.
%    31-Mar-2020 16:52:33

r = in1(:,1);
s = in1(:,13);
u = in1(:,19);
ut = in1(:,20);
ux = in1(:,21);
uxx = in1(:,22);
uy = in1(:,23);
uyy = in1(:,24);
z = in1(:,7);
t2 = u.^2;
f_x = r.*-4.845016406907234+s.*6.96612441301113+ut.*5.457984690783633e-1-ux.*1.530748504418966e-2+uxx.*2.135644249305187-uy.*3.570878181824355e-2+uyy.*5.02823932467436-z.*1.323504040227272e2+r.*u.*6.191151455437648-s.*u.*9.105578580027213-t2.*u.*1.077295023277402e2+u.*ut.*5.65024831920482e-2+u.*ux.*1.830355084143775e-2-u.*uxx.*4.132096419489244+u.*uy.*4.442896435307375e-2-u.*uyy.*6.867807677976089+u.*z.*1.83605552916415e2+4.028421339788474e1;


function [kernel,rawkernel] = calibrate(obj, AtA, nCoil, coil)

sampling = ones([obj.kernelSize(1:2),nCoil]);

dummyK = zeros(obj.kernelSize(1),obj.kernelSize(2),nCoil); dummyK((end+1)/2,(end+1)/2,coil) = 1;
idxY = find(dummyK);
sampling(idxY) = 0;
idxA = find(sampling);

Aty = AtA(:,idxY); Aty = Aty(idxA); % correlation values to target point, take complete neighbourhood and not just aquired ones
AtA = AtA(idxA,:); AtA =  AtA(:,idxA); % kick out the searched point

kernel = sampling*0;

lambda = norm(AtA,'fro')/size(AtA,1)*obj.calibTyk;

rawkernel = inv(AtA + eye(size(AtA))*lambda)*Aty; % grappa weighting values
kernel(idxA) = rawkernel;

end


%% clear all workspace variables
clear ;

%% this is where all the algorithm parameters are
addpath(genpath('./input_data'));
% this is where all the problems are defined
addpath(genpath('./problemdef'));
% this is where all the legacy rng related stuffs are.
% THIS IS NOT VECTORIZED, SO DO NOT USE, SLOW !!!
addpath(genpath('./rand'));

%% global variables that may be used here
global popsize ;
global nreal ;
global nbin ;
global nbits ;
global nobj ;
global ncon ;
global ngen ;

%% load algorithm parameters
load_input_data('input_data/zdt4.in');
pprint('\nInput data successfully entered, now performing initialization\n\n');

%% for debugging puproses
% global min_realvar ;
% global max_realvar ;
% popsize = 24 ;
% nreal = 3 ;
% ngen = 400 ;
% min_realvar = min_realvar(1:nreal);
% max_realvar = max_realvar(1:nreal);
% global min_binvar ;
% global max_binvar ;
% nbin = 2;
% nbits = [3;3];
% min_binvar = [0;0];
% max_binvar = [5;5];

if(nreal > 0)
    obj_col = nreal + 1 : nreal + nobj ;
elseif(nbin > 0)
    obj_col = sum(nbits) + 1 : sum(nbits) + nobj ;
end

%% this is the objective function that we are going to optimize
obj_func = @zdt4 ;

%% allocate memory for pops
if(nreal > 0)
    child_pop = zeros(popsize, nreal + nobj + ncon + 3);
    mixed_pop = zeros(2 * popsize, nreal + nobj + ncon + 3);
elseif(nbin > 0)
    child_pop = zeros(popsize, sum(nbits) + nobj + ncon + 3);
    mixed_pop = zeros(2 * popsize, sum(nbits) + nobj + ncon + 3);
end

%% you need to warm-up the cache if you need to do profiling
% for k = 1:50000
%     tic(); elapsed = toc();
% end

%% start nsga2
tic;
% initialize population
parent_pop = initialize_pop(90);
pprint('Initialization done, now performing first generation\n\n');
parent_pop = evaluate_pop(parent_pop, obj_func);
parent_pop = assign_rank_and_crowding_distance(parent_pop);

do_plot = false ;
% plot the pareto front
if(do_plot); show_plot(1, parent_pop, false, [1 2 3]); end;

do_save = false ;
% save the current pop
if(do_save); save_pop(1, parent_pop, false); end;

for i = 2:ngen
    fprintf('gen = %d\n', i)
    child_pop = selection(parent_pop, child_pop);
    child_pop = mutation_pop(child_pop);
    child_pop(:,obj_col) = 0;
    child_pop = evaluate_pop(child_pop, obj_func);
    mixed_pop = merge_pop(parent_pop, child_pop);
    parent_pop = fill_nondominated_sort(mixed_pop);

    % plot the current pareto front
    % if(do_plot)
    %   show_plot(i, parent_pop, false, [1 2 3], [], ...
    %       [0.0, 1.0], [0.0, 1.0]);
    % end;
    if(do_plot); show_plot(i, parent_pop, false, [1 2 3]); end;

    % save the current pop
    if(do_save); save_pop(i, parent_pop, false); end;
end
toc;
fprintf('Generations finished, now reporting solutions\n');

if(do_save)
    % save the final pop
    save_pop(i, parent_pop, false, 'final');
    % save the best pop
    save_pop(i, parent_pop, false, 'best');
end
fprintf('Routine successfully exited\n');


function prob = logitFn(paramS,doseBinsC,volHistC)
% function prob = logitFn(paramS,doseBinsC,volHistC);
% This function returns the outcomes probabilities based on logistic fit.
%----------------------------------------------------------------------------
% INPUT parameters:
% paramS:
% Specify the variates using the following format:
% paramS.field1.val = 1;
% paramS.field1.weight = 2;
% paramS.field1.val can also be a string, in which case it will act as a
% function name. This function must have the signature
% x(doseBinsV,volHistV).
%---------------------------------------------------------------------------
% APA, 02/15/2017
% AI, 02/21/17
% AI , 11/14/17  Created separate function for appelt model
% AI, 11/16/17   Copy number of fractions, abRatio to any sub-parameter structures

%Extract parameters and corresponding weights
[weight,x] = getParCoeff(paramS,'weight',doseBinsC,volHistC);
%Compute TCP/NTCP
gx = sum(weight.*x);
prob = 1 / (1 + exp(-gx));

%%--- Functions to extract model parameters and weights ----
    function [coeff,par] = getParCoeff(paramS,fieldName,doseBinsC,volHistC)

        %Extract relevant parameters
        genFieldC = fields(paramS);
        for i = 1:numel(genFieldC)
            if strcmpi(genFieldC{i},'structures')
                structS = paramS.(genFieldC{i});
                structListC = fieldnames(structS);
                for j = 1:length(structListC)
                    strParamS = structS.(structListC{j});
                    strParamListC = fieldnames(strParamS);
                    for k = 1 : numel(strParamListC)
                        if isfield(strParamS.(strParamListC{k}),'cteg') |  isfield(strParamS.(strParamListC{k}),'weight')
                            parName = [structListC{j},strParamListC{k}];
                            keepParS.(parName) = strParamS.(strParamListC{k});
                        end
                    end
                end
            else
                 if isfield(paramS.(genFieldC{i}),'cteg') |  isfield(paramS.(genFieldC{i}),'weight')
                     parName = genFieldC{i};
                     keepParS.(parName) = paramS.(genFieldC{i});
                 end
            end
        end

       %Compute parameters, extract coefficients
        keepParC = fieldnames(keepParS);
        numStr = 0;
        par = zeros(1,length(keepParC));
        coeff = zeros(1,length(keepParC));
        for n = 1:length(keepParC)
            coeff(n) = keepParS.(keepParC{n}).(fieldName);
            if isnumeric(keepParS.(keepParC{n}).val)
               par(n) = keepParS.(keepParC{n}).val;
            else
                if ~iscell(doseBinsC)  %For single-structure models
                    doseBinsV = doseBinsC;
                    volHistV = volHistC;
                else
                numStr = numStr+1;
                doseBinsV = doseBinsC{numStr};
                volHistV = volHistC{numStr};
                end
                if ~isfield(keepParS.(keepParC{n}),'params')
                    par(n) = eval([keepParS.(keepParC{n}).val,...
                        '(doseBinsV, volHistV)']);
                else
                    %Copy number fo fractions, abRatio
                    if isfield(paramS,'numFractions')
                        keepParS.(keepParC{n}).params.numFractions.val = paramS.numFractions.val;
                    end
                    if isfield(paramS,'abRatio')
                        keepParS.(keepParC{n}).params.abRatio.val = paramS.abRatio.val;
                    end
                    par(n) = eval([keepParS.(keepParC{n}).val,...
                        '(doseBinsV, volHistV,keepParS.(keepParC{n}).params)']);
                end
            end
        end
    end

end


function [ a, ipvt, rcond ] = chico ( a, lda, n )

%*****************************************************************************80
%
%% CHICO factors a complex hermitian matrix and estimates its condition.
%
%  Discussion:
%
%    If RCOND is not needed, CHIFA is slightly faster.
%
%    To solve A*X = B, follow CHICO by CHISL.
%
%    To compute inverse(A)*C, follow CHICO by CHISL.
%
%    To compute inverse(A), follow CHICO by CHIDI.
%
%    To compute determinant(A), follow CHICO by CHIDI.
%
%    To compute inertia(A), follow CHICO by CHIDI.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 May 2007
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Jim Bunch, Cleve Moler, Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979,
%    ISBN13: 978-0-898711-72-1,
%    LC: QA214.L56.
%
%  Parameters:
%
%    Input, complex A(LDA,N); on input, the hermitian matrix to be
%    factored.
%
%    Input, integer LDA, the leading dimension of A.
%
%    Input, integer N, the order of the matrix.
%
%    Output, complex A(LDA,N); a block diagonal matrix and the multipliers
%    which were used to obtain it.  The factorization can be written
%    A = U*D*hermitian(U) where U is a product of permutation and unit
%    upper triangular matrices, hermitian(U) is the conjugate transpose
%    of U, and D is block diagonal with 1 by 1 and 2 by 2 blocks.
%    Only the diagonal and upper triangle are used.
%
%    Output, integer IPVT(N), the pivot indices.
%
%    Output, real RCOND, an estimate of the reciprocal condition of
%    the matrix.  For the system A*X = B, relative perturbations in A and B
%    of size EPSILON may cause relative perturbations in X of size
%    (EPSILON/RCOND).  If RCOND is so small that the logical expression
%      1.0 + RCOND == 1.0
%    is true, then A may be singular to working precision.  In particular,
%    RCOND is zero if exact singularity is detected or the estimate underflows.
%
%  Local Parameters:
%
%    Local, complex Z(N), a work vector whose contents are usually
%    unimportant.  If A is close to a singular matrix, then Z is an
%    approximate null vector in the sense that
%      norm(A*Z) = RCOND * norm(A) * norm(Z).
%

%
%  Find norm of A using only upper half.
%
  for j = 1 : n

    z(j) = scasum ( j, a(1:j,j), 1 );

    for i = 1 : j - 1
      z(i) = real ( z(i) ) + cabs1 ( a(i,j) );
    end

  end

  anorm = 0.0;
  for j = 1 : n
    anorm = max ( anorm, real ( z(j) ) );
  end
%
%  Factor.
%
  [ a, ipvt, info ] = chifa ( a, lda, n );
%
%  RCOND = 1/(norm(A)*(estimate of norm(inverse(A)))).
%
%  Estimate = norm(Z)/norm(Y) where A*Z = Y and A*Y = E.
%
%  The components of E are chosen to cause maximum local
%  growth in the elements of W where U*D*W = E.
%
%  The vectors are frequently rescaled to avoid overflow.
%
%  Solve U*D*W = E.
%
  ek = 1.0;
  z(1:n) = 0.0;

  k = n;

  while ( 0 < k )

    if ( ipvt(k) < 0 )
      ks = 2;
    else
      ks = 1;
    end

    kp = abs ( ipvt(k) );
    kps = k + 1 - ks;

    if ( kp ~= kps )
      t      = z(kps);
      z(kps) = z(kp);
      z(kp)  = t;
    end

    if ( cabs1 ( z(k) ) ~= 0.0 )
      ek = csign1 ( ek, z(k) );
    end

    z(k) = z(k) + ek;
    z(1:k-ks) = z(1:k-ks) + z(k) * transpose ( a(1:k-ks,k) );

    if ( ks ~= 1 )

      if ( cabs1 ( z(k-1) ) ~= 0.0 )
        ek = csign1 ( ek, z(k-1) );
      end

      z(k-1) = z(k-1) + ek;
      z(1:k-ks) = z(1:k-ks) + z(k-1) * a(1:k-ks,k-1);

    end

    if ( ks ~= 2 )

      if ( cabs1 ( a(k,k) ) < cabs1 ( z(k) ) )
        s = cabs1 ( a(k,k) ) / cabs1 ( z(k) );
        z(1:n) = z(1:n) * s;
        ek = s * ek;
      end

      if ( cabs1 ( a(k,k) ) ~= 0.0 )
        z(k) = z(k) / a(k,k);
      else
        z(k) = 1.0;
      end

    else

      ak = a(k,k) / conj ( a(k-1,k) );
      akm1 = a(k-1,k-1) / a(k-1,k);
      bk = z(k) / conj ( a(k-1,k) );
      bkm1 = z(k-1) / a(k-1,k);
      denom = ak * akm1 - 1.0;
      z(k) = ( akm1 * bk - bkm1 ) / denom;
      z(k-1) = ( ak * bkm1 - bk ) / denom;

    end

    k = k - ks;

  end

  s = 1.0 / scasum ( n, z, 1 );
  z(1:n) = z(1:n) * s;
%
%  Solve hermitian(U) * Y = W.
%
  k = 1;

  while ( k <= n )

    if ( ipvt(k) < 0 )
      ks = 2;
    else
      ks = 1;
    end

    if ( k ~= 1 )

      z(k) = z(k) + z(1:k-1) * conj ( a(1:k-1,k) );

      if ( ks == 2 )
        z(k+1) = z(k+1) + z(1:k-1) * conj ( a(1:k-1,k+1) );
      end

      kp = abs ( ipvt(k) );

      if ( kp ~= k )
        t     = z(k);
        z(k)  = z(kp);
        z(kp) = t;
      end

    end

    k = k + ks;

  end

  s = 1.0 / scasum ( n, z, 1 );
  z(1:n) = z(1:n) * s;
  ynorm = 1.0;
%
%  Solve U*D*V = Y.
%
  k = n;

  while ( 0 < k )

    if ( ipvt(k) < 0 )
      ks = 2;
    else
      ks = 1;
    end

    if ( k ~= ks )

      kp = abs ( ipvt(k) );
      kps = k + 1 - ks;

      if ( kp ~= kps )
        t      = z(kps);
        z(kps) = z(kp);
        z(kp)  = t;
      end

      z(1:k-ks) = z(1:k-ks) + z(k) * transpose ( a(1:k-ks,k) );

      if ( ks == 2 )
        z(1:k-ks) = z(1:k-ks) + z(k-1) * a(1:k-ks,k-1);
      end

    end

    if ( ks ~= 2 )

      if ( cabs1 ( a(k,k) ) < cabs1 ( z(k) ) )
        s = cabs1 ( a(k,k) ) / cabs1 ( z(k) );
        z(1:n) = z(1:n) * s;
        ynorm = s * ynorm;
      end

      if ( cabs1 ( a(k,k) ) ~= 0.0 )
        z(k) = z(k) / a(k,k);
      else
        z(k) = 1.0;
      end

    else

      ak = a(k,k) / conj ( a(k-1,k) );
      akm1 = a(k-1,k-1) / a(k-1,k);
      bk = z(k) / conj ( a(k-1,k) );
      bkm1 = z(k-1) / a(k-1,k);
      denom = ak * akm1 - 1.0;
      z(k) = ( akm1 * bk - bkm1 ) / denom;
      z(k-1) = ( ak * bkm1 - bk ) / denom;

    end

    k = k - ks;

  end

  s = 1.0 / scasum ( n, z, 1 );
  z(1:n) = z(1:n) * s;
  ynorm = s * ynorm;
%
%  Solve hermitian(U) * Z = V.
%
  k = 1;

  while ( k <= n )

    if ( ipvt(k) < 0 )
      ks = 2;
    else
      ks = 1;
    end

    if ( k ~= 1 )

      z(k) = z(k) + z(1:k-1) * conj ( a(1:k-1,k) );

      if ( ks == 2 )
        z(k+1) = z(k+1) + z(1:k-1) *  conj ( a(1:k-1,k+1) );
      end

      kp = abs ( ipvt(k) );

      if ( kp ~= k )
        t     = z(k);
        z(k)  = z(kp);
        z(kp) = t;
      end

    end

    k = k + ks;

  end
%
%  Make ZNORM = 1.
%
  s = 1.0 / scasum ( n, z, 1 );
  z(1:n) = z(1:n) * s;
  ynorm = s * ynorm;

  if ( anorm ~= 0.0 )
    rcond = ynorm / anorm;
  else
    rcond = 0.0;
  end

  return
end


function path = grFindGeodesicPath(nodes, edges, ind0, ind1, edgeWeights)
%GRFINDGEODESICPATH Find a geodesic path between two nodes in the graph
%
%   PATH = grFindGeodesicPath(NODES, EDGES, NODE1, NODE2, WEIGHTS)
%   NODES and EDGES defines the graph, NODE1 and NODE2 are indices of the
%   node extremities, and WEIGHTS is the set of weights associated to each
%   edge.
%   The function returns a set of edge indices.
%
%
%   See also
%   grFindMaximalLengthPath
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2011-05-22,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

% ensure weights are defined
if ~exist('edgeWeights', 'var')
    edgeWeights = ones(size(edges, 1), 1);
end

% check indices limits
nNodes = size(nodes, 1);
if max(ind0) > nNodes
    error('Start index exceed number of nodes in the graph');
end
if max(ind1) > nNodes
    error('End index exceed number of nodes in the graph');
end

% find a vertex opposite to the first extremity
dists = grPropagateDistance(nodes, edges, ind0, edgeWeights);

% iterate on neighbors of current node: choose next neighbor with smallest
% cumulated weight, until we are back on source node
path = [];
while true
    % find neighbor with lowest cumulated distance
    neighs = grAdjacentNodes(edges, ind1);
    neighDists = dists(neighs);
    indN = find(neighDists == min(neighDists), 1);
    ind2 = neighs(indN);

    if isempty(ind2)
        warning('graphs:grFindGeodesicPath', ...
            'No neighbor node found for node %d, graph may be not connected', ind1);
        break;
    end

    % add edge index to the path
    indE = find(sum(ismember(edges, [ind1 ind2]), 2) == 2, 1);
    path = [path indE]; %#ok<AGROW>

    % test if path is finished or not
    if ind2 == ind0
        break;
    end
    ind1 = ind2;
end

% reverse path direction
path = path(end:-1:1);


%% Pole Figure Tutorial
%
%%
% This tutorial explains the basic concepts for ananyzing x-ray, synchrotron
% and neutron diffraction pole figure data.
%
%% Import pole figure diffraction data
% Click on <matlab:import_wizard('PoleFigure') Import pole figure data> to
% start the import wizard which is a GUI leading you through the import of
% pole figure data. After finishing the wizard you will end up with a
% script similar to the following one.

% This script was automatically created by the import wizard. You should
% run the whole script or parts of it in order to import your data. There
% is no problem in making any changes to this script.
%
% *Specify Crystal and Specimen Symmetries*

% crystal symmetry for this ZnCuTi data is hexagonal.  Here we define the crystallographic unit cell and how it relates to cartesian xyz axes.
CS = crystalSymmetry('6/mmm', [2.633 2.633 4.8], 'X||a*', 'Y||b', 'Z||c');

% specimen symmetry tells MTEX if a certain symmetry should be present in the plotted pole figures.  The command used here selects triclinic, the most flexible option.
SS = specimenSymmetry('1');

% plotting convention
setMTEXpref('xAxisDirection','north');
setMTEXpref('zAxisDirection','outOfPlane');

%%
% *Specify File Names*

% path to files downloaded with the MTEX package
pname = [mtexDataPath filesep 'PoleFigure' filesep 'ZnCuTi' filesep];

% which pole figure files are to be imported
fname = {...
  [pname 'ZnCuTi_Wal_50_5x5_PF_002_R.UXD'],...
  [pname 'ZnCuTi_Wal_50_5x5_PF_100_R.UXD'],...
  [pname 'ZnCuTi_Wal_50_5x5_PF_101_R.UXD'],...
  [pname 'ZnCuTi_Wal_50_5x5_PF_102_R.UXD'],...
  };

% defocusing correction to compensate for the equipment-dependent loss of intensity at certain angles.
fname_def = {...
  [pname 'ZnCuTi_defocusing_PF_002_R.UXD'],...
  [pname 'ZnCuTi_defocusing_PF_100_R.UXD'],...
  [pname 'ZnCuTi_defocusing_PF_101_R.UXD'],...
  [pname 'ZnCuTi_defocusing_PF_102_R.UXD'],...
  };

%%
% *Specify Miller Indices*

% These correspond to the files loaded, in order.
h = { ...
  Miller(0,0,2,CS),...
  Miller(1,0,0,CS),...
  Miller(1,0,1,CS),...
  Miller(1,0,2,CS),...
  };

%%
% *Import the Data*

% create a Pole Figure variable containing the data
pf = PoleFigure.load(fname,h,CS,SS,'interface','uxd');

% create a defocusing pole figure variable
pf_def = PoleFigure.load(fname_def,h,CS,SS,'interface','uxd');

% correct data by applying the defocusing compensation
pf = correct(pf,'def',pf_def);

%%
% After running the script the variable |pf| is created which contains all
% information about the pole figure data. You may plot the data using the
% command <PoleFigure.plot.html plot>

plot(pf)

%%
% By default pole figures are plotted as intensity-colored dots for every
% data point. There are many options to specify the way pole figures are
% plotted in MTEX. Have a look at the <PoleFigurePlot.html plotting
% section> for more information.
%
% After import make sure that the Miller indices are correctly assigned to
% the pole figures and that the alignment of the specimen coordinate
% system, i.e., X, Y, Z is correct. In case of outliers or misaligned data,
% you may want to correct your raw data. Have a look at the
% <PoleFigureCorrection.html correction section> for further information.
% MTEX offers several methods correcting pole figure data, e.g.
%
% * rotating pole figures
% * scaling pole figures
% * finding outliers
% * removing specific measurements
% * superposing pole figures
%
% As an example we set all negative intensities to zero

pf(pf.intensities<0) = 0;
plot(pf)

%% ODF Estimation
%
% Once your data is in good shape, i.e. defocusing correction has been
% done and few outliers are left you can reconstruct an ODF out of
% this data. This is done by the command <PoleFigure.calcODF.html
% calcODF>.

odf = calcODF(pf,'silent')

%%
% Note that reconstructing an ODF from pole figure data is a severely ill-
% posed problem, i.e., it does *not* provide a unique solution. A more
% through discussion on the ambiguity of ODF reconstruction from
% pole figure data can be found <PoleFigure2ODFAmbiguity.html here>. As a
% rule of thumb: the more pole figures you have and the more consistent your
% pole figure data the better your reconstructed ODF will be.
%
% To check how well your reconstructed ODF fits the measured pole figure
% data use

figure;plotPDF(odf,pf.h)

%%
% Compare the recalculated pole figures with the measured data.
% A quantitative measure for the fitting is the so called RP value. They
% can be computed for each imported pole figure with

calcError(odf,pf)

%%
% In the case of a bad fit, you may want to tweak the reconstruction
% algorithm. See <PoleFigure2ODF.html here> for more information.

%% Visualize the ODF
% Finally one can plot the resulting ODF

plot(odf)
mtexColorMap LaboTeX


function tapas_hgf_plotTraj(r)
% Plots the estimated or generated trajectories for the HGF perceptual model
% Usage example:  est = tapas_fitModel(responses, inputs); tapas_hgf_plotTraj(est);
%
% --------------------------------------------------------------------------------------------------
% Copyright (C) 2012-2013 Christoph Mathys, TNU, UZH & ETHZ
%
% This file is part of the HGF toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

% Optional plotting of standard deviations (true or false)
plotsd = true;

% Set up display
scrsz = get(0,'screenSize');
outerpos = [0.2*scrsz(3),0.2*scrsz(4),0.8*scrsz(3),0.8*scrsz(4)];
figure(...
    'OuterPosition', outerpos,...
    'Name', 'HGF trajectories');

% Time axis
if size(r.u,2) > 1 && ~isempty(find(strcmp(fieldnames(r.c_prc),'irregular_intervals'))) && r.c_prc.irregular_intervals
    t = r.u(:,end)';
else
    t = ones(1,size(r.u,1));
end

ts = cumsum(t);
ts = [0, ts];

% Number of levels
l = length(r.p_prc.p)/5;

% Upper levels
for j = 1:l-1

    % Subplots
    subplot(l,1,j);

    if plotsd == true
        upperprior = r.p_prc.mu_0(l-j+1) +sqrt(r.p_prc.sa_0(l-j+1));
        lowerprior = r.p_prc.mu_0(l-j+1) -sqrt(r.p_prc.sa_0(l-j+1));
        upper = [upperprior; r.traj.mu(:,l-j+1)+sqrt(r.traj.sa(:,l-j+1))];
        lower = [lowerprior; r.traj.mu(:,l-j+1)-sqrt(r.traj.sa(:,l-j+1))];

        plot(0, upperprior, 'ob', 'LineWidth', 1);
        hold all;
        plot(0, lowerprior, 'ob', 'LineWidth', 1);
        fill([ts, fliplr(ts)], [(upper)', fliplr((lower)')], ...
             'b', 'EdgeAlpha', 0, 'FaceAlpha', 0.15);
    end
    plot(ts, [r.p_prc.mu_0(l-j+1); r.traj.mu(:,l-j+1)], 'b', 'LineWidth', 2);
    hold all;
    plot(0, r.p_prc.mu_0(l-j+1), 'ob', 'LineWidth', 2); % prior
    xlim([0 ts(end)]);
    title(['Posterior expectation of x_' num2str(l-j+1)], 'FontWeight', 'bold');
    ylabel(['\mu_', num2str(l-j+1)]);
end

% Input level
subplot(l,1,l);

if plotsd == true
    upperprior = r.p_prc.mu_0(1) +sqrt(r.p_prc.sa_0(1));
    lowerprior = r.p_prc.mu_0(1) -sqrt(r.p_prc.sa_0(1));
    upper = [upperprior; r.traj.mu(:,1)+sqrt(r.traj.sa(:,1))];
    lower = [lowerprior; r.traj.mu(:,1)-sqrt(r.traj.sa(:,1))];

    plot(0, upperprior, 'or', 'LineWidth', 1);
    hold all;
    plot(0, lowerprior, 'or', 'LineWidth', 1);
    fill([ts, fliplr(ts)], [(upper)', fliplr((lower)')], ...
         'r', 'EdgeAlpha', 0, 'FaceAlpha', 0.15);
end
plot(ts, [r.p_prc.mu_0(1); r.traj.mu(:,1)], 'r', 'LineWidth', 2);
hold all;
plot(0, r.p_prc.mu_0(1), 'or', 'LineWidth', 2); % prior
plot(ts(2:end), r.u(:,1), '.', 'Color', [0 0.6 0]); % inputs
if ~isempty(find(strcmp(fieldnames(r),'y'))) && ~isempty(r.y)
    plot(ts(2:end), r.y(:,1), '.', 'Color', [1 0.7 0]); % responses
    title(['Response y (orange), input u (green), and posterior expectation of x_1 ', ...
           '(red) for \rho=', num2str(r.p_prc.rho), ', \kappa=', ...
           num2str(r.p_prc.ka), ', \omega=', num2str(r.p_prc.om), ...
           ', \pi_u=', num2str(r.p_prc.pi_u)], ...
          'FontWeight', 'bold');
    ylabel('y, u, \mu_1');
else
    title(['Input u (green) and posterior expectation of x_1 ', ...
           '(red) for \rho=', num2str(r.p_prc.rho), ', \kappa=', ...
           num2str(r.p_prc.ka), ', \omega=', num2str(r.p_prc.om), ...
           ', \pi_u=', num2str(r.p_prc.pi_u)], ...
          'FontWeight', 'bold');
    ylabel('u, \mu_1');
end
xlim([0 ts(end)]);
xlabel({'Trial number', ' '}); % A hack to get the relative subplot sizes right
hold off;


fileID = fopen('rgd_cropped320/rgb_0000_annotationsCropped320.txt','r');
sizeA = [2 inf];
A = fscanf(fileID, '%f %f', sizeA)
imread('rgd_cropped320/rgd_0000Cropped320.png');

figure;
imshow(ans);
hold on;
[row col] = size(A);

for idx = 1:4:col
    x = A(1, [idx:idx+3 idx]);
    y = A(2, [idx:idx+3 idx]);
    plot(x,y);
    hold on
end
fclose(fileID);


% this function calculates the required traffic inforamtion for a basic cell in our example the ju area

function traffic()
% here we define oure figure from pushbuttons to edit boxes to axis and etc..
figure('name','traffic','menubar','none','numbertitle','off','units','normalized','color',[1 1 1],'position',[0.25 0.25 0.7 0.6])
uicontrol('style','text','units','normalized','position',[0.05 0.8 0.2 0.1],'string','Number of users');
e1=uicontrol('style','edit','units','normalized','position',[0.25 0.8 0.2 0.1]);
uicontrol('style','text','units','normalized','position',[0.05 0.6 0.2 0.1],'string','Lambda');
e2=uicontrol('style','edit','units','normalized','position',[0.25 0.6 0.2 0.1]);
uicontrol('style','text','units','normalized','position',[0.05 0.5 0.2 0.1],'string','Gamma');
e3=uicontrol('style','edit','units','normalized','position',[0.25 0.5 0.2 0.1]);
uicontrol('style','text','units','normalized','position',[0.05 0.4 0.2 0.1],'string','Totla number of channels');
e4=uicontrol('style','edit','units','normalized','position',[0.25 0.4 0.2 0.1]);
uicontrol('style','text','units','normalized','position',[0.05 0.7 0.2 0.1],'string','percent');
e5=uicontrol('style','edit','units','normalized','position',[0.25 0.7 0.2 0.1]);
uicontrol('style','text','units','normalized','position',[0.05 0.3 0.2 0.1],'string','min C/I');

e6=uicontrol('style','edit','units','normalized','position',[0.25 0.3 0.2 0.1]);
uicontrol('style','text','units','normalized','position',[0.05 0.2 0.2 0.1],'string','Number of Sectors');

e7=uicontrol('style','edit','units','normalized','position',[0.25 0.2 0.2 0.1]);

uicontrol('style','pushbutton','callback',@push,'string','Calculate','units','normalized','position',[0.15 0.01 0.2 0.1]);

tt1=uicontrol('style','text','units','normalized','position',[0.5 0.7 0.4 0.1]);
tt=uicontrol('style','text','units','normalized','position',[0.46 .7 0.03 0.1],'string','A');
tt2=uicontrol('style','text','units','normalized','position',[0.5 0.6 0.4 0.1]);
uicontrol('style','text','units','normalized','position',[0.46 .6 0.03 0.1],'string','Ncell');
tt3=uicontrol('style','text','units','normalized','position',[0.5 0.5 0.4 0.1]);
uicontrol('style','text','units','normalized','position',[0.46 .5 0.03 0.1],'string','#of cell');
mi=	uimenu('label','example','callback',@ex);
	function ex(varargin)
% 		This function loads the already saved example in the directory
		load('example.mat','n','l','g','Nt','pe','ci','nm');
		n;
		l;
		g;
		Nt;
		pe;
		ci;
		nm;
		set(e1,'string',num2str(n));
		set(e2,'string',num2str(l));
		set(e3,'string',num2str(g));
		set(e4,'string',num2str(Nt));
		set(e5,'string',num2str(pe));
		set(e6,'string',num2str(ci));
		set(e7,'string',num2str(nm));
	end

	function push(varargin)
		%calculation of the traffic
		n=str2num(get(e1,'string'));
		l=str2num(get(e2,'string'));
		g=str2num(get(e3,'string'));
		Nt=str2num(get(e4,'string'));
		pe=str2num(get(e5,'string'));
		ci=str2num(get(e6,'string'));
		nm=str2num(get(e7,'string'));
		A=(n*(pe/100)*l)/60;
		set(tt1,'string',num2str(A,6));
		q=((10^(ci/10))*(6/nm))^(1/3);
		er=[0.01;0.15;0.43;0.81;1.26;1.76;2.30;2.87;3.46;4.08;4.71;5.36;6.03;6.71;7.39;8.09;8.80;9.52;10.24;20.97;11.71;12.45;13.21;12.96;14.72;15.49;16.25;17.03;17.81;18.59;19.37;20.16;20.95;21.75;22.55;23.35;24.15;24.96;25.76;26.58;27.39;28.20;29.02;29.84;30.67;31.49;32.31;33.14;33.97;34.81;35.58;36.42;37.27;38.10;38.94;39.78;40.63;41.47;42.32;43.16];
		cc=length(er);
		gg=round(er);
		k=(q^2)/3;
		cd=k;
		i=1;
		j=1;
		k=i^2+j^2+i*j;

		ee=0;
		i=0;
		j=1;
		while ee<cd

			i=i+1;
			ee=i^2+j^2+i*j;

			j=j+1;;
			k=ee;

		end
		if nm == 1
			nc=Nt/(k*nm);
			set(tt2,'string',num2str(nc));
			aaa=er(nc);
			nce=A/aaa;
			nce=ceil(nce);
			set(tt3,'string',num2str(nce));
		else
			Ns=63/(nm*k);
			As=er(round(Ns));
			Acell=3*As;
			set(tt2,'string',num2str(find(gg==ceil(Acell),1)));
			nce=A/Acell;
			nce=ceil(nce);
			set(tt3,'string',num2str(nce))
				save('model.mat','nce')
		end

	end

function push1(varargin)
	%save the number of channels that we calculated to be used on the site
	%configruation.
		save('model.mat','nce')
	end
end


filename='Cantileverbeam_Tetrahedra_Linear_Structured_SYM';
 ptype = 'MACRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'full';
cost = {'compliance'};
weights = [1];
constraint = {'volume'};
optimizer = 'PROJECTED GRADIENT';
incrementFactor = 1;
designVariable = 'Density';
filterType = 'P1';
constraint_case = 'INEQUALITY';
line_search_initiator = 'INCREASING LAST STEP';
showBC = true;

nsteps = 10;
Vfrac_final = 0.1;
Perimeter_target = 1;
optimality_final = 1e-3;
constr_final =1e-3;

Vfrac_initial = 1;
optimality_initial = 1e-3;
constr_initial = 1e-3;
TOL.rho_plus = 1;
TOL.rho_minus = 0;
TOL.E_plus = 1;
TOL.E_minus = 1e-3;
TOL.nu_plus = 1/3;
TOL.nu_minus = 1/3;


% Demo for DCM for fMRI (without Balloon observer)
% This demo inverts the DCM for fMRI model, without the ballon model, which
% is replaced by a nonlinear sigmoid observation function.

% close all
clear variables

%% First get neural level dynamics
n_t = 1.5e2;
TR = 2e0;
microDT = 1e-1;
nreg = 3;
nu = 2;
u       = zeros(2,n_t);         % inputs
u(1,2:15) = 1;
u(1,30:31) = 1;
u(1,50:51) = 1;
u(2,30:31) = 1;
u(2,60:61) = 1;
alpha   = Inf;
sigma   = Inf;
% DCM specification
A = [0 1 1
     1 0 1
     0 1 0];
B{1} = zeros(nreg,nreg);
B{2} = [0 0 0
        1 0 0
        0 0 0];
C = [1 0
     0 0
     0 0];
D{1} = [0 0 0
        0 0 0
        0 1 0];
D{2} = zeros(nreg,nreg);
D{3} = zeros(nreg,nreg);
% Prepare precalculated matrices for DCM inversion
[options.inF] = prepare_dcm(A,B,C,D);
inG.G0 = 50;
inG.k = 1;
% A matrix
t_A = exp([ -1.5
            -1.5
            -0.5
            -2.5
            -1.5 ]);
% self-inhibition gain
t_Aself = -1;
% B matrices
t_B{1} = [];
t_B{2} = exp([ -0.5 ]);
% C matrix
t_C = exp([ +0.1 ]);
% D matrices
t_D{1} = 0*exp([ -2 ]);
t_D{2} = [];
t_D{3} = [];
% fill in theta
theta(options.inF.indA) = t_A;
for i=1:nu
    theta(options.inF.indB{i}) = t_B{i};
end
theta(options.inF.indC) = t_C;
for i=1:nreg
    theta(options.inF.indD{i}) = t_D{i};
end
theta(options.inF.indself) = t_Aself;
theta = theta(:);
phi     = [];
% Build options structure for temporal integration of SDE
options.inG     = inG;
options.decim = max([1,floor(TR./microDT)]);
options.inF.deltat = TR./options.decim;
dim.n_theta         = length(theta);
dim.n_phi           = 0;
dim.n               = nreg;
dim.p               = nreg;
dim.n_t             = n_t;
f_fname = @f_dcm4fmri;
g_fname = @g_Id;
% get micro-time dynamics
out0.options = options;
out0.options.dim = dim;
out0.options.OnLine = 0;
out0.options.microU = 0;
out0.suffStat.dx = [];
out0.options.f_fname = f_fname;
out0.options.g_fname = g_fname;
[xx] = VBA_microTime(...
    struct('muTheta',theta,'muPhi',phi,'muX0',[0;0;0]),u,out0);

%% then get full dynamics (including hemodynamics)
[thetaHRF,phiHRF]   = get_HRFparams(TR,options.inF.deltat);
f_fname2             = @f_DCMwHRF;
g_fname2             = @g_HRF3;
[options]           = prepare_fullDCM(A,B,C,D,TR,options.inF.deltat);
options.inG.TE      = 0.04;
% simulated evolution parameters: hemodynamic level
t_E0 = thetaHRF(1)*ones(nreg,1);       % HbO2 extraction fraction gain
t_tau0 = thetaHRF(2)*ones(nreg,1);     % mean blood transit time gain
t_kaf = thetaHRF(3)*ones(nreg,1);      % vasodilatory signal feedback regulation
t_kas = thetaHRF(4)*ones(nreg,1);      % vasodilatory signal decay gain
t_alpha = thetaHRF(6)*ones(nreg,1);    % vessel stifness gain
% simulated observation parameters
p_E0 = phiHRF(1)*ones(nreg,1);       % HbO2 extraction fraction gain
p_epsilon = phiHRF(2)*ones(nreg,1);  % ratio of intra- and extravascular signal
% fill in theta
theta(options.inF.ind1) = t_E0;
theta(options.inF.ind2) = t_tau0;
theta(options.inF.ind3) = t_kaf;
theta(options.inF.ind4) = t_kas;
theta(options.inF.ind5) = t_alpha;
phi(options.inG.ind1) = p_E0;
phi(options.inG.ind2) = p_epsilon;
phi = phi(:);
dim.n_theta         = options.inF.ind5(end);
dim.n_phi           = 2*nreg;
dim.n               = 5*nreg;
dim.p               = nreg;
dim.n_t             = n_t;
X0 = kron(ones(nreg,1),[0;0;0;0;0]);
% get micro-time dynamics
out.options = options;
out.options.dim = dim;
out.options.OnLine = 0;
out.options.microU = 0;
out.suffStat.dx = [];
out.options.f_fname = f_fname2;
out.options.g_fname = g_fname2;
[xx0,y] = VBA_microTime(...
    struct('muTheta',theta,'muPhi',phi,'muX0',X0),u,out);

%% Finally, convolve neural dynamics with canonical HRF
f_fname3     = @f_HRF2;               % Ballon model evolution function
g_fname3     = @g_HRF3;               % Balloon model observation function
options.inF.fullDCM = 0;
options.inG.fullDCM = 0;
options.inG.TE      = 0.04;
options.microU      = 1;
dim.n_theta         = 6;
dim.n_phi           = 2;
dim.n               = 4;
dim.p               = 1;
dim.n_t             = n_t;
dim.u               = 1;
% get micro-time dynamics
out1.options = options;
out1.options.dim = dim;
out1.dim = dim;
out1.options.OnLine = 0;
out1.options.microU = 1;
out1.suffStat.dx = [];
out1.options.f_fname = f_fname3;
out1.options.g_fname = g_fname3;
yhrf = zeros(size(xx));
xx1 = zeros(size(xx0));
xx1(options.inF.n5,:) = xx;
for i=1:nreg
    u = [xx(i,:)];
    [xxhrf,yhrf(i,:)] = VBA_microTime(...
        struct('muTheta',thetaHRF,'muPhi',phiHRF,'muX0',[0;0;0;0]),u,out1);
    xx1(options.inF.n1(i),:) = xxhrf(1,:);
    xx1(options.inF.n2(i),:) = xxhrf(2,:);
    xx1(options.inF.n3(i),:) = xxhrf(3,:);
    xx1(options.inF.n4(i),:) = xxhrf(4,:);
end