function [g1, g2] = lfmaXlfmKernGradient(lfmKern1, lfmKern2, t1, t2, covGrad, meanVector)

% LFMAXLFMKERNGRADIENT Compute a cross gradient between a LFMA and a LFM.
% FORMAT
% DESC computes cross gradient of parameters of a cross kernel
% between two lfm kernels, one lfm kernel corresponds to the accel. and
% the other corresponds to the position. It is supposed to be used together
% with the multiple output kernel.
% ARG lfmKern1 : the kernel structure associated with the first LFM
% kernel (acceleration).
% ARG lfmKern2 : the kernel structure associated with the second LFM
% kernel (position).
% ARG t1 : inputs for which kernel is to be computed.
% ARG covGrad : gradient of the objective function with respect to
% the elements of the cross kernel matrix.
% RETURN g1 : gradient of the parameters of the first kernel, for
% ordering see lfmKernExtractParam.
% RETURN g2 : gradient of the parameters of the second kernel, for
% ordering see lfmKernExtractParam.
%
% FORMAT
% DESC computes cross gradient of parameters of a cross kernel
% between two lfm kernels, one lfm kernel corresponds to the accel. and
% the other corresponds to the position. It is supposed to be used together
% with the multiple output kernel.
% ARG lfmKern1 : the kernel structure associated with the first LFM
% kernel (acceleration).
% ARG lfmKern2 : the kernel structure associated with the second LFM
% kernel (position).
% ARG t1 : row inputs for which kernel is to be computed.
% ARG t2 : column inputs for which kernel is to be computed.
% ARG covGrad : gradient of the objective function with respect to
% the elements of the cross kernel matrix.
% RETURN g1 : gradient of the parameters of the first kernel, for
% ordering see lfmKernExtractParam.
% RETURN g2 : gradient of the parameters of the second kernel, for
% ordering see lfmKernExtractParam.
%
% FORMAT
% DESC computes cross gradient of parameters of a cross kernel
% between two lfm kernels, one lfm kernel corresponds to the accel. and
% the other corresponds to the position. It is supposed to be used together
% with the multiple output kernel.
% ARG lfmKern1 : the kernel structure associated with the first LFM
% kernel (acceleration).
% ARG lfmKern2 : the kernel structure associated with the second LFM
% kernel (position).
% ARG t1 : row inputs for which kernel is to be computed.
% ARG t2 : column inputs for which kernel is to be computed.
% ARG covGrad : gradient of the objective function with respect to
% the elements of the cross kernel matrix.
% ARG meanVec : precomputed factor that is used for the switching dynamical
% latent force model.
% RETURN g1 : gradient of the parameters of the first kernel, for
% ordering see lfmKernExtractParam.
% RETURN g2 : gradient of the parameters of the second kernel, for
% ordering see lfmKernExtractParam.
%
% SEEALSO : multiKernParamInit, multiKernCompute, lfmvKernParamInit
%
% COPYRIGHT : Mauricio Alvarez, 2010

% KERN

subComponent = false; % This is just a flag that indicates if this kernel is part of a bigger kernel (SDLFM)

if nargin == 4
    covGrad = t2;
    t2 = t1;
