function symb_pvec = sdisplay(pvec,precision)
%SDISPLAY Symbolic display of SDPVAR expression
%
% As variables in YALMIP do not have any actual names internally, the
% command is not guaranteed to recover the variable names you use in the
% work-space correctly. It tries to figure out the names of the variables
% by searching in the work-space for variables involving the same variable
% indicies, but this can fails in many instances.
%
% EXAMPLES
%  sdpvar x y
%  sdisplay(x^2+y^2)
%    ans =
%       'x^2+y^2'
%
% Optionally, we can supply an option to round the data to N decimal digits
%
%  sdisplay(pi*x1^2,4)
%    ans = '3.1416*x^2'

if nargin < 2
    precision = inf;
end

% Support displaying non-sdpvar input
if ~isa(pvec,'sdpvar')
    for r1=1:size(pvec,1)
        for r2=1:size(pvec,2)
            p = full(pvec(r1,r2));
            if isa(p,'double')
                symb_pvec{r1,r2} = num2str2(p,precision);
            else
                symb_pvec{r1,r2} = p;
            end
        end
    end
    if prod(size(symb_pvec))==1 & nargout==0
        display(symb_pvec{1,1});
        clear symb_pvec
    end
    return;
end

% First, some boooring stuff. we need to
% figure out the symbolic names and connect
% these names to YALMIPs variable indicies
W = evalin('caller','whos');

% First, sort the variables available in the work-space based
% on the creation. Early creation means it is more likely the
% relevant variable to display
createTime = [];
for i = 1:size(W,1)
    if strcmp(W(i).class,'sdpvar') || strcmp(W(i).class,'ncvar')
        keep(i) = 1;
        z = evalin('caller',['struct(' W(i).name ').extra.createTime;']);
        createTime = [createTime z];
    else
        keep(i) = 0;
    end
end
W = W(find(keep));
[sorted,index] = sort(createTime);
W = W(index);

global_LinearVariables = depends(pvec);
global_x = recover(global_LinearVariables);
[global_exponent_p,global_ordered_list] = exponents(pvec,global_x);
global_exponent_p = full(global_exponent_p);
global_names = cell(length(global_x),1);

for i = 1:size(W,1)
    if strcmp(W(i).class,'sdpvar') || strcmp(W(i).class,'ncvar')
        % Get the SDPVAR variable
        thevars = evalin('caller',W(i).name);

        % Distinguish 4 cases
        % 1: Sclalar varible x
        % 2: Vector variable x(i)
        % 3: Matrix variable x(i,j)
        % 4: Variable not really defined
        if is(thevars,'scalar') && is(thevars,'linear') && length(getvariables(thevars))==1 & isequal(getbase(thevars),[0 1])
            index_in_p = find(ismember(global_LinearVariables,getvariables(thevars)));

            if ~isempty(index_in_p)
                already = ~isempty(global_names{index_in_p});
                if already
                    already = (isempty(strfind(global_names{index_in_p},'internal')) | isempty(strfind(global_names{index_in_p},'ans')));
                end
            else
                already = 0;
            end

            if ~isempty(index_in_p) & ~already
                % Case 1
                global_names{index_in_p}=W(i).name;
            end
        elseif is(thevars,'lpcone')

            if size(thevars,1)==size(thevars,2)
                % Case 2
                vars = getvariables(thevars);
                indicies = find(ismember(vars,global_LinearVariables));
                for ii = indicies
                    index_in_p = find(ismember(global_LinearVariables,vars(ii)));

                    if ~isempty(index_in_p)
                        already = ~isempty(global_names{index_in_p});
                        if already
                            already = (isempty(strfind(global_names{index_in_p},'internal')) | isempty(strfind(global_names{index_in_p},'ans')));
                        end
                    else
                        already = 0;
                    end

                    if ~isempty(index_in_p) & ~already
                        B = reshape(getbasematrix(thevars,vars(ii)),size(thevars,1),size(thevars,2));
                        [ix,jx,kx] = find(B);
                        ix=ix(1);
                        jx=jx(1);
                        global_names{index_in_p}=[W(i).name '(' num2str(ix) ',' num2str(jx) ')'];
                    end
                end

            else
                % Case 3
                vars = getvariables(thevars);
                indicies = find(ismember(vars,global_LinearVariables));
                for ii = indicies
                    index_in_p = find(ismember(global_LinearVariables,vars(ii)));

                    if ~isempty(index_in_p)
                        already = ~isempty(global_names{index_in_p});
                        if already
                            already = (isempty(strfind(global_names{index_in_p},'internal')) | isempty(strfind(global_names{index_in_p},'ans')));
                        end
                    else
                        already = 0;
                    end

                    if ~isempty(index_in_p) & ~already
                        global_names{index_in_p}=[W(i).name '(' num2str(ii) ')'];
                    end
                end
            end

        elseif is(thevars,'sdpcone')
            % Case 3
            vars = getvariables(thevars);
            indicies = find(ismember(vars,global_LinearVariables));
            for ii = indicies
                index_in_p = find(ismember(global_LinearVariables,vars(ii)));
                if ~isempty(index_in_p)
                    already = ~isempty(global_names{index_in_p});
                    if already
                        already = ~strfind(global_names{index_in_p},'internal');
                    end
                else
                    already = 0;
                end

                if ~isempty(index_in_p) & ~already
                    B = reshape(getbasematrix(thevars,vars(ii)),size(thevars,1),size(thevars,2));
                    [ix,jx,kx] = find(B);
                    ix=ix(1);
                    jx=jx(1);
                    global_names{index_in_p}=[W(i).name '(' num2str(ix) ',' num2str(jx) ')'];
                end
            end

        else
%             % Case 4
%             vars = getvariables(thevars);
%             indicies = find(ismember(vars,global_LinearVariables));
%
%             for i = indicies
%                 index_in_p = find(ismember(global_LinearVariables,vars(i)));
%                 if ~isempty(index_in_p) & isempty(global_names{index_in_p})
%                     global_names{index_in_p}=['internal(' num2str(vars(i)) ')'];
%                 end
%             end

        end
    end
end

for i = 1:length(global_names)
    if length(global_names{i}) == 0
        global_names{i} = ['internal(' num2str(global_LinearVariables(i)) ')'];
    end
end

for pi = 1:size(pvec,1)
    for pj = 1:size(pvec,2)
        p = pvec(pi,pj);
        if isa(p,'double')
            symb_p = num2str2(p,precision);
        else
            symb_p = createSymbolicExpression(p,global_LinearVariables,global_names,precision);
        end
        symb_pvec{pi,pj} = symb_p;
    end
end

if prod(size(symb_pvec))==1 & nargout==0
    display(symb_pvec{1,1});
    clear symb_pvec
end

function symb_p =  createSymbolicExpression(p,global_LinearVariables,global_names,precision)
LinearVariables = depends(p);
x = recover(LinearVariables);
[exponent_p,ordered_list] = exponents(p,x);
exponent_p = full(exponent_p);
[~,map] = ismember(LinearVariables,global_LinearVariables);
names = {global_names{map}};

% Remove 0 constant
symb_p = '';
if size(ordered_list,1)>0
    nummonoms = size(ordered_list,1);
    if full(getbasematrix(p,0)) ~= 0
        symb_p = num2str2(full(getbasematrix(p,0)),precision);
    end
elseif all(exponent_p(1,:)==0)
    symb_p = num2str2(full(getbasematrix(p,0)),precision);
    exponent_p = exponent_p(2:end,:);
    nummonoms = size(exponent_p,1);
else
    nummonoms = size(exponent_p,1);
end

% Loop through all monomial terms
for i = 1:nummonoms
    coeff = full(getbasematrixwithoutcheck(p,i));
    switch coeff
        case 1
            coeff='+';
        case -1
            coeff = '-';
        otherwise
            if isreal(coeff)
                if coeff >0
                    coeff = ['+' num2str2(coeff,precision)];
                else
                    coeff=[num2str2(coeff,precision)];
                end
            else
                coeff = ['+' '(' num2str2(coeff,precision) ')' ];
            end
    end
    if isempty(ordered_list)
        symb_p = [symb_p coeff symbmonom(names,exponent_p(i,:))];
    else
        symb_p = [symb_p coeff symbmonom_noncommuting(names,ordered_list(i,:))];
    end
end
% Clean up some left overs, lazy coding...
symb_p = strrep(symb_p,'+*','+');
symb_p = strrep(symb_p,'-*','-');
if symb_p(1)=='+'
    symb_p = symb_p(2:end);
end
if symb_p(1)=='*'
    symb_p = symb_p(2:end);
end

function s = symbmonom(names,monom)
s = '';
for j = 1:length(monom)
    if abs( monom(j))>0
        if isempty(names{j})
            names{j} = ['internal(' num2str(j) ')'];
        end
        s = [s '*' names{j}];
        if monom(j)~=1
            s = [s '^' num2str(monom(j))];
        end
    end
end

function s = symbmonom_noncommuting(names,monom)
s = '';
j = 1;
while j <= length(monom)
    if abs( monom(j))>0
        if isempty(names{monom(j)})
            names{monom(j)} = ['internal(' num2str(j) ')'];
        end
        s = [s '*' names{monom(j)}];
        power = 1;
        k = j;
        while j<length(monom) & monom(j) == monom(j+1)
            power = power + 1;
            j = j + 1;
            %if j == (length(monom)-1)
            %    j = 5;
            %end
        end
        if power~=1
            s = [s '^' num2str(power)];
        end
    end
    j = j + 1;
end

function s = num2str2(x,precision)
if isinf(precision)
    if isreal(x)
        s = sprintf('%.12g',x);
    else
        s = sprintf('%.12g+%.12gi',real(x),imag(x));
    end
else
    if isreal(x)
        s = sprintf('%.12g',round(x*10^precision)/10^precision);
    else
        s = sprintf('%.12g+%.12gi',round(real(x)*10^precision)/10^precision,round(imag(x)*10^precision)/10^precision);
    end
end
s(s==10)=[];
s(s==32)=[];


function paths = zero_jump_link(frames, downweight_notrack)
% AUTORIGHTS
% ---------------------------------------------------------
% Copyright (c) 2015, Georgia Gkioxari
%
% This file is part of the Action Tubes code and is available
% under the terms of the Simplified BSD License provided in
% LICENSE. Please retain this notice and LICENSE if you use
% this file (or any portion of it) in your project.

% at each iteration in the while loop, a new path is generated and the boxes, scores and box boxes_idx
% associated with this path is removed so that when the next path will be generated it will consider the remaining
% boxes. e.g. from frame 1 , out of 5 boxes, box no 2 is used to generate path 1, so we
% remove the box from the list, so when we will generate path 2, we will not use this box 2 again

% This version is corrected to keep track of the correct boxes indices in each
% path , as the boxes are removed after generating each path , to keep track of the indices
% of the boxes following lines are added :

% index = frames(V(j)).boxes_idx(id);
% index =  [index;  frames(V(j+1)).boxes_idx(id)]; %% newly added
% frames(V(j)).boxes_idx(id)  = []; %% newly added
% ---------------------------------------------------------

% set of vertices
num_frames = length(frames);
V = 1:num_frames;
isempty_vertex = false(length(V),1);
if nargin < 2
  downweight_notrack = false;
end
% CHECK: make sure data is not empty
for i=1:num_frames
    if isempty(frames(i).boxes)
        disp(i);
        error('Empty frame');
    end
end

%%--- dymamic programming (K-paths)
path_counter = 0;

