function mObject3 = timeFrequencySTRAIGHTmorphingExt(mObject1,mObject2,mRate,mixMethod);
%   Morphing based on STRAIGHT parameters
%   mObject3 = timeFrequencySTRAIGHTmorphing(mObject1,mObject2,mRate,mixMethod);

%   Designed and coded by Hideki Kawahara
%   28/Feb./2005
%   Copyright(c) 2005, Hideki Kawahara
%   14/March/2005 bug fix on sampling frequency
%   01/Oct./2005 bug fix on similarity check
%   04/Oct./2005 partial morphing extension
%   18/Oct./2005 direct differential manipulation and API cange
%   29/Jan./2006 bug fix on boundary conditions
%   24/Oct./2006 modificaton of definition

switch nargin
    case 0
        mObject3.morphingObject = createMobject;
        mixRate.F0 = 0;
        mixRate.spectrum = 0;
        mixRate.aperiodicity = 0;
        mixRate.timeCoordinate = 0;
        mixRate.freqCoordinate = 0;
        mObject3.mixRate = mixRate;
        mObject3.mixMethods = {'linear','log','differentialLogarithm'};
        return
end;
if ~isfield(mObject1,'vuv')
    mObject1.vuv = (mObject1.F0>0);
elseif length(mObject1.vuv) == 0
    mObject1.vuv = (mObject1.F0>0);
end;
if ~isfield(mObject2,'vuv')
    mObject2.vuv = (mObject2.F0>0);
elseif length(mObject2.vuv) == 0
    mObject2.vuv = (mObject2.F0>0);
end;
mObject3 = checkForSimilarity(mObject1,mObject2);
mixRate = checkForMorphingConditions(mRate);
mObject1 = checkForIntegrity(mObject1);
mObject2 = checkForIntegrity(mObject2);
fs = mObject1.samplingFrequency;
if length(mObject3) ==0;return;end;
dtFrame = mObject1.frameUpdateInterval;
endLocation1 = (length(mObject1.F0)-1)*dtFrame; % in ms
endLocation2 = (length(mObject2.F0)-1)*dtFrame; % in ms
timeAnchor1 = [0;mObject1.anchorTimeLocation;endLocation1];
timeAnchor2 = [0;mObject2.anchorTimeLocation;endLocation2];
locationOn1 = (0:length(mObject1.F0)-1)*dtFrame;
locationOn2 = (0:length(mObject2.F0)-1)*dtFrame;
mapFrom1to2 = interp1(timeAnchor1,timeAnchor2,locationOn1);
[nr1,nc1] = size(mObject1.spectrogram);
[nr2,nc2] = size(mObject2.spectrogram);

%---- initialize frequency mapping function
fmapFrom1to2OnTime1 = generateFrequencyMap(mObject1,mObject2);

%---- mixing on mObject1's time axis
nAxis1 = length(locationOn1);
nAxis2 = length(locationOn2);
morphedF0 = zeros(nAxis1,1);
morphedvuv = zeros(nAxis1,1);
morphedAp = zeros(nr1,nAxis1);
morphedSgram = zeros(nr1,nAxis1);
weightSumF0 = zeros(nAxis1,1);
for ii=1:nAxis1
    mappedIndexOn2 = mapFrom1to2(ii)/dtFrame+1;
    iFloor = floor(mappedIndexOn2);
    iFraction = mappedIndexOn2-iFloor;
    fIndex = floor(fmapFrom1to2OnTime1(:,ii)/fs*2*(nr1-1))+1;
    dAp = iFraction*(mObject2.aperiodicityIndex(:,min(iFloor+1,nAxis2))-mObject2.aperiodicityIndex(:,min(iFloor,nAxis2)));
    ap2on2faxis = mObject2.aperiodicityIndex(:,min(iFloor,nAxis2))+dAp;
    ap2on1faxis = ap2on2faxis(fIndex);
    morphedAp(:,ii) = (1-mixRate.aperiodicity)*mObject1.aperiodicityIndex(:,ii)+mixRate.aperiodicity*ap2on1faxis; %04/Oct/2005 HK
    switch mixMethod
        case 'linear'
            dSgram = iFraction*(mObject2.spectrogram(:,min(iFloor+1,nAxis2))-mObject2.spectrogram(:,min(iFloor,nAxis2)));
            sgram2on2faxis = mObject2.spectrogram(:,min(iFloor,nAxis2))+dSgram;
            sgram2on1faxis = sgram2on2faxis(fIndex);
            morphedSgram(:,ii) = (1-mixRate.spectrum)*mObject1.spectrogram(:,ii)+mixRate.spectrum*sgram2on1faxis;
        case 'log'
            dSgram = iFraction*(log(mObject2.spectrogram(:,min(iFloor+1,nAxis2)))-log(mObject2.spectrogram(:,min(iFloor,nAxis2))));
            sgram2on2faxis = log(mObject2.spectrogram(:,min(iFloor,nAxis2)))+dSgram;
            sgram2on1faxis = sgram2on2faxis(fIndex);
            tmp = (1-mixRate.spectrum)*log(mObject1.spectrogram(:,ii))+mixRate.spectrum*sgram2on1faxis;
            morphedSgram(:,ii) = exp(tmp);
        case 'differentialLogarithm'
            dSgram = iFraction*(mObject2.spectrogram(:,min(iFloor+1,nAxis2))-mObject2.spectrogram(:,min(iFloor,nAxis2)));
            sgram2on2faxis = mObject2.spectrogram(:,min(iFloor,nAxis2))+dSgram;
            sgram2on1faxis = sgram2on2faxis(fIndex);
            tmp = (1-mixRate.spectrum)*log(mObject1.spectrogram(:,ii))+mixRate.spectrum*sgram2on1faxis;
            morphedSgram(:,ii) = exp(tmp);
    end;
    if mObject1.F0(ii)>0
        morphedF0(ii) = (1-mixRate.F0)*log(mObject1.F0(ii));
        weightSumF0(ii) = (1-mixRate.F0);
    end;
    if (mObject2.F0(iFloor)>0) & (mObject2.F0(min(iFloor+1,nAxis2))>0)
        dF0 = iFraction*(log(mObject2.F0(min(iFloor+1,nAxis2)))-log(mObject2.F0(min(iFloor,nAxis2))));
        morphedF0(ii) = mixRate.F0*(log(mObject2.F0(min(iFloor,nAxis2)))+dF0)+morphedF0(ii);
        weightSumF0(ii) = weightSumF0(ii)+mixRate.F0;
    end;
    morphedvuv(ii) = ((mObject1.vuv(ii)*abs(1-mixRate.F0)+abs(mixRate.F0)*mObject2.vuv(min(iFloor,nAxis2)))>0);
end;
morphedF0(weightSumF0>0) = exp(morphedF0(weightSumF0>0)./weightSumF0(weightSumF0>0));

%----- mapping back onto morphed time axis
timeAnchorMorph = (1-mixRate.timeCoordinate)*timeAnchor1 + mixRate.timeCoordinate*timeAnchor2;
locationOnMorph = (0:(timeAnchorMorph(end)/dtFrame))*dtFrame;
mapFormMorphTo1 = interp1(timeAnchorMorph,timeAnchor1,locationOnMorph);
nAxisMorph = length(locationOnMorph);
morphedApOnMorph = zeros(nr1,nAxisMorph);
morphedSgramOnMorph = zeros(nr1,nAxisMorph);
morphedF0onMorph = zeros(nAxisMorph,1);
morphedVUVonMorph = zeros(nAxisMorph,1);
%----- set place holders
mObject3.samplingFrequency = fs;
mObject3.F0 = morphedF0onMorph;
mObject3.vuv = morphedVUVonMorph;
mObject3.aperiodicityIndex = morphedApOnMorph;
mObject3.spectrogram = morphedSgramOnMorph;
mObject3.anchorTimeLocation = timeAnchorMorph(2:end-1);
mObject3.anchorFrequency = (1-mixRate.freqCoordinate)*mObject1.anchorFrequency+mixRate.freqCoordinate*mObject2.anchorFrequency;
%------ nitialize frequency mapping function
fmapFromMorphto1OnTimeMorph = generateFrequencyMap(mObject3,mObject1);
for ii=1:nAxisMorph
    mappedIndexOn1 = mapFormMorphTo1(ii)/dtFrame+1;
    iFloor = floor(mappedIndexOn1);
    iFraction = mappedIndexOn1-iFloor;
    fIndex = floor(fmapFromMorphto1OnTimeMorph(:,ii)/fs*2*(nr1-1))+1;
    morphedApOnMorph(:,ii) = morphedAp(fIndex,iFloor) ...
        +iFraction*(morphedAp(fIndex,min(iFloor+1,nAxis1))-morphedAp(fIndex,iFloor));
    morphedSgramOnMorph(:,ii) = morphedSgram(fIndex,iFloor) ...
        +iFraction*(morphedSgram(fIndex,min(iFloor+1,nAxis1))-morphedSgram(fIndex,iFloor));
    if (morphedF0(iFloor)>0) & (morphedF0(min(iFloor+1,nAxis1))>0)
        dF0 = iFraction*(morphedF0(min(iFloor+1,nAxis1))-morphedF0(iFloor));
        morphedF0onMorph(ii) = morphedF0(iFloor)+dF0;
    end;
    morphedVUVonMorph(ii) = morphedvuv(iFloor);
end;
mObject3.F0 = morphedF0onMorph;
mObject3.vuv = morphedVUVonMorph;
mObject3.aperiodicityIndex = morphedApOnMorph;
mObject3.spectrogram = morphedSgramOnMorph;
mObject3.anchorTimeLocation = timeAnchorMorph(2:end-1);
%mObject3.anchorFrequency = (1-mRate)*mObject1.anchorFrequency+mRate*mObject2.anchorFrequency;
%mObject3 = fmapFromMorphto1OnTimeMorph; % This line is a dummy.
return;

%%% ------ Internal function to check for object's similarity
function mObject3 = checkForSimilarity(mObject1,mObject2)
mObject3 = [];
if mObject1.samplingFrequency ~= mObject2.samplingFrequency;mObject3 = [];return;end;
if mObject1.frameUpdateInterval ~= mObject2.frameUpdateInterval;mObject3 = [];return;end;
if length(mObject1.anchorTimeLocation) ~= length(mObject2.anchorTimeLocation);mObject3 = [];return;end;
nAnchor = length(mObject1.anchorTimeLocation);
for ii=1:nAnchor % check for similarity of anchor structure
    frequencyAnchor1 = mObject1.anchorFrequency(ii,:)';% 01/Oct./2005 by HK
    frequencyAnchor2 = mObject2.anchorFrequency(ii,:)';% 01/Oct./2005 by HK
    if (sum(frequencyAnchor1>0) ~= sum(frequencyAnchor2>0)) | ...
            (sum(frequencyAnchor1<0) ~= sum(frequencyAnchor2<0))
        display('Warning!! Object structures are inconsistent!'); % 01/Oct./2005 by HK
        return;
    end;
end;
mObject3 = createMobject;
m0bject3.samplingFrequency = mObject1.samplingFrequency;
m0bject3.frameUpdateInterval = mObject1.frameUpdateInterval;
return;

%%%--------
function mixRate = checkForMorphingConditions(mRate);
%   04/Oct./2005 added by HK

if ~isstruct(mRate)
    mixRate.F0 = mRate;
    mixRate.spectrum = mRate;
    mixRate.aperiodicity = mRate;
    mixRate.timeCoordinate = mRate;
    mixRate.freqCoordinate = mRate;
    return;
end;
mixRate.F0 = mRate.F0;
mixRate.spectrum = mRate.spectrum;
mixRate.aperiodicity = mRate.aperiodicity;
mixRate.timeCoordinate = mRate.timeCoordinate;
mixRate.freqCoordinate = mRate.freqCoordinate;
return;

%%%--------
function fmapFrom1to2OnTime1 = generateFrequencyMap(mObject1,mObject2);

dtFrame = mObject1.frameUpdateInterval;
endLocation1 = (length(mObject1.F0)-1)*dtFrame; % in ms
timeAnchor1 = [0;mObject1.anchorTimeLocation;endLocation1];
locationOn1 = (0:length(mObject1.F0)-1)*dtFrame;
fs = mObject1.samplingFrequency;
[nr1,nc1] = size(mObject1.spectrogram);
nAnchor = length(mObject1.anchorTimeLocation);
fmapFrom1to2 = zeros(nr1,nAnchor);
frequencyAxis = (0:nr1-1)'/(nr1-1)*fs/2;
numberOfFrequencyAnchors = zeros(nAnchor,1);
for ii=1:nAnchor
    frequencyAnchor1 = mObject1.anchorFrequency(ii,:)';
    frequencyAnchor1 = [0;frequencyAnchor1(frequencyAnchor1>0);fs/2];
    numberOfFrequencyAnchors(ii) = length(frequencyAnchor1(frequencyAnchor1>0));
    frequencyAnchor2 = mObject2.anchorFrequency(ii,:)';
    frequencyAnchor2 = [0;frequencyAnchor2(frequencyAnchor2>0);fs/2];
    fmapFrom1to2(:,ii) = interp1(frequencyAnchor1,frequencyAnchor2,frequencyAxis);
end;
for ii=1:nAnchor
    if numberOfFrequencyAnchors(ii) == 1
        if numberOfFrequencyAnchors(min(ii+1,nAnchor)) > 1
            fmapFrom1to2(:,ii) = fmapFrom1to2(:,min(ii+1,nAnchor));
        elseif numberOfFrequencyAnchors(max(ii-1,1)) > 1
            fmapFrom1to2(:,ii) = fmapFrom1to2(:,max(ii-1,1));
        end;
    end;