elseif nargin == 6
    subComponent = true;
    if numel(meanVector)>1
        if size(meanVector,1) == 1,
            if size(meanVector, 2)~=size(covGrad, 2)
                error('The dimensions of meanVector don''t correspond to the dimensions of covGrad')
            end
        else
            if size((meanVector'), 2)~=size(covGrad,2)
                error('The dimensions of meanVector don''t correspond to the dimensions of covGrad')
            end
        end
    else
        if numel(t1)==1 && numel(t2)>1
            % matGrad will be row vector and so should be covGrad
            dimcovGrad = length(covGrad);
            covGrad = reshape(covGrad, [1 dimcovGrad]);
        elseif numel(t1)>1 && numel(t2)==1
            % matGrad will be column vector and sp should be covGrad
            dimcovGrad = length(covGrad);
            covGrad = reshape(covGrad, [dimcovGrad 1]);
        end
    end
end

if size(t1, 2) > 1 || size(t2, 2) > 1
    error('Input can only have one column');
end
if lfmKern1.inverseWidth ~= lfmKern2.inverseWidth
    error('Kernels cannot be cross combined if they have different inverse widths.')
end

% Parameters of the simulation (in the order providen by kernExtractParam)

m = [lfmKern1.mass lfmKern2.mass];                  % Par. 1
D = [lfmKern1.spring lfmKern2.spring];              % Par. 2
C = [lfmKern1.damper lfmKern2.damper];              % Par. 3
sigma2 = 2/lfmKern1.inverseWidth;                   % Par. 4
sigma = sqrt(sigma2);
S = [lfmKern1.sensitivity lfmKern2.sensitivity];    % Par. 5

alpha = C./(2*m);
omega = sqrt(D./m-alpha.^2);

% Initialization of vectors and matrices

g1 = zeros(1,5);
g2 = zeros(1,5);

% Precomputations
computeH  = cell(4,1);
computeUpsilonMatrix = cell(2,1);
computeUpsilonVector = cell(2,1);
gradientUpsilonMatrix = cell(4,1);
gradientUpsilonVector = cell(4,1);
gamma1_p = alpha(1) + j*omega(1);
gamma1_m = alpha(1) - j*omega(1);
gamma2_p = alpha(2) + j*omega(2);
gamma2_m = alpha(2) - j*omega(2);
preExp1 = zeros(length(t1),2);
preExp2 = zeros(length(t2),2);
preExpg1 = zeros(length(t1),2);
preExpgg1 = zeros(length(t1),2);
preExpt1 = zeros(length(t1),2);
preExpt2 = zeros(length(t2),2);
preGamma(1) = gamma1_p + gamma2_p;
preGamma(2) = gamma1_p + gamma2_m;
preGamma(3) = gamma1_m + gamma2_p;
preGamma(4) = gamma1_m + gamma2_m;
preGamma2 = preGamma.^2;
preConst = 1./preGamma;
preConst2 = 1./(preGamma2);
preFactors(1) = preConst(2) - preConst(1);
preFactors(2) = preConst(3) - preConst(4);
preFactors(3) = preConst(3) - preConst(1);
preFactors(4) = preConst(2) - preConst(4);
preFactors2(1) = -preConst2(2) + preConst2(1);
preFactors2(2) = -preConst2(3) + preConst2(4);
preFactors2(3) = -preConst2(3) + preConst2(1);
preFactors2(4) = -preConst2(2) + preConst2(4);
preExp1(:,1) = exp(-gamma1_p*t1);
preExp1(:,2) = exp(-gamma1_m*t1);
preExp2(:,1) = exp(-gamma2_p*t2);
preExp2(:,2) = exp(-gamma2_m*t2);
preExpg1(:,1) = (2*gamma1_p)*preExp1(:,1);
preExpg1(:,2) = (2*gamma1_m)*preExp1(:,2);
preExpgg1(:,1) = (gamma1_p^2)*preExp1(:,1);
preExpgg1(:,2) = (gamma1_m^2)*preExp1(:,2);
preExpt1(:,1) = t1.*preExpgg1(:,1);
preExpt1(:,2) = t1.*preExpgg1(:,2);
preExpt2(:,1) = t2.*exp(-gamma2_p*t2);
preExpt2(:,2) = t2.*exp(-gamma2_m*t2);
[computeH{1}, computeUpsilonMatrix{1}, computeUpsilonMatrixLocal{1}] =  lfmComputeH3AP(gamma1_p, gamma1_m, sigma2, t1,t2,preFactors([1 2]), 0);
[computeH{2}, computeUpsilonMatrix{2}, computeUpsilonMatrixLocal{2}] =  lfmComputeH3AP(gamma2_p, gamma2_m, sigma2, t2,t1,preFactors([3 4]), 1);
[computeH{3}, computeUpsilonVector{1}, computeUpsilonVectorLocal{1}] =  lfmComputeH4AP(gamma1_p, gamma1_m, sigma2, t1, preGamma([1 2 4 3]), preExp2, 0 );
[computeH{4}, computeUpsilonVector{2}, computeUpsilonVectorLocal{2}] =  lfmComputeH4AP(gamma2_p, gamma2_m, sigma2, t2, preGamma([1 3 4 2]), preExpgg1, 1 );
preKernel = ( computeH{1} + computeH{2}.' + computeH{3} + computeH{4}.');

% Precompute derivatives
gradientUpsilonMatrix{1} = lfmapGradientUpsilonMatrix(gamma1_p,sigma2,t1, t2, 0, computeUpsilonMatrixLocal{1}{1});
gradientUpsilonMatrix{2} = lfmapGradientUpsilonMatrix(gamma1_m,sigma2,t1, t2, 0, computeUpsilonMatrixLocal{1}{2});
gradientUpsilonMatrix{3} = lfmapGradientUpsilonMatrix(gamma2_p,sigma2,t2, t1, 1, computeUpsilonMatrixLocal{2}{1});
gradientUpsilonMatrix{4} = lfmapGradientUpsilonMatrix(gamma2_m,sigma2,t2, t1, 1, computeUpsilonMatrixLocal{2}{2});
gradientUpsilonVector{1} = lfmapGradientUpsilonVector(gamma1_p,sigma2,t1, computeUpsilonVectorLocal{1}{1});
gradientUpsilonVector{2} = lfmapGradientUpsilonVector(gamma1_m,sigma2,t1, computeUpsilonVectorLocal{1}{2});
gradientUpsilonVector{3} = lfmGradientUpsilonVector(gamma2_p,sigma2,t2);
gradientUpsilonVector{4} = lfmGradientUpsilonVector(gamma2_m,sigma2,t2);

if lfmKern1.isNormalised
    K0 =  lfmKern1.sensitivity*lfmKern2.sensitivity/(8*sqrt(2)*lfmKern1.mass*lfmKern2.mass*prod(omega));
    K02 = 1/(8*sqrt(2)*prod(m)*prod(omega));
else
    K0 =  sigma*sqrt(pi)*lfmKern1.sensitivity*lfmKern2.sensitivity/(8*lfmKern1.mass*lfmKern2.mass*prod(omega));
    K02 = sigma*sqrt(pi)/(8*prod(m)*prod(omega));
end

% Gradient with respect to m, D and C
for ind_theta = 1:3 % Parameter (m, D or C)
    for ind_par = 0:1 % System (1 or 2)
        % Choosing the right gradients for m, omega, gamma1 and gamma2
        switch ind_theta
            case 1  % Gradient wrt m
                gradThetaM = [1-ind_par ind_par];
                gradThetaAlpha = -C./(2*(m.^2));
                gradThetaOmega = (C.^2-2*m.*D)./(2*(m.^2).*sqrt(4*m.*D-C.^2));
            case 2  % Gradient wrt D
                gradThetaM = zeros(1,2);
                gradThetaAlpha = zeros(1,2);
                gradThetaOmega = 1./sqrt(4*m.*D-C.^2);
            case 3  % Gradient wrt C
                gradThetaM = zeros(1,2);
                gradThetaAlpha = 1./(2*m);
                gradThetaOmega = -C./(2*m.*sqrt(4*m.*D-C.^2));
        end
        gradThetaGamma1 = gradThetaAlpha + j*gradThetaOmega;
        gradThetaGamma2 = gradThetaAlpha - j*gradThetaOmega;
        % Gradient evaluation
        gradThetaGamma11 = [gradThetaGamma1(1) gradThetaGamma2(1)];
        gradThetaGamma2 = [gradThetaGamma1(2) gradThetaGamma2(2)];
        gradThetaGamma1 = gradThetaGamma11;

        if ~ind_par % ind_par = k or d
            matGrad = K0 ...
                * ( lfmGradientH31( preFactors([1 2]), preFactors2([1 2]), gradThetaGamma1, ...
                gradientUpsilonMatrix{1}, gradientUpsilonMatrix{2}, computeUpsilonMatrix{1}{1}, ...
                computeUpsilonMatrix{1}{2}, 1) + ...
                lfmGradientH32( preGamma2,  gradThetaGamma1, computeUpsilonMatrix{2}{1}, ...
                computeUpsilonMatrix{2}{2}, 1).' + ...
                lfmGradientH41( preGamma, preGamma2, gradThetaGamma1, preExp2, ...
                gradientUpsilonVector{1}, gradientUpsilonVector{2}, computeUpsilonVector{1}{1},...
                computeUpsilonVector{1}{2}, 1) + ...
                lfmGradientH42AP(preGamma, preGamma2, gradThetaGamma1, preExpg1, preExpgg1, preExpt1, ...
                computeUpsilonVector{2}{1}, computeUpsilonVector{2}{2}).'...
                - (gradThetaM(1+ind_par)/m(1+ind_par) ...
                + gradThetaOmega(1+ind_par)/omega(1+ind_par)) ...
                *preKernel);
        else % ind_par = r or d'
            matGrad = K0 ...
                * ( lfmGradientH31( preFactors([3 4]), preFactors2([3 4]), gradThetaGamma2, ...
                gradientUpsilonMatrix{3}, gradientUpsilonMatrix{4}, computeUpsilonMatrix{2}{1}, ...
                computeUpsilonMatrix{2}{2}, 1).' + ...
                lfmGradientH32( preGamma2([1 3 2 4]),  gradThetaGamma2, computeUpsilonMatrix{1}{1}, ...
                computeUpsilonMatrix{1}{2}, 1) + ...
                lfmGradientH41( preGamma([1 3 2 4]), preGamma2([1 3 2 4]), gradThetaGamma2, preExpgg1, ...
                    gradientUpsilonVector{3}, gradientUpsilonVector{4}, computeUpsilonVector{2}{1},...
                    computeUpsilonVector{2}{2}, 1).' + ...
                lfmGradientH42(preGamma([1 3 2 4]), preGamma2([1 3 2 4]), gradThetaGamma2, preExp2, preExpt2, ...
                computeUpsilonVector{1}{1}, computeUpsilonVector{1}{2}, 1)...
                - (gradThetaM(1+ind_par)/m(1+ind_par) ...
                + gradThetaOmega(1+ind_par)/omega(1+ind_par)) ...
                *preKernel);
        end

        if subComponent
            if size(meanVector,1) ==1,
                matGrad = matGrad*meanVector;
            else
                matGrad = (meanVector*matGrad).';
            end
        end

        % Check the parameter to assign the derivative
        if ind_par == 0
            g1(ind_theta) = sum(sum(matGrad.*covGrad));
        else
            g2(ind_theta) = sum(sum(matGrad.*covGrad));
        end
    end
end

% Gradients with respect to sigma
if lfmKern1.isNormalised
    matGrad = K0*(lfmGradientSigmaH3AP(gamma1_p, gamma1_m, sigma2, t1, t2, preFactors([1 2]), 0)...
        +  lfmGradientSigmaH3AP(gamma2_p, gamma2_m, sigma2, t2, t1, preFactors([3 4]), 1).'...
        +  lfmGradientSigmaH4AP(gamma1_p, gamma1_m, sigma2, t1, preGamma([1 2 4 3]), preExp2, 0 )...
        +  lfmGradientSigmaH4AP(gamma2_p, gamma2_m, sigma2, t2, preGamma([1 3 4 2]), preExpgg1, 1 ).');
else
    matGrad = (prod(S)*sqrt(pi)/(8*prod(m)*prod(omega))) ...
        * (preKernel ...
        + sigma*(lfmGradientSigmaH3AP(gamma1_p, gamma1_m, sigma2, t1, t2, preFactors([1 2]), 0)...
        +  lfmGradientSigmaH3AP(gamma2_p, gamma2_m, sigma2, t2, t1, preFactors([3 4]), 1).'...
        +  lfmGradientSigmaH4AP(gamma1_p, gamma1_m, sigma2, t1, preGamma([1 2 4 3]), preExp2, 0 )...
        +  lfmGradientSigmaH4AP(gamma2_p, gamma2_m, sigma2, t2, preGamma([1 3 4 2]), preExpgg1, 1 ).' ));
end

if subComponent
    if size(meanVector,1) ==1,
        matGrad = matGrad*meanVector;
    else
        matGrad = (meanVector*matGrad).';
    end
end
g1(4) = sum(sum(matGrad.*covGrad))*(-(sigma^3)/4);
g2(4) = g1(4);

% Gradients with respect to S

matGrad = K02*preKernel;

if subComponent
    if size(meanVector,1) ==1,
        matGrad = matGrad*meanVector;
    else
        matGrad = (meanVector*matGrad).';
    end
end

g1(5) = sum(sum(S(2)*matGrad.*covGrad));
g2(5) = sum(sum(S(1)*matGrad.*covGrad));

g2(4) = 0; % Otherwise is counted twice, temporarly changed by Mauricio Alvarez

g1 = real(g1);
g2 = real(g2);


classdef ProductComputerOutputCreator < handle

    properties (Access = private)
        fourthOrder
        secondOrder
        secondOrderOut
    end

    methods (Access = public)

        function obj = ProductComputerOutputCreator(C,e)
            obj.init(C,e)
            obj.createSecondOrderOut()
        end

        function s = getSecondOrderOut(obj)
            s = obj.secondOrderOut;
        end
    end

    methods (Access = private)

        function init(obj,C,e)
            obj.fourthOrder = C;
            obj.secondOrder = e;
        end

        function createSecondOrderOut(obj)

            if obj.isTensor()
                if obj.is3D()
                    if obj.isStress()
                        s = Stress3DTensor;
                    elseif obj.isStrain()
                        s = Strain3DTensor;
                    end
                elseif obj.isPlaneStress()
                    if obj.isStress()
                        s = StressPlaneStressTensor;
                    elseif obj.isStrain()
                        s = StrainPlaneStressTensor;
                    end
                end
            elseif obj.isVoigt()
                if obj.is3D()
                    if obj.isStress()
                        s = Stress3DVoigtTensor();
                    elseif obj.isStrain()
                        s = Strain3DTensor;
                    end
                elseif obj.isPlaneStress()
                    if obj.isStress()
                        s = StressPlaneStressVoigtTensor;
                    elseif obj.isStrain()
                        s = StrainPlaneStressVoigtTensor;
                    end
                end
            end
            obj.secondOrderOut = s;

        end

        function itIs = isVoigt(obj)
            isFourthVoigt = strcmp(obj.fourthOrder.getRepresentation(),'voigt');
            isSecondVoigt = strcmp(obj.secondOrder.getRepresentation(),'voigt');
            itIs = isFourthVoigt && isSecondVoigt;
        end

        function itIs = isTensor(obj)
            isFourthVoigt = strcmp(obj.fourthOrder.getRepresentation(),'tensor');
            isSecondVoigt = strcmp(obj.secondOrder.getRepresentation(),'tensor');
            itIs = isFourthVoigt && isSecondVoigt;
        end

        function itIs = isStress(obj)
            isConstiutive = strcmp(obj.fourthOrder.getOrder(),'fourth');
            isStrian = strcmp(obj.secondOrder.getFieldName(),'strain');
            itIs = isConstiutive && isStrian;
        end

        function itIs = isStrain(obj)
            isConstiutive = strcmp(obj.fourthOrder.getOrder(),'fourth');
            isStress = strcmp(obj.secondOrder.getFieldName(),'stress');
            itIs = isConstiutive && isStress;
        end

        function itIs = is3D(obj)
            isFourth3D = strcmp(obj.fourthOrder.getElasticityCase(),'3D');
            isSecond3D = strcmp(obj.secondOrder.getElasticityCase(),'3D');
            itIs = isFourth3D && isSecond3D;
        end

        function itIs = isPlaneStress(obj)
            isFourthPS = strcmp(obj.fourthOrder.getElasticityCase(),'planeStress');
            isSecondPS = strcmp(obj.secondOrder.getElasticityCase(),'planeStress');
            itIs = isFourthPS && isSecondPS;
        end

    end

end


function c = demean(c)

   % DEMEAN removes the mean of each trace.
   %
   % C = DEMEAN(C) removes the DC offset from each trace. In most cases it is
   % unnecessary to call this function directly. By default, all traces are
   % demeaned and detrended when they are loaded into a correlation object.
   % This is one of the assumptions of the correlation toolbox.

   % Author: Michael West, Geophysical Institute, Univ. of Alaska Fairbanks
   % $Date$
   % $Revision$

   c.traces = demean(c.traces);
end


function [X, R] = imstack2vectors(S, MASK)
[M, N, n] = size(S);
if nargin == 1
   MASK = true(M, N);
else
   MASK = MASK ~= 0;
end

[I, J] = find(MASK);
R = [I, J];

Q = M*N;
X = reshape(S, Q, n);

MASK = reshape(MASK, Q, 1);

X = X(MASK, :);


function rf=lpcis2rf(is)
%LPCRF2IS Convert inverse sines to reflection coefficients RF=(IS)

%      Copyright (C) Mike Brookes 1997
%      Version: $Id: lpcis2rf.m,v 1.4 2007/05/04 07:01:38 dmb Exp $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

rf=sin(is*pi/2);


% SYNTAX:
% data_dod = hmrR_MotionCorrectSpline(data_dod, mlAct, tIncCh, p, turnon)
%
% UI NAME:
% Spline_Motion_Correction
%
% DESCRIPTION:
% Perform a cubic spline correction of the motion artifacts identified in
% tIncCh. The algorithm follows the procedure describe by
% Scholkmann et al., Physiol. Meas. 31, 649-662 (2010). Set p = -1 to skip
% this function.
%
% INPUTS:
% data_dod: SNIRF data structure containing delta_OD
% mlAct:
% tIncCh:   Matrix of included time points (1=included; 0=not included (movement)
%           The matrix is #time points x #channels and usually comes from
%           hmrR_MotionArtifactByChannel()
% p:        Parameter p used in the spline interpolation. The value
%           recommended in the literature is 0.99. Use -1 if you want to skip this
%           motion correction.
% turnon:   Optional argument to enable/disable this function in a processing stream chain
%
% OUTPUTS:
% dod:   SNIRF data structure containing delta_OD after spline interpolation correction,
%        same size as dod (Channels that are not in the active ml remain unchanged)
%
% USAGE OPTIONS:
% Spline_Motion_Correction: dod = hmrR_MotionCorrectSpline(dod, mlActAuto, tIncAutoCh, p, turnon)
%
% PARAMETERS:
% p: 0.99
% turnon: 1
%
% PREREQUISITES:
% Motion_Artifact_By_Channel: [tIncAuto, tIncAutoCh] = hmrR_MotionArtifactByChannel(dod, probe, mlActMan, tIncMan, tMotion, tMask, STDEVthresh, AMPthresh)
%
% LOG:
% created 01-26-2012, J. Selb
% modified 03/27/2019 by J. Dubb
%
% TO DO:
%
function data_dod = hmrR_MotionCorrectSpline(data_dod, mlAct, tIncCh, p, turnon)

if ~exist('turnon','var')
    turnon = 1;
end
if turnon==0
    return;
end

% Check input args
if isempty(mlAct)
    mlAct = cell(length(data_dod),1);
end
if isempty(tIncCh)
    tIncCh = cell(length(data_dod),1);
end
if p>1 || p<0    % if p outside its authorized range, exit with warning
    fprintf('Parameter has to be between 0 and 1. Returning with no correction\n');
    return;
end

for iBlk=1:length(data_dod)

    dod         = data_dod(iBlk).GetDataTimeSeries();
    t           = data_dod(iBlk).GetTime();
    MeasList    = data_dod(iBlk).GetMeasList();

    mlAct{iBlk} = mlAct_Initialize(mlAct{iBlk}, MeasList);
    lstAct = mlAct_Matrix2IndexList(mlAct{iBlk}, MeasList);

    tIncCh{iBlk} = tIncCh_Initialize(tIncCh{iBlk}, dod, MeasList);
    tIncChBlk    = tIncCh{iBlk}(1:length(t),:);

    fs = 1/mean(t(2:end)-t(1:end-1));

    % window widths limits for computing the mean in the segment shifts
    dtShort = 0.3;  % seconds
    dtLong  = 3;    % seconds

    dodSpline = dod;
    t = t(:);  % needs to be a column vector

    for ii = 1:length(lstAct)

        idx_ch = lstAct(ii);

        lstMA = find(tIncChBlk(:,idx_ch)==0);   % sublist of motion artifact segments

        if ~isempty(lstMA)

            % Find indexes of starts and ends of MA segments
            lstMs = find(diff(tIncChBlk(:,idx_ch))==-1);   % starting indexes of mvt segments
            lstMf = find(diff(tIncChBlk(:,idx_ch))==1);    % ending indexes of mvt segments

            % Case where there's a single MA segment, that either starts at the
            % beginning or ends at the end of the total time duration
            if isempty(lstMf)
                lstMf = size(tIncChBlk,1);
            end
            if isempty(lstMs)
                lstMs = 1;
            end
            % If any MA segment either starts at the beginning or
            % ends at the end of the total time duration
            if lstMs(1)>lstMf(1)
                lstMs = [1;lstMs];
            end
            if lstMs(end)>lstMf(end)
                lstMf(end+1,1) = size(tIncChBlk,1);
            end

            lstMl = lstMf-lstMs;    % lengths of MA segments
            nbMA = length(lstMl);   % number of MA segments

            % Do the spline interpolation on each MA segment
            % only include channels in the active meas list

            for jj = 1:nbMA
                lst = lstMs(jj):(lstMf(jj)-1);
                % spline interp
                SplInterp = csaps(t(lst)', dod(lst,idx_ch)', p, t(lst)')';
                % corrected signal = original signal - spline interpolation
                dodSpline(lst,idx_ch) = dod(lst,idx_ch) - SplInterp;
            end

            % Reconstruction of the whole time series (shift each segment)

            % First MA segment: shift to the previous noMA segment if it exists,
            % to the next noMA segment otherwise
            lst = (lstMs(1)):(lstMf(1)-1);
            SegCurrLength = lstMl(1);
            if SegCurrLength < dtShort*fs
                windCurr = SegCurrLength;
            elseif SegCurrLength < dtLong*fs
                windCurr = floor(dtShort*fs);
            else
                windCurr = floor(SegCurrLength/10);
            end

            if lstMs(1)>1
                SegPrevLength = length(1:(lstMs(1)-1));
                if SegPrevLength < dtShort*fs
                    windPrev = SegPrevLength;
                elseif SegPrevLength < dtLong*fs
                    windPrev = floor(dtShort*fs);
                else
                    windPrev = floor(SegPrevLength/10);
                end
                meanPrev = mean(dodSpline(lst(1)-windPrev:(lst(1)-1), idx_ch));
                meanCurr = mean(dodSpline(lst(1):(lst(1)+windCurr-1), idx_ch));
                dodSpline(lst,idx_ch) = dodSpline(lst,idx_ch) - meanCurr + meanPrev;

            else
                if length(lstMs)>1
                    SegNextLength = length(lstMf(1):(lstMs(2)));
                else
                    SegNextLength = length(lstMf(1):size(tIncChBlk,1));
                end
                if SegNextLength < dtShort*fs
                    windNext = SegNextLength;
                elseif SegNextLength < dtLong*fs
                    windNext = floor(dtShort*fs);
                else
                    windNext = floor(SegNextLength/10);
                end
                meanCurr = mean(dodSpline((lst(end)-windCurr):(lst(end)-1),  idx_ch));
                meanNext = mean(dodSpline((lst(end)+1):(lst(end)+windNext), idx_ch));
                dodSpline(lst,idx_ch) = dodSpline(lst,idx_ch) - meanCurr + meanNext;
            end

            % Intermediate segments
            for kk=1:(nbMA-1)
                % no motion
                lst = lstMf(kk):(lstMs(kk+1)-1);
                SegPrevLength = lstMl(kk);
                SegCurrLength = length(lst);
                if SegPrevLength < dtShort*fs
                    windPrev = SegPrevLength;
                elseif SegPrevLength < dtLong*fs
                    windPrev = floor(dtShort*fs);
                else
                    windPrev = floor(SegPrevLength/10);
                end
                if SegCurrLength < dtShort*fs
                    windCurr = SegCurrLength;
                elseif SegCurrLength < dtLong*fs
                    windCurr = floor(dtShort*fs);
                else
                    windCurr = floor(SegCurrLength/10);
                end
                meanPrev = mean(dodSpline((lst(1)-windPrev):(lst(1)-1), idx_ch));
                meanCurr = mean(dod(lst(1):(lst(1)+windCurr-1), idx_ch));

                dodSpline(lst,idx_ch) = dod(lst,idx_ch) - meanCurr + meanPrev;

                % motion
                lst = (lstMs(kk+1)):(lstMf(kk+1)-1);
                SegPrevLength = SegCurrLength;
                SegCurrLength = lstMl(kk+1);
                if SegPrevLength < dtShort*fs
                    windPrev = SegPrevLength;
                elseif SegPrevLength < dtLong*fs
                    windPrev = floor(dtShort*fs);
                else
                    windPrev = floor(SegPrevLength/10);
                end
                if SegCurrLength < dtShort*fs
                    windCurr = SegCurrLength;
                elseif SegCurrLength < dtLong*fs
                    windCurr = floor(dtShort*fs);
                else
                    windCurr = floor(SegCurrLength/10);
                end
                meanPrev = mean(dodSpline((lst(1)-windPrev):(lst(1)-1), idx_ch));
                meanCurr = mean(dodSpline(lst(1):(lst(1)+windCurr-1), idx_ch));

                dodSpline(lst,idx_ch) = dodSpline(lst,idx_ch) - meanCurr + meanPrev;
            end

            % Last not MA segment
            if lstMf(end)<length(t)
                lst = (lstMf(end)-1):length(t);
                SegPrevLength = lstMl(end);
                SegCurrLength = length(lst);
                if SegPrevLength < dtShort*fs
                    windPrev = SegPrevLength;
                elseif SegPrevLength < dtLong*fs
                    windPrev = floor(dtShort*fs);
                else
                    windPrev = floor(SegPrevLength/10);
                end
                if SegCurrLength < dtShort*fs
                    windCurr = SegCurrLength;
                elseif SegCurrLength < dtLong*fs
                    windCurr = floor(dtShort*fs);
                else
                    windCurr = floor(SegCurrLength/10);
                end
                meanPrev = mean(dodSpline((lst(1)-windPrev):(lst(1)-1), idx_ch));
                meanCurr = mean(dod(lst(1):(lst(1)+windCurr-1), idx_ch));

                dodSpline(lst,idx_ch) = dod(lst,idx_ch) - meanCurr + meanPrev;
            end

            %else
            %   dodSpline(:,i_ch) = dod;
        end
    end
    data_dod(iBlk).SetDataTimeSeries(dodSpline);
end


function [f,fu,fx] = f_fu_fx_Wrapper(u,x,p,parIdx)

% dx = f(u,x,p)
    coder.cinclude('iiwa14.h');
    [xDim,~] = size(x);
    [uDim,~] = size(u);
    f = f_Wrapper(u,x,p,parIdx);
    fu = zeros(xDim,uDim);
    fx = zeros(xDim,xDim);

    q = x(1:7,1);
    qd = x(8:end,1);
    tau = u(1:7,1);

    dq  = zeros(7,7);
    dqd = zeros(7,7);
    dtau= zeros(7,7);

    coder.ceval('derivatives_cal', ...
                coder.ref(q),...
                coder.ref(qd),...
                coder.ref(tau),...
                coder.ref(dq),...
                coder.ref(dqd),...
                coder.ref(dtau),...
                parIdx);
    fu(8:end,1:7) = dtau;
    fx = [zeros(7,7),eye(7);dq,dqd];
end


function net = cnn_imagenet_init(varargin)
% CNN_IMAGENET_INIT  Initialize a standard CNN for ImageNet

opts.scale = 1 ;
opts.initBias = 0.1 ;
opts.weightDecay = 1 ;
%opts.weightInitMethod = 'xavierimproved' ;
opts.weightInitMethod = 'gaussian' ;
opts.model = 'alexnet' ;
opts.batchNormalization = false ;
opts.networkType = 'simplenn' ;
opts.cudnnWorkspaceLimit = 1024*1024*1204 ; % 1GB
opts.classNames = {} ;
opts.classDescriptions = {} ;
opts.averageImage = zeros(3,1) ;
opts.colorDeviation = zeros(3) ;
opts = vl_argparse(opts, varargin) ;

% Define layers
switch opts.model
  case 'alexnet'
    net.meta.normalization.imageSize = [227, 227, 3] ;
    net = alexnet(net, opts) ;
    bs = 256 ;
  case 'vgg-f'
    net.meta.normalization.imageSize = [224, 224, 3] ;
    net = vgg_f(net, opts) ;
    bs = 256 ;
  case 'vgg-m'
    net.meta.normalization.imageSize = [224, 224, 3] ;
    net = vgg_m(net, opts) ;
    bs = 196 ;
  case 'vgg-s'
    net.meta.normalization.imageSize = [224, 224, 3] ;
    net = vgg_s(net, opts) ;
    bs = 128 ;
  case 'vgg-vd-16'
    net.meta.normalization.imageSize = [224, 224, 3] ;
    net = vgg_vd(net, opts) ;
    bs = 32 ;
  case 'vgg-vd-19'
    net.meta.normalization.imageSize = [224, 224, 3] ;
    net = vgg_vd(net, opts) ;
    bs = 24 ;
  otherwise
    error('Unknown model ''%s''', opts.model) ;
end

% final touches
switch lower(opts.weightInitMethod)
  case {'xavier', 'xavierimproved'}
    net.layers{end}.weights{1} = net.layers{end}.weights{1} / 10 ;
end
net.layers{end+1} = struct('type', 'softmaxloss', 'name', 'loss') ;

% Meta parameters
net.meta.inputSize = [net.meta.normalization.imageSize, 32] ;
net.meta.normalization.cropSize = net.meta.normalization.imageSize(1) / 256 ;
net.meta.normalization.averageImage = opts.averageImage ;
net.meta.classes.name = opts.classNames ;
net.meta.classes.description = opts.classDescriptions;
net.meta.augmentation.jitterLocation = true ;
net.meta.augmentation.jitterFlip = true ;
net.meta.augmentation.jitterBrightness = double(0.1 * opts.colorDeviation) ;
net.meta.augmentation.jitterAspect = [3/4, 4/3] ;
%net.meta.augmentation.jitterContrast = 0.4 ;
%net.meta.augmentation.jitterSaturation = 0.4 ;
%net.meta.augmentation.jitterScale = [0.9, 1] ;

if ~opts.batchNormalization
  lr = logspace(-2, -4, 60) ;
else
  lr = logspace(-1, -4, 20) ;
end

net.meta.trainOpts.learningRate = lr ;
net.meta.trainOpts.numEpochs = numel(lr) ;
net.meta.trainOpts.batchSize = bs ;
net.meta.trainOpts.weightDecay = 0.0005 ;

% Fill in default values
net = vl_simplenn_tidy(net) ;

% Switch to DagNN if requested
switch lower(opts.networkType)
  case 'simplenn'
    % done
  case 'dagnn'
    net = dagnn.DagNN.fromSimpleNN(net, 'canonicalNames', true) ;
    net.addLayer('top1err', dagnn.Loss('loss', 'classerror'), ...
                 {'prediction','label'}, 'top1err') ;
    net.addLayer('top5err', dagnn.Loss('loss', 'topkerror', ...
                                       'opts', {'topK',5}), ...
                 {'prediction','label'}, 'top5err') ;
  otherwise
    assert(false) ;
end

% --------------------------------------------------------------------
function net = add_block(net, opts, id, h, w, in, out, stride, pad)
% --------------------------------------------------------------------
info = vl_simplenn_display(net) ;
fc = (h == info.dataSize(1,end) && w == info.dataSize(2,end)) ;
if fc
  name = 'fc' ;
else
  name = 'conv' ;
end
convOpts = {'CudnnWorkspaceLimit', opts.cudnnWorkspaceLimit} ;
net.layers{end+1} = struct('type', 'conv', 'name', sprintf('%s%s', name, id), ...
                           'weights', {{init_weight(opts, h, w, in, out, 'single'), ...
                             ones(out, 1, 'single')*opts.initBias}}, ...
                           'stride', stride, ...
                           'pad', pad, ...
                           'learningRate', [1 2], ...
                           'weightDecay', [opts.weightDecay 0], ...
                           'opts', {convOpts}) ;
if opts.batchNormalization
  net.layers{end+1} = struct('type', 'bnorm', 'name', sprintf('bn%s',id), ...
                             'weights', {{ones(out, 1, 'single'), zeros(out, 1, 'single'), ...
                               zeros(out, 2, 'single')}}, ...
                             'learningRate', [2 1 0.3], ...
                             'weightDecay', [0 0]) ;
end
net.layers{end+1} = struct('type', 'relu', 'name', sprintf('relu%s',id)) ;

% -------------------------------------------------------------------------
function weights = init_weight(opts, h, w, in, out, type)
% -------------------------------------------------------------------------
% See K. He, X. Zhang, S. Ren, and J. Sun. Delving deep into
% rectifiers: Surpassing human-level performance on imagenet
% classification. CoRR, (arXiv:1502.01852v1), 2015.

switch lower(opts.weightInitMethod)
  case 'gaussian'
    sc = 0.01/opts.scale ;
    weights = randn(h, w, in, out, type)*sc;
  case 'xavier'
    sc = sqrt(3/(h*w*in)) ;
    weights = (rand(h, w, in, out, type)*2 - 1)*sc ;
  case 'xavierimproved'
    sc = sqrt(2/(h*w*out)) ;
    weights = randn(h, w, in, out, type)*sc ;
  otherwise
    error('Unknown weight initialization method''%s''', opts.weightInitMethod) ;
end

% --------------------------------------------------------------------
function net = add_norm(net, opts, id)
% --------------------------------------------------------------------
if ~opts.batchNormalization
  net.layers{end+1} = struct('type', 'normalize', ...
                             'name', sprintf('norm%s', id), ...
                             'param', [5 1 0.0001/5 0.75]) ;
end

% --------------------------------------------------------------------
function net = add_dropout(net, opts, id)
% --------------------------------------------------------------------
if ~opts.batchNormalization
  net.layers{end+1} = struct('type', 'dropout', ...
                             'name', sprintf('dropout%s', id), ...
                             'rate', 0.5) ;
end

% --------------------------------------------------------------------
function net = alexnet(net, opts)
% --------------------------------------------------------------------

net.layers = {} ;

net = add_block(net, opts, '1', 11, 11, 3, 96, 4, 0) ;
net = add_norm(net, opts, '1') ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool1', ...
                           'method', 'max', ...
                           'pool', [3 3], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '2', 5, 5, 48, 256, 1, 2) ;
net = add_norm(net, opts, '2') ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool2', ...
                           'method', 'max', ...
                           'pool', [3 3], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '3', 3, 3, 256, 384, 1, 1) ;
net = add_block(net, opts, '4', 3, 3, 192, 384, 1, 1) ;
net = add_block(net, opts, '5', 3, 3, 192, 256, 1, 1) ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool5', ...
                           'method', 'max', ...
                           'pool', [3 3], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '6', 6, 6, 256, 4096, 1, 0) ;
net = add_dropout(net, opts, '6') ;

net = add_block(net, opts, '7', 1, 1, 4096, 4096, 1, 0) ;
net = add_dropout(net, opts, '7') ;

net = add_block(net, opts, '8', 1, 1, 4096, 1000, 1, 0) ;
net.layers(end) = [] ;
if opts.batchNormalization, net.layers(end) = [] ; end

% --------------------------------------------------------------------
function net = vgg_s(net, opts)
% --------------------------------------------------------------------

net.layers = {} ;
net = add_block(net, opts, '1', 7, 7, 3, 96, 2, 0) ;
net = add_norm(net, opts, '1') ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool1', ...
                           'method', 'max', ...
                           'pool', [3 3], ...
                           'stride', 3, ...
                           'pad', [0 2 0 2]) ;

net = add_block(net, opts, '2', 5, 5, 96, 256, 1, 0) ;
net = add_norm(net, opts, '2') ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool2', ...
                           'method', 'max', ...
                           'pool', [2 2], ...
                           'stride', 2, ...
                           'pad', [0 1 0 1]) ;

net = add_block(net, opts, '3', 3, 3, 256, 512, 1, 1) ;
net = add_block(net, opts, '4', 3, 3, 512, 512, 1, 1) ;
net = add_block(net, opts, '5', 3, 3, 512, 512, 1, 1) ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool5', ...
                           'method', 'max', ...
                           'pool', [3 3], ...
                           'stride', 3, ...
                           'pad', [0 1 0 1]) ;

net = add_block(net, opts, '6', 6, 6, 512, 4096, 1, 0) ;
net = add_dropout(net, opts, '6') ;

net = add_block(net, opts, '7', 1, 1, 4096, 4096, 1, 0) ;
net = add_dropout(net, opts, '7') ;

net = add_block(net, opts, '8', 1, 1, 4096, 1000, 1, 0) ;
net.layers(end) = [] ;
if opts.batchNormalization, net.layers(end) = [] ; end

% --------------------------------------------------------------------
function net = vgg_m(net, opts)
% --------------------------------------------------------------------

net.layers = {} ;
net = add_block(net, opts, '1', 7, 7, 3, 96, 2, 0) ;
net = add_norm(net, opts, '1') ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool1', ...
                           'method', 'max', ...
                           'pool', [3 3], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '2', 5, 5, 96, 256, 2, 1) ;
