function feature = import_idt(file,tra_len)
if nargin < 2
    tra_len = 15;
end
    fid = fopen(file,'rb');
    feat = fread(fid,[10+4*tra_len+96*3+108,inf],'float');
	feature = struct('info',[],'tra',[],'tra_shape',[],'hog',[],'hof',[],'mbhx',[],'mbhy',[]);
	if ~isempty(feat)
		feature.info = feat(1:10,:);
		feature.tra = feat(11:10+tra_len*2,:);
        feature.tra_shape = feat(11+tra_len*2:10+tra_len*4,:);
        ind = 10+tra_len*4;
		feature.hog = feat(ind+1:ind+96,:);
		feature.hof = feat(ind+97:ind+204,:);
		feature.mbhx = feat(ind+205:ind+300,:);
		feature.mbhy = feat(ind+301:end,:);
	end
    fclose(fid);
end


function net = insertLossLayers(net, varargin)

import dagnn.*
opts.numClasses = 101;
opts = vl_argparse(opts, varargin);

for p = 1:numel(net.params)
  name = net.params(p).name ;
  sz = size(net.params(p).value);
  if numel(sz) == 4
    if sz(4) == opts.numClasses
      lossAlreadyExists = false;
        for l=1:numel(net.layers)
          if ~isempty(net.layers(l).params)
            if any(strcmp(name, net.layers(l).params(:))), break; end
          end
        end
        pred_layer = l;
        for l = 1:numel(net.layers)
          if any(strcmp(net.layers(pred_layer).outputs, net.layers(l).inputs))  && ...
              isa(net.layers(l).block, 'dagnn.Loss') && isempty(strfind(net.layers(l).name, 'err'))
              lossAlreadyExists = true;
              break;
          end
        end
        if lossAlreadyExists, continue; end;
        name = sprintf('loss_%s',net.layers(pred_layer).name);
        net.addLayer(name, ...
          dagnn.Loss( 'loss', 'softmaxlog'), ...
             [net.layers(pred_layer).outputs{:} {'label'}], sprintf('objective_%s',net.layers(pred_layer).name)) ;
    end
  end

end


function [model] = em_single_instance(model_3d,test, instance, max_em_iter)
%EM_SINGLE_INSTANCE Summary of this function goes here
%   Detailed explanation goes here
params = get_params();

%% Changing test data for just the particular instance
N = size(test.points,1)/2;
testInstance.points = test.points([instance N+instance],:);
testInstance.voc_image_id{1} = test.voc_image_id{instance};
testInstance.labels = test.labels;
testInstance.bbox = test.bbox(instance,:);
testInstance.imsize = test.imsize(instance,:);
try
    testInstance.poly_x = test.poly_x(instance);
    testInstance.poly_y = test.poly_y(instance);
catch
    testInstance.mask = test.mask{instance};
end
testInstance.bbox   = test.bbox(instance,:);
if(isfield(test,'voc_rec_id'))
    testInstance.voc_rec_id(1) = test.voc_rec_id(instance);
end
if(isfield(test,'flip'))
    testInstance.flip(1) = test.flip(instance);
end

%% Obtaining the model
model = test_nrsfm(testInstance,model_3d,max_em_iter);

end


function [varargout] = ft_plot_box(position, varargin)

% FT_PLOT_BOX plots the outline of a box that is specified by its lower
% left and upper right corner
%
% Use as
%   ft_plot_box(position, ...)
% where the position of the box is specified as is [x1, x2, y1, y2].
%
% Optional arguments should come in key-value pairs and can include
%   'facealpha'       = transparency value between 0 and 1
%   'facecolor'       = color specification as [r g b] values or a string, for example 'brain', 'cortex', 'skin', 'red', 'r'
%   'edgecolor'       = color specification as [r g b] values or a string, for example 'brain', 'cortex', 'skin', 'red', 'r'
%   'tag'             = string, the name assigned to the object. All tags with the same name can be deleted in a figure, without deleting other parts of the figure.
%
% It is possible to plot the object in a local pseudo-axis (c.f. subplot), which is specfied as follows
%   'hpos'            = horizontal position of the center of the local axes
%   'vpos'            = vertical position of the center of the local axes
%   'width'           = width of the local axes
%   'height'          = height of the local axes
%   'hlim'            = horizontal scaling limits within the local axes
%   'vlim'            = vertical scaling limits within the local axes
%   'parent'          = handle which is set as the parent for all plots
%
% Example
%   ft_plot_box([-1 1 2 3], 'facecolor', 'b')
%   axis([-4 4 -4 4])
%
% See also FT_PLOT_LINE, FT_PLOT_CROSSHAIR

% Copyrights (C) 2009-2011, 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$

ws = warning('on', 'MATLAB:divideByZero');

% get the optional input arguments
hpos        = ft_getopt(varargin, 'hpos');
vpos        = ft_getopt(varargin, 'vpos');
width       = ft_getopt(varargin, 'width');
height      = ft_getopt(varargin, 'height');
hlim        = ft_getopt(varargin, 'hlim');
vlim        = ft_getopt(varargin, 'vlim');
facealpha   = ft_getopt(varargin, 'facealpha', 1);
facecolor   = ft_getopt(varargin, 'facecolor', 'none');
edgecolor   = ft_getopt(varargin, 'edgecolor', 'k');
tag         = ft_getopt(varargin, 'tag',       '');
parent      = ft_getopt(varargin, 'parent', []);

% color management
if ischar(facecolor) && exist([facecolor '.m'], 'file')
	facecolor = eval(facecolor);
end
if ischar(edgecolor) && exist([edgecolor '.m'], 'file')
	edgecolor = eval(edgecolor);
end

% convert the two cornerpoints into something that the patch function understands
% the box position is represented just like the argument to the AXIS function
x1 = position(1);
x2 = position(2);
y1 = position(3);
y2 = position(4);
X = [x1 x2 x2 x1 x1];
Y = [y1 y1 y2 y2 y1];

if isempty(hlim) && isempty(vlim) && isempty(hpos) && isempty(vpos) && isempty(height) && isempty(width)
  % no scaling is needed, the input X and Y are already fine
  % use a shortcut to speed up the plotting

else
  % use the full implementation
  if isempty(hlim)
    hlim = get(gca, 'XLim');
  end

  if isempty(vlim)
    vlim = get(gca, 'YLim');
  end

  if isempty(hpos)
    hpos = (hlim(1)+hlim(2))/2;
  end

  if isempty(vpos)
    vpos = (vlim(1)+vlim(2))/2;
  end

  if isempty(width)
    width = hlim(2)-hlim(1);
  end

  if isempty(height)
    height = vlim(2)-vlim(1);
  end

  % first shift the horizontal axis to zero
  X = X - (hlim(1)+hlim(2))/2;
  % then scale to length 1
  X = X ./ (hlim(2)-hlim(1));
  % then scale to the new width
  X = X .* width;
  % then shift to the new horizontal position
  X = X + hpos;

  % first shift the vertical axis to zero
  Y = Y - (vlim(1)+vlim(2))/2;
  % then scale to length 1
  Y = Y ./ (vlim(2)-vlim(1));
  % then scale to the new width
  Y = Y .* height;
  % then shift to the new vertical position
  Y = Y + vpos;

end % shortcut

% use an arbitrary color, which will be replaced by the correct color a few lines down
C = 0;

h = patch(X, Y, C);
set(h, 'FaceAlpha', facealpha)
set(h, 'FaceColor', facecolor)
set(h, 'EdgeColor', edgecolor)
set(h, 'tag', tag);

if ~isempty(parent)
  set(h, 'Parent', parent);
end

% the (optional) output is the handle
if nargout == 1
  varargout{1} = h;
end

warning(ws); % revert to original state


%% Create a TSE sequence and export for execution
%
% The |Sequence| class provides functionality to create magnetic
% resonance sequences (MRI or NMR) from basic building blocks.
%
% This provides an implementation of the open file format for MR sequences
% described here: http://pulseq.github.io/specification.pdf
%
% This example performs the following steps:
%
% # Create slice selective RF pulse for imaging.
% # Create readout gradient and phase encode strategy.
% # Loop through phase encoding and generate sequence blocks.
% # Write the sequence to an open file format suitable for execution on a
% scanner.
%
%   Juergen Hennig <juergen.hennig@uniklinik-freiburg.de>
%   Maxim Zaitsev  <maxim.zaitsev@uniklinik-freiburg.de>

%% Instantiation and gradient limits
% The system gradient limits can be specified in various units _mT/m_,
% _Hz/cm_, or _Hz/m_. However the limits will be stored internally in units
% of _Hz/m_ for amplitude and _Hz/m/s_ for slew. Unspecificied hardware
% parameters will be assigned default values.

dG=250e-6;
system = mr.opts('MaxGrad', 30, 'GradUnit', 'mT/m', ...
    'MaxSlew', 170, 'SlewUnit', 'T/m/s', 'rfRingdownTime', 100e-6, ...
    'rfDeadTime', 100e-6, 'adcDeadTime', 10e-6);

%%
% A new sequence object is created by calling the class constructor.
seq=mr.Sequence(system);

%% Sequence events
% Some sequence parameters are defined using standard MATLAB variables
fov=256e-3;
Nx=128; Ny=128; necho=16; Nslices=1;
rflip=180;
if (numel(rflip)==1), rflip=rflip+zeros([1 necho]); end
sliceThickness=5e-3;
TE=12e-3; TR=2000e-3;
TEeff=60e-3;
k0=round(TEeff/TE);
PEtype='linear';

samplingTime= 6.4e-3;
readoutTime = samplingTime + 2*system.adcDeadTime;
tEx=2.5e-3;
tExwd=tEx+system.rfRingdownTime+system.rfDeadTime;
tRef=2e-3;
tRefwd=tRef+system.rfRingdownTime+system.rfDeadTime;
tSp=0.5*(TE-readoutTime-tRefwd);
tSpex=0.5*(TE-tExwd-tRefwd);
fspR=1.0;
fspS=0.5;

rfex_phase=pi/2; % MZ: we need to maintain these as variables because we will overwrtite phase offsets for multiple slice positions
rfref_phase=0;

%%
%%% Base gradients
%%% Slice selection
% Key concepts in the sequence description are *blocks* and *events*.
% Blocks describe a group of events that are executed simultaneously. This
% hierarchical structure means that one event can be used in multiple
% blocks, a common occurrence in MR sequences, particularly in imaging
% sequences.
%
% First, the slice selective RF pulses (and corresponding slice gradient)
% are generated using the |makeSincPulse| function.
% Gradients are recalculated such that their flattime covers the pulse plus
% the rfdead- and rfringdown- times.
%
flipex=90*pi/180;
[rfex, gz] = mr.makeSincPulse(flipex,system,'Duration',tEx,...
    'SliceThickness',sliceThickness,'apodization',0.5,'timeBwProduct',4,'PhaseOffset',rfex_phase);
GSex = mr.makeTrapezoid('z',system,'amplitude',gz.amplitude,'FlatTime',tExwd,'riseTime',dG);
% plotPulse(rfex,GSex);

flipref=rflip(1)*pi/180;
[rfref, gz] = mr.makeSincPulse(flipref,system,'Duration',tRef,...
    'SliceThickness',sliceThickness,'apodization',0.5,'timeBwProduct',4,'PhaseOffset',rfref_phase,'use','refocusing');
GSref = mr.makeTrapezoid('z',system,'amplitude',GSex.amplitude,'FlatTime',tRefwd,'riseTime',dG);
% plotPulse(rfref,GSref);

AGSex=GSex.area/2;
GSspr = mr.makeTrapezoid('z',system,'area',AGSex*(1+fspS),'duration',tSp,'riseTime',dG);
GSspex = mr.makeTrapezoid('z',system,'area',AGSex*fspS,'duration',tSpex,'riseTime',dG);