while ~any(isempty_vertex)

    %fprintf('# of iteration = %d\n',path_counter);
    % step1: initialize data structures
    T = length(V);
    for i=1:T
        num_states = size(frames(V(i)).boxes,1);
        data(i).scores = zeros(num_states,1);
        data(i).index  = nan(num_states,1);
        data(i).track_scores = nan(num_states,1);

    end

    % step2: solve viterbi -- forward pass --
    % we do the forward pass from the frame before the last frame (T-1),
    % computing the edge scores between the boxes at last frame (T) and the frame before the last frame (T-1), and continue this till we
    % reach the first frame,
    % at the first iteration when we compute the edge scores between frames
    % T-1 and frame T and add it with the data(i+1).scores', the
    % data(i+1).scores' values are all 0, this is the case only at first
    % iteration, and at the end of the first iteration data(i+1).scores'
    % are initialised with the max edge scores for each boxes in the frame
    % T-1, in the subsequent iteration, we add the max edge scores of boxes from i+1-th frame to the edge scores of boxes of i-th frame
    % and then we compute the max_edge_scores for i-th frame and store them in data(i).scores and the indices of the boxes havining max_edge_scores
    % with the i+1 frame boxes are stored in data(i).index
    for i=T-1:-1:1
        [edge_score, data(i).track_scores]  = score_of_edge(frames(V(i)),frames(V(i+1)), downweight_notrack);
        edge_score = bsxfun(@plus,edge_score,data(i+1).scores');
        [data(i).scores, data(i).index] = max(edge_score,[],2);
    end
    % step3: decode -- backward pass of Viterbi - back tracing
    path_counter = path_counter+1;
    [s, si] = sort(data(1).scores,'descend'); % sort the max_edge_scores of boxes in decreasing order in the first frame
    id = si(1); % index of the box having maximum edge score in the first frame
    score = data(1).scores(id);
    %index = id;
    index = frames(V(1)).boxes_idx(id);
    boxes = frames(V(1)).boxes(id,:);
    scores = frames(V(1)).scores(id,1);
    for j=1:T-1
        id = data(j).index(id);
        index =  [index;  frames(V(j+1)).boxes_idx(id)]; %% newly added
        boxes =  [boxes;  frames(V(j+1)).boxes(id,:)];
        scores = [scores; frames(V(j+1)).scores(id,:)];
    end
    paths(path_counter).total_score = score/num_frames;
    paths(path_counter).idx   = index;
    paths(path_counter).boxes = [boxes scores];

    [top_scores] = sort(scores,'descend'); % sort the max_edge_scores of boxes in decreasing order in the first frame
    mean_top_scrs = mean(top_scores(1:ceil(numel(top_scores)*0.5)));
    g_filter = [1 4 6 4 1]/16;
    smooth_scores = imfilter(scores(:),g_filter(:),'symmetric');
    paths(path_counter).smooth_scores = smooth_scores ;

    scores = scores +mean_top_scrs;
    paths(path_counter).scores = scores ;

    % step4: remove covered boxes
    for j=1:T
        id = paths(path_counter).idx(j);
        id11 = id==frames(V(j)).boxes_idx; % box id 2 remove, because it is included in this path
        id2Rem = find(id11); % % box id 2 remove
        frames(V(j)).boxes(id2Rem,:) = [];
        %frames(V(j)).feat(id2Rem,:)  = [];
        frames(V(j)).scores(id2Rem)  = [];
        frames(V(j)).boxes_idx(id2Rem)  = []; %% newly added
        isempty_vertex(j) = isempty(frames(V(j)).boxes);
    end

end

% -------------------------------------------------------------------------
function [score, track_score] = score_of_edge(v1,v2, downweight_notrack)
% -------------------------------------------------------------------------

N1 = size(v1.boxes,1);
N2 = size(v2.boxes,1);
score = nan(N1,N2);
track_score = nan(N1,N2);

for i1=1:N1
    % scores
    scores2 = v2.scores;
    scores1 = v1.scores(i1);
    score(i1,:) = scores1+scores2';
end
if isfield(v2, 'trackedboxes') && ~isempty(v1.trackedboxes)
  if numel(v2.trackedboxes) < 3
  overlap_ratio_1 = get_overlap_MtoN(v1.boxes, v1.trackedboxes{1,1});
  overlap_ratio_2 = get_overlap_MtoN(v2.boxes, v1.trackedboxes{1,2});
  track_score = round(overlap_ratio_1) * round(overlap_ratio_2');
  score(track_score > 0) = score(track_score > 0)  + 1 ;

  if downweight_notrack
      score(~track_score) = score(~track_score) -1;
  end
  track_score = double(track_score > 0);

  else
    if ~isempty(v1.trackedboxes)
      overlap_ratio_a1 = get_overlap_MtoN(v1.boxes, v1.trackedboxes{1,2});
      overlap_ratio_a2 = get_overlap_MtoN(v2.boxes, v1.trackedboxes{1,3});
      track_12 = round(overlap_ratio_a1) * round(overlap_ratio_a2');
    else
      track_12 = zeros(size(score));
    end
    overlap_ratio_b1 = get_overlap_MtoN(v1.boxes, v2.trackedboxes{1,1});
    overlap_ratio_b2 = get_overlap_MtoN(v2.boxes, v2.trackedboxes{1,2});
    track_21 = round(overlap_ratio_b1) * round(overlap_ratio_b2');
  score(track_12 > 0) = score(track_12 > 0)  + .5 ;
  score(track_21 > 0) = score(track_21 > 0)  + .5 ;

  track_score = double(track_12 > 0) + double(track_21 > 0);
  end
end

% -------------------------------------------------------------------------
function iou = inters_union(bounds1,bounds2)
% -------------------------------------------------------------------------

inters = rectint(bounds1,bounds2);
ar1 = bounds1(:,3).*bounds1(:,4);
ar2 = bounds2(:,3).*bounds2(:,4);
union = bsxfun(@plus,ar1,ar2')-inters;

iou = inters./(union+eps);


function  [volselpts] = mrSelLineOblVol(obPts,obSlice,obSize,obMin,obMax,sagX,sagY,volselpts,sagSize)
%
% MRSELLINEOBLVOL
%
%	 [volselpts] = mrSelLineOblVol(obSlice,obSize,obMin,obMax,sagX,sagY,volselpts,sagSize)
%
%	Select ROI points from the current oblique image.
%

[thexs,theys] = mrSelLineVol(obSlice,obSize,obMin,obMax,sagX,sagY);
obcoords = round(theys +round(thexs-1)*obSize(1));
obsel = obPts(obcoords,:);
sagcoords = round(obsel(:,2) +round(obsel(:,1)-1)*sagSize(1));
plcoords = round(obsel(:,3));
newsel = sagcoords+(plcoords-1)*prod(sagSize);
volselpts = [volselpts,newsel];


function mtrExportFiberGroupToMetrotrac(outFile, fgFile, faNiftiFile)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% mtrExportFiberGroupToMetrotrac(outFile, [fgFile], [faNiftiFile])
%%
%% outFile - filename for metrotrac pathways
%%
%%
%% Author: Anthony Sherbondy
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if ieNotDefined('fgFile')
    [f,p] = uigetfile({'*.mat';'*.*'},'Select a fiber group file for input...');
    if(isnumeric(f)), disp('Conversion canceled.'); return; end
    fgFile = fullfile(p,f);
end
fg = dtiNewFiberGroup();
fg = dtiReadFibers(fgFile);

if ieNotDefined('faNiftiFile')
    [f,p] = uigetfile({'*.nii.gz';'*.*'},'Select a FA file for reference to DTI space input...');
    if(isnumeric(f)), disp('Conversion canceled.'); return; end
    faNiftiFile = fullfile(p,f);
end
nifa = niftiRead(faNiftiFile);
mmPerVox = nifa.pixdim;
xformToAcpc = nifa.qto_xyz;
scene_dim = size(nifa.data);

% Matrix for converting fiber group coords into the metrotrac pathway space
xformFromAcpc = diag([(mmPerVox(:)') 1])*inv(xformToAcpc);

% HACK: Unchecked and can be bogus because DTIQuery doesn't use this
% Get ACPC from transform
ACPC = [xformToAcpc(1,4)/xformToAcpc(1,1) xformToAcpc(2,4)/xformToAcpc(2,2) xformToAcpc(3,4)/xformToAcpc(3,3)];

% Create blank database for finding some of the sizes to write out
pdb = mtrPathwayDatabase();

numstats = length( pdb.pathway_statistic_headers );

% Redo offset
offset = 5*4 + 6*8 + numstats * getStatisticsHeaderSizeWordAligned(pdb); % 5 uint,6 doubles
%5* sizeof (int) + 6 * sizeof(double) + pathways->getNumPathStatistics()*sizeof (DTIPathwayStatisticHeader);
% bool == char, but not guaranteed on all platforms

fid = fopen(outFile, 'wb');

% Writing header
fwrite(fid,offset,'uint');

fwrite(fid,scene_dim,'uint');
fwrite(fid,mmPerVox,'double');
fwrite(fid,ACPC,'double');
fwrite(fid,numstats,'uint');

% Write Stat Header
saveStatisticsHeader(pdb,fid);

%Writing path info
numpaths = length(fg.fibers);
fwrite(fid,numpaths,'uint');

for ff = 1:numpaths
    path_offset = 3 * 4  + numstats*8; % 3 int, numstats double
    fwrite(fid,path_offset,'int');

    %nn = size( fg.fibers{ff}.coords, 2 );
    nn = size( fg.fibers{ff}, 2 );

    fwrite(fid,nn,'int');
    fwrite(fid,1,'int'); % algo type HACK
    fwrite(fid,1,'int'); % seedpointindex HACK ???

    % Stats
    if( numstats ~= 0 )
        error('Can not handle nonzero statistics with path.');
    end

    % Writing path nodes
    %pos = fg.fibers{ff}.coords;
    pos = fg.fibers{ff};
    pos = mrAnatXformCoords(xformFromAcpc, pos')';
    % Change from 1 based to 0 based positions in mm space
    pos = pos - repmat(mmPerVox(:),1,size(pos,2));
    fwrite(fid,pos,'double');

    % HACK: Don't worry numstats has to be zero right now
% %     % Writing stats values per position
% %     for as = 1:numstats
% %         if( this.pathway_statistic_headers(as).is_computed_per_point )
% %             fwrite(fid,this.pathways(p).point_stat_array(as,:),'double');
% %         end
% %     end

end

disp('Saved Database.');
fclose(fid);

function pos = asMatrixStruct(this)
pos = [this.xpos; this.ypos; this.zpos];
return


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright 2014 National Renewable Energy Laboratory and National
% Technology & Engineering Solutions of Sandia, LLC (NTESS).
% Under the terms of Contract DE-NA0003525 with NTESS,
% the U.S. Government retains certain rights in this software.
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% wecSimMCR
% WEC-Sim multiple condition run executable
clear mcr imcr i j k l1 l2 m n name nseed kkk len numConditions
clear body waves simu output pto constraint ptoSim

evalc('wecSimInputFile');

if isempty(simu.mcrMatFile) == 0
    load(simu.mcrMatFile);
else
    kkk=0;
    mcr.header = {'waves.height','waves.period'};
    if isempty(simu.mcrExcelFile) == 0
        mcr.waveSS = xlsread(simu.mcrExcelFile);
        mcr.waveSS(isnan(mcr.waveSS))=0;
        for i=2:length(mcr.waveSS(:,1))
            for j=2:length(mcr.waveSS(1,:))
                if (mcr.waveSS(i,j)>0)
                    kkk = kkk+1;
                    mcr.cases(kkk,1) = mcr.waveSS(i,1);
                    mcr.cases(kkk,2) = mcr.waveSS(1,j);
                end
            end
        end
    else
        for i=1:length(waves.height)
            for j=1:length(waves.period)
                kkk = kkk+1;
                mcr.cases(kkk,1) = waves.height(i);
                mcr.cases(kkk,2) = waves.period(j);
            end
        end
    end

    numConditions=2;
    if length(waves.phaseSeed)>1
        numConditions=numConditions+1;
        mcr.header{numConditions} = 'waves.phaseSeed';
        len = length(mcr.cases(:,1));
        for nseed=1:length(waves.phaseSeed)
            mcr.cases(len*(nseed-1)+1:len*(nseed-1)+len,1:numConditions-1) = mcr.cases(1:len,1:numConditions-1);
            mcr.cases(len*(nseed-1)+1:len*(nseed-1)+len,    numConditions) = waves.phaseSeed(nseed);
        end
    end

    if exist('pto','var')
        for n=1:size(pto,2)
            if (length(pto(n).damping)>1 || length(pto(n).stiffness)>1)
                numConditions=numConditions+2;
                name = sprintf('pto(%i).damping', n);
                mcr.header{numConditions-1} = name;
                name = sprintf('pto(%i).stiffness', n);
                mcr.header{numConditions  } = name;

                len = length(mcr.cases(:,1)); kkk = 0;
                for l2=1:length(pto(n).stiffness)
                    for l1=1:length(pto(n).damping)
                        kkk=kkk+1;
                        mcr.cases(len*(kkk-1)+1:len*(kkk-1)+len,1:numConditions-2) = mcr.cases(1:len,1:numConditions-2);
                        mcr.cases(len*(kkk-1)+1:len*(kkk-1)+len,  numConditions-1) = pto(n).damping(l1);
                        mcr.cases(len*(kkk-1)+1:len*(kkk-1)+len,    numConditions) = pto(n).stiffness(l2);
                    end
                end
            end
        end; clear i j k l1 l2 m n name nseed kkk len numConditions
    end
end

%% Execute wecSimMCR
% Run WEC-Sim
warning('off','MATLAB:DELETE:FileNotFound'); delete('mcrCase*.mat')
for imcr=1:length(mcr.cases(:,1))
    wecSim;
    if exist('userDefinedFunctionsMCR.m','file') == 2
        userDefinedFunctionsMCR;
    end

    %% Store hydrodata in memory for reuse in future runs.
    if simu.reloadH5Data == 0 && imcr == 1        % Off->'0', On->'1', (default = 0)
        for ii = 1:simu.numHydroBodies
            hydroData(ii) = body(ii).hydroData;
        end
    end
end; clear imcr ans hydroData


function [data_train, labels_train, vid_ids_train_string, data_devel, labels_devel, vid_ids_devel_string, raw_devel, PC, means_norm, stds_norm, success_devel] = ...
    Prepare_HOG_AU_data_generic_intensity(train_users, devel_users, au_train, bp4d_dir, features_dir)

%%
addpath(genpath('../data extraction/'));

% First extracting the labels
[ labels_train, valid_ids_train, vid_ids_train ] = extract_BP4D_labels_intensity(bp4d_dir, train_users, au_train);
au_other = setdiff([6, 10, 12, 14, 17], au_train);
[ labels_other, ~, ~ ] = extract_BP4D_labels_intensity(bp4d_dir, train_users, au_other);
labels_other = cat(1, labels_other{:});

train_geom_data = Read_geom_files(train_users, features_dir);

% Reading in the HOG data (of only relevant frames)
[train_appearance_data, valid_ids_train_hog, vid_ids_train_string] = Read_HOG_files(train_users, features_dir);
train_appearance_data = cat(2, train_appearance_data, train_geom_data);

% Subsample the data to make training quicker
labels_train = cat(1, labels_train{:});
valid_ids_train = logical(cat(1, valid_ids_train{:}));

reduced_inds = false(size(labels_train,1),1);
reduced_inds(labels_train > 0) = true;

% make sure the same number of positive and negative samples is taken
pos_count = sum(labels_train > 0);
neg_count = sum(labels_train == 0);

num_other = floor(pos_count / (size(labels_other, 2)));

inds_all = 1:size(labels_train,1);

if(numel(train_users) > 0)
    if(numel(au_train) == 1)
        for i=1:size(labels_other, 2)+1

            if(i > size(labels_other, 2))
                % fill the rest with a proportion of neutral
                inds_other = inds_all(sum(labels_other,2)==0 & ~labels_train );
                num_other_i = min(numel(inds_other), pos_count - sum(labels_train(reduced_inds,:)==0));
            else
                % take a proportion of each other AU
                inds_other = inds_all(labels_other(:, i) & ~labels_train );
                num_other_i = min(numel(inds_other), num_other);
            end
            inds_other_to_keep = inds_other(round(linspace(1, numel(inds_other), num_other_i)));
            reduced_inds(inds_other_to_keep) = true;

        end
    end
    % Remove invalid ids based on CLM failing or AU not being labelled
    reduced_inds(~valid_ids_train) = false;
    reduced_inds(~valid_ids_train_hog) = false;

    labels_other = labels_other(reduced_inds, :);
    labels_train = labels_train(reduced_inds,:);
    train_appearance_data = train_appearance_data(reduced_inds,:);
    vid_ids_train_string = vid_ids_train_string(reduced_inds,:);

end

%% Extract devel data

% First extracting the labels
[ labels_devel, valid_ids_devel, vid_ids_devel ] = extract_BP4D_labels_intensity(bp4d_dir, devel_users, au_train);

devel_geom_data = Read_geom_files(devel_users, features_dir);
% Reading in the HOG data (of only relevant frames)
[devel_appearance_data, valid_ids_devel_hog, vid_ids_devel_string] = Read_HOG_files(devel_users, features_dir);
devel_appearance_data = cat(2, devel_appearance_data, devel_geom_data);

valid_ids_devel = logical(cat(1, valid_ids_devel{:}));

labels_devel = cat(1, labels_devel{:});

success_devel = valid_ids_devel;

% Peforming zone specific masking
if(au_train < 8 || au_train == 43 || au_train == 45) % upper face AUs ignore bottom face
    % normalise the data
    pca_file = '../../pca_generation/generic_face_upper.mat';
    load(pca_file);
elseif(au_train > 9) % lower face AUs ignore upper face and the sides
    % normalise the data
    pca_file = '../../pca_generation/generic_face_lower.mat';
    load(pca_file);
elseif(au_train == 9) % Central face model
    % normalise the data
    pca_file = '../../pca_generation/generic_face_rigid.mat';
    load(pca_file);
end

PC_n = zeros(size(PC)+size(devel_geom_data, 2));
PC_n(1:size(PC,1), 1:size(PC,2)) = PC;
PC_n(size(PC,1)+1:end, size(PC,2)+1:end) = eye(size(devel_geom_data, 2));
PC = PC_n;

means_norm = cat(2, means_norm, zeros(1, size(devel_geom_data,2)));
stds_norm = cat(2, stds_norm, ones(1, size(devel_geom_data,2)));

% Grab all data for validation as want good params for all the data
raw_devel = devel_appearance_data;

devel_appearance_data = bsxfun(@times, bsxfun(@plus, devel_appearance_data, -means_norm), 1./stds_norm);
data_devel = devel_appearance_data * PC;

if(numel(train_users) > 0)
    train_appearance_data = bsxfun(@times, bsxfun(@plus, train_appearance_data, -means_norm), 1./stds_norm);
    data_train = train_appearance_data * PC;
else
    data_train = [];
end

end


function runBinEnergy(energy, fieldSize, numBin, extraBin, startBin, endBin, IncreaseFluence, OnlyHorn, UseFlatFilter, FFA, FFB, FFDistance, ParticleType, DoseNormFlag, nhist, r, c, s)
% 'runBinEnergy'
% JC 1/29/06
% How to use
%> runBinEnergy 18 20 4 100000000
%
% Written by JC. Dec 2005
% Run DPM for the different energy bins, for optimize the photon spectrum later.
%"input" is the .MAT file have DPMIN, CTscan, and indV
%DPMIN - DPM input structure
%CTscan - DPM scan structure
%indV = sub2ind(getUniformizedSize(planC), r, c, s); see DPMInfluence.m
%line 72
%DPMIN_CTscan_indV DMPIN, CTScan, indV
%"number" is how many bins we're going to divide the whole energy range
% Typical value for "number" is 20
%nhis - number of histories
%
% JC Oct 18, 2006  use target to flattening filter distance as 12.5cm instead of 9.5cm);
% JC Feb 26, 2007
    % Add  DoseNormFlag
    % DPMIN.NumParticles = nhist*fieldSize*fieldSize;
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

setappdata(0, 'usenativesystemdialogs', false)
currentDir = cd;

[FileName,path] = uigetfile('*.mat','Select MAT file containing DPMIN, CTscan, & indV, p');

if path == 0
    errordlg('File Should exist');
    error('File Should exist');
end

cd(path);
load (FileName, 'DPMIN', 'CTscan', 'indV')
cd(currentDir);

if (class(energy)== 'char')
    energy = str2num(energy);numBin = str2num(numBin);extraBin = str2num(extraBin);nhist = str2num(nhist);
    r = str2num(r); c = str2num(c); s = str2num(s); fieldSize = str2num(fieldSize);
end

[FileName,path] = uigetfile('*.*','Select dpm.dll to execute');

if path == 0
    errordlg('File Should exist');
    error('File Should exist');
end

% need ./local to run dpm. if no. crush.
% so creat it
mkdir local

rand('state',sum(100*clock));
%for i = 0: numBin + extraBin - 1,

% Add input ParticleType as 0 for photon or -1 for electron
DPMIN.ParticleType = str2num(ParticleType);
DPMIN.SourceEnergy = energy;
% DPMIN.NumParticles = nhist;
DPMIN.NumParticles = nhist*fieldSize*fieldSize;

source = DPMIN.SourceXYZ;
% scale 40cm/100cm back from the iso center.
% 0.5*0.4 = (half field size on the plus/minus sides; 0.5;
%           (distance from source-to-jaw: 40cm / isodistance 100cm = 0.4)
%  == 0.2
DPMIN.ClmtCorner1 = [source(1)-0.2*fieldSize    source(2)+40    source(3)+0.2*fieldSize];
DPMIN.ClmtCorner2 = [source(1)+0.2*fieldSize    source(2)+40    source(3)+0.2*fieldSize];
DPMIN.ClmtCorner3 = [source(1)+0.2*fieldSize    source(2)+40    source(3)-0.2*fieldSize];

% DPMIN.FlatFilterA = -0.21300000000000;
% DPMIN.FlatFilterB= -0.10000000000000;
% DPMIN.FlatFilterDist = 12.50000000000000;
DPMIN.FlatFilterA = str2num(FFA);
DPMIN.FlatFilterB= str2num(FFB);
DPMIN.FlatFilterDist = str2num(FFDistance);

DPMIN.IsoDistance = 100;
DPMIN.IncreaseFluence = str2num(IncreaseFluence);
DPMIN.OnlyHorn = str2num(OnlyHorn);
DPMIN.UseFlatFilter = str2num(UseFlatFilter)
DPMIN.DoseNormFlag = str2num(DoseNormFlag);

if(DPMIN.ParticleType == 0)

    for i = str2num(startBin): str2num(endBin)
        DPMIN.BinEnergy = [i*energy/numBin (i+1)*energy/numBin]
        DPMIN.UsePhotSpectrum = 0;
        DPMIN.OutputError = 0;
        DPMIN.RandSeeds = [rand*1000 rand*10000];

        if (DPMIN.ParticleType == 0)
            DPMIN.Prefix = 'pre4phot'
        elseif (DPMIN.ParticleType == -1)
            DPMIN.Prefix = 'pre4elec'
        else
            error('DPMIN.ParticleType has to be 0 or -1')
        end

        cd(path);
        tic; doseV = dpm(DPMIN, CTscan); toc
        cd(currentDir);

        dose3D = zeros(r,c,s);
        %   Change the convention of the filename, using the upper bound of the
        %   bin as the file name, instead of the lower bound.
        %    filename = ['doseV_', num2str(i*energy/numBin),'MV.mat'];
        dose3D(indV) = doseV;
        filename = ['dose3D_', num2str((i+1)*energy/numBin),'MV.mat'];
        if (DPMIN.OnlyHorn == 1)
            filename =  ['dose3D_Horn_', num2str((i+1)*energy/numBin),'MV.mat'];
		end

		% Jan 11, 2008. After the extension, UseFlatFilter can be 0, 1, or 2.
        if (DPMIN.UseFlatFilter ~= 0)
            filename =  ['dose3D_FF_', num2str((i+1)*energy/numBin),'MV.mat'];
        end

        save (filename, 'dose3D');

    end

elseif (DPMIN.ParticleType == -1)
    DPMIN.Prefix = 'pre4elec';
    DPMIN.UseFlatFilter = 0

    cd(path);
    tic; doseV = dpm(DPMIN, CTscan); toc
    cd(currentDir);

    dose3D = zeros(r,c,s);
    dose3D(indV) = doseV;
    filename = ['dose3D_elec.mat'];
    save(filename,'dose3D');

else
    error('DPMIN.ParticleType has to be 0 or -1')
end
end


function [options,u,dim] = VBA_check(y,u,f_fname,g_fname,dim,options)
% VBA_CHECK
% [options,u,dim] = VBA_check(y,u,f_fname,g_fname,dim,options)
% Checks (and fills in default) optional inputs to VBA_NLStateSpaceModel.m
% function [options,u,dim] = VBA_check(y,u,f_fname,g_fname,dim,options)
% This function checks the consistency of the arguments to the
% VBA_NLStateSpaceModel.m function. Importantly, it fills in the missing
% priors and optional arguments.
% NB: if the user-specified priors on the stochastic innovations precision
% is a delta Dirac at infinity (priors.a_alpha = Inf and priors.b_alpha =
% 0), the priors are modified to invert an ODE-like state-space model, i.e.
% the equivalent deterministic system.

%% ________________________________________________________________________
%  check model dimension

% set default if static model
if isempty(f_fname)
    dim = VBA_check_struct(dim, ...
        'n_theta', 0, ...
        'n', 0);
end

% check if hidden state dimension:
assert( ...
     isfield(dim,'n')          ... exists,
  && isscalar(dim.n)           ... is a scalar value
  && mod(dim.n,1) == 0         ... that is integer
  && dim.n >= 0                ... and non negative
, '*** Please provide the dimension of the hidden state in dim.n');

% check if evolution parameters dimension:
assert( ...
     isfield(dim,'n_theta')    ... exists
  && isscalar(dim.n_theta)     ... is a scalar value
  && mod(dim.n_theta,1) == 0   ... that is integer
  && dim.n_theta >= 0          ... and non negative
, '*** Please provide the dimension of the evolution parameters in dim.n_theta');

% check if observation parameters dimension:
assert( ...
     isfield(dim,'n_phi')      ... exists
  && isscalar(dim.n_phi)       ... is a scalar value
  && mod(dim.n_phi,1) == 0     ... that is integer
  && dim.n_phi >= 0            ... and non negative
, '*** Please provide the dimension of the observation parameters in dim.n_phi');

dim = VBA_check_struct(dim, ...
    'n_t'   , size(y,2), ... % number of trials or time samples
    'p'     , size(y,1)  ... % data dimension
);

if isempty(u)
    u = zeros(0,dim.n_t);
else
    u = full(u);
end
dim.u = size(u,1);

%% ________________________________________________________________________
%  check VBA's options structure

if isfield(options,'binomial') % check for legacy binomial field
    options.sources = struct('type', options.binomial , ...
                             'out' , 1:dim.p          );
    options = rmfield(options, 'binomial');
    fprintf('*** WARNING: options.binomial is now deprecated. Please use ''options.sources.type = 1'' to specify a binary observation distribution.\n');
end

% set defaults
options = VBA_check_struct(options, ...
    'decim'      , 1     , ...     % Micro-time resolution
    'microU'     , 0     , ...     % Micro-resolution input
    'inF'        , []    , ...     % Optional (internal) parameters of the evolution function
    'inG'        , []    , ...     % Optional (internal) parameters of the observation function
    'checkGrads' , 0     , ...     % Check analytical gradients against numerical gradients
    'updateX0'   , 1     , ...     % Flag for initial conditions update
    'updateHP'   , 1     , ...     % Flag for hyperparameters update
    'initHP'     , 1     , ...     % Flag for hyperparameters initialization
    'backwardLag', 1     , ...     % time lag of the short-sighted backward-pass
    'MaxIter'    , 32    , ...     % Maximum number of iterations
    'MaxIterInit', 32    , ...     % Maximum number of iterations for the initialization
    'MinIter'    , 0     , ...     % Minimum number of iterations
    'TolFun'     , 2e-2  , ...     % Minimum change in the free energy
    'DisplayWin' , 1     , ...     % VB display window
    'gradF'      , 0     , ...     % Gauss-Newton ascent on free (1) or variational (0) energy
    'GnMaxIter'  , 32    , ...     % Gauss-Newton coordinate ascent maximum number of iterations:
    'GnTolFun'   , 1e-5  , ...     % Gauss-Newton coordinate ascent threshold on relative variational energy:
    'GnFigs'     , 0     , ...     % Gauss-Newton inner-loops figures
    'verbose'    , 1     , ...     % matlab window messages
    'OnLine'     , 0     , ...     % On-line version (true when called from VBA_OnLineWrapper.m)
    'delays'     , []    , ...     % delays
    'kernelSize' , 16    , ...     % max lag of Volterra kernels
    'nmog'       , 1     , ...     % split-Laplace VB?
    'UNL'        , 0     , ...     % un-normalized likelihood?
    'UNL_width'  , 4     , ...     % for partition function estimation
    'UNL_ng'     , 64      ...     % for partition function estimation
) ;

options = VBA_check_struct(options, ...
    'isYout'    , zeros(dim.p,dim.n_t)    , ... % excluded data
    'skipf'     , zeros(1,dim.n_t)        , ... % steady evolution
    'sources'   , struct()                  ...
) ;

options.sources = VBA_check_struct(options.sources, ...
    'type', 0        , ... % default to gaussian
    'out' , 1:dim.p  );

% % retrocompatibility
% if ~isfield(options,'binomial') && numel(options.sources)==1
%         options.binomial = options.sources.type;
% end

options.backwardLag = min([max([floor(round(options.backwardLag)),1]),dim.n_t]);
options.kernelSize  = min([dim.n_t,options.kernelSize]);

for i=1:numel(options.sources)
    if options.sources(i).type ~= 0 % if binomial
        if ~isempty(y)
            isYoutSource = options.isYout(options.sources(i).out,:);
            ySource = y(options.sources(i).out,:);
            if ~ VBA_isBinary (ySource(~ isYoutSource))
                error('*** Data should be binary!')
            end
            if islogical(ySource(~isYoutSource))
                error('*** Binary data should be numerical (0,1) not logical (true,false).\n*** Use y=+y or y=double(y) to convert your observations.',[])
            end
        end
    end
end

% split in multisession
[f_fname,g_fname,dim,options,u] = VBA_multisession_expand(f_fname,g_fname,dim,options,u);

% Deal with micro-resolution input
u = VBA_getU(u,options,dim,'2macro');

%% ________________________________________________________________________
%  check priors
[options,options.params2update] = VBA_fillInPriors(dim,options);
priors = options.priors;
% check consistency of priors and model dimensions
assert(size(priors.muX0,1)==dim.n,'*** Dimension of options.priors.muX0 does not match dim.n!')
assert(isequal(size(priors.SigmaX0),dim.n*[1,1]),'*** Dimension of options.priors.SigmaX0 does not match dim.n!')
assert(size(priors.muPhi,1)==dim.n_phi,'*** Dimension of options.priors.muPhi does not match dim.n_phi!')
assert(isequal(size(priors.SigmaPhi),dim.n_phi*[1,1]),'*** Dimension of options.priors.SigmaPhi does not match dim.n_phi!')
assert(size(priors.muTheta,1)==dim.n_theta,'*** Dimension of options.priors.muTheta does not match dim.n_theta!')
assert(isequal(size(priors.SigmaTheta),dim.n_theta*[1,1]),'*** Dimension of options.priors.SigmaTheta does not match dim.n_theta!')

if dim.n>0 && isempty(options.params2update.x0)
    options.updateX0 = 0;
end

% Name of the display figure
if ~isfield(options,'figName')
    if dim.n > 0
        if isinf(priors.a_alpha) && isequal(priors.b_alpha,0)
            options.figName = 'VB-Laplace identification of deterministic system';
        else
            options.figName = 'VB-Laplace identification of stochastic system';
        end
    else
        options.figName = 'VB-Laplace inversion of static model';
    end
end

% % ensure excluded data consistency (gaussian sources)
% TODO: remove once VBA_Iphi deal with isYout
if numel(options.sources) == 1
gsi = find([options.sources.type]==0);
for i=1:numel(gsi)
    for t=1:dim.n_t
        diQ = (diag(priors.iQy{t,i}) == 0) | options.isYout(options.sources(gsi(i)).out,t);
        options.isYout(options.sources(gsi(i)).out,t) = +diQ;
        priors.iQy{t,i} = diag(~diQ)*priors.iQy{t,i}*diag(~diQ);
    end
end
end

% store evolution/observation function handles
options.f_fname = f_fname;
options.g_fname = g_fname;

%% ________________________________________________________________________
%  check inversion specific cases

% split-MoG sufficient statistics
if options.nmog > 1
    np = length(options.params2update.phi);
    [m0,s0,w0] = getMoG4N01(options.nmog,1,0);
    tic,[C] = get_nkdraws(options.nmog,np,0);toc
    nd = size(C,2);
    split.w = zeros(nd,1);
    split.m = zeros(np,nd);
    split.s = zeros(np,nd);
    for i=1:nd
        split.w(i) = prod(w0(C(:,i)));
        split.m(:,i) = m0(C(:,i));
        split.s(:,i) = s0(C(:,i));
    end
    split.w = split.w./sum(split.w);
    options.split = split;
end

% Delay embedding
if dim.n > 0 && sum(options.delays(:)) > 0
    % modify options:
    dim.n_embed = dim.n*max(options.delays(:));
    inF.dim = dim;
    inF.options = options;
    inF.f_fname = f_fname;
    inF.f_nout = nargout(f_fname);
    inG.dim = dim;
    inG.options = options;
    inG.g_fname = g_fname;
    inG.g_nout = nargout(g_fname);
    options.inF = inF;
    options.inG = inG;
    options.f_fname = @f_embed;
    options.g_fname = @g_embed;
    options.delays = [];
    % modify priors:
    Zeros = zeros(inF.dim.n,dim.n_embed);
    for t=1:dim.n_t
        tmp = 1e2*kron(eye(max(inG.options.delays(:))),priors.iQx{t});
        priors.iQx{t} = [   priors.iQx{t}	Zeros
                            Zeros'          tmp    ];
        priors.iQx{t}(isnan(priors.iQx{t})) = 0;
        dpc = diag(priors.iQx{t});
        iz = find(isinf(dpc));
        if ~isempty(iz)
            options.params2update.x{t} = setdiff(1:dim.n,iz);
        else
            options.params2update.x{t} = 1:dim.n;
        end
    end
    priors.muX0 = repmat(priors.muX0,max(inF.options.delays(:))+1,1);
    priors.SigmaX0 = kron(eye(max(inF.options.delays(:))+1),priors.SigmaX0);
    dpc = diag(priors.SigmaX0);
    iz = find(dpc==0);
    if ~isempty(iz)
        options.params2update.x0 = setdiff(1:length(priors.SigmaX0),iz);
    else
        options.params2update.x0 = 1:length(priors.SigmaX0);
    end
    dim.n = dim.n*(max(inF.options.delays(:))+1);
end

% Add other inputs in the options structure:
options.g_nout = nargout(options.g_fname);
options.priors = priors;
options.dim = dim;

% Special case: DCM check
if isequal(options.f_fname,@f_DCMwHRF) && isequal(options.g_fname,@g_HRF3)
    % DCM for fMRI
    [options] = VBA_check4DCM(options);
end

if dim.n > 0
    options.f_nout = nargout(options.f_fname);
    if isinf(priors.a_alpha) && isequal(priors.b_alpha,0)
        % Check whether SDE --> ODE [ p(alpha) = Dirac at 0 ]
        % This will allow the algorithm to shortcut the VB-Laplace extended Kalman
        % smoother, treating the model as non-stochastic DCM. In this version, the
        % hidden states are assumed to obey an ODE, which is the deterministic
        % variant of the more general SDE.
        priors0 = priors;
        dim0 = dim;
        options0 = options;
        % Embed evolution parameters and initial conditions in observation
        % parameters  --> modify prior structure accordingly
        priors.muTheta = [];
        priors.SigmaTheta = [];
        priors.muX0 = [];
        priors.SigmaX0 = [];
        if dim0.n_theta > 0
            priors.muPhi = [priors0.muPhi;priors0.muTheta];
            Zeros = zeros(dim0.n_phi,dim0.n_theta);
            priors.SigmaPhi = [ priors0.SigmaPhi  Zeros
                                Zeros'            priors0.SigmaTheta ];
            options.params2update.phi = [options0.params2update.phi,options0.params2update.theta + dim0.n_phi];
        end
        if options.updateX0
            priors.muPhi = [priors.muPhi;priors0.muX0];
            Zeros = zeros(dim0.n_phi+dim0.n_theta,dim0.n);
            priors.SigmaPhi = [ priors.SigmaPhi  Zeros
                                Zeros'           priors0.SigmaX0 ];
            options.params2update.phi = [options.params2update.phi,options0.params2update.x0 + dim0.n_phi + dim0.n_theta];
        end
        % Modify dim and options structures
        dim.n_theta = 0;
        dim.n_phi = size(priors.muPhi,1);
        dim.n = 0;
        options.f_fname = [];
        options.f_nout = 0;
        options.g_fname = @VBA_odeLim;
        options.g_nout = nargout(@VBA_odeLim);
        options.inF = [];
        options.inG = [];
        options.inG.old.dim = dim0;
        options.inG.old.options = options0;
        options.inG.dim = dim;
        options.priors = priors;
        options.dim = dim;
    else % stochastic inversion
        % Derive marginalization operators for the lagged Kalman filter
        n = dim.n;
        lag = options.backwardLag + 1;
        options.lagOp.C = [zeros(n,n*(lag-1)),eye(n)];
        options.lagOp.D = [zeros(n,n*(lag-2)),eye(n),zeros(n,n)];
        options.lagOp.E = [eye(n*(lag-1)),zeros(n*(lag-1),n)];
        options.lagOp.Eu = [zeros(n*(lag-1),n),eye(n*(lag-1))];
        options.lagOp.M = [eye(n),zeros(n,n*(lag-1))];
    end
end


function y = downsample2(x,K)

for i = 1:size(x,3)
y(:,:,i) = downsample(downsample(x(:,:,i),K)',K)';
end

end


function C = gsp_jtv_mat2vec(C)
%GSP_JTV_MAT2VEC vector to matrix transform
%   Usage:  C  = gsp_jtv_mat2vec(C);
%
%   Input parameters:
%       C       : Data
%
%   Ouput parameter
%       C       : Data
%
%   Reshape the data from the matrix form to the vector form

[N,T,Nf,Ns] = size(C);

C = reshape(C,N*T*Nf,Ns);

end


%DNADamage
%
% Author: Jonathan Karr, jkarr@stanford.edu
% Affiliation: Covert Lab, Department of Bioengineering, Stanford University
% Last Updated: 4/19/2011
classdef DNADamage
    methods (Static = true)
        function run(sim, fileName)
            import edu.stanford.covert.cell.sim.analysis.DNADamage;
            import edu.stanford.covert.cell.sim.util.PrintUtil;

            %excel file
            [content, colLabels, indentation] = DNADamage.calcExpectedRates(sim);
            if nargin == 1
                PrintUtil.printToStdIO(content, colLabels, struct('indentation', indentation));
            else
                PrintUtil.printToFile(content, colLabels, [fileName '.xls'], 'State', struct('indentation', indentation));
            end
        end

        function [content, colLabels, indentation] = calcExpectedRates(sim)
            d = sim.process('DNADamage');

            reactionVulnerableMotifs = d.reactionVulnerableMotifs;
            tfs = ismember(d.reactionVulnerableMotifTypes, {'damagedBases','damagedSugarPhosphates','intrastrandCrossLinks'});
            reactionVulnerableMotifs(tfs) = ...
                d.metabolite.wholeCellModelIDs(cell2mat(d.reactionVulnerableMotifs(tfs)));
            tfs = ismember(d.reactionVulnerableMotifTypes, {'abasicSites','gapSites','hollidayJunctions', 'strandBreaks'});
            reactionVulnerableMotifs(tfs) = cell(sum(tfs), 1);

            rates = d.calcExpectedReactionRates();

            reactionRadiation = cell(size(d.reactionRadiation));
            reactionRadiationLevels = zeros(size(d.reactionRadiation));
            reactionRadiation(d.reactionRadiation~=0) = ...
                d.substrateWholeCellModelIDs(d.reactionRadiation(d.reactionRadiation~=0));
            reactionRadiationLevels(d.reactionRadiation~=0) = ...
                d.substrates(d.reactionRadiation(d.reactionRadiation~=0));

            colLabels = {'ID', 'Name', ...
                'Damage Type', 'Damage Motif', 'No. Vulnerable Site', ...
                'Specific Rate (eg 1/s/nt/gy)', 'Rate (1/s/cell)', 'Rate (1/cell cycle)', ...
                'Radiation ID', 'Radiation Value'};

            content = [...
                d.reactionWholeCellModelIDs d.reactionNames ...
                d.reactionVulnerableMotifTypes reactionVulnerableMotifs num2cell(d.calcNumberVulnerableSites()) ...
                num2cell(d.reactionBounds(:, 2)) num2cell(rates) num2cell(rates * ((9.0 + 2) * 3600)) ...
                reactionRadiation num2cell(reactionRadiationLevels) ...
                ];

            indentation = zeros(size(content, 1), 1);
        end
    end
end


function imsegs2 = transferLabels(imsegs1, imsegs2, l2v, l2h)
%
% imsegs2 = transferLabels(imsegs1, imsegs2)
%
% Transfers labeling from imsegs1 to imsegs2.  imsegs1.segimage and ground
% truth labels are used to create a label map, which is then used to label
% the superpixels in imsegs2.  l2v and l2h give conversions from full label
% index to vertical and horz sublabel indices, respectively.
% (default: l2v = [1 2 2 2 2 2 3], l2h = [0 1 2 3 4 5 0])

if ~exist('l2v')
    l2v = [1 2 2 2 2 2 3];
end
if ~exist('l2h')
    l2h = [0 1 2 3 4 5 0];
end

for f = 1:numel(imsegs1)

    disp(num2str(f))

    stats = regionprops(imsegs1(f).segimage, 'PixelIdxList');
    idx = {stats.PixelIdxList};
    lmap = zeros(size(imsegs1(f).segimage));
    for s = 1:imsegs1(f).nseg
        lmap(idx{s}) = imsegs1(f).labels(s);
    end

    % set imsegs2
    nseg = imsegs2(f).nseg;
    imsegs2(f).vlabels = cell(nseg, 1);
    imsegs2(f).hlabels = cell(nseg, 1);
    imsegs2(f).labels = zeros(nseg, 1);
    imsegs2(f).vert_labels = zeros(nseg, 1);
    imsegs2(f).horz_labels = zeros(nseg, 1);
    imsegs2(f).label_names = imsegs1(f).label_names;
    imsegs2(f).vert_names = imsegs1(f).vert_names;
    imsegs2(f).horz_names = imsegs1(f).horz_names;

    stats = regionprops(imsegs2(f).segimage, 'PixelIdxList');
    idx = {stats.PixelIdxList};

    for s = 1:nseg
        mcl = mode(lmap(idx{s}));

        imsegs2(f).labels(s) = mcl;
        if mcl==0
            imsegs2(f).vert_labels(s) = 0;
            imsegs2(f).horz_labels(s) = 0;
        else
            imsegs2(f).vert_labels(s) = l2v(mcl);
            imsegs2(f).horz_labels(s) = l2h(mcl);
        end

        if imsegs2(f).vert_labels(s)==0
            imsegs2(f).vlabels{s} = '---';
        else
            imsegs2(f).vlabels{s} = imsegs2(f).vert_names{imsegs2(f).vert_labels(s)};
        end
        if imsegs2(f).horz_labels(s)==0
            imsegs2(f).hlabels{s} = '---';
        else
            imsegs2(f).hlabels{s} = imsegs2(f).horz_names{imsegs2(f).horz_labels(s)};
        end
    end
end


function out=isinf(x)

%%%precision=x(1).precision;
%%%out=zeros(size(x));
%%%
%%%for ii=1:numel(x)
%%% imag=false;
%%% [xrval,xival]=getVals(x,ii);
%%% if hasimag(xival), imag=true; end
%%% if imag
%%%  temp=mpfr_isinf(precision,xrval);
%%%  if temp~=0, out(ii)=1; end
%%%  temp=mpfr_isinf(precision,xival);
%%%  if temp~=0, out(ii)=1; end
%%% else
%%%  out(ii)=mpfr_isinf(precision,xrval);
%%%  if out(ii)~=0, out(ii)=1; end
%%% end
%%%end % for ii=1:max(ex,

out=x==inf;


function ind = gpDataIndices(model, dimNo, blockNo)

% GPDATAINDICES Return indices of present data.
% FORMAT
% DESC returns the indices of data which is not missing for a given
% dimension in the GP-LVM.
% ARG model : the model for which the indices are being returned.
% ARG dimNo : the dimension for which the presence of missing data
% is being looked at.
% RETURN ind : indices of training data along that dimension which
% isn't missing.
%
% DESC returns the indices of data which is not missing for a given
% dimension in the GP-LVM and a block number in the PITC approximation.
% ARG model : the model for which the indices are being returned.
% ARG dimNo : the dimension for which the presence of missing data
% is being looked at.
% ARG blockNo : the block number in the PITC approximation for
% which the indices are required.
% RETURN ind : indices of training data along that dimension which
% isn't missing.
%
% SEEALSO : gpCreate
%
% COPYRIGHT : Neil D. Lawrence, 2006

% GP

if nargin > 2
  if ~strcmp(model.approx, 'pitc')
    error('Block number only relevant for pitc approximation.');
  else
    if blockNo == 1
      startVal = 1;
    else
      startVal = model.blockEnd(blockNo-1)+1;
    end
    endVal = model.blockEnd(blockNo);
    if model.isMissingData
      st = min(find(model.indexPresent{dimNo}>=startVal));
      fi = max(find(model.indexPresent{dimNo}<=endVal));
      ind = model.indexPresent{dimNo}(st:fi)';
    else
      ind = startVal:endVal;
    end
  end
else
  if strcmp(model.approx, 'pitc')
    error('Must give block number with PITC approximation');
  else
    if model.isMissingData
      ind = model.indexPresent{dimNo}';
    else
      ind = 1:model.N;
    end
  end
end


function read_bv
% read_bv - read data from an eeg-File
%
% SYNOPSIS
%    data = read_bv(file, HDR, OPT);
%
% ARGUMENTS
%                file - Name of EEG file (.eeg) is appended)
%                HDR  - Information about the file (read from the *.vhdr header file)
%                   .fs      - Sampling rate
%                   .nChans  - Number of channels
%                   .nPoints - Number of data points in the file (optional)
%                   .scale   - Scaling factors for each channel
%                   .endian  - Byte ordering: 'l' little or 'b' big
%                OPT  - Struct with following fields
%                   .chanidx         - Indices of the channels that are to be read
%                   .fs              - Down sample to this sampling rate
%                   .filt_b          - Filter coefficients of IIR filter
%                                      applied to raw data (b part)
%                                      (optional)
%                   .filt_a          - Filter coefficients of IIR filter
%                                      applied to raw data (a part)
%                                      (optional)
%                   .filt_subsample  - Filter coefficients of FIR filter
%                                      used for sub sampling (optional)
%                   .data            - A matrix where the data is stored
%                                      (optional)
%                   .dataPos         - The position in the matrix
%                                      [dataStart dataEnd fileStart
%                                      fileEnd](optional)
%
%      The filter parts of the OPT structure are optional fields.
%      The default for the filt_subsample is a filter which takes the last
%      value of filtered block e.g. [0 ... 0 1]
%
%      With opt.data and opt.dataPos read_bv can write directly to a
%      matrix. dataPos is an optional value for opt.data where you can set
%      the position of the read data. dataStart is the position in data
%      where the first read datasample is stored.
%
%       Please note, that the fields chanidx and dataPos used as c indices
%       starting at 0.
% RETURNS
%          data: [nChans, len] the actual data
%
% DESCRIPTION
%    Open a file and read the eeg data. The data is filtered with an IIR
%    filter and an FIR filter.
%
%    For the eeg file we assume that it was written with the following
%    settings: DataFormat = BINARY
%              DataOrientation = MULTIPLEXED
%              BinaryFormat = INT_16
%
% COMPILE WITH
%    mex read_bv.c
%
% AUTHOR
%    Max Sagebaum
%
%    2008/04/15 - Max Sagebaum
%                   - file created
% (c) 2005 Fraunhofer FIRST


function [st, stack] = stt                                             % setting [directory, number of frames, map setting]

%% main directories
st.dr.nm   = '04';                                                     % dataset name
if     filesep == '/';  mdr = sprintf('%s','~');                       % linux
elseif filesep == '\';  mdr = sprintf('%s','D:');                      % windows
end
st.dr.pts  = [mdr filesep 'dataset' filesep 'sequences' filesep ...                                        % directory of points
              st.dr.nm filesep 'velodyne' filesep];
st.dr.pose = [mdr filesep 'dataset' filesep 'poses' filesep];                                              % directory of poses
st.dr.img  = [mdr filesep 'dataset' filesep 'color' filesep st.dr.nm filesep 'image_2' filesep];           % directory of images
st.dr.clb  = [mdr filesep 'dataset' filesep 'calibration' filesep st.dr.nm filesep];                       % directory of calibration
st.dr.rec  = [filesep 'media' filesep 'ali' filesep 'TOSHIBA EXT' filesep 'result' filesep 'mar' filesep]; % directory of record
%% setting
st.st.st   = 1;                                                        % start frames
st.st.tn   = size(dir(sprintf('%s*.bin',st.dr.pts)),1);                % number of frames
%% local grid options
st.vm.xf   = +40;                                                      % x direction and front (x: -35 ~ +55)
st.vm.xb   = -20;                                                      % x direction and behind
st.vm.yl   = +12;                                                       % left and right (y: -15 ~ +15)
st.vm.yr   = -12;
st.vm.zu   = 2.5;                                                      % z direction and up (z: 0 ~ +2.5)
st.vm.zd   = -1;                                                       % z direction and down
st.vm.nxf  = +30;                                                       % new x direction and front (x: -35 ~ +55)
st.vm.nxb  = -10;                                                       % new x direction and behind
st.vm.nyl  = +10;                                                       % new left and right (y: -15 ~ +15)
st.vm.nyr  = -10;
st.vm.bs   = 3;                                                        % blind spot radius
st.vm.tr   = 1;                                                        % minimum number of points to make a valid voxel
%% cell size
st.vx.x    = 0.2;   % 0.2
st.vx.y    = 0.2;   % 0.2
st.vx.ix   = (st.vm.xf - st.vm.xb) / st.vx.x;                          % mat size
st.vx.iy   = (st.vm.yl - st.vm.yr) / st.vx.y;
%% road detection options
st.rd.vr   = 0.02;                                                     % road blocks should have variance lower than a threshold
st.rd.mx   = 0.8;                                                      % road blocks should have height lower than a threshold
%% stack option
st.stc.sz  = 90;                                                       % stack size (history)
st.stc.in  = 60;                                                       % number of integrating measurements
stack.mat  = zeros(st.vx.ix, st.vx.iy, st.stc.sz);                     % initialize stack
stack.ind  = zeros(st.vx.ix, st.vx.iy, st.stc.sz);
stack.pts  = zeros(st.vx.ix* st.vx.iy, 3, st.stc.sz);                  % associated pts
stack.ptn  = zeros(st.vx.ix* st.vx.iy, 3, st.stc.sz);                  % associated ptn
%% foreground detection
st.fr.sz   = 2;                                                        % check neighbourhood (sensor error in x-y) 0.6
%% plot options
figure('units','normalized','outerposition',[0 0 1 1])  % figure()
st.pl.vl   = '.b';                                                     % velodyne point's shape and color
st.pl.cl   = 'g';
st.pl.az   = -25;                                                      % driverview (-90, 20) [azimuth, elevation]
st.pl.el   = 45;                                                       % globalview (-25, 45) topview(0, 90)
st.pl.x    = 0.5 * max(st.vm.nxf, abs(st.vm.nxb));                     % the coordinates size
st.pl.y    = 0.5 * st.vm.nyl;
st.pl.z    = st.vm.zu - st.vm.zd;
st.cr.bs   = 8;                                                        % coordinate bias to show on image
%% Colors
st.pl.cv   = zeros(15, 3);
st.pl.cv(1, :)   = [255, 0, 0] / 255;         % red
st.pl.cv(2, :)   = [0, 255, 0] / 255;         % green
st.pl.cv(3, :)   = [0, 0, 255] / 255;         % blue
st.pl.cv(4, :)   = [176, 23, 31] / 255;       % indian red
st.pl.cv(5, :)   = [30, 144, 255] / 255;      % dodger blue
st.pl.cv(6, :)   = [142, 142, 142] / 255;     % gray 56
st.pl.cv(7, :)   = [142, 142, 56] / 255;      % olive lab
st.pl.cv(8, :)   = [255, 215, 0] / 255;       % gold
st.pl.cv(9, :)   = [128, 0, 128] / 255;       % purple
st.pl.cv(10, :)  = [205, 198, 115] / 255;     % khaki 3
st.pl.cv(11, :)  = [255, 20, 147] / 255;      % deep pink
st.pl.cv(12, :)  = [255, 165, 0] / 255;       % orange
st.pl.cv(13, :)  = [210, 180, 140] / 255;     % tan
st.pl.cv(14, :)  = [139, 35, 35] / 255;       % brown 4
st.pl.cv(15, :)  = [139, 69, 19] / 255;       % saddle brown
st.pl.cv(16, :)  = [0, 0, 0] / 255;           % black
st.pl.cv(17, :)  = [255, 255, 255] / 255;     % white

end


function [sv,stat0]=ephpos(time,teph,sat,nav,iode,sv) %#ok

global glc gls
stat0=1; tt=1e-3; sv1=gls.sv;
[sys,~]=satsys(sat);

if sys==glc.SYS_GPS||sys==glc.SYS_GAL||sys==glc.SYS_BDS||sys==glc.SYS_QZS
%     [eph,stat]=searcheph(teph,sat,iode,nav);
    [eph,stat]=searcheph_h(teph,sat,-1,nav.eph);
    if stat==0,stat0=0;return;end
    sv=eph2pos(time,eph,sv);
    time=timeadd(time,tt);
    sv1=eph2pos(time,eph,sv1);
    sv.svh=eph.svh;
elseif sys==glc.SYS_GLO
%     [geph,stat]=searchgeph(teph,sat,iode,nav);
    [geph,stat]=searchgeph_h(teph,sat,-1,nav.geph);
    if stat==0,stat0=0;return;end
    sv=geph2pos(time,geph,sv);
    time=timeadd(time,tt);
    sv1=geph2pos(time,geph,sv1);
    sv.svh=geph.svh;
else
    stat0=0; return;
end

sv.vel=(sv1.pos-sv.pos)/tt;
sv.dtsd=(sv1.dts-sv.dts)/tt;

return


classdef CelestialBodyIntegration
    %CelestialBodyIntegration Summary of this class goes here
    %   Detailed explanation goes here

    properties
        celBodyData CelestialBodyData
    end

    methods
        function obj = CelestialBodyIntegration(celBodyData)
            obj.celBodyData = celBodyData;
        end

        function integrateCelestialBodies(obj, minUT, maxUT, hWaitbar)
            arguments
                obj(1,1) CelestialBodyIntegration
                minUT(1,1) double
                maxUT(1,1) double
                hWaitbar = [];
            end

%             allBodies = obj.celBodyData.getAllBodyInfo();
            [~, allBodiesCell] = ma_getSortedBodyNames(obj.celBodyData);

            for(i=1:length(allBodiesCell)) %#ok<*NO4LP>
                allBodies(i) = allBodiesCell{i}; %#ok<AGROW>
            end

            bool = [allBodies.propTypeEnum] == BodyPropagationTypeEnum.Numerical;
            if(any(bool))
%                 hFig = uifigure('Position',[0,0,400,125], 'WindowStyle','modal', 'Icon','logoSquare_48px_transparentBg.png');
%                 centerUIFigure(hFig);
                drawnow;

                numericBodies = allBodies(bool);
                numericInds = 1:sum(bool);

                analyticBodies = allBodies(not(bool));
                analyticInds = 1:sum(not(bool));

                epochs = [numericBodies.epoch];
                if(numel(unique(epochs)) == 1)
                    t0 = unique(epochs);

                    [y0, numericMasses] = CelestialBodyIntegration.getInitialStates(numericBodies);
                    if(t0 > minUT)
                        [T,Y,~] = obj.callIntegrator(numericBodies, numericMasses, numericInds, analyticBodies, analyticInds, t0, minUT, y0, hWaitbar);

                        t0 = T(end);
                        y0 = Y(end,:);
                    end

                    [T,~,YY] = obj.callIntegrator(numericBodies, numericMasses, numericInds, analyticBodies, analyticInds, t0, maxUT, y0, hWaitbar);

                    if(not(isempty(hWaitbar)))
                        hWaitbar.Message = 'Performing frame rotations on computed states.  Please wait.';
                        hWaitbar.Value = 0;
                        hWaitbar.Indeterminate = 'off';
                    end

                    for(i=1:size(YY,3))
                        bodyInfo = numericBodies(i);
                        states = YY(:,:,i);

                        times = T;
                        rVects = states(:,1:3)';
                        vVects = states(:,4:6)';
                        cartElem = CartesianElementSet(times, rVects, vVects, obj.celBodyData.globalBaseFrame, true);

                        if(not(isempty(bodyInfo.getParBodyInfo(obj.celBodyData))))
                            parentBody = bodyInfo.getParBodyInfo(obj.celBodyData);
                            convertFrame = parentBody.getBodyCenteredInertialFrame();

                        else
                            convertFrame = obj.celBodyData.globalBaseFrame;
                        end

                        cartElem = convertToFrame(cartElem, convertFrame);

                        times = [cartElem.time]';
                        rVects = [cartElem.rVect];
                        vVects = [cartElem.vVect];
                        states = vertcat(rVects, vVects)';
                        bodyInfo.setStateCacheData(times, states, convertFrame);

                        if(not(isempty(hWaitbar)))
                            hWaitbar.Value = i/size(YY,3);
                        end
                    end
                else
                    error('All bodies must be defined with the same orbit epoch.');
                end

%                 if(isvalid(hFig))
%                     close(hFig);
%                 end
            end
        end
    end

    methods(Access=private)
        function [T,Y,YY] = callIntegrator(obj, numericBodies, numericMasses, numericInds, analyticBodies, analyticInds, t0, tf, y0, hWaitbar)
            numPts = length(numericBodies);

            ptCombsNum = getPtsCombs(numericInds, numericInds, true);
            ptCombsAnalytic = getPtsCombs(numericInds, analyticInds, false);

            massesAnalytic = [analyticBodies.gm];

            hWaitbar.Indeterminate = false;

            odefcn = @(t,y) odefun(t,y, numericMasses, numPts, ptCombsNum, massesAnalytic, ptCombsAnalytic, analyticBodies, obj.celBodyData);
            options = odeset('AbsTol',1E-10, 'RelTol',1E-6, ...
                             'OutputFcn',@(t,y,flag) outputFcn(t,y,flag, t0, tf, hWaitbar)); %'Events',@(t,y) myEventsFcn(t,y, numPts, masses, density, ptCombs),
                                                                             %'OutputFcn',@(t,y,flag) myOutputFcn(t,y,flag), ...

            tspan = [t0 tf];
            [T,Y] = ode113(odefcn, tspan, y0, options);

            YY = reshape(Y, size(Y,1), size(Y,2)/numPts, numPts);
        end
    end

    methods(Static, Access=private)
        function [y0, masses] = getInitialStates(bodies)
            rVects = NaN(3, length(bodies));
            vVects = rVects;
            masses = NaN(1, length(bodies));
            for(i=1:length(bodies))
                bodyInfo = bodies(i);

                [rVectB, vVectB] = getPositOfBodyWRTSun(bodyInfo.epoch, bodyInfo, bodyInfo.celBodyData);
                rVects(:,i) = rVectB(:);
                vVects(:,i) = vVectB(:);
                masses(i) = bodyInfo.gm;
            end

            states = [rVects;vVects];
            y0 = states(:);
        end
    end
end

function ydot = odefun(t,y, masses, numPtsNumeric, ptCombsNumeric, massesAnalytic, ptCombsAnalytic, analyticBodies, celBodyData)
    %Gravity from numerically propagated bodies
    states = reshape(y, 6, numPtsNumeric);
    rVects = states(1:3,:);
    vVects = states(4:6,:);

    ydot = NaN(size(states));
    ydot(1:3,:) = vVects;

    rDiffs = rVects(:, ptCombsNumeric(2,:)) - rVects(:, ptCombsNumeric(1,:));
    rDiffMags = sqrt(sum((rDiffs.^2), 1));

    massProducts = masses(ptCombsNumeric(2,:));

    fVectMag = (massProducts ./ (rDiffMags.^3));
    accelVects = bsxfun(@times, fVectMag, rDiffs);

    accelVects = reshape(accelVects, [3, size(accelVects,2)/numPtsNumeric, numPtsNumeric]);
    accelVectsTotalNumeric = sum(accelVects,2);
    accelVectsTotalNumeric = reshape(accelVectsTotalNumeric,[3,numPtsNumeric]);

    %Gravity from analytic propagated bodies
    if(not(isempty(massesAnalytic)))
        rVectAnalytic = NaN(3,numel(analyticBodies));
        for(i=1:length(analyticBodies))
            rVectAnalytic(:,i) = getPositOfBodyWRTSun(t, analyticBodies(i), celBodyData);
        end

        rDiffs = -1*(rVects(:, ptCombsAnalytic(2,:)) - rVectAnalytic(:, ptCombsAnalytic(1,:)));
        rDiffMags = sqrt(sum((rDiffs.^2), 1));

        massProducts = massesAnalytic(ptCombsAnalytic(1,:));

        fVectMag = (massProducts ./ (rDiffMags.^3));
        accelVects = bsxfun(@times, fVectMag, rDiffs);

        accelVectsTotalAnalytic = NaN([3, numPtsNumeric]);
        for(i=1:numPtsNumeric)
            accelVectsTotalAnalytic(:,i) = sum(accelVects(:, ptCombsAnalytic(2,:) == i), 2);
        end
    else
        accelVectsTotalAnalytic = zeros(size(accelVectsTotalNumeric));
    end

    %Sum up inputs
    accelVectsTotal = accelVectsTotalNumeric + accelVectsTotalAnalytic;
    ydot(4:6,:) = accelVectsTotal; %a = F/m
    ydot = ydot(:);
end

%% Output function (for fun)
function status = outputFcn(t,~,flag, t0, tf, hWaitbar)
    if(isempty(flag))
        tPercent = (t-t0)/(tf-t0);
        hWaitbar.Value = tPercent;
    end
    status = 0;
end

%% Utility function(s)
function ptCombs = getPtsCombs(ptInds1, ptInd2, removeDups)
    ptCombs = combvec(ptInds1,ptInd2);

    if(removeDups)
        ptCombs(:, ptCombs(1,:) == ptCombs(2,:)) = []; %eliminate duplicates
    end

    A = ptCombs(1,:);
    B = ptCombs(2,:);
    ptCombs = [B;A];
end


classdef AD9361TRx
    %% properties applicable to simulation-based study
    properties (Constant)
        % WLAN Toolbox functions operate over 1x-rate data.
        % Oversample signal prior to passing it through AD9361 Rx Simulink model.
        ovx = [2 1] % ovx factor = ovx(1)/ovx(2)
    end

    properties
        % AGC mode (applicable only when SIM_MODE is set to 1 or 3)
        % 0 - manual
        % 1 - fast attack
        % 2 - slow attack
        % 3 - fast during preamble, manual during data payload
        AGC_MODE = 3
        % Log output of ADC block? 1/0 - Y/N
        % The size of log-file will be significantly larger if set to 1
        % since ADC runs at a higher rate than the sample clock.
        % Applicable when SIM_STUDY is set to true.
        LOG_ADC_OUTPUT = 0
        % Save log-data to .mat file? 1/0 - Y/N
        % Applicable when SIM_STUDY is set to true.
        SAVE_LOG_DATA = 1
    end

    properties (Access = private)
        num_sims
        sig_filename
        testwaveform_fileloc
        folder_name
        model
        block
        rx_block
        logged_blocks
        error_message
        log_data
        log_data_indices
    end

    properties
        rxNonHT_2x
        input_waveform
    end

    %% properties applicable to physical radio-based study
    properties
        RXBufferSize = 2^13;
        TransmitRepeat = false
        TimeOut = 2
    end

    methods
        function obj = AD9361TRx(sim_settings, varargin)%ad9361_settings, agc_settings)
            if ~isempty(varargin{1})
                ad9361_settings = varargin{1}{1};
                agc_settings = varargin{1}{2};
            end
            % local variables
            fs = obj.fs;
            M = obj.ovx(1);
            N = obj.ovx(2);
            SampleTime_rx = obj.SampleTime_rx;
            obj.folder_name = 'ad9361_rx_input_files';

            % if (sim_settings.SIM_STUDY)
                %% Simulation-based study
                if ((sim_settings.SIM_MODE == 0) || (sim_settings.SIM_MODE == 2))
                    % Simulation mode #0 or #2 - no simulink-model-in-loop
                    obj.input_waveform = obj.rxWaveform;
                else
                    % Simulation mode #1 or #3 - simulink-model-in-loop
                    % generate all combinations of AGC settings
                    [local_agc_settings, obj.num_sims] = obj.agc_settings_all_combos(agc_settings);

                    % Enable logging for desired signals
                    obj.model = 'ad9361_rx_wlan_testbench';
                    obj.block = 'ad9361_rx';
                    load_system(obj.model); % load model into memory
                    st_param = get_param(obj.model, 'ModelWorkspace');
                    assignin(st_param,'SampleTime_rx', SampleTime_rx); % assign value to sample-time
                    obj = obj.gen_testWaveform_file(); % set Baseband file name
                    obj.rx_block = strcat(obj.model, '/', obj.block);

                    obj.logged_blocks = {['ADC ' newline 'Overload ' newline 'Detector'],...
                        ['LMT ' newline 'Peak ' newline 'Detector'],...
                        'DDC_Filters_RX', 'In', 'Average Power Meter', 'AGC'};
                    if (ad9361_settings.LOG_ADC_OUTPUT)
                        obj.logged_blocks{end+1} = 'ADC_RX';
                    end
                    num_logged_signals = obj.enable_signal_logging();
                    save_system(obj.model);

                    % Tune AGC settings and run the AD9361 simulink model, ...
                    sim_time = ceil(1e4*length(obj.rxNonHT_2x)/(M*fs/N))/1e4;
                    WLAN_ad9361_simin = Simulink.SimulationInput.empty(obj.num_sims, 0);
                    for idx = 1:obj.num_sims
                        WLAN_ad9361_simin(idx) = Simulink.SimulationInput(obj.model);
                        WLAN_ad9361_simin(idx) = WLAN_ad9361_simin(idx).setModelParameter('StopTime',sprintf('%f',sim_time));
                        WLAN_ad9361_simin(idx) = obj.tune_agc_settings(ad9361_settings.AGC_MODE, idx, WLAN_ad9361_simin(idx), local_agc_settings);
                    end
                    WLAN_ad9361_simout = parsim(WLAN_ad9361_simin, 'ShowProgress', 'on');
                    % then, disable signal logging and save model
                    obj.disable_signal_logging();
                    save_system(obj.model);

                    % Extract log-data
                    for idx = 1:obj.num_sims
                        obj.error_message{idx} = WLAN_ad9361_simout(idx).ErrorMessage;
                        [obj.log_data{idx}, obj.log_data_indices{idx}] = obj.extract_log_data(num_logged_signals, WLAN_ad9361_simout(idx));
                        % Resample 9361 output to 1x rate for consumption by WLAN receiver
                        obj.input_waveform{idx} = resample(obj.log_data{idx}{obj.log_data_indices{idx}.AD9361_Output}.Data, N, M);
                    end
                end
%             else
%                 %% Physical radio-based study
%                 obj.TransmitRepeat = false;
%                 obj.TXGain = TXGains;
%
%                 results = RunDeployedDesign(testCase);
%
%
%
%             end

            if ~isempty(varargin{1})
                obj.AGC_MODE = ad9361_settings.AGC_MODE;
                obj.LOG_ADC_OUTPUT = ad9361_settings.LOG_ADC_OUTPUT;
                obj.SAVE_LOG_DATA = ad9361_settings.SAVE_LOG_DATA;
            end
        end

        %% functions applicable to simulation-based study
        % determine all combinations of AGC settings to apply
        function [local_agc_settings, num_combos] = agc_settings_all_combos(obj, agc_settings)
            AGC_fields = fields(agc_settings);
            tuned_settings = [];
            for ii = 1:length(AGC_fields)
                if (length(agc_settings.(AGC_fields{ii})) > 1)
                    tuned_settings = [tuned_settings; ii length(agc_settings.(AGC_fields{ii}))];
                end
            end
            if isempty(tuned_settings)
                local_agc_settings = agc_settings;
                num_combos = 1;
            else
                num_combos = prod(tuned_settings(:, 2));
                num_params = length(tuned_settings(:, 2));

                count = 1;
                sets = cell(num_params, 1);
                combos = zeros(num_combos, num_params);
                for ii = tuned_settings(:, 1).'
                    sets{count} = agc_settings.(AGC_fields{ii});
                    count = count+1;
                end
                combos_temp = cell(1,num_params);
                [combos_temp{:}] = ndgrid(sets{:});
                for ii = 1:num_params
                    combos(:, ii) = combos_temp{ii}(:);
                end

                for ii = 1:length(AGC_fields)
                    if ~ismember(ii, tuned_settings(:, 1))
                        local_agc_settings.(AGC_fields{ii}) = agc_settings.(AGC_fields{ii})*ones(1, num_combos);
                    end
                end
                count = 1;
                for ii = tuned_settings(:, 1).'
                    local_agc_settings.(AGC_fields{ii}) = combos(:, count).';
                    count = count+1;
                end
            end
        end

        % save the test waveform in a baseband file format
        function obj = gen_testWaveform_file(obj)
            fc = obj.fc;
            fs = obj.fs;
            M = obj.ovx(1);
            N = obj.ovx(2);

            warning('off', 'MATLAB:MKDIR:DirectoryExists');
            mkdir(obj.folder_name);
            obj.sig_filename = char('testWaveform_'+regexprep(string(datetime),'[:-\s]','_')+'.bb');
            obj.testwaveform_fileloc = [pwd '\' obj.folder_name '\' obj.sig_filename];
            obj.rxNonHT_2x = resample(obj.rxWaveform, M, N);
            bbw = comm.BasebandFileWriter(obj.testwaveform_fileloc,(M/N)*fs,fc);
            bbw.Metadata = struct('Date',date);
            bbw(obj.rxNonHT_2x);
            release(bbw);

            top_level_blocks = find_system(obj.model);
            for ii = 1:length(top_level_blocks)
                blocks_path = strsplit(top_level_blocks{ii}, '/');
                if (length(blocks_path) < 2)
                    continue;
                end
                str = regexprep(blocks_path{2},'[\n\r-\s_]','');
                if strcmpi(str, 'BasebandFileReader')
                    set_param(top_level_blocks{ii},'Filename',obj.testwaveform_fileloc);
                    break;
                end
            end

            % configure filter parameters
            set_param([obj.model '/' obj.block],'RF',num2str(fc));
            set_param([obj.model '/' obj.block],'LO',num2str(fc));
            set_param([obj.model '/' obj.block],'Trf', [num2str(obj.SampleTime_rx) '/' num2str(M/N)]);
        end

        % programmatically enable logging selected blocks in the Simulink
        % model
        function num_logged_signals = enable_signal_logging(obj)
            num_logged_signals = 0;
            for ii = 1:length(obj.logged_blocks)
                rx_under_mask = [obj.rx_block '/' obj.logged_blocks{ii}];
                ph = get_param(rx_under_mask,'PortHandles');
                str = regexprep(obj.logged_blocks{ii},'[\n\r-\s_]','');
                switch (str)
                    case {'LMTPeakDetector', 'ADCOverloadDetector', 'DDCFiltersRX'}
                        set_param(ph.Outport(1),'DataLogging','on');
                        set_param(ph.Outport(2),'DataLogging','on');
                        num_logged_signals = num_logged_signals+2;
                    otherwise
                        set_param(ph.Outport(1),'DataLogging','on');
                        num_logged_signals = num_logged_signals+1;
                end
            end
        end

        % programmatically disable logging selected blocks in the Simulink
        % model
        function disable_signal_logging(obj)
            for ii = 1:length(obj.logged_blocks)
                rx_under_mask = [obj.rx_block '/' obj.logged_blocks{ii}];
                ph = get_param(rx_under_mask,'PortHandles');
                str = regexprep(obj.logged_blocks{ii},'[\n\r-\s_]','');
                switch (str)
                    case {'LMTPeakDetector', 'ADCOverloadDetector', 'DDCFiltersRX'}
                        set_param(ph.Outport(1),'DataLogging','off');
                        set_param(ph.Outport(2),'DataLogging','off');
                    otherwise
                        set_param(ph.Outport(1),'DataLogging','off');
                end
            end
        end

        % programmatically set AGC parameters in the Simulink model
        function in = tune_agc_settings(obj, AGC_MODE, idx, in, AGC_settings)
            % Toggle manual switch to select AGC mode control input
            rx_top_level = find_system(obj.model);
            for ii = 1:length(rx_top_level)
                rx_top_level_path = strsplit(rx_top_level{ii}, '/');
                if (length(rx_top_level_path) < 2)
                    continue;
                end

                str = regexprep(rx_top_level_path{2},'[\n\r-\s_]','');
                if strcmpi(str, 'ManualSwitch')
                    if (AGC_MODE == 3)
                        in = in.setBlockParameter(rx_top_level{ii}, 'sw', '0');
                    else
                        in = in.setBlockParameter(rx_top_level{ii}, 'sw', '1');
                    end
                elseif strcmpi(str, 'Attackmode')
                    if (AGC_MODE ~= 3)
                        if (AGC_MODE == 0)
                            in = in.setBlockParameter(rx_top_level{ii}, 'Attackmode', 'Manual');
                        elseif (AGC_MODE == 1)
                            in = in.setBlockParameter(rx_top_level{ii}, 'Attackmode', 'Fast');
                        elseif (AGC_MODE == 2)
                            in = in.setBlockParameter(rx_top_level{ii}, 'Attackmode', 'Slow');
                        end
                    end
                end
            end

            rx_under_mask = find_system(obj.rx_block, 'LookUnderMasks', 'on', 'SearchDepth', 1);

            for ii = 1:length(rx_under_mask)
                logged_block_path = strsplit(rx_under_mask{ii}, '/');
                if (length(logged_block_path) < 3)
                    continue;
                end

                str = regexprep(logged_block_path{3},'[\n\r-\s_]','');
                if strcmpi(str, 'AGC')
                    % set AGC mask parameters
                    in = in.setBlockParameter(rx_under_mask{ii}, 'AGC_attack_delay', '1');
                    in = in.setBlockParameter(rx_under_mask{ii}, 'Max_Increase', num2str(AGC_settings.MaxIncrease(idx)));
                    in = in.setBlockParameter(rx_under_mask{ii}, 'EnergyLost', num2str(AGC_settings.EnergyLostLevel(idx)));
                    in = in.setBlockParameter(rx_under_mask{ii}, 'LowPower', num2str(AGC_settings.LowPwrTh(idx)));
                    in = in.setBlockParameter(rx_under_mask{ii}, 'AGC_G_inc_fast', num2str(AGC_settings.AvgPwrLInc(idx)));
                    in = in.setBlockParameter(rx_under_mask{ii}, 'AGC_G_inc_slow', num2str(AGC_settings.AvgPwrSInc(idx)));
                    in = in.setBlockParameter(rx_under_mask{ii}, 'AGC_G_dec_fast', num2str(AGC_settings.AvgPwrLDec(idx)));
                    in = in.setBlockParameter(rx_under_mask{ii}, 'AGC_G_dec_slow', num2str(AGC_settings.AvgPwrSDec(idx)));
                    in = in.setBlockParameter(rx_under_mask{ii}, 'AGC_lock_level', num2str(AGC_settings.AGCLockLevel(idx)));
                elseif strcmpi(str, 'LMTPeakDetector')
                    in = in.setBlockParameter(rx_under_mask{ii}, 'HThreshold', num2str(AGC_settings.LMT_Hth(idx)));
                    in = in.setBlockParameter(rx_under_mask{ii}, 'LThreshold', num2str(AGC_settings.LMT_Lth(idx)));
                elseif strcmpi(str, 'ADCOverloadDetector')
                    in = in.setBlockParameter(rx_under_mask{ii}, 'Hthreshold', num2str(AGC_settings.ADC_Hth(idx)));
                    in = in.setBlockParameter(rx_under_mask{ii}, 'Lthreshold', num2str(AGC_settings.ADC_Lth(idx)));
                    in = in.setBlockParameter(rx_under_mask{ii}, 'Ncycles', num2str(AGC_settings.ADC_Ncycles(idx)));
                elseif strcmpi(str, 'AveragePowerMeter')
                    in = in.setBlockParameter(rx_under_mask{ii}, 'Ncycles', num2str(AGC_settings.AvgPwrMtr_Ncycles(idx)));
                end
            end
        end

        % extract log data from each of the logged blocks in the Simulink
        % model
        function [log_data, indices] = extract_log_data(obj, num_logged_signals, WLAN_ad9361_sim)
            log_data = cell(num_logged_signals, 1);
            for ii = 1:num_logged_signals
                if (isprop(WLAN_ad9361_sim,'logsout'))
                    simData_sigObj = WLAN_ad9361_sim.logsout{ii};
                else
                    continue;
                end
                logged_block_path = strsplit(simData_sigObj.BlockPath.getBlock(1), '/');
                block_name = regexprep(logged_block_path{3},'[\n\r-\s_]','');

                % Enable both output ports for some blocks and for the remaining,
                % enable the only output port
                switch block_name
                    case 'ADCOverloadDetector'
                        if (simData_sigObj.PortIndex == 1)
                           log_data{ii} = struct('Name', strcat(block_name,'Low'), 'Time', simData_sigObj.Values.Time);
                           indices.ADC_Peak_Detector_Low = ii;
                        elseif (simData_sigObj.PortIndex == 2)
                           log_data{ii} = struct('Name', strcat(block_name,'High'), 'Time', simData_sigObj.Values.Time);
                           indices.ADC_Peak_Detector_High = ii;
                        end
                    case 'LMTPeakDetector'
                        if (simData_sigObj.PortIndex == 1)
                           log_data{ii} = struct('Name', strcat(block_name,'High'), 'Time', simData_sigObj.Values.Time);
                           indices.LMT_Peak_Detector_High = ii;
                        elseif (simData_sigObj.PortIndex == 2)
                           log_data{ii} = struct('Name', strcat(block_name,'Low'), 'Time', simData_sigObj.Values.Time);
                           indices.LMT_Peak_Detector_Low = ii;
                        end
                    case 'DDCFiltersRX'
                        if (simData_sigObj.PortIndex == 1)
                           log_data{ii} = struct('Name', strcat(block_name,'OutputPwr'), 'Time', simData_sigObj.Values.Time);
                           indices.AD9361_Output_Power = ii;
                        elseif (simData_sigObj.PortIndex == 2)
                           log_data{ii} = struct('Name', strcat(block_name,'OutputSig'), 'Time', simData_sigObj.Values.Time);
                           indices.AD9361_Output = ii;
                        end
                    otherwise
                        log_data{ii} = struct('Name', block_name, 'Time', simData_sigObj.Values.Time);
                        if (strcmp(block_name, 'ADCRX'))
                            indices.ADC_Output = ii;
                        elseif strcmp(block_name, 'LPFRX')
                            indices.ADC_Input = ii;
                        elseif strcmp(block_name, 'In')
                            indices.AD9361_Input = ii;
                        elseif strcmp(block_name, 'RealImagtoComplex1')
                            indices.LMT_Output = ii;
                        elseif strcmp(block_name, 'AGC')
                            indices.AGC_Gain = ii;
                        elseif strcmp(block_name, 'AveragePowerMeter')
                            indices.Digital_Power = ii;
                        end
                end

                % if log-data is in (1x1xN) matrix format, extract data along the third dimension
                if (numel(size(simData_sigObj.Values.Data)) == 3)
                    log_data{ii}.Data = permute(simData_sigObj.Values.Data(1,1,:),[3 1 2]);
                else
                    log_data{ii}.Data = simData_sigObj.Values.Data;
                end
            end
        end

        %% functions applicable to physical radio-based study
        function results = RunDeployedDesign(obj)
            % waveform transmitted by the radio
            txWaveform = int16(2^15.*obj.txFrms./max(abs(obj.txFrms)));

            % HW setup
            [rx, tx] = obj.SetupHardware(obj.fs,obj.fc);
            obj.reTuneRadio(rx,tx,txWaveform);
            [rx, tx] = testCase.SetupHardware(obj.fs,obj.fc);

            % Transmit and Receive
            fprintf('Initializing RX and TX devices\n');
            if (obj.TransmitRepeat)
                tx.EnableCyclicBuffers = true;
                tx(txWaveform);
                pause(0.1);
            end
            % Clean buffer
            fprintf('Cleaning buffer \n');
            for k = 10:-1:0
                if ~obj.TransmitRepeat
                    % Send packets
                    pause(1);
                    tx(txWaveform);
                end
                rx();
                fprintf('%d ',k);
                pause(0.1);
            end

        end

        function reTuneRadio(testCase,rx,tx,data)
            rx.SamplingRate = fix(rx.SamplingRate*0.9);
            tx.SamplingRate = fix(tx.SamplingRate*0.9);
            rx.CenterFrequency = fix(rx.CenterFrequency*0.9);
            tx.CenterFrequency = fix(tx.CenterFrequency*0.9);
            tx(data);
            for l=1:10
                rx();
            end
            clear rx tx;
            system(['ssh -t root@',testCase.radioIP(4:end),' /root/reg/reg']);
        end

        function [rx,tx] = SetupHardware(obj,Rs,fc)
            % Receiver and transmitter objects
            rx = adi.AD9361.Rx;
            tx = adi.AD9361.Tx;
            rx.uri = testCase.radioIP;
            tx.uri = testCase.radioIP;
            rx.channelCount = 4;
            rx.SamplingRate = Rs;
            tx.SamplingRate = Rs;
            tx.AttenuationChannel0 = obj.TXGain;
            rx.RFBandwidth = fix(Rs*1.2);
            tx.RFBandwidth = fix(Rs*1.2);
            if (AGC_MODE == 0)
                rx.GainControlModeChannel0 = 'manual';
            elseif (AGC_MODE == 1)
                rx.GainControlModeChannel0 = 'slow_attack';
            elseif (AGC_MODE == 2)
                rx.GainControlModeChannel0 = 'fast_attack';
            end

            % Receiver Setup
            rx.DataTimeout = obj.TimeOut;
            rx.CenterFrequency = obj.fc;
            rx.SamplesPerFrame = obj.RXBufferSize;

            % Transmitter Setup
            tx.CenterFrequency = obj.fc;
        end

    end
end


function [ output_meta ] = meta2sicd_acft( acft_struct )
%META2SICD_ACFT Converts metadata stored in the ACFTA/B NITF TRE into a
% SICD metadata format
%
% Written by: Wade Schwartzkopf, NGA/IDT
%
% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////

M2F=3.28083989501312; % Set meters-to-feet conversion constant

if ~isempty(acft_struct.SENSOR_ID)
    output_meta.CollectionInfo.CollectorName=acft_struct.SENSOR_ID;
end

% This NITF value is actually the ground plane spacing.  Should actually be
% multiplied by cos of graze angle for SICD slant plane spacing.
output_meta.Grid.Col.SS=acft_struct.ROW_SPACING;
% This NITF value is actually the ground plane spacing.  Should actually be
% multiplied by cos of tilt angle for SICD slant plane spacing.
output_meta.Grid.Row.SS=acft_struct.COL_SPACING;

if ~isfield(acft_struct,'ROW_SPACING_UNITS')||acft_struct.ROW_SPACING_UNITS=='f'
    output_meta.Grid.Col.SS=output_meta.Grid.Col.SS/M2F;
end
if ~isfield(acft_struct,'COL_SPACING_UNITS')||acft_struct.COL_SPACING_UNITS=='f'
    output_meta.Grid.Row.SS=output_meta.Grid.Row.SS/M2F;
end

end

% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////


function h = dtiLoadDt6Gui(h, fname)
% Load a dt6 (tensor) data file into the mrDiffusion GUI handle structure.
%
%    handles = dtiLoadDt6Gui(handles, dt6fname);
%
% This routine adds a number of background images and data values from a
% dt6 file and adds them to the window handle struct.
%
% The name of the main figure is adjusted to be mrdMain <subName>
%
% If you want to load a dt6 struct without attaching the data to the GUI
% (like in a batch script), use dtiLoadDt6.
%
% Example:
%
% To load a file and attach it to the window, but without bringing up the
% load GUI, use
%
%  dtiFiberUI;
%  dt6Name = fullfile(mrvDataRootPath,'diffusion','sampleData','dti40','dt6.mat')
%  f = dtiGet; h = guidata(f);
%  h = dtiLoadDt6Gui(h, dt6Name);
%  guidata(f, h);
%  h = dtiRefreshFigure(h);
%
% See also:  dtiLoadDt6, dtiFiberUI, t_mrd
%
% (c) Stanford VISTA Team

% TODO
% There is another function, handles = updateStandardSpaceValue(handles);
% that Bob calls.  I am not sure why it is there as well. I didn't put it
% in the example.
% Perhaps this routine should include the guidata() call to attach the
% updated handles, rather than have that be done on the return.
%

% Always apply the brain mask
applyBrainMask = true;

% Load the data from the file and apply the mask
if(~exist('fname','var')), fname = []; end
[dt, t1] = dtiLoadDt6(fname, applyBrainMask);
if(isempty(dt)), return; end

% Clear old data
if(isfield(h, 'bg')), h = rmfield(h, {'bg'}); end
set(h.popupBackground, 'String', {'loading...'});
set(h.popupOverlay, 'String', {'loading...'});

% Go through the dt field names and replace the data in handles. This
% attaches the dt6 structure and many other parameters to the figure
% handle.
fn = fieldnames(dt);
for ii=1:length(fn)
    h.(fn{ii}) = dt.(fn{ii});
end
clear dt;

h.dataDir = fileparts(h.dataFile);
h.defaultPath = h.dataDir;

% Add the b=0 image data
h = dtiAddBackgroundImage(h, double(h.b0), 'b0', h.mmPerVoxel, h.xformToAcpc, [0.4 0.99], 1, 'arb');
h = rmfield(h,'b0');

% The dt6 was attached to h above.
[eigVec, eigVal] = dtiSplitTensor(h.dt6);
eigVal(isnan(eigVal)|eigVal<0) = 0;
md = mean(eigVal,4);
h = dtiAddBackgroundImage(h, md, 'Mean Diffusivity', h.mmPerVoxel, h.xformToAcpc, [], 0, h.adcUnits, [0 5 1]);

fa = dtiComputeFA(eigVal);
fa(isnan(fa)) = 0; fa(fa>1) = 1; fa(fa<0) = 0;
[h, faNum] = dtiAddBackgroundImage(h, fa, 'FA', h.mmPerVoxel, h.xformToAcpc, [0 1], 0, 'ratio');
set(h.popupOverlay, 'Value', faNum);

img = squeeze(eigVec(:,:,:,[1 2 3],1));
img(isnan(img)) = 0;
img = abs(img);
for ii=1:3, img(:,:,:,ii) = img(:,:,:,ii).*fa; end
h = dtiAddBackgroundImage(h, img, 'vectorRGB', h.mmPerVoxel, h.xformToAcpc, [0 1], 0, '');

% For some reason, the t1 data are handled separately.
if(~isempty(t1) && isfield(t1,'img'))
	h = dtiAddBackgroundImage(h, double(t1.img), 't1', t1.mmPerVoxel, t1.xformToAcpc, [0.4 0.99], 1, 'arb');
    if(isfield(t1,'brainMask'))
        h.brainMask = t1.brainMask;
        h.brainMaskXform = t1.brainMaskXform;
    end
end

if(isfield(t1,'talairachScale'))
    h.talairachScale = t1.talairachScale;
    h = dtiSet(h, 'addStandardSpace', 'Talairach');
end

if(isfield(t1,'t1NormParams'))
    h.t1NormParams = t1.t1NormParams;
    if(isfield(h.t1NormParams,'name'))
        for ii=1:length(h.t1NormParams)
            h = dtiSet(h, 'addStandardSpace', h.t1NormParams(ii).name);
        end
        if(~isempty(strmatch('MNI',{h.t1NormParams.name})))
            labels = dtiGetBrainLabel;
            for ii=1:length(labels)
                h = dtiSet(h, 'addStandardSpace', labels{ii});
            end
        end
    end
end

% Add the subject name to the figure name.
h.title =  sprintf('mrdMain%d %s',h.fig,h.subName);
set(h.fig,'Name',h.title);

return;