net = add_norm(net, opts, '2') ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool2', ...
                           'method', 'max', ...
                           'pool', [3 3], ...
                           'stride', 2, ...
                           'pad', [0 1 0 1]) ;

net = add_block(net, opts, '3', 3, 3, 256, 512, 1, 1) ;
net = add_block(net, opts, '4', 3, 3, 512, 512, 1, 1) ;
net = add_block(net, opts, '5', 3, 3, 512, 512, 1, 1) ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool5', ...
                           'method', 'max', ...
                           'pool', [3 3], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '6', 6, 6, 512, 4096, 1, 0) ;
net = add_dropout(net, opts, '6') ;

net = add_block(net, opts, '7', 1, 1, 4096, 4096, 1, 0) ;
net = add_dropout(net, opts, '7') ;

net = add_block(net, opts, '8', 1, 1, 4096, 1000, 1, 0) ;
net.layers(end) = [] ;
if opts.batchNormalization, net.layers(end) = [] ; end

% --------------------------------------------------------------------
function net = vgg_f(net, opts)
% --------------------------------------------------------------------

net.layers = {} ;
net = add_block(net, opts, '1', 11, 11, 3, 64, 4, 0) ;
net = add_norm(net, opts, '1') ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool1', ...
                           'method', 'max', ...
                           'pool', [3 3], ...
                           'stride', 2, ...
                           'pad', [0 1 0 1]) ;