end;
fmapFrom1to2 = [fmapFrom1to2(:,1) fmapFrom1to2 fmapFrom1to2(:,nAnchor)];
fmapFrom1to2OnTime1 = interp1(timeAnchor1,fmapFrom1to2',locationOn1)';
return;

%%%-------
function cleanedUpObject = checkForIntegrity(inputObject);

maximumIndex = max([length(inputObject.F0), ...
    size(inputObject.spectrogram,2) ...
    size(inputObject.aperiodicityIndex,2)]);
if length(inputObject.F0) < maximumIndex
    inputObject.F0 = [inputObject.F0(:);inputObject.F0(end)*ones(maximumIndex - length(inputObject.F0),1)];
end;
if size(inputObject.spectrogram,2) < maximumIndex
    numberOfFillIn = maximumIndex-size(inputObject.spectrogram,2);
    inputObject.spectrogram = [inputObject.spectrogram inputObject.spectrogram(:,end)*ones(1,numberOfFillIn)];
end;
if size(inputObject.aperiodicityIndex,2) < maximumIndex
    numberOfFillIn = maximumIndex-size(inputObject.aperiodicityIndex,2);
    inputObject.aperiodicityIndex = [inputObject.aperiodicityIndex inputObject.aperiodicityIndex(:,end)*ones(1,numberOfFillIn)];
end;
cleanedUpObject = inputObject;


function varargout = subsref(grains,s)
% implements grains(1:3)
%
% Syntax
%   grains(1:10)            % the 10 first grains
%   grains('Fe')            % only Fe grains
%   grains('id',5)          % give the grain with id 5
%   grains(5)               % give the 5th grain in the list
%   grains( ~grains('fe') ) % all grains but Fe
%   grains(cond)
%
% Input
%  grains - @grain2d
%  cond   - logical array with same size as grains
%

% some special cases to speed things up
if strcmp(s(1).type,'()') && ...
    length(s)>1 && strcmp(s(2).type,'.') && strcmp(s(2).subs,'meanOrientation')

  if strcmp(s(1).type,'{}')
    ind = grains.id2ind(s(1).subs{1});
  else
    ind = subsind(grains,s(1).subs);
  end

  phId = unique(grains.phaseId(ind));

  if length(phId) > 1
    error('MTEX:MultiplePhases',['\n' ...
      '----------------------------------------------------------------\n'...
      'Your variable contains the phases: ' ...
      grains.mineralList{phId(1)} ', ' grains.mineralList{phId(2)} '\n\n' ...
      'However, you are executing a command that is only permitted for a single phase!\n\n' ...
      'Please read the chapter ' doclink('EBSDSelect','"select EBSD data"')  ...
      ' for how to restrict grains to a single phase.\n' ...
      '----------------------------------------------------------------\n']);
  end
  if isempty(ind)
    ori = orientation;
  else
    ori = orientation(grains.prop.meanRotation(ind),grains.CSList{phId});
  end

  if numel(s)>2
    [varargout{1:nargout}] = builtin('subsref',ori,s(3:end));
  else
    varargout{1} = ori;
  end
  return
end

if strcmp(s(1).type,'()') || strcmp(s(1).type,'{}')

  if strcmp(s(1).type,'{}')
    ind = grains.id2ind(s(1).subs{1});
  else
    ind = subsind(grains,s(1).subs);
  end

  grains = subSet(grains,ind);

  % is there something more to do?
  if numel(s)>1
    s = s(2:end);
  else
    varargout{1} = grains;
    return
  end
end

% maybe reference to a dynamic property
if isProperty(grains,s(1).subs)

  [varargout{1:nargout}] = subsref@dynProp(grains,s);

else

  [varargout{1:nargout}] = builtin('subsref',grains,s);

end

end


function [varargout] = maxDose(planC, varargin)
%Calculate a maxDose metric.
%Stand alone metric :       maxDose(planC, structNum, doseNum, 'Percent' or 'Absolute');
%Request m object   :       maxDose(planC, 'getnewmetric');
%Evaluate m object  :       maxDose(planC, m, 'evaluate');
%LM:  4 Jan 06, JOD: changed interface.
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with CERR.  If not, see <http://www.gnu.org/licenses/>.

indexS = planC{end};
optS = planC{indexS.CERROptions};

if(nargin > 1)
    call = varargin{end};
else
    warning('Incorrect Usage, try: maxDose(planC, structNum, doseNum, ''Percent'' or ''Absolute'');');
    return;
end

switch upper(call)
    case 'GETNEWMETRIC'
        m.name = 'maxDose';
        m.valueV = [];
        m.description = 'Returns the max dose in specified structure';
        m.functionName = @maxDose;
        m.note = '';
        m.params(1).name = 'Structure';
        m.params(1).type = 'DropDown';
        m.params(1).list = {planC{indexS.structures}.structureName};
        m.params(1).value = 1;
        m.params(2).name = 'IsTarget?';
        m.params(2).type = 'DropDown';
        m.params(2).list ={'Target', 'Not Target'};
        m.params(2).value = 2;
        m.units = [];
        m.range = [0 inf];
        m.doseSets = [1];
        varargout = {planC,m};
    return;

    case 'EVALUATE'
        m = varargin{1};
        structName = planC{indexS.structures}(m.params(1).value).structureName;
        m.note = structName;
        m.valueV = [];

        maxD = -inf;
		for i=1:length(m.doseSets)
            [planC, doseBinsV, volsHistV] = getDVHMatrix(planC, m.params(1).value, m.doseSets(i));
            ans = calc_maxDose(doseBinsV, volsHistV, m.params(2).value);
            m.valueV = [m.valueV ans];
            doseArray = getDoseArray(planC{indexS.dose}(m.doseSets(i)));
            maxD = max(maxD, max(doseArray(:)));
        end
        if m.params(2).value == 1
            %Is target, high dose is best.
            m.range = [0 max(m.valueV)];
        elseif m.params(2).value == 2
            m.range = [maxD min(m.valueV)];
        end
        m.units = getDoseUnitsStr(i,planC);
        varargout = {planC,m};
        return;

    otherwise  %No specific call has been made, assume user just wants raw metric.
        if(nargin > 3)
            structNum = varargin{1};
            doseNum = varargin{2};
            volumeTypeString = varargin{3};
            if(strcmp(upper(volumeTypeString), 'ABSOLUTE'))
                volumeType = 2;
            else
                volumeType = 1;
            end
            [planC, doseBinsV, volsHistV] = getDVHMatrix(planC, structNum, doseNum);
            varargout = {calc_maxDose(doseBinsV, volsHistV, volumeType)};
        else
            error('Not enough parameters, try: maxDose(planC, structNum, doseNum, ''Percent'' or ''Absolute'');')
            return;
        end
    end


% HYBRJ  Solve a SNLE using HYBRJ
%
% THIS IS A LOW LEVEL FUNCTION - USE opti_hybrj() INSTEAD!
%
% hybrj uses the Minpack Powell Hybrid library.
%
%   [x,fval,exitflag,fevals] = hybrj(fun,grad,x0,opts)
%
%   Input arguments:
%       fun - vector of nonlinear functions (equations to be solved)
%       grad - gradient of nonlinear equations (optional)
%       x0 - initial solution guess
%       opts - solver options (see below)
%
%   Return arguments:
%       x - solution vector
%       fval - objective value at the solution
%       exitflag - exit status (see below)
%       fevals - number of function evaluations taken
%
%   Option Fields (all optional):
%       display - solver display level [0,1,2]
%       maxfeval - maximum function evaluations
%       maxtime - maximum solver execution time
%       iterfun - Iteration Callback Function, stop = iterfun(iter,fval,x)
%
%   Return Status:
%       1 - optimal
%       0 - maximum iterations exceeded
%      -1 - infeasible / could not converge
%      -2 - hybrj error / other
%      -5 - user exit
%
%
%   Copyright (C) 2011 Jonathan Currie (I2C2)


% Demo for aggregate channel features object detector on KAIST dataset.
%
% See also acfReadme.m
%
% Piotr's Computer Vision Matlab Toolbox      Version 3.40
% Copyright 2014 Piotr Dollar.  [pdollar-at-gmail.com]
% Licensed under the Simplified BSD License [see external/bsd.txt]
%
% 2015.06.02. Modified by Soonmin Hwang [smhwang-at-rcv.kaist.ac.kr]
% 2017.10.11. Update

%% extract training and testing images and ground truth
dataDir='data/kaist-rgbt/';
addpath( genpath( 'pdollar-toolbox' ) );
addpath( genpath( 'libs' ) );

%% set up opts for training detector (see acfTrain)
opts=acfTrain2(); opts.modelDs=[50 20.5]; opts.modelDsPad=[64 32];
opts.pPyramid.smooth=.5;
opts.pPyramid.pChns.pColor.smooth=0; opts.nWeak=[32 128 256 512 1024 2048];
opts.pBoost.pTree.maxDepth=4;
opts.pBoost.pTree.fracFtrs=1/16;
opts.nNeg=50000;
opts.nAccNeg = 100000;
opts.nPerNeg = 20;
opts.pPyramid.pChns.pGradHist.softBin=1; opts.pJitter=struct('flip',1);

% opts.trainSet = [dataDir 'imageSets/train20.txt'];
opts.trainSet = [dataDir 'imageSets/train04.txt'];
opts.posGtDir=[dataDir 'annotations'];
opts.posImgDir=[dataDir 'images'];

pLoad={'lbls',{'person'},'ilbls',{'people','person?','cyclist'},'squarify',{3,.41}};
opts.pLoad = [pLoad 'hRng',[45 inf], 'vType', {'none'} ];

%% Set thermal features
opts = acfSetTchFeatures(opts, [1 0 1 0]);  % T, TM, THOG, TM+TO

%% train detector (see acfTrain)
detector = acfTrain2( opts );

%% modify detector (see acfModify)
pModify=struct('cascThr',0,'cascCal',.025);
detector=acfModify(detector,pModify);

%% run detector on a sample image (see acfDetect)
imgDir = [dataDir 'images']; gtDir = [dataDir 'annotations'];
testSet = [dataDir 'imageSets/test20.txt'];

imgNms =bbGt2('getSubsetFiles',{imgDir, imgDir, gtDir}, testSet);

idx = 102;
I = imreadHistEq(imgNms{1,idx}, imgNms{2,idx});
tic, bbs=acfDetect2(I,detector); toc
figure(1); imshow(I(:,:,1:3)); bbApply('draw',bbs); pause(.1);

%% test detector and plot roc (see acfTest)
% Reasonable
[~,~,gt,dt]=acfTest2('name',opts.name,'imgDir',imgDir,...
  'gtDir',gtDir,'pLoad',[pLoad, 'hRng',[45 inf],...
  'vType',{{'none','partial'}},'xRng',[5 635],'yRng',[5 475]],...
  'pModify',pModify,'reapply',0,'show',2,...
  'lims', [3.1e-3 3.1e1 .2 1], 'clr', 'g', 'subset', testSet, ...
  'figName', 'Reasonable-all');


function y = vl_nnconcat(inputs, dim, dzdy, varargin)
%VL_NNCONCAT CNN concatenate multiple inputs.
%  Y = VL_NNCONCAT(INPUTS, DIM) concatenates the inputs in the cell
%  array INPUTS along dimension DIM generating an output Y.
%
%  DZDINPUTS = VL_NNCONCAT(INPUTS, DIM, DZDY) computes the derivatives
%  of the block projected onto DZDY. DZDINPUTS has one element for
%  each element of INPUTS, each of which is an array that has the same
%  dimensions of the corresponding array in INPUTS.

% Copyright (C) 2015 Karel Lenc and Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

opts.inputSizes = [] ;
opts = vl_argparse(opts, varargin, 'nonrecursive') ;

if nargin < 2, dim = 3; end;
if nargin < 3, dzdy = []; end;

if isempty(dzdy)
  y = cat(dim, inputs{:});
else
  if isempty(opts.inputSizes)
    opts.inputSizes = cellfun(@size, inputs, 'UniformOutput', false) ;
  end
  start = 1 ;
  y = cell(1, numel(opts.inputSizes)) ;
  s.type = '()' ;
  s.subs = {':', ':', ':', ':'} ;
  for i = 1:numel(opts.inputSizes)
    stop = start + opts.inputSizes{i}(dim) ;
    s.subs{dim} = start:stop-1 ; ;
    y{i} = subsref(dzdy,s) ;
    start = stop ;
  end
end


%Voice Based Biometric System
%By Ambavi K. Patel.

function op1=cmpr(cb,cd,n,k,r,c)
op1(1:n)=0;
for j=1:n      % finding euclidian distance

  x(j)=sqrt(sum((cb(1,1:r)-cd((n*(k-1))+j,1:r)).^2));
    y(j)=sqrt(sum((cb(1,r+1:r+c)-cd((n*(k-1))+j,r+1:r+c)).^2));

    if x(j)<0.05 && y(j)<3     % comparing with threshold values
        op1(j)=1;
    else op1(j)=0;
    end;
end;
% display(x);
% display(y);
%


classdef Estimator < handle
    %ESTIMATOR  Rotation estimator base class
    %
    % It takes features of all images, pairwise matches between all images
    % and estimates rotations of all cameras.
    %
    % Note: The coordinate system origin is implementation-dependent, but you
    % can always normalize the rotations in respect to the first camera, for
    % instance.
    %
    % See also: cv.Stitcher, cv.BundleAdjuster
    %

    properties (SetAccess = private)
        % Object ID
        id
    end

    methods
        function this = Estimator(estimatorType, varargin)
            %ESTIMATOR  Constructor
            %
            %     obj = cv.Estimator(estimatorType)
            %     obj = cv.Estimator(..., 'OptionName',optionValue, ...)
            %
            % ## Input
            % * __estimatorType__ Estimator type. One of:
            %   * __HomographyBasedEstimator__ Homography based rotation
            %     estimator.
            %   * __AffineBasedEstimator__ Affine transformation based
            %     estimator. This estimator uses pairwise transformations
            %     estimated by matcher to estimate final transformation for
            %     each camera.
            %
            % The following are options for the various algorithms:
            %
            % ### `HomographyBasedEstimator`
            % * __IsFocalsEstimated__ default false
            %
            % See also: cv.Estimator.estimate
            %
            this.id = Estimator_(0, 'new', estimatorType, varargin{:});
        end

        function delete(this)
            %DELETE  Destructor
            %
            %     obj.delete()
            %
            % See also: cv.Estimator
            %
            if isempty(this.id), return; end
            Estimator_(this.id, 'delete');
        end

        function typename = typeid(this)
            %TYPEID  Name of the C++ type (RTTI)
            %
            %     typename = obj.typeid()
            %
            % ## Output
            % * __typename__ Name of C++ type
            %
            typename = Estimator_(this.id, 'typeid');
        end
    end

    %% Estimator
    methods
        function [cameras,success] = estimate(this, features, pairwise_matches)
            %ESTIMATE  Estimates camera parameters
            %
            %     cameras = obj.estimate(features, pairwise_matches)
            %     [cameras, success] = obj.estimate(...)
            %
            % ## Input
            % * __features__ Features of images. See cv.FeaturesFinder.
            % * **pairwise_matches** Pairwise matches of images. See
            %   cv.FeaturesMatcher.
            %
            % ## Output
            % * __cameras__ Estimated camera parameters. Structure that
            %   describes camera parameters with the following fields:
            %   * __aspect__ Aspect ratio.
            %   * __focal__ Focal length.
            %   * __ppx__ Principal point X.
            %   * __ppy__ Principal point Y.
            %   * __R__ 3x3 camera rotation matrix.
            %   * __t__ 3x1 camera translation vector.
            %   * __K__ 3x3 camera intrinsic parameters.
            % * __success__ True in case of success, false otherwise.
            %
            % See also: cv.Estimator.Estimator
            %
            [cameras,success] = Estimator_(this.id, 'estimate', features, pairwise_matches);
        end
    end

    %% Auto-calibration methods
    methods (Static)
        function [K,success] = calibrateRotatingCamera(Hs)
            %CALIBRATEROTATINGCAMERA  Calibrate rotating camera
            %
            %     K = cv.Estimator.calibrateRotatingCamera(Hs)
            %     [K,success] = cv.Estimator.calibrateRotatingCamera(Hs)
            %
            % ## Input
            % * __Hs__ Cell-array of 3x3 double matrices.
            %
            % ## Output
            % * __K__ 3x3 double matrix.
            % * __success__ True in case of success, false otherwise.
            %
            [K,success] = Estimator_(0, 'calibrateRotatingCamera', Hs);
        end

        function focals = estimateFocal(features, pairwise_matches)
            %ESTIMATEFOCAL  Estimates focal lengths for each given camera
            %
            %     focals = cv.Estimator.estimateFocal(features, pairwise_matches)
            %
            % ## Input
            % * __features__ Features of images.
            % * **pairwise_matches** Matches between all image pairs.
            %
            % ## Output
            % * __focals__ Estimated focal lengths for each camera, vector of
            %   doubles.
            %
            focals = Estimator_(0, 'estimateFocal', features, pairwise_matches);
        end

        function [f0, f1, f0_ok, f1_ok] = focalsFromHomography(H)
            %FOCALSFROMHOMOGRAPHY  Tries to estimate focal lengths from the given homography under the assumption that the camera undergoes rotations around its centre only
            %
            %     [f0, f1] = cv.Estimator.focalsFromHomography(H)
            %     [f0, f1, f0_ok, f1_ok] = cv.Estimator.focalsFromHomography(H)
            %
            % ## Input
            % * __H__ Homography, 3x3 double matrix.
            %
            % ## Output
            % * __f0__ Estimated focal length along X axis.
            % * __f1__ Estimated focal length along Y axis.
            % * **f0_ok** True, if `f0` was estimated successfully, false
            %   otherwise.
            % * **f1_ok** True, if `f1` was estimated successfully, false
            %   otherwise.
            %
            % ## References
            % > Heung-Yeung Shum and Richard Szeliski. "Construction of
            % > of Panoramic Image Mosaics with Global and Local Alignment".
            %
            [f0, f1, f0_ok, f1_ok] = Estimator_(0, 'focalsFromHomography', H);
        end
    end

end


% PLOTPROJ - plot projections of one or more ICA components along with
%              the original data (returns the data plotted)
%
% Usage:
%   >> [projdata] = plotproj(data,weights,compnums);
%   >> [projdata] = plotproj(data,weights,compnums, ...
%                                 title,limits,chanlist,channames,colors);
%
% Inputs:
%   data        = single epoch of RUNICA input data (chans,frames)
%   weights     = unmixing matrix (=weights*sphere)
%   compnums    = vector of component numbers to project and plot
%
% Optional inputs:
%   title       = 'fairly short plot title' {0 -> 'PLOTPROJ'}
%   limits      = [xmin xmax ymin ymax]  (x's in msec)
%                          {0, or both y's 0 -> data limits}
%   chanlist    = list of data channels to plot {0 -> all}
%   channames   = channel location file or structure (see READLOCS)
%   colors      = file of color codes, 3 chars per line  ('.' = space)
%                          {0 -> default color order (black/white first)}
%
% Author: Scott Makeig, SCCN/INC/UCSD, La Jolla, 05-01-96
%
% See also: PLOTDATA

% Without color arg, reads filename for PROJCOLORS from icadefs.m

% Copyright (C) 05-01-96 from PLOTDATA Scott Makeig, SCCN/INC/UCSD,
% scott@sccn.ucsd.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

% 05-25-96 added chanlist, nargin tests, rearranged variable order -sm
% 07-29-96 debugged, added chanlist channames option -sm
% 10-26-96 added test for column of compnums  -sm
% 02-18-97 improved usage message -sm
% 02-19-97 merged versions -sm
% 03-19-97 changed VAR to diag(COV), use datamean arg instead of frames/baseframes -sm
% 04-24-97 tested datamean for 1-epoch; replaced COV with mean-squares -sm
% 05-20-97 read icadefs for PROJCOLORS & MAXPLOTDATACHANS -sm
% 06-05-97 use arbitrary chanlist as default channames -sm
% 06-07-97 changed order of args to conform to runica -sm
% 06-12-97 made sumdata(chanlist in line 159 below -sm
% 07-23-97 removed datamean from args; let mean distribut4e over components -sm
% 09-09-97 corrected write out line " summing " -sm
% 10-31-97 removed errcode var -sm
% 11-05-97 added test for channames when chanlist ~= 1:length(chanlist) -sm & ch
% 12-19-00 adjusted new ICAPROJ args -sm
% 01-12-01 removed sphere arg -sm
% 01-25-02 reformated help & license, added links -ad

function [projdata] = plotproj(data,weights,compnums,titl,limits,chanlist,channels,colors);

icadefs       % read default PROJCOLORS & MAXPLOTDATACHANS variables from icadefs.m
DEFAULT_TITLE = 'plotproj()';

%
% Substitute for missing arguments
%

if nargin < 8,
    colors = 'white1st.col';
elseif colors==0,
    colors = 'white1st.col';
end

if nargin < 7,
    channels = 0;
end
if nargin < 6
    chanlist = 0;
end
if nargin < 5,
    limits = 0;
end
if nargin < 4,
    titl = 0;
end
if titl==0,
    titl = DEFAULT_TITLE;
end

if nargin < 3,
    fprintf('plotproj(): must have at least four arguments.\n\n');
    help plotproj
    return
end
%
% Test data size
%
[chans,framestot] = size(data);

frames = framestot; % assume one epoch

[wr,wc]           = size(weights);

if wc ~= chans
    fprintf('plotproj(): sizes of weights and data incompatible.\n\n');
    return
end
%
% Substitute for 0 arguments
%
if chanlist == 0,
    chanlist = [1:chans];
end
if compnums == 0,
    compnums = [1:wr];
end
if size(compnums,1)>1,        % handle column of compnums !
    compnums = compnums';
end
if length(compnums) > 256,
    fprintf('plotproj(): cannot plot more than %d channels of data at once.\n',256);
    return
end

if channels ~= 0  % if chan name file given
   if ~all(chanlist == [1:length(chanlist)])
     fprintf('plotproj(): Cannot read an arbitrary chanlist of channel names.\n');
     return
   end
end
if channels==0,
    channels = chanlist;
end

if max(compnums)>wr,
   fprintf(...
 '\n    plotproj(): Component index (%d) > number of components (%d).\n', ...
                                 max(compnums),wr);
   return
end

fprintf('Reconstructing (%d chan, %d frame) data summing %d components.\n', ...
                   chans,frames,length(compnums));
%
% Compute projected data for single components
%
projdata = data(chanlist,:);
fprintf('plotproj(): Projecting component(s) ');
for s=compnums,            % for each component
   fprintf('%d ',s);
   proj = icaproj(data,weights,s);   % let offsets distribute
   projdata = [projdata proj(chanlist,:)];  % append projected data onto projdata
   % size(projdata) = [length(chanlist)  framestot*(length(compnums)+1)]
end
fprintf('\n');
%
% Compute percentage of variance accounted for
%
sumdata = icaproj(data,weights,compnums);% let offsets distribute
sigmssq = mean(sum(data(chanlist,:).*data(chanlist,:)));
   data(chanlist,:) = data(chanlist,:) - sumdata(chanlist,:);
difmssq = mean(sum(data(chanlist,:).*data(chanlist,:)));

pvaf   = round(100.0*(1.0-difmssq/sigmssq)); % percent variance accounted for

rtitl = ['(p.v.a.f. ' int2str(pvaf) '%)'];
%
% Make the plot
%
plotdata(projdata,length(data),limits,titl,channels,colors,rtitl);
                                                % make the plot


function [fitness,convar,xtxi,models] = testlist(stimLists,GA,HRF,varargin)
% [fitness,convar,xtxi,models] = testlist(stimLists,GA,HRF,[opt args])
%
% stimLists can have multiple lists (columns)
%
% 9/12/01 Tor Wager

clockStart = cputime;			  	% keeps track of starting time

for i = 1:length(varargin)
    if isstr(varargin{i})
        switch varargin{i}
        case 'rest', restMatrix = varargin{i+1};
        case 'svi', svi = varargin{i+1};
        case 'S', S = varargin{i+1};
        end
    end
end

% ----------------------------------------------------------------
% * vars setup
% ----------------------------------------------------------------

trans2switch = GA.trans2switch;
trans2block = GA.trans2block;
maxOrder = GA.maxOrder;
conditions = GA.conditions;
freqConditions = GA.freqConditions;
cbalColinPowerWeights = GA.cbalColinPowerWeights;
contrastweights = GA.contrastweights;
NumStimthresh = GA.NumStimthresh;
maxCbalDevthresh = GA.maxCbalDevthresh;
maxFreqDevthresh = GA.maxFreqDevthresh;
ISI = GA.ISI;
TR = GA.TR;
nonlinthreshold = GA.nonlinthreshold;
scanLength = GA.scanLength;
restevery = GA.restevery;
restlength = GA.restlength;
HPlength = GA.HPlength;
xc = GA.xc;
contrasts = GA.contrasts;

% ----------------------------------------------------------------
% * contrast setup
% ----------------------------------------------------------------

% work out whether to use contrasts.
if isempty(contrasts)
   nconds = sum(conditions > 0);
   %contrasts = zeros(nconds,nconds);
    %for i = 1:nconds
    %    contrasts(i,i) = 1;
    %end
    %disp('  ...no contrasts entered; using original model')
    docontrasts = 0;
 else
    %disp(' ...contrasts entered')
    docontrasts = 1;
    %contrasts
end

%if ~(size(contrasts,1) == sum(conditions > 0)),
    %disp('	...fyi: Num contrasts does not equal num conditions')
%end

% ----------------------------------------------------------------
% * setup freqConditions and rests
% ----------------------------------------------------------------

% normalize freqConditions
if ~sum(freqConditions) == 1,
	freqConditions(1:end-1) = (1 - freqConditions(end)) / (size(freqConditions,2)-1);
	disp(['	...freqConditions does not sum to 1: normalizing to ' num2str(freqConditions)])
end

% flag for rest length.
	if ~isempty(restevery) &  ~isempty(restlength)
		disp(['	...Using rests of length ' num2str(restlength) ' and resting every ' num2str(restevery)])
		dorests = 1;
	else disp('	...No rests specified.'),dorests = 0;
	end

if ~(mod(scanLength / ISI,1) == 0),disp('Warning: Scan length in s is not an even multiple of ISI!'),end

% ----------------------------------------------------------------
% * initial computation of list lengths and output
% ----------------------------------------------------------------

numStim = ceil(scanLength / (ISI));
if dorests,
	numRestStim = (ceil(numStim/(mean(restevery)+restlength)) - 1) * restlength;
else
	numRestStim = 0;
end
numStimEachCond = ceil((numStim-numRestStim) * freqConditions);			            % row vector of stim in each cond
numsamps = ceil(numStim*ISI/TR);

% ----------------------------------------------------------------
% * get smoothing matrix and autocorrelation matrix
% ----------------------------------------------------------------
if isempty(HPlength),HPlength = 'none';,end
if ~isfield(GA,'LPsmooth'),GA.LPsmooth = 1;,end

dofilter = 1;
if strcmp(HPlength,'none') & ~GA.LPsmooth
    dofilter = 0;
end

%disp(['	...setting smoothing, hrf, and autocorrelation matrices, HPlength = ' num2str(HPlength) ', Smoothing = ' num2str(GA.LPsmooth)])

if ~(exist('S') == 1)
%use spm_filter
if strcmp(HPlength,'none') & GA.LPsmooth									% LP only
	%disp('		...LP only')
	[S,KL] = use_spm_filter(TR,numsamps,'hrf','none',[]);
elseif GA.LPsmooth															% HP and LP
	[S,KL,KH] = use_spm_filter(TR,numsamps,'hrf','specify',HPlength);
	%disp('		...HP and LP')
elseif strcmp(HPlength,'none') & ~GA.LPsmooth								% neither
	%disp('		...no filtering')
	S = eye(numsamps);
	dofilter = 0;
else [S,KL,KH] = use_spm_filter(TR,numsamps,'none','specify',HPlength);		% HP only
	%disp('		HP only')
end

end % if ~exist S

if ~(exist('svi') == 1)

if isempty(xc),Vi = eye(numsamps);,disp('Using white noise autocorrelation')
else Vi = getv('make',xc,numsamps);
end

svi = S * Vi * S';

end % if exist svi

clear KL, clear KH, clear Vi, clear myscannerV

% ----------------------------------------------------------------
% * criterion measures setup
% ----------------------------------------------------------------
if ~isempty(NumStimthresh) | ~isempty(maxCbalDevthresh) | ~isempty(maxFreqDevthresh)
	docriterion = 1;
	if isempty(NumStimthresh),NumStimthresh = 10000;,end
 	if isempty(maxCbalDevthresh),maxCbalDevthresh = 10000;,end
	if isempty(maxFreqDevthresh),maxFreqDevthresh = 10000;,end
else
	docriterion = 0;
end

maxrestthresh = 2;					% max number of rests in a row.

% ----------------------------------------------------------------
% * saturation setup
% ----------------------------------------------------------------
if isempty(nonlinthreshold) | strcmp(nonlinthreshold,'none'),dosaturation = 0;,nonlinthreshold = 'none';,else dosaturation = 1;,end

% add intercept
% ------------------------------
if docontrasts, contrasts(:,end+1) = 0;, end

% ----------------------------------------------------------------
% * do it.
% ----------------------------------------------------------------

for z = 1:size(stimLists,2)

	stimList = stimLists(:,z);

% The Switch Hack: transform list of stimuli into list of switches/no switches for each stimtype (R or L)
      if trans2switch, stimList = transform2switches(stimList);,end
      if trans2block,
	     restMatrix = varargin{1};
	     restlength = GA.restlength;

             restList = restMatrix(:,z);
             stimList = transform2block(stimList,restList,restlength);
      end

      % ===== counterbalancing ============================================
      %if (cbalColinPowerWeights(1) > 0)    removed 3/30 to implement criterion rather than weights.
   		[cBal,dummy,maxDev] = getCounterBal(stimList, maxOrder,conditions,freqConditions);
		 % ...if optimizing this measure, add it to fitness scores.
         if (cbalColinPowerWeights(1) > 0),fitnessMatrix(1,z) = cBal;,end
	  %end

	  % ===== frequency discrepancy ========================================
	  % calculate max discrepancy between actual frequencies and requested frequencies
	  %if size(cbalColinPowerWeights,2) > 3
      	%if (cbalColinPowerWeights(4) > 0)
            for i = 1:size(freqConditions,2)
         		freqMat(i) = sum(stimList == conditions(i)) / size(stimList,1);
      	    end
            freqMat = freqMat ./ sum(freqMat);   % adjust for probe ''0''s
			maxFreqDev = max(abs(freqConditions - freqMat));
			% ...if optimizing this measure, add it to fitness scores.
      		if (cbalColinPowerWeights(4) > 0), dummy = 1 - maxFreqDev;,end
		%end
	  %end

	  % criterion measures
	  % ====================================================================
	    go = 1;
	    if docriterion
	  	[maxNumStim,maxrest] = getMaxInARow(stimList,dojitter);
	  	if maxNumStim > NumStimthresh | maxrest > maxrestthresh | maxDev > maxCbalDevthresh | maxFreqDev > maxFreqDevthresh
		  go = 0;
		  error('Criteria not met.')
          	end
	   end

		% =====power calculation =============================================
    if (cbalColinPowerWeights(2) > 0 | cbalColinPowerWeights(3) > 0) & go   % build predictor set of vectors and convolve with HRF
        model = sampleInSeconds(stimList,ISI);
        model = getPredictors(model,HRF);
        model = resample(model,1,TR*10);
	if dosaturation,model = modelSaturation(model,nonlinthreshold);,end						% saturation (nonlinear responses)
        if size(model,1) > numsamps, model = model(1:numsamps,:);,end

	% add intercept
	% ------------------------------
	model(:,end+1) = 1;

        if dofilter
		try
            model = S * model;                                                  % temporal smoothing and HP filter
        catch
            whos model
            whos S
            error('model smoothing: wRoNg Sizes!')
        end
	end
        xtxitx = pinv(model);                                       		% inv(X'S'SX)*(SX)'; pseudoinv of (S*X)

	if docontrasts,
		try
            con1 =  model * contrasts(1,:)';
        catch
            whos model
            whos contrasts
            error('contrast multiplication: wRoNg Sizes!')
        end
	end
	%figure; subplot(2,1,1)
	%plot(model(:,1))
	%title(['Model ' num2str(z) ' Predictor 1'])
	%subplot(2,1,2)
	%plot(con1)
	%title(['Model ' num2str(z) ' Contrast 1'])
	%drawnow; pause(5)

	xtxi{z} = inv(model'*model);
	models{z} = model;

        if docontrasts											% compute the variance of the contrasts
           try
              fitness(z) = 1./(contrastweights * diag(contrasts*xtxitx*svi*xtxitx'*contrasts'));
	      convar(z) = (contrasts(1,:)*xtxitx*svi*xtxitx'*contrasts(1,:)');
              % it's 1/ because we want to minimize the variance, but we maximize fitnessMatrix value.
           catch
             disp('using contrasts: wrong sizes!!!')
             contrasts
             whos xtxitx
             whos svi
             diag(xtxitx*svi*xtxitx')
             error('Exiting...')
           end

        else
           try
               fitness(z) = 1./(contrastweights * diag(xtxitx*svi*xtxitx')); % variance of chosen regressors.
		myconvar = diag(xtxitx*svi*xtxitx');
	       convar(z) = myconvar(1);
           catch
               disp(['no contrasts version: wrong sizes!!!'])
               whos contrastweights
               whos xtxitx
               whos svi
               diag(xtxitx*svi*xtxitx')
               error('Exiting...')
           end
	end
    end

end % loop through designs

%figure;for i = 1:length(models),subplot(1,length(models),i),imagesc(models{i}),
%	title(['Model ' num2str(i) ' v = ' num2str(convar(i)) ' f = ' num2str(fitness(i))])
%end

disp(['testlist done: ' num2str(cputime-clockStart) ' s'])

return


%% Sample execution for Baseline on CFNet-conv3
% hyper-parameters reported in Supp.material for CVPR'17, Table 2 for arXiv version
tracker_par.join.method = 'corrfilt';
tracker_par.net = 'baseline-conv3-on-cfnet-conv3_e100.mat';
tracker_par.net_gray = 'baseline-conv3-on-cfnet-conv3_gray_e70.mat';
tracker_par.scaleStep = 1.034;
tracker_par.scalePenalty = 0.9820;
tracker_par.scaleLR = 0.66;
tracker_par.wInfluence = 0.27;
tracker_par.zLR = 0.008;

[~,~,dist,overlap,~,~,~,~] = run_tracker_evaluation('all', tracker_par);


function varargout = segGet(seg, property, varargin);
% Get properties of a segmentation.
%
% [vals] = segGet(seg, property, [optional arguments]);
%
% Some properties include:
%   'classPath':    path to the .class file describing the white/gray
%                   classification.
%   'grayPath':     path to the .gray graph.
%   'curMeshNum':   # of the currently-selected mesh (0=no meshes loaded).
%   'mesh',[M]:     the M-th loaded mesh <defaults to current mesh if M
%                   omitted.>
%
%   'nodes':        gray nodes. The rows of the 8xN nodes matrix represent:
%                   (1-3) s/i, a/p, l/r coords (in I|P|R space -- see
%                   mrFormatDescription) of each gray node.
%                   (4)
%                   (5)
%                   (6) gray level/layer, counting from white matter up.
%                   (7)
%                   (8)
%                   The number N of nodes will represent all the gray
%                   nodes for this segmentation, regardless of the
%                   current mapping.
%   'edges':        gray edges.
%   [nodes edges] = segGet('gray') returns both gray nodes and edges
%                   (preventing redundant loading of the gray graph).
%
%   'meshCoords',[M],[mmPerPix]:
%                   3xN coordinates (in IPR space) of each node
%                   represented by the M-th mesh, using the current
%                   mapping. The current mapping is determined by
%                   mrmPreferences. The number N of columns will
%                   correspond to the columns of mesh{M}.initVertices,
%                   as well as the mesh colors.
%                   <if M omitted, uses selected mesh; if mmPerPix
%                   omitted, tries to read from segementation's anat file,
%                   or else assumes 1x1x1.>
%
%	'nearestNode',[coord],[tolerance=5mm]:
%					Return the index of the nearest gray node to a given
%					3D coordinate. This simply finds the node with the
%					smallest euclidean distance from the input coordinate.
%					The input coord should be a 1x3 or 3x1 vector, and should
%					be in the same format as the gray coords. (This is in order
%					The optional tolerance argument specifies how large a
%					distance should be accepted for a nearest node; if no
%					node is less than this amount, the nearestNode will
%					return empty. By default, the tolerance is 5mm.
%
% ras 04/06
if nargin<2, help(mfilename); error('Not enough input args.'); end

switch lower(property)
    case {'classpath' 'classfile'}
        if isstr(seg.class),    varargout{1} = seg.class;
        else,                   varargout{1} = seg.class.filename;
        end

    case {'classification' 'classdata' 'voxels' 'wm' 'class'}
        if isstr(seg.class),    varargout{1} = readClassFile(seg.class);
        else,                   varargout{1} = seg.class;
        end

    case {'graypath' 'graygraph' 'grayfile'}
        if isstr(seg.gray),     varargout{1} = seg.gray;
        else,                   varargout{1} = seg.gray.path;
        end

    case {'curmeshnum' 'curmeshn' 'meshnum' 'selectedmeshnum'}
        varargout{1} = seg.settings.mesh;

    case {'mesh' 'curmesh' 'selectedmesh'}
        if length(varargin)==0, M = segGet(seg, 'curMeshNum');
        else, M = varargin{1};
        end

        if M==0 | isempty(seg.mesh),
            varargout{1} = [];
        else
            varargout{1} = seg.mesh{M};
        end

    case {'nodes' 'graynodes'}
        if isempty(seg.nodes),  varargout{1} = readGrayGraph(seg.gray);
        else,                   varargout{1} = seg.nodes;
        end

    case {'edges' 'grayedges'}
        if isempty(seg.edges),  [x varargout{1}] = readGrayGraph(seg.gray);
        else,                   varargout{1} = seg.edges;
        end

    case {'gray'}
        if isempty(seg.nodes) | isempty(seg.edges)
            [varargout{1} varargout{2}] = readGrayGraph(seg.gray);
        else
            varargout{1} = seg.nodes;
            varargout{2} = seg.edges;
        end

    case {'graycoords'}
        nodes = segGet(seg, 'nodes');
        varargout{1} = nodes([2 1 3],:);

    case {'meshcoords' 'coords'}
        varargin{3} = []; % fast way to init. args 1 & 2 if unspecified
        M = varargin{1};  mmPerPix = varargin{2};
        if isempty(M), M = segGet(seg, 'curMeshNum'); end
        if isempty(mmPerPix)
            try
                anat = mrLoad(seg.anatFile);
                mmPerPix = anat.voxelSize(1:3);
            catch
                disp(['Couldn''t read segmentation anatomy. Guessing ' ...
                      'mmPerPix as [1 1 1]...'])
                 mmPerPix = [1 1 1];
            end
        end

        % get mapping from mesh vertices to gray nodes
        [nodes edges] = segGet(seg, 'gray');
        v2g = mrmMapVerticesToGray(seg.mesh{M}.initVertices, nodes, ...
                                   mmPerPix, edges);

        % grab appropriate coords from nodes
        varargout{1} = nodes(1:3,v2g);

	case {'nearestnode'}
        varargin{3} = []; % fast way to init. args 1 & 2 if unspecified
		pt = varargin{1}(:); tolerance = varargin{2};
		if isempty(pt), error('Need an input coordinate.'); end
		if isempty(tolerance), tolerance = 5; end

		% compute Euclidean distance of each node from the coord
		C = segGet(seg, 'GrayCoords');
		dist = sqrt( [C(1,:) - pt(1)] .^ 2 + ...
					 [C(2,:) - pt(2)] .^ 2 + ...
					 [C(3,:) - pt(3)] .^ 2 );
		if min(dist) > tolerance
			warning(sprintf('[%s]: no node found within tolerance [%i mm]', ...
							 mfilename, tolerance));
			varargout{1} = [];
		else
			I = find(dist==min(dist));
			varargout{1} = I(1);
		end

    otherwise, error('Unknown property.')

end

return


function test_bug2647
% DEPENDENCY ft_freqstatistics

% WALLTIME 00:10:00
% MEM 2gb

load(dccnpath('/home/common/matlab/fieldtrip/data/test/bug2647.mat'));
stat = ft_freqstatistics(cfg,data,BL);
%assert(all(~isfinite(stat.stat(:))));
assert(~all(~isfinite(stat.stat(:)))); % this should now work after making ft_statfun_actvsblT more robust for NaNs

cfg.design = cfg.design(:,[1:4 6:9]);
data.powspctrm = data.powspctrm(2:end,:,:,:);
BL.powspctrm   = BL.powspctrm(2:end,:,:,:);
stat = ft_freqstatistics(cfg,data,BL);
assert(~all(~isfinite(stat.stat(:))));

% conclusion: the first rpt was all NaN, causing stat.stat to be all NaN,
% no meaningful inference possible


%  Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved.
%
%  usage:
%    calib_info = GetMeg160CalibInfoM( fid )
%
%  arguments:
%    fid             : file ID
%
%  return values:
%    calib_info      : (m x 3) matrix of calibration information. (m: channel_count)
%                        detail of n: (If the sensor doesn't have following item, the item's entry will be 'Inf'.)
%                            1   : channel number in Meg160(zero start)
%                            2   : gain [Tesla/V]
%                            3   : offset voltage [V]
%
%  confirmation of revision:
%   GetMeg160CalibInfoM( Inf ) will show and return revision of this function.
%


function [estimate] = ft_inverse_music(sourcemodel, sens, headmodel, dat, varargin)

% FT_INVERSE_MUSIC source localization using MUltiple SIgnal Classification.
% This is a signal subspace method, which covers the techniques for
% multiple source localization by using the eigen-structure of the
% measured data matrix.
%
% Use as
%   [estimate] = ft_inverse_music(sourcemodel, sens, headmodel, dat, ...)
% where
%   sourcemodel is the input source model, see FT_PREPARE_SOURCEMODEL
%   sens        is the gradiometer or electrode definition, see FT_DATATYPE_SENS
%   headmodel   is the volume conductor definition, see FT_PREPARE_HEADMODEL
%   dat         is the data matrix with the ERP or ERF
% and
%   estimate    contains the estimated source parameters
%
% Additional input arguments should be specified as key-value pairs and can include
%   'cov'              = data covariance matrix
%   'numcomponent'     = integer number
%   'feedback'         = can be 'none', 'gui', 'dial', 'textbar', 'text', 'textcr', 'textnl' (default = 'text')
%
% These options influence the forward computation of the leadfield
%   'reducerank'      = 'no' or number  (default = 3 for EEG, 2 for MEG)
%   'backproject'     = 'yes' or 'no', in the case of a rank reduction this parameter determines whether the result will be backprojected onto the original subspace (default = 'yes')
%   'normalize'       = 'no', 'yes' or 'column' (default = 'no')
%   'normalizeparam'  = parameter for depth normalization (default = 0.5)
%   'weight'          = number or Nx1 vector, weight for each dipole position to compensate for the size of the corresponding patch (default = 1)
%
% This implements
% - J.C. Mosher, P.S. Lewis and R.M. Leahy, "Multiple dipole modeling and
%   localization from spatiotemporal MEG data", IEEE Trans. Biomed. Eng.,
%   pp 541-557, June, 1992.
%
% See also FT_SOURCEANALYSIS, FT_PREPARE_HEADMODEL, FT_PREPARE_SOURCEMODEL

% Copyright (C) 2004-2008, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

if mod(nargin-4,2)
  % the first 4 arguments are fixed, the other arguments should come in pairs
  ft_error('invalid number of optional arguments');
end

% get the optional input arguments, or use defaults
cov            = ft_getopt(varargin, 'cov');
numcomponent   = ft_getopt(varargin, 'numcomponent');     % this is required, see below
feedback       = ft_getopt(varargin, 'feedback', 'text');

% construct the low-level options for the leadfield computation as key-value pairs, these are passed to FT_COMPUTE_LEADFIELD
leadfieldopt = {};
leadfieldopt = ft_setopt(leadfieldopt, 'reducerank',     ft_getopt(varargin, 'reducerank'));
leadfieldopt = ft_setopt(leadfieldopt, 'backproject',    ft_getopt(varargin, 'backproject'));
leadfieldopt = ft_setopt(leadfieldopt, 'normalize',      ft_getopt(varargin, 'normalize'));
leadfieldopt = ft_setopt(leadfieldopt, 'normalizeparam', ft_getopt(varargin, 'normalizeparam'));
leadfieldopt = ft_setopt(leadfieldopt, 'weight',         ft_getopt(varargin, 'weight'));

if isempty(numcomponent)
  ft_error('you must specify the number of signal components');
end

% flags to avoid calling isfield repeatedly in the loop over grid positions (saves a lot of time)
hasmom        = isfield(sourcemodel, 'mom');
hasleadfield  = isfield(sourcemodel, 'leadfield');
hasfilter     = false; % not used here

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% find the dipole positions that are inside/outside the brain
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if ~isfield(sourcemodel, 'inside')
  if hasfilter
    sourcemodel.inside = ~cellfun(@isempty, sourcemodel.filter);
  elseif hasleadfield
    sourcemodel.inside = ~cellfun(@isempty, sourcemodel.leadfield);
  else
    sourcemodel.inside = ft_inside_headmodel(sourcemodel.pos, headmodel);
  end
end

% convert to logical representation
sourcemodel = fixinside(sourcemodel);

% keep the original details on inside and outside positions
originside = sourcemodel.inside;
origpos    = sourcemodel.pos;

% select only the dipole positions inside the brain for scanning
sourcemodel.pos    = sourcemodel.pos(originside,:);
sourcemodel.inside = true(size(sourcemodel.pos,1),1);

if hasmom
  sourcemodel.mom = sourcemodel.mom(:,originside);
end

if hasleadfield
  ft_info('using precomputed leadfields\n');
  sourcemodel.leadfield = sourcemodel.leadfield(originside);
else
  ft_info('computing forward model on the fly\n');
end

if ~isempty(cov)
  % compute signal and noise subspace from covariance matrix
  [u, s, v] = svd(cov);
else
  % compute signal and noise subspace from average data matrix
  [u, s, v] = svd(dat);
end
% select the noise subspace, c.f. equation 25
us = u(:,(numcomponent+1):end);
ps = us * us';

% allocate space to hold the result
estimate = [];
estimate.jr = nan(size(sourcemodel.pos,1),1);

ft_progress('init', feedback, 'scanning grid');
for i=1:size(sourcemodel.pos,1)
  ft_progress(i/size(sourcemodel.pos,1), 'scanning grid %d/%d\n', i, size(sourcemodel.pos,1));

  if hasleadfield && hasmom && size(sourcemodel.mom, 1)==size(sourcemodel.leadfield{i}, 2)
    % reuse the leadfield that was previously computed and project
    lf = sourcemodel.leadfield{i} * sourcemodel.mom(:,i);
  elseif  hasleadfield &&  hasmom
    % reuse the leadfield that was previously computed but don't project
    lf = sourcemodel.leadfield{i};
  elseif  hasleadfield && ~hasmom
    % reuse the leadfield that was previously computed
    lf = sourcemodel.leadfield{i};
  elseif ~hasleadfield &&  hasmom
    % compute the leadfield for a fixed dipole orientation
    lf = ft_compute_leadfield(sourcemodel.pos(i,:), sens, headmodel, leadfieldopt{:}) * sourcemodel.mom(:,i);
  else
    % compute the leadfield
    lf = ft_compute_leadfield(sourcemodel.pos(i,:), sens, headmodel, leadfieldopt{:});
  end

  % compute the music metric, c.f. equation 26
  estimate.jr(i) = (norm(ps * lf)./norm(lf)).^2;
  % as described in the Mosher 1992 paper on page 550, "...the general approach is to
  % evaluare Jr(i) over a fine three-dimensional grid, plot its inverse,
  % and look for p sharp spikes..."

end % for each dipole position
ft_progress('close');

% reassign the estimated values over the inside and outside grid positions
estimate.inside   = originside;
estimate.pos      = origpos;
if isfield(estimate, 'jr')
  estimate.jr( originside) = estimate.jr;
  estimate.jr(~originside) = nan;
end
if isfield(estimate, 'leadfield')
  estimate.leadfield( originside) = estimate.leadfield;
  estimate.leadfield(~originside) = {[]};
end


classdef Source < handle & matlab.mixin.Heterogeneous
	% Source is a superclass for all electric current sources J.

	properties (SetAccess = immutable)
		lgrid  % {x_array, y_array, z_array}: locations (intercepts with normal axis) of grid planes of grid type "this.gt"
		laltgrid  % {x_array, y_array, z_array}: locations (intercepts with normal axis) of grid planes of grid type "alter(this.gt)"
		shape  % shape of source; used to draw source
		forceprim  % true or false: flag to control the behavior of get.l()s
	end

	properties (SetAccess = private)
		gt  % GT.prim or GT.dual: type of grid line along which dipole sources of this source are defined
	end

	properties (Dependent, SetAccess = immutable)
		l
	end

	methods (Abstract = true)
		[index_cell, Jw_patch] = generate_kernel(this, w_axis, grid3d)
	end

	methods
		function this = Source(lgrid_cell, laltgrid_cell, shape, forceprim)
			chkarg(istypesizeof(lgrid_cell, 'realcell', [1 Axis.count], [1 0]), ...
				'"lgrid_cell" should be length-%d row cell array whose each element is row vector with real elements.', Axis.count);
			chkarg(istypesizeof(laltgrid_cell, 'realcell', [1 Axis.count], [1 0]), ...
				'"laltgrid_cell" should be length-%d row cell array whose each element is row vector with real elements.', Axis.count);
			chkarg(istypesizeof(shape, 'Shape'), '"shape" should be instance of Shape.');

			if nargin < 4  % no forceprim
				forceprim = false;
			end
			chkarg(istypesizeof(forceprim, 'logical'), '"forceprim" should be logical.');

			this.lgrid = lgrid_cell;
			this.laltgrid = laltgrid_cell;
			this.shape = shape;
			this.gt = GT.empty();
			this.forceprim = forceprim;
		end

		function set_gridtype(this, gt)
			% If this is SRCJ and E-field grid is primary, then gt = GT.prim.
			% If this is SRCJ and E-field grid is dual, then gt = GT.dual.
			% If this is SRCM and E-field grid is primary, then gt = GT.dual.
			% If this is SRCM and E-field grid is dual, then gt = GT.prim.
			chkarg(istypesizeof(gt, 'GT'), '"gt" should be instance of GT.');
			this.gt = gt;
		end

		function l = get.l(this)
			l = cell(Axis.count, GT.count);
			if this.forceprim
				l(:, GT.prim) = this.lgrid.';
				l(:, GT.dual) = this.laltgrid.';
			else
				l(:, this.gt) = this.lgrid.';
				l(:, alter(this.gt)) = this.laltgrid.';
			end
		end

		function [index_cell, JMw_patch] = generate(this, w_axis, grid3d)
			chkarg(istypesizeof(w_axis, 'Axis'), '"w_axis" should be instance of Axis.');
			chkarg(istypesizeof(grid3d, 'Grid3d'), '"grid3d" should be instance of Grid3d.');

			try
				[index_cell, JMw_patch] = this.generate_kernel(w_axis, grid3d);  % Cw_patch: current source
			catch err
				exception = MException('Maxwell:srcAssign', 'Source assignment failed.');
				throw(addCause(exception, err));
			end
		end
	end
end


% The COBRAToolbox: testloadBiGGModel.m
%
% Purpose:
%     - reads models from BiGG and the previously downloaded version in
%       the models directory and compares them.
%     - tests one model for equivalence wrt FBA results.
%
% Authors:
%     - Thomas Pfau
%

global CBTDIR
global CBT_MISSING_REQUIREMENTS_ERROR_ID

%Check the requirements (a LP solver is necessary)
solverPkgs = prepareTest('needsLP',true,'requireOneSolverOf',{'gurobi','ibm_cplex','glpk','mosek','quadMinos'},'needsWebAddress','http://bigg.ucsd.edu/api/v2/models');

% save the current path
currentDir = pwd;

% initialize the test
fileDir = fileparts(which('testLoadBiGGModel.m'));
cd(fileDir);

% initialize the test
cd([CBTDIR, filesep, 'test', filesep, 'models']);

% Models: FileName of local file, model ID and type for BiGG, along with
% FBA Min and Max value.
modelArr = {'iIT341.xml','iIT341','sbml','BiGGSBML',0,0.692812693473487;...
    'iJO1366.mat','iJO1366','mat','BiGG',NaN,NaN};

% set the tolerance
tol = 1e-6;

tested = false;

%loop through the models
for i = 1:size(modelArr,1)
    %reading the models takes quite a bit of time, so only do it once for
    %all solvers.
    % output a line before launching the test for model i
    fprintf('   Testing %s ...\n', modelArr{i,2});

    % load the model (actually supply the full filename of the path
    % where the model is found)
    model1 = getDistributedModel(modelArr{i,1});
    try
        model2 = loadBiGGModel(modelArr{i,2},modelArr{i,3});
        tested = true;
    catch ME
        if strcmp(ME.identifier,'MATLAB:webservices:Timeout')
            %Could not load the model, skip.
            continue;
        end
    end

    model3 = readCbModel(modelArr{i,2},'fileType',modelArr{i,4});

    %Check that the direct load is the same
    if 1
        printLevel=1;
        [isSame, nDiff, commonFields] = isSameCobraModel(model1, model2, printLevel);
        assert(isSame)
    else
        assert(isSameCobraModel(model1,model2));
    end

    %Check that the model loaded through readCbModel is the same.

    if 1
        printLevel=1;
        [isSame, nDiff, commonFields] = isSameCobraModel(model1, model3, printLevel);
        assert(isSame)
    else
        assert(isSameCobraModel(model1,model3));
    end

    if ~isnan(modelArr{i,5})
        for k = 1:length(solverPkgs.LP)
            fprintf(' -- Running testLoadBiGGModel using the solver interface: %s ... ', solverPkgs.LP{k});
            changeCobraSolver(solverPkgs.LP{k}, 'LP', 0);

            fprintf('   Testing loaded model ... \n');

            % solve the maximisation problem
            FBA = optimizeCbModel(model2, 'max');

            % test the maximisation solution
            assert(FBA.stat == 1);
            assert(abs(FBA.f - modelArr{i,6}) < tol);
            assert(norm(model2.S * FBA.x) < tol);

            % solve the minimisation problem
            FBA = optimizeCbModel(model2, 'min');

            % test the minimisation solution
            assert(FBA.stat == 1);
            assert(abs(FBA.f - modelArr{i,5}) < tol);
            assert(norm(model2.S * FBA.x) < tol);

            % print a line for success of loop i
            fprintf(' Done.\n');
        end
    end
end
%This should only ever happen, if the BiGG db could not be contacted.
if ~tested
    error(CBT_MISSING_REQUIREMENTS_ERROR_ID,'Could not connect to BiGG Database');
end
% change the directory
cd(currentDir)


function model = fgplvmExpandParam(model, params)

% FGPLVMEXPANDPARAM Expand a parameter vector into a GP-LVM model.
% FORMAT
% DESC takes an FGPLVM structure and a vector of parameters, and
% fills the structure with the given parameters. Also performs any
% necessary precomputation for likelihood and gradient
% computations, so can be computationally intensive to call.
% ARG model : the FGPLVM structure to put the parameters in.
% ARG params : parameter vector containing the parameters to put in
% the FGPLVM structure.
%
% COPYRIGHT : Neil D. Lawrence, 2005, 2006, 2009
%
% MODIFICATION : Carl Henrik Ek, 2009
%
% SEEALSO : fgplvmCreate, fgplvmExtractParam, modelExpandParam

% FGPLVM

startVal = 1;
if isfield(model, 'back') & ~isempty(model.back)
  % update modelParameters
  endVal = model.back.numParams;
  model.back = modelExpandParam(model.back, params(startVal:endVal));

  % update latent locations
  tmp = modelOut(model.back,model.y);
  tmp_dim = 1;
  for(i = 1:1:model.q)
    if(length(find(model.back.indexOut==i))~=0)
      model.X(:,model.back.indexOut(tmp_dim)) = tmp(:,tmp_dim);
      tmp_dim = tmp_dim + 1;
    else
      startVal = endVal + 1;
      endVal = endVal + model.N;
      model.X(:,i) = reshape(params(startVal:endVal),model.N,1);
    end
  end
  clear tmp tmp_dim;
else
  endVal = model.N*model.q;
  model.X = reshape(params(startVal:endVal), model.N, model.q);
end
startVal = endVal+1;
endVal = endVal + model.kern.nParams;

switch model.approx
 case 'ftc'
  endVal = endVal;
 case {'dtc', 'dtcvar', 'fitc', 'pitc'}
  if model.fixInducing
    % account for beta attached to the end.
    endVal = endVal + 1;
    % X_u values are taken from X values.
    model.X_u = model.X(model.inducingIndices, :);
  else
    % Parameters include inducing variables and beta.
    endVal = endVal + model.q*model.k + 1;
  end

 otherwise
  error('Unknown approximation type.')
end
if model.learnScales
  endVal = endVal + model.d;
end
model = gpExpandParam(model, params(startVal:endVal));

% Give parameters to dynamics if they are there.
if isfield(model, 'dynamics') & ~isempty(model.dynamics)
  startVal = endVal + 1;
  endVal = length(params);

  % Fill the dynamics model with current latent values.
  model.dynamics = modelSetLatentValues(model.dynamics, model.X);

  % Update the dynamics model with parameters (thereby forcing recompute).
  model.dynamics = modelExpandParam(model.dynamics, params(startVal:endVal));
end

% Constraints
if(isfield(model,'constraints')&&~isempty(model.constraints))
  for(i = 1:1:model.constraints.numConstraints)
    model.constraints.comp{i} = constraintExpandParam(model.constraints.comp{i},model.X);
  end
end


function cdf = gp_predcdf(gp, x, y, varargin)
%GP_PREDCDF  Predictive CDF evaluated at YT
%
%  Description
%    CDF = GP_PREDCDF(GP, X, Y, XT, 'yt', YT, OPTIONS)
%    takes a GP structure together with matrix X of training
%    inputs and vector Y of training targets, and evaluates the
%    cdf of the predictive distribution at test inputs XT, YT.
%
%    CDF = GP_PREDCDF(GP, X, Y, OPTIONS) evaluates the
%    cdf of the predictive distribution at training inputs X, Y.
%
%    OPTIONS is optional parameter-value pair
%      tstind - a vector defining, which rows of X belong to which
%               training block in *IC type sparse models. Default is [].
%               See also GP_PRED.
%      z      - optional observed quantity in triplet (x_i,y_i,z_i)
%               Some likelihoods may use this. For example, in case of
%               Poisson likelihood we have z_i=E_i, that is, expected value
%               for ith case.
%      zt     - optional observed quantity in triplet (xt_i,yt_i,zt_i)
%               Some likelihoods may use this. For example, in case of
%               Poisson likelihood we have z_i=E_i, that is, the expected
%               value for the ith case.
%
%  See also
%    GP_PRED, GP_PAK, GP_UNPAK
%
% Copyright (c) 2012 Aki Vehtari

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

  ip=inputParser;
  ip.FunctionName = 'GP_PREDCDF';
  ip.addRequired('gp',@(x) isstruct(x) || iscell(x));
  ip.addRequired('x', @(x) ~isempty(x) && isreal(x) && all(isfinite(x(:))))
  ip.addRequired('y', @(x) ~isempty(x) && isreal(x) && all(isfinite(x(:))))
  ip.addOptional('xt', [], @(x) isempty(x) || (isreal(x) && all(isfinite(x(:)))))
  ip.addParamValue('yt', [], @(x) isreal(x) && all(isfinite(x(:))))
  ip.addParamValue('z', [], @(x) isreal(x) && all(isfinite(x(:))))
  ip.addParamValue('zt', [], @(x) isreal(x) && all(isfinite(x(:))))
  ip.addParamValue('prct', [5 50 95], @(x) isreal(x) && all(isfinite(x(:))))
  ip.addParamValue('nsamp', 5000, @(x) isreal(x) && all(isfinite(x(:))))
  ip.addParamValue('predcf', [], @(x) isempty(x) || ...
                   isvector(x) && isreal(x) && all(isfinite(x)&x>0))
  ip.addParamValue('tstind', [], @(x) isempty(x) || iscell(x) ||...
                   (isvector(x) && isreal(x) && all(isfinite(x)&x>0)))
  if numel(varargin)==0 || isnumeric(varargin{1})
    % inputParser should handle this, but it doesn't
    ip.parse(gp, x, y, varargin{:});
  else
    ip.parse(gp, x, y, [], varargin{:});
  end
  xt=ip.Results.xt;
  yt=ip.Results.yt;
  z = ip.Results.z;
  zt = ip.Results.zt;
  prct = ip.Results.prct;
  nsamp = ip.Results.nsamp;
  predcf=ip.Results.predcf;
  tstind=ip.Results.tstind;
  if isempty(xt)
    xt=x;
    if isempty(tstind)
      if iscell(gp)
        gptype=gp{1}.type;
      else
        gptype=gp.type;
      end
      switch gptype
        case {'FULL' 'VAR' 'DTC' 'SOR'}
          tstind = [];
        case {'FIC' 'CS+FIC'}
          tstind = 1:size(x,1);
        case 'PIC'
          if iscell(gp)
            tstind = gp{1}.tr_index;
          else
            tstind = gp.tr_index;
          end
      end
    end
    if isempty(yt)
      yt=y;
    end
    if isempty(zt)
      zt=z;
    end
  end

  % pass these forward
  options=struct();
  if ~isempty(z);options.z=z;end
  if ~isempty(yt);options.yt=yt;end
  if ~isempty(zt);options.zt=zt;end
  if ~isempty(predcf);options.predcf=predcf;end
  if ~isempty(tstind);options.tstind=tstind;end

  [tn, nin] = size(x);

  if iscell(gp) || numel(gp.jitterSigma2)>1 || isfield(gp,'latent_method')
    % gp_array
    if iscell(gp)
      nGP = numel(gp);
      for i1=1:nGP
        Gp=gp{i1};
        P_TH(:,i1)=Gp.ia_weight;
        [Ef,Varf]=gp_pred(Gp,x,y,xt,options);
        cdfs(:,i1)=Gp.lik.fh.predcdf(Gp.lik, Ef, Varf, yt);
      end
      cdf=sum(bsxfun(@times,cdfs,P_TH),2);
    elseif numel(gp.jitterSigma2)>1
      % MCMC samples
      [Efs,Varfs]=gpmc_preds(gp,x,y,xt,options);
      nmc=size(gp.jitterSigma2,1);
      for i1=1:nmc
        Gp = take_nth(gp,i1);
        cdfs(:,i1)=Gp.lik.fh.predcdf(Gp.lik, Ef, Varf, yt);
      end
      cdf=mean(cdfs, 2);
    else
      [Ef,Varf]=gp_pred(gp,x,y,xt,options);
      cdf=gp.lik.fh.predcdf(gp.lik, Ef, Varf, yt);
    end

  end

end


function model = changeCOBRAConstraints(model, constraintID, varargin)
% Modify an existing COBRA constraint by providing new settings for the
% constraint to update existing settings.
% USAGE:
%    model = changeCOBRAConstraints(model, constraintID, varargin)
%
% INPUTS:
%    model:             model structure
%    constraintID:      The ID of the constraint (or the index in the
%                       ctrs field)
%
% OPTIONAL INPUTS:
%    varargin:      all elements (name, d, dsense and c can be modified as indicated below.
%                   * idList:           cell array of ids either from either the rxns, or the evars vectors. Can also be a a double vector of indices (in which case indices in evars have to be set off by numel(rxns).
%                   * c:                the elements of the C matrix. If idList is empty, this has to be a vector of length #rxns + #evars
%                   * dsense:           the constraint sense ('L': <= ,'G': >=, 'E': =), or a vector for multiple constraints
%                   * d:                The right hand side of the C*v <= d constraint (or a vector, for multiple simultaneous addition)
%                   * name:             The new, descriptive name of the constraint.
%
% OUTPUT:
%    model:         constrained model
%
% EXAMPLE:
%    Modify the constraint 'A_and_B_Lower_10' to read A + B + C <= 10
%    model = addCOBRAConstraints(model, 'A_and_B_Lower_10', 'idList', {'A','B','C'}, 'c', [1,1,1]);
%
% NOTE:
%    If c is provided, the whole constraint coefficients will be reset and
%    existing coefficients will be removed!
%
% Author: Thomas Pfau, Oct 2018

parser = inputParser();
parser.addRequired('model',@isstruct);
parser.addRequired('constraintID',@(x) ischar(x) && any(ismember(model.ctrs,x)));
parser.addParameter('d',[],@isnumeric);
parser.addParameter('c',[],@(x) isnumeric(x));
parser.addParameter('dsense','', @ischar );
parser.addParameter('idList',{},@(x) iscell(x) );
parser.addParameter('name',[],@(x) ischar(x) );
parser.parse(model,constraintID,varargin{:});

coefs = columnVector(parser.Results.c)';
d = parser.Results.d;
dsense = parser.Results.dsense;
idList = parser.Results.idList;
name = parser.Results.name;
c = parser.Results.c;

% get some model properties
[~,nRxns] = size(model.S);
if isfield(model,'evars')
    [nCtrs,nVars] = size(model.D);
else
    nVars = 0;
end

if ischar(constraintID)
    constraintID = find(ismember(model.ctrs,constraintID));
end

% check idList to determine new C/D values.
if ~isempty(c)
    if isempty(idList)
        if size(coefs,2) ~= nVars + nRxns
            error('If no idList is provided, the c vector has to contain one element for each reaction and each variable in the model');
        end
        newC = c(1:nRxns);
        newD = c((nRxns+1):end);
    else
        if size(c,2) ~= numel(idList)
            error('If idList is provided, the c vector has to contain one element for each element in idList');
        end
        % get the positions of the provided ids in rxns/evars
        [pos,pres] = getIDPositions(model,idList,'rxns');
        if any(~pres)
            missingreactions = idList(~pres);
            error('The following ids were not found in the model:\n%s\nNo Constraint was added',strjoin(missingreactions,', '));
        end
        % create the respective rows.
        newC = sparse(1,nRxns);
        newD = sparse(1,nVars);
        % get the positions of the variables
        vars = pos > nRxns;
        varPos = pos(vars) - nRxns;
        varCoefs = c(vars);
        rxns = pos <= nRxns;
        rxnPos = pos(rxns);
        rxnCoefs = c(rxns);
        newC(rxnPos) = rxnCoefs;
        newD(varPos) =varCoefs;
    end

    % set the rows if applicable
    model.C(constraintID,:) = newC;
    if isfield(model, 'D')
        model.D(constraintID,:) = newD;
    end
end

% update d
if ~isempty(d)
    model.d(constraintID) = d;
end

% update dsense
if ~isempty(dsense)
    model.dsense(constraintID) = dsense;
end

% update name:
if ~isempty(name)
    if ~isfield(model,'ctrNames')
        model = createEmptyFields(model,'ctrNames');
    end
    model.ctrNames{constraintID} = name;
end


dbcnn.name = 'dbcnn' ;
dbcnn.opts = {...
  'type', 'bcnn', ...
  'modela', 'D:\dbcnn\data\models\imagenet-vgg-verydeep-16.mat', ...
  'layera', 30,...
  'modelb', 'D:\dbcnn\data\models\scnn.mat', ...
  'layerb', 18,...
  'shareWeight', false,...
  };

opts.setupNameList = {'dbcnn'};
opts.encoderList = {{dbcnn}};
opts.datasetList = {{'live', 1}};
%opts.learningRate = 1e-6;
opts.momentum = 0.9;
opts.batchSize = 8;
opts.numEpoch = 30;
opts.dataset = opts.datasetList{1,1}{1};

srcc = zeros(1,10);
plcc = zeros(1,10);

switch opts.dataset
    case 'live'
        subdirec = 'data\checkgpu\live-seed-01';
        modelpath = 'models\LIVE_models';
        datapath = 'data\checkgpu\live-seed-01';
        opts.learningRate = 1e-6;
    case 'csiq'
        subdirec = 'data\checkgpu\csiq-seed-01';
        modelpath = 'models\CSIQ_models';
        datapath = 'data\checkgpu\csiq-seed-01';
        opts.learningRate = 1e-6;
    case 'tid'
        subdirec = 'data\checkgpu\tid-seed-01';
        modelpath = 'models\TID_models';
        datapath = 'data\checkgpu\tid-seed-01';
        opts.learningRate = 1e-5;
    case 'mlive'
        subdirec = 'data\checkgpu\mlive-seed-01';
        modelpath = 'models\MLIVE_models';
        datapath = 'data\checkgpu\mlive-seed-01';
        opts.learningRate = 1e-5;
    case 'clive'
        subdirec = 'data\checkgpu\clive-seed-01';
        modelpath = 'models\Challen_models';
        datapath = 'data\checkgpu\clive-seed-01';
        opts.learningRate = 1e-5;
end

for split = 1:10
    mkdir(subdirec);
    rmdir(subdirec,'s');
    imdbpath = fullfile(subdirec,'imdb');
    mkdir(imdbpath);
    copyfile(fullfile(modelpath,num2str(split),'imdb-seed-1.mat'),...
        fullfile(imdbpath,'imdb-seed-1.mat'));
    [options, imdb] = run_experiments_bcnn_train(opts);
    deploy_each_dagnet(opts.numEpoch, datapath);
    options.ftpath = fullfile(subdirec,'fine-tuned-model');
    [srcc(1,split),plcc(1,split),index] = find_bestmodel(opts.numEpoch, imdb, options);
end


function [ output_args ] = Makeparadigm_MI( varargin )
% Makeparadigm_MI (Experimental paradigm):
%
% Description:
%   Basic motor imagery experiment paradigm using psychtoolbox.
%   It shows a cross, an arrow, and blank screen alternately.
%
% Example:
%   Makeparadigm_MI({'time_cross',1.5;'time_sti',60;'time_blank',5;'num_trial',1;'num_class',3});
%
% Input: (Nx2 size, cell-type)
%   time_cross  - time for concentration, showing a cross [s]
%   time_sti    - time for a stimulus, showing an arrow (right, left, or down) [s]
%   time_blank  - time for rest, showing nothing but gray screen [s]
%   num_trial   - number of trials per class
%   num_class   - number of class you want, 1 to 3, (right, left, and foot)
%   num_screen  - number of screen to show
%   screen_size - size of window showing experimental stimulus
%                 'full' or matrix (e.g.[0 0 300 300])
%

opt=opt_cellToStruct(varargin{:});

%% default setting
if ~isfield(opt,'time_sti'),    time_sti=4;      else time_sti=opt.time_sti;      end
if ~isfield(opt,'time_cross'),  time_cross=3;    else time_cross=opt.time_cross;  end
if ~isfield(opt,'time_blank'),  time_blank=3;    else time_blank=opt.time_blank;  end
if ~isfield(opt,'num_trial'),   num_trial=50;    else num_trial=opt.num_trial;    end
% if ~isfield(opt,'time_jitter'), time_jitter=0.1; else time_jitter=opt.time_jitter;end
if ~isfield(opt,'num_class'),   num_class=3;     else num_class=opt.num_class;    end
% screenNumber=2;

%% screen setting
screens=Screen('Screens');
if ~isfield(opt,'num_screen'),screenNumber=max(screens); else screenNumber=opt.num_screen; end
if ~isfield(opt,'screen_size'),screen_size='full'; else screen_size=opt.screen_size; end
% if ~isfield(opt,'screen_type'),screen_type='window'; else screen_type=opt.screen_type; end

%% beep setting
beep='on';
freq=22000;
beepLengthSecs=0.5;

%% trigger setting
global IO_ADDR IO_LIB;
IO_ADDR=hex2dec('D010');
IO_LIB=which('inpoutx64.dll');

%% jittering
a=-1;b=1;
% association with + time jittering
jitter = a + (b-a).*rand(num_trial*num_class,1);
jitter=jitter*0.5;

%% image load
currentFile = mfilename( 'fullpath' );
[pathstr,~,~] = fileparts( currentFile );
img_right=imread(fullfile(pathstr, "..", '\Stimulus\right.jpg'));
img_left=imread(fullfile(pathstr, "..",'\Stimulus\\left.jpg'));
img_down=imread(fullfile(pathstr, "..",'\Stimulus\down.jpg'));
% img_cross=imread('\Stimulus\cross.jpg');

%% beep sound
if strcmp(beep,'on')
    [beep,samplingRate] = MakeBeep(500,beepLengthSecs,freq);
    Snd('Open');
    sound=1;
else
    sound=0;
end
% Screen('Preference', 'SkipSyncTests', 1);

%% psychtoolbox setting
gray=GrayIndex(screenNumber);
% screenRes = [0 0 300 300];
if strcmp(screen_size,'full')
    [w, wRect]=Screen('OpenWindow',screenNumber, gray);
else
    [w, wRect]=Screen('OpenWindow',screenNumber, gray, screen_size);
end

%% order of stimulus (random)
for i=1:num_class
    a1(i,1:num_trial)=i;
end
% a1=Shuffle(a1);
% [t s]=size(a1);
% sti_stack=reshape(a1,1,t*s);
sti_stack=Shuffle(a1(:)'); % smkim

% click to start:
Screen('TextSize',w, 50);
DrawFormattedText(w,'Mouse click to start MI experiment \n\n (Press s to pause, esc to stop)','center','center',[0 0 0]);
Screen('Flip', w);
GetClicks(w);
ppTrigger(111); % START

escapeKey = KbName('esc');
waitKey=KbName('s');
p_close=0;

%% Eyes open/closed
% run(fullfile(pathstr,"..", '\Artifact\eyesOpenClosed')) % script
run('Paradigm\Artifact\eyesOpenClosed') % script

%% fixation cross
[X,Y] = RectCenter(wRect);
FixationSize = 20;
FixCross = [X-1,Y-FixationSize,X+1,Y+FixationSize;X-FixationSize,Y-1,X+FixationSize,Y+1];

%% paradigm start
    Screen('FillRect', w, [0 0 0], FixCross');
    Screen('Flip', w);
    WaitSecs(2.5)

for num_stimulus=1:length(sti_stack)

    if num_stimulus==length(sti_stack)/2
        Screen('TextSize',w, 50);
        DrawFormattedText(w,'Rest\n\n(Pause the brain vision)','center','center',[0 0 0]);
        Screen('Flip', w);
        GetClicks(w);
        DrawFormattedText(w,'(Resume recording)','center','center',[0 0 0]);
        Screen('Flip', w);
        GetClicks(w);
        DrawFormattedText(w,'Click to continue the experiment','center','center',[0 0 0]);
        Screen('Flip', w);
        GetClicks(w);
    end

    start=GetSecs;
    while GetSecs < start+time_blank+jitter(num_stimulus)-2
        [ keyIsDown, seconds, keyCode ] = KbCheck;
        if keyIsDown
            if keyCode(escapeKey)
%                 ShowCursor;
%                 p_close=1;
                Screen('CloseAll');
                fclose('all');
                return
            elseif keyCode(waitKey)
                warning('stop')
                GetClicks(w);
                Screen('Close',tex1);

            end
        end
        pause(0.1);
    end

%     if p_close
%         break;
%     end

    Screen('FillRect', w, [0 0 0], FixCross');
    Screen('Flip', w);
    if sound
        Snd('Play',beep);
    end

    WaitSecs(1)
    ppTrigger(5);
    WaitSecs(time_cross)

    switch sti_stack(num_stimulus)
        case 1 % right class
            ppTrigger(1);
            image=img_right;
            tex1=Screen('MakeTexture', w, image );
            Screen('DrawTexture', w, tex1);
            Screen('FillRect', w, [0 0 0], FixCross');
            Screen('Flip', w);

            WaitSecs(time_sti);
            Screen('Close',tex1);
%             ppTrigger(11);

        case 2 % left class
            ppTrigger(2);
            image=img_left;
            tex1=Screen('MakeTexture', w, image );
            Screen('DrawTexture', w, tex1);
            Screen('FillRect', w, [0 0 0], FixCross');
            Screen('Flip', w);

            WaitSecs(time_sti);
            Screen('Close',tex1);
%             ppTrigger(22);

        case 3 % foot class
            ppTrigger(3);
            image=img_down;
            tex1=Screen('MakeTexture', w, image );
            Screen('DrawTexture', w, tex1);
            Screen('FillRect', w, [0 0 0], FixCross');
            Screen('Flip', w);

            WaitSecs(time_sti);
            Screen('Close',tex1);
%             ppTrigger(33);
    end
    num_stimulus

    Screen('Flip', w);
    WaitSecs(time_blank)

end

ppTrigger(222);
Screen('TextSize',w, 50);
DrawFormattedText(w, 'Thank you', 'center', 'center', [0 0 0]);
Screen('Flip', w);
WaitSecs(2);
Screen('CloseAll');
ShowCursor;
fclose('all');
Priority(0);


function invert = spm_cfg_eeg_inv_invert
% Configuration file for configuring imaging source inversion
% reconstruction
%__________________________________________________________________________
% Copyright (C) 2010-2016 Wellcome Trust Centre for Neuroimaging

% Vladimir Litvak
% $Id: spm_cfg_eeg_inv_invert.m 7076 2017-05-19 12:47:36Z vladimir $

D = cfg_files;
D.tag = 'D';
D.name = 'M/EEG datasets';
D.filter = 'mat';
D.num = [1 Inf];
D.help = {'Select the M/EEG mat files.'};

val = cfg_entry;
val.tag = 'val';
val.name = 'Inversion index';
val.strtype = 'n';
val.help = {'Index of the cell in D.inv where the forward model can be found and the results will be stored.'};
val.val = {1};

all = cfg_const;
all.tag = 'all';
all.name = 'All';
all.val  = {1};
all.help = {''};

condlabel = cfg_entry;
condlabel.tag = 'condlabel';
condlabel.name = 'Condition label';
condlabel.strtype = 's';
condlabel.val = {''};
condlabel.help = {''};

conditions = cfg_repeat;
conditions.tag = 'conditions';
conditions.name = 'Conditions';
conditions.help = {'Specify the labels of the conditions to be included in the inversion'};
conditions.num  = [1 Inf];
conditions.values  = {condlabel};
conditions.val = {condlabel};

whatconditions = cfg_choice;
whatconditions.tag = 'whatconditions';
whatconditions.name = 'What conditions to include?';
whatconditions.values = {all, conditions};
whatconditions.val = {all};
whatconditions.help = {'What conditions to include?'};

standard = cfg_const;
standard.tag = 'standard';
standard.name = 'Standard';
standard.help = {'Use default settings for the inversion'};
standard.val  = {1};

invtype = cfg_menu;
invtype.tag = 'invtype';
invtype.name = 'Inversion type';
invtype.help = {'Select the desired inversion type'};
invtype.labels = {'MSP (GS)',  'COH', 'IID', 'EBB'};
invtype.values = {'GS',        'LOR', 'IID', 'EBB'};
invtype.val = {'GS'};

woi = cfg_entry;
woi.tag = 'woi';
woi.name = 'Time window of interest';
woi.strtype = 'r';
woi.num = [1 2];
woi.val = {[-Inf Inf]};
woi.help = {'Time window to include in the inversion (ms)'};

foi = cfg_entry;
foi.tag = 'foi';
foi.name = 'Frequency window of interest';
foi.strtype = 'r';
foi.num = [1 2];
foi.val = {[0 256]};
foi.help = {'Frequency window (the same as high-pass and low-pass in the GUI)'};

hanning = cfg_menu;
hanning.tag = 'hanning';
hanning.name = 'PST Hanning window';
hanning.help = {'Multiply the time series by a Hanning taper to emphasize the central part of the response.'};
hanning.labels = {'yes', 'no'};
hanning.values = {1, 0};
hanning.val = {1};

priorsmask  = cfg_files;
priorsmask.tag = 'priorsmask';
priorsmask.name = 'Priors file';
priorsmask.filter = '(.*\.gii$)|(.*\.mat$)|(.*\.nii(,\d+)?$)|(.*\.img(,\d+)?$)';
priorsmask.num = [0 1];
priorsmask.help = {'Select a mask or a mat file with priors.'};
priorsmask.val = {{''}};

space = cfg_menu;
space.tag = 'space';
space.name = 'Prior image space';
space.help = {'Space of the mask image.'};
space.labels = {'MNI', 'Native'};
space.values = {1, 0};
space.val = {1};

priors = cfg_branch;
priors.tag = 'priors';
priors.name = 'Source priors';
priors.help = {'Restrict solutions to pre-specified VOIs'};
priors.val  = {priorsmask, space};

locs  = cfg_entry;
locs.tag = 'locs';
locs.name = 'Source locations';
locs.strtype = 'r';
locs.num = [Inf 3];
locs.help = {'Input source locations as n x 3 matrix'};
locs.val = {zeros(0, 3)};

radius = cfg_entry;
radius.tag = 'radius';
radius.name = 'Radius of VOI (mm)';
radius.strtype = 'r';
radius.num = [1 1];
radius.val = {32};
radius.help = {''};

mask  = cfg_files;
mask.tag = 'mask';
mask.name = 'Mask image';
mask.filter = '(.*\.nii(,\d+)?$)|(.*\.img(,\d+)?$)';
mask.num = [0 1];
mask.help = {'Select a mask image'};
mask.val = {{''}};

restrict = cfg_branch;
restrict.tag = 'restrict';
restrict.name = 'Restrict solutions';
restrict.help = {'Restrict solutions to pre-specified VOIs'};
restrict.val  = {locs, radius, mask};

custom = cfg_branch;
custom.tag = 'custom';
custom.name = 'Custom';
custom.help = {'Define custom settings for the inversion'};
custom.val  = {invtype, woi, foi, hanning, priors, restrict};

isstandard = cfg_choice;
isstandard.tag = 'isstandard';
isstandard.name = 'Inversion parameters';
isstandard.help = {'Choose whether to use standard or custom inversion parameters.'};
isstandard.values = {standard, custom};
isstandard.val = {standard};

modality = cfg_menu;
modality.tag = 'modality';
modality.name = 'Select modalities';
modality.help = {'Select modalities for the inversion (only relevant for multimodal datasets).'};
modality.labels = {'All', 'EEG', 'MEG', 'MEGPLANAR', 'EEG+MEG', 'MEG+MEGPLANAR', 'EEG+MEGPLANAR', 'EEG+MEG+MEGPLANAR'};
modality.values = {
    {'All'}
    {'EEG'}
    {'MEG'}
    {'MEGPLANAR'}
    {'EEG', 'MEG'}
    {'MEG', 'MEGPLANAR'}
    {'EEG', 'MEGPLANAR'}
    {'EEG', 'MEG', 'MEGPLANAR'}
    }';
modality.val = {{'All'}};

invert = cfg_exbranch;
invert.tag = 'invert';
invert.name = 'Source inversion';
invert.val = {D, val, whatconditions, isstandard, modality};
invert.help = {'Run imaging source reconstruction'};
invert.prog = @run_inversion;
invert.vout = @vout_inversion;
invert.modality = {'EEG'};

function  out = run_inversion(job)

D = spm_eeg_load(job.D{1});

inverse = [];
if isfield(job.whatconditions, 'condlabel')
    inverse.trials = job.whatconditions.condlabel;
end

if isfield(job.isstandard, 'custom')
    inverse.type = job.isstandard.custom.invtype;
    inverse.woi  = fix([max(min(job.isstandard.custom.woi), 1000*D.time(1)) min(max(job.isstandard.custom.woi), 1000*D.time(end))]);
    inverse.Han  = job.isstandard.custom.hanning;
    inverse.lpf  =  fix(min(job.isstandard.custom.foi));
    inverse.hpf  =  fix(max(job.isstandard.custom.foi));

    P = char(job.isstandard.custom.priors.priorsmask);
    if ~isempty(P)
        [p,f,e] = fileparts(P);
        switch lower(e)
            case '.gii'
                g = gifti(P);
                inverse.pQ = cell(1,size(g.cdata,2));
                for i=1:size(g.cdata,2)
                    inverse.pQ{i} = double(g.cdata(:,i));
                end
            case '.mat'
                load(P);
                inverse.pQ = pQ;
            case {'.img', '.nii'}
                S.D = D;
                S.fmri = P;
                S.space = job.isstandard.custom.priors.space;
                D = spm_eeg_inv_fmripriors(S);
                inverse.fmri = D.inv{D.val}.inverse.fmri;
                load(inverse.fmri.priors);
                inverse.pQ = pQ;
            otherwise
                error('Unknown file type.');
        end
    end

    if ~isempty(job.isstandard.custom.restrict.locs)
        inverse.xyz = job.isstandard.custom.restrict.locs;
        inverse.rad = job.isstandard.custom.restrict.radius;
    end

    P = char(job.isstandard.custom.restrict.mask);
    if ~isempty(P)
        inverse.mask = P;
    end
end

[mod, list] = modality(D, 1, 1);
if strcmp(job.modality{1}, 'All')
    inverse.modality  = list;
else
    inverse.modality  = intersect(list, job.modality);
end

if numel(inverse.modality) == 1
    inverse.modality = inverse.modality{1};
end

D = {};

for i = 1:numel(job.D)
    D{i} = spm_eeg_load(job.D{i});

    D{i}.val = job.val;

    D{i}.con = 1;

    if ~isfield(D{i}, 'inv')
        error('Forward model is missing for subject %d.', i);
    elseif  numel(D{i}.inv)<D{i}.val || ~isfield(D{i}.inv{D{i}.val}, 'forward')
        if D{i}.val>1 && isfield(D{i}.inv{D{i}.val-1}, 'forward')
            D{i}.inv{D{i}.val} = D{i}.inv{D{i}.val-1};
            warning('Duplicating the last forward model for subject %d.', i);
        else
            error('Forward model is missing for subject %d.', i);
        end
    end

    D{i}.inv{D{i}.val}.inverse = inverse;
end

D = spm_eeg_invert(D);

if ~iscell(D)
    D = {D};
end

for i = 1:numel(D)
    save(D{i});
end

out.D = job.D;

function dep = vout_inversion(job)
% Output is always in field "D", no matter how job is structured
dep = cfg_dep;
dep.sname = 'M/EEG dataset(s) after imaging source reconstruction';
% reference field "D" from output
dep.src_output = substruct('.','D');
% this can be entered into any evaluated input
dep.tgt_spec   = cfg_findspec({{'filter','mat'}});


function engine = jtree_2TBN_inf_engine(bnet, varargin)
% JTREE_ONLINE_INF_ENGINE Online Junction tree inference algorithm for DBNs.
% engine = jtree_online_inf_engine(bnet, ...)
%
% The following optional arguments can be specified in the form of name/value pairs:
% [default value in brackets]
%
% clusters - specifies variables that must be grouped in the 1.5 slice DBN
% maximize - 1 means do max-product, 0 means sum-product [0]
%
% The same nodes must be observed in every slice.

ss = length(bnet.intra);
clusters = {};
engine.maximize = 0;

args = varargin;
nargs = length(args);
for i=1:2:length(args)
  switch args{i},
   case 'clusters', clusters = args{i+1};
   case 'maximize', engine.maximize = args{i+1};
   otherwise, error(['unrecognized argument ' args{i}])
  end
end

engine.evidence = [];
engine.node_sizes = [];

%int = compute_interface_nodes(bnet.intra, bnet.inter);
int = [];

if 1
% include nodes with any outgoing arcs
for u=1:ss
  if any(bnet.inter(u,:))
    int = [int u];
  end
end
end

if 0
% include nodes with any incoming  arcs
incoming = [];
for u=1:ss
  if any(bnet.inter(:,u))
    int = [int u];
    incoming = [incoming u];
  end
end
% include nodes which are parents of nodes with incoming
for u=1:ss
  cs = children(bnet.intra, u);
  if ~isempty(cs) & mysubset(cs, incoming)
    int = [int u];
  end
end
int = unique(int);
end % if

int
engine.interface = int;
engine.nonint = mysetdiff(1:ss, int);

onodes = bnet.observed;

% Create a "1.5 slice" jtree, containing the interface nodes of slice 1
% and all the nodes of slice 2
% To keep the node numbering the same, we simply disconnect the non-interface nodes
% from slice 1, and set their size to 1.
% We do this to speed things up, and so that the likelihood is computed correctly - we do not need to do
% this if we just want to compute marginals (i.e., we can include nodes whose potentials will
% be left as all 1s).
intra15 = bnet.intra;
for i=engine.nonint(:)'
  intra15(:,i) = 0;
  intra15(i,:) = 0;
end
dag15 = [intra15      bnet.inter;
	 zeros(ss)    bnet.intra];
ns = bnet.node_sizes(:);
%ns(engine.nonint) = 1; % disconnected nodes get size 1
obs_nodes = [onodes(:) onodes(:)+ss];
bnet15 = mk_bnet(dag15, ns, 'discrete', bnet.dnodes, 'equiv_class', bnet.equiv_class(:), ...
		 'observed', obs_nodes(:));

% use unconstrained elimination,
% but force there to be a clique containing both interfaces
clusters(end+1:end+2) = {int, int+ss};
engine.jtree_engine = jtree_inf_engine(bnet15, 'clusters', clusters, 'root', int+ss);
jtree_engine = struct(engine.jtree_engine); % violate object privacy

engine.in_clq = clq_containing_nodes(engine.jtree_engine, int);
engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss);
engine.clq_ass_to_node = jtree_engine.clq_ass_to_node;
engine.root = jtree_engine.root_clq;

% Also create an engine just for slice 1
bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, 'discrete', myintersect(bnet.dnodes,1:ss), ...
		'equiv_class', bnet.equiv_class(:,1), 'observed', onodes);
for i=1:max(bnet1.equiv_class)
  bnet1.CPD{i} = bnet.CPD{i};
end
engine.jtree_engine1 = jtree_inf_engine(bnet1, 'clusters', {int}, 'root', int);
jtree_engine1 = struct(engine.jtree_engine1); % violate object privacy
engine.int_clq1 = clq_containing_nodes(engine.jtree_engine1, int);
engine.clq_ass_to_node1 = jtree_engine1.clq_ass_to_node;
engine.root1 = jtree_engine1.root_clq;

engine.observed = [onodes onodes+ss];
engine.observed1 = onodes;
engine.pot_type = determine_pot_type(bnet, onodes);
engine.slice_size = bnet.nnodes_per_slice;

engine = class(engine, 'jtree_2TBN_inf_engine', inf_engine(bnet));


function test_ft_appendsens

% MEM 2gb
% WALLTIME 00:10:00
% DEPENDENCY

% regular
elec1.elecpos = [1 1 1; 2 2 2; 3 3 3];
elec1.chanpos = elec1.elecpos;
elec1.label = {'1';'2';'3'};
elec1.unit  = 'mm';
elec1.coordsys  = 'acpc';

elec2.elecpos = [4 4 4; 5 5 5];
elec2.chanpos = elec2.elecpos;
elec2.label = {'4';'5'};
elec2.unit  = 'mm';
elec2.coordsys  = 'acpc';

elec = ft_appendsens([], elec1, elec2);

% duplicate chanpos, elecpos, and channel
elec1.elecpos = [1 1 1; 2 2 2; 3 3 3];
elec1.chanpos = elec1.elecpos;
elec1.label = {'1';'2';'3'};
elec1.unit  = 'mm';
elec1.coordsys  = 'acpc';
elec1.tra  = [1 0 0; 0 1 0; 0 0 1];
elec2.elecpos = [2 2 2; 0 0 0]; % 2 2 2 is a duplicate
elec2.chanpos = elec2.elecpos;
elec2.label = {'2';'7'}; % 2 is a duplicate
elec2.unit  = 'mm';
elec2.coordsys  = 'acpc';
elec2.tra  = [1 0; 0 1];
elec = ft_appendsens([], elec1, elec2);

% duplicate elecpos (eg same elec used for two bipolar derivations)
elec1.elecpos = [1 1 1; 2 2 2];
elec1.chanpos = [1.5 1.5 1.5];
elec1.label = {'1-2'};
elec1.unit  = 'mm';
elec1.coordsys  = 'acpc';
elec1.tra  = [1 -1];
elec2.elecpos = [2 2 2; 3 3 3]; % 2 2 2 is a duplicate
elec2.chanpos = [2.5 2.5 2.5];
elec2.label = {'2-3'}; % 2 is a duplicate
elec2.unit  = 'mm';
elec2.coordsys  = 'acpc';
elec2.tra  = [1 -1];

elec = ft_appendsens([], elec1, elec2);

% duplicate chanpos and elecpos, but no duplicate label (eg two electrodes
% localized to the same location)
elec1.elecpos = [1 1 1; 2 2 2; 3 3 3];
elec1.chanpos = elec1.elecpos;
elec1.label = {'1';'2';'3'};
elec1.unit  = 'mm';
elec1.coordsys  = 'acpc';
elec1.tra  = [1 0 0; 0 1 0; 0 0 1];
elec2.elecpos = [2 2 2; 0 0 0]; % 2 2 2 is a duplicate
elec2.chanpos = elec2.elecpos;
elec2.label = {'8';'7'}; % no duplicate label
elec2.unit  = 'mm';
elec2.coordsys  = 'acpc';
elec2.tra  = [1 0; 0 1];

try
  elec = ft_appendsens([], elec1, elec2);
  % this SHOULD throw an error because two labels for the same chanpos are not allowed
  error('an error was expected but not thrown')
catch
  fprintf('ft_appendsens threw an error as expected\n')
end