function [F,V,C]=delaunayZip(F1,V1,F2,V2,inputStruct)

% function [Fn]=delaunayZip(F1,V1,F2,V2,inputStruct)
%-------------------------------------------------------------------------
%
%
% Change log:
% 2018/05/09: Added growing of region size if error occurs
% 2018/05/09: Added stepwise removal of last triangle since it does not
% include next points.
% 2018/11/02: Added self-triangulation as an option (default on)
% 2018/11/02: Added walk-back for paths so that one will not be too long
% 2018/11/02: Fixed bug in relation to one of the paths "running out of
% points". Remainder is triangulated properly.
%-------------------------------------------------------------------------

%%

maxD=max([patchEdgeLengths(F1,V1);patchEdgeLengths(F2,V2)]);

defaultInputStruct.ind1=[];
defaultInputStruct.ind2=[];
defaultInputStruct.distLocal=2*maxD;
defaultInputStruct.startInd=[];
defaultInputStruct.plotOn=0;
defaultInputStruct.selfTriangulate=1; %Option to self-triangulate surfaces first
defaultInputStruct.angleThreshold=(60/180)*pi; %Angular threshold for self-triangulation
[inputStruct]=structComplete(inputStruct,defaultInputStruct,0); %Complement provided with default if missing or empty

ind1=inputStruct.ind1;
ind2=inputStruct.ind2;
distLocal=inputStruct.distLocal;
startInd=inputStruct.startInd;
selfTriangulate=inputStruct.selfTriangulate;
angleThreshold=inputStruct.angleThreshold;
plotOn=inputStruct.plotOn;

%% Self-triangulate if needed

if selfTriangulate==1
    if ind1(1)==ind1(end)
        isClosedLoop=1;
    else
        isClosedLoop=0;
    end
    numFacesInitial_1=size(F1,1);
    [F1,V1,ind1]=triSurfSelfTriangulateBoundary(F1,V1,ind1,angleThreshold,isClosedLoop);
    numFaces_1=size(F1,1);
    numFacesInitial_2=size(F2,1);
    [F2,V2,ind2]=triSurfSelfTriangulateBoundary(F2,V2,ind2,angleThreshold,isClosedLoop);
    numFaces_2=size(F2,1);

    L1=false(size(F1,1),1);
    if numFaces_1>numFacesInitial_1
        L1(end-(numFaces_1-numFacesInitial_1-1):end)=1;
    end
    L2=false(size(F2,1),1);
    if numFaces_2>numFacesInitial_2
        L2(end-(numFaces_2-numFacesInitial_2-1):end)=1;
    end
else
    L1=zeros(size(F1,1),1);
    L2=zeros(size(F2,1),1);
end

%%
[F,V,C]=joinElementSets({F1,F2},{V1,V2});
[~,~,Nv]=patchNormal(F,V);

%%

ind2=ind2+size(V1,1);
startInd(2)=startInd(2)+size(V1,1);

%%
%Create edges list
E=[ind1(1:end-1) ind1(2:end); ind2(1:end-1) ind2(2:end)];

%%