net = add_block(net, opts, '2', 5, 5, 64, 256, 1, 2) ;
net = add_norm(net, opts, '2') ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool2', ...
                           'method', 'max', ...
                           'pool', [3 3], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '3', 3, 3, 256, 256, 1, 1) ;
net = add_block(net, opts, '4', 3, 3, 256, 256, 1, 1) ;
net = add_block(net, opts, '5', 3, 3, 256, 256, 1, 1) ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool5', ...
                           'method', 'max', ...
                           'pool', [3 3], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '6', 6, 6, 256, 4096, 1, 0) ;
net = add_dropout(net, opts, '6') ;

net = add_block(net, opts, '7', 1, 1, 4096, 4096, 1, 0) ;
net = add_dropout(net, opts, '7') ;

net = add_block(net, opts, '8', 1, 1, 4096, 1000, 1, 0) ;
net.layers(end) = [] ;
if opts.batchNormalization, net.layers(end) = [] ; end

% --------------------------------------------------------------------
function net = vgg_vd(net, opts)
% --------------------------------------------------------------------

net.layers = {} ;
net = add_block(net, opts, '1_1', 3, 3, 3, 64, 1, 1) ;
net = add_block(net, opts, '1_2', 3, 3, 64, 64, 1, 1) ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool1', ...
                           'method', 'max', ...
                           'pool', [2 2], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '2_1', 3, 3, 64, 128, 1, 1) ;
net = add_block(net, opts, '2_2', 3, 3, 128, 128, 1, 1) ;
net.layers{end+1} = struct('type', 'pool', 'name', 'pool2', ...
                           'method', 'max', ...
                           'pool', [2 2], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '3_1', 3, 3, 128, 256, 1, 1) ;
net = add_block(net, opts, '3_2', 3, 3, 256, 256, 1, 1) ;
net = add_block(net, opts, '3_3', 3, 3, 256, 256, 1, 1) ;
if strcmp(opts.model, 'vgg-vd-19')
  net = add_block(net, opts, '3_4', 3, 3, 256, 256, 1, 1) ;
end
net.layers{end+1} = struct('type', 'pool', 'name', 'pool3', ...
                           'method', 'max', ...
                           'pool', [2 2], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '4_1', 3, 3, 256, 512, 1, 1) ;
net = add_block(net, opts, '4_2', 3, 3, 512, 512, 1, 1) ;
net = add_block(net, opts, '4_3', 3, 3, 512, 512, 1, 1) ;
if strcmp(opts.model, 'vgg-vd-19')
  net = add_block(net, opts, '4_4', 3, 3, 512, 512, 1, 1) ;
end
net.layers{end+1} = struct('type', 'pool', 'name', 'pool4', ...
                           'method', 'max', ...
                           'pool', [2 2], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '5_1', 3, 3, 512, 512, 1, 1) ;
net = add_block(net, opts, '5_2', 3, 3, 512, 512, 1, 1) ;
net = add_block(net, opts, '5_3', 3, 3, 512, 512, 1, 1) ;
if strcmp(opts.model, 'vgg-vd-19')
  net = add_block(net, opts, '5_4', 3, 3, 512, 512, 1, 1) ;
end
net.layers{end+1} = struct('type', 'pool', 'name', 'pool5', ...
                           'method', 'max', ...
                           'pool', [2 2], ...
                           'stride', 2, ...
                           'pad', 0) ;

net = add_block(net, opts, '6', 7, 7, 512, 4096, 1, 0) ;
net = add_dropout(net, opts, '6') ;

net = add_block(net, opts, '7', 1, 1, 4096, 4096, 1, 0) ;
net = add_dropout(net, opts, '7') ;

net = add_block(net, opts, '8', 1, 1, 4096, 1000, 1, 0) ;
net.layers(end) = [] ;
if opts.batchNormalization, net.layers(end) = [] ; end


function x_it=m_st_block(x_it,mparams)
%m_st_block   block preconditioner for Stokes equations
%   x_it = m_st_block(x_it,mparams);
%   input
%          x_it         operand for preconditioning operator
%          mparams      structure defining block preconditioning operator
%   output
%          x_it         result of ilu preconditioning operation
%
%   IFISS function: DJS, HCE; 9 April 2005.
% Copyright (c) 2005 D.J. Silvester, H.C. Elman, A. Ramage

nv=size(mparams.Ast,1); np=size(mparams.Q,1);
rv=x_it(1:nv); rp=x_it(nv+1:nv+np);
zv=mparams.Ast\rv; zp=mparams.Q\rp;
x_it = [zv;zp];


function [constants,general,singles,pairs] = classifyfactors(L,M,R)

nfac = length(L);
used = zeros(1,nfac);

constants = 0;
general = 0;
singles = {};
pairs = {};
for i = 1:length(L)
    if isa(M{i},'double')
        constants = constants + L{i}*M{i}*R{i};
        used(i)=1;
    end
end

for i = 1:length(L)
    if ~used(i)
        temp = struct(M{i});
        if ~(is(M{i},'sdpcone') || is(M{i},'lpcone') || isequal(temp.originalbasis,'skew') || isequal(temp.originalbasis,'diagonal'))
            general = general + L{i}*M{i}*R{i};
            used(i) = 1;
        elseif size(M{i},2)~=size(R{i},1) | size(M{i},1)~=size(L{i},2)
            % Something like scalar*matrix
            % simplifies code if we treat that as a general
            general = general + L{i}*M{i}*R{i};
            used(i) = 1;
        end
    end
end

% sameL = [];
% sameR = [];
% for i = 1:length(L)-1
%     for j = i+1:length(L)
%         if isequal(M{i},M{j})
%             if isequal(L{i},L{j})
%                 mmm(i,j) = 1;
%                 mmm(j,i) = 1;
%                 sameL = [sameL;i j];
%             elseif isequal(R{i},R{j})
%                 sameR = [sameR;i j];
%                 mmm(i,j) = 1;
%                 mmm(j,i) = 1;
%             end
%         end
%     end
% end
% if length(sameL)>1
%     for i = 1:size(sameL,1)-1
%         for j = 2:size(sameL,2)
%             AA = sameL([i j],:);
%             BB = sameR([i j],:);
%             if AA == BB'
%                 candidate = unique([AA(:);BB(:)]);
%             end
%         end
%     end
% end

