classdef NDK
    % NDK works with NDK files can convert it to a ZmapCatalog
    %
    % from : https://www.ldeo.columbia.edu/~gcmt/projects/CMT/catalog/allorder.ndk_explained
    %
    % CMT files for download at: http://www.globalcmt.org/CMTfiles.html
    %
    % CMT reference:
    %   Dziewonski, A. M., T.-A. Chou and J. H. Woodhouse, Determination of earthquake source parameters from waveform data for studies of global and regional seismicity, J. Geophys. Res., 86, 2825-2852, 1981. doi:10.1029/JB086iB04p02825
    %   Ekström, G., M. Nettles, and A. M. Dziewonski, The global CMT project 2004-2010: Centroid-moment tensors for 13,017 earthquakes, Phys. Earth Planet. Inter., 200-201, 1-9, 2012. doi:10.1016/j.pepi.2012.04.002
    properties
        allNDKs table

        % TypeOfSourceInvertedFor is
        %"CMT: 0" - general moment tensor;
        %"CMT: 1" - moment tensor with constraint of zero trace (standard);
        %"CMT: 2" - double-couple source.

        % from line 3 of NDK format : CMT info (2)
        % Centroid_Time is  wrt reference time

        % CentroidDepthType is one of FREE, FIX, BODY

        % from line 4 of NDK format : CMT info (3)
        % ExponentForAllMomentValues most all moment measurements need to be multipleid by exponent
        %Mrr % r is up
        %Mtt % t is south
        %Mpp % p is east
    end
    properties(Constant)
        base_directory = 'https://www.ldeo.columbia.edu/~gcmt/projects/CMT/catalog/';
        % different dates are stored in differing locations.
        filelocations = {... [startdate>=, <enddate],location relative to base.
            datetime([1962 1976], 1, 1), {'PRE1976/deep_1962-1976.ndk','PRE1976/intdep_1962-1976.ndk'};
            datetime([1976 2017], 1, 1), 'jan76_dec17.ndk';...
            datetime([2017 year(datetime)], 1, 1), 'NEW_MONTHLY/{yyyy}';...
            [datetime(year(datetime), 1, 1), datetime], 'NEW_QUICK/E{yyyymmddHHMM}.ndk'...
            }

    end

    methods
        function obj = NDK(ndktext)
            %
            %
            % parsing based on documentation found at :
            % https://www.ldeo.columbia.edu/~gcmt/projects/CMT/catalog/allorder.ndk_explained

            if nargin==0 || isempty(ndktext)
                return
            end
            if ischar(ndktext) && isvector(ndktext)
                ndktext=splitlines(strip(ndktext));
            end
            obj=obj.fillLine1(strjoin(ndktext(1:5:end),newline));
            obj=obj.fillLine2(strjoin(ndktext(2:5:end),newline));
            obj=obj.fillLine3(strjoin(ndktext(3:5:end),newline));
            obj=obj.fillLine4(strjoin(ndktext(4:5:end),newline));
            obj=obj.fillLine5(strjoin(ndktext(5:5:end),newline));

        end
        function obj = fillLine1(obj,s)
            % make sure reference catalog is not empty, otherwise textscan will choke
            noCat = strfind(s,[newline '    ']);
            s(noCat+1)='-';
            s(noCat+2)='-';
            s(noCat+3)='-';

            % make sure location is not empyt, otherwise textscan will choke
            sidexes = 57:81:numel(s);
            no_location= s(sidexes)==' ';
            s(sidexes(no_location))='-';
            % NDK's exist with 60 seconds. datetime chokes on this. Fix it.
            sidexes = 23:81:numel(s);
            add_a_minute = s(sidexes)=='6';
            s(sidexes(add_a_minute))='0';

            [c,POS]=textscan(s,'%4C %{uuuu/MM/DD}D %{HH:mm:ss.s}D %f %f %f %f %f %24c');
            obj.allNDKs.HypocenterReferenceCatalog=c{1};
            obj.allNDKs.ReferenceEventDateTime =c{2} + timeofday(c{3}) + minutes(add_a_minute(:));
            obj.allNDKs.Latitude = c{4};
            obj.allNDKs.Longitude=c{5};
            obj.allNDKs.Depth=c{6};
            obj.allNDKs.ReportedMagnitudes = [c{7},c{8}];
            obj.allNDKs.GeographicalLocation=categorical(string(c{9}));
        end

        function obj = fillLine2(obj,s)

            c = textscan(s, '%16s B:%d %d %d S:%d %d %d M:%d %d %d CMT:%C %5C:%f');

            % c is now a 1x13 cell, each cell is a field, and contains an array with one item per NDK
            obj.allNDKs.CMTEventName=c{1};
            obj.allNDKs.LPBodyWaves_NumStationsUsed=c{2};
            obj.allNDKs.LPBodyWaves_NumComponentsUsed=c{3};
            obj.allNDKs.LPBodyWaves_ShortestPeriodUsed=c{4};
            obj.allNDKs.IntermedPSurfaceWaves_NumStationsUsed=c{5};
            obj.allNDKs.IntermedPSurfaceWaves__NumComponentsUsed=c{6};
            obj.allNDKs.IntermedPSurfaceWaves_ShortestPeriodUsed=c{7};
            obj.allNDKs.LPMantleWaves_NumStationsUsed=c{8};
            obj.allNDKs.LPMantleWaves__NumComponentsUsed=c{9};
            obj.allNDKs.LPMantleWaves_ShortestPeriodUsed=c{10};
            obj.allNDKs.TypeOfSourceInvertedFor=c{11};
            obj.allNDKs.MomentRateFunctionType=c{12};
            obj.allNDKs.MomentRateFunctionDuration=c{13};
        end

        function obj = fillLine3(obj,s)

            [c, POS] = textscan(s, 'CENTROID: %f %f %f %f %f %f %f %f %C %c-%14c');
            obj.allNDKs.Centroid_Time =c{1};% wrt reference time
            obj.allNDKs.Centroid_TimeStderr = c{2};
            obj.allNDKs.Centroid_Lat = c{3};
            obj.allNDKs.Centroid_LatStderr = c{4};
            obj.allNDKs.Centroid_Lon = c{5};
            obj.allNDKs.Centroid_LonStderr = c{6};
            obj.allNDKs.Centroid_Depth = c{7};
            obj.allNDKs.Centroid_DepthStderr = c{8};
            obj.allNDKs.CentroidDepthType = c{9}; % one of FREE, FIX, BODY
            obj.allNDKs.TimeStampPrefix = c{10};
            obj.allNDKs.TimeStamp = c{11};
        end

        %from line 3 of NDK format : CMT info (2)

        function obj = fillLine4(obj,s)

            [c, POS] = textscan(s, '%d %f %f %f %f %f %f %f %f %f %f %f %f');
            % from line 4 of NDK format : CMT info (3)
            obj.allNDKs.ExponentForAllMomentValues=c{1};
            obj.allNDKs.Mrr=c{2}; % r is up
            obj.allNDKs.MrrStderr=c{3};
            obj.allNDKs.Mtt=c{4}; % t is south
            obj.allNDKs.MttStderr=c{5};
            obj.allNDKs.Mpp=c{6}; % p is east
            obj.allNDKs.MppStderr=c{7};
            obj.allNDKs.Mrt=c{8};
            obj.allNDKs.MrtStderr=c{9};
            obj.allNDKs.Mrp=c{10};
            obj.allNDKs.MrpStderr=c{11};
            obj.allNDKs.Mtp=c{12};
            obj.allNDKs.MtpStderr=c{13};
        end

        function obj = fillLine5(obj,s)
            [c,POS] = textscan(s, '%3C %f %d %d %f %d %d %f %d %d %f %d %d %d %d %d %d');

            obj.allNDKs.VersionCode=c{1};
            obj.allNDKs.MTEigenvalue=[c{2} c{3} c{4}];
            obj.allNDKs.MTPlunge=[c{5} c{6} c{7}];
            obj.allNDKs.MTAzimuth=[c{8} c{9} c{10}];
            obj.allNDKs.ScalarMoment=c{11}; % needs to be multiplied by exponent
            obj.allNDKs.Strike_NodalPlane1=c{12};
            obj.allNDKs.Dip_NodalPlane1=c{13};
            obj.allNDKs.Rake_NodalPlane1=c{14};
            obj.allNDKs.Strike_NodalPlane2=c{15};
            obj.allNDKs.Dip_NodalPlane2=c{16};
            obj.allNDKs.Rake_NodalPlane2=c{17};
        end

        function c = toZmapCatalog(obj)
            c = ZmapCatalog;
            c.Name          = 'ndk';
            c.Longitude     = obj.allNDKs.Longitude;
            c.Latitude      = obj.allNDKs.Latitude;
            c.Depth         = obj.allNDKs.Depth;
            c.Date          = obj.allNDKs.ReferenceEventDateTime;
            c.Magnitude     = obj.allNDKs.ReportedMagnitudes(:,1);
            c.MagnitudeType = repmat(categorical({''}),size(c.Magnitude));
            mt      = obj.allNDKs(:,{'Mrr','Mtt','Mpp','Mrt','Mrp','Mtp'});
            mt{:,:} = mt{:,:}.* 10.^double(obj.allNDKs.ExponentForAllMomentValues);
            mt.Properties.VariableNames = {'mrr', 'mtt', 'mff', 'mrt', 'mrf', 'mtf'};
            mtAddon                 = MomentTensorAddon(mt);
            mtAddon.Dip             = double(obj.allNDKs.Dip_NodalPlane1);
            mtAddon.DipDirection    = mod(double(obj.allNDKs.Strike_NodalPlane1)+ 90, 360 );
            mtAddon.Rake            = double(obj.allNDKs.Rake_NodalPlane1);
            c.setAddon(mtAddon);
        end
    end

    methods(Static)

        function NDKS = read(f)
            tx=fileread(f);
            NDKS = NDK(splitlines(strip(tx)));
        end

        function NDKS = download(varargin)
            p=inputParser();
            p.addRequired('starttime');
            p.addRequired('endtime');
            p.addParameter('minmagnitude',-inf);
            p.addParameter('maxmagnitude',inf);
            p.addParameter('minlatitude',-90);
            p.addParameter('maxlatitude',90);
            p.addParameter('minlongitude',-180);
            p.addParameter('maxlongitude',180);
            p.addParameter('mindepth',inf);
            p.addParameter('maxdepth',inf);
            % TODO finish this

        end
        function tb = getFileLocations(starttime, endtime)
            % unpack theoretical file locations into real ones.
            floc_cells = NDK.filelocations;
            fls = NDK.filelocations{:,1}(1);
            fle = NDK.filelocations{:,1}(2);
            ignoreMe =   starttime > fle || endtime <= fls ;
            floc_cells(ignoreMe,:) = [];
            tb = table('Size', [1,3],...
                'VariableTypes', {'datetime',   'datetime', 'string'},...
                'VariableNames', {'starttime',  'endtime',  'url'});
            % TODO finish this

        end

    end
end


%tstoolbox/mex/range_search
%   Syntax:
%
%     * [count, neighbors] = range_search(pointset, atria, query_points,
%       r)
%     * [count, neighbors] = range_search(pointset, atria, query_indices,
%       r, exclude)
%
%   Input arguments:
%
%     * pointset - a N by D double matrix containing the coordinates of
%       the point set, organized as N points of dimension D
%     * atria - output of (cf. Section )nn_prepare for pointset
%     * query_points - a R by D double matrix containing the coordinates
%       of the query points, organized as R points of dimension D
%     * query_indices - query points are taken out of the pointset,
%       query_indices is a vector of length R which contains the indices
%       of the query points
%     * r - range or search radius (r > 0)
%     * exclude - in case the query points are taken out of the pointset,
%       exclude specifies a range of indices which are omitted from
%       search. For example if the index of the query point is 124 and
%       exclude is set to 3, points with indices 121 to 127 are omitted
%       from search. Using exclude = 0 means: exclude self-matches
%
%   Output arguments:
%
%     * count - a vector of length R contains the number of points within
%       distance r to the corresponding query point
%     * neighbors - a Matlab cell structure of size R by 2 which contains
%       vectors of indices and vectors of distances to the neighbors for
%       each given query point. This output argument can not be stored in
%       a standard Matlab matrix because the number of neighbors within
%       distance r is not the same for all query points. The vectors if
%       indices and distances for one query point have exactly the length
%       that is given in count. The values in the distances vectors are
%       not sorted..
%
% Copyright 1997-2001 DPI Goettingen, License http://www.physik3.gwdg.de/tstool/gpl.txt


function []=anim8_DIC3D_reconstructedPairs_faceMeasure(DIC3DAllPairsResults,faceMeasureString,varargin)
%% function for plotting 3D-DIC results of face measures in STEP3.
% plotting 3D surfaces from camera pairs, animation changing
% with time, and the faces colored according to faceMeasureString
% this function is called in plotMultiDICPairResults
%
% Options:
% anim8_DIC_3D_pairs_faceMeasure(DIC3DAllPairsResults,faceMeasureString)
% anim8_DIC_3D_pairs_faceMeasure(DIC3DAllPairsResults,faceMeasureString,optStruct)
%
% Inputs:
% * DIC3DAllPairsResults
% * faceMeasureString: can be any of the following:
%   'dispMgn','dispX','dispY','dispZ','FaceColors','FaceIsoInd','pairInd'
% * optStruct: optional structure for plotting options which may include any of the following fields:
%   - smoothLogic: logical variable for smoothing (true)/not smoothing (false) the face measure
%   - FaceAlpha: transparacy of the faces (scalar between 0 and 1, where zero is transparent and 1 is opaque)
%   - colorBarLimits: a 2x1 scalar vector for the colobar limits. if not set, it's automatic
%   - dataLimits: a 2x1 scalar vector for the data limits of the face measure. if a face measure is outside these limits, it is set to NaN. if not set no face is set to NaN
%   - colorMap
%   - zDirection: 1 for z up and -1 for z down
%   - lineColor: line color for the mesh. can be for example 'b','k','none',etc...
%   - TitleString=faceMeasureString;