%%
%%% Readout gradient
% To define the remaining encoding gradients we need to calculate the
% $k$-space sampling. The Fourier relationship
%
% $$\Delta k = \frac{1}{FOV}$$
%
% Therefore the area of the readout gradient is $n\Delta k$.
deltak=1/fov;
kWidth = Nx*deltak;

GRacq = mr.makeTrapezoid('x',system,'FlatArea',kWidth,'FlatTime',readoutTime,'riseTime',dG);
adc = mr.makeAdc(Nx,'Duration',samplingTime, 'Delay', system.adcDeadTime);%,'Delay',GRacq.riseTime);
GRspr = mr.makeTrapezoid('x',system,'area',GRacq.area*fspR,'duration',tSp,'riseTime',dG);
GRspex = mr.makeTrapezoid('x',system,'area',GRacq.area*(1+fspR),'duration',tSpex,'riseTime',dG);

AGRspr=GRspr.area;%GRacq.area/2*fspR;
AGRpreph = GRacq.area/2+AGRspr;%GRacq.area*(1+fspR)/2;
GRpreph = mr.makeTrapezoid('x',system,'Area',AGRpreph,'duration',tSpex,'riseTime',dG);

%%
%%% Phase encoding
% To move the $k$-space trajectory away from 0 prior to the readout a
% prephasing gradient must be used. Furthermore rephasing of the slice
% select gradient is required.

%[PEorder,Ny] = myTSE_PEorder(Ny,necho,k0,PEtype);
nex=floor(Ny/necho);
pe_steps=(1:(necho*nex))-0.5*necho*nex-1;
if 0==mod(necho,2)
    pe_steps=circshift(pe_steps,[0,-round(nex/2)]); % for odd number of echoes we have to apply a shift to avoid a contrast jump at k=0
end
PEorder=reshape(pe_steps,[nex,necho])';
phaseAreas = PEorder*deltak;

%% split gradients and recombine into blocks
% lets start with slice selection....
GS1times=[0 GSex.riseTime];
GS1amp=[0 GSex.amplitude];
GS1 = mr.makeExtendedTrapezoid('z','times',GS1times,'amplitudes',GS1amp);

GS2times=[0 GSex.flatTime];
GS2amp=[GSex.amplitude GSex.amplitude];
GS2 = mr.makeExtendedTrapezoid('z','times',GS2times,'amplitudes',GS2amp);

GS3times=[0 GSspex.riseTime GSspex.riseTime+GSspex.flatTime GSspex.riseTime+GSspex.flatTime+GSspex.fallTime];
GS3amp=[GSex.amplitude GSspex.amplitude GSspex.amplitude GSref.amplitude];
GS3 = mr.makeExtendedTrapezoid('z','times',GS3times,'amplitudes',GS3amp);

GS4times=[0 GSref.flatTime];
GS4amp=[GSref.amplitude GSref.amplitude];
GS4 = mr.makeExtendedTrapezoid('z','times',GS4times,'amplitudes',GS4amp);

GS5times=[0 GSspr.riseTime GSspr.riseTime+GSspr.flatTime GSspr.riseTime+GSspr.flatTime+GSspr.fallTime];
GS5amp=[GSref.amplitude GSspr.amplitude GSspr.amplitude 0];
GS5 = mr.makeExtendedTrapezoid('z','times',GS5times,'amplitudes',GS5amp);

GS7times=[0 GSspr.riseTime GSspr.riseTime+GSspr.flatTime GSspr.riseTime+GSspr.flatTime+GSspr.fallTime];
GS7amp=[0 GSspr.amplitude GSspr.amplitude GSref.amplitude];
GS7 = mr.makeExtendedTrapezoid('z','times',GS7times,'amplitudes',GS7amp);

% and now the readout gradient....

GR3=GRpreph;%GRspex;

GR5times=[0 GRspr.riseTime GRspr.riseTime+GRspr.flatTime GRspr.riseTime+GRspr.flatTime+GRspr.fallTime];
GR5amp=[0 GRspr.amplitude GRspr.amplitude GRacq.amplitude];
GR5 = mr.makeExtendedTrapezoid('x','times',GR5times,'amplitudes',GR5amp);

GR6times=[0 readoutTime];
GR6amp=[GRacq.amplitude GRacq.amplitude];
GR6 = mr.makeExtendedTrapezoid('x','times',GR6times,'amplitudes',GR6amp);

GR7times=[0 GRspr.riseTime GRspr.riseTime+GRspr.flatTime GRspr.riseTime+GRspr.flatTime+GRspr.fallTime];
GR7amp=[GRacq.amplitude GRspr.amplitude GRspr.amplitude 0];
GR7 = mr.makeExtendedTrapezoid('x','times',GR7times,'amplitudes',GR7amp);

% and filltimes
%tex=GS1.t(end)+GS2.t(end)+GS3.t(end);
%tref=GS4.t(end)+GS5.t(end)+GS7.t(end)+readoutTime;
%tend=GS4.t(end)+GS5.t(end);
tex=mr.calcDuration(GS1)+mr.calcDuration(GS2)+mr.calcDuration(GS3);
tref=mr.calcDuration(GS4)+mr.calcDuration(GS5)+mr.calcDuration(GS7)+readoutTime;
tend=mr.calcDuration(GS4)+mr.calcDuration(GS5);

tETrain=tex+necho*tref+tend;
TRfill=(TR-Nslices*tETrain)/Nslices;
% round to gradient raster
TRfill=system.gradRasterTime * round(TRfill / system.gradRasterTime);
if TRfill<0, TRfill=1e-3;
    disp(strcat('Warning!!! TR too short, adapted to include all slices to : ',num2str(1000*Nslices*(tETrain+TRfill)),' ms'));
else
    disp(strcat('TRfill : ',num2str(1000*TRfill),' ms'));
end
delayTR = mr.makeDelay(TRfill);

%% Define sequence blocks
% Next, the blocks are put together to form the sequence
for kex=0:nex % MZ: we start at 0 to have one dummy
    for s=1:Nslices
        rfex.freqOffset=GSex.amplitude*sliceThickness*(s-1-(Nslices-1)/2);
        rfref.freqOffset=GSref.amplitude*sliceThickness*(s-1-(Nslices-1)/2);
        rfex.phaseOffset=rfex_phase-2*pi*rfex.freqOffset*mr.calcRfCenter(rfex); % align the phase for off-center slices
        rfref.phaseOffset=rfref_phase-2*pi*rfref.freqOffset*mr.calcRfCenter(rfref); % dito

        seq.addBlock(GS1);
        seq.addBlock(GS2,rfex);
        seq.addBlock(GS3,GR3);
        %GS4.first=GS4f;
        %GS4.first=GS3.last;
        for kech=1:necho,
            if (kex>0)
                phaseArea=phaseAreas(kech,kex);
            else
                phaseArea=0;
            end
            GPpre = mr.makeTrapezoid('y',system,'Area',phaseArea,'Duration',tSp,'riseTime',dG);
            GPrew = mr.makeTrapezoid('y',system,'Area',-phaseArea,'Duration',tSp,'riseTime',dG);
            seq.addBlock(GS4,rfref);
            seq.addBlock(GS5,GR5,GPpre);
            if (kex>0)
                seq.addBlock(GR6,adc);
            else
                seq.addBlock(GR6);
            end
            seq.addBlock(GS7,GR7,GPrew);
            %GS4.first=GS7.last;
        end
        seq.addBlock(GS4);
        seq.addBlock(GS5);
        seq.addBlock(delayTR);
    end
end

%% check whether the timing of the sequence is correct
[ok, error_report]=seq.checkTiming;

if (ok)
    fprintf('Timing check passed successfully\n');
else
    fprintf('Timing check failed! Error listing follows:\n');
    fprintf([error_report{:}]);
    fprintf('\n');
end

%% k-space trajectory calculation
[ktraj_adc, t_adc, ktraj, t_ktraj, t_excitation, t_refocusing] = seq.calculateKspacePP();