logicNotUsed=ismember((1:1:size(V,1))',E); %Logic to keep track of points that are used

%Initialize other parameters
Fn=[]; %Faces
Cn=[]; %"Colors"=step count for face group
c=1; %While loop counter variable

indGroup=startInd(:); %Initialize current group
numGroup=numel(indGroup); %Initialize current number of members of the current group
numGroupPrevious=0;

if plotOn==1
    h1=[]; %Initiate empty plot handle
    markerSize=25;

    hf=cFigure; hold on;
    gpatch(F1(~L1,:),V1,'r','none',0.2);
    gpatch(F1(L1,:),V1,'rw','k',1);
    gpatch(F2(~L2,:),V2,'b','none',0.2);
    gpatch(F2(L2,:),V2,'bw','k',1);
    plotV(V(ind1,:),'r.-','LineWidth',1,'MarkerSize',10);
    plotV(V(ind2,:),'b.-','LineWidth',1,'MarkerSize',10);

    axisGeom;
    camlight headlight;
    colormap(gjet(250));
    colorbar;
    drawnow;
end

%Turn off Delaunay warning as this case is handled properly
warning('off','MATLAB:delaunayTriangulation:ConsConsSplitWarnId');

%%
while 1

    numGroupStep=1;
    lastTry=0;
    while 1
        try
            if plotOn==1 %%Plot if plotting is on
                delete(h1); h1=[];
            end

            if plotOn==1 %%Plot if plotting is on
                figure(hf);
                h1(end+1)=plotV(V(startInd,:),'y.','MarkerSize',markerSize);
                drawnow
            end

            %Grow the current region
            while 1 %Loop to form local group (stuff attached to current group within a given distance)
                logicMember=any(ismember(E,indGroup),2); %Logic for all edges touching the current groupt
                E_sub=E(logicMember,:); %The subset of touching edges

                indGroup=unique([indGroup; E_sub(:)]); %Grow group with point indices in the edges that are touching

                d1=sqrt(sum((V(indGroup,:)-V(startInd(1)*ones(numel(indGroup),1),:)).^2,2));
                d2=sqrt(sum((V(indGroup,:)-V(startInd(2)*ones(numel(indGroup),1),:)).^2,2));
                D=min(d1,d2);

                logicKeep= (D<distLocal) & (logicNotUsed(indGroup));
                indGroup=indGroup(logicKeep); %Remove points that are too far
                if numGroup==numel(indGroup) %Compare current group size to previous step
                    break %break while loop if the group is no longer growing
                end
                numGroup=numel(indGroup); %Get new current group size
            end

            %Get curve start and end points
            logicMember=all(ismember(E,indGroup),2); %Logic for all edges touching the current group
            E_sub=E(logicMember,:); %The subset of touching edges

            [~,~,~,vCount]=cunique(E_sub); %Get vertex occurance counts
            indEndPoints=unique(E_sub(vCount==1));
            indEndPoints1=indEndPoints(ismember(indEndPoints,ind1));
            indEndPoints2=indEndPoints(ismember(indEndPoints,ind2));

            %Compose sub-curves
            logicSub1=all(ismember(E_sub,ind1),2);
            %             if ~any(logicSub1)
            %                 warning('None of the current edges nodes are a member of ind1');
            %             end
            E_sub1=E_sub(logicSub1,:);
            [indListSub1]=edgeListToCurve(E_sub1);
            indListSub1=indListSub1(:);

            logicSub2=all(ismember(E_sub,ind2),2);
            %             if ~any(logicSub2)
            %                 warning('None of the current edges nodes are a member of ind2');
            %             end
            E_sub2=E_sub(logicSub2,:);
            [indListSub2]=edgeListToCurve(E_sub2);
            indListSub2=indListSub2(:);

            %Alter segments so they can be merged into closed loop curve
            if isempty(Fn) %First iteration
                d=sqrt(sum((V([indListSub2(1) indListSub2(end)],:)-V(indListSub1(1)*ones(1,2),:)).^2,2));
                [~,indClosest]=min(d);
                if indClosest~=2 %If the start is closest to the other start
                    indListSub2=flipud(indListSub2);
                end
            else
                indStart1=find(ismember(indListSub1,startInd));
                if indStart1~=1
                    indListSub1=flipud(indListSub1);
                end
                indStart2=find(ismember(indListSub2,startInd));
                if indStart2==1
                    indListSub2=flipud(indListSub2);
                end
            end

            if any(ismember(indGroup,ind1))==0
                startInd
                ind1
                indGroup
            end

            %             if any(ismember(indGroup,ind1)) && any(ismember(indGroup,ind2))
            %             else
            %                 %One of the two sets contains only 1 member, triangulate
            %                 %remaining points manually
            %
            %                 %-----------------------------------
            %                 if nnz(ismember(indGroup,ind1))==0
            %                     indLeft=flipud(indListSub2);
            %                     sKeep=startInd(ismember(startInd,ind1));
            %                 else%if nnz(ismember(indGroup,ind2))==0
            %                     indLeft=indListSub1;
            %                     sKeep=startInd(ismember(startInd,ind2));
            %                 end
            %
            %                 f=[];
            %                 for qStep=1:1:numel(indLeft)-1
            %                     sVary=indLeft(1);
            %                     f=[f; [sKeep sVary indLeft(2)]];
            %                     indLeft=indLeft(2:end); %First is part of startInd
            %                 end
            %             end

            %Shorten curves if they stick out to much wrt end of other curve
            d=sqrt(sum((V(indListSub2,:)-V(indListSub1(end)*ones(1,numel(indListSub2)),:)).^2,2));
            [~,indClosest]=min(d);
            if indClosest~=1 && indClosest~=numel(indListSub2)
                indListSub2=indListSub2(indClosest:end);
            end

            d=sqrt(sum((V(indListSub1,:)-V(indListSub2(1)*ones(1,numel(indListSub1)),:)).^2,2));
            [~,indClosest]=min(d);
            if indClosest~=numel(indListSub1) && indClosest~=1
                indListSub1=indListSub1(1:indClosest);
            end

            %Create closed curve
            if nnz(ismember(indGroup,ind1))==0
                indListSub=[startInd(ismember(startInd,ind1)); indListSub2; startInd(ismember(startInd,ind1))]; %Closed loop
            elseif nnz(ismember(indGroup,ind2))==0
                indListSub=[startInd(ismember(startInd,ind2)); indListSub1; startInd(ismember(startInd,ind2))]; %Closed loop
            else
                indListSub=[indListSub1;indListSub2;indListSub1(1)]; %Closed loop
            end

            indGroup=indListSub(1:end-1);

            if plotOn==1 %%Plot if plotting is on
                figure(hf);
                if ~isempty(indEndPoints1)
                    h1(end+1)=plotV(V(indEndPoints1,:),'r.','MarkerSize',markerSize);
                end
                if ~isempty(indEndPoints2)
                    h1(end+1)=plotV(V(indEndPoints2,:),'b.','MarkerSize',markerSize);
                end
                if ~isempty(indListSub1)
                    h1(end+1)=plotV(V(indListSub1,:),'r-','LineWidth',3);
                end
                if ~isempty(indListSub2)
                    h1(end+1)=plotV(V(indListSub2,:),'b-','LineWidth',3);
                end
                if ~isempty(indListSub)
                    h1(end+1)=plotV(V(indListSub,:),'k-','LineWidth',2);
                end
                drawnow
            end

            %Rotate current point set
            V_now=V(indListSub(1:end-1),:); %Current closed curve coordinate set
            [R]=pointSetPrincipalDir(V_now); %Fit local coordinate system with 3rd direction pointing outward of local planar-ish region
            V_now_R=V_now*R; %Rotate coordinate set to prepare for 2D Delaunay based triangulation

            %Do 2D Delaunay triangulation
            DT_contraints=[(1:numel(indGroup))' ([2:numel(indGroup) 1])']; %Constraints are edges forming boundary
            DT = delaunayTriangulation(V_now_R(:,[1 2]),DT_contraints); % Initial triangulation
            f=DT.ConnectivityList; %Get faces set
            L = isInterior(DT); %Remove faces not inside region
            f=f(L,:); %Faces excluding external faces (only keep those inside constraint edges)
            f=indGroup(f); %Change indices to overall system

            %Remove first and last triangles if there are more than 3 triangles, this
            %will improve triangulation quality as these triangles were not fully
            %embedded in the point set.
            %                 if size(f,1)>2
            %                     logicKeep=~(any(ismember(f,indEndPoints1(~ismember(indEndPoints1,Fn))),2)...
            %                         & any(ismember(f,indEndPoints2(~ismember(indEndPoints2,Fn))),2))...
            %                         | any(ismember(f,startInd),2);
            %                     f=f(logicKeep,:);
            %
            %                     [~,~,IND_FF]=tesIND(f,V);
            %                     logicNeighbours=sum(IND_FF>1,2)>1;
            %                     logicNeighbours(any(ismember(f,startInd),2))=1;
            %                     f=f(logicNeighbours,:);
            %                 end

            break

        catch ME
            if lastTry==1
                rethrow(ME)
            end

            if numGroupStep==numGroupPrevious
                lastTry=1;
            end
            distLocal=distLocal+maxD;
            warning(['Failed using current step size, increasing to: ',num2str(distLocal)]);
            numGroupPrevious=numGroupStep;
        end
    end
    distLocal=inputStruct.distLocal; %reset

    if dot(mean(patchNormal(f,V),1),mean(Nv(indListSub(1:end-1),:),1))<0
        f=fliplr(f);
    end

    if plotOn==1 %%Plot if plotting is on
        figure(hf);
        V_now_mean=mean(V_now); %Mean of coordinate set
        h1(end+1)=plotV(V_now_mean,'kx','MarkerSize',markerSize);
        gpatch(f,V,c*ones(size(f,1),1),'k',1);
        drawnow
    end

    %Collect faces and color data
    Fn=[Fn;f];
    Cn=[Cn;c*ones(size(f,1),1)];

    E_Fn=sort(patchEdges(Fn,0),2);
    ind_E_Fn= reshape(sub2indn(size(V,1)*ones(1,2),E_Fn),size(Fn));

    Es=sort(E,2);
    ind_E= sub2indn(size(V,1)*ones(1,2),Es);

    logicEdgesUsed=ismember(ind_E,ind_E_Fn);

    E_sub=E(~logicEdgesUsed,:);
    indUnusedPoints=unique(E_sub);
    logicNotUsed=false(size(logicNotUsed));
    logicNotUsed(indUnusedPoints)=1;

    if any(logicNotUsed)==0
        break
    end

    %Get curve start and end points
    [~,~,~,vCount]=cunique(E_sub); %Get vertex occurance counts
    indEndPoints=unique(E_sub(vCount==1));
    indEndPoints1=indEndPoints(ismember(indEndPoints,ind1));
    indEndPoints2=indEndPoints(ismember(indEndPoints,ind2));

    e=patchEdges(Fn,1);
    edgeEndPoints=e(any(ismember(e,indEndPoints1),2)&any(ismember(e,indEndPoints2),2),:);
    logicMemberOfLast=any(ismember(edgeEndPoints,f),2);
    edgeEndPoints=edgeEndPoints(logicMemberOfLast,:);
    if ~isempty(edgeEndPoints)
        startInd=edgeEndPoints(1,:);
    else
        startInd=[indListSub1(end) indListSub2(1)];
    end

    c=c+1;
end

F=[F;Fn];
C=[C; max(C(:))+Cn];

%Turn Delaunay warning back on
warning('on','MATLAB:delaunayTriangulation:ConsConsSplitWarnId');

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


function [cls,M1] = spm_preproc_write8(res,tc,bf,df,mrf,cleanup,bb,vx,odir)
% Write out VBM preprocessed data
% FORMAT [cls,M1] = spm_preproc_write8(res,tc,bf,df,mrf,cleanup,bb,vx,odir)
%__________________________________________________________________________
% Copyright (C) 2008-2016 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: spm_preproc_write8.m 7415 2018-09-10 18:24:16Z john $

% Prior adjustment factor.
% This is a fudge factor to weaken the effects of the tissue priors.  The
% idea here is that the bias from the tissue priors probably needs to be
% reduced because of the spatial smoothing typically used in VBM studies.
% Having the optimal bias/variance tradeoff for each voxel is not the same
% as having the optimal tradeoff for weighted averages over several voxels.

if isfield(res,'mg')
    lkp = res.lkp;
    Kb  = max(lkp);
else
    Kb  = size(res.intensity(1).lik,2);
end
N       = numel(res.image);

if nargin<2, tc = true(Kb,4); end % native, import, warped, warped-mod
if nargin<3, bf = false(N,2); end % field, corrected
if nargin<4, df = false(1,2); end % inverse, forward
if nargin<5, mrf = 1;         end % MRF parameter
if nargin<6, cleanup = 1;     end % Run the ad hoc cleanup
if nargin<7, bb = NaN(2,3);   end % Default to TPM bounding box
if nargin<8, vx = NaN;        end % Default to TPM voxel size
if nargin<9, odir = [];       end % Output directory

% Read essentials from tpm (it will be cleared later)
tpm = res.tpm;
if ~isstruct(tpm) || ~isfield(tpm, 'bg1')
    tpm = spm_load_priors8(tpm);
end
d1      = size(tpm.dat{1});
d1      = d1(1:3);
M1      = tpm.M;

% Define orientation and field of view of any "normalised" space
% data that may be generated (wc*.nii, mwc*.nii, rc*.nii & y_*.nii).
if any(isfinite(bb(:))) || any(isfinite(vx))
    % If a bounding box is supplied, combine this with the closest
    % bounding box derived from the dimensions and orientations of
    % the tissue priors.
    [bb1,vx1] = spm_get_bbox(tpm.V(1), 'old');
    bb(~isfinite(bb)) = bb1(~isfinite(bb));
    if ~isfinite(vx), vx = abs(prod(vx1))^(1/3); end
    bb(1,:) = vx*round(bb(1,:)/vx);
    bb(2,:) = vx*round(bb(2,:)/vx);
    odim    = abs(round((bb(2,1:3)-bb(1,1:3))/vx))+1;

    mm  = [[bb(1,1) bb(1,2) bb(1,3)
            bb(2,1) bb(1,2) bb(1,3)
            bb(1,1) bb(2,2) bb(1,3)
            bb(2,1) bb(2,2) bb(1,3)
            bb(1,1) bb(1,2) bb(2,3)
            bb(2,1) bb(1,2) bb(2,3)
            bb(1,1) bb(2,2) bb(2,3)
            bb(2,1) bb(2,2) bb(2,3)]'; ones(1,8)];
    vx3 = [[1       1       1
            odim(1) 1       1
            1       odim(2) 1
            odim(1) odim(2) 1
            1       1       odim(3)
            odim(1) 1       odim(3)
            1       odim(2) odim(3)
            odim(1) odim(2) odim(3)]'; ones(1,8)];
    mat    = mm/vx3;
else
    % Use the actual dimensions and orientations of
    % the tissue priors.
    odim = tpm.V(1).dim;
    mat  = tpm.V(1).mat;
end

[pth,nam] = fileparts(res.image(1).fname);
if ~isempty(odir) && ischar(odir), pth = odir; end
ind  = res.image(1).n;
d    = res.image(1).dim(1:3);

[x1,x2,o] = ndgrid(1:d(1),1:d(2),1);
x3 = 1:d(3);

chan(N) = struct('B1',[],'B2',[],'B3',[],'T',[],'Nc',[],'Nf',[],'ind',[]);
for n=1:N
    d3         = [size(res.Tbias{n}) 1];
    chan(n).B3 = spm_dctmtx(d(3),d3(3),x3);
    chan(n).B2 = spm_dctmtx(d(2),d3(2),x2(1,:)');
    chan(n).B1 = spm_dctmtx(d(1),d3(1),x1(:,1));
    chan(n).T  = res.Tbias{n};

    % Need to fix writing of bias fields or bias corrected images, when the data used are 4D.
    [pth1,nam1] = fileparts(res.image(n).fname);
    if ~isempty(odir) && ischar(odir), pth1 = odir; end
    chan(n).ind = res.image(n).n;

    if bf(n,2)
        chan(n).Nc      = nifti;
        chan(n).Nc.dat  = file_array(fullfile(pth1,['m', nam1, '.nii']),...
                                     res.image(n).dim(1:3),...
                                     [spm_type('float32') spm_platform('bigend')],...
                                     0,1,0);
        chan(n).Nc.mat  = res.image(n).mat;
        chan(n).Nc.mat0 = res.image(n).mat;
        chan(n).Nc.descrip = 'Bias corrected';
        create(chan(n).Nc);
    end

    if bf(n,1),
        chan(n).Nf      = nifti;
        chan(n).Nf.dat  = file_array(fullfile(pth1,['BiasField_', nam1, '.nii']),...
                                     res.image(n).dim(1:3),...
                                     [spm_type('float32') spm_platform('bigend')],...
                                     0,1,0);
        chan(n).Nf.mat  = res.image(n).mat;
        chan(n).Nf.mat0 = res.image(n).mat;
        chan(n).Nf.descrip = 'Estimated Bias Field';
        create(chan(n).Nf);
    end
end

do_cls   = any(tc(:)) || nargout>=1;
tiss(Kb) = struct('Nt',[]);
for k1=1:Kb
    if tc(k1,4) || any(tc(:,3)) || tc(k1,2) || nargout>=1,
        do_cls  = true;
    end
    if tc(k1,1),
        tiss(k1).Nt      = nifti;
        tiss(k1).Nt.dat  = file_array(fullfile(pth,['c', num2str(k1), nam, '.nii']),...
                                      res.image(n).dim(1:3),...
                                      [spm_type('uint8') spm_platform('bigend')],...
                                      0,1/255,0);
        tiss(k1).Nt.mat  = res.image(n).mat;
        tiss(k1).Nt.mat0 = res.image(n).mat;
        tiss(k1).Nt.descrip = ['Tissue class ' num2str(k1)];
        create(tiss(k1).Nt);
        do_cls = true;
    end
end

prm     = [3 3 3 0 0 0];
Coef    = cell(1,3);
Coef{1} = spm_bsplinc(res.Twarp(:,:,:,1),prm);
Coef{2} = spm_bsplinc(res.Twarp(:,:,:,2),prm);
Coef{3} = spm_bsplinc(res.Twarp(:,:,:,3),prm);

do_defs = any(df);
do_defs = do_cls | do_defs;
if do_defs
    if df(1)
        Ndef      = nifti;
        Ndef.dat  = file_array(fullfile(pth,['iy_', nam, '.nii']),...
                               [res.image(1).dim(1:3),1,3],...
                               [spm_type('float32') spm_platform('bigend')],...
                               0,1,0);
        Ndef.mat  = res.image(1).mat;
        Ndef.mat0 = res.image(1).mat;
        Ndef.descrip = 'Inverse Deformation';
        create(Ndef);
    end
    if df(2) || any(any(tc(:,[2,3,4]))) || nargout>=1,
        y = zeros([res.image(1).dim(1:3),3],'single');
    end
end

spm_progress_bar('init',length(x3),['Working on ' nam],'Planes completed');
M = M1\res.Affine*res.image(1).mat;

if do_cls
    Q = zeros([d(1:3),Kb],'single');
end

for z=1:length(x3)

    % Bias corrected image
    cr = cell(1,N);
    for n=1:N
        f          = spm_sample_vol(res.image(n),x1,x2,o*x3(z),0);
        bf         = exp(transf(chan(n).B1,chan(n).B2,chan(n).B3(z,:),chan(n).T));
        cr{n}      = bf.*f;
        if ~isempty(chan(n).Nc),
            % Write a plane of bias corrected data
            chan(n).Nc.dat(:,:,z,chan(n).ind(1),chan(n).ind(2)) = cr{n};
        end
        if ~isempty(chan(n).Nf),
            % Write a plane of bias field
            chan(n).Nf.dat(:,:,z,chan(n).ind(1),chan(n).ind(2)) = bf;
        end
    end

    if do_defs
        % Compute the deformation (mapping voxels in image to voxels in TPM)
        [t1,t2,t3] = defs(Coef,z,res.MT,prm,x1,x2,x3,M);

        if exist('Ndef','var')
            % Write out the deformation to file, adjusting it so mapping is
            % to voxels (voxels in image to mm in TPM)
            Ndef.dat(:,:,z,1,1) = M1(1,1)*t1 + M1(1,2)*t2 + M1(1,3)*t3 + M1(1,4);
            Ndef.dat(:,:,z,1,2) = M1(2,1)*t1 + M1(2,2)*t2 + M1(2,3)*t3 + M1(2,4);
            Ndef.dat(:,:,z,1,3) = M1(3,1)*t1 + M1(3,2)*t2 + M1(3,3)*t3 + M1(3,4);
        end

        if exist('y','var')
            % If needed later, save in variable y
            y(:,:,z,1) = t1;
            y(:,:,z,2) = t2;
            y(:,:,z,3) = t3;
        end

        if do_cls
            % Generate variable Q if tissue classes are needed
            msk = any((f==0) | ~isfinite(f),3);

            if isfield(res,'mg')
                % Parametric representation of intensity distributions
                q   = zeros([d(1:2) Kb]);
                q1  = likelihoods(cr,[],res.mg,res.mn,res.vr);
                q1  = reshape(q1,[d(1:2),numel(res.mg)]);
                b   = spm_sample_priors8(tpm,t1,t2,t3);
                wp  = res.wp;
                s   = zeros(size(b{1}));
                for k1 = 1:Kb
                    b{k1} = wp(k1)*b{k1};
                    s     = s + b{k1};
                end
                for k1=1:Kb
                    tmp       = sum(q1(:,:,lkp==k1),3);
                    tmp(msk)  = 1e-3;
                    q(:,:,k1) = tmp.*(b{k1}./s);
                end
            else
                % Nonparametric representation of intensity distributions
                q   = spm_sample_priors8(tpm,t1,t2,t3);
                wp  = res.wp;
                s   = zeros(size(q{1}));
                for k1 = 1:Kb
                    q{k1} = wp(k1)*q{k1};
                    s     = s + q{k1};
                end
                for k1 = 1:Kb
                    q{k1} = q{k1}./s;
                end
                q   = cat(3,q{:});

                for n=1:N
                    tmp = round(cr{n}*res.intensity(n).interscal(2) + res.intensity(n).interscal(1));
                    tmp = min(max(tmp,1),size(res.intensity(n).lik,1));
                    for k1=1:Kb
                        likelihood = res.intensity(n).lik(:,k1);
                        q(:,:,k1)  = q(:,:,k1).*likelihood(tmp);
                    end
                end
            end
            Q(:,:,z,:) = reshape(q,[d(1:2),1,Kb]);
        end
    end
    spm_progress_bar('set',z);
end
spm_progress_bar('clear');

cls   = cell(1,Kb);
if do_cls
    P = zeros([d(1:3),Kb],'uint8');
    if mrf==0
        % Normalise to sum to 1
        sQ = (sum(Q,4)+eps)/255;
        for k1=1:size(Q,4)
            P(:,:,:,k1) = uint8(round(Q(:,:,:,k1)./sQ));
        end
        clear sQ
    else
        % Use a MRF cleanup procedure
        nmrf_its = 10;
        spm_progress_bar('init',nmrf_its,['MRF: Working on ' nam],'Iterations completed');
        G   = ones([Kb,1],'single')*mrf;
        vx2 = 1./single(sum(res.image(1).mat(1:3,1:3).^2));
        for iter=1:nmrf_its
            spm_mrf(P,Q,G,vx2);
            spm_progress_bar('set',iter);
        end
    end
    clear Q

    if cleanup
        % Use an ad hoc brain cleanup procedure
        if size(P,4)>3
            P = clean_gwc(P,cleanup);
        else
            warning('Cleanup not done.');
        end
    end

    % Write tissues if necessary
    for k1=1:Kb
        if ~isempty(tiss(k1).Nt)
            for z=1:length(x3)
                tmp = double(P(:,:,z,k1))/255;
                tiss(k1).Nt.dat(:,:,z,ind(1),ind(2)) = tmp;
            end
        end
    end
    spm_progress_bar('clear');

    % Put tissue classes into a cell array...
    for k1=1:Kb
        if tc(k1,4) || any(tc(:,3)) || tc(k1,2) || nargout>=1
            cls{k1} = P(:,:,:,k1);
        end
    end
    clear P % ...and remove the original 4D array
end

clear tpm
M0  = res.image(1).mat;

if any(tc(:,2))
    % "Imported" tissue class images

    % Generate mm coordinates of where deformations map from
    x      = affind(rgrid(d),M0);

    % Generate mm coordinates of where deformation maps to
    y1     = affind(y,M1);

    % Procrustes analysis to compute the closest rigid-body
    % transformation to the deformation, weighted by the
    % interesting tissue classes.
    ind    = find(tc(:,2)); % Saved tissue classes
    [dummy,R] = spm_get_closest_affine(x,y1,single(cls{ind(1)})/255);
    clear x y1

    mat0   = R\mat; % Voxel-to-world of original image space

    fwhm   = max(vx./sqrt(sum(res.image(1).mat(1:3,1:3).^2))-1,0.01);
    for k1=1:size(tc,1)
        if tc(k1,2)

            % Low pass filtering to reduce aliasing effects in downsampled images,
            % then reslice and write to disk
            tmp1    = decimate(single(cls{k1}),fwhm);
            Ni      = nifti;
            Ni.dat  = file_array(fullfile(pth,['rc', num2str(k1), nam, '.nii']),...
                                 odim,...
                                 [spm_type('float32') spm_platform('bigend')],...
                                 0,1,0);
            Ni.mat         = mat;
            Ni.mat_intent  = 'Aligned';
            Ni.mat0        = mat0;
            Ni.mat0_intent = 'Aligned';
            Ni.descrip     = ['Imported Tissue ' num2str(k1)];
            create(Ni);

            for i=1:odim(3)
                tmp           = spm_slice_vol(tmp1,M0\mat0*spm_matrix([0 0 i]),odim(1:2),[1,NaN])/255;
                Ni.dat(:,:,i) = tmp;
            end
            clear tmp1
        end
    end
end

if any(tc(:,3)) || any(tc(:,4)) || nargout>=1 || df(2)
    % Adjust stuff so that warped data (and deformations) have the
    % desired bounding box and voxel sizes, instead of being the same
    % as those of the tissue probability maps.
    M = mat\M1;
    for i=1:size(y,3)
        t1         = y(:,:,i,1);
        t2         = y(:,:,i,2);
        t3         = y(:,:,i,3);
        y(:,:,i,1) = M(1,1)*t1 + M(1,2)*t2 + M(1,3)*t3 + M(1,4);
        y(:,:,i,2) = M(2,1)*t1 + M(2,2)*t2 + M(2,3)*t3 + M(2,4);
        y(:,:,i,3) = M(3,1)*t1 + M(3,2)*t2 + M(3,3)*t3 + M(3,4);
    end
    M1 = mat;
    d1 = odim;
end

if any(tc(:,3)) || any(tc(:,4)) || nargout>=1

    if any(tc(:,3))
        C = zeros([d1,Kb],'single');
    end

    spm_progress_bar('init',Kb,'Warped Tissue Classes','Classes completed');
    for k1 = 1:Kb
        if ~isempty(cls{k1})
            c = single(cls{k1})/255;
            if any(tc(:,3))
                [c,w]       = spm_diffeo('push',c,y,d1(1:3));
                vx          = sqrt(sum(M1(1:3,1:3).^2));
                spm_field('boundary',1);
                C(:,:,:,k1) = spm_field(w,c,[vx  1e-6 1e-4 0  3 2]);
                clear w
            else
                c      = spm_diffeo('push',c,y,d1(1:3));
            end
            if nargout>=1
                cls{k1} = c;
            end
            if tc(k1,4)
                N      = nifti;
                N.dat  = file_array(fullfile(pth,['mwc', num2str(k1), nam, '.nii']),...
                                    d1,...
                                    [spm_type('float32') spm_platform('bigend')],...
                                    0,1,0);
                N.mat  = M1;
                N.mat0 = M1;
                N.descrip = ['Jac. sc. warped tissue class ' num2str(k1)];
                create(N);
                N.dat(:,:,:) = c*abs(det(M0(1:3,1:3))/det(M1(1:3,1:3)));
            end
            spm_progress_bar('set',k1);
        end
    end
    spm_progress_bar('Clear');

    if any(tc(:,3))
        spm_progress_bar('init',Kb,'Writing Warped Tis Cls','Classes completed');
        C = max(C,eps);
        s = sum(C,4);
        for k1=1:Kb
            if tc(k1,3)
                N      = nifti;
                N.dat  = file_array(fullfile(pth,['wc', num2str(k1), nam, '.nii']),...
                                    d1,'uint8',0,1/255,0);
                N.mat  = M1;
                N.mat0 = M1;
                N.descrip = ['Warped tissue class ' num2str(k1)];
                create(N);
                N.dat(:,:,:) = C(:,:,:,k1)./s;
            end
            spm_progress_bar('set',k1);
        end
        spm_progress_bar('Clear');
        clear C s
    end
end

if df(2)
    y         = spm_diffeo('invdef',y,d1,eye(4),M0);
    y         = spm_extrapolate_def(y,M1);
    N         = nifti;
    N.dat     = file_array(fullfile(pth,['y_', nam, '.nii']),...
                           [d1,1,3],'float32',0,1,0);
    N.mat     = M1;
    N.mat0    = M1;
    N.descrip = 'Deformation';
    create(N);
    N.dat(:,:,:,:,:) = reshape(y,[d1,1,3]);
end

return;

%==========================================================================
% function [x1,y1,z1] = defs(sol,z,MT,prm,x0,y0,z0,M)
%==========================================================================
function [x1,y1,z1] = defs(sol,z,MT,prm,x0,y0,z0,M)
iMT = inv(MT);
x1  = x0*iMT(1,1)+iMT(1,4);
y1  = y0*iMT(2,2)+iMT(2,4);
z1  = (z0(z)*iMT(3,3)+iMT(3,4))*ones(size(x1));
x1a = x0    + spm_bsplins(sol{1},x1,y1,z1,prm);
y1a = y0    + spm_bsplins(sol{2},x1,y1,z1,prm);
z1a = z0(z) + spm_bsplins(sol{3},x1,y1,z1,prm);
x1  = M(1,1)*x1a + M(1,2)*y1a + M(1,3)*z1a + M(1,4);
y1  = M(2,1)*x1a + M(2,2)*y1a + M(2,3)*z1a + M(2,4);
z1  = M(3,1)*x1a + M(3,2)*y1a + M(3,3)*z1a + M(3,4);
return;

%==========================================================================
% function t = transf(B1,B2,B3,T)
%==========================================================================
function t = transf(B1,B2,B3,T)
if ~isempty(T)
    d2 = [size(T) 1];
    t1 = reshape(reshape(T, d2(1)*d2(2),d2(3))*B3', d2(1), d2(2));
    t  = B1*t1*B2';
else
    t = zeros(size(B1,1),size(B2,1),size(B3,1));
end
return;

%==========================================================================
% function p = likelihoods(f,bf,mg,mn,vr)
%==========================================================================
function p = likelihoods(f,bf,mg,mn,vr)
K  = numel(mg);
N  = numel(f);
M  = numel(f{1});
cr = zeros(M,N);
for n=1:N
    if isempty(bf)
        cr(:,n) = double(f{n}(:));
    else
        cr(:,n) = double(f{n}(:).*bf{n}(:));
    end
end
p  = ones(numel(f{1}),K);
for k=1:K
    amp    = mg(k)/sqrt((2*pi)^N * det(vr(:,:,k)));
    d      = bsxfun(@minus,cr,mn(:,k)')/chol(vr(:,:,k));
    p(:,k) = amp*exp(-0.5*sum(d.*d,2)) + eps;
end
return;

%==========================================================================
% function dat = decimate(dat,fwhm)
%==========================================================================
function dat = decimate(dat,fwhm)
% Convolve the volume in memory (fwhm in voxels).
lim = ceil(2*fwhm);
x  = -lim(1):lim(1); x = spm_smoothkern(fwhm(1),x); x  = x/sum(x);
y  = -lim(2):lim(2); y = spm_smoothkern(fwhm(2),y); y  = y/sum(y);
z  = -lim(3):lim(3); z = spm_smoothkern(fwhm(3),z); z  = z/sum(z);
i  = (length(x) - 1)/2;
j  = (length(y) - 1)/2;
k  = (length(z) - 1)/2;
spm_conv_vol(dat,dat,x,y,z,-[i j k]);
return;

%==========================================================================
% function y1 = affind(y0,M)
%==========================================================================
function y1 = affind(y0,M)
y1 = zeros(size(y0),'single');
for d=1:3
    y1(:,:,:,d) = y0(:,:,:,1)*M(d,1) + y0(:,:,:,2)*M(d,2) + y0(:,:,:,3)*M(d,3) + M(d,4);
end
return;

%==========================================================================
% function x = rgrid(d)
%==========================================================================
function x = rgrid(d)
x = zeros([d(1:3) 3],'single');
[x1,x2] = ndgrid(single(1:d(1)),single(1:d(2)));
for i=1:d(3)
    x(:,:,i,1) = x1;
    x(:,:,i,2) = x2;
    x(:,:,i,3) = single(i);
end
return;

%==========================================================================
% function [P] = clean_gwc(P,level)
%==========================================================================
function [P] = clean_gwc(P,level)
if nargin<2, level = 1; end

b    = P(:,:,:,2);

% Build a 3x3x3 seperable smoothing kernel
%--------------------------------------------------------------------------
kx=[0.75 1 0.75];
ky=[0.75 1 0.75];
kz=[0.75 1 0.75];
sm=sum(kron(kron(kz,ky),kx))^(1/3);
kx=kx/sm; ky=ky/sm; kz=kz/sm;

th1 = 0.15;
if level==2, th1 = 0.2; end
% Erosions and conditional dilations
%--------------------------------------------------------------------------
niter  = 32;
niter2 = 32;
spm_progress_bar('Init',niter+niter2,'Extracting Brain','Iterations completed');
for j=1:niter
    if j>2, th=th1; else th=0.6; end  % Dilate after two its of erosion
    for i=1:size(b,3)
        gp       = double(P(:,:,i,1));
        wp       = double(P(:,:,i,2));
        bp       = double(b(:,:,i))/255;
        bp       = (bp>th).*(wp+gp);
        b(:,:,i) = uint8(round(bp));
    end
    spm_conv_vol(b,b,kx,ky,kz,-[1 1 1]);
    spm_progress_bar('Set',j);
end

% Also clean up the CSF.
if niter2 > 0
    c = b;
    for j=1:niter2
        for i=1:size(b,3)
            gp       = double(P(:,:,i,1));
            wp       = double(P(:,:,i,2));
            cp       = double(P(:,:,i,3));
            bp       = double(c(:,:,i))/255;
            bp       = (bp>th).*(wp+gp+cp);
            c(:,:,i) = uint8(round(bp));
        end
        spm_conv_vol(c,c,kx,ky,kz,-[1 1 1]);
        spm_progress_bar('Set',j+niter);
    end
end

th = 0.05;
for i=1:size(b,3)
    slices = cell(1,size(P,4));
    for k1=1:size(P,4)
        slices{k1} = double(P(:,:,i,k1))/255;
    end
    bp        = double(b(:,:,i))/255;
    bp        = ((bp>th).*(slices{1}+slices{2}))>th;
    slices{1} = slices{1}.*bp;
    slices{2} = slices{2}.*bp;

    if niter2>0
        cp        = double(c(:,:,i))/255;
        cp        = ((cp>th).*(slices{1}+slices{2}+slices{3}))>th;
        slices{3} = slices{3}.*cp;
    end
    tot       = zeros(size(bp))+eps;
    for k1=1:size(P,4)
        tot   = tot + slices{k1};
    end
    for k1=1:size(P,4)
        P(:,:,i,k1) = uint8(round(slices{k1}./tot*255));
    end
end
spm_progress_bar('Clear');


function anal = er_chopTSeries2(tSeries,trials,params,varargin);
% anal = er_chopTSeries2(tSeries,trials,params,[options]);
%
% View-independent verson of er_chopTSeries.
% chops up entered tSeries according to the assigned parfiles.
%
% Inputs are tSeries (matrix where rows are time points, cols are
% different tSeries, say from diff't rois/voxels), and trials
% (a struct obtained from er_concatParfiles, containing design matrix
% information).
%
% returns an analysis struct with the following fields:
%
%   wholeTc: vector of whole time course, concatenated across scans,
%            for selected scans, voxels
%   allTcs:  3D matrix of time courses for every trial. The rows
%            are different time points, the columns are different
%            trials, and the slices (z dim) are different conditions.
%            As with other trials, the data is taken from the specified
%            time window, incl. prestim frames.
%   meanTcs: matrix of mean time courses for each condition. Rows
%            are different time points, columns are different conds.
%   sems:    corresponding standard errors of the mean for meanTcs.
%   timeWindow: vector specifying the time in seconds, relative to the
%               trial onset, from which each trial / mean trial time
%               course is taken. [default is -4:16].
%   peakPeriod: time, in seconds, where the HRF is expected to peak.
%               This will be used for t-test and amplitude results below.
%               [default is 8:14].
%   bslPeriod:  time, in seconds, to consider as a baseline period.
%               [default is 2:6].
%   amps:       Estimated amplitudes for each trial, taken
%               as the mean amplitude during the peak period
%               minus the mean amplitude during the baseline period.
%               This is a 2D matrix where rows are different trials
%               and columns are different conditions.
%   relamps:    relative fMRI amplitudes (e.g. dot products with the
%               mean time course) for each trial, in the same format
%               as amps. These should be less sensitive to the choice
%               of peak and baseline periods than amps, but may not be
%               accurate if different conditions have fundamentally
%               different response shapes (e.g., if there's a baseline
%               period where everything is decreasing and all other
%               conditions are increasing.)
%   Hs:         1 x nConds binary vector reflecting whether
%               each condition had a mean significant activation
%               during peak relative to baseline periods
%               (one-sided t-test alpha = 0.05 by default but
%               may be entered as an optional argument).
%   ps:         Corresponding p-values for the t-tests for Hs.
%   SNR:        Mean signal to noise ratio for all trials.
%               (mean signal for peakPeriod - bslPeriod)/(stdev bslPeriod)
%   SNRdb:      Expression of SNR as decibels: 20 * log10(SNR).
%
% Many params can be entered as optional arguments. In these cases,
% call them with the form ...'arg name',[value],.... The fields
% that can be entered are: timeWindow, peakPeriod, bslPeriod, alpha.
%
% Further options:
%   barebones:          do only a minimal analysis, extracting
%                       mean time courses, amplitudes, and SEMs.
%                       This is useful for across-voxel analyses.
%
%   normBsl,[1 or 0]:   if 1, will align trials during the baseline
%                       period [default is 1].
%   alpha,[val]:        alpha value for t-tests [default 0.05].
%   onsetDelta,[val]:   automatically shift the onsets in parfiles
%                       relative to the time course by this amount
%                       (e.g. to compensate for HRF rise time).
%   'mrvWaitbar':          put up a mrvWaitbar instead of showing progress in
%                       the command line.
%   'findPeaks':        when calculating response amplitudes, figure
%                       out the peak amplitude separately for each
%                       condition, taking the peak and surrounding 2 points.
%   [params struct]:    input a struct containing all of these
%                       params. See er_getParams.
%
% 06/17/04 ras: wrote it.
% 07/28/04 ras: clarified annotation.
% 01/25/05 ras: can now input params struct.
% 05/25/05 ras: fixed calculation of relative amplitudes.
if ieNotDefined('params')
    params = er_defaultParams;
end

%%%%% params/defaults %%%%%
barebones = 1;                  % if 0, do full analysis; if 1, do minimal analysis
normBsl = params.normBsl;       % flag to zero baseline or not
alpha = params.alpha;           % threshold for significant activations
bslPeriod = params.bslPeriod;   % period to use as baseline in t-tests, in seconds
peakPeriod = params.peakPeriod; % period to look for peaks in t-tests, in seconds
timeWindow = params.timeWindow; % seconds relative to trial onset to take for each trial
onsetDelta = params.onsetDelta; % # secs to shift onsets in parfiles, relative to time course
snrConds = params.snrConds;     % For calculating SNR, which conditions to use (if empty, use all)
waitbarFlag = 0;        % flag to show a graphical mrvWaitbar to show load progress
findPeaksFlag = 0;      % when computing amps, find peak period separately for each cond
TR = trials.TR;

%%%%% parse the options %%%%%
varargin = unNestCell(varargin);
for i = 1:length(varargin)
    if isstruct(varargin{i})
        % assume it's a params struct
        names = fieldnames(varargin{i});
        for j = 1:length(names)
            cmd = sprintf('%s = varargin{i}.%s;',names{j},names{j});
            eval(cmd);
        end

    elseif ischar(varargin{i})
        switch lower(varargin{i})
        case 'barebones', barebones = 1;
        case 'normbsl', normBsl = varargin{i+1};
        case 'alpha', alpha = varargin{i+1};
        case 'peakperiod', peakPeriod = varargin{i+1};
        case 'bslperiod', bslPeriod = varargin{i+1};
        case 'timewindow', timeWindow = varargin{i+1};
        case 'onsetdelta', onsetDelta = varargin{i+1};
        case 'snrconds', snrConds = varargin{i+1};
        case 'mrvWaitbar', waitbarFlag = 1;
        case 'findpeaks', findPeaksFlag = 1;
        otherwise, % ignore
        end
    end
end

%%%%% account for format of time series
% in this code compared to elsewhere (dumb, I know, but there's a reason)
if size(tSeries,2)==1 & size(tSeries,1) > 1 % column vector
    wholeTc = tSeries'; % flip the col vector around
elseif (size(tSeries,1)>1) & (size(tSeries,2)>1)
    % what the heck, let's go recursively on the columns
    for i = 1:size(tSeries,2)
        anal(i) = er_chopTSeries2(tSeries(:,i),trials,params,varargin);
    end
    return
else
    wholeTc = tSeries;
end
clear tSeries;

% account for onset shift
if mod(onsetDelta,TR) ~= 0
    % ensure we shift by an integer # of frames
    onsetDelta = TR * round(onsetDelta/TR);
end
trials.onsetSecs = trials.onsetSecs + onsetDelta;
trials.onsetFrames = trials.onsetFrames + onsetDelta/TR;

%%%%% get nConds from trials struct
condNums = unique(trials.cond(trials.cond >= 0));
nConds = length(condNums);

%%%%% get a set of label names, if they were specified in the parfiles
for i = 1:nConds
    ind = find(trials.cond==condNums(i));
    labels{i} = trials.label{ind(1)};
end

%%%%% convert params expressed in secs into frames
% first, find the min and max time in seconds expressed in time window:
% with this change, we ignore the intervening time-window values (e.g.,
% timeWindow=[-4 20] and timeWindow=[-4:2:20] produce the same result, so
% we're more flexible when it comes to non-integer TRs)
t1 = min(timeWindow);  t2 = max(timeWindow);

% second, re-express t1 and t2 in terms of TRs / MR frames
f1 = fix(t1 / TR);  f2 = fix(t2 / TR);

% now have a 'frame window' specifying the time window in integer MR frames
frameWindow = f1:f2;

% figure out auxilliary values: how many frames before the stimulus starts?
prestim = max( -f1, 0 ); % if f1 > 0, there is no prestim (only zuul :)

% which frames reflect the peak and baseline periods?
pk1 = fix( min(peakPeriod) / TR );
pk2 = fix( max(peakPeriod) / TR );
peakFrames = find(ismember(frameWindow, pk1:pk2));

bs1 = fix( min(bslPeriod) / TR );
bs2 = fix( max(bslPeriod) / TR );
bslFrames = find(ismember(frameWindow, bs1:bs2));

%%%%% remove trials at the very end of a scan, without
%%%%% enough data to fill the time window
cutOff = find(trials.onsetFrames+frameWindow(end) > length(wholeTc)+1);
if ~isempty(cutOff)
    keep = setdiff(1:length(trials.cond),cutOff);
    trials.cond = trials.cond(keep);
    trials.onsetFrames = trials.onsetFrames(keep);
    trials.onsetSecs = trials.onsetSecs(keep);
end

%%%%% build allTcs matrix of time points x trials x  conditions
%%%%% take (frameWindow) secs from each trial
allTcs = [];

for i = 1:nConds
   cond = condNums(i);
   ind = find(trials.cond==cond);
   for j = 1:length(ind)
       tstart = max(trials.onsetFrames(ind(j)),1);
       tend = min([tstart+frameWindow(end),length(wholeTc)]);
       rng = tstart:tend;

       % add prestim
       if tstart < prestim+1
           % for 1st trial, no baseline available -- set to 0
           allTcs(:,j,i) = [zeros(1,prestim) wholeTc(rng)]';
       else
           % augment the range by previous [prestim] frames
           fullrng = rng(1)-prestim:rng(end);
           allTcs(1:length(fullrng),j,i) = wholeTc(fullrng)';
       end

       % remove baseline estimate, if selected
       if normBsl
           % estimate DC offset by prestim baseline vals
           DC = nanmean(allTcs(bslFrames,j,i));
           allTcs(:,j,i) = allTcs(:,j,i) - DC;
       end
   end
end

%%%%% find 'empty' trials, set to NaNs
% (Empty trials will result if some conditions have more
% trials than others -- in the conditions w/ fewer trials,
% the allTcs matrix will be padded with 0s to keep it a cube).
for y = 1:size(allTcs,2)
    for z = 1:size(allTcs,3)
        if all(allTcs(:,y,z)==0)
            allTcs(:,y,z) = NaN;
        end
    end
end

%%%%% get mean time courses, sems for each condition
meanTcs = zeros(length(frameWindow),nConds);
sems = zeros(length(frameWindow),nConds);
maxNTrials = size(allTcs,2);

for i = 1:nConds
    nTrials = size(allTcs,2) - sum(any(isnan(allTcs(:,:,i))));
    if maxNTrials > 1
        meanTcs(:,i) = nanmean(allTcs(:,:,i)')';
        sems(:,i) = nanstd(allTcs(:,:,i)')' ./ sqrt(nTrials);
    else
        meanTcs(:,i) = allTcs(:,:,i);
    end
end

%%%%% calc amplitudes, do t-tests of post-baseline v. baseline
for i = 1:nConds
    if findPeaksFlag==1
        % find the peak separately for
        % each condition
        maxVal = max(meanTcs(2:end-1,i));
        maxT = find(meanTcs(:,i)==maxVal);
        peak = allTcs(maxT-1:maxT+1,:,i);
        bsl = allTcs(bslFrames,:,i);
    else
        bsl = allTcs(bslFrames,:,i);
        peak = allTcs(peakFrames,:,i);
    end
    amps(:,i) = (mean(peak) - mean(bsl))';

    if ~barebones
        [Hs(i) ps(i)] = ttest2(bsl(:),peak(:),alpha,-1);
    end
end

%%%%% compute Signal-to-Noise Ratio
if ~barebones
    if isempty(snrConds)
        snrConds = find(condNums > 0);
    else
        % index into condNumbers (e.g. so you can select 0)
        snrConds = find(ismember(condNums,snrConds));
    end

	allBsl = meanTcs(bslFrames,snrConds);
	allPk = meanTcs(peakFrames,snrConds);
	SNR = abs(mean(allPk(:)) - mean(allBsl(:))) / std(allBsl(:));
end

%%%%% compute relamps
% the resulting matrix will be of size
% nTrials x nConds
if ~barebones
%	relamps = er_relamps(allTcs);
end

%%%%% assign everything to the output struct
anal.wholeTc = double(wholeTc);
anal.allTcs = allTcs;
anal.meanTcs = double(meanTcs);
anal.sems = sems;
anal.labels = labels;
anal.timeWindow = timeWindow(mod(timeWindow,TR)==0);
anal.peakPeriod = peakPeriod(mod(peakPeriod,TR)==0);
anal.bslPeriod = bslPeriod(mod(bslPeriod,TR)==0);
anal.condNums = condNums;
anal.amps = amps;

if ~barebones
	anal.Hs = zeros(1, nConds); %Hs;
	anal.ps = ones(1, nConds); %ps;
	% anal.relamps = relamps;
	anal.SNR = SNR;
	anal.SNRdb = 20 * log10(SNR);
end

return


function [DietFormulation] = readInDietFromVMH(fileNameDiet)
% This function reads in the diet that has been created and downloaded from
% the https://www.vmh.life/#nutrition and converts it into the whole-body
% metabolic model consistent format.
%
% [DietFormulation] = readInDietFromVMH(fileNameDiet)
%
% INPUT
% fileNameDiet      File name
%
% OUTPUT
% DietFormulation   Diet definition
%
% Ines Thiele 2016-2019

[Numbers, Strings] = xlsread(fileNameDiet{1});

ColFlux = 1;% assumes that fluxValues are given in 2nd col

DietNames = Strings(2:end,6); % assumes that Rxn names are given in 6th column

DietNames = regexprep(DietNames,'EX_','Diet_EX_');
DietNames = regexprep(DietNames,'\(e\)','\[d\]');
% Diet exchanges for all individuals
Diets = cellstr(num2str((Numbers(:,ColFlux))));

DietFormulation = [DietNames  Diets];


function rx = rxObliqueRx(rx);
%
% rx = rxObliqueRx(rx);
%
% Add an Rx positioned (for most alignment situations in KGS / Wandell
% Lab land) roughly perpindicular to the calcarine sulcus,
% for aligning oblique inplanes to a volume anatomy using mrRx.
%
% ras 01/06.
if ieNotDefined('rx')
    cfig = findobj('Tag','rxControlFig');
    rx = get(cfig,'UserData');
end

% % store the existing settings
% rx = rxStore(rx, 'Last Setting');

% ras 01/06:
% I find these rotations / flips cover the most common case,
% where the first slice is the most anterior, pretty well:
voxRatio = rx.rxVoxelSize ./ rx.volVoxelSize;
trans = rx.volDims/2 - rx.rxDims/2 + [60 0 0];
rot = deg2rad([90 63 90]);
scale = [1 -1 1];
newXform = affineBuild(trans, rot, scale, [0 0 0]);

% if there's an Rx Figure open, set it to sagittal view, which
% is easiest to prescribe off of:
if ishandle(rx.ui.volOri(1))
    selectButton(rx.ui.volOri, 3);
end

rx = rxSetXform(rx, newXform, 1);
rx = rxStore(rx, 'Oblique Rx');

return


function computeAllPrediction_STS(pathWORK,fSetNameType,outcome,freedomMat,maxOrder,nBoot)
% -------------------------------------------------------------------------
% function computeAllPrediction_STS(pathWORK,fSetNameType,outcome,freedomMat,maxOrder,nBoot)
% -------------------------------------------------------------------------
% DESCRIPTION:
% This function computes prediction performance estimation for a given
% feature set type, and for all model orders of all experiments with
% different degrees of freedom. See ref. [1] for more details.
% -------------------------------------------------------------------------
% REFERENCE:
% [1] Vallieres, M. et al. (2015). A radiomics model from joint FDG-PET and
%     MRI texture features for the prediction of lung metastases in soft-tissue
%     sarcomas of the extremities. Physics in Medicine and Biology, 60(14),
%     5471-5496. doi:10.1088/0031-9155/60/14/5471
% -------------------------------------------------------------------------
% INPUTS:
% - pathWORK: Full path to the STS WORKSPACE directory.
% - fSetNameType: String specifying the name of the type of feature set
%                 (e.g., 'PET', 'SEPARATE', 'FUSED', etc.)
% - outcome: Column vector of size [nInst X 1] specifying the outcome status
%            (1 or 0) for all instances.
% - freedomMat:  Matrix of row vectors of 1's and 0's to specify the degree
%                of freedom on texture extraction parameters for all
%                experiments. For example, for an ith experiment where
%                extraction parameters 1, 2 and 4 in paramAll are allowed
%                to vary, use freedomMat(i,:) = [1,1,0,1].
% - maxOrder: Integer specifying the maximal multivariable model order
%             to construct.
% - nBoot: Number of bootstrap samples to use.
% -------------------------------------------------------------------------
% OUTPUTS: Prediction performance results are saved in a folder named
%          'RESULTS' in the STS WORKSPACE.
% -------------------------------------------------------------------------
% AUTHOR(S): Martin Vallieres <mart.vallieres@gmail.com>
% -------------------------------------------------------------------------
% HISTORY:
% - Creation: May 2015
%--------------------------------------------------------------------------
% STATEMENT:
% This file is part of <https://github.com/mvallieres/radiomics/>,
% a package providing MATLAB programming tools for radiomics analysis.
% --> Copyright (C) 2015  Martin Vallieres
%
%    This package is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    This package is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with this package.  If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------

startpath = pwd;
cd([pathWORK,'/MODELS']), pathModels = pwd;
cd([pathWORK,'/RESULTS']), pathResults = pwd;

nParamType = size(freedomMat,2);
nFreedom = size(freedomMat,1);
tStart = tic;
for i = 1:nFreedom
    cd(pathModels)
    results = struct;
    nameOpen = ['MODELS_',fSetNameType,'_'];
    for j = 1:nParamType
        nameOpen = [nameOpen,num2str(freedomMat(i,j))];
    end
    models = load(nameOpen); models = struct2cell(models); models = models{1};
    fprintf(['COMPUTING PREDICTION PERFORMANCE (MODEL ORDERS OF 1 to % u) FOR ',nameOpen,' ... '],maxOrder)
    tic
    for j = 1:maxOrder
        orderName = ['Order',num2str(j)];
        data = models.(orderName).Data;
        [orderResults] = predictionPerformanceEstimation_STS(data,outcome,nBoot,'IABR');
        results.(orderName) = orderResults;
        results.(orderName).Data = models.(orderName).Data;
        results.(orderName).Name = models.(orderName).Name;
    end
    toc
    cd(pathResults)
    save(['RESULTS',nameOpen(7:end)],'results')
end
time = toc(tStart);
fprintf('TOTAL TIME: %.2f seconds\n',time)

cd(startpath)
end


function training(video, method, frames)

opts.expDir = ['net/' method '/' num2str(frames) '/' video];

opts.train.batchSize = 5 ;
opts.train.numEpochs = 20;
opts.train.continue = true ;
opts.train.useGpu = true ;
opts.train.learningRate = 1e-3;
opts.train.expDir = opts.expDir;

% --------------------------------------------------------------------
% Prepare data
% --------------------------------------------------------------------
imgDir = ['../' video '/input'];
labelDir = ['../' video '/GT'];

grayDir = fullfile('../result/', method, '/', num2str(num_frames), video);

imdb = getImdb_new(imgDir, labelDir, grayDir);

mask = imread(['../' video '/ROI.bmp']);
mask = mask(:, :, 1);
A = max(max(mask));
mask(mask == A) = 1;
if size(mask, 1) > 400 || size(mask,2) > 400
    mask = imresize(mask, 0.5, 'nearest');
end
imdb.mask = single(double(mask));
imdb.half_size = 15;

%%%%%%Yi%%%%%% redefined the net
load('net');

net.layers{1} = struct('type', 'conv', ...
    'filters', 0.01 * randn(7, 7, 4, 32, 'single'), ...
    'biases', zeros(1, 32, 'single'), ...
    'stride', 1, ...
    'pad', 0) ;

net.layers{end-1} = struct('type', 'conv', ...
    'filters', 0.1*randn(1,1,64,1, 'single'), ...
    'biases', zeros(1, 1, 'single'), ...
    'stride', 1, ...
    'pad', 0) ;
net.layers{end} = struct('type', 'sigmoidcrossentropyloss');

load('meanPixel.mat');
imdb.meanPixel = meanPixel;

[net,info] = cnn_train_adagrad(net, imdb, @getBatch,...
    opts.train, 'errorType', 'euclideanloss', ...
    'conserveMemory', true);
end

function [im, labels, mask] = getBatch(imdb, batch)

half_size = imdb.half_size;
meanPixel = imdb.meanPixel;
meanPixel(:,:,4) =0;

for ii = 1 : numel(batch)
    imagename = imdb.images.name{batch(ii)};
    im_ii = single(imread(imagename));

    labelname = imdb.images.labels{batch(ii)};
    roi = imread(labelname);
    labels_ii = zeros(size(roi, 1), size(roi, 2));
    labels_ii( roi == 50 )  = 0.25;       %shade
    labels_ii( roi == 170 ) = 0.75;       %object boundary
    labels_ii( roi == 255 ) = 1;          %foreground

    % resize the image to half size
    if size(im_ii, 1) > 400 || size(im_ii, 2) >400
        im_ii = imresize(im_ii, 0.5, 'nearest');
        labels_ii = imresize(labels_ii, 0.5, 'nearest');
    end

    grayname =imdb.images.gray_name{batch(ii)};

    im_ii(:,:,4) = single(imread(grayname));

    im_large = padarray(im_ii, [half_size, half_size], 'symmetric');
    im_ii = bsxfun(@minus, im_large, meanPixel);

    im(:, :, :, ii) = im_ii;
    labels(:, :, 1, ii) = labels_ii;
    labels(:, :, 2, ii) = double(imdb.mask);
end
end

function imdb = getImdb_new(imgDir, labelDir, grayDir)
files = dir([imgDir '/*.jpg']);
label_files = dir([labelDir '/*.png']);

names = {};
labels = {};
gray_names = {};

for ii = 1:numel(files)
    names{end+1} = [imgDir '/' files(ii).name];
    labels{end+1} = [labelDir '/' label_files(ii).name];

    %prob_name = strrep(label_files(ii).name, 'gt', 'in');

    prob_name = strrep(label_files(ii).name, 'gt', 'in');

    gray_names{end+1} = [grayDir '/' prob_name];

end

imdb.images.set = ones(1,numel(names));
imdb.images.name = names ;
imdb.images.gray_name = gray_names;
imdb.images.labels = labels;
end


% testGraphCutsScript3

if 0
    imdir = '../images/all_images';
    outdir = '../data';
    load([outdir '/rand_indices.mat']);
    load([outdir '/allimsegs2.mat']);
    load([outdir '/mcmcSuperpixelClassifier.mat']);
    load([outdir '/mcmcEdgeData.mat']);
    load([outdir '/mcmcEdgeClassifier.mat']);
end

alpha = [1:1:3];

for k = 1:numel(alpha);

    disp(num2str(alpha(k)))

    for cvf = 1:numel(cv_images)

        disp([num2str(cvf) ': ' imsegs(cv_images(cvf)).imname])

        f = cv_images(cvf);
        c = ceil(cvf/50);

        im = im2double(imread([imdir '/' imsegs(f).imname]));
        wseg = segmentWatershed(im, 1);

        cimages = pg2confidenceImages(imsegs(f), pg(cvf));
        [labv, labh] = testImageGraphCuts3(im, wseg, cimages{1}, alpha(k));

        nsp = numel(labv);
        pg2{cvf} = zeros(nsp, 7);
        lab = (labv==1) + (labv==2).*(1+labh) + 7*(labv==3);
        % set most likely label
        pg2{cvf}((lab-1)*nsp + [1:nsp]') = 1;
        % set so that h accuracy can be determined
        pg2{cvf}((labh)*nsp + [1:nsp]') = 0.5;

        [pv1, ph1] = splitpg(pg{cvf});
        lim1 = APPgetLabeledImage2(im, imsegs(f), pv1, ph1);
        [pv2, ph2] = splitpg(pg2{cvf});
        lim2 = APPgetLabeledImage2(im, wseg, pv2, ph2);
        figure(1), hold off, imagesc(lim1), axis image;
        figure(2), hold off, imagesc(lim2), axis image;
        drawnow; pause(1)
    end

    [vaccgc(k), haccgc(k)] = mcmcProcessResult(imsegs(cv_images), pg2);
    disp(num2str([vaccgc ; haccgc]))
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MRiLab auto generated file: DO NOT EDIT!     %
% Generated by MRiLab "DoWriteXML2m" Generator %
% MRiLab Version 1.3                           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [B1x, B1y, B1z, E1x, E1y, E1z, Pos]=Coil_1ChHead
%====================================
p.Azimuth=0;
p.CoilID=1;
p.CurrentDir=1;
p.Elevation=0;
p.PosX=-0.1;
p.PosY=0;
p.PosZ=0;
p.Radius=0.06;
p.Scale=0.1;
p.Segment=20;
[B1xt, B1yt, B1zt, E1xt, E1yt, E1zt, Post]=CoilCircle(p);
B1x(:,:,:,p.CoilID)=B1xt;
B1y(:,:,:,p.CoilID)=B1yt;
B1z(:,:,:,p.CoilID)=B1zt;
E1x(:,:,:,p.CoilID)=E1xt;
E1y(:,:,:,p.CoilID)=E1yt;
E1z(:,:,:,p.CoilID)=E1zt;
Pos(p.CoilID,:)=Post;
p=[];
%--------------------
end


%kminvdiag 'Compute inverse of diagonal matrix '
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros minvdiag.pane file
%
% Parameters:
% InputFile: i 'Input Matrix', required: 'Input matrix'
% OutputFile: o 'Output Matrix', required: 'Output matrix'
%
% Example: o = kminvdiag(i, {'i','';'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% minvdiag - Compute Inverse of Diagonal Matrix
%
%  DESCRIPTION
% .I minvdiag
% computes the inverse of a diagonal matrix. The matrix can be non-square.
% Output is of type KDCOMPLEX if the input matrix is a complex type, otherwise
% the output is of type KDOUBLE.
%
% No checking is done for a divide by zero condition.
%
% Note that only the diagonal elements of the input matrix are modified.
%
% "minvdiag\fR is a pane object pointing to \fIminvert\fR.
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kminvdiag(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kminvdiag(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'o', '__output'};
maxval={0,0};
minval={0,0};
istoggle=[0,0];
was_set=istoggle * 0;
paramtype={'InputFile','OutputFile'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(1,1);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
[varargout{:}]=callKhoros([w 'minvert"  -diag'],Inputs,narglist);


function mr = mrReadSSFP(pth, phaseCyclePath, nFrames, varargin);
%
%  mr = mrReadSSFP([non-phase-cycle directory], [phase-cycle directory], [nFrames], [options]);
%
% Read in a series of SSFP files, combining phase-cycle and non-phase cycle
% scans using the maximum intensity projection described in (Lee et al,
% Neuroimage, 2008).
%
% Note that this function reconstructs the P-files from K-space. To get the
% raw K-space data, use the function mrReadSSFPRaw.
%
%
% ras, 02/2009.
if notDefined('pth')
    pth = mrvSelectFile('r', '7', 'Select SSFP Raw (P*.7) file');
end

if notDefined('phaseCyclePath'), phaseCyclePath = '';   end

if notDefined('nFrames'),       nFrames = [];           end

%% params
combineMethod = 'sumofsquares';  % 'maxintensity' or 'sumofsquares'
kspaceFraction = 5/8;

% GUM: defaults are from SSFP pilot data
voxelSize = [1.5 1.5 2.5 2.16];

%% parse options
for ii = 1:2:length(varargin)
    eval( sprintf('%s = %s', varargin{ii}, num2str(varargin{ii+1})) );
end

%% get full path, and fileparts of the path:
pth = fullpath(pth);
[p f ext] = fileparts(pth);

%% initalize an empty mr struct:
mr = mrCreateEmpty;
mr.format = 'ssfp';
mr.name = [f ext];
mr.path = pth;

% set other fields
mr.voxelSize = voxelSize;
mr.dataUnits = 'Arbitrary';
mr.dimUnits = {'mm' 'mm' 'mm' 'sec'};

%% read the data
[R I] = ssfpReadData(pth, nFrames);

mr.data = I;
mr.dims = size(mr.data);
if length(mr.dims) < 4, mr.dims(4) = 1; end
mr.extent = mr.dims .* mr.voxelSize;
mr.dataRange = mrvMinmax(mr.data);

%% set other fields: coordinat spaces, etc.
mr.spaces = mrStandardSpaces(mr);

%% combine with phase-cycled data if needed
if ~isempty(phaseCyclePath)
    mr_cycle = mrReadSSFP(phaseCyclePath, '', nFrames);

    % note what data we're combining, and how:
    msg = sprintf('Combination of %s and %s using %s method.', mr.path, ...
                  mr_cycle.path, combineMethod);
    mr.comments = strvcat(mr.comments, msg);

    switch lower(combineMethod)
        case {'maxintensity' 'max' 'mip' 'maxintensityprojection'}
            mr = maxIntensityProjection(mr, mr_cycle);
        case {'sumofsquares' 'sos' 'sumsquared'}
            mr = sumOfSquares(mr, mr_cycle);
        otherwise
            error('Invalid combination method: %s.', combineMethod)
    end
    return
end

return
% /--------------------------------------------------------------------/ %

% /--------------------------------------------------------------------/ %
function mr = maxIntensityProjection(mr, mr2);
% Combine two mr data volumes using the maximum-intensity projection method
% described in Lee et al, NeuroImage, 2008). This puts the data in the
% first mr struct provided.
%
% ras 02/2009.

verbose = prefsVerboseCheck;
if verbose >= 1
    h = mrvWaitbar(0, 'Computing Max Intensity Projection');
end

% first, compute the mean images over time for each MR data set.
mu1 = nanmean(abs(mr.data), 4);
mu2 = nanmean(abs(mr2.data), 4);

% create a binary mask indicating which MR data set from which draw data
% for each voxel.
mask = zeros( size(mu1) );
for ii = 1:numel(mask)
    if mu1(ii) > mu2(ii)
        mask(ii) = 1;
    else
        mask(ii) = 2;
    end
end

% now, for those points for which the mask indicates to use mr2, copy over
% those data points into the mr1 data. (For the other points, where the
% mask indicates mr data 1, we already have the appropriate data loaded.
for t = 1:size(mr.data, 4)
    subvol = mr.data(:,:,:,t);
    subvol2 = mr2.data(:,:,:,t);

    subvol(mask==2) = subvol2(mask==2);

    mr.data(:,:,:,t) = subvol;

    if verbose >= 1, mrvWaitbar( t / size(mr.data, 4), h ); end
end

if verbose >= 1
    close(h);
end

return
% /--------------------------------------------------------------------/ %

% /--------------------------------------------------------------------/ %
function mr = sumOfSquares(mr, mr2);
% Combine two mr data volumes using the sum-of-squares method
% described in Lee et al, NeuroImage, 2008). This puts the data in the
% first mr struct provided.
%
% ras 02/2009.
mr.data = sqrt( (mr.data .^ 2) + (mr2.data .^ 2) );
return


function [engine, clqtoroot] = push(engine, clq, pushdom)
%PUSH_POT push the variables in putshdom which is subset of clq to the clique toword the root and get new engine
%pushdom is pushed variables set
%clq is the index of the clique that pushdom belongs to

clqdom = engine.cliques{clq};
assert( mysubset(pushdom, clqdom));
clqtoroot = parents(engine.jtree, clq);
%sepdom = engine.separator{clq, clqtoroot};
sepdom = engine.separator{clqtoroot, clq};

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Calculate the strong marginal of the union of pushdom and and the separatordomain and  %
% the corresponding complement                                                           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%[margpot, comppot] = complement_pot(engine.clpot{clq}, pushdom);
newsepdom = myunion(pushdom,sepdom);
[margpot,comppot] = complement_pot(engine.clpot{clq}, newsepdom);
engine.clpot{clqtoroot} = direct_combine_pots(engine.clpot{clqtoroot}, margpot);
engine.clpot{clq} = comppot;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Calculation of the new separator and separatorpotential of the junction tree %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
engine.seppot{clqtoroot, clq} = direct_combine_pots(engine.seppot{clqtoroot, clq}, margpot);
engine.separator{clqtoroot, clq} = myunion(engine.separator{clqtoroot, clq}, pushdom);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Add pushdomain to the clique towards the root %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
engine.cliques{clqtoroot} = myunion(engine.cliques{clqtoroot}, pushdom);

num_cliques = length(engine.cliques);
B = sparse(num_cliques, 1);
for i=1:num_cliques
  B(i, engine.cliques{i}) = 1;
end
engine.cliques_bitv = B;


function view=rmSearchFit_sigmaOnly(view,params,matFileName,sigmaExtend);
% rmSearchFit_sigmaOnly - find minimum for retinotopic model per voxel
%
% model=rmSearchFit(view,params,matFileName,sigmaExtend);
%
% Refine sigma estimate over range originalsigma*sigmaExtend
%
% sigmaExtend defaults to [1./3 3];
%
% 2006/04 SOD: wrote it.
% 2006/12 SOD: further optimizations fminsearch->fmincon

% Programming notes:
% This will probably only work for data in 'Gray'-view.

%-----------------------------------
%--- input handling
%-----------------------------------
if ieNotDefined('view'),   error('Need view struct'); end;
if ieNotDefined('params'),
    % See first if they are stored in the view struct
    params = viewGet(view,'rmParams');
    % if not loaded load them:
    if isempty(params),
        view = rmLoadParameters(view);
        params = viewGet(view,'rmParams');
    end;
end;
if ieNotDefined('sigmaExtend'),   sigmaExtend = [1./3 3]; end;

% get rmFile. This is the model definition that will start as a
% starting point for our search.
try,
    rmFile = viewGet(view,'rmFile');
catch,
    disp(sprintf('[%s]:No file selected',mfilename));
    view = rmSelect(view);
    rmFile = viewGet(view,'rmFile');
end;

% Load previous model, but not params since these are allowed to be
% redefined every time. It is the model that is transferable
% between every scan of the same subject but not the exact
% parameters.
% actually we are going to load it so we can use the "grid" to confine our
% nonlinear minimization.
tmp = load(rmFile);
model = tmp.model;

% lastly we need to define the output file name
if ieNotDefined('matFileName'),
    if ieNotDefined('params.matFileName'),
        params.matFileName = ['retModel-',datestr(now,'yyyymmdd'),'-sFit.mat'];
        % else, use existing params.matFileName
    end;
else,
    params.matFileName = matFileName;
end;

% roi check
switch lower(params.wData),
    case {'roi'},

        % if no roi is selected: select one
        if view.selectedROI == 0,
            switch lower(view.viewType),

                case 'inplane',
                    % for inplanes default to gray matter
                    filename = 'gray.mat';
                    try,
                        view   = loadROI(view,filename);
                    catch
                        view   = loadROI(view,filename);
                    end;

                otherwise,
                    % otherwise ask
                    filename = getROIfilename(view);
                    view     = loadROI(view,filename);

            end;
        end;
        ROIcoords = view.ROIs(view.selectedROI).coords;

    otherwise,
        ROIcoords = [];
        % do nothing
end;

%-----------------------------------
%--- make trends to fit with the model (dc, linear and sinewaves)
%-----------------------------------
[trends nTrends] = rmMakeTrends(params);

%-----------------------------------
%--- now loop over slices
%--- but initiate stuff first
%-----------------------------------
switch lower(params.wData),
    case {'fig','roi'},
        loopSlices = 1;
    otherwise,
        % ras 07/07: now uses a separate analysis param, instead of stim
        % param:
        loopSlices = 1:params.analysis.nSlices;

end;
numSlices    = length(loopSlices);

%--- parameters for search fit (fminsearch)
% t-threshold above which to do search. This limit's the search
% algorithms to voxels that will have 'good' data.
params.analysis.fmins.tthresh = 4.42; %p=1e-5; 3.3 = p = 1e-3 (uncorrected)

% display iterations?
params.analysis.fmins.Display = 'none';%'none','iter','final'

% maximum iterations:
params.analysis.fmins.MaxIter = 50;

% Precision of output (degrees). That is, stop if the estimate is
% within TolX degrees:
params.analysis.fmins.TolX    = 1e-2; % degrees

% Precision of evaluation function. We define RMS improvement
% relative to the initial raw 'no-fit' data RMS. So, 1 means
% stop if there is less than 1% improvement on the fit:
params.analysis.fmins.TolFun  = 1e-2; % percent

% fminsearch options
searchOptions.TolX    = params.analysis.fmins.TolX;
searchOptions.MaxIter = params.analysis.fmins.MaxIter;
searchOptions.Display = params.analysis.fmins.Display;
searchOptions.tolFun  = params.analysis.fmins.TolFun;
tthresh       = params.analysis.fmins.tthresh;

% for backward compatibility:
if ~exist('params.analysis.relativeGridStep'),
    params.analysis.relativeGridStep = 1;
end;

% give some feedback so we know we are going
if isempty(ROIcoords),
    fprintf(1,'[%s]:Processing voxels with |t| >= %.2f\n',...
        mfilename,tthresh);
else,
    fprintf(1,'[%s]:Processing voxels with |t| >= %.2f in ROI: %s\n',...
        mfilename,tthresh,view.ROIs(view.selectedROI).name);
end;

% go loop over slices
for slice=loopSlices,

    %-----------------------------------
    % Place datasets behind each other. This is a rather crude way of
    % stimultaneously fitting both. Due to this we cannot
    % prewhiten (we could zeropadd/let the trends deal with this/not care).
    %-----------------------------------
    % we get all the data -
    p2 = params;
    p2.wData = 'all';
    [data, p2] = rmLoadData(view,p2,slice);
    %  [data, params] = rmLoadData(view,params,slice);

    %-----------------------------------
    % now we extract only the data from that slice and put it in a
    % temporary structure that will be modified throughout.
    %-----------------------------------
    s = extractSlice(model,slice);
    % We take the predefined model and remake the params. They can
    % give problems if the 'betas' are different. This may be because
    % there is different amount of detrending and/or different amount
    % of data-sets were used. Anyway, we need to make sure that the
    % amount of 'betas' are set to the current conditions.
    % This means we may have to add more trends to the data:
    if nTrends+1 > size(s{1}.b,1),
        sz = size(s{1}.b,1);
        s{1}.b(sz+1:nTrends+1,:) = 0;
        % or we may have to remove some betas from the model data-set:
    elseif nTrends+1 < size(s{1}.b,1),
        s{1}.b = s{1}.b(1:nTrends+1,:);
    end;
    % sometimes the fit return negative values.

    % amount of models
    nModels  = numel(s);
    % and which ones we are processing (positive only)
    idModels = 1:2:nModels;
    % amount of negative fit
    nNegFit  = 0;

    % for double gaussian model if it exists
    if nModels>2,
        if nTrends+2 > size(s{3}.b,1),
            sz = size(s{3}.b,1);
            s{3}.b(sz+1:nTrends+2,:) = 0;
            % or we may have to remove some betas from the model data-set:
        elseif nTrends+2 < size(s{3}.b,1),
            s{3}.b = s{3}.b(1:nTrends+2,:);
        end;
    end;

    % premake contrasts:
    C{1} = zeros(1,nTrends+1);
    C{1}(1) = 1;
    C{2} = zeros(4,nTrends+2);
    C{2}(:,1:2) = [1 1;1 0;0 1;1 -1];

    %-----------------------------------
    % Now find voxels (|voxel|>tthresh AND in ROI) that will be processed
    %-----------------------------------
    if isempty(ROIcoords),
        wProcess = find(abs(s{1}.t)>=tthresh);
    else,
        %wProcess  = zeros(1,size(ROIcoords,2));
        allcoords = viewGet(view,'coords');
        [tmp, wProcess] = intersectCols(allcoords,ROIcoords);
        wProcess = wProcess(find(s{1}.t(wProcess)>=tthresh));
    end;

    %-----------------------------------
    % Go for each voxel
    %-----------------------------------
    progress = 0;tic;
    for ii = 1:numel(wProcess),

        % progress monitor (10 dots)
        if floor(ii./numel(wProcess)*10)>progress,
            % print out estimated time left
            if slice==1 && progress==0,
                esttime = toc.*10.*numSlices;
                if floor(esttime./3600)>0,
                    fprintf(1,'[%s]:Estimated processing time: %d voxels: %d hours.\n',...
                        mfilename,numel(wProcess),ceil(esttime./3600));
                else,
                    fprintf(1,'[%s]:Estimated processing time: %d voxels: %d minutes.\n',...
                        mfilename,numel(wProcess),ceil(esttime./60));
                end;
                fprintf(1,'[%s]:Nonlinear optimization (x,y,sigma):',mfilename);
            end;
            fprintf(1,'.');drawnow;
            progress = progress + 1;
        end;

        % volume index
        vi = wProcess(ii);

        % raw rss value
        rawrss     = norm(data(:,vi)).^2;

        % start point from original fit
        xy          = [s{1}.x(vi);...
            s{1}.y(vi)];
        startParams = [s{1}.s(vi)];

        % tight search region [lowerbound upperbound]
        % gridSigmas==startParams(3), somehow this fails sometimes so we'll
        % look for the closest one.
        bndParams      = startParams*sigmaExtend;

        % actual fitting routine
        outParams = ...
            fmincon(@(x) rmModelSearchFit_oneGaussianSigmaOnly(x,data(:,vi),trends,...
            params.analysis.X,...
            params.analysis.Y,...
            params.analysis.allstimimages,...
            rawrss,xy),...
            startParams,[],[],[],[],bndParams(1),bndParams(2),...
            [],searchOptions);

        % compute t
        pred = rfMakePrediction(params,[outParams(1) outParams(1) 0 ...
            xy(1) xy(2)]);
        [t, tmp, rss, b] = rmGLM(data(:,vi),[pred trends],C{1});

        if b(1)>0,
            % store results only if the first beta is positive, somehow fmincon
            % outputs negative fits. If the fit is negative keep old (grid) fit.
            s{1}.s(vi)    = outParams(1);
            s{1}.t(vi)    = t;
            s{1}.rss(vi)  = rss;
            s{1}.rawrss(vi) = rawrss;
            s{1}.b(:,vi)  = b;
        else,
            %disp('Negative beta!?! - ignoring fit');
            nNegFit = nNegFit + 1;
        end

        %--- now for double Gaussian model:
        if numel(s)>2,
            % start point from grid fit
            startParams = [s{3}.x(vi); ...
                s{3}.y(vi); ...
                s{3}.s(vi);...
                s{3}.s2(vi)];

            % tight search region [lowerbound upperbound]
            bndParams   = [-1 1; -1 1; ...
                0.01 params.analysis.sigmaRatioMaxVal;...
                0.1  params.analysis.sigmaRatioInfVal];
            bndParams(1:2,1:2) = startParams(1:2)*[1 1] + ...
                [-1 1;-1 1].*(params.analysis.relativeGridStep.*startParams(3));

            % actual fitting routine
            outParams = ...
                fmincon(@(x) rmModelSearchFit_twoGaussians(x,data(:,vi),trends,...
                params.analysis.X,...
                params.analysis.Y,...
                params.analysis.allstimimages,...
                rawrss),...
                startParams,[],[],[],[],bndParams(:,1),bndParams(:,2),...
                [],searchOptions);
            % compute t
            pred = rfMakePrediction(params,[outParams(3) outParams(3) 0 ...
                outParams(1) outParams(2); ...
                outParams(4) outParams(4) 0 ...
                outParams(1) outParams(2)]);
            [t, tmp, rss, b] = rmGLM(data(:,vi),[pred trends],C{2});

            if b(1)>0 && b(1)+b(2)>0,
                % store results only if the first beta is positive, somehow fmincon
                % outputs negative fits. If the fit is negative keep old (grid) fit.
                s{3}.x(vi)    = outParams(1);
                s{3}.y(vi)    = outParams(2);
                s{3}.s(vi)    = outParams(3);
                s{3}.s2(vi)   = outParams(4);
                s{3}.t(vi)    = t;
                s{3}.rss(vi)  = rss;
                s{3}.b(:,vi)  = b;
            end;
        end;
    end;

    %-----------------------------------
    % now we put back the temporary data from that slice
    %-----------------------------------
    model = putSlice(model,s,slice);

    % end time monitor
    et  = toc;
    if floor(et/3600)>0,
        fprintf(1,'Done [%d hours].\n',ceil(et/3600));
    else,
        fprintf(1,'Done [%d minutes].\n',ceil(et/60));
    end;
    fprintf(1,'[%s]:Removed negative fits: %d (%.1f%%).\n',...
        mfilename,nNegFit,nNegFit./numel(wProcess).*100);
    drawnow;
end;

%-----------------------------------
% save
%-----------------------------------
for n=1:length(model),
    model{n} = rmSet(model{n},'coords',[]);
end;
output = rmSave(view,model,params,1);
view   = viewSet(view,'rmFile',output);

% that's it
return;
%-----------------------------------

%-----------------------------------
function tmp = extractSlice(model,slice);
% some code to extract slice from model struct and place it
% into temporary struct
f = {'x','y','s','rss','t','b','rawrss'};

% loop over models
for n=1:length(model),

    if n==1 || n==2 || n==5, % retinotopy and full field
        f = {'x','y','s','rss','t','rawrss'};
    else,
        if n==3 || n==4,
            f = {'x','y','s','s2','rss','rawrss'};
        else,
            f = {'x','y','s','rss','rawrss'};
        end;
        % put all t values in one matrix
        ts         = {'tall','trm','tf','trmf'};
        tmp{n}.t   = zeros(length(ts),size(val,2));
        for fn = 1:length(ts),
            val            = rmGet(model{n},ts{fn});
            tmp{n}.t(fn,:) = val(slice,:);
        end;
    end;

    % for all models
    tmp{n}.desc = rmGet(model{n},'desc');
    tmp{n}.df   = rmGet(model{n},'dfglm');
    for fn = 1:length(f),
        val    = rmGet(model{n},f{fn});
        if ~isempty(val),
            tmp{n}.(f{fn}) = val(slice,:);
        end;
    end;

    % put all beta values in one matrix
    val      = rmGet(model{n},'b');
    tmp{n}.b = zeros(size(val,3),size(val,2));
    for fn = 1:size(val,3),
        tmp{n}.b(fn,:) = val(slice,:,fn);
    end;
end;

return;
%-----------------------------------

%-----------------------------------
function model = putSlice(model,tmp,slice);
% some code to put slice info into model struct

% loop over models
for n=1:length(model),
    if n<=2, % retinotopy only
        ftmp = {'x','y','s','rss','t','rawrss'};
        fput = {'x','y','s','rss','trm','rawrss'};
        model{n}       = rmSet(model{n},'dfcorr',tmp{n}.df-3); % for x,y,s
    elseif n==5, % full field only
        ftmp = {'x','y','s','rss','t','rawrss'};
        fput = {'x','y','s','rss','tf','rawrss'};
        model{n}       = rmSet(model{n},'dfcorr',tmp{n}.df);
    else, % both
        if n==3 || n==4,
            ftmp = {'x','y','s','s2','rss','rawrss'};
            model{n}       = rmSet(model{n},'dfcorr',tmp{n}.df-4); % for x,y,s,s2
        else,
            ftmp = {'x','y','s','rss','rawrss'};
            model{n}       = rmSet(model{n},'dfcorr',tmp{n}.df-3); % for x,y,s
        end;
        fput = ftmp;

        % distribute t values
        ts  = {'tall','trm','tf','trmf'};
        for fn = 1:4,
            val           = rmGet(model{n},ts{fn});
            val(slice,:)  = tmp{n}.t(fn,:);
            model{n}      = rmSet(model{n},ts{fn},val);
        end;
    end;

    % now get values from model and put in new slice values
    for fn = 1:length(ftmp),
        val             = rmGet(model{n},fput{fn});
        if ~isempty(val),
            val(slice,:)  = tmp{n}.(ftmp{fn});
            model{n}      = rmSet(model{n},fput{fn},val);
        end;
    end;
    model{n}       = rmSet(model{n},'dfglm',tmp{n}.df);

    % distribute beta values
    val      = rmGet(model{n},'b');
    for fn = 1:size(tmp{n}.b,1),
        val(slice,:,fn) = tmp{n}.b(fn,:);
    end;
    model{n} = rmSet(model{n},'b',val);

end;
return;
%-----------------------------------


function colorSegmentationSol ( config_name )

%
%  Create a replicated array of colors
%
  colors = {'red', 'yellow', 'green', 'magenta'};
%
%  Read the image into a replicated array
%
  image = imread('fabric.png');
%
%  Set up the matlabpool
%
if matlabpool('size') > 0; matlabpool('close'); end
%
% there are four colors, each lab filters one
%
if nargin < 1 || ~strcmp(config_name, 'ithaca');
    matlabpool('open', 'local', 4);
else
    matlabpool('open', 'ithaca_2009b', 4, ...
          'FileDependencies', {'colorSegmentationSol.m', 'colorFilter.m'});
end

%
%  Each lab filters a different color,
%  and writes the filtered result to a JPEG file.
%
  spmd

    filteredImage = colorFilter(image, colors{labindex});

    imwrite(filteredImage, ['fab' num2str(labindex) '.jpg']);

  end

  return
end


function [ y ] = vl_nnselection( X,idx,dzdy )
% SelectionLayer
% X	: 1 x 2 x n x b
% y : 1 x 2 x nidx x b

if nargin<3
    %forward
    y = zeros(1,size(X,2),length(idx),size(X,4),'single');
    y(1,:,:,:) = X(1,:,idx,:);
else
    %backward
    y = zeros(size(X),'single');
    y(1,:,idx,:) = dzdy;
end

end


% Demo for Edge Boxes (please see readme.txt first).

addpath(genpath(pwd)); savepath;
addpath(genpath('/home/priyanka/Documents/autonomous_systems/sem-4/edgeBoxes/toolbox/')); savepath;

%% load pre-trained edge detection model and set opts (see edgesDemo.m)
% model=load('models/forest/modelBsds'); model=model.model;
model=load('models/forest/modelNyud2Rgbd'); model=model.model;
model.opts.multiscale=0; model.opts.sharpen=2; model.opts.nThreads=4;

%% set up opts for edgeBoxes (see edgeBoxes.m)
opts = edgeBoxes;
opts.alpha = .65;     % step size of sliding window search
opts.beta  = .75;     % nms threshold for object proposals
opts.minScore = .01;  % min score of boxes to detect
opts.maxBoxes = 1e4;  % max number of boxes to detect

%dataDir='/home/priyanka/Documents/autonomous_systems/sem-4/edgeBoxes/pdollar-edges-94260b5/BSR/nyud2_dataset/data/';
dataDir='/home/priyanka/Documents/autonomous_systems/sem-4/edgeBoxes/pdollar-edges-94260b5/BSR/vocb3do/data/';
flist=dir([dataDir '/images/train/*.png']); flist={flist.name};

cnt=0;
trainfileID = fopen('train_annot.txt','a');
testfileID = fopen('test_annot.txt','a');
trainFileName=importdata('train.txt');
testFileName=importdata('val.txt');
recall=0;
t_imgs=0;
num_prop=2000;
numel(flist)
for fidx=1:numel(flist)
	tp=0;
	tpfn=0;
	I=single(imread([dataDir 'images/train/' flist{fidx}]))/255;
	%D=single(imread([dataDir 'depth/train/' flist{fidx}]))/1e4;
	D=single(imread([dataDir 'depth/train/' flist{fidx}(1:end-4) '_abs_smooth.png']))/1e4;
	tic, bbs=edgeBoxes(I,D,model,opts); toc
	display(sprintf('img %d of %d, number of proposals: %d',fidx,numel(flist),size(bbs,1)));
	%if(size(bbs,1) > num_prop)
	%	bbs=bbs(1:num_prop,:);
	%end
	%num_prop=size(bbs,1);
	%t_imgs=numel(flist);
	%%% detect Edge Box bounding box proposals (see edgeBoxes.m)
	%I = imread('peppers.png');
	%tic, bbs=edgeBoxes(I,model,opts); toc

	%%% show evaluation results (using pre-defined or interactive boxes)
	%gt=[122 248 92 65; 193 82 71 53; 410 237 101 81; 204 160 114 95; ...
	%  9 185 86 90; 389 93 120 117; 253 103 107 57; 81 140 91 63];
	try
		display('in try')
		fName=['/home/priyanka/Desktop/VOCB3DO/VOCB3DO_Annotations/all_objects/' flist{fidx}(1:end-3) 'txt'];
		%fName=['/home/priyanka/Desktop/VOCB3DO/VOCB3DO_Annotations/all_objects/img_0013.txt'];
		fileID = fopen(fName);
		C = textscan(fileID,'%d %d %d %d %s');
		gt=cat(2,C{1},C{2},C{3},C{4});
		class_name=C{5};
		fclose(fileID);
		t_imgs=t_imgs+1;
	catch
		display('in catch')
		continue;
	end
	if(0), gt='Please select an object box.'; disp(gt); figure(1); imshow(I);
	  title(gt); [~,gt]=imRectRot('rotate',0); gt=gt.getPos(); end
	gt(:,5)=0; [gtRes,dtRes]=bbGt('evalRes',gt,double(bbs),.7);
	figure(1); bbGt('showRes',I,gtRes,dtRes(dtRes(:,6)==1,:)); pause(0.1);
	title('green=matched gt  red=missed gt  dashed-green=matched detect');
	A=bbGt('showRes',I,gtRes,dtRes(dtRes(:,6)==1,:));

	iname=['imgs/' flist{fidx}(1:end-4) '.png'];
	saveas(gcf,iname);

	% getting object bounding boxes
	%fName=replace(fName,'/home/priyanka/Desktop/VOCB3DO/VOCB3DO_Annotations/all_objects/','');
	fName=strrep(fName,'/home/priyanka/Desktop/VOCB3DO/VOCB3DO_Annotations/all_objects/','');

	isTrain=any(ismember(trainFileName,flist{fidx}(1:end-4)));
	isTest=any(ismember(testFileName,flist{fidx}(1:end-4)));
	if(isTrain == 1)
		depthDir='/home/priyanka/Documents/autonomous_systems/sem-4/edgeBoxes/pdollar-edges-94260b5/b3do/train/depth/';
		rgbDir='/home/priyanka/Documents/autonomous_systems/sem-4/edgeBoxes/pdollar-edges-94260b5/b3do/train/rgb/';
		writefileID=trainfileID;
	end
	if(isTest == 1)
		depthDir='/home/priyanka/Documents/autonomous_systems/sem-4/edgeBoxes/pdollar-edges-94260b5/b3do/test/depth/';
		rgbDir='/home/priyanka/Documents/autonomous_systems/sem-4/edgeBoxes/pdollar-edges-94260b5/b3do/test/rgb/';
		writefileID=testfileID;
	end

	origD=imread([dataDir 'depth/train/' flist{fidx}(1:end-4) '_abs_smooth.png']);
	for gidx=1:size(gt,1)
		cnt=cnt+1;
		tempgt = gt(gidx,:);
		[gtResT,dtResT]=bbGt('evalRes',tempgt,double(bbs),.7);
		loc = find(dtResT(:,6)==1);
		if(~isempty(loc))
			oname = class_name{gidx};
			I2 = imcrop(I,gtResT(1:4));
			D2 = imcrop(origD,gtResT(1:4));
			r_name=[oname '_1_1_' num2str(cnt) '_crop.png'];
			d_name=[oname '_1_1_' num2str(cnt) '_depthcrop.png'];
			imwrite(I2,[rgbDir '' r_name]);
			imwrite(D2,[depthDir '' d_name]);
			fprintf(writefileID,'%s %s\n',r_name,num2str(lookup(oname)));

		end
	end

	loc = find(dtRes(:,6)==1);
	tp = tp + numel(loc);
	tpfn = tpfn+size(gtRes,1);
	%display(tp);
	%display('...');
	%display(dtRes(loc,:));
	%display(tpfn);
	%display('---');
	%disp(tp);
	%disp(tpfn);
	recall=recall+(tp/tpfn);
end

display(recall);
display(recall/t_imgs);
if 0
%% run and evaluate on entire dataset (see boxesData.m and boxesEval.m)
if(~exist('boxes/VOCdevkit/','dir')), return; end
split='val'; data=boxesData('split',split);
nm='EdgeBoxes70'; opts.name=['boxes/' nm '-' split '.mat'];
edgeBoxes(data.imgs,model,opts); opts.name=[];
boxesEval('data',data,'names',nm,'thrs',.7,'show',2);
boxesEval('data',data,'names',nm,'thrs',.5:.05:1,'cnts',1000,'show',3);
end


function varargout = gammaincinv_x(varargin)

switch class(varargin{1})

    case 'double'
        varargout{1} = gammaincinv(varargin{1},varargin{2});

    case 'char'

        operator = CreateBasicOperator('increasing','positive','callback');
        operator.range = [0 inf];
        operator.domain = [0 1];

        varargout{1} = [];
        varargout{2} = operator;
        varargout{3} = varargin{3};

    otherwise
        error(['SDPVAR/' upper(mfilename) ' called with weird argument']);
end


function semantic_segmentation_rgb(fileName, sensorType, varName)

    %% Check if input is valid
    if ~isstring(fileName) && ~ischar(fileName)
        error("File name must a string or char array\n")
    end

    if ~strcmp(sensorType, "semantic_segmentation_rgb")
       error("Wrong sensor selected\n")
    end

    if ~isvarname(varName)
        error("Invalid variable name\n")
    end

    %% Create a python file
    file = fopen(strcat(fileName, '.py'), 'w');

    % Automatically genrates a python file containing the sensor call back
    % bindings
    fprintf(file, 'import numpy as np\n');
    fprintf(file, '\n');
    fprintf(file, '# Converts the tags to human observable colors\n');
    fprintf(file, '_mapDict = { 0:( 0, 0, 0),			1:(70, 70, 70),		2:(190, 153, 153),\n');
    fprintf(file, '             3:(250, 170, 160),		4:(220, 20, 60),	5:(153, 153, 153),\n');
    fprintf(file, '             6:(157, 234, 50),		7:(128, 64, 128),	8:(244, 35, 232),\n');
    fprintf(file, '             9:(107, 142, 35),		10:(0, 0, 142),		11:(102, 102, 156),\n');
    fprintf(file, '             12:(220, 220, 0)}\n');
    fprintf(file, '\n');
    fprintf(file, 'def _setup_mapping():\n');
    fprintf(file, '    global _mapDict\n');
    fprintf(file, '    global _mapping_array\n');
    fprintf(file, '\n');
    fprintf(file, '    tags = np.array(list(_mapDict.keys()))\n');
    fprintf(file, '    colors = np.array(list(_mapDict.values()))\n');
    fprintf(file, '\n');
    fprintf(file, '    _mapping_array = np.zeros((tags.max()+1, 3), dtype="uint8")\n');
    fprintf(file, '    _mapping_array[tags] = colors\n');
    fprintf(file, '\n');

    fprintf(file, 'def bindSensor(sensor):\n');
    fprintf(file, '    _setup_mapping()\n');
    fprintf(file, '    sensor.listen(lambda _image: do_something(_image))\n');
    fprintf(file, '\n');
    fprintf(file, 'def do_something(_image):\n');
    fprintf(file, '    global %s\n', varName);
    fprintf(file, '    global _mapping_array\n');
    fprintf(file, '\n');
    fprintf(file, '    data = np.frombuffer(_image.raw_data, dtype=np.dtype("uint8"))\n');
    fprintf(file, '\n');
    fprintf(file, '    # Get the red channel which has the tags\n');
    fprintf(file, '    data = np.reshape(data, (_image.height, _image.width, 4))\n');
    fprintf(file, '    data = data[:, :, 2]\n');
    fprintf(file, '\n');
    fprintf(file, '    # Map the tags to their respective RGB colors\n');
    fprintf(file, '    data = _mapping_array[data]\n');
    fprintf(file, '\n');
    fprintf(file, '    # Convert the data into MATLAB cast compatible type\n');
    fprintf(file, '    %s = np.ascontiguousarray(data)\n', varName);

    fclose(file);

end