%% Assign plot options
Narg=numel(varargin);
switch Narg
    case 1
        optStruct=varargin{1};
    case 0
        optStruct=struct;
    otherwise
        ('wrong number of input arguments');
end

% complete the struct fields
if ~isfield(optStruct,'smoothLogic')
    optStruct.smoothLogic=0;
end
if ~isfield(optStruct,'dataLimits')
    optStruct.dataLimits=[-inf inf];
end
if ~isfield(optStruct,'zDirection') % 1 or -1
    optStruct.zDirection=1;
end
if ~isfield(optStruct,'lineColor') % 'none' or 'k'
    optStruct.lineColor='none';
end
if ~isfield(optStruct,'TitleString')
    optStruct.TitleString=faceMeasureString;
end
if ~isfield(optStruct,'maxCorrCoeff')
    optStruct.maxCorrCoeff=[];
end

%%
nPairs=numel(DIC3DAllPairsResults);
nFrames=numel(DIC3DAllPairsResults{1}.Points3D);

%% Assign the right face measure into FC
FC=cell(nPairs,nFrames);
switch faceMeasureString

    case {'DispMgn'}
        for ip=1:nPairs
            for it=1:nFrames
                Fnow=DIC3DAllPairsResults{ip}.Faces;
                dispNow=DIC3DAllPairsResults{ip}.Disp.(faceMeasureString){it}; % point measure
                FC{ip,it}=mean(dispNow(Fnow),2); % turn into face measure
                if ~isempty(optStruct.maxCorrCoeff)
                    corrNow=DIC3DAllPairsResults{ip}.FaceCorrComb{it};
                    FC{ip,it}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
                end
            end
        end
        FCmat = cell2mat(FC);
        if ~isfield(optStruct,'colorBarLimits')
            optStruct.colorBarLimits=[0 prctile(FCmat(:),100)];
        end
        colorBarLogic=1;
        if ~isfield(optStruct,'colorMap')
            optStruct.colorMap='parula';
        end
                if ~isfield(optStruct,'FaceAlpha')
            optStruct.FaceAlpha=0.8;
        end
        legendLogic=0;

    case {'DispX'}
        for ip=1:nPairs
            for it=1:nFrames
                Fnow=DIC3DAllPairsResults{ip}.Faces;
                dispNow=DIC3DAllPairsResults{ip}.Disp.DispVec{it}(:,1); % point measure
                FC{ip,it}=mean(dispNow(Fnow),2); % turn into face measure
                if ~isempty(optStruct.maxCorrCoeff)
                    corrNow=DIC3DAllPairsResults{ip}.FaceCorrComb{it};
                    FC{ip,it}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
                end
            end
        end
        FCmat = cell2mat(FC);
        if ~isfield(optStruct,'colorBarLimits')
            optStruct.colorBarLimits=[min(FCmat(:)) max(FCmat(:))];
        end
        colorBarLogic=1;
        if ~isfield(optStruct,'colorMap')
            optStruct.colorMap='parula';
        end
                if ~isfield(optStruct,'FaceAlpha')
            optStruct.FaceAlpha=0.8;
        end
        legendLogic=0;

    case {'DispY'}
        for ip=1:nPairs
            for it=1:nFrames
                Fnow=DIC3DAllPairsResults{ip}.Faces;
                dispNow=DIC3DAllPairsResults{ip}.Disp.DispVec{it}(:,2); % point measure
                FC{ip,it}=mean(dispNow(Fnow),2); % turn into face measure
                if ~isempty(optStruct.maxCorrCoeff)
                    corrNow=DIC3DAllPairsResults{ip}.FaceCorrComb{it};
                    FC{ip,it}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
                end
            end
        end
        FCmat = cell2mat(FC);
        if ~isfield(optStruct,'colorBarLimits')
            optStruct.colorBarLimits=[min(FCmat(:)) max(FCmat(:))];
        end
        colorBarLogic=1;
        if ~isfield(optStruct,'colorMap')
            optStruct.colorMap='parula';
        end
                if ~isfield(optStruct,'FaceAlpha')
            optStruct.FaceAlpha=0.8;
        end
        legendLogic=0;

    case {'DispZ'}
        for ip=1:nPairs
            for it=1:nFrames
                Fnow=DIC3DAllPairsResults{ip}.Faces;
                dispNow=DIC3DAllPairsResults{ip}.Disp.DispVec{it}(:,3); % point measure
                FC{ip,it}=mean(dispNow(Fnow),2); % turn into face measure
                if ~isempty(optStruct.maxCorrCoeff)
                    corrNow=DIC3DAllPairsResults{ip}.FaceCorrComb{it};
                    FC{ip,it}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
                end
            end
        end
        FCmat = cell2mat(FC);
        if ~isfield(optStruct,'colorBarLimits')
            optStruct.colorBarLimits=[min(FCmat(:)) max(FCmat(:))];
        end
        colorBarLogic=1;
        if ~isfield(optStruct,'colorMap')
            optStruct.colorMap='parula';
        end
                if ~isfield(optStruct,'FaceAlpha')
            optStruct.FaceAlpha=0.8;
        end
        legendLogic=0;

    case {'FaceCorrComb'}
        for ip=1:nPairs
            for it=1:nFrames
                FC{ip,it}=DIC3DAllPairsResults{ip}.(faceMeasureString){it};
                if ~isempty(optStruct.maxCorrCoeff)
                    corrNow=DIC3DAllPairsResults{ip}.FaceCorrComb{it};
                    FC{ip,it}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
                end
            end
        end
        FCmat = cell2mat(FC);
        if ~isfield(optStruct,'colorBarLimits')
            optStruct.colorBarLimits=[0 prctile(FCmat(:),100)];
        end
        colorBarLogic=1;
        if ~isfield(optStruct,'colorMap')
            optStruct.colorMap='parula';
        end
                if ~isfield(optStruct,'FaceAlpha')
            optStruct.FaceAlpha=0.8;
        end
        legendLogic=0;

    case {'FaceColors'}
        for ip=1:nPairs
            for it=1:nFrames
                FC{ip,it}=DIC3DAllPairsResults{ip}.(faceMeasureString);
                if ~isempty(optStruct.maxCorrCoeff)
                    corrNow=DIC3DAllPairsResults{ip}.FaceCorrComb{it};
                    FC{ip,it}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
                end
            end
        end
        if ~isfield(optStruct,'colorBarLimits')
            optStruct.colorBarLimits=[0 255];
        end
        colorBarLogic=1;
        if ~isfield(optStruct,'colorMap')
            optStruct.colorMap='gray';
        end
        legendLogic=0;
        if ~isfield(optStruct,'FaceAlpha')
            optStruct.FaceAlpha=1;
        end
    case 'pairInd'
        for ip=1:nPairs
            for it=1:nFrames
                FC{ip,it}=ip;
                if ~isempty(optStruct.maxCorrCoeff)
                    corrNow=DIC3DAllPairsResults{ip}.FaceCorrComb{it};
                    FC{ip,it}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
                end
            end
        end
        if ~isfield(optStruct,'colorBarLimits')
            optStruct.colorBarLimits=[1 nPairs];
        end
        colorBarLogic=0;
        if ~isfield(optStruct,'colorMap')
            optStruct.colorMap='gjet';
        end
                if ~isfield(optStruct,'FaceAlpha')
            optStruct.FaceAlpha=0.8;
        end
        legendLogic=1;
    otherwise
        error('unexpected face measure string. plots not created');

end

%% Plot
DIC_3Djoined_results=join3DreconstructedPairs(DIC3DAllPairsResults);
[xl,yl,zl]=axesLimits(DIC_3Djoined_results.Points3D);

animStruct=struct;

hf=cFigure;
hf.Units='normalized'; hf.OuterPosition=[.05 .05 .9 .9]; hf.Units='pixels';

axisGeom;
ax=gca;
ax.CameraUpVector=[0 0 optStruct.zDirection];
Colors=gjet(nPairs);

colormap(optStruct.colorMap);
if colorBarLogic
    cbh=colorbar;
    caxis(optStruct.colorBarLimits);
end

gtitle(optStruct.TitleString,20);
% axis off
% camlight headlight

it=1;
for ip=1:nPairs
    Fnow=DIC3DAllPairsResults{ip}.Faces;
    Pnow=DIC3DAllPairsResults{ip}.Points3D{it};
    CFnow=FC{ip,it};
    if optStruct.smoothLogic
        [CFnow]=triSmoothFaceMeasure(CFnow,Fnow,Pnow,[],[]);
    end
    CFnow(CFnow<optStruct.dataLimits(1))=NaN;
    CFnow(CFnow>optStruct.dataLimits(2))=NaN;
    if strcmp(faceMeasureString,'pairInd')
        hp(ip)=gpatch(Fnow,Pnow,Colors(ip,:),Colors(ip,:),optStruct.FaceAlpha); hold on
    else
        hp(ip)=gpatch(Fnow,Pnow,CFnow,optStruct.lineColor,optStruct.FaceAlpha); hold on
    end
end

if legendLogic
    pairStrings=arrayfun(@num2str,1:nPairs,'unif',0);
    legendStrings=strcat('pair',pairStrings);
    legend(legendStrings);
end

h_ax=gca;
h_ax.XLim = xl; h_ax.YLim = yl; h_ax.ZLim = zl;

animStruct.Time=1:nFrames;
animStruct.Handles=cell(1,nFrames);
animStruct.Props=cell(1,nFrames);
animStruct.Set=cell(1,nFrames);

ic=1;
for it=1:nFrames
    animStruct.Handles{ic}=[];
    animStruct.Props{ic}=cell(1,2*nPairs);
    animStruct.Set{ic}=cell(1,2*nPairs);

    for ip=1:nPairs
        Fnow=DIC3DAllPairsResults{ip}.Faces;
        Pnow=DIC3DAllPairsResults{ip}.Points3D{it};
        CFnow=FC{ip,it};
        if optStruct.smoothLogic
            [CFnow]=triSmoothFaceMeasure(CFnow,Fnow,Pnow,[],[]);
        end
        CFnow(CFnow<optStruct.dataLimits(1))=NaN;
        CFnow(CFnow>optStruct.dataLimits(2))=NaN;
        animStruct.Handles{ic}=[animStruct.Handles{ic} hp(ip) hp(ip)]; %Handles of objects to animate
        animStruct.Props{ic}{2*ip-1}='CData';
        animStruct.Props{ic}{2*ip}='Vertices'; %Properties of objects to animate
        animStruct.Set{ic}{2*ip-1}=CFnow;
        animStruct.Set{ic}{2*ip}=Pnow; %Property values for to set in order to animate
    end

    h_ax.XLim = xl; h_ax.YLim = yl; h_ax.ZLim = zl;

    ic=ic+1;
end
anim8(hf,animStruct);

end

%%
% MultiDIC: a MATLAB Toolbox for Multi-View 3D Digital Image Correlation
%
% License: <https://github.com/MultiDIC/MultiDIC/blob/master/LICENSE.txt>
%
% Copyright (C) 2018  Dana Solav
%
% If you use the toolbox/function for your research, please cite our paper:
% <https://engrxiv.org/fv47e>


function vbmc_iterplot(vp,gp,optimState,stats,elbo)
%VBMC_ITERPLOT Plot current iteration of the VBMC algorithm.

D = vp.D;
iter = optimState.iter;
fontsize = 14;

if D == 1
    hold off;
    gplite_plot(gp);
    hold on;
    xlims = xlim;
    xx = linspace(xlims(1),xlims(2),1e3)';
    yy = vbmc_pdf(vp,xx,false,true);
    hold on;
    plot(xx,yy+elbo,':');
    drawnow;

else
    if ~isempty(vp)
        Xrnd = vbmc_rnd(vp,1e5,1,1);
    else
        Xrnd = gp.X;
    end
    X_train = gp.X;

    if iter == 1
        idx_new = true(size(X_train,1),1);
    else
        X_trainold = stats.gp(iter-1).X;
        idx_new = false(size(X_train,1),1);
        [~,idx_diff] = setdiff(X_train,X_trainold,'rows');
        idx_new(idx_diff) = true;
    end
    idx_old = ~idx_new;

    if ~isempty(vp.trinfo); X_train = warpvars_vbmc(X_train,'inv',vp.trinfo); end

    Pdelta = optimState.PUB_orig - optimState.PLB_orig;
    X_min = min(X_train,[],1) - Pdelta*0.1;
    X_max = max(X_train,[],1) + Pdelta*0.1;
    bounds = [max(min(optimState.PLB_orig,X_min),optimState.LB_orig); ...
        min(max(optimState.PUB_orig,X_max),optimState.UB_orig)];

    try
        for i = 1:D; names{i} = ['x_{' num2str(i) '}']; end
        [~,ax] = cornerplot(Xrnd,names,[],bounds);
        for i = 1:D-1
            for j = i+1:D
                axes(ax(j,i));  hold on;
                if any(idx_old)
                    scatter(X_train(idx_old,i),X_train(idx_old,j),'ok');
                end
                if any(idx_new)
                    scatter(X_train(idx_new,i),X_train(idx_new,j),'or','MarkerFaceColor','r');
                end
            end
        end

        h = axes(gcf,'Position',[0 0 1 1]);
        set(h,'Color','none','box','off','XTick',[],'YTick',[],'Units','normalized','Xcolor','none','Ycolor','none');
        text(0.9,0.9,['VBMC (iteration ' num2str(iter) ')'],'FontSize',fontsize,'HorizontalAlignment','right');

        drawnow;
    catch
        % pause
    end