% plot k-spaces
figure; plot(t_ktraj,ktraj'); title('k-space components as functions of time'); % plot the entire k-space trajectory
figure; plot(ktraj(1,:),ktraj(2,:),'b',...
             ktraj_adc(1,:),ktraj_adc(2,:),'r.'); % a 2D plot
axis('equal'); % enforce aspect ratio for the correct trajectory display
title('2D k-space');

%% Write to file

% The sequence is written to file in compressed form according to the file
% format specification using the |write| method.
seq.write('tse.seq')

%%
% Display the first few lines of the output file
% s=fileread('myTSE.seq');
% disp(s(1:300))
seq.plot();

% seq.install('siemens');


% fir_filterdcpadded() - Pad data with DC constant and filter
%
% Usage:
%   >> data = fir_filterdcpadded(b, a, data, causal);
%
% Inputs:
%   b             - vector of filter coefficients
%   a             - 1
%   data          - raw data (times x chans)
%   causal        - boolean perform causal filtering {default 0}
%   usefftfilt    - boolean use fftfilt instead of filter
%
% Outputs:
%   data      - smoothed data
%
% Note:
%   firfiltdcpadded always operates (pads, filters) along first dimension.
%   Not memory optimized.
%
% Author: Andreas Widmann, University of Leipzig, 2014

%123456789012345678901234567890123456789012345678901234567890123456789012

% Copyright (C) 2013 Andreas Widmann, University of Leipzig, widmann@uni-leipzig.de
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
%
% $Id$

function [ data ] = fir_filterdcpadded(b, a, data, causal, usefftfilt)

% Defaults
if nargin <= 4 || isempty(usefftfilt)
  usefftfilt = 0;
end
if nargin <= 3 || isempty(causal)
  causal = 0;
end

% Check arguments
if nargin < 3
  ft_error('Not enough input arguments.');
end

% Is FIR?
if ~isscalar(a) || a ~= 1
  ft_error('Not a FIR filter. onepass-zerophase and onepass-minphase filtering is available for FIR filters only.')
end

% Group delay
if mod(length(b), 2) ~= 1
  ft_error('Filter order must be a real, even, positive integer.');
end
groupDelay = (length(b) - 1) / 2;

if causal == 0
  % Filter symmetry, add a check with some numeric tolerance, needed if the
  % filter coefficients are computed using the compat functions
  isSym     = all(b(1:groupDelay)  ==  b(end:-1:groupDelay + 2));
  isAntisym = all([b(1:groupDelay) == -b(end:-1:groupDelay + 2) b(groupDelay + 1) == 0]);

  % the filter should be either symmetric or antisymmetric: the check above
  % requires exact numeric anti-/symmetry. The compat drop in replacements
  % have some numeric inaccuracies, close to eps, so we might be a bit
  % lenient here
  if ~isSym && isalmostequal(b(1:groupDelay), b(end:-1:groupDelay + 2), 'abstol', eps*10)
    ft_warning('Filter coefficients are nearly symmetric, making them explicitly symmetric');
    bold = b;
    b(1:groupDelay)          = ( bold(1:groupDelay) + bold(end:-1:groupDelay + 2) )./2;
    b(end:-1:groupDelay + 2) = ( bold(1:groupDelay) + bold(end:-1:groupDelay + 2) )./2;
  end
  isSym     = all(b(1:groupDelay)  ==  b(end:-1:groupDelay + 2));

  if ~isAntisym && isalmostequal(b(1:groupDelay), -b(end:-1:groupDelay + 2), 'abstol', eps*10) && isalmostequal(b(groupDelay + 1), 0, 'abstol', eps*10)
    ft_warning('Filter coefficients are nearly antisymmetric, making them explicitly antisymmetric');
    bold = b;
    b(1:groupDelay)          =  ( bold(1:groupDelay) - bold(end:-1:groupDelay + 2) )./2;
    b(end:-1:groupDelay + 2) = -( bold(1:groupDelay) - bold(end:-1:groupDelay + 2) )./2;
  end
  isAntisym = all([b(1:groupDelay) == -b(end:-1:groupDelay + 2) b(groupDelay + 1) == 0]);

  if ~(isSym || isAntisym)
    ft_error('Filter is not anti-/symmetric. For onepass-zerophase filtering the filter must be anti-/symmetric.')
  end
end

% Padding
if causal
  startPad = repmat(data(1, :), [2 * groupDelay 1]);
  endPad = [];
else
  startPad = repmat(data(1, :), [groupDelay 1]);
  endPad = repmat(data(end, :), [groupDelay 1]);
end

% Filter data (with double precision)
isSingle = isa(data, 'single');

if usefftfilt
  data = fftfilt(double(b), double([startPad; data; endPad]));
else
  data = filter(double(b), 1, double([startPad; data; endPad])); % Pad and filter with double precision
end

% Convert to single
if isSingle
  data = single(data);
end

% Remove padded data
data = data(2 * groupDelay + 1:end, :);

end


function [] = isotopomerViewer(mdv1, mdv2, names)
% Takes in an "experiment" and views the isotopomer as distributions
% between `mdv1` and `mdv2`. No output.
%
% USAGE:
%
%    isotopomerViewer(mdv1, mdv2, names)
%
% INPUTS:
%    mdv1, mdv2:    structures
%    names:         names in the plot

bins = round(sqrt(size(mdv1,2)));

for i = 1:size(mdv1,1)
    subplot(4,4,mod(i-1,16)+1);
    [x1,x2]=hist(mdv1(i,:), bins);
    plot(x2,x1);
    if max(x2) < .02
        plot(x2,x1, 'k');
    end
    hold on;
    [x1,x2]=hist(mdv2(i,:), bins);
    plot(x2,x1, 'g');
    if max(x2) < .02
        plot(x2,x1, 'k');
    end
    title(names{i});
    hold off;
    if mod(i,16) == 0
        pause;
    end
end


function [DCM] = spm_dcm_erp_results(DCM,Action,fig)
% Results for ERP Dynamic Causal Modeling (DCM)
% FORMAT spm_dcm_erp_results(DCM,'ERPs (mode)');
% FORMAT spm_dcm_erp_results(DCM,'ERPs (sources)');
% FORMAT spm_dcm_erp_results(DCM,'Coupling (A)');
% FORMAT spm_dcm_erp_results(DCM,'Coupling (B)');
% FORMAT spm_dcm_erp_results(DCM,'Coupling (C)');
% FORMAT spm_dcm_erp_results(DCM,'trial-specific effects');
% FORMAT spm_dcm_erp_results(DCM,'Input');
% FORMAT spm_dcm_erp_results(DCM,'Response');
% FORMAT spm_dcm_erp_results(DCM,'Response (image)');
% FORMAT spm_dcm_erp_results(DCM,'Scalp maps');
% FORMAT spm_dcm_erp_results(DCM,'Data');
%
%__________________________________________________________________________
%
% DCM is a causal modelling procedure for dynamical systems in which
% causality is inherent in the differential equations that specify the model.
% The basic idea is to treat the system of interest, in this case the brain,
% as an input-state-output system.  By perturbing the system with known
% inputs, measured responses are used to estimate various parameters that
% govern the evolution of brain states.  Although there are no restrictions
% on the parameterisation of the model, a bilinear approximation affords a
% simple re-parameterisation in terms of effective connectivity.  This
% effective connectivity can be latent or intrinsic or, through bilinear
% terms, model input-dependent changes in effective connectivity.  Parameter
% estimation proceeds using fairly standard approaches to system
% identification that rest upon Bayesian inference.
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_dcm_erp_results.m 6644 2015-12-12 14:53:37Z karl $

% get Action if necessary
%--------------------------------------------------------------------------
if nargin < 2

    str{1}  = 'ERPs (mode)';
    str{2}  = 'ERPs (sources)';
    str{3}  = 'Coupling (A)';
    str{4}  = 'Coupling (B)';
    str{5}  = 'Coupling (C)';
    str{6}  = 'trial-specific effects';
    str{7}  = 'Input';
    str{8}  = 'Response';
    str{9}  = 'Response (image)';
    str{10} = 'Scalp maps';
    str{11} = 'Data';

    s       = listdlg('PromptString','Select an option:',...
        'SelectionMode','single',...
        'ListString',str);

    Action = str{s};

end

% get figure
%--------------------------------------------------------------------------
if nargin < 3, spm_figure('GetWin','Graphics'); end
colormap(gray)
clf

% trial data
%--------------------------------------------------------------------------
xY  = DCM.xY;                   % data
nt  = length(xY.y);             % Nr trial types
ne  = size(xY.y{1},2);          % Nr electrodes
nb  = size(xY.y{1},1);          % Nr time bins
t   = xY.pst;                   % PST

% plot data
%--------------------------------------------------------------------------
switch(lower(Action))
    case{lower('Data')}
        try
            A = [0 0];
            for i = 1:nt

                % confounds if specified
                %----------------------------------------------------------
                try
                    X0 = spm_orth(xY.X0(1:nb,:),'norm');
                    R  = speye(nb,nb) - X0*X0';
                catch
                    R  = speye(nb,nb);
                end

                % plot data
                %----------------------------------------------------------
                subplot(nt,2,(i - 1)*2 + 1)
                plot(t,R*xY.y{i})
                xlabel('time (ms)')
                try
                    title(sprintf('Observed response (code:%i)',xY.code(i)))
                catch
                    title(sprintf('Observed response %i',i))
                end
                axis square
                a    = axis;
                A(1) = min(A(1),a(3));
                A(2) = max(A(2),a(4));

                % image data
                %----------------------------------------------------------
                subplot(nt,2,(i - 1)*2 + 2)
                imagesc([1:ne],t,R*xY.y{i})
                xlabel('channels');ylabel('peri-stimulus time (ms)')
                axis square
                try
                    title(sprintf('Observed response (code:%i)',xY.code(i)))
                catch
                    title(sprintf('Observed response %i',i))
                end
            end

            % set axis
            %--------------------------------------------------------------
            for i = 1:nt
                subplot(nt,2,(i - 1)*2 + 1)
                set(gca,'YLim',A)
            end
        end
        return
end

% post inversion parameters
%--------------------------------------------------------------------------
nu  = length(DCM.B);          % Nr inputs
nc  = size(DCM.H{1},2);       % Nr modes
ns  = size(DCM.A{1},1);       % Nr of sources
np  = size(DCM.K{1},2)/ns;    % Nr of population per source

% switch
%--------------------------------------------------------------------------
switch(lower(Action))

    case{lower('ERPs (mode)')}

        % spm_dcm_erp_results(DCM,'ERPs (mode)');
        %------------------------------------------------------------------
        co = {'b', 'r', 'g', 'm', 'y', 'k'};
        lo = {'-', '--'}; A = [0 0];

        for i = 1:nc
            subplot(ceil(nc/2),2,i), hold on
            str   = {};
            for j = 1:nt
                plot(t,DCM.H{j}(:,i), lo{1},...
                    'Color', co{j},...
                    'LineWidth',2);
                str{end + 1} = sprintf('trial %i (predicted)',j);
                plot(t,DCM.H{j}(:,i) + DCM.R{j}(:,i), lo{2},...
                    'Color',co{j});
                str{end + 1} = sprintf('trial %i (observed)',j);
                set(gca, 'XLim', [t(1) t(end)]);

            end
            hold off
            title(sprintf('mode %i',i))
            grid on
            axis square
            a    = axis;
            A(1) = min(A(1),a(3));
            A(2) = max(A(2),a(4));
        end
        xlabel('time (ms)')
        legend(str)

        % set axis
        %------------------------------------------------------------------
        for i = 1:nc
            subplot(ceil(nc/2),2,i)
            set(gca,'YLim',A)
        end

    case{lower('ERPs (sources)')}

        % spm_dcm_erp_results(DCM,'ERPs (sources)');
        %------------------------------------------------------------------
        col   = {'b','r','g','m','y','c'}; A = [0 0];
        sty   = {':','-.','-','--','-'};
        for i = 1:ns
            str   = {};
            subplot(ceil(ns/2),2,i), hold on

            % if J maps from states to sources, use J (a matrix)
            %--------------------------------------------------------------
            if strcmpi(DCM.options.model,'DEM')

                for j = find(DCM.Eg.J(i,:))
                    for k = 1:nt
                        plot(t, DCM.K{k}(:,j) , ...
                            'Color',col{k}, ...
                            'LineWidth',1);
                        str{end + 1} = sprintf('trial %i (pop. %i)',k,j);
                    end
                end

            else

                % otherwise assume normal form for states (source x states)
                %----------------------------------------------------------
                for j = 1:np
                    for k = 1:nt

                            plot(t, DCM.K{k}(:,i + ns*(j - 1)), ...
                                'Color',col{k}, ...
                                'LineStyle',sty{j}, ...
                                'LineWidth',2);

                        str{end + 1} = sprintf('trial %i (pop. %i)',k,j);
                    end
                end
            end

            hold off
            title(DCM.Sname{i},'FontSize',16)
            grid on
            axis square
            a    = axis;
            A(1) = min(A(1),a(3));
            A(2) = max(A(2),a(4));
        end
        xlabel('time (ms)','FontSize',14)
        legend(str)

        % set axis
        %------------------------------------------------------------------
        for i = 1:ns
            subplot(ceil(ns/2),2,i)
            axis([t(1) t(end) A(1) A(2)]);

            % or
            %--------------------------------------------------------------
            spm_axis tight

        end

    case{lower('Coupling (A)')}

        % spm_dcm_erp_results(DCM,'coupling (A)');
        %------------------------------------------------------------------
        if ~isfield(DCM.Ep,'A'), return, end
        n    = length(DCM.Ep.A);
        if n == 2
            str = {'Forward','Backward'};
        elseif n == 3
            str = {'Forward','Backward','Lateral'};
        else
            str = {'Forward (i)','Forward (ii)','Backward (i)','Backward (ii)'};
        end

        for i = 1:n

            % images
            %--------------------------------------------------------------
            subplot(4,n,i)
            imagesc(exp(DCM.Ep.A{i}))
            title(str{i},'FontSize',10)
            set(gca,'YTick',[1:ns],'YTickLabel',DCM.Sname,'FontSize',8)
            set(gca,'XTick',[])
            xlabel('from','FontSize',8)
            ylabel('to','FontSize',8)
            axis square

            % table
            %--------------------------------------------------------------
            subplot(4,n,i + n)
            text(0,1/2,num2str(full(exp(DCM.Ep.A{i})),' %.2f'),'FontSize',8)
            axis off,axis square

            % PPM
            %--------------------------------------------------------------
            subplot(4,n,i + n + n)
            image(64*DCM.Pp.A{i})
            set(gca,'YTick',[1:ns],'YTickLabel',DCM.Sname,'FontSize',8)
            set(gca,'XTick',[])
            title('PPM')
            axis square

            % table
            %--------------------------------------------------------------
            subplot(4,n,i + n + n + n)
            text(0,1/2,num2str(DCM.Pp.A{i},' %.2f'),'FontSize',8)
            axis off, axis square

        end

    case{lower('Coupling (C)')}

        % spm_dcm_erp_results(DCM,'coupling (C)');
        %------------------------------------------------------------------
        if ~isfield(DCM.Ep,'C'), return, end

        % images
        %------------------------------------------------------------------
        subplot(2,4,1)
        imagesc(exp(DCM.Ep.C))
        title('Factors','FontSize',10)
        set(gca,'XTick',[1:nu],'XTickLabel','Input','FontSize',8)
        set(gca,'YTick',[1:ns],'YTickLabel',DCM.Sname, 'FontSize',8)
        axis square

        % PPM
        %------------------------------------------------------------------
        subplot(2,4,3)
        image(64*DCM.Pp.C)
        title('Factors','FontSize',10)
        set(gca,'XTick',[1:nu],'XTickLabel','Input','FontSize',8)
        set(gca,'YTick',[1:ns],'YTickLabel',DCM.Sname, 'FontSize',8)
        axis square
        title('PPM')

        % table
        %------------------------------------------------------------------
        subplot(2,4,2)
        text(0,1/2,num2str(full(exp(DCM.Ep.C)),' %.2f'),'FontSize',8)
        axis off

        % table
        %------------------------------------------------------------------
        subplot(2,4,4)
        text(0,1/2,num2str(DCM.Pp.C,' %.2f'),'FontSize',8)
        axis off

    case{lower('Coupling (B)')}

        % spm_dcm_erp_results(DCM,'coupling (B)');
        %------------------------------------------------------------------
        if ~isfield(DCM.Ep,'B'), return, end
        if  isfield(DCM.Ep,'N')
            if any(spm_vec(DCM.Ep.N))
                xU.name = [DCM.xU.name DCM.xU.name];
                Ep.B    = [DCM.Ep.B DCM.Ep.N];
                Pp.B    = [DCM.Pp.B DCM.Pp.N];
            else
                xU.name = DCM.xU.name;
                Ep.B    = DCM.Ep.B;
                Pp.B    = DCM.Pp.B;
            end
        else
            xU.name = DCM.xU.name;
            Ep.B    = DCM.Ep.B;
            Pp.B    = DCM.Pp.B;
        end

        nb    = length(Ep.B);
        for i = 1:nb

            % images
            %--------------------------------------------------------------
            subplot(4,nb,i)
            imagesc(exp(Ep.B{i}))
            title(xU.name{i},'FontSize',10)
            set(gca,'YTick',1:ns,'YTickLabel',DCM.Sname,'FontSize',8)
            set(gca,'XTick',[])
            xlabel('from','FontSize',8)
            ylabel('to','FontSize',8)
            axis square

            % tables
            %--------------------------------------------------------------
            subplot(4,nb,i + nb)
            text(0,1/2,num2str(full(exp(Ep.B{i})),' %.2f'),'FontSize',8)
            axis off
            axis square

            % PPM
            %--------------------------------------------------------------
            subplot(4,nb,i + 2*nb)
            image(64*Pp.B{i})
            set(gca,'YTick',[1:ns],'YTickLabel',DCM.Sname,'FontSize',8)
            set(gca,'XTick',[])
            title('PPM')
            axis square

            % tables
            %--------------------------------------------------------------
            subplot(4,nb,i + 3*nb)
            text(0,1/2,num2str(Pp.B{i},' %.2f'),'FontSize',8)
            axis off
            axis square

        end

    case{lower('trial-specific effects')}

        % spm_dcm_erp_results(DCM,'trial-specific effects');
        %------------------------------------------------------------------
        if ~any(isfield(DCM.Ep,{'B','N'})), return, end

        for i = 1:ns
            for j = 1:ns

                % ensure connection is enabled
                %----------------------------------------------------------
                q     = 0;
                for k = 1:nu
                    try, q = q | DCM.Ep.B{k}(i,j); end
                    try, q = q | DCM.Ep.N{k}(i,j); end
                end

                % plot trial-specific effects
                %----------------------------------------------------------
                if q
                    D     = zeros(nt,0);
                    B     = zeros(nt,1);
                    N     = zeros(nt,1);
                    for k = 1:nu
                        try, B = B + DCM.xU.X(:,k)*DCM.Ep.B{k}(i,j); end
                        try, N = N + DCM.xU.X(:,k)*DCM.Ep.N{k}(i,j); end
                    end

                    if any(B(:)), D = B;     end
                    if any(N(:)), D = [D N]; end

                    subplot(ns,ns,(i - 1)*ns + j)
                    bar(exp(D)*100)
                    title([DCM.Sname{j}, ' to ' DCM.Sname{i}],'FontSize',10)
                    xlabel('trial',  'FontSize',8)
                    ylabel('strength (%)','FontSize',8)
                    set(gca,'XLim',[0 nt + 1])
                end
            end
        end

    case{lower('Input')}

        % plot data
        % -----------------------------------------------------------------
        tU    = t - t(1);
        U     = spm_erp_u(tU/1000,DCM.Ep,DCM.M);

        subplot(2,1,1)
        plot(t,U)
        xlabel('time (ms)')
        title('input')
        axis square, grid on
        for i = 1:length(DCM.M.ons)
            str{i} = sprintf('input (%i)',i);
        end
        legend(str)

    case{lower('Response')}

        % get spatial projector
        % -----------------------------------------------------------------
        try
            U = DCM.M.U';
        catch
            U = 1;
        end

        % plot data
        % -----------------------------------------------------------------
        try
            A     = [];
            for i = 1:nt
                subplot(nt,2,2*i - 1)
                plot(t,(DCM.H{i} + DCM.R{i})*U)
                xlabel('time (ms)')
                try
                    title(sprintf('Observed (adjusted-code:%i)',xY.code(i)))
                catch
                    title(sprintf('Observed (adjusted) %i',i))
                end
                A(end + 1,:) = axis;

                subplot(nt,2,2*i - 0)
                plot(t,DCM.H{i}*U)
                xlabel('channels')
                ylabel('time (ms)')
                title('Predicted')
                A(end + 1,:) = axis;
            end
            a(1)  = min(A(:,1));
            a(2)  = max(A(:,2));
            a(3)  = min(A(:,3));
            a(4)  = max(A(:,4));
            for i = 1:nt
                subplot(nt,2,2*i - 1)
                axis(a); axis square, grid on
                subplot(nt,2,2*i - 0)
                axis(a); axis square, grid on
            end

        end

    case{lower('Response (image)')}

        % get spatial projector
        % -----------------------------------------------------------------
        try
            U = DCM.M.U';
        catch
            U = 1;
        end

        % plot data
        % -----------------------------------------------------------------
        try
            for i = 1:nt
                subplot(nt,2,2*i - 1)
                imagesc([1:ne],t,(DCM.H{i} + DCM.R{i})*U)
                xlabel('channels')
                ylabel('time (ms)')
                try
                    title(sprintf('Observed (adjusted-code:%i)',xY.code(i)))
                catch
                    title(sprintf('Observed (adjusted) %i',i))
                end
                axis square, grid on, A = axis;

                subplot(nt,2,2*i - 0)
                imagesc(1:ne,t,DCM.H{i}*U)
                xlabel('channels')
                ylabel('time (ms)')
                title('Predicted')
                axis(A); axis square, grid on
            end
        end

    case{lower('Scalp maps')}

        % get spatial projector
        % -----------------------------------------------------------------
        try
            U = DCM.M.U';
        catch
            U = 1;
        end

        try
            pos = DCM.xY.coor2D;
        catch
            [xy, label]  = spm_eeg_project3D(DCM.M.dipfit.sens, DCM.xY.modality);
            [sel1, sel2] = spm_match_str(DCM.xY.name, label);
            pos = xy(:, sel2);
        end

        ns = 5; %number of time frames

        in           = [];
        in.type      = DCM.xY.modality;
        in.f         = gcf;
        in.noButtons = 1;
        in.cbar      = 0;
        in.plotpos   = 0;

        % plot data
        % -----------------------------------------------------------------

        for i = 1:nt
            Yo  = (DCM.H{i} + DCM.R{i})*U;
            Yp  = DCM.H{i}*U;

            for j = 1:ns
                ind    = ((j-1)*floor(nb/ns)+1):j*floor(nb/ns);

                in.max = max(abs(mean(Yo(ind, :))));
                in.min = -in.max;

                in.ParentAxes = subplot(nt*2,ns,(i - 1)*2*ns + j);
                spm_eeg_plotScalpData(mean(Yo(ind, :))', pos , DCM.xY.name, in);
                title(sprintf('observed\n%s\n%.0f ms', DCM.xY.code{i}, mean(t(ind))));

                in.ParentAxes = subplot(nt*2,ns,(i - 1)*2*ns + ns + j);
                spm_eeg_plotScalpData(mean(Yp(ind, :))', pos, DCM.xY.name, in);
                title(sprintf('predicted\n%s\n%.0f ms', DCM.xY.code{i}, mean(t(ind))));
            end
        end

    case{lower('Dipoles')}

        % return if LFP
        % -----------------------------------------------------------------
        if strcmpi(DCM.xY.modality,'lfp')
            warndlg('There are no ECDs for these LFP data')
            return
        end

        % plot dipoles
        % -----------------------------------------------------------------
        switch DCM.options.spatial

            case{'ECD'}
                P            = DCM.Eg;
                P.L          = spm_cat(P.L);
                np           = size(P.L,2)/size(P.Lpos,2);
                sdip.n_seeds = 1;
                sdip.n_dip   = np*ns;
                sdip.Mtb     = 1;
                sdip.j{1}    = full(P.L);
                sdip.j{1}    = sdip.j{1}./repmat(sqrt(sum(sdip.j{1}.^2)), 3, 1);
                sdip.j{1}    = sdip.j{1}(:);
                sdip.loc{1}  = kron(ones(1,np),full(P.Lpos));
                spm_eeg_inv_ecd_DrawDip('Init', sdip)

            case{'LFP'}
                warndlg('This is a LFP spatial model')

            case{'IMG'}
                warndlg('use the render API button to see reconstruction')

            otherwise
                return
        end

end


function [ap, ph2] = phmap(score,label,labelvalue)
hd2_ind=find(score<=2);
if isempty(hd2_ind)
    ph2=0;
else
    ph2=sum(label(hd2_ind)==labelvalue)/length(hd2_ind);
end
ap = apcal(score,label,labelvalue);


% Functions specific for simulating scenarios.
%
% 3D objects (with edges information)
%   obj2pnts           - Get points matrix from 3D object.
%   obj2segs           - Get segments matrix from 3D object.
%
% 3D patches (objects without edges information)
%   camGraphics        - Create a camera graphics 3D object.
%   camSimpleGraphics  - Create a simple camera graphics 3D object.
%   swing              - Create a graphics structure with a wing shape.
%   thickVehicle       - Create a vehicle graphics 3D object.
%   wing               - Create a wing graphics 3D object.
%
% 3D points (3-by-N matrices)
%   obj2pnts           - Get points matrix from 3D object.
%   cloister           - Generates features in a 2D cloister shape.
%   thickCloister      - Generates features in a 3D cloister shape.
%
% 3D segments (6-by-N matrices)
%   obj2segs           - Get segments matrix from 3D object.
%   makeSegment        - Make a segment out of two endpoints
%   xSegment           - Horizontal segment in the X direction
%   ySegment           - Horizontal segment in the Y direction
%   zSegment           - Vertical segment
%   XYRectangle        - Rectangle in the XY plane.
%   XZRectangle        - Rectangle in the XZ plane.
%   YZRectangle        - Rectangle in the YZ plane.
%   house              - House made out of segments.
%
% Work with pre-processed data
%   readControlSignal  - Read robot-s control signal from file.
%   readProcessedImg   - Read processed image data from file.
%   writeControlSignal - Write robot's control signal to file.
%   writeProcessedImg  - Write processed image data to file.


classdef Slice < dagnn.ElementWise
  properties
    dim = 3
    slicePoint = 3
  end

  properties (Transient)
    inputSizes = {}
  end

  methods
    function outputs = forward(obj, inputs, params)
      outputs = vl_nnslice(inputs{1}, obj.dim, obj.slicePoint, []) ;
      obj.inputSizes = cellfun(@size, inputs, 'UniformOutput', false) ;
    end

    function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
      derInputs = vl_nnslice(inputs, obj.dim, obj.slicePoint, ...
                            derOutputs, 'inputSizes', obj.inputSizes) ;
      derParams = {} ;
    end

    function reset(obj)
      obj.inputSizes = {} ;
    end

    function outputSizes = getOutputSizes(obj, inputSizes)
      sz = inputSizes{1} ;
      for k = 2:numel(inputSizes)
        sz(obj.dim) = sz(obj.dim) + inputSizes{k}(obj.dim) ;
      end
      outputSizes{1} = sz ;
    end

    function rfs = getReceptiveFields(obj)
      numInputs = numel(obj.net.layers(obj.layerIndex).inputs) ;
      if obj.dim == 3 || obj.dim == 4
        rfs = getReceptiveFields@dagnn.ElementWise(obj) ;
        rfs = repmat(rfs, numInputs, 1) ;
      else
        for i = 1:numInputs
          rfs(i,1).size = [NaN NaN] ;
          rfs(i,1).stride = [NaN NaN] ;
          rfs(i,1).offset = [NaN NaN] ;
        end
      end
    end

    function load(obj, varargin)
      s = dagnn.Layer.argsToStruct(varargin{:}) ;
      % backward file compatibility
      if isfield(s, 'numInputs'), s = rmfield(s, 'numInputs') ; end
      load@dagnn.Layer(obj, s) ;
    end

    function obj = Slice(varargin)
      obj.load(varargin{:}) ;
    end
  end
end


function varargout = gammainc(varargin)

if nargin ~= 2
    error('Not enough input arguments in gammainc.');
end

if isa(varargin{1},'sdpvar') && isa(varargin{2},'sdpvar')
    error('Only one argument in gammainc(X,A) can be an SDPVAR');
end

switch class(varargin{1})
    case 'double'

        if varargin{1} < 0
            error('X must be real and non-negative in gammainc(X,A)')
        end
        varargout{1} = InstantiateElementWise('gammainc_a',varargin{2:-1:1});

    case 'sdpvar'

        if varargin{2}<0
            error('A must be real and non-negative gammainc(X,A)');
        end
        varargout{1} = InstantiateElementWise('gammainc_x',varargin{:});

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


% von Bertalanffy 1.1 : a COBRA toolbox extension to thermodynamically constrain a metabolic model
% Ronan M. T. Fleming
% Science Institute and Center for Systems Biology, University of Iceland, Reykjavik.
% Ines Thiele
% Center for Systems Biology and Faculty of Industrial Engineering, Mechanical Engineering and
% Computer Science, University of Iceland, Reykjavik
%
%INSTALLATION
initVonBertalanffy
%TESTING
testSetupThermoModel
%PDF DOCUMENTATION
%
%Theory:
%R.M.T. Fleming†, I. Thiele, H.P. Nasheuer. Quantitative assignment of reaction directionality in
%constraint-based models of metabolism: Application to Escherichia coli.
%Biophysical Chemistry, 145, 47-56, 2009.
%
%Code:
%von Bertalanffy 1.0 : a COBRA toolbox extension to thermodynamically constrain a metabolic model
%(submitted)
%
%HTML DOCUMENTATION
%open YOURPATH/vonBertalanffy/doc/index.html in browser.
%
%html documentation can be renerated using m2html by running
%initVonBertalanffy.m if no doc folder is present
%http://www.artefact.tk/software/matlab/m2html/


% function PairwiseMaskScreen(hfig,fMaskList_matchZ,fMask_matchZ_ZList);

% FC{i_fish,i_reg} = [];
% FC{i_fish,i_reg}.cIX = cIX;
% FC{i_fish,i_reg}.gIX = gIX;
% FC{i_fish,i_reg}.xyz = xyz;
% FC{i_fish,i_reg}.xyz_avr = xyz_avr;
% FC{i_fish,i_reg}.xyz_norm = xyz_norm;
% FC{i_fish,i_reg}.xyz_norm_avr = xyz_norm_avr;

%% Part 1: from zMasks.

range_fish = 1:18;
numFish = length(range_fish);

% screen ALL pairs within these candidate fMasks
% [instead of "for each zMask, find nodes"]

% for ref fish
%   load fMask_ref range;
%   for each ref mask
%     set fMask_ref;
%     for test fish,
%         load fMask_test range;
%         for each test mask,
%             load fMask_test;
%             compute perc overlap for this pair,pool;
% end;end;end;end

% treat ZBrain masks similarly to a ref fish

for i_fishnum = 1:numFish,% cycle through each fish as reference fish

    % choose reference fish
    i_fish_ref = range_fish(i_fishnum);

    % load fMask_ref range
    name = ['fMASKs_',num2str(i_fish),'.mat'];
    load(fullfile(data_masterdir,'fMASKs',name),'fMASKs');
    nfMasks = size(fMASKs.MaskDatabase,2);

end

%%
% function PairwiseClusterScreen
range_fish = 2:4;
numFish = length(range_fish);
%% Batch pre-load
numReg = 1;
i_reg = 1;
M_clus = cell(numFish,numReg);
for i_fish = range_fish,
    [cIX,gIX,M_xyz_norm] = GetDefaultClustersFromLoad(hfig,i_fish);
    M_clus{i_fish,i_reg} = [];
%     M_clus{i_fish,i_reg}.cIX = cIX;
    M_clus{i_fish,i_reg}.gIX = gIX;
    M_clus{i_fish,i_reg}.M_xyz_norm = M_xyz_norm;
end

%% screen ALL pairs (non-directional) between ALL fish
% init
TF_fishrange = cell(1,numFish);
Pairs_AllClusAllFish = []; % each row: {[fish#1, clusID1]}, {[fish#2, clusID2]}

% cycle through each fish as reference fish
for i_refnum = 1:numFish,
    i_fish_ref = range_fish(i_refnum);
    disp(['i_fish_ref = ' num2str(i_fish_ref)]);
    gIX_ref = M_clus{i_fish_ref,i_reg}.gIX;
    M_xyz_norm_ref = M_clus{i_fish_ref,i_reg}.M_xyz_norm;

    % init
    U_ref = unique(gIX_ref);
    numClus_ref = length(U_ref);
    TF_reffish = zeros(numClus_ref,numFish-1);

    % cycle through clusters in reference fish
    for i_clus_ref = 1:numClus_ref,
        if mod(i_clus_ref,10)==0,
            disp(['i_clus_ref = ' num2str(i_clus_ref)]);
        end
        clusID_ref = U_ref(i_clus_ref);
        IX = find(gIX_ref == clusID_ref);
        XYZ_ref = M_xyz_norm_ref(IX,:);

        % cycle through test fish for given ref fish
        for i_testnum = (i_refnum+1):numFish,% only do ordered pairwise test (other half redundant)
            i_fish_test = range_fish(i_testnum);
            gIX_test = M_clus{i_fish_test,i_reg}.gIX;
            M_xyz_norm_test = M_clus{i_fish_test,i_reg}.M_xyz_norm;

            U_test = unique(gIX_test);
            numClus_test = length(U_test);
            scores_test = zeros(numClus_test,1);

            % cycle through clusters in test fish
            for i_clus_test = 1:numClus_test,
                clusID_test = U_test(i_clus_test);
                IX = find(gIX_test == clusID_test);
                XYZ_test = M_xyz_norm_test(IX,:);

                % compute distance score
                scores_test(i_clus_test,1) = ClusterDistanceTestD12(XYZ_ref,XYZ_test);
            end

            % save qualifying pairs for this test fish
            IX_pass = find(scores_test);
            TF_reffish(i_clus_ref,i_testnum) = length(IX_pass);
            if ~isempty(IX_pass),
                clusID_test_pass = U_test(IX_pass);
                for i = 1:length(clusID_test_pass),
                    Pairs_AllClusAllFish = [Pairs_AllClusAllFish; ...
                        {[i_fish_ref, clusID_ref]}, {[i_fish_test, clusID_test_pass(i)]}]; %#ok<AGROW>
                end
            end
        end
    end
    TF_fishrange{i_refnum} = TF_reffish;
end

github-repos/MATLAB/xiuyechen-FishExplorer/FishExplorer-c61392cf0835480d64fc03c15f1992935fdc7106/unused analyses/conserved cluster screens/obsl mask screen/PairwiseMaskScreen.m


%     NeuroSLAM System Copyright (C) 2018-2019
%     NeuroSLAM: A Brain inspired SLAM System for 3D Environments
%
%     Fangwen Yu (www.yufangwen.com), Jianga Shang, Youjian Hu, Michael Milford(www.michaelmilford.com)
%
%     The NeuroSLAM V1.0 (MATLAB) was developed based on the OpenRatSLAM (David et al. 2013).
%     The RatSLAM V0.3 (MATLAB) developed by David Ball, Michael Milford and Gordon Wyeth in 2008.
%
%     Reference:
%     Ball, David, Scott Heath, Janet Wiles, Gordon Wyeth, Peter Corke, and Michael Milford.
%     "OpenRatSLAM: an open source brain-based SLAM system." Autonomous Robots 34, no. 3 (2013): 149-176.
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.

clear workspace

visual_odo_initial( ...
    'ODO_IMG_TRANS_Y_RANGE', 1:270, ...
    'ODO_IMG_TRANS_X_RANGE', 1:480, ...
    'ODO_IMG_HEIGHT_V_Y_RANGE', 1:270, ...
    'ODO_IMG_HEIGHT_V_X_RANGE', 1:480, ...
    'ODO_IMG_YAW_ROT_Y_RANGE', 1:270, ...
    'ODO_IMG_YAW_ROT_X_RANGE', 1:480, ...
    'ODO_IMG_TRANS_RESIZE_RANGE', [130, 240], ...
    'ODO_IMG_YAW_ROT_RESIZE_RANGE', [130, 240], ...
    'ODO_IMG_HEIGHT_V_RESIZE_RANGE', [130, 240], ...
    'ODO_TRANS_V_SCALE', 30, ...
    'ODO_YAW_ROT_V_SCALE', 1, ...
    'ODO_HEIGHT_V_SCALE', 5, ...
    'MAX_TRANS_V_THRESHOLD', 0.4, ...
    'MAX_YAW_ROT_V_THRESHOLD', 4.2, ...
    'MAX_HEIGHT_V_THRESHOLD', 0.4, ...
    'ODO_SHIFT_MATCH_HORI', 30, ...
    'ODO_SHIFT_MATCH_VERT', 30, ...
    'FOV_HORI_DEGREE', 75, ...
    'FOV_VERT_DEGREE', 20, ...
    'KEY_POINT_SET', [3750, 4700, 8193, 9210], ...
    'ODO_STEP', 5);

% vt initial
vt_image_initial('*.png', ...
    'VT_MATCH_THRESHOLD', 3.4, ...
    'VT_IMG_CROP_Y_RANGE', 1:270, ...
    'VT_IMG_CROP_X_RANGE', 1:480, ...
    'VT_IMG_RESIZE_X_RANGE', 48, ...
    'VT_IMG_RESIZE_Y_RANGE', 27, ...
    'VT_IMG_X_SHIFT', 5, ...
    'VT_IMG_Y_SHIFT', 3, ...
    'VT_GLOBAL_DECAY', 0.5, ...
    'VT_ACTIVE_DECAY', 0.5, ...
    'PATCH_SIZE_Y_K', 5, ...
    'PATCH_SIZE_X_K', 5, ...
    'VT_PANORAMIC', 0, ...
    'VT_STEP', 1);

% yaw_height_hdc initial
yaw_height_hdc_initial( ...
    'YAW_HEIGHT_HDC_Y_DIM', 36, ...
    'YAW_HEIGHT_HDC_H_DIM', 36, ...
    'YAW_HEIGHT_HDC_EXCIT_Y_DIM', 8, ...
    'YAW_HEIGHT_HDC_EXCIT_H_DIM', 8, ...
    'YAW_HEIGHT_HDC_INHIB_Y_DIM', 5, ...
    'YAW_HEIGHT_HDC_INHIB_H_DIM', 5, ...
    'YAW_HEIGHT_HDC_EXCIT_Y_VAR', 1.9, ...
    'YAW_HEIGHT_HDC_EXCIT_H_VAR', 1.9, ...
    'YAW_HEIGHT_HDC_INHIB_Y_VAR', 3.1, ...
    'YAW_HEIGHT_HDC_INHIB_H_VAR', 3.1, ...
    'YAW_HEIGHT_HDC_GLOBAL_INHIB', 0.0002, ...
    'YAW_HEIGHT_HDC_VT_INJECT_ENERGY', 0.1, ...
    'YAW_ROT_V_SCALE', 1, ...
    'HEIGHT_V_SCALE', 1, ...
    'YAW_HEIGHT_HDC_PACKET_SIZE', 5);

% 3d gc initial
gc_initial( ...
    'GC_X_DIM', 36, ...
    'GC_Y_DIM', 36, ...
    'GC_Z_DIM', 36, ...
    'GC_EXCIT_X_DIM', 7, ...
    'GC_EXCIT_Y_DIM', 7, ...
    'GC_EXCIT_Z_DIM', 7, ...
    'GC_INHIB_X_DIM', 5, ...
    'GC_INHIB_Y_DIM', 5, ...
    'GC_INHIB_Z_DIM', 5, ...
    'GC_EXCIT_X_VAR', 1.5, ...
    'GC_EXCIT_Y_VAR', 1.5, ...
    'GC_EXCIT_Z_VAR', 1.5, ...
    'GC_INHIB_X_VAR', 2, ...
    'GC_INHIB_Y_VAR', 2, ...
    'GC_INHIB_Z_VAR', 2, ...
    'GC_GLOBAL_INHIB', 0.0002, ...
    'GC_VT_INJECT_ENERGY', 0.1, ...
    'GC_HORI_TRANS_V_SCALE', 1, ...
    'GC_VERT_TRANS_V_SCALE', 1, ...
    'GC_PACKET_SIZE', 4);

% 3d em initial 1/2/5/
exp_initial( ...
    'DELTA_EXP_GC_HDC_THRESHOLD', 30, ...
    'EXP_LOOPS', 5, ...
    'EXP_CORRECTION', 0.5 );

% main process
% file path: visualDataFile, expMapHistoryFile, odoMapHistoryFile, groundTruthFile,vtHistoryFile, emHistoryFile, varargin

imageFolderPath = 'C:\NeuroSLAM_Datasets\01_NeuroSLAM_Datasets\03_QUTCarparkData';
SynPerDataFile = fullfile (imageFolderPath, '');

gtDataFolderPath = '';
gtDataFile = fullfile(gtDataFolderPath, '');

experiDataPath = 'C:\NeuroSLAM_Datasets\03_NeuroSLAM_Experiments_Results\QUTCarparData';
expMapFile  = fullfile(experiDataPath, '01_exp_map_ml.txt');
odoMapFile  = fullfile(experiDataPath, '02_odo_map_ml.txt');
emHisFile   = fullfile(experiDataPath, '03_em_history_ml.txt');
vtHisFile   = fullfile(experiDataPath, '04_vt_history_ml.txt');
gcTrajFile  = fullfile(experiDataPath, '05_gc_trajectory.txt');
hdcTrajFile = fullfile(experiDataPath, '06_hdc_trajectory.txt');

main(SynPerDataFile, ...
    gtDataFile, ...
    expMapFile, ...
    odoMapFile, ...
    emHisFile, ...
    vtHisFile, ...
    gcTrajFile, ...
    hdcTrajFile, ...
    'BLOCK_READ', 50, ...
    'RENDER_RATE', 2, ...
    'GT_ODO_X_SCALING', 20, ...
    'GT_ODO_Y_SCALING', 20, ...
    'GT_ODO_Z_SCALING', 20, ...
    'GT_EXP_X_SCALING', 20, ...
    'GT_EXP_Y_SCALING', 20, ...
    'GT_EXP_Z_SCALING', 20, ...
    'ODO_MAP_X_SCALING', -0.8, ...
    'ODO_MAP_Y_SCALING', 0.8, ...
    'ODO_MAP_Z_SCALING', 0.1, ...
    'EXP_MAP_X_SCALING', 0.8, ...
    'EXP_MAP_Y_SCALING', 0.8, ...
    'EXP_MAP_Z_SCALING', 0.1);


function tess_transform( SurfaceFiles, transf )
% TESS_TRANSFORM: Apply a transformation (rotation + translation) to a set of surfaces.
%
% USAGE:  tess_transform( SurfaceFiles, transf )
%
% DESCRIPTION:
%     The transformation structure should contain at least 2 fields: transf.R and transf.T
%     They are the rotation and the translation that will be applied to the coordinates
%     of the vertices of each of the surfaces listed in SurfaceFiles.
%
% INPUT:
%     - SurfaceFiles   : cell array of strings, full path to all the surfaces files to process
%     - Transformation : structure, rotation (.R) + translation (.T) to apply

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2009

% Parse inputs
if ischar(SurfaceFiles)
    SurfaceFiles = {SurfaceFiles};
end
% Process all the files
for iFile = 1:length(SurfaceFiles)
    % If relative path name, add the protocol path
    if ~file_exist(SurfaceFiles{iFile})
        SurfaceFiles{iFile} = file_fullpath(SurfaceFiles{iFile});
    end
    % Load vertices
    SurfaceMat = in_tess_bst(SurfaceFiles{iFile});
    % Apply transform
    SurfaceMat.Vertices = ([transf.R, transf.T] * [SurfaceMat.Vertices'; ones(1,size(SurfaceMat.Vertices,1))])';
    % Update comment
    SurfaceMat.Comment = [SurfaceMat.Comment, '_SCS'];
    % History: Apply rotation + translation
    SurfaceMat = bst_history('add', SurfaceMat, 'transform', sprintf('Rotation: [%1.3f,%1.3f,%1.3f; %1.3f,%1.3f,%1.3f; %1.3f,%1.3f,%1.3f]', transf.R'));
    SurfaceMat = bst_history('add', SurfaceMat, 'transform', sprintf('Translation: [%1.3f,%1.3f,%1.3f]', transf.T));
    % Save new vertices positions
    bst_save(SurfaceFiles{iFile}, SurfaceMat, 'v7');
    % Unload surface file
    bst_memory('UnloadSurface', SurfaceFiles{iFile});
end


function [Iwhite,lilI,lilmask] = maskCropper(I,mask)
%function [Iwhite,lilI,lilmask] = maskCropper(I,mask)
%Given an Image and a Binary Segmentation Mask create a small icon
%showing only the image content inside the segment
%Iwhite is the resulting icon with background colored white
%lilI is the rectangular subimage defined by extent of mask
%lilmask is the small mask
%Tomasz Malisiewicz (tomasz@cmu.edu)

sss = [size(I,1) size(I,2)];

[uu,vv] = find(mask);
minu = min(uu);
maxu = max(uu);
minv = min(vv);
maxv = max(vv);

lilmask = mask(minu:maxu,minv:maxv);
I = I(minu:maxu,minv:maxv,:);

Iwhite = (I.*repmat(lilmask,[1 1 3])) + repmat(~lilmask,[1 1 3]);
lilI = I;


function conv_layer_idx = get_conv_layer_idx_from_layer_idx(layer_idx)
    global config;
    c = 0;
    for m = 1:layer_idx
        if strfind(config.forward_pass_scheme{m}, 'conv')
            c = c + 1;
        end
    end
    conv_layer_idx = c;
end


function G = rayxgridfZ(F, transla, val)
%------------------------------------------------------------------------------
% Multiplies gridfunction F with element of stencil given by its value
% val and its position transla.
% Excess area is filled by padding with zeroes.
%
% Design and implementation by:
% Dr. Paul M. de Zeeuw <Paul.de.Zeeuw@cwi.nl>  http://homepages.cwi.nl/~pauldz/
% Last Revision: June 23, 2000.
% (c) 1999-2002 Stichting CWI, Amsterdam.
%------------------------------------------------------------------------------
o=[0 0];
if ~all(size(o) == size(transla))
  error(' rayxgridfZ - unexpected dimensions of transla ')
end
G = val * moveLRZ(moveUDZ(F, -transla(1)), -transla(2));
%------------------------------------------------------------------------------


function [thrs,cntR,sumR,cntP,sumP,V] = edgesEvalImg( E, G, varargin )
% Calculate edge precision/recall results for single edge image.
%
% Enhanced replacement for evaluation_bdry_image() from BSDS500 code:
%  http://www.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/
% Uses same format and is fully compatible with evaluation_bdry_image.
% Given default prms results are *identical* to evaluation_bdry_image.
%
% In addition to performing the evaluation, this function can optionally
% create a visualization of the matches and errors for a given edge result.
% The visualization of edge matches V has the following color coding:
%  green=true positive, blue=false positive, red=false negative
% If multiple ground truth labels are given the false negatives have
% varying strength (and true positives can match *any* ground truth).
%
% This function calls the mex file correspondPixels. Pre-compiled binaries
% for some systems are provided in /private, source for correspondPixels is
% available as part of the BSDS500 dataset (see link above). Note:
% correspondPixels is computationally expensive and very slow in practice.
%
% USAGE
%  [thrs,cntR,sumR,cntP,sumP,V] = edgesEvalImg( E, G, [prms] )
%
% INPUTS
%  E          - [h x w] edge probability map (may be a filename)
%  G          - file containing a cell of ground truth boundaries
%  prms       - parameters (struct or name/value pairs)
%   .out        - [''] optional output file for writing results
%   .thrs       - [99] number or vector of thresholds for evaluation
%   .maxDist    - [.0075] maximum tolerance for edge match
%   .thin       - [1] if true thin boundary maps
%
% OUTPUTS
%  thrs       - [Kx1] vector of threshold values
%  cntR,sumR  - [Kx1] ratios give recall per threshold
%  cntP,sumP  - [Kx1] ratios give precision per threshold
%  V          - [hxwx3xK] visualization of edge matches
%
% EXAMPLE
%
% See also edgesEvalDir
%
% Structured Edge Detection Toolbox      Version 3.01
% Code written by Piotr Dollar, 2014.
% Licensed under the MSR-LA Full Rights License [see license.txt]

% get additional parameters
dfs={ 'out','', 'thrs',99, 'maxDist',.0075, 'thin',1 };
[out,thrs,maxDist,thin] = getPrmDflt(varargin,dfs,1);
if(any(mod(thrs,1)>0)), K=length(thrs); thrs=thrs(:); else
  K=thrs; thrs=linspace(1/(K+1),1-1/(K+1),K)'; end

% load edges (E) and ground truth (G)
if(all(ischar(E))), E=double(imread(E))/255; end
G=load(G); G=G.groundTruth; n=length(G);
for g=1:n, G{g}=double(G{g}.Boundaries); end

% evaluate edge result at each threshold
Z=zeros(K,1); cntR=Z; sumR=Z; cntP=Z; sumP=Z;
if(nargout>=6), V=zeros([size(E) 3 K]); end
for k = 1:K
  % threshhold and thin E
  E1 = double(E>=max(eps,thrs(k)));
  if(thin), E1=double(bwmorph(E1,'thin',inf)); end
  % compare to each ground truth in turn and accumualte
  Z=zeros(size(E)); matchE=Z; matchG=Z; allG=Z;
  for g = 1:n
    [matchE1,matchG1] = correspondPixels(E1,G{g},maxDist);
    matchE = matchE | matchE1>0;
    matchG = matchG + double(matchG1>0);
    allG = allG + G{g};
  end
  % compute recall (summed over each gt image)
  cntR(k) = sum(matchG(:)); sumR(k) = sum(allG(:));
  % compute precision (edges can match any gt image)
  cntP(k) = nnz(matchE); sumP(k) = nnz(E1);
  % optinally create visualization of matches
  if(nargout<6), continue; end; cs=[1 0 0; 0 .7 0; .7 .8 1]; cs=cs-1;
  FP=E1-matchE; TP=matchE; FN=(allG-matchG)/n;
  for g=1:3, V(:,:,g,k)=max(0,1+FN*cs(1,g)+TP*cs(2,g)+FP*cs(3,g)); end
  V(:,2:end,:,k) = min(V(:,2:end,:,k),V(:,1:end-1,:,k));
  V(2:end,:,:,k) = min(V(2:end,:,:,k),V(1:end-1,:,:,k));
end

% if output file specified write results to disk
if(isempty(out)), return; end; fid=fopen(out,'w'); assert(fid~=1);
fprintf(fid,'%10g %10g %10g %10g %10g\n',[thrs cntR sumR cntP sumP]');
fclose(fid);

end


function [varargout] = splitGradientAt(grad, timepoint, varargin)
%SplitGradient Splits a trapezoidal gradient into two extended trapezoids
%(currently shaped gradients) defined by the cut line.
%
%   [grads] = splitGradient(grad)
%   Returns the two gradient parts by cutting the original 'grad' at the
%   'timepoint' . For the input type 'trapezoid' the results are trtyurned
%   as extended trapezoids, for 'arb' as arbitrary gradient objects. The
%    delays in the individual gradient events are adapted such that
%   addGradients(...) produces an gradient equivalent to 'grad'.
%
%   See also  splitGradient makeExtendedTrapezoid makeTrapezoid
%             Sequence.addBlock  mr.opts
%
%   Maxim Zaitsev <maxim.zaitsev@uniklinik-freiburg.de>
%   Stefan Kroboth <stefan.kroboth@uniklinik-freiburg.de>

persistent parser

if isempty(parser)
    parser = inputParser;
    parser.FunctionName = 'splitGradientAt';
	parser.addRequired('grad', @isstruct);
    parser.addRequired('timepoint', @isnumeric);
    parser.addOptional('system', mr.opts(), @isstruct);
end
parse(parser, grad, timepoint, varargin{:});
opt = parser.Results;

gradRasterTime = opt.system.gradRasterTime;

% round the time point to the gradient raster;
timeindex = round(timepoint / gradRasterTime);
timepoint = timeindex * gradRasterTime;
timeindex = timeindex + 1; % convert to Matlab convention

ch = grad.channel;

if strcmp(grad.type, 'grad')
    % check if we have an arbitrary gradient or an exended trapezoid
    if abs(grad.tt(1)-0.5*gradRasterTime)<1e-10 && ...
       all(abs(grad.tt(2:end)-grad.tt(1:end-1)-gradRasterTime)<1e-10)
        % arbitrary gradient -- the most trivial conversion
        % if timepoint is out of range we have nothing to do
        if timeindex == 1 || timeindex >= length(grad.tt)
            varargout{1} = grad;
        else
            grad1=grad;
            grad2=grad;
            grad1.last=0.5*(grad.waveform(timeindex-1)+grad.waveform(timeindex)); % FIXME: retrive the double-sampling point (e.g. the corner of the trapezoid)
            grad2.first=grad1.last;
            grad2.delay=grad.delay + timepoint;
            grad1.tt=grad.tt(1:(timeindex-1));
            grad1.waveform=grad.waveform(1:(timeindex-1));
            grad2.tt=grad.tt(timeindex:end) - timepoint;
            grad2.waveform=grad.waveform(timeindex:end);

            if nargout==1
                varargout{1} = [grad1 grad2];
            else
                varargout{1} = grad1;
                varargout{2} = grad2;
            end
        end
        return; % early return
    else
        % we have an extended trapezoid -- excellent choice!
        times      = grad.tt;
        amplitudes = grad.waveform;
    end
elseif strcmp(grad.type, 'trap')
    grad.delay    = round(grad.delay   /gradRasterTime)*gradRasterTime; % MZ: was ceil
    grad.riseTime = round(grad.riseTime/gradRasterTime)*gradRasterTime; % MZ: was ceil
    grad.flatTime = round(grad.flatTime/gradRasterTime)*gradRasterTime; % MZ: was ceil
    grad.fallTime = round(grad.fallTime/gradRasterTime)*gradRasterTime; % MZ: was ceil

    % prepare the extended trapezoid structure
    if grad.flatTime == 0
        times      = [0 grad.riseTime  grad.riseTime+grad.fallTime];
        amplitudes = [0 grad.amplitude 0];
    else
        times      = [0 grad.riseTime  grad.riseTime+grad.flatTime grad.riseTime+grad.flatTime+grad.fallTime];
        amplitudes = [0 grad.amplitude grad.amplitude              0];
    end
else
    error('Splitting of unsupported event.');
end

% if the cutline is behind the gradient there is no second gradient to create
if timepoint >= grad.delay+times(end)
    error('trying to place the splitting time point after the end of the gradient');
end

% now we have everything in the extended trapezoid structure

% if the cutline goes through the delay we need special treatment
if timepoint < grad.delay
    times=[0 grad.delay+times];
    amplitudes = [0 amplitudes];
    grad.delay=0;
else
    timepoint = timepoint - grad.delay;
end

% sample at timepoint
amp_tp=interp1(times, amplitudes, timepoint, 'linear'); % MZ: interp1() is not OK here for the corner situation TODO: fixme! (e.g. by restoring the corners as done in waveforms_and_times())
% split the data
teps=1e-10; % we need this because of the rounding problems
times1 = [ times(times<timepoint-teps) timepoint ];
amplitudes1 = [ amplitudes(times<timepoint-teps) amp_tp ];
times2 = [ timepoint times(times>timepoint+teps) ] - timepoint;
amplitudes2 = [ amp_tp amplitudes(times>timepoint+teps) ];

% recreate gradients
grad1 = mr.makeExtendedTrapezoid(ch, opt.system, 'times', times1,...
                                  'amplitudes', amplitudes1, ...
                                  'skip_check', true);
grad1.delay = grad.delay;
grad2 = mr.makeExtendedTrapezoid(ch, opt.system, 'times', times2,...
                                  'amplitudes', amplitudes2, ...
                                  'skip_check', true);
grad2.delay = timepoint + grad.delay;

%grads = [grad1 grad2];
if nargout==1
    varargout{1} = [grad1 grad2];
else
    varargout{1} = grad1;
    varargout{2} = grad2;
end

end


function img = mrAnatMontage(img, xform, acpcSlices, fname, figHandle)
% montageRgbImg = mrAnatMontage(img, xform, acpcSlices, fname, figHandle)
%
% Quick hack for displaying nice anatomy montages with ac-pc slice
% labels. Must be a volume, but can be an intensity image (will be
% displayed as grayscale) or an [x,y,z,3] rgb volume.
%
% HISTORY:
% 2006.08.08 RFD: wrote it.
%

if(~exist('fname','var')) fname = ''; end
if(~exist('figHandle','var')) figHandle = figure; end

if(size(img,4)==1)
  img = repmat(img,[1,1,1,3]);
end
% reorient so that the eyes point up
img = flipdim(permute(img,[2 1 3 4]),1);
for(ii=1:length(acpcSlices)) slLabel{ii} = sprintf('Z = %d',acpcSlices(ii)); end
[t,r,s] = affineDecompose(xform);
slImg = inv(xform)*[zeros(length(acpcSlices),2) acpcSlices' ones(length(acpcSlices),1)]';
slImg = round(slImg(3,:));
img = makeMontage3(img, slImg, s(1), 0, slLabel,[],figHandle);
if(~isempty(fname)) mrUtilPrintFigure(fname); end

% be kind to those who forget a semicolon:
if(nargout<1) clear img; end
return;


classdef LHSintegrator < handle

    properties (Access = protected)
        mesh
        fun
        quadrature
        quadratureOrder
    end

    methods (Access = public, Static)

        function obj = create(s)
            f = LHSintegratorFactory();
            obj = f.create(s);
        end

    end

    methods (Access = public)

        function obj = LHSintegrator(cParams)
            obj.init(cParams);
            obj.createQuadrature();
        end

    end

    methods (Access = protected)

        function init(obj, cParams)
            obj.fun      = cParams.fun;
            obj.mesh     = cParams.mesh;
            obj.setQuadratureOrder(cParams);
        end

        function setQuadratureOrder(obj, cParams)
            if isfield(cParams, 'quadratureOrder')
                obj.quadratureOrder = cParams.quadratureOrder;
            else
                obj.quadratureOrder = obj.fun.order;
            end
        end

        function createQuadrature(obj)
            quad = Quadrature.set(obj.mesh.type);
            quad.computeQuadrature(obj.quadratureOrder);
            obj.quadrature = quad;
        end

    end

end


% module = factor_module_gp_factorized(N, covfuncs, theta, varargin)

function module = factor_module_gp_factorized(N, covfuncs, theta, varargin)

D = length(covfuncs);

%
% Parse options
%
options = struct('is_pseudo', false(D,1), ...
                 'noise_prior', [], ...
                 'update_hyperparameters', true, ...
                 'maxiter_hyperparameters', 30, ...
                 'init', [], ...
                 'update_schedule', []);
[options, errmsg] = argparse(options, varargin{:});
error(errmsg);

if isempty(options.update_schedule)
  options.update_schedule = {1:D};
end

K_xx = cell(D,1);
K_px = cell(D,1);
K_pp = cell(D,1);

linsolve_K = cell(D,1);

X = zeros(D,N);
CovX = zeros(D,N);
for d=1:D
  if ~options.is_pseudo(d)
    K_xx{d} = covfuncs{d}(theta{d});
  else
    [K_pp{d}, K_px{d}, K_xx{d}] = covfuncs{d}(theta{d});
  end
end
if isfield(options.init, 'X')
  X(:,:) = options.init.X;
else
  % Initialize from the prior
  for d=1:D
    if ~options.is_pseudo(d)
      L = chol(K_xx{d}, 'lower');
      X(d,:) = L * randn(N,1);
    else
      L = chol(K_pp{d}, 'lower');
      Xp = L * randn(length(L),1);
      X(d,:) = K_px{d}' * linsolve_lchol(L, Xp);
    end
  end
end
if isfield(options.init, 'CovX')
  CovX(:,:) = options.init.CovX;
else
  % Initialize with prior
  for d=1:D
    if ~options.is_pseudo(d)
      CovX(d,:) = 0.1*diag(K_xx{d});
    else
      CovX(d,:) = 0.1*K_xx{d};
    end
  end
end
rho = 1;

module.get_struct = @get_struct;
%module.initialize = @initialize;
module.update = @update;
module.rotate = @rotate;
module.rotation_cost = @rotation_cost;

  function S = get_struct()
  % TODO: not ready yet..
  S.module = 'factor_module_gp_factorized';
  S.X = X;
  S.CovX = CovX;
  S.rho = rho;
  S.covfuncs = covfuncs;
  S.theta = theta;
  S.init = options.init;
  S.options = options;
  end

% $$$   function [Z, CovZ, rhoz] = initialize()
% $$$   end

  function [Z, CovZ, rhoz, logrhoz, KL] = update(iter, Y, Obs, W, CovW, ...
                                                 rhow, Tau)

% $$$   whos
% $$$   for d=1:D
% $$$     nonzeros = nnz(K_xx{d}) / numel(K_xx{d});
% $$$     fprintf('Nonzeros in %d=%.3f\n', d, nonzeros);
% $$$   end

  linsolve_K(:) = {[]};

  M = size(Tau,1);

  % Update each component (component-wise factorization)
  KL = 0;
  Tau(~Obs) = 0;

  if any(rhow~=1)
    error('rhow ~= 1 not yet implemented')
  else
    v_W = ones(M,1);
  end

  updateable = options.update_schedule{min(iter,length(options.update_schedule))};

  for d=1:D

    if any(updateable==d)

      % Indeces of the other components
      others = [1:(d-1), (d+1):D];

      %
      % Pre-evaluations
      %

      % TODO: What if there are totally missing rows in Y??
      % Then u will contain zeros..

      if ndims(CovW) == 2 && all(size(CovW)==[D,M])
        Yh = W(others,:)'*X(others,:);
        u = Tau' * (W(d,:).^2+CovW(d,:))';
        z = (Tau.*(Y-Yh))' * W(d,:)';
      else
        % TODO: Optimize this.. Do not use loops..
        %
        % See help from ARD-module..
        %warning('Optimize this..');
        u = zeros(N,1);
        z = zeros(N,1);
        for n=1:N
          obs = Obs(:,n);

          % Is this correct
          covw = reshape(CovW(d,others,obs),[length(others), sum(obs)]);
% $$$           z(n) = (Tau(obs,n).*v_W(obs).*W(d,obs)')' * (Y(obs,n)-W(others,obs)) - ...
% $$$                  (Tau(obs,n)'*covw')*X(others,n);

          z(n) = (Tau(obs,n).*v_W(obs).*W(d,obs)')'*Y(obs,n) - ...
                 (Tau(obs,n)'*covw')*X(others,n);

          varw = vec(CovW(d,d,obs));
          ww = v_W(obs).*(W(d,obs)'.^2) + varw;
          u(n) = vec(Tau(obs,n))' * ww;
        end
      end
      % Remove totally missing observations
      ind_obs = (u~=0);
      z = z(ind_obs);
      u = u(ind_obs);
      % Helpful variables
      invU_z = z./u;
      invU = spdiag(1./u);
      % Noise covariance function
      covfunc_noise = gp_cov_wrap(invU);

      %
      % Update variables
      %

      if ~options.is_pseudo(d)

        % Standard full GP

        % Form the joint covariance function
        covfunc = gp_cov_sum(gp_cov_select(covfuncs{d}, ind_obs), covfunc_noise);

        % Learn the hyperparameters
        if index_selected(iter, options.update_hyperparameters) && ...
              any(d==updateable)
          [theta{d}, logpdf] = gp_learn(invU_z, covfunc, theta{d}, ...
                                        'maxiter', options.maxiter_hyperparameters, ...
                                        'checkgrad', false);
          K_xx{d} = covfuncs{d}(theta{d});
        else
          if isempty(K_xx{d})
            K_xx{d} = covfuncs{d}(theta{d});
          end
          logpdf = gp_loglikelihood(invU_z, covfunc, theta{d});
        end

        % Evaluate the mean and the variance
        y = invU_z;
        K_y = K_xx{d}(ind_obs,ind_obs) + invU;
        K_yf = K_xx{d}(ind_obs,:);
        k_f = diag(K_xx{d});
        [X(d,:),CovX(d,:)] = gp_predict(y, K_y, K_yf, k_f);
% $$$       [X(d,:),CovX(d,:)] = gp_predict(invU_z, K_xx{d}+invU, K_xx{d}, ...
% $$$                                  diag(K_xx{d}));

      else

        % Sparse approximation GP using pseudo inputs

        % Remove totally missing observations
        covfunc = gp_cov_select_pseudo(covfuncs{d}, ind_obs);

        % Learn the hyperparameters
        if index_selected(iter, options.update_hyperparameters)

          [theta{d}, ~, logpdf] = gp_learn_pseudo(invU_z, ...
                                                  covfunc, ...
                                                  theta{d}, ...
                                                  covfunc_noise, ...
                                                  [], ...
                                                  'maxiter', ...
                                                  options.maxiter_hyperparameters, ...
                                                  'checkgrad', false);
          [K_pp{d}, K_px{d}, K_xx{d}] = covfuncs{d}(theta{d});
        else
          logpdf = gp_loglikelihood_pseudo(invU_z, covfunc, theta{d}, ...
                                           covfunc_noise, []);
          if isempty(K_pp{d}) || isempty(K_px{d}) || isempty(K_xx{d})
            [K_pp{d}, K_px{d}, K_xx{d}] = covfuncs{d}(theta{d});
          end
        end

        % Evaluate the mean and the variance
        [X(d,:),CovX(d,:)] = gp_predict_pseudo(invU_z, ...
                                               @(A) bsxfun(@times, u, A), ...
                                               K_px{d}(:,ind_obs), ...
                                               K_pp{d}, ...
                                               K_px{d}, ...
                                               K_xx{d});

      end

      %
      % Compute Kullback-Leibler divergence KL(q(X)||p(X))
      %
      logpdf_bound = gaussian_logpdf(z'*invU_z, ...
                                     z'*X(d,ind_obs)', ...
                                     (X(d,ind_obs).^2+CovX(d,ind_obs))*u, ...
                                     -sum(log(u)), ...
                                     N);

      KL = KL + logpdf_bound - logpdf;
    else

      % Do not update the variable
      if ~options.is_pseudo(d)
        if isempty(K_xx{d})
          K_xx{d} = covfuncs{d}(theta{d});
        end
      else
        if isempty(K_pp{d}) || isempty(K_px{d}) || isempty(K_xx{d})
          [K_pp{d}, K_px{d}, K_xx{d}] = covfuncs{d}(theta{d});
        end
      end

      KL = KL + 0; % ???

    end

  end

  % Update q(rho)
  rho = 1;
  logrho = 0;
  KL_rho = 0;

  KL = KL + KL_rho;

  Z = X;
  CovZ = CovX;
  rhoz = rho.*ones(N,1);
  logrhoz = logrho.*ones(N,1);

  %tsplot(X)

  end

  function [c, dc] = rotation_cost(A, U, S, V)
% $$$   if any(options.is_pseudo)
% $$$     error('Rotation cost not implemented for pseudo inputs yet..');
% $$$   end
  % Cost from <log q(X)>
  c = -N * logdet_diag(S);
  dc = -N * inv(A)'; % FIX THIS
  % Cost from -<log p(X)>
  AX = A*X;
  varAX = A.^2*CovX;
  invdiagK = zeros(D,N);
  invK_XA = zeros(N,D);
  for d = 1:D
    if ~options.is_pseudo(d)
      if isempty(linsolve_K{d})
        linsolve_K{d} = get_linsolve_cov(K_xx{d});
      end
      invdiagK(d,:) = 1./diag(K_xx{d});
      invK_XA(:,d) = linsolve_K{d}(AX(d,:)');
    else
      %error('Pseudo cost not maybe correct..');
      if isempty(linsolve_K{d})
        L = chol(K_pp{d}, 'lower');
        Z = linsolve_tril(L, K_px{d});
        h = K_xx{d} - dot(Z,Z,1)';
        h = h + 1e-6*max(h);
        %H = spdiag(h);
        %Z = L(K_xp{d}*diag(h.^(-0.5)));
        H = spdiag(h);
        %plot(h)
        Lambda = speye(size(L)) + Z*spdiag(1./h)*Z';
        L_Lambda = get_linsolve_cov(Lambda);
        linsolve_K{d} = @(x) (H\x - H\(Z'*L_Lambda(Z*(H\x))));

% $$$         L = get_linsolve_cov(K_pp{d});
% $$$         h = K_xx{d} - diagprod(K_xp{d}, L(K_xp{d}')');
        %H = 1e-6*speye(size(H)); % better conditioning...
        %LL = get_linsolve_cov(K_pp{d}+K_xp{d}'*(H\K_xp{d}));
        %linsolve_K{d} = @(x) (H\x - H\(K_xp{d}*LL(K_xp{d}')*(H\x)));
      end
      invK_XA(:,d) = linsolve_K{d}(AX(d,:)');
      invdiagK(d,:) = 1./K_xx{d};
      %invK_XA(:,d) = AX(d,:)' ./ K_xx{d};
    end
    c = c + 0.5 * rho * (AX(d,:)*invK_XA(:,d));
    c = c + 0.5 * varAX(d,:) * invdiagK(d,:)';
  end
  dc = dc + rho * (invK_XA'*X');
  dc = dc + A .* (invdiagK*CovX');
% $$$   dc = dc + 0.5 * (invdiagK*CovX'*A' + A'*invdiagK*CovX');

  end

  function [Z, CovZ] = rotate(A)
  X = A*X;
  CovX = A.^2*CovX;
  Z = X;
  CovZ = CovX;
  end

end


clc;clear all;close all;
%***********************************************%
% This code runs on the VeRi-776 dataset.
% This code uses post fuse the results of CNN + CN + SIFT.
% We use the mAP and hit-1/5 rate as evaluation
%***********************************************%
%% load query hist and test hist
CNN_featureLen = 431;
CN_featureLen = 5600;
SIFT_featureLen = 10000;
nQuery = 1678;
nTest = 11579;

dist_SIFT = zeros(nTest, nQuery, 'double');
dist_CN = zeros(nTest, nQuery, 'double');
dist_CNN = zeros(nTest, nQuery, 'double');

fidin = fopen('dist_SIFT_776.txt');
for i = 1:nTest
    dist_line = fgetl(fidin);
    dist_line = str2num(dist_line);
    dist_SIFT(i, 1:length(dist_line)) = dist_line;
end
fclose(fidin);
fidin = fopen('dist_CN_776.txt');
for i = 1:nTest
    dist_line = fgetl(fidin);
    dist_line = str2num(dist_line);
    dist_CN(i, 1:length(dist_line)) = dist_line;
end
fclose(fidin);
fidin = fopen('dist_CNN_776.txt');
for i = 1:nTest
    dist_line = fgetl(fidin);
    dist_line = str2num(dist_line);
    dist_CNN(i, 1:length(dist_line)) = dist_line;
end
fclose(fidin);

dist = dist_CNN*0.7 + dist_CN*0.2 + dist_SIFT*0.1;

%% load ground truth index
maxgt = 256;
gt_index =  zeros(nQuery, maxgt);
fidin = fopen('gt_index_776.txt');

for i = 1:nQuery
    gt_index_line = fgetl(fidin);
    gt_line = str2num(gt_index_line);
    for j = 1:size(gt_line, 2)
       gt_index(i, j) = gt_line(j);
    end
end

maxjk = 256;
jk_index = zeros(nQuery, maxjk);
fidin = fopen('jk_index_776.txt');
for i = 1:nQuery
    jk_index_line = fgetl(fidin);
    jk_line = str2num(jk_index_line);
    for j = 1:size(jk_line, 2)
       jk_index(i, j) = jk_line(j);
    end
end
%% search the database and calcuate re-id accuracy
ap = zeros(nQuery, 1); % average precision
CMC = zeros(nQuery, nTest);
r1 = 0; % rank 1 precision with single query
for k = 1:nQuery
    k
    % load groud truth for each query (good and junk)
      good_index = reshape(gt_index(k,:), 1, []);
      good_index = good_index(good_index ~= 0);
      junk_index = reshape(jk_index(k,:), 1, []);
      junk_index = junk_index(junk_index ~= 0);
    tic
    %score = dist(:, k);
    %score = dist_null(:, k);
    score = dist_LOMO(:, k);
    [~, index] = sort(score, 'ascend');  % single query
    [ap(k), CMC(k, :)] = compute_AP(good_index, junk_index, index);% compute AP for single query

end
CMC = mean(CMC);
%% print result
fprintf('single query:  mAP = %f,	r1 precision = %f,	r5 precision = %f\r\n', mean(ap), CMC(1), CMC(5));
%% plot CMC curves
figure;
s = 50;
CMC_curve = CMC;
plot(1:s, CMC_curve(:, 1:s));


function s = spmatrix(a)
%SPMATRIX Converts a two-way sparse tensor to sparse matrix.
%
%   SPMATRIX(X) converts a sparse tensor to a sparse matrix. The sparse
%   tensor must be two-dimensional.
%
%   See also SPTENSOR, SPTENSOR/RESHAPE, SPTENMAT
%
%MATLAB Tensor Toolbox.
%Copyright 2015, Sandia Corporation.

% This is the MATLAB Tensor Toolbox by T. Kolda, B. Bader, and others.
% http://www.sandia.gov/~tgkolda/TensorToolbox.
% Copyright (2015) Sandia Corporation. Under the terms of Contract
% DE-AC04-94AL85000, there is a non-exclusive license for use of this
% work by or on behalf of the U.S. Government. Export of this data may
% require a license from the United States Government.
% The full license terms can be found in the file LICENSE.txt

if ndims(a) ~= 2
    error('Sparse tensor must be two dimensional.');
end

if isempty(a.subs)
    s = sparse(a.size(1), a.size(2));
else
    s = sparse(a.subs(:,1), a.subs(:,2), a.vals, a.size(1), a.size(2));
end