for i = 1:length(L)

     if issymmetric(M{i}) && isequal(find(L{i}),find(R{i}'))
        Rttmp = R{i}';
        tmp = L{i}(L{i}~=0)./(Rttmp(Rttmp~=0));
     else
         tmp = [];
     end

    if ~used(i)
        if issymmetric(M{i}) && (isequal(L{i},R{i}'))
            singles{end+1}.L = L{i};
            singles{end}.M = M{i};
            singles{end}.R = R{i};
            singles{end}.negated = 0;
            used(i)=1;
        elseif issymmetric(M{i}) && (isequal(L{i},-R{i}'))
            singles{end+1}.L = L{i};
            singles{end}.M = M{i};
            singles{end}.R = R{i};
            singles{end}.negated = 1;
            used(i)=1;
        elseif issymmetric(M{i}) && isequal(find(L{i}),find(R{i}')) &  length(unique(tmp)) == 1
        %    Rttmp = R{i}';
        %    tmp = L{i}(L{i}~=0)./(Rttmp(Rttmp~=0));

         %   if length(unique(tmp)) == 1
                  singles{end+1}.L = L{i}/sqrt(abs(tmp(1)));
                  singles{end}.M = M{i};
                  singles{end}.R = R{i}*sqrt(abs(tmp(1)));
                  if tmp(1) > 0
                      singles{end}.negated = 0;
                  else
                      singles{end}.negated = 1;

                  end
                  used(i)=1;
        %  end

        else
            for j = i+1:length(L)
                if isa(L{i}*M{i}*R{i}-R{j}'*M{j}'*L{j}','double')
                    pairs{end+1}.L = L{i};
                    pairs{end}.M = M{i};
                    pairs{end}.R = R{i};
                    used(j)=1;
                    used(i)=1;
                    break
                end
            end
        end
    end
end

for k = find(~used)
    if isequal(size(M{k}),[1 1])
        general = general + L{k}*M{k}*R{k};
    else
        error('Couldn''t classify all factors');
    end
end


function status = svm_learn(options, examples, model)
% SVM_LEARN - Interface to SVM light, learning module
%
%   STATUS = SVM_LEARN(OPTIONS, EXAMPLES, MODEL)
%   Call the training program 'svm_learn' of the SVM light
%   package.
%   OPTIONS must be a structure generated by SVMLOPT.
%   EXAMPLES is the name of the file containing the training examples
%   (use SVMLWRITE to convert a Matlab matrix to the appropriate format).
%   MODEL is the name of the file holding the trained Support Vector
%   Machine.
%   If 'svm_learn' is not on the path, OPTIONS must contain a field
%   'ExecPath' with the path of the executable.
%   STATUS is the error code returned by SVM light (0 if everything went
%   fine)
%
%   See also SVMLOPT, SVMLWRITE, SVM_CLASSIFY, SVMLREAD
%

%
% Copyright (c) by Anton Schwaighofer (2001)
% $Revision: 1.6 $ $Date: 2002/08/09 20:24:03 $
% mailto:anton.schwaighofer@gmx.net
%
% This program is released unter the GNU General Public License.
%

error(nargchk(3, 3, nargin));

% check parameter consistency for kernels
if ~isempty(options.Kernel),
  if (options.Kernel~=0) & isempty(options.KernelParam),
    error(sprintf('The chosen Kernel = %i requires parameters, but none are given in KernelParam', ...
                  options.Kernel));
  end
  parlen = length(options.KernelParam);
  isString = isa(options.KernelParam, 'char');
  switch options.Kernel
    case {1, 2}
      if isString | (parlen~=1),
        error(sprintf('The chosen Kernel = %i requires a scalar parameter', ...
                      options.Kernel));
      end
    case 3
       if isString | (parlen~=2),
        error(sprintf('The chosen Kernel = %i requires 2 scalar parameters', ...
                      options.Kernel));
      end
    case 4,
      if ~isString,
        error(sprintf('The chosen Kernel = %i requires a string parameter', ...
                      options.Kernel));
      end
  end
end

if ~isempty(options.NewVariables),
  if isempty(options.MaximumQP),
    maxval = 10;
  else
    maxval = options.MaximumQP;
  end
  if options.NewVariables>maxval,
    error('Option ''NewVariables'' must be smaller than 10 resp. value of MaximumQP');
  end
end

Names = fieldnames(options);
[m,n] = size(Names);

s = '';
for i = 1:m,
  field = Names{i,:};
  value = getfield(options, field);
  switch field,
    case 'Verbosity'
      s = stroption(s, '-v %i', value);
    case 'Regression'
      if ~isempty(value),
        if value==0,
          s = [s ' -z c'];
        else
          s = [s ' -z r'];
        end
      end
    case 'C'
      s = stroption(s, '-c %.10g', value);
    case 'TubeWidth'
      s = stroption(s, '-w %.10g', value);
    case 'CostFactor'
      s = stroption(s, '-j %.10g', value);
    case 'Biased'
      s = stroption(s, '-b %i', value);
    case 'RemoveIncons'
      s = stroption(s, '-i %i', value);
    case 'ComputeLOO'
      s = stroption(s, '-x %i', value);
    case 'XialphaRho'
      s = stroption(s, '-o %.10g', value);
    case 'XialphaDepth'
      s = stroption(s, '-k %.10g', value);
    case 'TransPosFrac'
      s = stroption(s, '-p %.10g', value);
    case 'Kernel'
      s = stroption(s, '-t %i', value);
    case 'KernelParam'
      if ~isempty(value),
        switch options.Kernel
          case 0
          case 1
            s = stroption(s, '-d %.10g', value(1));
          case 2
            s = stroption(s, '-g %.10g', value(1));
          case 3
            s = stroption(s, '-s %.10g -r %.10g', value(1), value(2));
          case 4
            s = stroption(s, '-u "%s"', value);
        end
      end
    case 'MaximumQP'
      s = stroption(s, '-q %i', value);
    case 'NewVariables'
      s = stroption(s, '-n %i', value);
    case 'CacheSize'
      s = stroption(s, '-m %i', value);
    case 'EpsTermin'
      s = stroption(s, '-e %.10g', value);
    case 'ShrinkIter'
      s = stroption(s, '-h %i', value);
    case 'ShrinkCheck'
      s = stroption(s, '-f %i', value);
    case 'TransLabelFile'
      s = stroption(s, '-l %s', value);
    case 'AlphaFile'
      s = stroption(s, '-a %s', value);
  end
end

evalstr = [fullfile(options.ExecPath, 'svm_learn') s ' ' ...
           examples ' ' model];
% fprintf('\nCalling SVMlight:\n%s\n\n', evalstr);
if isunix,
  status = unix(evalstr);
else
  status = dos(evalstr);
end

function s = stroption(s, formatstr, value, varargin)
% STROPTION - Add a new option to string
%

if ~isempty(value),
  s = [s ' ' sprintf(formatstr, value, varargin{:})];
end


filename='Bridge_Quadrilateral_Bilinear_Structured';
ptype = 'MACRO';
method = 'SIMP_P3'; % !! Instead of proportional to material density !!
materialType = 'ISOTROPIC';
initial_case = 'holes';
cost = {'compliance'};
weights = [1];
constraint = {'volumeConstraint'};
optimizer = 'HAMILTON-JACOBI'; incrementFactor = 1;
filterType = 'P1';
constraint_case = 'INEQUALITY';

HJiter0 = 1;
e2 = 30;
N_holes = [5 6];
R_holes = 0.7;
phase_holes = [0 pi/2];

nsteps = 1;
Vfrac_final = 0.5;
Perimeter_target=3.5;
optimality_final =1e-3;
constr_final =1e-3;

Vfrac_initial = 1;
optimality_initial = 1e-3;
constr_initial = 1e-3;

TOL.rho_plus = 1;
TOL.rho_minus = 0;
TOL.E_plus = 1;
TOL.E_minus = 1e-3;
TOL.nu_plus = 0.3;
TOL.nu_minus = 0.3;

plotting = 1;
printing = 0;
monitoring = 1;
monitoring_interval = 1;

maxiter = 50;


function test_libltfat_fifo
gl = 20;
fifoLen = 120; % Must be at least as big as gl + max expected bufLen
M = gl;
a = 7;
g = firwin('hann',gl);
gd = gabdual(g,a,M);
gg = fftshift(g.*gd)*M;

fifoPtr = calllib('libltfat','rtdgtreal_fifo_init_d',fifoLen,gl,a,1);
fifoPtr.Value.buf.setdatatype('doublePtr',fifoLen+1)
ififoPtr = calllib('libltfat','rtidgtreal_fifo_init_d',fifoLen,gl,a,1);
ififoPtr.Value.buf.setdatatype('doublePtr',fifoLen+gl+1)

bufIn = (1:1000)';
%bufIn = ones(1,1000);
bufOut = zeros(size(bufIn));
bufLen = 100;
bufOutPtr = libpointer('doublePtr',zeros(gl,1));

for ii=1:length(bufIn)/bufLen
slice = (ii-1)*bufLen + 1 : ii*bufLen;
buf = bufIn(slice);
bufInPtr = libpointer('doublePtr',buf);
bufInPtrTmp = libpointer('doublePtr',zeros(size(buf)));

written = calllib('libltfat','rtdgtreal_fifo_write_d',fifoPtr,bufLen,bufInPtr);

while calllib('libltfat','rtdgtreal_fifo_read_d',fifoPtr,bufOutPtr) > 0
    bufOutPtr.Value = bufOutPtr.Value.*gg;
    written = calllib('libltfat','rtidgtreal_fifo_write_d',ififoPtr,bufOutPtr)
end

read = calllib('libltfat','rtidgtreal_fifo_read_d',ififoPtr,bufLen,bufInPtrTmp)

bufOut(slice) = bufInPtrTmp.Value;

end

inshift = circshift(bufIn,(gl-1));
inshift(1:(gl-1)) = 0;
stem([bufOut, inshift]);shg;

calllib('libltfat','rtdgtreal_fifo_done_d',fifoPtr);
calllib('libltfat','rtidgtreal_fifo_done_d',ififoPtr);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file is part of OLPS: http://OLPS.stevenhoi.org/
% Original authors: Doyen Sahoo
% Contributors: Bin LI, Steven C.H. Hoi
% Change log:
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [] = resultManager(results, job)
%% The results analysis of the Algorithm Analyser can be seen here

    % r.returns_daily     = returns;
    % r.returns           = cumprod(returns_daily+1);
    % r.portfolio         = portfolio;
    % r.stats             = stats;
    % r.benchmarks        = benchmakrs;
    % r.benchmarks_daily  = benchmarks_daily;
    % r.chosenStrategy    = chosenStrategy;
    % r.dataFrequency     = dataFrequency;

    [results.r, results.c]  = size(results.portfolio);

    menuId = 6; % Result Manager for Algorithm Analyser
    displayMenu(menuId);
    prompt = 'Please enter your choice (1-6):';
    choice = input(prompt);

    switch(choice),
        case 1,
            % Print table of results
            displayTable(results);
            resultManager(results, job);

        case 2,
            % Plot the graphs of returns (both cumulative return and
            % log(cumulative return) of all algorithms
            cumReturns      = [results.benchmarks results.returns];
            dailyReturns    = [(results.benchmarks_daily-1) results.returns];

            figure;
            plot(cumReturns);
            xlim([0 results.r+1]);
            legend('Uniform BAH', 'Uniform CRP', 'Best Stock', 'Best CRP', results.chosenStrategy, 'Location', 'Best');
            grid on;
            title('Cumulative Returns of the Algorithms');
            xlabel('Time');
            ylabel('Portfolio Value');

            figure;
            semilogy(cumReturns);
            xlim([0 results.r+1]);
            legend('Uniform BAH', 'Uniform CRP', 'Best Stock', 'Best CRP', results.chosenStrategy, 'Location', 'Best');
            grid on;
            title('LOG Cumulative Returns of the Algorithms');
            xlabel('Time');
            ylabel('Portfolio Value');

            resultManager(results, job);

        case 3,
            % Produce all the risk plots. Tell user to chaneg the window
            % size in the config if needed
            load ../GUI/config/config.mat
            disp('Generating all the Risk Plots');
            msg = 'windowSize = ';
            msg = strcat(msg, num2str(windowRisk));
            disp(msg);
            disp('(You can modify the window size by changing windowRisk variable in the config)');

            % Produce all risk plots based on windowRisk
            window = windowRisk;
            if isnan(window) || window < 2
                errorMessage('Window size must be a number greater than or equal to 2');
            else
                window = round(window);

                % 1. Annualized Sharpe Ratio
                addpath('../GUI/lib');

                [r, c] = size(results.returns_daily);
                sharpeRatios = zeros(r,1);
                for i = 50:1:r
                    start = max(i-window+1, 1);
                    finish = i;
                    sharpeRatios(i) = sharpe(results.returns_daily(start:finish), results.returns(finish)/results.returns(start), results.dataFrequency);
                end
                figure;
                plot(sharpeRatios);
                xlim([0 r+1]);
                legend('Sharpe Ratio', 'Location', 'Best');
                title('Sharpe Ratio of the Algorithm');
                xlabel('Time');
                ylabel('Sharpe Ratio');

                % 2. Calmar Ratio
                calmarRatios = zeros(r,1);
                for i = 50:1:r
                    start = max(i-window+1, 1);
                    finish = i;
                    mdd = maxDD(results.returns(start:finish));
                    calmarRatios(i) = calmar(results.returns(start:finish), mdd, results.dataFrequency);
                end
                figure;
                plot(calmarRatios);
                xlim([0 r+1]);
                legend('Calmar Ratio', 'Location', 'Best');
                title('Calmar Ratio of the Algorithm');
                xlabel('Time');
                ylabel('Calmar Ratio');

                % 3. Sortino Ratio
                sortinos = zeros(r,1);
                for i = 50:1:r
                    start = max(i-window+1, 1);
                    finish = i;
                    sortinos(i) = sortino(results.returns_daily(start:finish),0);
                end

                figure;
                plot(sortinos);
                xlim([0 r+1]);
                legend('Sortino Ratio', 'Location', 'Best');
                title('Sortino Ratio of the Algorithm');
                xlabel('Time');
                ylabel('Sortino Ratio');

                % 4. Value at Risk
                vars = zeros(r,1);
                for i = 50:1:r
                    start = max(i-window+1, 1);
                    finish = i;
                    vars(i) = var5(results.returns_daily(start:finish));
                end

                figure;
                plot(vars);
                xlim([0 r+1]);
                legend('Value at Risk', 'Location', 'Best');
                title('Value at Risk of the Algorithm');
                xlabel('Time');
                ylabel('Value at Risk');

                % 5. Maximum Draw Down
                mdds = zeros(r,1);
                for i = 50:1:r
                    start = max(i-window+1, 1);
                    finish = i;
                    mdds(i) = maxDD(results.returns(start:finish));
                end

                figure;
                plot(mdds);
                xlim([0 r+1]);
                legend('Maximum Draw Down', 'Location', 'Best');
                title('Maximum Draw Down of the Algorithm');
                xlabel('Time');
                ylabel('Maximum Draw Down (%)');

                rmpath('../GUI/lib');
            end
            resultManager(results, job);

        case 4,
            % Portfolio allocation plots
            portfolio   = results.portfolio;
            expected    = mean(portfolio);
            deviation   = std(portfolio);

            errorbar(expected, deviation, 'xr');
            xlim([0 results.c+1]);

            title('Average Portfolio Allocation');
            xlabel('Assets');
            ylabel('Fraction of Portfolio');

            resultManager(results, job);

        case 5,
            % Save the results.
            prompt ='Enter Name of File to save results: ';
            filename = input(prompt);
            [ resultsTable ] = getTable(results);
            cd ../Log/Results/
            save(filename, 'results', 'job', 'resultsTable');
            disp('Results saved in /Log/Result ');
            cd ../../PGUI/
            resultManager(results, job);

        case 6,
            disp('Exiting Result Manager --> to Algorithm Analyser');
            [ job ] = jobInit();
            algorithmAnalyserMenu( job );

        otherwise,
            disp('ERROR: Please enter a valid input');
            resultManager(results, job);
    end

end

function [ algorithmJob ] = jobInit()
% Construct an instance of an algorithm analyser job

    % Read configuration
    load ../GUI/config/config.mat;
    algorithmJob.algorithmId    = 1;
    algorithmJob.datasetId      = 1;
    AL                          = char(algorithmList);
    algorithmJob.algorithm      = AL(algorithmJob.algorithmId,:);
    DL                          = char(dataList);
    algorithmJob.dataset        = DL(algorithmJob.datasetId,:);
    algorithmJob.parameters     = cell2mat(defaultParameters(algorithmJob.algorithmId,:));
end

function [ resultsTable ] = getTable(results)

    cumReturns      = [results.benchmarks results.returns];
    dailyReturns    = [results.benchmarks_daily-1 results.returns_daily];

    % Compute the statsand display the important numbers in table using the
    % library functions
    addpath('../GUI/lib');

    % Get final Values
    [r c] = size(cumReturns);
    results.finalValues = cumReturns(r,:);

    % Get the mean returnfor every day - This is a simple average
    results.meanReturns = mean(dailyReturns);

    % Get annualised returns
    denominator = 252/results.dataFrequency;
    Y = r/denominator;
    results.annualisedReturns = results.finalValues.^(1/Y)-1;

    % Get standard deviation- a measureof risk
    results.standardDeviation = std(dailyReturns);

    % Get annualised standard deviation
    results.annualisedStandardDeviation = results.standardDeviation * sqrt(denominator);

    % Get sharpe ratios
    results.sharpeRatios = sharpe(dailyReturns, results.finalValues,results.dataFrequency);

    % Get Sortino ratios
    results.sortinoRatios = sortino(dailyReturns, 0);

    % Get Value risks at level 5%
    results.valueAtRisks = var5(dailyReturns);

    % Get Maximum draw down
    results.mdds = maxDD_general(cumReturns);

    % Get Calmar ratios
    results.calmars = calmar(cumReturns, results.mdds, results.dataFrequency);

    % Fill up the tables

    tableData   = [results.finalValues; results.meanReturns; results.annualisedReturns; results.standardDeviation; results.annualisedStandardDeviation; results.sharpeRatios; results.calmars; results.sortinoRatios; results.valueAtRisks; results.mdds];

    Market      = tableData(:,1);
    Uniform     = tableData(:,2);
    BestStock   = tableData(:,3);
    BCRP        = tableData(:,4);
    Algorithm   = tableData(:,5);
    report      = {'Final Value','Mean Return','Annualised Return','Standard Deviation','Annualised Standard Deviation','Sharpe Ratio','Calmar Ratio','Sortino Ratio','Value at Risk','Maximum Draw Down'};
    % tableData   = table(Market,Uniform,BestStock,BCRP, Algorithm,
    % 'RowNames', report); % - works only in Matlab 2014a onwards

    finalDisplay = report';
    finalDisplay(2:end+1) = finalDisplay;
    finalDisplay{1} = '';

    finalDisplay{1,2} = 'Market';
    finalDisplay{1,3} = 'Uniform';
    finalDisplay{1,4} = 'BestStock';
    finalDisplay{1,5} = 'BCRP';
    finalDisplay{1,6} = 'Algorithm';

    for i = 1:1:10
        for j = 1:1:5
            finalDisplay{i+1,j+1} = tableData(i,j);
        end
    end

    resultsTable = finalDisplay;
end


function r = roots(f, varargin)
%ROOTS   Roots of a CLASSICFUN in the interval [a,b].
%   ROOTS(F) returns the real roots of the CLASSICFUN F in the interval [a,b].
%
%   ROOTS(F, OPTIONS) modifies the default ROOTS properties, by passing the
%   OPTIONS to the rootfinding method of the ONEFUN of F.
%
%   If F is an array-valued CLASSICFUN then there is no reason to expect each column to
%   have the same number of roots. In order to return a useful output, the roots
%   of each column are computed and then padded with NaNs so that a matrix may
%   be returned. The columns of R = ROOTS(F) correspond to the columns of F.
%
% See also ONEFUN. [TODO]: Why may we also want to see ONEFUN?

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% Deal with empty case:
if ( isempty(f) )
    r = [];
    return
end

% Find the roots of the ONEFUN of F:
onefunRoots = roots(f.onefun, varargin{:});

% Map the roots found on [-1,1] to the interval [a,b]:
r = f.mapping.For(onefunRoots);

end


function T = mytoeplitz(c, r)
% function T = mytoeplitz(c, r)
% Emulate the function TOEPLITZ for fun...

if nargin<2
    r=c;
end

c=c(:);
r=r(:);
v = [flipud(c); r(2:end)];

sz= [length(c) length(r)];
[I J] = itril(sz,Inf);
K = J-I+length(c);
Ilin = sub2ind(sz, I, J);
T = zeros(sz);
T(Ilin) = v(K);


report_this_filefun(mfilename('fullpath'));

% compute the source zones for landers

dy = 0.15;
tmin1 = 3;
newt0 = newt2;
tpre =  120;

l=storedcat.Date <= min(maepi.Date) + days(60);
a=storedcat.subset(l);
update(mainmap()); newt2 = a;
timeplot

d = [];
prol = 0.90;

l = a.Magnitude > 7;
maepi = a.subset(l);

mati = maepi(1,3);
M = 7.4 - 4;
da = []; anz = [];
B2 = [];
t0 = (max(a.Date) - mati)*365;
tlen = t0;
cd /home2/stefan/ZMAP/aspar
fid2 = fopen('sourczones.txt','w');

dx = 0.33;

for x = 29:dx:31
    l = a.Longitude >= x & a.Longitude < x+dx;
    b1 = prctile2(a(l,2),20);
    b2 = prctile2(a(l,2),80);

    newt2 = a.subset(l);
    mcperc_ca3;
    if isnan(Mc95) == 0
        magco = Mc95;
    elseif isnan(Mc90) == 0
        magco = Mc90;
    else
        [bv magco stan av me mer me2,  pr] =  bvalca3(b,1,1);
    end
    magco
    l = newt2.Magnitude >= magco;
    newt2 = newt2(l,:);

    figure_w_normalized_uicontrolunits(map)
    try
        delete(pl)
    catch ME
        disp(ME.message);
    end

    hold on
    pl = plot(newt2.Longitude,newt2.Latitude,'xk');drawnow
    timeplot

    calcp
    %da = [da ; x+dx/2 P];
    B2 = [B2 ; b1 x  b2 x];

    anz = [];
    for m2 = 4.75:0.5:7.25
        M2 = maepi(1,6) - m2;
        t0 = tlen;
        pla = 0; pla2 = 0;
        dt = 0.5;
        for t = t0:dt:t0+tpre
            pla = pla + (10^(A + bv*(M2)) * (t + c)^(-p))  *dt;
            pla2 = pla2 + (10^(A + bv*(M2-0.5)) * (t + c)^(-p))  *dt;
        end

        anz = [anz ;  m2+0.25  (pla-pla2)/tpre];
    end
    % anz(5,2) = anz(5,2)/10;

    % write info to file
    s = ['0    1.     -1          zn03']; s = s';
    fprintf(fid2,'%s\n',s);
    s = ['2 1 1']; s = s';
    fprintf(fid2,'%s\n',s);
    s = [num2str(x) ' ' num2str(b1,5) ' ' num2str(x) ' ' num2str(b2,5)]; s = s';
    fprintf(fid2,'%s\n',s);
    s = [num2str(x+dx) ' ' num2str(b1,5) ' ' num2str(x+dx) ' ' num2str(b2,5)]; s = s';
    fprintf(fid2,'%s\n',s);
    fprintf(fid2,'%7.6f    ',anz(:,2));
    fprintf(fid2,'\n');
    fprintf(fid2,'\n');
    fprintf(fid2,'%3.2f  ',anz(:,1));
    fprintf(fid2,'\n');
end

%end

fclose(fid2)

do = [' ! cat head_turk.txt | sed -e"s/sub1/' num2str(prol) ' 1 ' num2str(tpre) '/" > head2.txt ' ]; eval(do)
do = [' ! cat head2.txt sourczones.txt tail.txt > /home2/stefan/srisk/myrisk.inp']; eval(do)

cd /home2/stefan/srisk/

do = [ '! /nfs/alaska/home2/stefan/srisk/seis4b.exe  myrisk.inp myrisk.out f2 f3' ]; eval(do)
do = [' !cat myrisk.out | grep -e "LAT   "  -e "' num2str(tpre) ' YE"  > tmp2 ']; eval(do)
do = ['condata2']; err = [' ']; eval(do,err);
save inpudata.xyz da -ascii

eq = [a.Longitude a.Latitude a.Magnitude];
save eqs2.dat eq -ascii

cd /home2/stefan/srisk/

do = [' ! /home2/stefan/srisk/myriskturk 0.05 0.02 ' num2str(tpre) ]; eval(do)

load lat
load lon
load hpga

[X,Y] = meshgrid(min(lon)-0.1:0.08:max(lon)+0.1,min(lat)-0.1:0.08:max(lat)+0.1);

Z = griddata(lon,lat,hpga,X,Y,'linear');
figure

pcolor(X,Y,Z); colorbar; shading flat
hold on
shading interp
overlay


% start : starting time of audio signal in seconds(e.g. 0 second)
% finish : e.g. ending time of audio signal in seconds (e.g. 30 second)
% filename: the input file (wavfile)
%
%
% segments: the signal segmentation with 20 msec accuracy based on RMS,
% if segments(i) = 1 then there is a change, otherwize segments(i) = 0
% The command find(segments == 1)/50 yields the signal segmentation times in sec
%
% classif: final classification of signal. classif(i) is the class
% of the i^{th} (20 msec) interval of the given signal (see also Fig 2 (b))
%
% Fig 1 shows the propability of each class per segment
%
% Fig 2 (a) shows the  segmentation of the audio signal
% Fig 2 (b) shows the  classification of the audio signal
% Fig 2 (c) shows the  RMS of the audio signal
%
% example to run: [classif, segments]=trmszc(0,60,'test3.wav')

function [classif, segments]=trmszc(start,finish,filename)

segments = [];
classif = [];

[Y1,FS,NBITS,OPTS]=wavread(filename,[1 5]);
duration = finish-start;
kanalia = size(Y1,2);
arxh = start*FS;
m = 100;
timeread = 1;

Vt = 0*[1:50];
Vta = [];
Vtz = 0*[1:50];
Vtz1 = 0*[1:50];

Vtaz = [];
Vtaz1 = [];

shma = [];
temp = [];
y = 0;
py = [1:1:50];

scp = 0;
sc = 0;
Vtp = [1:1:50];
i=1;
[PYs,FS,NBITS,OPTS]=wavread(filename,[arxh+1+(i-1)*timeread*FS  arxh+i*timeread*FS]);
sf11 = 0;
aVt = [];

%READING - Computation of RMS-ZC-RMS*ZC per 20 msec

for i=1:floor(duration/timeread),
   [Ys,FS,NBITS,OPTS]=wavread(filename,[arxh+1+(i-1)*timeread*FS  arxh+i*timeread*FS]);
   if kanalia==2,
      Ys = Ys(:,1)+Ys(:,2);
   end
   for j=1:timeread*50,
      y = Ys(round((j-1)*0.02*FS+1):floor(j*0.02*FS));
      rms = sqrt(sum(y.*y));
      Vtp = Vt;
      Vt = [Vt(2:50) rms];
      l = length(y);
      y1 = y(1:l-1);
      y2 = y(2:l);
      mm1 = y1.*y2;
      zc = 0.5*sum((abs(sign(mm1))-sign(mm1)));
      Vtz1 = [Vtz1(2:50) zc];
      zc = zc*rms;
      Vtz = [Vtz(2:50) zc];
   end

   m = mean(Vt);
   v = var(Vt);
   Vta = [Vta Vt];
   Vtaz = [Vtaz Vtz];
   Vtaz1 = [Vtaz1 Vtz1];

   if (v ~= 0 & m ~= 0)
      b(i) = v/m;
      a(i) = (m/b(i))-1;
   else
      b(i) = 1000000;
      a(i) = -1;
   end
end

%Computation of  KVRMS

l = length(Vta);
ftm(1) = mean(Vta(1:50));
ftv(1) = var(Vta(1:50));
for i=2:l-50,
  ftm(i) = ftm(i-1)+(Vta(i+49)-Vta(i-1))/50;
  ftv(i) = ftv(i-1) + ftm(i-1)*ftm(i-1) + ((Vta(i+49)*Vta(i+49)-Vta(i-1)*Vta(i-1))/50) - ftm(i)*ftm(i);

  if  ftm(i)~= 0,
     kvrms(i) =   ftv(i)/(ftm(i)*ftm(i));
  else
     kvrms(i) = 0;
  end
end

l = floor(duration/timeread);
m = mean(kvrms);
v = var(kvrms);
b1111 = v/m;
a111 = (m/b1111)-1;

%computation of similarity (omiot) between windows  based on RMS distribution
for i=2:l,
   k = (a(i)+a(i-1)+2)/2;
   omiot1(i-1) = ((2/(b(i-1)+b(i)))^k)*(b(i-1)^((a(i)+1)/2))*(b(i)^((a(i-1)+1)/2))*gamma(k)/(sqrt(gamma(a(i-1)+1)*gamma(a(i)+1)));
   if omiot1(i-1) ~= omiot1(i-1),
      omiot1(i-1) = 0;
   end
end

for i=3:l,
   k = (a(i)+a(i-2)+2)/2;
   omiot2(i-2) = ((2/(b(i-2)+b(i)))^k)*(b(i-2)^((a(i)+1)/2))*(b(i)^((a(i-2)+1)/2))*gamma(k)/(sqrt(gamma(a(i-2)+1)*gamma(a(i)+1)));
   if omiot2(i-2) ~= omiot2(i-2),
      omiot2(i-2) = 0;
   end
end

P = [];

%Segmentation
%Computation of propability  P of change  (at window i)

for i=2:l-1,
   P(i-1) =(1-omiot2(i-1))*(1-omiot1(i-1)+1-omiot1(i))*(1-omiot2(i-1));
end

for i=2:l-1,
   P(i-1) =(1-omiot2(i-1));
end

P = [0 P 0];

M = mean(P);
V1 = mean(abs(P(1:l-3)-P(2:l-2)));
V2 = mean(abs(P(1:l-4)-P(3:l-2)));

V = (V1+V2)*0.25;

V = 0.25*median(abs((P(1:l-4)-P(3:l-2))));

Pd(1) = P(1);
Pd(2) = P(2);

for i=3:l-2,
   m = mean(P([i-2:i-1 i+1:i+2]));
   m1 = max(P([i-2:i-1 i+1:i+2]));

   if (m < 0.1*M)
      m1 = 0.1*M;
   end
   d = (P(i)-m)/m1;

   if d < 0,
      d = 0;
   end
   Pd(i) = P(i)*d/V;
end
Pd(l) = P(l);
Pd(l-1) = P(l-1);

%window size = 1 sec

%Selection of candicate windows where there is a change

j = 0;
for i=3:l-3,
   if (Pd(i) > 5 & P(i) > P(i+1) & P(i) > P(i-1)),
      j = j+1;
      pos(j) = i;
   end
end

if j == 0,
   return;
end

%Computation of change with 20 msec accurancy

k2 = 1;
c = 25;
for k1=1:length(pos),
   i = 50*(pos(k1)-2);  % msec
   for j=-c:50+c,
      if (ftv(i+j) ~= 0 & ftm(i+j) ~= 0),
         b1 = ftv(i+j)/ftm(i+j);
         a1 = ftm(i+j)/b1-1;
      else
         b1 = 10000;
         a1 = -1;
      end

      if (ftv(i+j+50) ~= 0 & ftm(i+j+50) ~= 0)
         b2 = ftv(i+j+50)/ftm(i+j+50);
         a2 = ftm(i+j+50)/b2-1;
      else
         b2 = 10000;
         a2 = -1;
      end
      k = (a2+a1+2)/2;
      Om(j+c+1) = ((2/(b1+b2))^k)*(b1^((a2+1)/2))*(b2^((a1+1)/2))*gamma(k)/(sqrt(gamma(a1+1)*gamma(a2+1)));
      if Om(j+c+1)~= Om(j+c+1),
         Om(j+c+1) = 0;
      end
   end
   [x posms(k1)] = min(Om);
   h = 1-Om;
   if mean(h(max(posms(k1)-25,1):min(2*c+51,posms(k1)+25))) >  0.1,
      msec(k2) = posms(k1)-1-c;
      mpos(k2) = pos(k1);
      k2 = k2+1;
   end
end

posms = [];
posms = msec;
pos = [];
pos = mpos;

fpos = start+pos-1+0.02*posms;

pfpos = floor(50*pos+posms-50);

bvoise = 0.14339738781836;
bmusic = 0.04399754659151;
amusic = 1.66349817725076;
avoise = 2.32677887950291;

pfpos = [1 pfpos length(kvrms)];
l = length(pfpos)-1;
V = [];
Pzero = [];
Fsp1 = [];

%Classification for each segment

for i=1:l,

   d = 0;

   x1 = mean(kvrms([pfpos(i):pfpos(i+1)]));
   x = x1;
   y = Vtaz([pfpos(i)+d:pfpos(i+1)-d]);
   y = y/(2*max(Vta(pfpos(i)+d:pfpos(i+1)-d)) - min(Vta(pfpos(i)+d:pfpos(i+1)-d))-median(Vta(pfpos(i)+d:pfpos(i+1)-d)));

   thor(i) = 50*mean(exp(-y));

   Pmusic(i) = (x^amusic)*exp(-x/bmusic)/(gamma(amusic+1)*bmusic^(amusic+1));
   Pvoise(i) = 0.5*(x^avoise)*exp(-x/bvoise)/(gamma(avoise+1)*bvoise^(avoise+1));
   sm = 0.7*median(ftm(pfpos(i):pfpos(i+1)))+0.3*mean(ftm(pfpos(i):pfpos(i+1)));
   Pspace(i) =  6*exp((-sm*sm)/(2*0.6*0.6));

   zpos(i) = sum(exp(-10*Vtaz1([pfpos(i)+d:pfpos(i+1)-d])))/length(Vtaz1([pfpos(i)+d:pfpos(i+1)-d]));

   if zpos(i) > 0.08 | x > 3
     Pvoise(i)  = 10;
  else
      Pmusic(i) = (x^amusic)*exp(-x/bmusic)/(gamma(amusic+1)*bmusic^(amusic+1));
      Pvoise(i)  = 0.5*(x^avoise)*exp(-x/bvoise)/(gamma(avoise+1)*bvoise^(avoise+1));
   end

   V(i,:) = [Pmusic(i)  Pvoise(i)];
   [Pmax(i) type(i)] = max(V(i,:));

  thor2(i) = 50*mean(exp(-4*y));
  Pmusicg(i) = 0;

   if thor2(i) > 3.5,
      Pvoiseg(i) = 10;
   else
      Pmusicg(i) = (x^amusic)*exp(-x/bmusic)/(gamma(amusic+1)*bmusic^(amusic+1));
      Pvoiseg(i)  = 0.5*(x^avoise)*exp(-x/bvoise)/(gamma(avoise+1)*bvoise^(avoise+1));
   end

   Vg(i,:) = [Pmusicg(i)  Pvoiseg(i)];
   [Pmaxg(i) typeg(i)] = max(Vg(i,:));

   Vk = (sign(Vtaz1([pfpos(i):pfpos(i+1)])));
   tempV = [];
   tempV = Vta([pfpos(i):pfpos(i+1)]);
   rr = max(tempV)+0.001;
   tempV1 = tempV/rr;
   Vk0 = Vk;

   for j = 1:length(Vk)
      if (tempV1(j) < 0.1 & tempV(j) < 1.5) | tempV(j) < 1
         Vk(j) = 0;
      end
   end
   Vk1 = Vk;

   for j = 1:length(Vk)
      if (tempV1(j) < 0.4 | tempV(j) < 2 | tempV(j) < mean(tempV(j)))
         Vk1(j) = 0;
      end
   end
   Zca = [];
   Zca = Vk1.*(Vtaz1([pfpos(i):pfpos(i+1)]));

   Pol = (ones(1,length(Vk)) -  sign(Vk)).*Vk0;

   VZC = Pol.*Vtaz1([pfpos(i):pfpos(i+1)]);

   dVk = abs(Vk(2:length(Vk))-Vk(1:length(Vk)-1));

   Freq(i,1) = 50*sum(dVk)/(2*length(Vk)); %FSP%
   Freq(i,2) = length(Vk)/50;%duration in sec of the segment
   Freq(i,3) = sum(Freq(:,2));
   Freq(i,4) = zpos(i);
   Freq(i,5) = thor2(i);
   Freq(i,6) =   max(Zca);

   Pmusicg(i) = 0;
   Pvoiseg(i) = 0;
   if Freq(i,1) < 0.59 & Freq(i,2) > 2.5,
      Pmusicg(i) = 10;
   else
      Pmusicg(i) = (x^amusic)*exp(-x/bmusic)/(gamma(amusic+1)*bmusic^(amusic+1));
      Pvoiseg(i)  = 0.5*(x^avoise)*exp(-x/bvoise)/(gamma(avoise+1)*bvoise^(avoise+1));
      if x > 3,
         Pvoiseg(i) = Pvoiseg(i)+0.1;

      end

      if x > 300 ,
         Pmusicg(i) = 9;
     end

      if thor2 > 3.5
         Pvoiseg(i) = 11;
      end
      if max(Zca) > 280,
         Pmusicg(i) = 11;
         max(Zca)

      end
      if Freq(i,1) > 4.62 & Freq(i,2) > 2.5 & (thor2(i) > 0.1 | zpos(i) > 0.05),
         Pvoiseg(i) = 12;
      end

      if zpos(i) > 0.15
         Pvoiseg(i)  = 13;
      end
  end
   Vg(i,:) = [Pmusicg(i)  Pvoiseg(i)];
   [Pmaxg(i) typeg(i)] = max(Vg(i,:));

	Fsp1 = [Fsp1 Vk];

   if (Pspace(i) > 4 & thor2(i) < 1)  | (Pspace(i) > 4.5),
      type(i) = 3; %silence
      typeg(i) = 3;
   end

   if (pfpos(i+1) - pfpos(i))/50 < 0.5 & i >= 1, % short segments
      type(i) = type(i-1);
   end
end

   g = [];
   g1 = [];
   tt = [];
   pt = [];
   pm = [];
   ps = [];
   pv = [];
   pmf = [];

for i=1:l,
   tt = [tt type(i)*ones(1,pfpos(i+1)-pfpos(i))];
   pt = [pt Pmax(i)*ones(1,pfpos(i+1)-pfpos(i))];
   pm = [pm Pmusic(i)*ones(1,pfpos(i+1)-pfpos(i))];
   pv = [pv Pvoise(i)*ones(1,pfpos(i+1)-pfpos(i))];
   ps = [ps Pspace(i)*ones(1,pfpos(i+1)-pfpos(i))];
end

PosV = 100*sum(exp(-10*abs(tt-2*ones(1,length(tt)))))/length(tt);
PosM = 100*sum(exp(-10*abs(tt-ones(1,length(tt)))))/length(tt);

l1 = l;
l = length(tt);

l = l1;
 g = [];
   g1 = [];
   tt = [];
   pt = [];
   pm = [];
   ps = [];
   pv = [];
   pmf = [];

for i=1:l,
   tt = [tt typeg(i)*ones(1,pfpos(i+1)-pfpos(i))];
   pt = [pt Pmaxg(i)*ones(1,pfpos(i+1)-pfpos(i))];
   pm = [pm Pmusicg(i)*ones(1,pfpos(i+1)-pfpos(i))];
   pv = [pv Pvoiseg(i)*ones(1,pfpos(i+1)-pfpos(i))];
   ps = [ps Pspace(i)*ones(1,pfpos(i+1)-pfpos(i))];
end
l = length(tt);

PosVg = 100*sum(exp(-10*abs(tt-2*ones(1,length(tt)))))/length(tt);
PosMg = 100*sum(exp(-10*abs(tt-ones(1,length(tt)))))/length(tt);

figure(1);
subplot(5,1,1);
plot([1:l]*(finish-start-1)/l+start,tt);
title('classification type (1 : Music, 2: Voise, 3: Silence)');
subplot(5,1,2);
plot([1:l]*(finish-start-1)/l+start,pt);
title('~probability posibility of selected type');
subplot(5,1,3);
plot([1:l]*(finish-start-1)/l+start,pm);
title('~probability MUsic');
subplot(5,1,4);
plot([1:l]*(finish-start-1)/l+start,pv);
title('~probability Voise');
subplot(5,1,5);
plot([1:l]*(finish-start-1)/l+start,ps);
title('~probability silence');

for k = 1:length(Vta),
   if Vta(k) < 2 | Vta(k) < 0.1*max(Vta),
      Vtaz1(k) = 0;
   end
end
m = 100;
temp = [];
h1 = [];
temp = Vtaz1;
h1 = hist(temp,m);
h1(1) = 0;
h1 = h1/sum(h1);
a1 = [min(temp):(max(temp)-min(temp))/m:max(temp)-(max(temp)-min(temp))/m];

segbar = [];
j = 1;
i = 1;
while i <= l,
   if j <= length(fpos) & round(50*fpos(j)) == i,
      segbar(i) = 1;
      j = j+1;
   else
      segbar(i) = 0;
   end
   i = i+1;
end

segments = segbar;

figure(2);
subplot(3,1,1);
stem([1:l]*(finish-start-1)/l+start,segbar);
axis([0 duration 0 1]);
title('Segmentation');
xlabel('sec');
subplot(3,1,2);
plot([1:l]*(finish-start-1)/l+start,tt);
axis([0.5 duration 0 3.5]);
title('classification type (1 : Music, 2: Voise, 3: Silence)');
xlabel('sec');
subplot(3,1,3);
plot(start+([1:length(Vta)]*duration/length(Vta)),Vta);
axis([0 duration 0 (floor(max(Vta))+1)]);
title('RMS');
xlabel('sec');

classif = tt;


function [mCat]=sr_makeSRC4(mCat,fTw,T)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This function removes events and creates a quiescence according to the
% chosen input variables. The lat/lon position of the quiescence is
% determined randomly.
%
% Input Variables
% mCat      Earthquake catalog in zmap-format
% fTw       Duration of PSQ
% T         Starting time of PSQ
% fR        Degree of rate change (0.75 = 75% reduction)
%
% Output Variables
% mCat      Catalog with PSQ%
%
% van Stiphout Thomas ; vanstiphout@sed.ethz.ch
% Created: 14.08.2007
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

disp('zmap/src/thomas/seismicrates/sr_makeSRC4.m')

% rate decrease for grid node
fR=0.75;
fLonPSQ=-116.4;
fLatPSQ=34.3;
nN=300;
fLon0=fLonPSQ;
fLat0=fLatPSQ;

% get N nearest events for certain grid point
%     [caNodeIndices, vResolution_] = ex_CreateIndexCatalog(mCat, [fLon0 fLat0], 1, 0, nN, 99, 0.1, 0.1);
%     % transform cell array to matrix
%     vSel=cell2mat(caNodeIndices);

% get events within certain radius of a grid point
[caNodeIndices, vResolution] = ex_CreateIndexCatalog(mCat, [fLon0 fLat0], 1, 1, ...
    100, 10, 0.1, 0.1);
% transform cell array to matrix
caNodeIndices_=cell2mat(caNodeIndices);
vSel=caNodeIndices_;
% transform cell array to matrix
vResolution_=cell2mat(vResolution);

% control plots
% figure;plot(mCat(:,1),mCat(:,2),'.k');
% hold on;plot(mCat(vSel,1),mCat(vSel,2),'dr');

% select from N events the one in the quiescence time period
vSel3=find((mCat(vSel,3)>T-fTw) & (mCat(vSel,3)<T));
% create help matrix for events in quite period
vSel4=zeros(size(vSel3,1),1);
% determine number of events to remove
fRemove=fR;
% create vector with % events to be removed (=1)
vSel4(1:ceil(size(vSel4,1)*fRemove))=1;
vSel4=logical(vSel4(randperm(size(vSel4,1))));
% Select indices of the N events to be removed
% vSel5 are events to be removed (indices from N events)
vSel5=vSel3(vSel4,1);
% create position of events in mCatalog to be removed
vSelNaN=vSel(vSel5);
% tag events to be removed with NaN
mCat(vSelNaN,1)=NaN;
mCat=mCat(~isnan(mCat(:,1)),:);

%% calculate rate increase in box

fBvalue=1;
fInc=0.1;
fMinLat=33.6;
fMaxLat=33.75;
fMinLon=-116.75;
fMaxLon=-116.5;
mPoly=[fMaxLon fMinLat;fMaxLon fMaxLat;fMinLon fMaxLat;fMinLon fMinLat];
fMinTime=T-fTw;
fMaxTime=T;

[vSel,bnd]=inpoly(mCat(:,1:2),mPoly);
vSel=find(vSel==1);
nNSel=size(vSel,1);
mNewCat=nan(nNSel,size(mCat,2));

% Create magnitudes
[mNewCat] = syn_create_magnitudes(mNewCat, fBvalue, min(mCat(:,6)), fInc);
% Randomize
rng('shuffle');

fMaxDepth=max(mCat(:,7));
fMinDepth=min(mCat(:,7));
% Create location
mNewCat(:,1) = rand(nNSel, 1) * (fMaxLon-fMinLon) + fMinLon;
mNewCat(:,2) = rand(nNSel, 1) * (fMaxLat-fMinLat) + fMinLat;
mNewCat(:,7) = rand(nNSel, 1) * (fMaxDepth-fMinDepth) + fMinDepth;

% Randomize
rng('shuffle');

% Create focal times
mNewCat(:,3) = rand(nNSel, 1) * (fMaxTime-fMinTime) + fMinTime;
% vst: datevec does not transform mNewCat(:,3) properly. Replaced by
% decyear2mat.
mNewCat(:,3)=mNewCat(randperm(size(mNewCat,1)),3);
% [mNewCat(:,10) mNewCat(:,4) mNewCat(:,5) mNewCat(:,8) mNewCat(:,9)] = datevec(mNewCat(:,3));
[mNewCat(:,10) mNewCat(:,4) mNewCat(:,5) mNewCat(:,8) mNewCat(:,9) tmp] = decyear2mat(mNewCat(:,3));

% Remove column 10 (seconds)
% mNewCat = mNewCat(:,1:end);
mCat=[mCat; mNewCat];
[Xsort, Xi]=sort(mCat(:,3),1);
mCat=mCat(Xi,:);


function [data, xAxis, yAxis, misc] = impload(filename)
% Reads intensity map data from PerkinElmer block structured files.
% This version is compatible with '1994' standard IMP files.
% IMP files have 2 constant data intervals.
%
% [data, xAxis, yAxis, misc] = impload(filename):
%   data: length(x) * length(y) 2D array
%   xAxis: vector for horizontal axis (e.g. micrometers)
%   yAxis: vector for vertical axis (e.g. micrometers)
%   misc: miscellanous information in name,value pairs

% Copyright (C)2007 PerkinElmer Life and Analytical Sciences
% Stephen Westlake, Seer Green
%
% History
% 2007-04-24 SW     Initial version

% Block IDs
DS3C2IData            = 5108;   % 3D DS: header info
DS3C2IPts             = 5109;   % 3D DS: point coordinates (CvCoOrdArray)
DS3C2IPtsCont         = 5110;   % 3D DS: point coordinates (continuator for large CvCoOrdArray)
DS3C2IHistory         = 5111;   % 3D DS: history record
DSet3DC2DIBlock       = 5112;   % 3D DS: the block containing all other 3d blocks.

fid = fopen(filename,'r');
if fid == -1
    error('Cannot open the file.');
    return
end

% Fixed file header of signature and description
signature = setstr(fread(fid, 4, 'uchar')');
if ~strcmp(signature, 'PEPE')
    error('This is not a PerkinElmer block structured file.');
    return
end
description = setstr(fread(fid, 40, 'uchar')');

% Initialize a variable so we can tell if we have read it.
xLen = int16(0);

% The rest of the file is a list of blocks
while ~feof(fid)
    blockID = fread(fid,1,'int16');
    blockSize = fread(fid,1,'int32');

    % feof does not go true until after the read has failed.
    if feof(fid)
        break
    end

    switch blockID
        case DS3C2IData % Dataset header
            len = fread(fid,1,'int16');
            alias = setstr(fread(fid, len, 'uchar')');

            xDelta = fread(fid, 1, 'double');
            yDelta = fread(fid, 1, 'double');
            x0 = fread(fid, 1, 'double');
            y0 = fread(fid, 1, 'double');
            xLen = fread(fid, 1, 'int32');
            yLen = fread(fid, 1, 'int32');

            len = fread(fid, 1, 'int16');
            xLabel = setstr(fread(fid, len, 'uchar')');
            len = fread(fid, 1, 'int16');
            yLabel = setstr(fread(fid, len, 'uchar')');
            len = fread(fid, 1, 'int16');
            zLabel = setstr(fread(fid, len, 'uchar')');

        case DS3C2IPts  % This contains the first block
            count = blockSize / 8;
            data = fread(fid, count, 'double');

        case DS3C2IPtsCont % Continuation blocks
            countCont = blockSize / 8;
            data(count + 1 : count + countCont) = fread(fid, countCont, 'double');
            count = count + countCont;

        otherwise               % unknown block, just seek past it
            fseek(fid, blockSize, 'cof');
    end
end
fclose(fid);

if xLen == 0
    error('The file does not contain spectral image data.');
    return
end

% Reshape the linear array we have read in and flip so the
% data is in the correct aspect for image(data) with 1,1 at the top.
data = flipud(transpose(reshape(data, xLen, yLen)));

% Expand the axes specifications into vectors
% The yAxis is reversed to match the flip.
xEnd = x0 + (xLen - 1) * xDelta;
yEnd = y0 + (yLen - 1) * yDelta;
xAxis = x0 : xDelta : xEnd;
yAxis = yEnd : -yDelta : y0;

% Return the other details as name,value pairs
misc(1,:) = {'xLabel', xLabel};
misc(2,:) = {'yLabel', yLabel};
misc(3,:) = {'zLabel', zLabel};
misc(4,:) = {'alias', alias};


function varargout = pivotplot(varargin)
%PIVOTPLOT   Semilogy plot of pivot values.
%   PIVOTPLOT( F ) semilogy plot related to the pivots values taken during
%   the construction of the SPHEREFUN F.
%
%   H = PIVOTPLOT( F ) returns a handle H to the figure.
%
%   PIVOTPLOT( F, S ) allows further plotting options, such as linestyle,
%   linecolor, etc. If S contains a string 'LOGLOG', the pseudo sig will be
%   displayed on a log-log scale.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

[varargout{1:nargout}] = pivotplot@separableApprox(varargin{:});

end


function result = HIDC_enterFunc(numIdentical,numAlike,numDistinct,numIter,inputPath)
    %% ======================================================================
    %%STEP 1: load the data
    fprintf('start load the data...\n');
%     fprintf(inputPath);
%     fprintf('\n');
    [TrainData, TestData, TrainLabel, TestLabel, numSource, numTrain, numTarget, numTest] = HIDC_loadData(inputPath);
      TrainData = double(TrainData);
      TestData = double(TestData);
      TrainLabel = double(TrainLabel);
      TestLabel = double(TestLabel);

      TrainData = sparse(TrainData);
      TestData = sparse(TestData);

    fprintf('training the model and testing...\n');
    [Results_TTL, Gt_TTL] = GenerativeTriTL(TrainData, TestData, TrainLabel, TestLabel, numIdentical, numAlike, numDistinct, numIter, numSource, numTrain, numTarget, numTest);

    result = Results_TTL(:,2)';
    result = result(end);
end


function [p,infeasible] = detectRedundantInfeasibleSOCPRows(p)
infeasible = 0;
if any(p.K.q)
    newEqualities = [];
    top = startofSOCPCone(p.K);
    for j = 1:length(p.K.q)
        % Looking for norm(x) <= k and k=0 or k<0
        m = p.K.q(j);
        M = p.F_struc(top:top+m-1,:);
        fixed = ~any(M(1,2:end));
        if fixed
            if M(1) <= -p.options.bnb.feastol
                infeasible = 1;
                return
            elseif M(1) <= 0
                % Not numerically infeasible,
                % but at least says x = 0
                equalityRows = M(2:m,:);
                newEqualities = [newEqualities;equalityRows];
                p.F_struc(top:top+m-1,:) = [];
                p.K.q(j) = 0;
            end
            top = top + p.K.q(j);
        end
    end
    p = addEquality(p,newEqualities);
    p.K.q(p.K.q == 0) = [];
end