end

end


function mtrEC2Tensor(subjectDirName, numRepeats, diffusionTime, numBootstrap)
% Converts eddy corrected DWI to tensor and related files.
%
%  mtrEC2Tensor(subjectDirName, numRepeats, [diffusionTime], [numBootstrap])
%
% subjectDirName: This conversion process follows a standardized file
% naming procedure. With files stored in the subject folder.
% numRepeats: Number of repeated volumes of DWIs recorded.
% numDWGrads: Number of diffusion weighted and non-diffusion weighted
%   measurements taken per repeat.
% diffusionTime: Time in seconds that diffusion was allowed to occur during
%   DWI experiment.  Default is 0.04s.
% numBootstrap: Number of synthetic bootstrap samples to generate during
%   tensor fitting and scanner noise estimation.  Default is 1000.
%
% With the following files and directories expected to already exist:
% INPUT
% rawAlignedFile - 'rawAligned.nii.gz': Eddy current corrected DWI images in compressed Nifti format
% bvalsFile - 'bvals': FSL format files specifying the b (s/mm^2) value of each DW measurement, where
%   b = q^2*delta and q = labeling strength (1/mm) and delta (s) is the diffusion time which we
%   assume as a default is 0.04s
% bvecsFile - 'rawAligned.bvecs': FSL format files specifying the vectors for DW measurements.
%   These vectors have a length of one.
%
%
% And the following files and directories produced:
% OUTPUT
% schemeFile - 'camino.scheme': Scheme file contains the same information
%   as the rawAligned.bvecs and bvals file combined with the additional diffusionTime
%   information.  This file is used during the bootstrap estimation of
%   scanner noise.
% rawAlignedVoxelFormatFile - 'rawDtiAligned.Bfloat': Big endian voxel order data file.
%   This file contains the same information as rawAlignedFile, except that the
%   data is ordered so that all voxel information is stored in the file in
%   order.
% bootstrapData - 'dtboot.Bdouble': Result of running the modelfit code
%   which uses bootstrap to generate 1000 sample
% brainMaskFile - 'brainMask.nii.gz': Output from FSL's BET program that
%   is a binary.
% tensorFile - 'bin\tensors.nii.gz': Tensor file in the format for DTIQuery.
%   Dxx,Dyy,Dzz,Dxy,Dxz,Dyz.
% meanB0File - 'bin\b0.nii.gz': Mean of the B0 data from the
%  raw eddy corrected files.
% faFile - 'bin\fa.nii.gz': Fractional anisotropy image
%   calculated from the tensorFile.
% wmMaskFile - 'bin\wmMask.nii.gz': Binary image indicating non-zero value
%   where white matter tissue is expected and zero otherwise.
% pdfFile - 'bin\pdf.nii.gz': Probability distribution function file that
%  is used during tractography in order to represent scanner noise per
%  voxel as well as shape information of the tensor fit per voxel. Data
%  stored: EV3,EV2,EV1,k1,k2,Cl,Cp.

%
% AUTOMATICALLY GENERATED OUTPUT
%
% SPECIFIED OUTPUT
%
% Examples:
%   Generate dt6 using dtiMakeDt6 <- (high level calls FromBin, FromTensorCalc, Muscle)
%
% AJS
%

% Go to subject directory
oldDirName = pwd;
cd(subjectDirName);

if( ieNotDefined('diffusionTime') )
    diffusionTime = 0.04;
end

if( ieNotDefined('numBootstrap') )
    numBootstrap = 1000;
end

schemeFile = fullfile('raw','camino.scheme');
rawAlignedFile = fullfile('raw','rawDti_aligned.nii.gz');
rawAlignedVoxelFormatFile = fullfile('raw','rawDti_aligned.Bfloat');
rawBvecsFile = fullfile('raw','rawDti_aligned.bvecs');
rawBvalsFile = fullfile('raw','rawDti_aligned.bvals');

% Check to see if which files need to be generated
%bGenBoot = queryOverwrite('dtboot.Bdouble');
bGenBoot = queryOverwrite(fullfile('bin','pdf.nii.gz'));
if bGenBoot
    bGenScheme = queryOverwrite(schemeFile);
else
    bGenScheme = 0;
end

% Convert bvecs and bvals into Camino scheme file
if bGenScheme
    if ispc
        error('Can not call fsl2scheme from matlab on Windows OS.')
    end
    delete(schemeFile);
    cmd = sprintf('fsl2scheme -bvalfile %s -bvecfile %s -diffusiontime %g -outputfile %s', rawBvalsFile, rawBvecsFile, diffusionTime, schemeFile);
    disp(cmd);
    [s, ret_info] = system(cmd,'-echo');
else
    disp('Using previously generated camino.scheme');
end

% Convert NIFTI raw image into Camino voxel format
if bGenBoot
    disp('Generating voxel format file, rawAligned.Bfloat');
    rawAligned = mtrNiftiToCamino(rawAlignedFile,'float', rawAlignedVoxelFormatFile);
    xformToAcPc = rawAligned.qto_xyz;
    mmPerVox = rawAligned.pixdim(1:3);
    numDWGrads = size(rawAligned.data,4) / numRepeats;
    if floor(numDWGrads) ~= numDWGrads
        msg = ['Num. volumes = ', num2str(size(rawAligned.data,4)), ' Num. repeats can''t be ', num2str(numRepeats)];
        error(msg);
    end
    % Calculate and save average B0 data
    img_b0 = mean(rawAligned.data(:,:,:,1:numDWGrads:end),4);
    dtiWriteNiftiWrapper(img_b0,xformToAcPc,fullfile('bin','b0.nii.gz'));
    clear rawAligned;
else
    nib0 = niftiRead(fullfile('bin','b0.nii.gz'));
    img_b0 = nib0.data;
    xformToAcPc = nib0.qto_xyz;
    mmPerVox = nib0.pixdim(1:3);
end

% Calculate and save brain mask
img_bm = mrAnatHistogramClip(img_b0,0.4,0.99);
img_bm = dtiCleanImageMask(img_bm > 0.25*max(img_bm(:)));
%img_bm = img_bm > 0.1;
%img_bm = dtiCleanImageMask(img_bm, 9);
dtiWriteNiftiWrapper(uint8(img_bm),xformToAcPc,fullfile('bin','brainMask.nii.gz'));

img_ten = zeros([size(img_bm) 6]);
img_fa = zeros([size(img_bm)]);
img_md = zeros([size(img_bm)]);

% Run bootstrap DTI fit
if bGenBoot

    % Store brain mask in a flat file for bootstrap fitting
    fid = fopen('brainMask.img','wb');
    fwrite(fid,img_bm,'short');fclose(fid);
    if ispc
        error('Can not call modelfitboot from matlab on Windows OS.')
    end
    delete(fullfile('raw','dtboot.Bdouble'));
    cmd = sprintf('modelfitboot -inputfile %s -inversion 1 -schemefile %s -outputfile raw/dtboot.Bdouble -bootstrap %g -bgmask brainMask.img -repeats %g -components %g', rawAlignedVoxelFormatFile, schemeFile, numBootstrap, numRepeats, numDWGrads);
    disp(cmd);
    [s, ret_info] = system(cmd,'-echo');

    % Remove flat file version of the brain mask
    delete('brainMask.img');

    % Load in the bootstrap results
    % XXX get format of data file, load data beforehand.
    fid = fopen(fullfile('raw','dtboot.Bdouble'),'rb','b');
    d = fread(fid,'double'); fclose(fid);

    % Write tensor file
    img_d = shiftdim(reshape(d,[21 81 106 76]),1);
    img_ten = zeros(size(img_d(:,:,:,3:8)));
    img_ten(:,:,:,1) = img_d(:,:,:,3);
    img_ten(:,:,:,2) = img_d(:,:,:,6);
    img_ten(:,:,:,3) = img_d(:,:,:,8);
    img_ten(:,:,:,4) = img_d(:,:,:,4);
    img_ten(:,:,:,5) = img_d(:,:,:,5);
    img_ten(:,:,:,6) = img_d(:,:,:,7);
    % Convert units from m^2/s to um^2 / ms
    img_ten(:) = img_ten(:)*1e9;
    dtiWriteNiftiWrapper(img_ten,xformToAcPc,fullfile('bin','tensors.nii.gz'));

    % Write fa file
    [eigVec, eigVal] = dtiSplitTensor(img_ten);
    [img_fa,img_md] = dtiComputeFA(eigVal);
    % Apply the brain mask
    img_fa(isnan(img_fa)) = 0;
    dtiWriteNiftiWrapper(img_fa,xformToAcPc,fullfile('bin','fa.nii.gz'));

    img_pdf = img_d(:,:,:,9:end-1);
    img_pdf(:,:,:,end+1) = eigVal(:,:,:,2);
    img_pdf(:,:,:,end+1) = eigVal(:,:,:,3);
    clear img_d;

    % Write pdf file for scanner fit uncertainty estimates
    % Make pdf 0 where it is outside of brain mask, this is necessary for
    % ConTrac program
    img_pdf( repmat(img_bm, [1 1 1 size(img_pdf,4)]) == 0 ) = 0;
    dtiWriteNiftiWrapper(img_pdf,xformToAcPc,fullfile('bin','pdf.nii.gz'));
    clear img_pdf;
    delete(fullfile('raw','dtboot.Bdouble'));

else
    disp('Using previously generated pdf.nii.gz');
    ni = niftiRead(fullfile('bin','tensors.nii.gz'));
    img_ten = ni.data;
    [eigVec, eigVal] = dtiSplitTensor(img_ten);
    [img_fa,img_md] = dtiComputeFA(eigVal);
    % Apply the brain mask
    img_fa(isnan(img_fa)) = 0;
    clear ni;
end

% Generate and write white matter mask file
bUseT1 = 0;
if bUseT1
    ni = niftiRead(fullfile('bin','t1.nii.gz'));
    disp('Please wait while calculating white matter from T1 image, this can take a few minutes ...');
    [wm, gm, csf] = mrAnatSpmSegment(ni.data,ni.qto_xyz,'MNIT1');
    bb = [-size(wm)/2; size(wm)/2-1];
    % now convert to mm space
    bb = ni.qto_xyz*[bb,[0;0]]';
    bb = bb(1:3,:)';
    img_wm = mrAnatResliceSpm(wm/max(wm(:)), inv(ni.qto_xyz), bb, [2 2 2]);
    dtiWriteNiftiWrapper(uint8(img_wm>0.5),ni.qto_xyz,fullfile('bin','wmMask.nii.gz'));
else
    %img_b0clip = mrAnatHistogramClip(img_b0,0.4,0.99);
    %img_brain = dtiCleanImageMask(img_b0clip > 0.4*max(img_b0clip(:)));
    % Do FA again after the clean image mask to make sure the ventricle holes
    % were not closed
    img_wm = img_bm & img_fa>.15 & (img_md<1.1 | img_fa>0.4);
    img_wm = dtiCleanImageMask(img_wm,0,0);
    dtiWriteNiftiWrapper(uint8(img_wm),xformToAcPc,fullfile('bin','wmMask.nii.gz'));
end

% Save out dt6File
l = license('inuse'); h = hostid;
created = ['Created at ' datestr(now,31) ' by ' l(1).user ' on ' h{1} '.'];
notes = '';
b0 = img_b0;
dtBrainMask = img_bm;
dt6 = img_ten;
disp('Writing dt6.mat');
save('dt6.mat', 'dt6', 'mmPerVox', 'notes', 'xformToAcPc', 'b0', 'dtBrainMask', 'created');

% Return to starting directory
cd(oldDirName);

function val = queryOverwrite(fileName)
val = 1;
if ~isempty(dir(fileName))
    [pathstr, strippedFileName, ext, versn] = fileparts(fileName);
    msg = sprintf('Do you want to overwrite %s ? Y/N [N]: ', [strippedFileName ext]);
    reply = input(msg, 's');
    if isempty(reply) || reply == 'n' || reply == 'N'
        val = 0;
    end
end
return;


function W = Fold(W, dim, i)
    dim = circshift(dim, [1-i, 1-i]);
    W = shiftdim(reshape(W, dim), length(dim)+1-i);
end


classdef (Abstract) mm_shared_pfcpf_acp < mp.mm_shared_pfcpf_ac

%   MATPOWER
%   Copyright (c) 2021-2022, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

%     properties
%     end

    methods
        function [vx_, z_, x_] = convert_x_m2n(obj, mmx, nm, only_v)
            %% x = obj.pf_convert(mmx, nm)
            %% [v, z] = obj.pf_convert(mmx, nm)
            %% [v, z, x] = obj.pf_convert(mmx, nm)
            %% ... = obj.pf_convert(mmx, nm, only_v)

            %% update v_, z_ from mmx
            nm_vars = obj.update_nm_vars(mmx, nm);
            vx_ = nm_vars.vm .* exp(1j * nm_vars.va);
            z_ = nm_vars.zr + 1j * nm_vars.zi;

            %% update z, if requested
            if nargin < 4 || ~only_v
                z_ = obj.update_z(nm, vx_, z_, obj.aux_data);
            end

            if nargout < 2
                vx_ = [vx_; z_];
            elseif nargout > 2
                x_ = [vx_; z_];
            end
        end
    end     %% methods
end         %% classdef


function output = callmosek(model)

% Retrieve needed data
options = model.options;
F_struc = model.F_struc;
c       = model.c;
Q       = model.Q;
K       = model.K;
x0      = model.x0;
integer_variables = model.integer_variables;
binary_variables = model.binary_variables;
extended_variables = model.extended_variables;
ub      = model.ub;
lb      = model.lb;
mt      = model.monomtable;

% *********************************
% What type of variables do we have
% *********************************
model.linear_variables = find((sum(abs(mt),2)==1) & (any(mt==1,2)));
model.nonlinear_variables = setdiff((1:size(mt,1))',model.linear_variables);
model.sigmonial_variables = find(any(0>mt,2) | any(mt-fix(mt),2));

% Some meta-solver thinks we handle binaries
if ~isempty(model.binary_variables)
    integer_variables = union(model.integer_variables, model.binary_variables);
    if isempty(lb)
        lb = repmat(-inf,1,length(model.c));
    end
    lb(model.binary_variables) = max(lb(model.binary_variables),0);
    if isempty(ub)
        ub = repmat(inf,1,length(model.c));
    end
    ub(model.binary_variables) = min(ub(model.binary_variables),1);
    model.lb = lb;
    model.ub = ub;
    model.integer_variables = integer_variables;
end

% Some meta solvers might construct model with empty cones
if any(model.K.s) && any(model.K.s == 0)
    model.K.s(model.K.s==0)=[];
end
if any(model.K.q) && any(model.K.q == 0)
    model.K.q(model.K.q==0)=[];
end

if ~isempty(model.sigmonial_variables) || isequal(model.solver.version,'GEOMETRIC')
    [x,D_struc,problem,r,res,solvertime,prob] = call_mosek_geometric(model);
else
    [x,D_struc,problem,r,res,solvertime,prob] = call_mosek_lpqpsocpsdp(model);
end

% YALMIP has introduced internal variables for socp/exp cones etc
if length(x) > 0 && length(x) ~= length(model.c)
    x = x(1:length(model.c));
end

% Save all data sent to solver?
if options.savesolverinput
    solverinput.prob = prob;
    solverinput.param = options.mosek;
else
    solverinput = [];
end

% Save all data from the solver?
if options.savesolveroutput
    solveroutput.r = r;
    solveroutput.res = res;

else
    solveroutput = [];
end

% Standard interface
output = createOutputStructure(x,D_struc,[],problem,model.solver.tag,solverinput,solveroutput,solvertime);

function [x,D_struc,problem,r,res,solvertime,prob] = call_mosek_lpqpsocpsdp(model);

[model,output] = normalizeExponentialCone(model);
if output.problem == 23
    % Cases such as 1-exp(t) >= x'*x
    [model,problem] = splitCones(model);
    if problem
        problem = 19;
        x = [];
        D_struc = [];
        r = [];
        res = [];
        solvertime = 0;
        prob = [];
    else
        [x,D_struc,problem,r,res,solvertime,prob] = call_mosek_lpqpsocpsdp(model);
    end
elseif output.problem
    problem = output.problem;
    x = [];
    D_struc = [];
    r = [];
    res = [];
    solvertime = 0;
    prob = [];
else
    if isempty(model.integer_variables)
        % Mosek cannot exploit this for continuous models (and if we keep
        % it from e.g. bnb, then the prmal version will be called, which
        % will run much slower for large SDPs)
        model.x0 = [];
    end
    if nnz(model.Q)==0 && isempty(model.integer_variables) && isempty(model.x0)
        % Standard cone problem which we can model by sending our standard dual
        % and then recover solution via Moseks dual
        [x,D_struc,problem,r,res,solvertime,prob] = call_mosek_dual(model);
    else
        % Integer conic program
        % Quadratic objective
        % Exponential cones
        [x,D_struc,problem,r,res,solvertime,prob] = call_mosek_primal(model);
    end
end


%% test1.m - exp03
% This script evaluates vector W (see test_bmrm.m and testValidatoin.m)
% against test data set (TST).
%
% 30-07-10 Michal Uricar
% 07-03-11 Michal Uricar, change to exp03

% clc;
close all; clearvars;

%% Timestamp

fprintf(1,'Started on %s\n\n', datestr(now));

%% Add path

addpath('./Functions/');
addpath('../../matlab_toolbox/mex/');

%% Select functions

load('./MAT/functions_gdisp.mat');

%% Load TST data

% load config
load('./MAT/config.mat');
lbpconfig_fname = ['./MAT/lbpconfig_nImages-' config.nImages '_hop-' num2str(config.heightOfPyramid) '.mat'];
images_fname = ['./MAT/ImagesTst_nImages-' config.nImages '.mat'];
gt_fname = ['./MAT/GTTst_nImages-' config.nImages '.mat'];

load(lbpconfig_fname);
load(images_fname);
load(gt_fname);
load('./results/options.mat');
S = options.S;

switch (config.nImages)
    case 'all'
        nImages = size(Images, 2);
    case 'half'
        nImages = size(Images, 2)/2;
    otherwise
        nImages = str2num(config.nImages);
end;

fprintf('Loading TST data...\n');
tic
data.lbp = lbpconfig; data.imSize = imSize; data.Images = Images; data.nImages = nImages;
options.S = S; data.Y = gt; data.options = options;
data.tmpData = getPsiMat(data, 1);
if (displacement)
    [data.options.PsiGS0, data.options.PsiGS1, data.options.PsiGS2] = getDisplacements(data.options);
end;
clear lbpconfig imSize Images nImages gt gt_fname images_fname lbpconfig_fname options S

% create mapTable for extracting components of W
data.mapTable = f_createMapTable(data.options, data.tmpData);
toc
fprintf('Done.\n');

w_fname = ['./results/W_nImages-' config.nImages '_hop-' num2str(config.heightOfPyramid) '.mat'];
load(w_fname);

load('./MAT/kappas.mat');

%% Test

% % start matlabpool
%try
%    matlabpool;
%catch ME1
%    idSegLast = regexp(ME1.identifier, '(?<=:)\w+$', 'match');
%    if (strcmp(idSegLast, 'OpenConnection'))
%        fprintf('Already connected to matlab pool. Skipping...\n');
%    end;
%end

fprintf('Running test...\n');

err_nose = inf(1, data.nImages);
err_canthus_rl = inf(1, data.nImages);
err_canthus_lr = inf(1, data.nImages);
err_mouth_corner_r = inf(1, data.nImages);
err_mouth_corner_l = inf(1, data.nImages);
err_canthus_rr = inf(1, data.nImages);
err_canthus_ll = inf(1, data.nImages);
err_mean = inf(1, data.nImages);
err_maxdist = inf(1, data.nImages);
L = zeros(1, data.nImages);

tic

for i = 1 : data.nImages
    [Test TestSparse] = getPsiMat(data, i);
    GT = data.Y{i};
    P = argmax_mex(data.options, W, data.mapTable, TestSparse);

    errors = sqrt(sum((P - GT).^2)) * kappa(i) * 100;

    err_nose(i) = errors(1);
    err_canthus_rl(i) = errors(2);
    err_canthus_lr(i) = errors(3);
    err_mouth_corner_r(i) = errors(4);
    err_mouth_corner_l(i) = errors(5);
    err_canthus_rr(i) = errors(6);
    err_canthus_ll(i) = errors(7);
    err_mean(i) = mean(errors);
    err_maxdist(i) = max(errors);

    L(i) = 1/data.options.M * sum( errors );
end;
Rtst = 1/data.nImages * sum(L);
toc

%try
%    matlabpool close;
%catch ME2
%    idSegLast = regexp(ME2.identifier, '(?<=:)\w+$', 'match');
%    if (strcmp(idSegLast, 'OpenConnection'))
%        fprintf('Cannot close matlabpool. Skipping...\n');
%    end;
%end;

%% Save errors

fprintf('Saving errors...\n');
options = data.options;
save('./results/errors.mat', 'options', 'L', 'err_nose', 'err_canthus_rl', ...
            'err_canthus_lr', 'err_mouth_corner_r', 'err_mouth_corner_l', ...
            'err_canthus_rr', 'err_canthus_ll', 'err_mean', 'err_maxdist', 'Rtst');
fprintf('Done.\n');

fprintf('Rtst = %.4f\n', Rtst);

%% Timestamp

fprintf(1,'Finished on %s\n\n', datestr(now));


function inspect_bug2993

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

cd(dccnpath('/home/common/matlab/fieldtrip/data/test/bug2993'));
elec_original = ft_read_sens('EEGMarkersLocalite.xml');

% elec_original = ft_determine_coordsys(elec_original);
elec_original.coordsys = 'lps';

% the electrodes should be rotated around the z-axis with 180 degrees to make them consistent
% with the MNI coordinate system (x=right, y=nose), which is expected by default in ft_prepare_layout

figure
ft_plot_sens(elec_original, 'label', 'on');
ft_plot_axes(elec_original);

%%
cfg = [];
cfg.elec = elec_original;
cfg.method = 'interactive';
elec_realigned1 = ft_electroderealign(cfg);

assert(~isequal(elec_realigned1.chanpos, elec_original.chanpos));

%%
cfg = [];
cfg.elec = elec_original;
cfg.method = 'interactive';
% this requires a headshape, but it can be empty
cfg.headshape = [];
cfg.headshape.pos  = zeros(0,3);
cfg.headshape.tri  = zeros(0,3);
cfg.headshape.unit = 'mm';
elec_realigned2 = ft_sensorrealign(cfg);

assert(~isequal(elec_realigned2.chanpos, elec_original.chanpos));

%%
cfg = [];
cfg.individual.elec = elec_original;
cfg.template.headshape = [];
cfg.template.headshape.pos  = randn(10,3);
cfg.template.headshape.tri  = zeros(0,3);
cfg.template.headshape.unit = 'mm';
cfg.method = 'interactive';
outcfg = ft_interactiverealign(cfg);

% this returns the transformation, not the updated electrode positions
assert(~isequal(outcfg.m, eye(4)));

%%

cfg = [];
cfg.elec = elec_original;
figure; ft_plot_layout(ft_prepare_layout(cfg));

cfg = [];
cfg.elec = elec_original;
cfg.rotate = 180;
figure; ft_plot_layout(ft_prepare_layout(cfg));

cfg = [];
cfg.elec = elec_realigned1;
figure; ft_plot_layout(ft_prepare_layout(cfg));


% Copyright (C) 2017-2018 Titus Cieslewski, RPG, University of Zurich,
%   Switzerland
%   You can contact the author at <titus at ifi dot uzh dot ch>
% Copyright (C) 2017-2018 Siddharth Choudhary, College of Computing,
%   Georgia Institute of Technology, Atlanta, GA, USA
% Copyright (C) 2017-2018 Davide Scaramuzza, RPG, University of Zurich,
%   Switzerland
%
% This file is part of dslam_open.
%
% dslam_open 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.
%
% dslam_open 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 dslam_open. If not, see <http://www.gnu.org/licenses/>.

function decentr_state = initDecentrState(full_state)

num_robots = numel(full_state);

decentr_state = cell(size(full_state));
for i = 1:num_robots
    decentr_state{i}.Sim_W_O = eye(4);
    decentr_state{i}.Sim_O_C = cell(0);
    decentr_state{i}.Sim_Cprev_C = cell(0);
    decentr_state{i}.original_T_O_C = cell(0);
    decentr_state{i}.times = [];
    decentr_state{i}.netvlad = [];
    decentr_state{i}.descs = {};
    decentr_state{i}.wids3 = {};
    decentr_state{i}.wids4 = {};
    decentr_state{i}.lms_in_frame = cell(0);
    decentr_state{i}.gt_T_W_C = cell(0);
    decentr_state{i}.T_gt_O_ate = full_state{i}.T_W_C{1};

    % DVPR related members
    decentr_state{i}.dvpr_queries_netvlad = [];
    decentr_state{i}.dvpr_queries_robot_i = [];
    decentr_state{i}.dvpr_queries_frame_i = [];

    % Robust relpose
    decentr_state{i}.consistent_groups = cell(num_robots, 1);
    for j = 1:num_robots
        decentr_state{i}.consistent_groups{j}.members = {};
        decentr_state{i}.consistent_groups{j}.floating = true;
    end

    decentr_state{i}.place_matches = cell(0);
    decentr_state{i}.grouped_with = [];
    decentr_state{i}.converged = true;
    % Pre-loading landmarks -> more managable
    T_O_W = full_state{i}.T_W_C{1} ^ -1;
    decentr_state{i}.p_O_lm = ...
        T_O_W(1:3, 1:3) * full_state{i}.p_W_lm' + T_O_W(1:3, 4);
end

end


function [ compdata ] = fiff_read_ctf_comp(fid,node,chs)

%
% [ compdata ] = fiff_read_ctf_comp(fid,node,chs)
%
% Read the CTF software compensation data from the given node
%

%
%   Author : Matti Hamalainen, MGH Martinos Center
%   License : BSD 3-clause
%
%
%   Revision 1.8  2007/11/13 10:55:32  msh
%   Specify the second argument to all calls to the exist function
%
%   Revision 1.7  2006/09/25 19:48:16  msh
%   Added projection item kinds to fiff_define_constants
%   Changed some fields to int32 in surface structures
%
%   Revision 1.6  2006/08/09 15:22:51  msh
%   Removed debug printout.
%
%   Revision 1.5  2006/06/22 21:22:46  msh
%   Take into account the possibility of calibrated compensation matrices
%
%   Revision 1.4  2006/04/23 15:29:40  msh
%   Added MGH to the copyright
%
%   Revision 1.3  2006/04/18 20:44:46  msh
%   Added reading of forward solution.
%   Use length instead of size when appropriate
%
%   Revision 1.2  2006/04/12 10:29:02  msh
%   Made evoked data writing compatible with the structures returned in reading.
%
%   Revision 1.1  2006/04/10 23:26:54  msh
%   Added fiff reading routines
%
%

global FIFF;
if isempty(FIFF)
    FIFF = fiff_define_constants();
end

me='MNE:fiff_read_ctf_comp';

if nargin ~= 3
    error(me,'Incorrect number of arguments');
end

compdata = struct('ctfkind',{},'kind',{},'save_calibrated',{},'rowcals',{},'colcals',{},'data',{});
comps = fiff_dir_tree_find(node,FIFF.FIFFB_MNE_CTF_COMP_DATA);

for k = 1:length(comps)
    node = comps(k);
    %
    %   Read the data we need
    %
    mat  = fiff_read_named_matrix(fid,node,FIFF.FIFF_MNE_CTF_COMP_DATA);
    for p = 1:node.nent
        kind = node.dir(p).kind;
        pos  = node.dir(p).pos;
        if kind == FIFF.FIFF_MNE_CTF_COMP_KIND
            tag = fiff_read_tag(fid,pos);
            break;
        end
    end
    if ~exist('tag','var')
        error(me,'Compensation type not found');
    end
    %
    %   Get the compensation kind and map it to a simple number
    %
    one.ctfkind = tag.data;
    clear('tag');
    one.kind    = int32(-1);
    if one.ctfkind     == hex2dec('47314252')
        one.kind = int32(1);
    elseif one.ctfkind == hex2dec('47324252')
        one.kind = int32(2);
    elseif one.ctfkind == hex2dec('47334252')
        one.kind = int32(3);
    else
        one.kind = one.ctfkind;
    end
    for p = 1:node.nent
        kind = node.dir(p).kind;
        pos  = node.dir(p).pos;
        if kind == FIFF.FIFF_MNE_CTF_COMP_CALIBRATED
            tag = fiff_read_tag(fid,pos);
            break;
        end
    end
    if ~exist('tag','var')
        calibrated = false;
    else
        calibrated = tag.data;
    end
    one.save_calibrated = calibrated;
    one.rowcals = ones(1,size(mat.data,1));
    one.colcals = ones(1,size(mat.data,2));
    if ~calibrated
        %
        %   Calibrate...
        %
        %
        %   Do the columns first
        %
        for p  = 1:length(chs)
            ch_names{p} = chs(p).ch_name;
        end
        for col = 1:size(mat.data,2)
            p = strmatch(mat.col_names{col},ch_names,'exact');
            if isempty(p)
                error(me,'Channel %s is not available in data',mat.col_names{col});
            elseif length(p) > 1
                error(me,'Ambiguous channel %s',mat.col_names{col});
            end
            col_cals(col) = 1.0/(chs(p).range*chs(p).cal);
        end
        %
        %    Then the rows
        %
        for row = 1:size(mat.data,1)
            p = strmatch(mat.row_names{row},ch_names,'exact');
            if isempty(p)
                error(me,'Channel %s is not available in data',mat.row_names{row});
            elseif length(p) > 1
                error(me,'Ambiguous channel %s',mat.row_names{row});
            end
            row_cals(row) = chs(p).range*chs(p).cal;
        end
        mat.data            = diag(row_cals)*mat.data*diag(col_cals);
        one.rowcals         = row_cals;
        one.colcals         = col_cals;
    end
    one.data       = mat;
    compdata(k)    = one;
    clear('row_cals');
    clear('col_cals');
end

if length(compdata) > 0
    fprintf(1,'\tRead %d compensation matrices\n',length(compdata));
end

return;

end


function varargout = pwf(varargin)
%PWF Defines a piecewise function
%
% t = PWF(h1,F1,h2,F2,...,hn,Fn)
%
% The variable t can only be used in convexity/concavity preserving
% operations, depending on the convexity of hi

switch class(varargin{1})

    case {'cell','struct'}
        % This should be an internal call to setup a PWA/PWQ function
        % defined in MPT

        if nargin<3
            pwaclass = 'general'
        end

        if isa(varargin{1},'struct')
            varargin{1} = {varargin{1}};
        end

        % Put in standard format
        if ~isfield(varargin{1}{1},'Bi')
            if ~isfield(varargin{1}{1},'Fi')
                error('Wrong format on input to PWA (requires Bi or Fi)');
            else
                for i = 1:length(varargin{1})
                    varargin{1}{1}.Ai = cell(1, varargin{1}{i}.Fi);
                    varargin{1}{i}.Bi = varargin{1}{i}.Fi
                    varargin{1}{i}.Ci = varargin{1}{i}.Gi
                end
            end
        end

        if isempty(varargin{1}{1}.Ai{1})
            varargout{1} = pwa_yalmip(varargin{:});
        else
            if  nnz([varargin{1}{1}.Ai{:}]) == 0
                varargout{1} = pwa_yalmip(varargin{:});
            else
                varargout{1} = pwq_yalmip(varargin{:});
            end
        end

    case {'sdpvar','double'} % Overloaded operator for SDPVAR objects. Pass on args and save them.
        if length(varargin{1}) == 1

            % If it is a quadratic function, we might treat it more
            % efficiently by writing it as sum(d_i q_i(x)) with d_i binary.
            % This is implemented in the pwq_operator
            quadratic_objective = 1;
            linear_constraint =   1;
            for i = 1:nargin/2
                ok = 0;
                if isa(varargin{2*i-1},'sdpvar')
                    if isa(varargin{2*i},'constraint')
                        varargin{2*i} = lmi(varargin{2*i});
                    end
                    if isa(varargin{2},'lmi')
                        if is(varargin{2*i-1},'quadratic') |  is(varargin{2*i-1},'linear')
                            if all(is(varargin{2*i},'elementwise') | is(varargin{2*i},'elementwise'))
                                if is(sdpvar(varargin{2*i}),'linear')
                                    ok = 1;
                                end
                            end
                        end
                    end
                end
                if ~ok
                    break
                end
            end
            if ok
                z = [];
                for i = 1:nargin/2
                    z = [z depends(varargin{2*i-1}) depends(varargin{2*i})];
                end
                z = recover(unique(z));

                pwq{1}.Ai = {};
                pwq{1}.Bi = {};
                pwq{1}.Ci = {};
                pwq{1}.Pn = [];
                for i = 1:nargin/2
                    [Q,c,f,x,info] = quaddecomp(varargin{2*i-1},z);
                    pwq{1}.Ai = {pwq{1}.Ai{:},Q};
                    pwq{1}.Bi = {pwq{1}.Bi{:},c(:)};
                    pwq{1}.Ci = {pwq{1}.Ci{:},f};
                    F = getbase([sdpvar(varargin{2*i});sum(z)]);
                    pwq{1}.Pn = [pwq{1}.Pn polytope(-F(1:end-1,2:end),F(1:end-1,1))];
                end
                pwq{1}.Pfinal = union(pwq{1}.Pn);
                varargout{1} = pwq_yalmip(pwq,z,'general');
            else
                varargout{1} = yalmip('define',mfilename,varargin{:});
            end
        else
            y = [];
            VV = varargin;
            for i = 1:length(varargin{1})
                VV = varargin;
                for j = 1:(length(varargin)/2)
                    VV{2*j-1} = VV{2*j-1}(i);
                end
                y = [y;yalmip('define',mfilename,VV{:})];
            end
            varargout{1} = y;
        end

    case 'char' % YALMIP sends 'model' when it wants the epigraph or hypograph
        if isequal(varargin{1},'graph')
            varargout{1} = [];
            varargout{2} =  struct('convexity','failure','monotoncity','failure','definiteness','failure');;
            varargout{3} = [];
        elseif isequal(varargin{1},'milp')
            % pwf represented by t
            t = varargin{2};
            % Get functions and guards
            for i = 3:2:nargin
                f{(i-1)/2} = varargin{i};
                Guard{(i+1)/2-1} = varargin{i+1};
            end

            % Indicator for where we are
            indicators = binvar(length(f),1);
            % We are in some of the regions
            F = (sum(indicators) == 1);

            % Control where we are using the indicators and big-M
            X = [];
            for i = 1:length(Guard)
                Xi = sdpvar(Guard{i});
                if is(Xi,'linear')
                    [M,m] = derivebounds(Xi);
                else
                    m = -1e4;
                end
                F = F + (Xi >= m*(1-indicators(i)));
                X = [X;recover(depends(Guard{i}))];
            end
            % cost = sum(delta_i*cost_i(x)) = sum(cost_i(delta_i*x))
            X = recover(getvariables(X));

            if 0
                cost = 0;
                for i = 1:length(f)
                    [Q{i},c{i},g{i},xi,info] = quaddecomp(f{i},X);
                    if info
                        error('Only convex quadratic functions allowed in PWF');
                    end
                    [M,m] = derivebounds(xi);
                    z{i} = sdpvar(length(xi),1);
                    cost = cost + z{i}'*Q{i}*z{i}+c{i}'*z{i} + g{i}*indicators(i);
                    F = F + (xi+(1-indicators(i))*m<=z{i}<xi+(1-indicators(i)).*M);
                    F = F + (m*indicators(i) <= z{i} <= M*indicators(i));
                end
                F = F + (cost <= t);
            else
                fmax_max = -inf;
                fmin_min = inf;
                for i = 1:length(f)
                    [Q{i},c{i},g{i},xi,info] = quaddecomp(f{i},X);
                    if info
                        error('Only convex quadratic functions allowed in PWF');
                    end
                    [fmax,fmin] = derivebounds(c{i}'*xi+g{i});
                    fmax_max = max(fmax,fmax_max);
                    fmin_min = min(fmin,fmin_min);
                    F = F + (c{i}'*xi +g{i} <= t + fmax*(1-indicators(i)));
                end
            end
            % To help variable strenghtening, constraint removal etc in
            % other functions, let us update the internal bound info
            bounds(t,fmin_min,fmax_max);

            % This function is convex when we relax the binary variables
            varargout{1} = F;
            varargout{2} = struct('convexity','milp','monotoncity','milp','definiteness','none');
            varargout{3} = X;
        else
            error('SDPVAR/NORM called with CHAR argument?');
        end
    otherwise
        error('Strange type on first argument in SDPVAR/NORM');
end


classdef InstanceSegMMLoss < dagnn.Loss
    properties
        marginAlpha_
    end
    properties (Transient)
        curSimMat
        weightMat
        mass_
        size_
    end

    methods
        function outputs = forward(obj, inputs, params)
            [h, w, ch, bs] = size(inputs{1});
            sz = [h, w, ch, bs];
            mass = sz(1) * sz(2) + 1;

            obj.size_ = sz;
            obj.mass_ = mass;

%             gpuMode = isa(inputs{1}, 'gpuArray');
%             if gpuMode
%                 grndLabel = gpuArray(zeros(sz, 'single'));
%             else
%                 grndLabel = zeros(sz, 'single');
%             end
%
%             for j = 1:sz(4)
%                 C = inputs{2}(:,:,:,j);
%                 C = reshape(C, [sz(1), 1]);
%                 C = repmat(C, 1, sz(2));
%                 C = (C==C');
%                 grndLabel(:,:,:,j) = C;
%             end
%             obj.curSimMat = grndLabel;

            layerName = 'obj_instSeg';
            if isnan(obj.net.getLayerIndex(layerName))
                layerName = 'obj_instSeg_reg';
            end
            obj.curSimMat = obj.net.layers(obj.net.getLayerIndex(layerName)).block.curSimMat;
            obj.weightMat = obj.net.layers(obj.net.getLayerIndex(layerName)).block.weightMat;

            outputs{1} = vl_nnloss(inputs{1}, obj.curSimMat, 'marginAlpha_', obj.marginAlpha_, ...
                'loss', obj.loss, ...
                'instanceWeights', obj.weightMat ) ; % 1./mass
            n = obj.numAveraged ;
            m = n + size(inputs{1},4) ;
            obj.average = (n * obj.average + double(gather(outputs{1}))) / m ;
            obj.numAveraged = m ;
        end

        function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
%             sz = obj.size_;
%             mass = obj.mass_;
%             grndLabel = obj.curSimMat;

            derInputs{1} = vl_nnloss(inputs{1}, obj.curSimMat, derOutputs{1}, 'marginAlpha_', obj.marginAlpha_, ...
                'loss', obj.loss, ...
                'instanceWeights', obj.weightMat ) ; % 1./mass
            derInputs{2} = [] ;
            derParams = {} ;
        end

        function obj = InstanceSegMMLoss(varargin)
            obj.load(varargin) ;
        end
    end
end


function  [tscounts, wfcounts, evcounts, contcounts] = plx_info(filename, fullread)
% plx_info(filename, fullread) -- read and display .plx or .pl2 file info
%
% [tscounts, wfcounts, evcounts, contcounts] = plx_info(filename, fullread)
%
% INPUT:
%   filename - if empty string, will use File Open dialog
%   fullread - if 0, reads only the file header
%              if 1, reads the entire file
%               for .pl2 files, this parameter is ignored
%
% OUTPUT:
%   tscounts - 2-dimensional array of timestamp counts for each unit
%      tscounts(i, j) is the number of timestamps for channel j-1, unit i
%                                (see comment below)
%   wfcounts - 2-dimensional array of waveform counts for each unit
%     wfcounts(i, j) is the number of waveforms for channel j-1, unit i
%                                (see comment below)
%   evcounts - 1-dimensional array of external event counts
%     evcounts(i) is the number of events for event channel i
%
%   contcounts - 1-dimensional array of sample counts for continuous channels
%     contcounts(i) is the number of continuous for slow channel i-1
%
% Note that for tscounts, wfcounts, the unit,channel indices i,j are off by one.
% That is, for channels, the count for channel n is at index n+1, and for units,
%  index 1 is unsorted, 2 = unit a, 3 = unit b, etc
% The dimensions of the tscounts and wfcounts arrays are
%   (NChan+1) x (MaxUnits+1)
% where NChan is the number of spike channel headers in the plx file, and
% MaxUnits is 4 if fullread is 0, or 26 if fullread is 1. This is because
% the header of a .plx file can only accomodate 4 units, but doing a
% fullread on the file may show that there are actually up to 26 units
% present in the file. Likewise, NChan will have a maximum of 128 channels
% if fullread is 0.
% The dimension of the evcounts and contcounts arrays is the number of event
% and continuous (slow) channels.
% The counts for slow channel 0 is at contcounts(1)

tscounts = [];
wfcounts = [];
evcounts = [];
contcounts = [];

if nargin ~= 2
    error 'expected 2 input arguments';
end

[ filename, isPl2 ] = internalPL2ResolveFilenamePlx( filename );
if isPl2 == 1
    pl2 = PL2GetFileIndex(filename);
    numSpikeChannels = numel(pl2.SpikeChannels);
    % pl2 files support up to 256 units, but we limit to
    % 26 sorted plus 1 unsorted to be compatible with plx_info
    tscounts = zeros(27,numSpikeChannels+1);
    for i=1:numSpikeChannels
        tscounts(:,i+1) = pl2.SpikeChannels{i}.UnitCounts(1:27);
    end
    wfcounts = tscounts;

    numAnalogChannels = numel(pl2.AnalogChannels);
    contcounts = zeros(1,numAnalogChannels);
    for i=1:numAnalogChannels
        contcounts(1,i) = pl2.AnalogChannels{i}.NumValues;
    end

    evcounts = pl2.EventCounts;
    return
end

[tscounts, wfcounts, evcounts, contcounts] = mexPlex(4, filename, fullread);

end


function[blobs] = rpUijlings2013(image, varargin)
% [blobs] = rpUijlings2013(image, varargin)
%
% Create a list of region proposals (blobs) of an image using the method of Uijlings2013.
%
% For information on the returned blobs see blob().
%
% Copyright by Holger Caesar, 2014

% Parse input
p = inputParser;
% Default settings suggested by Jasper
addParameter(p, 'ks', [50, 100]);
addParameter(p, 'sigma', 0.8);
addParameter(p, 'colorTypes', {'Hsv', 'Lab'});
addParameter(p, 'simFunctionHandles', {@SSSimColourTextureSizeFillOrig, @SSSimTextureSizeFill});
parse(p, varargin{:});

ks = p.Results.ks;
sigma = p.Results.sigma;
colorTypes = p.Results.colorTypes;
simFunctionHandles = p.Results.simFunctionHandles;

% Init SS
hierarchyCount = numel(ks) * numel(colorTypes) * numel(simFunctionHandles);
blobs = cell(hierarchyCount, 1);
priorities = cell(hierarchyCount, 1);
hBlobsInd = 1;

% Perform Selective Search on all parameter combinations
for ksInd = 1 : numel(ks),
    for colorTypeInd = 1 : numel(colorTypes),
        for simHndsI = 1 : numel(simFunctionHandles),
            % Compute hierarchical grouping with current settings
            [~, blobIndIm, blobBoxesInIm, hierarchy, priority] = Image2HierarchicalGrouping(image, sigma, ks(ksInd), ks(ksInd), colorTypes{colorTypeInd}, simFunctionHandles(simHndsI));

            % Convert boxes to blobs (when there is only one blob, we can't
            % create a hierarchy, i.e. for k=400)
            if isempty(hierarchy),
                blobs{hBlobsInd} = RecreateBlobHierarchyIndIm(blobIndIm, blobBoxesInIm, []);
            else
                blobs{hBlobsInd} = RecreateBlobHierarchyIndIm(blobIndIm, blobBoxesInIm, hierarchy{1});
            end;

            % Store priority
            priorities{hBlobsInd} = priority;
            hBlobsInd = hBlobsInd + 1;
        end;
    end;
end;

% Put all parameter results in a single cell array
blobs = flattenCellArray(blobs);
priorities = flattenCellArray(priorities);

% Do pseudo random sorting as in paper
priorities = priorities .* rand(size(priorities));
[~, sortIds] = sort(priorities, 'ascend');
blobs = blobs(sortIds, :);

% Convert to col struct
blobs = [blobs{:}];
blobs = blobs(:);


function [doseHandle,cMap,window] = matRad_plotDoseSlice(axesHandle,doseCube,plane,slice,threshold,alpha,cMap,window)
% matRad function that generates a dose plot of a selected slice
% The function can also be used in personal matlab figures by passing the
% corresponding axes handle.
%
% call
%   [doseHandle,cMap,window] = matRad_plotDoseSlice(axesHandle, doseCube,plane,slice,threshold)
%   [doseHandle,cMap,window] = matRad_plotDoseSlice(axesHandle, doseCube,plane,slice,threshold,alpha)
%   [doseHandle,cMap,window] = matRad_plotDoseSlice(axesHandle, doseCube,plane,slice,threshold,cMap)
%   [doseHandle,cMap,window] = matRad_plotDoseSlice(axesHandle, doseCube,plane,slice,threshold,window)
%   [doseHandle,cMap,window] = matRad_plotDoseSlice(axesHandle, doseCube,plane,slice,threshold,alpha,cMap)
%   [doseHandle,cMap,window] = matRad_plotDoseSlice(axesHandle, doseCube,plane,slice,threshold,alpha,window)
%   [doseHandle,cMap,window] = matRad_plotDoseSlice(axesHandle, doseCube,plane,slice,threshold,cMap,window)
%   [doseHandle,cMap,window] = matRad_plotDoseSlice(axesHandle, doseCube,plane,slice,threshold,alpha,cMap,window)
%
% input
%   axesHandle  handle to axes the slice should be displayed in
%   doseCube    3D array of the dose to select the slice from
%   plane       plane view (coronal=1,sagittal=2,axial=3)
%   slice       slice in the selected plane of the 3D cube
%   threshold   threshold above which the dose shall be displayed
%               for negative values (i.e. difference maps), also the values
%               smaller than the negative threshold will be displayed
%               if empty, no threshold will be applied
%   alpha       optional argument defining the alpha value, default is 0.6.
%               To use the default when providing a custom culormap, put in
%               an empty array by [].
%   cMap        optional argument defining the colormap, default is jet
%               if you want to use the default map with the window argument
%               you can use an empty array []
%   window      optional argument defining the displayed range. default is
%               [min(doseCube(:)) max(doseCube(:))]
%
% output
%   doseHandle: handle of the plotted dose axes
%   cMap        used colormap (same as input if set)
%   window      used window (same as input if set)
%
% References
%   -
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Copyright 2015 the matRad development team.
%
% This file is part of the matRad project. It is subject to the license
% terms in the LICENSE file found in the top-level directory of this
% distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part
% of the matRad project, including this file, may be copied, modified,
% propagated, or distributed except according to the terms contained in the
% LICENSE file.
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

matRad_cfg = MatRad_Config.instance();

%Use default colormap?
if nargin < 7 || isempty(cMap)
    cMap = jet(64);
end
if nargin < 6 || isempty(alpha)
    alpha = 0.6;
end
if nargin < 8 || isempty(window)
    window = [min(doseCube(:)) max(doseCube(:))];
end

maxDose = max(doseCube(:));

cMapScale = size(cMap,1) - 1;

if plane == 1  % Coronal plane
    dose_slice = squeeze(doseCube(slice,:,:));
elseif plane == 2 % sagittal plane
    dose_slice = squeeze(doseCube(:,slice,:));
elseif plane == 3 % Axial plane
    dose_slice = squeeze(doseCube(:,:,slice));
else
	matRad_cfg.dispError('Invalid plane ''%d'' selected for visualization!',plane);
end

if ~isempty(threshold)
    mask = alpha * (dose_slice < window(2) & dose_slice > window(1) & dose_slice > threshold*maxDose);
else
    mask = alpha * (dose_slice < window(2) & dose_slice > window(1));
end

dose_slice = uint8(cMapScale*(dose_slice - window(1))/(window(2)-window(1)));

%This circumenvents a bug in Octave when the index in the image hase the maximum value of uint8
if matRad_cfg.isOctave
	dose_slice(dose_slice == 255) = 254;
end

dose_rgb = ind2rgb(dose_slice,cMap);

% plot dose distribution
doseHandle = image('CData',dose_rgb,'Parent',axesHandle);

% alphadata for image objects is not yet implemented in Octave
set(doseHandle,'AlphaData',mask);

end


function Y = spm_data_read(V,varargin)
% Read data from disk [Y = V(I)]
% FORMAT Y = spm_data_read(V)
% V        - a structure array (see spm_data_hdr_read)
% Y        - an array of data values; the last dimension indexes numel(V)
%
% FORMAT Y = spm_data_read(V,'slice',S)
% V        - a structure array of image volumes (see spm_data_hdr_read)
% S        - an array of slice indices
% Y        - an array of data values with dimensions (x,y,s,v)
%
% FORMAT Y = spm_data_read(V,'xyz',XYZ)
% V        - a structure array (see spm_data_hdr_read)
% XYZ      - a [n x m] array of m coordinates {voxel (n=3 or 4)/vertex (n=1)}
% Y        - an array of data values with dimensions (v,m)
%
% FORMAT Y = spm_data_read(V,I1,I2,...)
% V        - a structure array (see spm_data_hdr_read)
% I1,I2,...- subscript arrays
% Y        - an array of data values with dimensions (v,m)
%__________________________________________________________________________
% Copyright (C) 2012-2019 Wellcome Trust Centre for Neuroimaging

% Guillaume Flandin
% $Id: spm_data_read.m 7577 2019-04-24 08:59:56Z guillaume $

if ~isstruct(V)
    V = spm_data_hdr_read(V);
end

cl = class(V(1).private);
if isfield(V(1),'dat') && ~isequal(cl,'gifti'), cl = 'nifti'; end

switch cl
    case 'nifti'
        if isempty(varargin)
            % Y = full(V.private.dat); % if numel(V)==1, is faster
            Y = spm_read_vols(V);
        elseif ischar(varargin{1}) && ~isequal(varargin{1},':')
            switch lower(varargin{1})
                case 'slice'
                    for i=1:numel(V), for p=1:numel(varargin{2})
                        Y(:,:,p,i) = spm_slice_vol(V(i),spm_matrix([0 0 varargin{2}(p)]),V(i).dim(1:2),0);
                    end, end
                    if numel(V)==1, Y=Y(:,:,:,1); end
                case 'xyz'
                    Y = spm_get_data(V,varargin{2});
                otherwise
                    error('Unknown input option.');
            end
        else
            indices = varargin;
            n = get_ndata(V(1).dim,indices{:});
            Y = zeros(numel(V),prod(n));
            for i=1:numel(V)
                if numel(indices) == 1
                    ind = {indices{1} + (V(i).n(1)-1)*prod(V(i).dim)};
                else
                    ind = indices;
                end
                Y(i,:) = reshape(V(i).private.dat(ind{:}),1,[]);
            end
        end

    case 'gifti'
        indices = varargin;
        if isempty(indices)
            indices = repmat({':'},1,ndims(V));
        elseif strcmpi(indices{1},'xyz')
            indices = {indices{2}(1,:)};
        end
        n = get_ndata(V(1).dim,indices{:});
        Y = zeros(numel(V),prod(n));
        for i=1:numel(V)
            Y(i,:) = reshape(V(i).private.cdata(indices{:}),1,[]);
        end
        if isempty(varargin), Y = Y'; end % to be coherent with spm_read_vols

    otherwise
        error('Unknown data type.');
end

%==========================================================================
function n = get_ndata(dim,varargin)
n = zeros(1,numel(varargin));
for i=1:numel(varargin)
    if isequal(varargin{i},':')
        if i==numel(varargin)
            n(i) = dim(i); %prod(dim(i:end));
        else
            n(i) = dim(i);
        end
    else
        n(i) = numel(varargin{i});
    end
end


function y = iterapp(op,afun,atype,afcnstr,x,varargin)
%ITERAPP   Apply matrix operator to vector and error gracefully.
%   ITERAPP(OP,AFUN,ATYPE,AFCNSTR,X) applies matrix operator AFUN to vector
%   X. If ATYPE is 'matrix, then AFUN is a matrix and the OP is applied
%   directly. OP is either 'mtimes' or 'mldivide'.
%   ATYPE and AFCNSTR are used in case of error.
%   ITERAPP(OP,AFUN,ATYPE,AFCNSTR,X,P1,P2,...) allows extra arguments to
%   AFUN(X,P1,P2,...) although this usage is now discouraged in favor of
%   using anonymous functions.
%   AFUN(X,P1,P2,...,PN,TFLAG) should accept a TFLAG as its final input if
%   the calling function is BICG, LSQR or QMR. TFLAG is either 'transp' or
%   'notransp' depending on whether A' OP X or A OP X is required.
%   ITERAPP is designed for use by iterative methods like PCG which
%   require matrix operators AFUN representing matrices A to operate on
%   vectors X and return A*X and may also have operators MFUN representing
%   preconditioning matrices M operate on vectors X and return M\X.
%
%   See also BICG, BICGSTAB, CGS, GMRES, LSQR, MINRES, PCG, QMR, SYMMLQ.

%   Copyright 1984-2013 The MathWorks, Inc.

if strcmp(atype,'matrix')
    switch lower(op)
        case 'mtimes'
            if (nargin >= 6) && isequal(varargin{end},'transp')
                y = afun' * x;
            else
                y = afun * x;
            end
        case 'mldivide'
            if (nargin >= 6) && isequal(varargin{end},'transp')
                y = afun' \ x;
            else
                y = afun \ x;
            end
        otherwise
            error(message('MATLAB:iterapp:InvalidOp'))
    end
else
%     try
        if (nargin >= 6) && isequal(varargin{end},'notransp')
            % A request for A*x coming from BICG, LSQR and QMR
            try
                % New syntax: we now request afun(x,P1,P2,...,PN,'notransp')
                y = afun(x,varargin{:});
            catch
                % Old syntax: we used to accept afun(x,P1,P2,...,PN)
                y = afun(x,varargin{1:end-1});
            end
        else
            % A request for A*x
            % coming from BICGSTAB, CGS, GMRES, MINRES, PCG or SYMMLQ
            % with the call always afun(P1,P2,...,PN)
            % or a request for A'*x coming from
            % BICG, LSQR and QMR in the afun(x,P1,P2,...,PN,'transp') case
            y = afun(x,varargin{:});
        end
%     catch ME
%         error(message('MATLAB:iterapp:InvalidInput', atype,afcnstr, ME.message));
%     end

%     if ~iscolumn(y)
%         error(message('MATLAB:iterapp:MustReturnColumn', atype, afcnstr));
%     end
end


% specify_parameters.m
%
% Run this program first to set up parameters for each data run.  The run
% parameters are stored in the file "CD_run_params.mat" in the current
% directory.  The program "extract_data.m" reads this file and adds some
% fixed radar parameters to the file.  Subsequent programs can read this
% file to obtain the parameters needed for the SAR processing.
%
% The radar data are stored on the CD supplied with the book, but they
% can be read from a disk file copied from the CD to your hard drive.
%
% The only file needed from the CD is "dat_01.001", which contains the
% radar data as well as the chirp replica and auxiliary data for each range
% line.  As none of the parameters like PRF and range gate delay change in
% this data set, and the replica is well defined by a linear FM chirp, the
% only data that are really needed from the CD is the raw radar signal data
% contained in "dat_01.001".  The radar parameters are stored in the
% program "extract_data.m".
%
% The radar data can be written in one block, or broken up into a number of
% blocks, with a set of files for each block.
%
% The first range cell and the number of range cells can be set to any
% value within the boundaries of the data array.  The first range line
% should be set to 1 plus a multiple of 8, and the number of lines per
% block set to a factor of 8.  Also, the number of lines should be set to a
% multiple of the number of lines per block.  If these rules are not
% obeyed, the "extract_data.m" program will quantize the values accordingly.

% Parameters to specify for each run:
% -----------------------------------
% input_path    : location of the radar data file 'dat_01.001'
% output_path   : location for the extracted data files
% output_prefix : prefix to the extracted data file names
%
% first_rg_cell : first range cell to extract
% Nrg_cells     : number of range cells to extract
% first_rg_line : first range line (azimuth sample) to extract
% Nrg_lines     : number of range lines to extract
% Nrg_lines_blk : number of range lines per block
% UseMATfiles   : Set to 0 if you want binary header, data, aux and replica
%                 files (.DAT) rather than just the MATLAB data files (.MAT)
% -------------------------------------------------------------------------
% Created :   Nov 29, 2004 by Kaan Ersahin
% Modified:   Nov 30, 2004 by Kaan Ersahin
% Modified:   Dec 3,  2004 by Ian Cumming
%             - moved fixed parameters to "extract_data.m"
%             - now use a fixed parameter file name for all programs
%             - added UseMATfiles option (=1 for MAT files)
% -------------------------------------------------------------------------

clear,   home,   format compact

% Define location of data files
% input_path      = 'Y:\RSAT\scene01\'; % These values are for runs at UBC
% output_path     = 'Y:\RSAT\EXTRACTED_DATA\';
input_path        = '.\scene01\';
output_path       = '.\scene01\';
CD_data_file_name = 'dat_01.001';
output_prefix     = 'raw';

%==========================================================================
%  Define area of interest of the radar data to be extracted
%  Note that the azimuth parameters are quantized in "extract_data.m"
%
%  Here are some possible values for first_rg_cell and first_rg_line:
%  For coal & ferry terminals, use range =  970, azimuth =  1801
%  For Vancouver airport,      use range = 1060, azimuth =  5561
%  For UBC and one ship,       use range =  760, azimuth =  7097
%  For Stanley Park & city,    use range = 1850, azimuth =  7657
%  For English Bay ships,      use range = 1050, azimuth =  7769
%  For Squamish & Garibaldi,   use range = 2640, azimuth = 16169
%  For Brackendale,            use range = 2800, azimuth = 17897 (max az)

%                              use range = 1350, azimuth =  3170

first_rg_cell   =  1050;    % Define the range limits
first_rg_line   =  7769;    % Define the azimuth limits  (19432 max)
Nrg_cells       =  2048;    % Suggest 2048 cells
Nrg_lines_blk   =  6*256;   % Suggest 1536, it should be larger than the
                            %        size of the azimuth match filter (705)
                            %              so that an image can be created.
Nrg_lines   =  1*Nrg_lines_blk;

UseMATfiles =  1; % (1) Use   MAT  files to save the extracted data
                  % (0) Use binary files to save the extracted data
SaveV6      =  0; % (1) Save data in MATLAB v6 format when using v7
                  % (0) Save data in MATLAB v7 format
                  % This variable is only used if you are running MATLAB 7
%==========================================================================

%  Save the data and run parameters in a matlab data file (*.mat)

vv = version;   vers = str2num(vv(1));  % Find MATLAB version
if vers == 6,   SaveV6 = 0;   end

if SaveV6
  save -v6 CD_run_params
  fprintf('\nData parameters written to:  CD_run_params.mat  in V6 format')
else
  save CD_run_params
  fprintf('\nData parameters written to:  CD_run_params.mat')
end

fprintf('\nNow run "extract_data.m"\n\n')
beep,   pause(0.4),   beep

%% This setup program is now finished, but you can add calls to subsequent
%%  data extraction and processing programs below, if desired.

% extract_data           % Extract the SAR data from the CD

% compute_azim_spectra   % Find the baseband Doppler centroid

% compress_data          % Perform SAR processing


function SaveParamsAsNIfTI(paramsfile, roifile, targetfile, outputpref)
%
% function SaveParamsAsNIfTI(paramsfile, roifile, targetfile, outputpref)
%
% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
%

% load the fitting results
fprintf('loading the fitted parameters from : %s\n', paramsfile);
load(paramsfile);

% load the roi file
fprintf('loading the roi from : %s\n', roifile);
load(roifile);

% load the target volume
fprintf('loading the target volume : %s\n', targetfile);
target = nifti(targetfile);
xsize = target.dat.dim(1);
ysize = target.dat.dim(2);
if length(target.dat.dim) == 2
    zsize = 1;
else
    zsize = target.dat.dim(3);
end
total = xsize*ysize*zsize;

% determine the volumes to be saved
% the number of fitted parameters minus the two fibre orientation
% parameters.
idxOfFitted = find(model.GD.fixed(1:end-2)==0);
noOfVols = length(idxOfFitted);
vols = zeros(total,noOfVols);
% the volume for the objective function values
fobj_ml_vol = zeros(total,1);
% the volume for the error code
error_code_vol = zeros(total,1);
% some special cases
if (strfind(model.name, 'Watson'))
    idxOfKappa = find(ismember(model.paramsStr, 'kappa')==1);
    odi_vol = zeros(total,1);
end

% the volumes for the fibre orientations
fibredirs_x_vol = zeros(total,1);
fibredirs_y_vol = zeros(total,1);
fibredirs_z_vol = zeros(total,1);
% compute the fibre orientations from the estimated theta and phi.
fibredirs = GetFibreOrientation(model.name, mlps);

% determine the volumes with MCMC fitting to be saved
if (model.noOfStages==3)
    idxOfFittedMCMC = find(model.MCMC.fixed(1:end-2)==0);
    noOfVolsMCMC = length(idxOfFittedMCMC);
    volsMCMC = zeros(total,noOfVolsMCMC);

    if (strfind(model.name, 'Watson'))
        idxOfKappa = find(ismember(model.paramsStr, 'kappa')==1);
	     if (model.MCMC.fixed(idxOfKappa)==0)
            odi_volMCMC = zeros(total,1);
        end
    end
end

% convert to volumetric maps
fprintf('converting the fitted parameters into volumetric maps ...\n');
for i=1:size(mlps,1)
    % compute the index to 3D
    volume_index = (idx(i,3)-1)*ysize*xsize + (idx(i,2)-1)*xsize + idx(i,1);

    % fitted parameters other than the fiber orientations
    for j=1:length(idxOfFitted)
        vols(volume_index,j) = mlps(i, idxOfFitted(j));
    end

    % objective function values
    fobj_ml_vol(volume_index) = fobj_ml(i);

    % error codes
    error_code_vol(volume_index) = error_code(i);

    % fiber orientations
    fibredirs_x_vol(volume_index) = fibredirs(1,i);
    fibredirs_y_vol(volume_index) = fibredirs(2,i);
    fibredirs_z_vol(volume_index) = fibredirs(3,i);

    % special cases
    if (strfind(model.name, 'Watson'))
        odi_vol(volume_index) = atan2(1, mlps(i,idxOfKappa)*10)*2/pi;
    end

	 % MCMC fitted parameters
    if (model.noOfStages==3)
        for j=1:length(idxOfFittedMCMC)
            volsMCMC(volume_index,j) = mean(squeeze(mcmcps(i,:,j)));
        end
        if (strfind(model.name, 'Watson'))
            % Warning: Here we hard-coded the index to kappa!!!
            odi_volMCMC(volume_index) = atan2(1, mean(squeeze(mcmcps(i,:,3)))*10)*2/pi;
        end
    end

end

% save as NIfTI
fprintf('Saving the volumetric maps of the fitted parameters ...\n');

niftiSpecs.dim = [xsize ysize zsize];
niftiSpecs.mat = target.mat;
niftiSpecs.mat_intent = target.mat_intent;
niftiSpecs.mat0 = target.mat0;
niftiSpecs.mat0_intent = target.mat0_intent;

% the fitted parameters other than the fiber orientations
for i=1:length(idxOfFitted)
    output = [outputpref '_' cell2mat(model.paramsStr(idxOfFitted(i))) '.nii'];
    SaveAsNIfTI(reshape(squeeze(vols(:,i)), [xsize ysize zsize]), niftiSpecs, output);
end

% the special cases
if (strfind(model.name, 'Watson'))
    output = [outputpref '_' 'odi.nii'];
    SaveAsNIfTI(reshape(odi_vol, [xsize ysize zsize]), niftiSpecs, output);
end

% the objective function values
output = [outputpref '_' 'fmin.nii'];
SaveAsNIfTI(reshape(fobj_ml_vol, [xsize ysize zsize]), niftiSpecs, output);

% the error codes
output = [outputpref '_' 'error_code.nii'];
SaveAsNIfTI(reshape(error_code_vol, [xsize ysize zsize]), niftiSpecs, output);

% the fibre orientations
output = [outputpref '_' 'fibredirs_xvec.nii'];
SaveAsNIfTI(reshape(fibredirs_x_vol, [xsize ysize zsize]), niftiSpecs, output);
output = [outputpref '_' 'fibredirs_yvec.nii'];
SaveAsNIfTI(reshape(fibredirs_y_vol, [xsize ysize zsize]), niftiSpecs, output);
output = [outputpref '_' 'fibredirs_zvec.nii'];
SaveAsNIfTI(reshape(fibredirs_z_vol, [xsize ysize zsize]), niftiSpecs, output);

% the MCMC fitted parameters
if (model.noOfStages==3)
    for i=1:length(idxOfFittedMCMC)
        output = [outputpref '_' cell2mat(model.paramsStr(idxOfFittedMCMC(i))) '_MCMC.nii'];
        SaveAsNIfTI(reshape(squeeze(volsMCMC(:,i)), [xsize ysize zsize]), niftiSpecs, output);
    end
    if (strfind(model.name, 'Watson'))
        output = [outputpref '_' 'odi_MCMC.nii'];
        SaveAsNIfTI(reshape(odi_volMCMC, [xsize ysize zsize]), niftiSpecs, output);
    end
end


function O = img_hist2(subdir)
% A general function for plotting histograms of any image
% For each subject, comparing across subjects
%
% :Inputs:
%
%   **imgname:**
%        name of image file to make intensity histograms from
%
%   **subdir:**
%        cell array of text strings containing names of individual subject
%        directories (wherein are contained the file specified in imgname
%        or each subject)
%
% Performs the histogram plot a number of times, without plotting
% and reports the variance in pdf moments as a function of subject,
% run, and condition (beta img within run).
%
% Start in directory above individual subject results
%
% :Examples:
% ::
%
%    img_hist2(EXPT.subjects)
%    img_hist2({'020827mk' '020829jh' '020903lb'})
%
% ..
% Tor Wager
% ..

% ..
%    defaults
% ..
dwcard = '02*';									% wildcard defining ind subject directories, e.g., '02*'
%csfname = 'rnnhet1spgr_seg3.img';	% reslice first to space of functionals
%grname = 'rnnhet1spgr_seg1.img';
%csfpath = '/data/placebo/';		% before ind subject
%csfp2 = 'anatomy';							% after ind subject

Pc = getcsfname(subdir);
PP = getimgname;

[dummy,txtlab] = fileparts(Pc(1,:));

% rows = subjects
% cols = moment
%
% rows = subjects
% cols = runs
% 3d   = beta (condition)

for condition = 1:size(PP,1)
   for run = 1:size(PP,2)

       fprintf(1,'%s\n ',PP{condition,run})
       % hP = get_filename(dwcard,PP{condition,run});
	hP = tor_list_files(subdir,PP{condition,run});
 	hP = str2mat(hP(:));
       csfM = spm_general_hist(hP,Pc,txtlab,0);

       % Mean, Std, skeW, Kurtosis
       O.m(:,run,condition) = csfM(:,1);
       O.s(:,run,condition) = csfM(:,2);
       O.w(:,run,condition) = csfM(:,3);
       O.k(:,run,condition) = csfM(:,4);

   end
end

fprintf(1,'\n ')

diary img_hist2.out

disp(['EXPERIMENT: ' pwd]);disp('')

[O.subjM,O.Mtotalv] = displayme(O.m,txtlab,'MEANS');disp('')
[O.subjS,O.Stotalv] = displayme(O.s,txtlab,'STD');disp('')
[O.subjW,O.Wtotalv] = displayme(O.w,txtlab,'SKEWNESS');disp('')
[O.subjK,O.Ktotalv] = displayme(O.k,txtlab,'KURTOSIS');disp('')

diary off

keyboard

return

function Pc = getcsfname(subdir)

doseg = input('Do anatomical images need to be segmented? (1/0)');
if doseg
    % get the list of csf images for each subject
    myp = spm_get(1,'*img',['Choose anatomical img for ' subdir{1} '-  Others should have similar path.']);
    [d f e] = fileparts(myp);
    disp([myp])
    %subc = input('Enter subject code part of this path (replaced for all subjects): ','s');
    x = findstr(d,subdir{1});
    [d2 f2] = fileparts(d(x:end));
    d = d(1:x-1);
    % use d, subdir, and f2 as path
    Pc = fullfile(d,subdir{1},f2,[f e]);

    for i = 2:length(subdir)
        Pc = str2mat(Pc,fullfile(d,subdir{i},f2,[f e]));
    end

    try
        V = spm_vol(Pc);
    catch
        Pc
        disp('Error loading images!')
        keyboard
    end

    disp('Images must be resliced to space of functionals.')
    fname = spm_get(1,'*img','Choose a functional image from this study.');
    reslice_imgs(fname,Pc,1);

    canonicalT1 = spm_get(1,'*img','Choose Template Image.');
    spm_segment(canonicalT1,'C')
end

% get the list of csf images for each subject
myp = spm_get(1,'*img',['Choose csf mask (in space of functionals) for ' subdir{1} '-  Others should have similar path.']);
[d f e] = fileparts(myp);
disp([myp])
%subc = input('Enter subject code part of this path (replaced for all subjects): ','s');
x = findstr(d,subdir{1});
[d2 f2] = fileparts(d(x:end));
d = d(1:x-1);
% use d, subdir, and f2 as path
Pc = fullfile(d,subdir{1},f2,[f e]);

for i = 2:length(subdir)
    Pc = str2mat(Pc,fullfile(d,subdir{i},f2,[f e]));
end

return

function PP = getimgname

% get the list of betas within runs
mypwd = pwd;
mydir = spm_get(-1,'*','Choose an individual subject SPM results dir');
eval(['cd ' mydir])
d = dir(['beta*img']);
load SPM
P = str2mat(d.name);
ind = 1;
for i = 1:length(Sess)
    for j = 1:length(Sess{i}.col)
        PP{j,i} = deblank(P(ind,:));
        ind = ind + 1;
    end
end
eval(['cd ' mypwd])

return

function a = getmeans(a,d1,d2)
% input mat, dim to avg over, 2nd dim to avg over

a = squeeze(mean(mean(a,d1),d2));
if size(a,2) > size(a,1), a = a';, end

return

function [subjM,Mtotalv] = displayme(mm,txtlab,tlab2)

gm = mean(mean(mean(mm)));
Mtotalv = sum((mm(:) - gm).^2);

disp(['Variability across ' tlab2 ' within mask: ' txtlab])
disp(['Grand mean (over the experiment) is ' num2str(gm) ', SSt = ' num2str(Mtotalv)])

subjM = getmeans(mm,2,3);
Mexp = (prod(size(mm)) ./ size(mm,1)) * sum((subjM - mean(subjM)).^2);
dfb = size(mm,1) - 1; dfw = prod(size(mm)) - (dfb+1);
F = Mexp./(Mtotalv-Mexp);
fprintf(1,'SESSION\tm %3.2f\tstd %3.2f\t SSb %3.2f\t%%Var explained %3.2f\tF(%3.0f,%3.0f) = %3.2f\tp = %3.5f\n', ...
	mean(subjM),std(subjM),Mexp,100*(Mexp./Mtotalv),dfb,dfw,F,1-fcdf(F,dfb,dfw));

subjM = getmeans(mm,1,3);
Mexp = (prod(size(mm)) ./ size(mm,2)) * sum((subjM - mean(subjM)).^2);
dfb = size(mm,2) - 1; dfw = prod(size(mm)) - (dfb+1);
F = Mexp./(Mtotalv-Mexp);
fprintf(1,'RUN\tm %3.2f\tstd %3.2f\t SSb %3.2f\t%%Var explained %3.2f\tF(%3.0f,%3.0f) = %3.2f\tp = %3.5f\n', ...
	mean(subjM),std(subjM),Mexp,100*(Mexp./Mtotalv),dfb,dfw,F,1-fcdf(F,dfb,dfw));

subjM = getmeans(mm,1,2);
Mexp = (prod(size(mm)) ./ size(mm,3)) * sum((subjM - mean(subjM)).^2);
dfb = size(mm,3) - 1; dfw = prod(size(mm)) - (dfb+1);
F = Mexp./(Mtotalv-Mexp);
fprintf(1,'CONDITION\tm %3.2f\tstd %3.2f\t SSb %3.2f\t%%Var explained %3.2f\tF(%3.0f,%3.0f) = %3.2f\tp = %3.5f\n', ...
	mean(subjM),std(subjM),Mexp,100*(Mexp./Mtotalv),dfb,dfw,F,1-fcdf(F,dfb,dfw));

return


function results = OTB_DEEP_settings(seq, res_path, bSaveImage, parameters)

close all

s_frames = seq.s_frames;

% Feature specific parameters
hog_params.cell_size = 4;
hog_params.compressed_dim = 10;

% grayscale_params.colorspace='gray';
% grayscale_params.cell_size = 1;
%
% cn_params.tablename = 'CNnorm';
% cn_params.useForGray = false;
% cn_params.cell_size = 4;
% cn_params.compressed_dim = 3;
%
% ic_params.tablename = 'intensityChannelNorm6';
% ic_params.useForColor = false;
% ic_params.cell_size = 4;
% ic_params.compressed_dim = 3;

cnn_params.nn_name = 'imagenet-vgg-m-2048.mat'; % Name of the network
cnn_params.output_layer = [3 14];               % Which layers to use
cnn_params.downsample_factor = [2 1];           % How much to downsample each output layer
cnn_params.compressed_dim = [16 64];            % Compressed dimensionality of each output layer
cnn_params.input_size_mode = 'adaptive';        % How to choose the sample size
cnn_params.input_size_scale = 1;                % Extra scale factor of the input samples to the network (1 is no scaling)

% Which features to include
params.t_features = {
    struct('getFeature',@get_cnn_layers, 'fparams',cnn_params),...
    struct('getFeature',@get_fhog,'fparams',hog_params),...
    ...struct('getFeature',@get_colorspace, 'fparams',grayscale_params),...
    ...struct('getFeature',@get_table_feature, 'fparams',cn_params),...
    ...struct('getFeature',@get_table_feature, 'fparams',ic_params),...
};

% Global feature parameters1s
params.t_global.normalize_power = 2;    % Lp normalization with this p
params.t_global.normalize_size = true;  % Also normalize with respect to the spatial size of the feature
params.t_global.normalize_dim = true;   % Also normalize with respect to the dimensionality of the feature

% Image sample parameters
params.search_area_shape = 'square';    % The shape of the samples
params.search_area_scale = 4.5;         % The scaling of the target size to get the search area
params.min_image_sample_size = 200^2;   % Minimum area of image samples
params.max_image_sample_size = 300^2;   % Maximum area of image samples

% Detection parameters
params.refinement_iterations = 1;       % Number of iterations used to refine the resulting position in a frame
params.newton_iterations = 5;           % The number of Newton iterations used for optimizing the detection score
params.clamp_position = false;          % Clamp the target position to be inside the image

% Learning parameters
params.output_sigma_factor = 1/12;		% Label function sigma
params.learning_rate = 0.011;	 	 	% Learning rate
params.nSamples = 50;                   % Maximum number of stored training samples
params.sample_replace_strategy = 'lowest_prior';    % Which sample to replace when the memory is full
params.lt_size = 0;                     % The size of the long-term memory (where all samples have equal weight)
params.train_gap = 5;                   % The number of intermediate frames with no training (0 corresponds to training every frame)
params.skip_after_frame = 1;            % After which frame number the sparse update scheme should start (1 is directly)
params.use_detection_sample = true;     % Use the sample that was extracted at the detection stage also for learning

% Factorized convolution parameters
params.use_projection_matrix = true;    % Use projection matrix, i.e. use the factorized convolution formulation
params.update_projection_matrix = true; % Whether the projection matrix should be optimized or not
params.proj_init_method = 'pca';        % Method for initializing the projection matrix
params.projection_reg = 2e-8;	 	 	% Regularization paremeter of the projection matrix

% Generative sample space model parameters
params.use_sample_merge = true;                 % Use the generative sample space model to merge samples
params.sample_update_criteria = 'Merge';        % Strategy for updating the samples
params.weight_update_criteria = 'WeightedAdd';  % Strategy for updating the distance matrix
params.neglect_higher_frequency = false;        % Neglect hiigher frequency components in the distance comparison for speed

% Conjugate Gradient parameters
params.CG_iter = 5;                     % The number of Conjugate Gradient iterations in each update after the first frame
params.init_CG_iter = 10*20;            % The total number of Conjugate Gradient iterations used in the first frame
params.init_GN_iter = 10;               % The number of Gauss-Newton iterations used in the first frame (only if the projection matrix is updated)
params.CG_use_FR = false;               % Use the Fletcher-Reeves (true) or Polak-Ribiere (false) formula in the Conjugate Gradient
params.CG_standard_alpha = true;        % Use the standard formula for computing the step length in Conjugate Gradient
params.CG_forgetting_rate = 80;	 	 	% Forgetting rate of the last conjugate direction
params.precond_data_param = 0.3;	 	% Weight of the data term in the preconditioner
params.precond_reg_param = 0.02;	 	% Weight of the regularization term in the preconditioner
params.precond_proj_param = 75;	 	 	% Weight of the projection matrix part in the preconditioner

% Regularization window parameters
params.use_reg_window = true;           % Use spatial regularization or not
params.reg_window_min = 1e-4;			% The minimum value of the regularization window
params.reg_window_edge = 10e-3;         % The impact of the spatial regularization
params.reg_window_power = 2;            % The degree of the polynomial to use (e.g. 2 is a quadratic window)
params.reg_sparsity_threshold = 0.05;   % A relative threshold of which DFT coefficients that should be set to zero

% Interpolation parameters
params.interpolation_method = 'bicubic';    % The kind of interpolation kernel
params.interpolation_bicubic_a = -0.75;     % The parameter for the bicubic interpolation kernel
params.interpolation_centering = true;      % Center the kernel at the feature sample
params.interpolation_windowing = false;     % Do additional windowing on the Fourier coefficients of the kernel

% Scale parameters for the translation model
% Only used if: params.use_scale_filter = false
params.number_of_scales = 5;            % Number of scales to run the detector
params.scale_step = 1.02;               % The scale factor

% Scale filter parameters
% Only used if: params.use_scale_filter = true
params.use_scale_filter = false;        % Use the fDSST scale filter or not (for speed)
% params.scale_sigma_factor = 1/16;       % Scale label function sigma
% params.scale_learning_rate = 0.025;		% Scale filter learning rate
% params.number_of_scales_filter = 17;    % Number of scales
% params.number_of_interp_scales = 33;    % Number of interpolated scales
% params.scale_model_factor = 1.0;        % Scaling of the scale model
% params.scale_step_filter = 1.02;        % The scale factor for the scale filter
% params.scale_model_max_area = 32*16;    % Maximume area for the scale sample patch
% params.scale_feature = 'HOG4';          % Features for the scale filter (only HOG4 supported)
% params.s_num_compressed_dim = 'MAX';    % Number of compressed feature dimensions in the scale filter
% params.lambda = 1e-2;					% Scale filter regularization
% params.do_poly_interp = true;           % Do 2nd order polynomial interpolation to obtain more accurate scale

% Other parameters
params.visualization = 0;               % Visualiza tracking and detection scores
params.debug = 0;                       % Do full debug visualization

% Initialize
params.init_sz = [seq.init_rect(1,4), seq.init_rect(1,3)];
params.init_pos = [seq.init_rect(1,2), seq.init_rect(1,1)] + (params.init_sz - 1)/2;
params.s_frames = s_frames;

% Run tracker
results = tracker(params);


function y = snakeindex(IDX)
% SNAKEINDEX  Create index for adpative interpolating the snake
%     y = snakeindex(IDX)
%

N = length(IDX);
y=1:0.5:N+0.5;
x=1:N;
y(2*x(IDX==0))=[];