%% DEMO_febio_0069_must_points_export
% Below is a demonstration for:
%
% * Building geometry for a cube with hexahedral elements
% * Defining the boundary conditions
% * Coding the febio structure
% * Running the model
% * Importing and visualizing the displacement and stress results

%% Keywords
%
% * febio_spec version 2.5
% * febio, FEBio
% * uniaxial loading
% * compression, tension, compressive, tensile
% * displacement control, displacement boundary condition
% * hexahedral elements, hex8
% * cube, box, rectangular
% * static, solid
% * hyperelastic, Ogden
% * displacement logfile
% * stress logfile

%%

clear; close all; clc;

%% Plot settings
fontSize=20;
faceAlpha1=0.8;
markerSize=40;
markerSize2=20;
lineWidth=3;

%% Control parameters

% Path names
defaultFolder = fileparts(fileparts(mfilename('fullpath')));
savePath=fullfile(defaultFolder,'data','temp');

% Defining file names
febioFebFileNamePart='tempModel';
febioFebFileName=fullfile(savePath,[febioFebFileNamePart,'.feb']); %FEB file name
febioLogFileName=fullfile(savePath,[febioFebFileNamePart,'.txt']); %FEBio log file name
febioLogFileName_disp=[febioFebFileNamePart,'_disp_out.txt']; %Log file name for exporting displacement
febioLogFileName_stress=[febioFebFileNamePart,'_stress_out.txt']; %Log file name for exporting stress

%Specifying dimensions and number of elements
cubeSize=10;
sampleWidth=cubeSize; %Width
sampleThickness=cubeSize; %Thickness
sampleHeight=cubeSize; %Height
pointSpacings=2*ones(1,3); %Desired point spacing between nodes
numElementsWidth=round(sampleWidth/pointSpacings(1)); %Number of elemens in dir 1
numElementsThickness=round(sampleThickness/pointSpacings(2)); %Number of elemens in dir 2
numElementsHeight=round(sampleHeight/pointSpacings(3)); %Number of elemens in dir 3

%Define applied displacement
appliedStrain=0.4; %Linear strain (Only used to compute applied stretch)
loadingOption='tension'; % or 'tension'
switch loadingOption
    case 'compression'
        stretchLoad=1-appliedStrain; %The applied stretch for uniaxial loading
    case 'tension'
        stretchLoad=1+appliedStrain; %The applied stretch for uniaxial loading
end
displacementMagnitude=(stretchLoad*sampleHeight)-sampleHeight; %The displacement magnitude

%Material parameter set
c1=0.7; %Shear-modulus-like parameter
m1=2; %Material parameter setting degree of non-linearity
k_factor=500; %Bulk modulus factor
k=c1*k_factor; %Bulk modulus
formulationType='uncoupled'; %coupled

% FEA control settings
numTimeStepsAnalysis=20; %Number of time steps desired
max_refs=25; %Max reforms
max_ups=0; %Set to zero to use full-Newton iterations
opt_iter=6; %Optimum number of iterations
max_retries=5; %Maximum number of retires
dtmin=(1/numTimeStepsAnalysis)/100; %Minimum time step size
dtmax=(1/numTimeStepsAnalysis); %Maximum time step size

%Define must points
numStepsOutput=11;
t_load_curve=linspace(0,1,numStepsOutput);
dtmax_load_curve=dtmax.*ones(size(t_load_curve));

%% Creating model geometry and mesh
% A box is created with tri-linear hexahedral (hex8) elements using the
% |hexMeshBox| function. The function offers the boundary faces with
% seperate labels for the top, bottom, left, right, front, and back sides.
% As such these can be used to define boundary conditions on the exterior.

% Create a box with hexahedral elements
cubeDimensions=[sampleWidth sampleThickness sampleHeight]; %Dimensions
cubeElementNumbers=[numElementsWidth numElementsThickness numElementsHeight]; %Number of elements
outputStructType=2; %A structure compatible with mesh view
[meshStruct]=hexMeshBox(cubeDimensions,cubeElementNumbers,outputStructType);

%Access elements, nodes, and faces from the structure
E=meshStruct.elements; %The elements
V=meshStruct.nodes; %The nodes (vertices)
Fb=meshStruct.facesBoundary; %The boundary faces
Cb=meshStruct.boundaryMarker; %The "colors" or labels for the boundary faces
elementMaterialIndices=ones(size(E,1),1); %Element material indices

%%
% Plotting model boundary surfaces and a cut view

hFig=cFigure;

subplot(1,2,1); hold on;
title('Model boundary surfaces and labels','FontSize',fontSize);
gpatch(Fb,V,Cb,'k',faceAlpha1);
colormap(gjet(6)); icolorbar;
axisGeom(gca,fontSize);

hs=subplot(1,2,2); hold on;
title('Cut view of solid mesh','FontSize',fontSize);
optionStruct.hFig=[hFig hs];
meshView(meshStruct,optionStruct);
axisGeom(gca,fontSize);

drawnow;

%% Defining the boundary conditions
% The visualization of the model boundary shows colors for each side of the
% cube. These labels can be used to define boundary conditions.

%Define supported node sets
logicFace=Cb==1; %Logic for current face set
Fr=Fb(logicFace,:); %The current face set
bcSupportList_X=unique(Fr(:)); %Node set part of selected face

logicFace=Cb==3; %Logic for current face set
Fr=Fb(logicFace,:); %The current face set
bcSupportList_Y=unique(Fr(:)); %Node set part of selected face

logicFace=Cb==5; %Logic for current face set
Fr=Fb(logicFace,:); %The current face set
bcSupportList_Z=unique(Fr(:)); %Node set part of selected face

%Prescribed displacement nodes
logicPrescribe=Cb==6; %Logic for current face set
Fr=Fb(logicPrescribe,:); %The current face set
bcPrescribeList=unique(Fr(:)); %Node set part of selected face

%%
% Visualizing boundary conditions. Markers plotted on the semi-transparent
% model denote the nodes in the various boundary condition lists.

hf=cFigure;
title('Boundary conditions','FontSize',fontSize);
xlabel('X','FontSize',fontSize); ylabel('Y','FontSize',fontSize); zlabel('Z','FontSize',fontSize);
hold on;

gpatch(Fb,V,'kw','k',0.5);

hl(1)=plotV(V(bcSupportList_X,:),'r.','MarkerSize',markerSize);
hl(2)=plotV(V(bcSupportList_Y,:),'g.','MarkerSize',markerSize);
hl(3)=plotV(V(bcSupportList_Z,:),'b.','MarkerSize',markerSize);
hl(4)=plotV(V(bcPrescribeList,:),'k.','MarkerSize',markerSize);

legend(hl,{'BC x support','BC y support','BC z support','BC z prescribe'});

axisGeom(gca,fontSize);
camlight headlight;
drawnow;

%% Defining the FEBio input structure
% See also |febioStructTemplate| and |febioStruct2xml| and the FEBio user
% manual.

%Get a template with default settings
[febio_spec]=febioStructTemplate;

%febio_spec version
febio_spec.ATTR.version='2.5';

%Module section
febio_spec.Module.ATTR.type='solid';

%Control section
febio_spec.Control.time_stepper=rmfield(febio_spec.Control.time_stepper,'dtmax');

febio_spec.Control.analysis.ATTR.type='static';
febio_spec.Control.title='Cube analysis';
febio_spec.Control.time_steps=numTimeStepsAnalysis;
febio_spec.Control.step_size=1/numTimeStepsAnalysis;
febio_spec.Control.time_stepper.dtmin=dtmin;
febio_spec.Control.time_stepper.dtmax.VAL=dtmax;
febio_spec.Control.time_stepper.dtmax.ATTR.lc=2;
febio_spec.Control.time_stepper.max_retries=max_retries;
febio_spec.Control.time_stepper.opt_iter=opt_iter;
febio_spec.Control.max_refs=max_refs;
febio_spec.Control.max_ups=max_ups;

febio_spec.Control.plot_level='PLOT_MUST_POINTS';
febio_spec.Control.output_level='OUTPUT_MUST_POINTS';

%Material section
switch formulationType
    case 'coupled'
        febio_spec.Material.material{1}.ATTR.type='Ogden unconstrained';
        febio_spec.Material.material{1}.ATTR.id=1;
        febio_spec.Material.material{1}.c1=c1;
        febio_spec.Material.material{1}.m1=m1;
        febio_spec.Material.material{1}.c2=c1;
        febio_spec.Material.material{1}.m2=-m1;
        febio_spec.Material.material{1}.cp=k;
    case 'uncoupled'
        febio_spec.Material.material{1}.ATTR.type='Ogden';
        febio_spec.Material.material{1}.ATTR.id=1;
        febio_spec.Material.material{1}.c1=c1;
        febio_spec.Material.material{1}.m1=m1;
        febio_spec.Material.material{1}.c2=c1;
        febio_spec.Material.material{1}.m2=-m1;
        febio_spec.Material.material{1}.k=k;
end

%Geometry section
% -> Nodes
febio_spec.Geometry.Nodes{1}.ATTR.name='nodeSet_all'; %The node set name
febio_spec.Geometry.Nodes{1}.node.ATTR.id=(1:size(V,1))'; %The node id's
febio_spec.Geometry.Nodes{1}.node.VAL=V; %The nodel coordinates

% -> Elements
febio_spec.Geometry.Elements{1}.ATTR.type='hex8'; %Element type of this set
febio_spec.Geometry.Elements{1}.ATTR.mat=1; %material index for this set
febio_spec.Geometry.Elements{1}.ATTR.name='Cube'; %Name of the element set
febio_spec.Geometry.Elements{1}.elem.ATTR.id=(1:1:size(E,1))'; %Element id's
febio_spec.Geometry.Elements{1}.elem.VAL=E;

% -> NodeSets
febio_spec.Geometry.NodeSet{1}.ATTR.name='bcSupportList_X';
febio_spec.Geometry.NodeSet{1}.node.ATTR.id=bcSupportList_X(:);

febio_spec.Geometry.NodeSet{2}.ATTR.name='bcSupportList_Y';
febio_spec.Geometry.NodeSet{2}.node.ATTR.id=bcSupportList_Y(:);

febio_spec.Geometry.NodeSet{3}.ATTR.name='bcSupportList_Z';
febio_spec.Geometry.NodeSet{3}.node.ATTR.id=bcSupportList_Z(:);

febio_spec.Geometry.NodeSet{4}.ATTR.name='bcPrescribeList';
febio_spec.Geometry.NodeSet{4}.node.ATTR.id=bcPrescribeList(:);

%Boundary condition section
% -> Fix boundary conditions
febio_spec.Boundary.fix{1}.ATTR.bc='x';
febio_spec.Boundary.fix{1}.ATTR.node_set=febio_spec.Geometry.NodeSet{1}.ATTR.name;
febio_spec.Boundary.fix{2}.ATTR.bc='y';
febio_spec.Boundary.fix{2}.ATTR.node_set=febio_spec.Geometry.NodeSet{2}.ATTR.name;
febio_spec.Boundary.fix{3}.ATTR.bc='z';
febio_spec.Boundary.fix{3}.ATTR.node_set=febio_spec.Geometry.NodeSet{3}.ATTR.name;

% -> Prescribe boundary conditions
febio_spec.Boundary.prescribe{1}.ATTR.bc='z';
febio_spec.Boundary.prescribe{1}.ATTR.node_set=febio_spec.Geometry.NodeSet{4}.ATTR.name;
febio_spec.Boundary.prescribe{1}.scale.ATTR.lc=1;
febio_spec.Boundary.prescribe{1}.scale.VAL=1;
febio_spec.Boundary.prescribe{1}.relative=1;
febio_spec.Boundary.prescribe{1}.value=displacementMagnitude;

%LoadData section
febio_spec.LoadData.loadcurve{1}.ATTR.id=1;
febio_spec.LoadData.loadcurve{1}.ATTR.type='linear';
febio_spec.LoadData.loadcurve{1}.point.VAL=[0 0; 1 1];

febio_spec.LoadData.loadcurve{2}.ATTR.id=2;
febio_spec.LoadData.loadcurve{2}.ATTR.type='linear';
febio_spec.LoadData.loadcurve{2}.point.VAL=[t_load_curve(:) dtmax_load_curve(:)];

%Output section
% -> log file
febio_spec.Output.logfile.ATTR.file=febioLogFileName;
febio_spec.Output.logfile.node_data{1}.ATTR.file=febioLogFileName_disp;
febio_spec.Output.logfile.node_data{1}.ATTR.data='ux;uy;uz';
febio_spec.Output.logfile.node_data{1}.ATTR.delim=',';
febio_spec.Output.logfile.node_data{1}.VAL=1:size(V,1);

febio_spec.Output.logfile.element_data{1}.ATTR.file=febioLogFileName_stress;
febio_spec.Output.logfile.element_data{1}.ATTR.data='sz';
febio_spec.Output.logfile.element_data{1}.ATTR.delim=',';
febio_spec.Output.logfile.element_data{1}.VAL=1:size(E,1);

%% Quick viewing of the FEBio input file structure
% The |febView| function can be used to view the xml structure in a MATLAB
% figure window.

%%
% |febView(febio_spec); %Viewing the febio file|

%% Exporting the FEBio input file
% Exporting the febio_spec structure to an FEBio input file is done using
% the |febioStruct2xml| function.

febioStruct2xml(febio_spec,febioFebFileName); %Exporting to file and domNode

%% Running the FEBio analysis
% To run the analysis defined by the created FEBio input file the
% |runMonitorFEBio| function is used. The input for this function is a
% structure defining job settings e.g. the FEBio input file name. The
% optional output runFlag informs the user if the analysis was run
% succesfully.

febioAnalysis.run_filename=febioFebFileName; %The input file name
febioAnalysis.run_logname=febioLogFileName; %The name for the log file
febioAnalysis.disp_on=1; %Display information on the command window
febioAnalysis.disp_log_on=1; %Display convergence information in the command window
febioAnalysis.runMode='external';%'internal';
febioAnalysis.t_check=0.25; %Time for checking log file (dont set too small)
febioAnalysis.maxtpi=1e99; %Max analysis time
febioAnalysis.maxLogCheckTime=10; %Max log file checking time

[runFlag]=runMonitorFEBio(febioAnalysis);%START FEBio NOW!!!!!!!!

%% Import FEBio results

if runFlag==1 %i.e. a succesful run

    %%
    % Importing nodal displacements from a log file
    dataStruct=importFEBio_logfile(fullfile(savePath,febioLogFileName_disp),1,1);

    %Access data
    N_disp_mat=dataStruct.data; %Displacement
    timeVec=dataStruct.time; %Time

    %Create deformed coordinate set
    V_DEF=N_disp_mat+repmat(V,[1 1 size(N_disp_mat,3)]);

    %%
    % Plotting the simulated results using |anim8| to visualize and animate
    % deformations

    DN_magnitude=sqrt(sum(N_disp_mat(:,:,end).^2,2)); %Current displacement magnitude

    % Create basic view and store graphics handle to initiate animation
    hf=cFigure; %Open figure
    gtitle([febioFebFileNamePart,': Press play to animate']);
    title('Displacement magnitude [mm]','Interpreter','Latex')
    hp=gpatch(Fb,V_DEF(:,:,end),DN_magnitude,'k',1); %Add graphics object to animate
    hp.Marker='.';
    hp.MarkerSize=markerSize2;
    hp.FaceColor='interp';
    gpatch(Fb,V,0.5*ones(1,3),'k',0.25); %A static graphics object

    axisGeom(gca,fontSize);
    colormap(gjet(250)); colorbar;
    caxis([0 max(DN_magnitude)]); caxis manual;
    axis(axisLim(V_DEF)); %Set axis limits statically
    camlight headlight;

    % Set up animation features
    animStruct.Time=timeVec; %The time vector
    for qt=1:1:size(N_disp_mat,3) %Loop over time increments
        DN_magnitude=sqrt(sum(N_disp_mat(:,:,qt).^2,2)); %Current displacement magnitude

        %Set entries in animation structure
        animStruct.Handles{qt}=[hp hp]; %Handles of objects to animate
        animStruct.Props{qt}={'Vertices','CData'}; %Properties of objects to animate
        animStruct.Set{qt}={V_DEF(:,:,qt),DN_magnitude}; %Property values for to set in order to animate
    end
    anim8(hf,animStruct); %Initiate animation feature
    drawnow;

    %%
    % Importing element stress from a log file
    dataStruct=importFEBio_logfile(fullfile(savePath,febioLogFileName_stress),1,1);

    %Access data
    E_stress_mat=dataStruct.data;

    %%
    % Plotting the simulated results using |anim8| to visualize and animate
    % deformations

    [CV]=faceToVertexMeasure(E,V,E_stress_mat(:,:,end));

    % Create basic view and store graphics handle to initiate animation
    hf=cFigure; %Open figure
    gtitle([febioFebFileNamePart,': Press play to animate']);
    title('$\sigma_{zz}$ [MPa]','Interpreter','Latex')
    hp=gpatch(Fb,V_DEF(:,:,end),CV,'k',1); %Add graphics object to animate
    hp.Marker='.';
    hp.MarkerSize=markerSize2;
    hp.FaceColor='interp';
    gpatch(Fb,V,0.5*ones(1,3),'k',0.25); %A static graphics object

    axisGeom(gca,fontSize);
    colormap(gjet(250)); colorbar;
    caxis([min(E_stress_mat(:)) max(E_stress_mat(:))]);
    axis(axisLim(V_DEF)); %Set axis limits statically
    camlight headlight;

    % Set up animation features
    animStruct.Time=timeVec; %The time vector
    for qt=1:1:size(N_disp_mat,3) %Loop over time increments

        [CV]=faceToVertexMeasure(E,V,E_stress_mat(:,:,qt));

        %Set entries in animation structure
        animStruct.Handles{qt}=[hp hp]; %Handles of objects to animate
        animStruct.Props{qt}={'Vertices','CData'}; %Properties of objects to animate
        animStruct.Set{qt}={V_DEF(:,:,qt),CV}; %Property values for to set in order to animate
    end
    anim8(hf,animStruct); %Initiate animation feature
    drawnow;

    %%
    % Calculate metrics to visualize stretch-stress curve

    DZ_set=N_disp_mat(bcPrescribeList,end,:); %Z displacements of the prescribed set
    DZ_set=mean(DZ_set,1); %Calculate mean Z displacements across nodes
    stretch_sim=(DZ_set(:)+sampleHeight)./sampleHeight; %Derive stretch
    stress_cauchy_sim=mean(squeeze(E_stress_mat(:,end,:)),1)';

    %%
    % Visualize stress-stretch curve

    cFigure; hold on;
    title('Uniaxial stress-stretch curve','FontSize',fontSize);
    xlabel('$\lambda$ [.]','FontSize',fontSize,'Interpreter','Latex');
    ylabel('$\sigma_{zz}$ [MPa]','FontSize',fontSize,'Interpreter','Latex');

    plot(stretch_sim(:),stress_cauchy_sim(:),'r-','lineWidth',lineWidth);

    view(2); axis tight;  grid on; axis square; box on;
    set(gca,'FontSize',fontSize);
    drawnow;

end

%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>

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


function v = ToVector(im)
sz = size(im);
if size(im,3)==3
    v = reshape(im, [prod(sz(1:2)) 3]);
else
    v = reshape(im, [prod(sz(1:2)) 1]);
end


%
% LibQPEP: A Library for Globally Optimal Solving Quadratic Pose Estimation Problems (QPEPs),
%          It also gives highly accurate uncertainty description of the solutions.
%
%
% Article:
%      Wu, J., Zheng, Y., Gao, Z., Jiang, Y., Hu, X., Zhu, Y., Jiao, J., Liu, M. (2020)
%           Quadratic Pose Estimation Problems: Unified Solutions,
%           Solvability/Observability Analysis and Uncertainty Description
%           in A Globally Optimal Framework.
%
%
% Authors:      Jin Wu and Ming Liu
% Affiliation:  Hong Kong University of Science and Technology (HKUST)
% Emails:       jin_wu_uestc@hotmail.com; eelium@ust.hk
% Websites:     https://zarathustr.github.io
%               https://ram-lab.com

function showSyms(obj)
for i = 1 : length(obj)
    assignin('caller', char(obj(i)), obj(i));
end
end


function pass = test_removeDeltas(pref)

% Get preferences:
if ( nargin < 1 )
    pref = chebfunpref();
end

% Test that the deltas are removed.
x = chebfun(@(x) x, [0 1], pref);
f = dirac(x - 0.2) + diff(dirac(x-1), 2);
thenorm = norm(removeDeltas(f), Inf); % Is infinite if deltas are present.
pass(1) = ( thenorm < Inf );

% Test that pointValues are changed.
f = dirac(x);
val = feval(removeDeltas(f), 0);
pass(2) = ( val == 0 );

% Test that removeDeltas is the identity for classicfuns.
f = sin(x);
g = removeDeltas(f);
pass(3) = isequal(f, g);

end


function [At,b,c,K]=fromsdpa(fname)
% readsdpa Reads SDP problem from sparse SDPA-formatted input file.
%    [At,b,c,K] = readsdpa(fname) produces conic optimization problem
%    data, as can be used by sedumi. "fname" contains a full pathname
%    to the SDPA 4.10-formatted file. (SDPA is a stand-alone solver for
%    semidefinite programming, by Fujisawa, Kojima and Nakata.  It is
%    used as a standard format in the collection SDPLIB by Borchers.)
%
%    To read and solve the problem "arch0", you may type
%
%    [At,b,c,K] = readsdpa('arch0.dat-s');
%    [x,y,info] = sedumi(At,b,c,K);
%
%    The above 2 lines assume that arch0.dat-s is somewhere in your MATLAB
%    search path, that it is not compressed, and that you know the extension
%    'dat-s'.  To alleviate these conditions, you may like to use the script
%    GETPROBLEM.
%
% SEE ALSO SeDuMi, getproblem, frompack, prelp.

%
% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA  (since 1.1)
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
% 02110-1301, USA%

fid = fopen(fname, 'r');
if fid == -1
    error('File not found.')
end
%The number of equality constraints is the first number in the file
m='';
while(isempty(m))
    m = fscanf(fid,'%d',1);
    if fgetl(fid) == -1;
        fclose(fid);
        error('Invalid SDPA file. Number of equality constraints not found.')
    end
end
%The number of semidefinite blocks
nblocks = fscanf(fid, '%d', 1);
if isempty(nblocks)
    fclose(fid);
    error('Invalid SDPA file. Number of semidefinite blocks not found.')
end
fgetl(fid);
%The dimension of the blocks
%Negative means diagonal block, we convert that to nonnegative variables
%.,(){} are omitted
dims = sscanf(regexprep(fgetl(fid), '[\.\,(){}]', ' '), '%d', nblocks)';
%Dimensions cannot be 0, and their number must be nblocks
if any(dims == 0) || length(dims) ~= nblocks
    fclose(fid);
    error('Invalid SDPA file. Invalid semidefinite block dimensions.')
end
nblocks = length(dims);
N = -sum(dims(dims<0)) + sum(dims(dims>0).^2);
%Create a vector with the offsets of the blocks.
%Starting with the first component, how many positions later do SDP blocks
%start
%This is one less than K.blkstart (inside sedumi)
%Diagonal and one dimensional blocks are coming first
loffset = 0;
sdpoffset = sum(abs(dims(dims <= 1) ));
offset = zeros(1, nblocks);
for i = 1:nblocks
    if dims(i) <= 1
        offset(i) = loffset;
        loffset = loffset+abs(dims(i));
    else
        offset(i) = sdpoffset;
        sdpoffset = sdpoffset+dims(i)^2;
    end
end
%This is needed so that we can compute where the subsequent columns start
%in a block
stride = dims;
stride(stride<0) = 0;

%Vector b
%,(){} are omitted
b = sscanf(regexprep(fgetl(fid),'[\,(){}]',' '),'%f',m);
if length(b) ~= m
    fclose(fid);
    error('Invalid SDPA file. The right-hand side vector is not of the right dimension.')
end
%If b is very sparse then we store it as sparse
if nnz(b)/m < 0.1
    b=sparse(b);
end

%Coefficients
%It is much faster to get all the numbers at once than to read the file
%line by line
try
    E = fscanf(fid,'%d %d %d %d %f',[5. inf]);
catch
    fclose(fid);
    error('Invalid SDPA file. Error reading the coefficients.')
end
fclose(fid);
%We are done with the file

%Extract the objective
cE = E(:,E(1,:)==0);

%Repeating indices in the sparse matrix structure create the sum of
%elements, we need to clear one for the diagonals
data2 = cE(5,:);
data2(cE(3,:)==cE(4,:)) = 0;
%we need the minus sign because the SDPA format assumes maximization while
%SeDuMi uses minimization by default
%This magic reshuffles the coefficients to the right place
c = -sparse([offset(cE(2,:))+(cE(3,:)-1).*stride(cE(2,:))+cE(4,:),offset(cE(2,:))+(cE(4,:)-1).*stride(cE(2,:))+cE(3,:)],...
    1,...
    [cE(5,:),data2],...
    N,1);
clear cE data2

%Get rid of the objective coefficients from E
AtE = E(:,E(1,:)~=0);
clear E
%Take all the coefficients
data2 = AtE(5,:);
%The coefficients for the diagonal elements in the blocks
data2(AtE(3,:)==AtE(4,:)) = 0;
At = sparse([offset(AtE(2,:))+(AtE(3,:)-1).*stride(AtE(2,:))+AtE(4,:),offset(AtE(2,:))+(AtE(4,:)-1).*stride(AtE(2,:))+AtE(3,:)],...
    [AtE(1,:),AtE(1,:)],...
    [AtE(5,:),data2],...
    N,m);
clear AtE data2

K.l = -sum(dims(dims<0)) + sum(dims==1);
K.s = dims(dims>1);

%Finally, let us correct the sparsity
%c and At are always stored as sparse
[i,j,v] = find(c);
c = sparse(i,1,v,N,1);
[i,j,v] = find(At);
At = sparse(i,j,v,N,m);


function SyntaxAnalysis_Callback(hObject, eventdata, handles)

[filename, filepath] = uigetfile({'*.mat;*.xlsx'},'Select Detection Files OR Exported Detections','MultiSelect', 'on',char(handles.data.settings.detectionfolder));
if isnumeric(filename); return; end
filename = cellstr(filename);

settings = inputdlg({'Maximum bout seperation (s)','Exclude Classes with frequency below (0-1)'},'Syntax',[1 50],{'2','.01'});
boutlength = str2num(settings{1});
minfreq = str2num(settings{2});

[~,~,ext] = fileparts(filename{1});

h = waitbar(0,'Loading Files');
%% Load Files
AllCalls = table([],[],[],[],[],'VariableNames',{'BeginTime_s_','Label','File','Bout','Accepted'});

if strcmp(ext,'.mat')
    for i = 1:length(filename)
        Calls = loadCallfile([filepath filename{i}],handles);

        Calls = Calls(Calls.Accept == 1, :);
        begintime = Calls.Box(:,1); % Get Box Position
        CallClass = Calls.Type;
        dist = pdist2(begintime,begintime);
        dist(dist > boutlength) = 0;
        G = graph(dist);
        bout = conncomp(G)';

        try
            g = table(begintime, CallClass, repmat(i,height(Calls),1), bout, Calls.Accept,'VariableNames',{'BeginTime_s_','Label','File','Bout','Accepted'});
            AllCalls = [AllCalls; g];
            waitbar(i/length(filename),h)
        catch
            warning('No Accepted Calls in File');
        end

    end
elseif strcmp(ext,'.xlsx')
    for i = 1:length(filename)
        t = readtable([filepath filename{i}]);
        t = t(t.Accepted == 1,{'Accepted' 'BeginTime_s_','Label'});
        dist = pdist2(t.BeginTime_s_,t.BeginTime_s_);
        dist(dist > boutlength) = 0;
        G = graph(dist);
        bout = conncomp(G)';
        try
            g = table(bout,repmat(i,height(t),1),'VariableNames',{'Bout','File'});
            AllCalls = [AllCalls; g t];
            waitbar(i/length(filename),h)
        catch
            warning('No Accepted Calls in File');
        end

    end
end
AllCalls.Label = categorical(AllCalls.Label);
AllCalls = sortrows(AllCalls,{'File' 'BeginTime_s_'});

%% Exclude rare classes and rejected calls
catcounts = countcats(AllCalls.Label);
CommonClasses = (catcounts ./ sum(catcounts)) > minfreq;
cats = categories(AllCalls.Label);
goodCalls = any(AllCalls.Label == cats(CommonClasses)',2);
AllCalls = AllCalls(AllCalls.Accepted == 1 & goodCalls ,:);
AllCalls.Label = removecats(AllCalls.Label);
cats = categories(AllCalls.Label);

%% Create Transition Table
counts = [];
for i = 1:length(cats)
    for j = 1:length(cats)
        %         counts(j,i) = mean((AllCalls{1:end-1,'Label'} == cats{i}) & (AllCalls{2:end,'Label'} == cats{j}));
        x = sum(...
            ((AllCalls{1:end-1,'Label'} == cats{i}) & (AllCalls{2:end,'Label'} == cats{j})) & ...
            (AllCalls{1:end-1,'Bout'} == AllCalls{2:end,'Bout'}) &...
            (AllCalls{1:end-1,'File'} == AllCalls{2:end,'File'}));
        n = sum(AllCalls{2:end,'Label'} == cats{j});
        counts(j,i) = x / n;
    end
end
delete(h)

%% Create Figures
figure('position',[0 0 700 600],'color','w')
h = heatmap(cats,cats,counts,'ColorMethod','mean');
h.XLabel = 'Transition Probability';
h.YLabel = 'Syllable';
set(gcf,'Colormap',inferno);
set(gca,'GridVisible','off','FontSize',14);
h.CellLabelFormat = '%.3f';
colorbar off

figure('position',[300 0 700 600],'color','w')
counts(counts<.05)=0;
G = digraph(counts,cats);
idxg=find(G.Edges.Weight<.075);
G=rmedge(G,idxg);
g = plot(G,'EdgeCData',G.Edges.Weight);
axis off
g.ArrowSize = 15;
g.LineWidth = 15*G.Edges.Weight;
g.EdgeAlpha = .8;
if isfield(g, 'NodeFontSize')
    g.NodeFontSize = 12;
end
g.NodeColor = [.2 .2 .2];
layout(g,'circle');
set(gcf,'Colormap',inferno);
cb=colorbar;
cb.Label.String='Transition Probability';
cb.Label.Rotation=90;

%% Save Matrix
[file,path] = uiputfile('*.xlsx','Save Transion Matrix');

if ~isnumeric(file)
    output = [];
    counts = cell(length(cats));
    for i = 1:length(cats)
        for j = 1:length(cats)
            %         counts(j,i) = mean((AllCalls{1:end-1,'Label'} == cats{i}) & (AllCalls{2:end,'Label'} == cats{j}));
            x = sum(...
                ((AllCalls{1:end-1,'Label'} == cats{i}) & (AllCalls{2:end,'Label'} == cats{j})) & ...
                (AllCalls{1:end-1,'Bout'} == AllCalls{2:end,'Bout'}) &...
                (AllCalls{1:end-1,'File'} == AllCalls{2:end,'File'}));
            n = sum(AllCalls{2:end,'Label'} == cats{j});
            counts(j,i) = {x / n};
        end
    end
    output = [output; [{'Conditional Probability'} cell(1,length(cats))]];
    output = [output; [[{'Category'} cats'] ; [cats, counts]]];

    counts = cell(length(cats));
    for i = 1:length(cats)
        for j = 1:length(cats)
            %         counts(j,i) = mean((AllCalls{1:end-1,'Label'} == cats{i}) & (AllCalls{2:end,'Label'} == cats{j}));
            x = sum(...
                ((AllCalls{1:end-1,'Label'} == cats{i}) & (AllCalls{2:end,'Label'} == cats{j})) & ...
                (AllCalls{1:end-1,'Bout'} == AllCalls{2:end,'Bout'}) &...
                (AllCalls{1:end-1,'File'} == AllCalls{2:end,'File'}));
            counts(j,i) = {x };
        end
    end
    output = [output; cell(3,length(cats)+1)];
    output = [output; [{'Transition Count'} cell(1,length(cats))]];
    output = [output;[[{'Category'} cats'] ; [cats, counts]]];

    counts = cell(length(cats),1);
    for i = 1:length(cats)
        counts(i) = {sum(AllCalls{1:end,'Label'} == cats{i})};
    end

    output = [output; cell(3,length(cats)+1)];
    output = [output; [{'Total Count'} cell(1,length(cats))]];
    output = [output; cats, counts, cell(length(cats),length(cats)-1)];

    writetable(cell2table(output),[path file],'WriteVariableNames',0);
end

end


formulae = {'C7H13A2N3O2';'C4H5A2N2O3';'CHA2NO';'C9H17A2N3O2';'C47H68O5';'C41H83NO8P';'C48H93NO8';'C13H24NO10P';...
          'C31H54NO4';'C28H44N2NaO23';'C5H10O3';'C6H11NO4';'C4H9N3O5P';'C55H95AN3O30';'C9H20ANO7P';'C39H44N4O12';'H';'Na';'C19H28O2'};

isotopeAbundance = 0; %use polyisotopic inexact mass i.e. uses all isotopes of each element weighted by natural abundance
generalFormula = 1; %NaN for unknown elements
[getMolecularMassMasses, knownMasses, unknownElements, Ematrix, elements] = getMolecularMass(formulae,isotopeAbundance,generalFormula);

%Jeff Kantor's code:
molweightMasses = molweight(formulae);

%here is the smallest difference obtained by tweaking the options
differenceMW = [0.00221999999999412;0.00127999999997996;0.000340000000001339;0.00281999999995719;0.0140999999999849;0.0121990000000096;0.0144400000000360;0.00379899999990130;0.00933999999989510;0.00847799999996823;0.00149999999999295;0.00183999999998719;0.00117900000000759;0.0166200000001027;0.00259899999997515;0.0118599999999560;0;-1.99999999850320e-06;0.00569999999993343];

%compare = [molweightMasses, getMolecularMassMasses]

%TODO not sure what is the correct code to use
res = molweightMasses - getMolecularMassMasses - differenceMW;
assert(norm(res(isfinite(res)),inf)<1e-11)


function varargout = deadhub(varargin)

switch class(varargin{1})

    case 'double'
        error('Overloaded SDPVAR/SIN CALLED WITH DOUBLE. Report error')

    case 'sdpvar'
        varargout{1} = InstantiateElementWise(mfilename,varargin{:});

    case 'char'

        operator = struct('convexity','convex','monotonicity','none','definiteness','positive','model','callback');
        operator.bounds     = @bounds;
        operator.convexhull = @convexhull;

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

    otherwise
        error('SDPVAR/SIN called with CHAR argument?');
end

function [L,U] = bounds(xL,xU,lambda)

fL = deadhub(xL,lambda);
fU = deadhub(xU,lambda);
U = max(fL,fU);
L = min(fL,fU);
if xL<0 & xU>0
    L = 0;
end

function [Ax, Ay, b, K] = convexhull(xL,xU,lambda)

K.l = 0;
K.f = 0;
fL = deadhub(xL,lambda);
fU = deadhub(xU,lambda);
if xL>=-lambda & xU<=lambda
     Ax = 0;Ay = 1;b = 0;K.f = 1;
elseif xU < -3*lambda
    Ax = 1;Ay = 1;b = 2*lambda^2;K.f = 1;
elseif xL > 3*lambda
    Ax = -1;Ay = 1;b = 2*lambda^2;K.f = 1;
else
    dfL = derivative(xL,lambda);
    dfU = derivative(xU,lambda);
    [Ax,Ay,b,K] = convexhullConvex(xL,xU,fL,fU,dfL,dfU);
end

function df=derivative(x,lambda)
ax = abs(x);
if ax<lambda
    df=0;
elseif ax>3*lambda
    df = lambda;
elseif ax<=3*lambda
    df = 0.25*(2*ax-6*lambda)+lambda;
end
if x<0
    df=-df;
end


function [y,deriv] = scaleColumns(w,scales)
% This is an MV2DF. See MV2DF_API_DEFINITION.readme.
%
%   w --> bsxfun(@times,reshape(w,[],n),scales(:)')
%
%   where n = length(scales);
%
% Note: this is a symmetric linear transform.

if nargin==0
    test_this();
    return;
end

if isempty(w)
    map = @(w)map_this(w,scales);
    y = linTrans(w,map,map);
    return;
end

if isa(w,'function_handle')
    f = scaleColumns([],scales);
    y = compose_mv(f,w,[]);
    return;
end

f = scaleColumns([],scales);
if nargout==1
    y = f(w);
else
    [y,deriv] = f(w);
end

function w = map_this(w,scales)
n = length(scales);
w = reshape(w,[],n);
w = bsxfun(@times,w,scales(:)');

function test_this()
K = 5;
N = 10;
M = randn(K,N);
scales = randn(1,N);

f = scaleColumns([],scales);
test_MV2DF(f,M(:));


function varargout = quiver3(F, varargin)
%QUIVER3   3-D quiver plot of a CHEBFUN3V object.
%   QUIVER3(F) plots velocity vectors as arrows with components F(1), F(2)
%   and F(3) which are CHEBFUN3 objects. QUIVER3 automatically scales the
%   arrows to fit. The arrows are plotted on a uniform grid.
%
%   QUIVER3(F, S) automatically scales the arrows to fit and then stretches
%   them by S. Use S=0 to plot the arrows with the automatic scaling.
%
%   QUIVER3(..., LINESPEC) uses the plot linestyle specified for the
%   velocity vectors.  Any marker in LINESPEC is drawn at the base instead
%   of an arrow on the tip. Use a marker of '.' to specify no marker at
%   all.
%
% See also quiver3.

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

numpts = 7;

% Empty check:
if ( isempty(F) )
    h = quiver3([], [], [], []);
    return
end

if ( isa(F, 'chebfun3v') && ...
        (isempty(varargin) || ~isa(varargin{1}, 'chebfun3v')) )

    nF = F.nComponents;
    if ( nF == 2 )
        error('CHEBFUN:CHEBFUN3V:quiver3:badInputs1',...
            'Needs three CHEBFUN3 objects.');
    else
        % Plot arrows are equally spaced locations
        dom = F.components{1}.domain;
        x = linspace(dom(1), dom(2), numpts);
        y = linspace(dom(3), dom(4), numpts);
        z = linspace(dom(5), dom(6), numpts);
        [xx, yy, zz] = ndgrid(x, y, z);
        vals1 = feval(F.components{1}, xx, yy, zz);
        vals2 = feval(F.components{2}, xx, yy, zz);
        vals3 = feval(F.components{3}, xx, yy, zz);
        h = quiver3(xx, yy, zz, vals1, vals2, vals3, varargin{:});
        axis([x(1), x(end), y(1), y(end), z(1), z(end)])
    end

else
    error('CHEBFUN:CHEBFUN3V:quiver3:badInputs3',...
        'Unrecognised input arguments.');
end

if ( nargout > 0 )
    varargout = {h};
end

end


function gT = rbfinfwhiteKernDiagGradX(kern, t)

% RBFINFWHITEKERNDIAGGRADX Gradient of RBF-WHITE kernel's (with integration
% limits between minus infinity and infinity) diagonal w.r.t. t.
% FORMAT
% DESC computes the gradient of the diagonal of the RBF-WHITE kernel matrix
% with respect to the elements of the input column vector given in t.
% ARG kern : the kernel structure for which gradients are being computed.
% ARG t : the input data in the form of a design matrix.
% RETURN gT : the gradients of the diagonal with respect to each element
% of t. The returned matrix has the same dimensions as t.
%
% SEEALSO : rbfinfwhiteKernParamInit, kernDiagGradX, rbfinfwhiteKernGradX
%
% COPYRIGHT : David Luengo, 2009

% KERN

if size(t, 2) > 1
  error('Input can only have one column');
end

gT = zeros(size(t));


function y = round(varargin)
% Implements Matlab's `round` with 2 or 3 inputs
% For symbolic data: only 1 input is supported by the original round function, so only that case is
% covered here
if nargin==1
    if ~isa(varargin{1},'sym')
        y = builtin('round',varargin{1});
    else
        y = builtin('@sym/round',varargin{1});
    end
elseif nargin==2 || (nargin==3 && strcmp(varargin{3}, 'decimal'))
    e = 10^varargin{2};
    y = builtin('round',varargin{1}*e)/e;
elseif nargin==3 && strcmp(varargin{3}, 'significant')
    e = 10^(varargin{2} - (floor(log10(abs(varargin{1})))+1));
    y = builtin('round',varargin{1}*e)/e;
else
    error('Incorrect inputs')
end
end


function kappa = evalkappa(lambda,varargin)
% eigenvalues of orientation tensor to bingham distribution parameters
%
% Options
%  approximated - approximated solution of kappas
%  precision    - precision of solvus
%  iteration    - number of newton interations
%
% See also
% orientation/mean EBSD/mean BinghamODF

% only approximated solution of kappas' which hold true only for large
% values of lambda see: F. Bachmann, R. Hielscher, P. Jupp, W. Pantleon, H.
% Schaeben, E.Wegert: Inferential statistics of electron backscatter
% diffraction data from within individual crystalline grains, Journal of
% applied Crystallogrpahy, 2010, 34, eq. 38.

lambda = sort(lambda);
kappa = -1./(2.*lambda);
kappa(4) = 0;
kappa = kappa - kappa(1);

% kappa = sort(1./((2.*lambda-1).*lambda));
% kappa = (kappa-min(kappa))/2;

end


function t_most_w_ds(quiet, solver, verbose)
%T_MOST_W_DS  Test for MOST with dynamical system constraints.

%   MOST
%   Copyright (c) 2015-2020, Power Systems Engineering Research Center (PSERC)
%   by Carlos E. Murillo-Sanchez, PSERC Cornell & Universidad Nacional de Colombia
%   and Ray Zimmerman, PSERC Cornell
%
%   This file is part of MOST.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://github.com/MATPOWER/most for more info.

if nargin < 3
    verbose = 0;
    if nargin < 2
        solver = '';
        if nargin < 1
            quiet = 0;
        end
    end
end

include_MIPS = 0;   %% set to 1, to attempt even if MIPS is the best solver
                    %% available (takes a LONG time and currently fails)
n_tests = 3;

t_begin(n_tests, quiet);

casefile = 'c118swf';
solnfile = 't_most_w_ds_z';

%% define named indices into data matrices
[PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
    VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
[GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
    MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
    QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
[F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
    TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
    ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
[PW_LINEAR, POLYNOMIAL, MODEL, STARTUP, SHUTDOWN, NCOST, COST] = idx_cost;
[CT_LABEL, CT_PROB, CT_TABLE, CT_TBUS, CT_TGEN, CT_TBRCH, CT_TAREABUS, ...
    CT_TAREAGEN, CT_TAREABRCH, CT_ROW, CT_COL, CT_CHGTYPE, CT_REP, ...
    CT_REL, CT_ADD, CT_NEWVAL, CT_TLOAD, CT_TAREALOAD, CT_LOAD_ALL_PQ, ...
    CT_LOAD_FIX_PQ, CT_LOAD_DIS_PQ, CT_LOAD_ALL_P, CT_LOAD_FIX_P, ...
    CT_LOAD_DIS_P, CT_TGENCOST, CT_TAREAGENCOST, CT_MODCOST_F, ...
    CT_MODCOST_X] = idx_ct;

if have_feature('cplex') || have_feature('gurobi') || ...
        have_feature('mosek') || have_feature('quadprog_ls') || include_MIPS
    mdi = md_init;

    %% choose solver
    if isempty(solver) || strcmp(upper(solver), 'DEFAULT')
        if have_feature('mosek')
            solver = 'MOSEK';
        elseif have_feature('cplex')
            solver = 'CPLEX';
        elseif have_feature('gurobi')
            solver = 'GUROBI';
        elseif have_feature('quadprog_ls')
            solver = 'OT';
        else
            solver = 'MIPS';
        end
    end
    mpopt = mpoption('most.solver', solver, 'verbose', verbose);

    %% set options
    if have_feature('cplex')
        mpopt = mpoption(mpopt, 'cplex.opts.threads', 2);   % set this manually here
    end
    if have_feature('gurobi')
        mpopt = mpoption(mpopt, 'gurobi.method', 2);        %% barrier
        mpopt = mpoption(mpopt, 'gurobi.threads', 4);
        mpopt = mpoption(mpopt, 'gurobi.opts.BarConvTol', 1e-6);        %% 1e-8
        mpopt = mpoption(mpopt, 'gurobi.opts.FeasibilityTol', 1e-4);    %% 1e-6
        mpopt = mpoption(mpopt, 'gurobi.opts.OptimalityTol', 1e-5);     %% 1e-6
    end
    if have_feature('quadprog_ls')
        mpopt = mpoption(mpopt, 'quadprog.TolFun', 1e-13);
    end
    if have_feature('mosek')
        mpopt = mpoption(mpopt, 'mosek.num_threads', 2);
    else
        mpopt = mpoption(mpopt, 'mips.max_it', 500);
        if have_feature('pardiso')
            mpopt = mpoption(mpopt, 'mips.linsolver', 'PARDISO');
        end
    end
    %% use e.g. t_most_w_ds(0, 'MOSEK') instead of uncommenting these lines
    % mpopt = mpoption(mpopt, 'most.solver', 'MOSEK');
    % mpopt = mpoption(mpopt, 'most.solver', 'CPLEX');
    % mpopt = mpoption(mpopt, 'most.solver', 'GUROBI');
    % mpopt = mpoption(mpopt, 'most.solver', 'OT');
    % mpopt = mpoption(mpopt, 'most.solver', 'BPMPD');
    % mpopt = mpoption(mpopt, 'most.solver', 'MIPS');

    mdi.mpc = loadcase(casefile);
    mdi.InitialPg = mdi.mpc.gen(:,PG);
    nt = 24;
    ng = size(mdi.mpc.gen, 1);
    mdi.idx.nt = nt;
    PositiveActiveReservePrice = ones(ng,1);
    PositiveActiveReserveQuantity = 0.25*mdi.mpc.gen(:,PMAX);
    NegativeActiveReservePrice = ones(ng,1);
    NegativeActiveReserveQuantity = PositiveActiveReserveQuantity;
    PositiveActiveDeltaPrice = ones(ng,1);
    NegativeActiveDeltaPrice = ones(ng,1);
    PositiveLoadFollowReservePrice = ones(ng,1);
    PositiveLoadFollowReserveQuantity = 0.5*mdi.mpc.gen(:,PMAX);
    NegativeLoadFollowReservePrice = ones(ng,1);
    NegativeLoadFollowReserveQuantity = PositiveLoadFollowReserveQuantity;
    %mdi.mpc.gen(:,RAMP_10) = 0.20 * mdi.mpc.gen(PMAX);
    %mdi.mpc.gen(:,RAMP_AGC) = 0.20 * mdi.mpc.gen(PMAX);
    %mdi.mpc.gen(:,RAMP_30) = 0.50 * mdi.mpc.gen(PMAX);
    mdi.mpc.gen(:,RAMP_10) = 1.0 * mdi.mpc.gen(:,PMAX);
    mdi.mpc.gen(:,RAMP_AGC) = 1.0 * mdi.mpc.gen(:,PMAX);
    mdi.mpc.gen(:,RAMP_30) = 1.0 * mdi.mpc.gen(:,PMAX);

    mdi.RampWearCostCoeff = 0.05 * ones(ng,1);   % (i, t) note different scheme!
    for t = 2:nt
      mdi.RampWearCostCoeff(:, t) = mdi.RampWearCostCoeff(:, 1);
    end
    mdi.Storage(1).UnitIdx = mdi.mpc.iess;
    ns = length(mdi.Storage.UnitIdx);
    Minstor = zeros(ns,1);
    Maxstor = 200 * ones(ns,1);
    %mdi.Storage.MinStorageLevel    = zeros(ns,1);
    %mdi.Storage.MaxStorageLevel    = 200 * ones(ns,1);
    mdi.Storage.InitialStorage     = 50 * ones(ns,1);
    mdi.Storage.InitialStorageLowerBound = 50*ones(ns,1);
    mdi.Storage.InitialStorageUpperBound = 50*ones(ns,1);
    mdi.Storage.OutEff             = 0.95 * ones(ns,1);
    mdi.Storage.InEff              = 0.9  * ones(ns ,1);
    mdi.Storage.InitialStorageCost         = 35 * ones(ns, 1);
    mdi.Storage.TerminalStoragePrice       = 35 * ones(ns, 1); % applied to psc_tij0, psd_tij0 (non-terminal states)
    mdi.Storage.TerminalChargingPrice0     = 35 * ones(ns, 1); % applied to psc_tijk (contingency terminal states)
    mdi.Storage.TerminalDischargingPrice0  = 35 * ones(ns, 1); % applied to psd_tijk (contingency terminal states)
    mdi.Storage.TerminalChargingPriceK     = 10 * ones(ns, 1); % applied to psc_tij0 (end-of-horizon terminal states)
    mdi.Storage.TerminalDischargingPriceK  = 40 * ones(ns, 1); % applied to psd_tij0 (end-of-horizon terminal states)
    mpopt = mpoption(mpopt, 'most.storage.terminal_target', 0);
    mdi.Storage.ExpectedTerminalStorageAim = mdi.Storage.InitialStorage;  % expected terminal storage if mpopt.most.storage.terminal_target is true
    mdi.Storage.LossFactor         = zeros(ns,1);  % fraction of storage lost in each period
    mdi.Storage.IncludeValueOfTerminalStorage = 1;
    mpopt = mpoption(mpopt, 'most.storage.cyclic', 1);

    for t = 1:nt
      mdi.offer(t).gencost = mdi.mpc.gencost;
      mdi.offer(t).PositiveActiveReservePrice = PositiveActiveReservePrice;
      mdi.offer(t).PositiveActiveReserveQuantity = PositiveActiveReserveQuantity;
      mdi.offer(t).NegativeActiveReservePrice = NegativeActiveReservePrice;
      mdi.offer(t).NegativeActiveReserveQuantity = NegativeActiveReserveQuantity;
      mdi.offer(t).PositiveActiveDeltaPrice = PositiveActiveDeltaPrice;
      mdi.offer(t).NegativeActiveDeltaPrice = NegativeActiveDeltaPrice;
      mdi.offer(t).PositiveLoadFollowReservePrice = PositiveLoadFollowReservePrice;
      mdi.offer(t).PositiveLoadFollowReserveQuantity = PositiveLoadFollowReserveQuantity;
      mdi.offer(t).NegativeLoadFollowReservePrice = NegativeLoadFollowReservePrice;
      mdi.offer(t).NegativeLoadFollowReserveQuantity = NegativeLoadFollowReserveQuantity;
      mdi.Storage.MinStorageLevel(:,t) = Minstor;
      mdi.Storage.MaxStorageLevel(:,t) = Maxstor;
    end
    mdi.Storage.MinStorageLevel(:,nt+1) = Minstor;  % Needed if mpopt.most.storage.cyclic
    mdi.Storage.MaxStorageLevel(:,nt+1) = Maxstor;

    %mdi.Storage.MinStorageLevel(:,4) = [10 ; 10];  % is this enough to create infeasibility?
    %mdi.Storage.MaxStorageLevel(:,4) = [10; 50 ];

    mdi.UC.CommitSched = ones(ng,nt);

    mdi.Delta_T = 1;
    %            0:0  1:00 2:00 3:00 4:00  5:00  6:00  7:00 8:00 9:00 10:00 11:00 12:00 13:00 14:00 15:00 16:00 17:00 18:00 19:00 20:00 21:00 22:00 23:00
    loadprof = [ 0.6  0.6   0.6 0.7  0.75  0.8   0.9   1.1  1.2  1.3   1.4  1.4   1.3   1.4    1.4   1.4   1.4   1.3   1.1   1.1   1.0   0.9   0.8   0.7  ];

    %                label  probability   type      row     column      chg type  newvalue
    partialcontabrow =[ 1       0        CT_TBUS     0        PD         CT_REL ];
    %mdi.tstep(1).OpCondSched(1).tab= [
    %                   1        0        CT_TBUS     0        PD         CT_REL     0.8  ];
    %mdi.tstep(2).OpCondSched(1).tab= [
    %                   1        0        CT_TBUS     0        PD         CT_REL     1.0  ];
    %mdi.tstep(3).OpCondSched(1).tab= [
    %                   1        0        CT_TBUS     0        PD         CT_REL     1.2  ];
    %mdi.tstep(4).OpCondSched(1).tab= [
    %                   1        0        CT_TBUS     0        PD         CT_REL     0.9 ];

    for t = 1:nt
      mdi.tstep(t).OpCondSched(1).tab = [ partialcontabrow   loadprof(t) ];
    end

    for t = 1:nt
       mdi.tstep(t).OpCondSched(2).tab = mdi.tstep(t).OpCondSched(1).tab;
       mdi.tstep(t).OpCondSched(2).tab(1,7) = 1.1*mdi.tstep(t).OpCondSched(2).tab(1,7);
       mdi.tstep(t).OpCondSched(3).tab = mdi.tstep(t).OpCondSched(1).tab;
       mdi.tstep(t).OpCondSched(3).tab(1,7) = 0.9*mdi.tstep(t).OpCondSched(1).tab(1,7);
    end

    contab = [%         1       0.01      CT_TBUS     0        PD         CT_REL     1.05 ;
                       1       0.01      CT_TGEN     2     GEN_STATUS    CT_REP      0    ;
                       2       0.01      CT_TGEN     5     GEN_STATUS    CT_REP      0    ;
                       ];

    for t = 1:nt
      for j = 1:3  % mdi.idx.nj(t)
        mdi.cont(t,j).contab = contab;
      end
    end

    mdi.tstep(1).TransMat = [ 1/3;
                               1/3
                               1/3];
    for t = 2:nt
      mdi.tstep(t).TransMat = 1/3 * ones(3,3);
    end

    ntds = 24;
    mdi.idx.ntds = ntds;
    m1 = 8;
    m2 = 12;
    B = sparse(m1*m2, ng);
    ilist = [ 2 3 4 5   3 4 5 6   3 4 5 7   3 4 5 7   3 4 5 6   4 5 6 7    2 3 4 ];
    jlist = [ 2 2 2 2   3 3 3 3   5 5 5 5   6 6 6 6   7 7 7 7   8 8 8 8    11 11 11 ];
    for i = 1:length(mdi.mpc.icoal)
     B((jlist(i)-1)*m1+ilist(i), mdi.mpc.icoal(i)) = 0.1;
    end
    A = mkdif(m1, m2, 0.5, 0.97, [1.0 0]);
    C = [];
    D = [];
    zmin = zeros(m1*m2, 1);
    zmax = 100*ones(m1*m2, 1);
    ymin = 0;
    ymax = 100;
    for t = 1:ntds
     mdi.dstep(t).A = A;
     mdi.dstep(t).B = B;
     mdi.dstep(t).C = C;
     mdi.dstep(t).D = D;
     mdi.dstep(t).zmin = zmin;
     mdi.dstep(t).zmax = zmax;
     mdi.dstep(t).ymin = ymin;
     mdi.dstep(t).ymax = ymax;
    end
    mdi.z1 = zeros(m1*m2, 1);

    mdo = most(mdi, mpopt);

    s = load(solnfile);

    t = 'success';
    t_is(mdo.results.success, 1, 12, t);

    t = 'objective function value (f)';
    t_is(mdo.QP.f, 1593399.5, -0.5, t);
% 1593399.487 % CPLEX ~25 sec
% 1594112.218 % GUROBI ~183 sec (fails)
% 1593400.863 % MOSEK ~10 sec
% 1593399.481 % OT ~88 sec

    t = 'dynamical system state (Z)';
    t_is(mdo.results.Z, s.Z, 4, t);

    % Z = mdo.results.Z;
    % save t_most_w_ds_z Z
else
    t_skip(3, 'requires MOSEK, CPLEX, Gurobi or quadprog');
end

% YorN = input('Play movie? (y/n) : ', 's');
% if strcmp(upper(YorN(1)), 'Y')
%     domovie;
% end

t_end

function A = mkdif(m1, m2, alpha, r, w)
% A = mkdif(m1, m2, r, w)
%
% computes an A matrix for the difussion equations in an m1 x m2 grid,
% using a difussion speed factor alpha <= 1, a dissipation factor r < 1 and
% a "wind" vector w = [wx wy] that roughly tells where the pollutants go.

% Carlos Murillo.  As naive as can be.

if norm(w) > 1
  w = w / norm(w);
end

n = m1 * m2;
A = sparse(n, n);
north = alpha / 4;
east = north;
south = north;
west = north;
self = (1-alpha);
if w(1) > 0
  west = west + w(1)*self;
  self = (1-w(1)) * self;
elseif w(2) < 0
  east = east + (-w(1))*self;
  self = (1+w(1)) * self;
end
if w(2) > 0
  south = south + w(2)*self;
  self = (1-w(2)) * self;
elseif w(2) < 0
  north = north + (-w(2))*self;
  self = (1+w(2)) * self;
end
tot = self + north + south + east + west;
self = (r/tot) * self;
north = (r/tot) * north;
south = (r/tot) * south;
east = (r/tot) * east;
west = (r/tot) * west;

for i = 1:m1
  for j = 1:m2
    A((j-1)*m1+i, (j-1)*m1+i) = self;
    % North
    if i > 1
      A((j-1)*m1+i, (j-1)*m1+i-1) = north;
    end
    % South
    if i < m1
      A((j-1)*m1+i, (j-1)*m1+i+1) = south;
    end
    % West
    if j > 1
      A((j-1)*m1+i, (j-2)*m1+i) = west;
    end
    % East
    if j < m2
      A((j-1)*m1+i, j*m1+i) = east;
    end
  end
end


function obj = loadDynamics(obj, file_path, mmat_names, mmat_ddx_names, vf_names, varargin)
    % load the symbolic expression of system dynamical equations from MX
    % binary files for fast loading
    %
    % Parameters:
    %  file_path: the path to the files @type char
    %  vf_names: the names of the drift vectors Fvec @type cellstr
    %  skip_load_vf: indicates whether to skip the loading of drift vectors
    %  which could takes a long time @type logical

    opts = struct(varargin{:});
    if isfield(opts, 'DelayCoriolisSet')
        delay_set = opts.DelayCoriolisSet;
    else
        delay_set = false;
    end

    x = obj.States.x;
    % load the mass matrix using the default name

    if ~isempty(mmat_names)

        for i=1:numel(mmat_names)
            mmat_name = mmat_names{i};
            mmat_ddx_name = mmat_ddx_names{i};
            M = SymFunction(mmat_name,[],{x});
            M = load(M,file_path);
            [nr,nc] = size(M);
            assert(nr==obj.numState && nc==obj.numState,...
                'The size of the mass matrix should be (%d x %d).',obj.numState,obj.numState);

            obj.Mmat{i} = M;

            if strcmp(obj.Type,'SecondOrder')
                ddx = obj.States.ddx;
                MmatDx = SymFunction(mmat_ddx_name,[],{x,ddx});
            else
                dx = obj.States.dx;
                MmatDx = SymFunction(mmat_ddx_name,[],{x,dx});
            end
            MmatDx = load(MmatDx,file_path);
            obj.MmatDx{i} = MmatDx;
        end
    else
        mmat_ddx_name = ['MmatDx_' obj.Name];
        obj.Mmat = [];
        if strcmp(obj.Type,'SecondOrder')
            ddx = obj.States.ddx;
            obj.MmatDx = SymFunction(mmat_ddx_name,-ddx,{x,ddx});
        else
            dx = obj.States.dx;
            obj.MmatDx = SymFunction(mmat_ddx_name,-dx,{x,dx});
        end
    end
    obj.MmatName_ = cellfun(@(f)f.Name, obj.Mmat,'UniformOutput',false);

    % load the drift vector
    if nargin > 4
        if ~iscell(vf_names), vf_names = {vf_names}; end
        vf = cell(size(vf_names));
        for i=1:numel(vf_names)

            if strcmp(obj.Type,'SecondOrder') % second order system
                sfun_vf = SymFunction(vf_names{i},[],{obj.States.x,obj.States.dx});
            else                         % first order system
                sfun_vf = SymFunction(vf_names{i},[],{obj.States.x});
            end
            if ~isempty(vf_names{i}) && ~delay_set
                sfun_vf = load(sfun_vf, file_path);
            end
            vf{i} = sfun_vf;

        end
        obj.Fvec = vf;
        obj.FvecName_ = cellfun(@(f)f.Name, vf,'UniformOutput',false);
    end

end


function imageInGray_InSpatialDomain = IFFT_image(imageInGray_fft_amplitudeOnly, imageInGray_fft_phaseOnly)
%IFFT_IMAGE

% interleaved the 2 FFT2 results
image_amplitudeWith_phaseInFreqDomain = imageInGray_fft_amplitudeOnly.*imageInGray_fft_phaseOnly;
% take only the real parts
imageInGray_InSpatialDomain = real(ifft2(image_amplitudeWith_phaseInFreqDomain));

end


function test_bug1248

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

for samp=[25 98 999]
  for fs=[235 943]
    data = [];
    data.hdr.Fs     = fs;
    data.hdr.label  = {'fakechan1','fakechan2','fakechan3'};
    data.fsample    = fs;
    data.label      = {'fakechan1','fakechan2','fakechan3'};
    data.trial      = {rand(3,samp),rand(3,samp+1),rand(3,samp+2)};
    data.time       = {1/fs:1/fs:samp/fs,1/fs:1/fs:(samp+1)/fs,1/fs:1/fs:(samp+2)/fs};

    cfg = [];
    cfg.hpfreq     = 2;
    cfg.hpfiltord  = [];
    cfg.hpfilter   = 'yes';
    cfg.hpfilttype = 'fir';
    data = ft_preprocessing(cfg,data);

    cfg = [];
    cfg.hpfreq     = 2;
    cfg.hpfiltord  = [];
    cfg.hpfilter   = 'yes';
    cfg.hpfilttype = 'firls';
    data = ft_preprocessing(cfg,data);

    % no problem originally here
    cfg = [];
    cfg.lpfreq     = 20;
    cfg.lpfiltord  = [];
    cfg.lpfilter   = 'yes';
    cfg.lpfilttype = 'fir';
    data = ft_preprocessing(cfg,data);

    cfg = [];
    cfg.bpfreq     = [2 20];
    cfg.bpfiltord  = [];
    cfg.bpfilter   = 'yes';
    cfg.bpfilttype = 'fir';
    data = ft_preprocessing(cfg,data);

    cfg = [];
    cfg.bsfreq     = [2 20];
    cfg.bsfiltord  = [];
    cfg.bsfilter   = 'yes';
    cfg.bsfilttype = 'fir';
    data = ft_preprocessing(cfg,data);

    cfg = [];
    cfg.bsfreq     = [2 20];
    cfg.bsfiltord  = [];
    cfg.bsfilter   = 'yes';
    cfg.bsfilttype = 'firls';
    data = ft_preprocessing(cfg,data);

  end
end


function pick = nms(boxes, overlap)
% Non-maximum suppression.
%   pick = nms(boxes, overlap)
%
%   Greedily select high-scoring detections and skip detections that are
%   significantly covered by a previously selected detection.
%
% Return value
%   pick      Indices of locally maximal detections
%
% Arguments
%   boxes     Detection bounding boxes (see pascal_test.m)
%   overlap   Overlap threshold for suppression
%             For a selected box Bi, all boxes Bj that are covered by
%             more than overlap are suppressed. Note that 'covered' is
%             is |Bi \cap Bj| / |Bj|, not the PASCAL intersection over
%             union measure.

% AUTORIGHTS
% -------------------------------------------------------
% Copyright (C) 2011-2012 Ross Girshick
% Copyright (C) 2008, 2009, 2010 Pedro Felzenszwalb, Ross Girshick
% Copyright (C) 2007 Pedro Felzenszwalb, Deva Ramanan
%
% This file is part of the voc-releaseX code
% (http://people.cs.uchicago.edu/~rbg/latent/)
% and is available under the terms of an MIT-like license
% provided in COPYING. Please retain this notice and
% COPYING if you use this file (or a portion of it) in
% your project.
% -------------------------------------------------------

if isempty(boxes)
  pick = [];
else
  x1 = boxes(:,1);
  y1 = boxes(:,2);
  x2 = boxes(:,3);
  y2 = boxes(:,4);
  s = boxes(:,end);
  area = (x2-x1+1) .* (y2-y1+1);

  [vals, I] = sort(s);
  pick = [];
  while ~isempty(I)
    last = length(I);
    i = I(last);
    pick = [pick; i];
    suppress = [last];
    for pos = 1:last-1
      j = I(pos);
      xx1 = max(x1(i), x1(j));
      yy1 = max(y1(i), y1(j));
      xx2 = min(x2(i), x2(j));
      yy2 = min(y2(i), y2(j));
      w = xx2-xx1+1;
      h = yy2-yy1+1;
      if w > 0 && h > 0
        % compute overlap
        o = w * h / area(j);
        if o > overlap
          suppress = [suppress; pos];
        end
      end
    end
    I(suppress) = [];
  end
end


%% Import Script for EBSD Data
%
% This script was automatically created by the import wizard. You should
% run the whoole script or parts of it in order to import your data. There
% is no problem in making any changes to this script.

%% Specify Crystal and Specimen Symmetries

% crystal symmetry
CS = {crystal symmetry};

% plotting convention
setMTEXpref('xAxisDirection',{xAxisDirection});
setMTEXpref('zAxisDirection',{zAxisDirection});

%% Specify File Names

% path to files
pname = {path to files};

% which files to be imported
fname = {file names};

%% Z-Values

Z = {Z-values};

%% Import the Data

% create an EBSD variable containing the data
ebsd = EBSD.load(fname,CS,'interface',{interface},{Z},{options});

%% Correct Data

rot = rotation.byEuler({phi1},{Phi},{phi2});
ebsd = rotate(ebsd,rot,{rotationOption});


function [f, g] = fgplvmSequenceObjectiveGradient(xvec, model, Y)

% FGPLVMSEQUENCEOBJECTIVEGRADIENT Wrapper function for objective
% and gradient of a single sequence in latent space and the corresponding output sequence.
% FORMAT
% DESC provides a wrapper function for the negative log probability
% of a given data sequence under the posterior distribution of the
% Gaussian process induced by the training data..
% ARG vecx : time ordered locations in input space for the sequence
% placed as a vector using the matlab X(:)' notation.
% ARG model : the model structure for which the negative log
% probability of the given data under the posterior is to be computed.
% ARG Y : time ordered locations in data spaces for the sequence.
% RETURN f : the negative of the log probability of the given data
% sequence under the posterior distribution induced by the training data.
% RETURN g : the gradient of the negative of the returned log probability
% with respect to the latent sequence.
%
% SEEALSO : fgplvmCreate, fgplvmSequenceLogLikelihood, fgplvmOptimiseSequence
%
% COPYRIGHT : Neil D. Lawrence, 2006

% FGPLVM

% Check how the optimiser has given the parameters
if size(xvec, 1) > size(xvec, 2)
  % As a column vector ... transpose everything.
  transpose = true;
  X = reshape(xvec', size(Y, 1), model.q);
else
  transpose = false;
  X = reshape(xvec, size(Y, 1), model.q);
end
f = - fgplvmSequenceLogLikelihood(model, X, Y);

if nargout > 1
  g = - fgplvmSequenceLogLikeGradient(model, X, Y);
  g = g(:)';
end
if transpose
  g = g';
end


filename='Cantilever_quad_fine';
 ptype = 'MACRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'full';
cost = {'compliance';'perimeter'};
weights = [1, 0.1];
constraint = {'volumeConstraint'};
optimizer = 'IPOPT';
incrementFactor = 1;
designVariable = 'Density';
filterType = 'P1';

nsteps = 5;
Vfrac_final = 0.4;
Perimeter_target = 1;
optimality_final = 1e-3;
constr_final =1e-3;

Vfrac_initial = 1;
optimality_initial = 1e-2;
constr_initial = 1e-3;
TOL.rho_plus = 1;
TOL.rho_minus = 0;
TOL.E_plus = 1;
TOL.E_minus = 1e-3;
TOL.nu_plus = 1/3;
TOL.nu_minus = 1/3;


% +IOSR
%
%   Contents file for +IOSR and its subfolders.
%
%   +IOSR
%   iosr.install                         - Set search paths, and download and install dependencies
%
%   +IOSR/+ACOUSTICS
%   iosr.acoustics.irStats               - Calculate RT, DRR, Cte, and EDT for impulse response file
%   iosr.acoustics.rtEst                 - Estimate reverberation time based on room size and absorption
%
%   +IOSR/+AUDITORY
%   iosr.auditory.azimuth2itd            - Convert azimuth in degrees to ITD
%   iosr.auditory.binSearch              - Conduct a binary search
%   iosr.auditory.calcIld                - Calculate normalised interaural level difference
%   iosr.auditory.chXcorr                - Calculate cross-correlograms with a wide range of options
%   iosr.auditory.chXcorr2               - Calculate cross-correlograms with a range of options
%   chXcorr2_c.c
%   chXcorr_c.c
%   iosr.auditory.createWindow           - Create a Hann or exp. window with specified onsets/offsets
%   iosr.auditory.dupWeight              - Calculate duplex weighting coefficients for ITD and ILD
%   iosr.auditory.erbRate2hz             - Convert ERB rate to Hz
%   iosr.auditory.freqMulti              - Calculate frequency coefficient for ITD-azimuth warping
%   iosr.auditory.gammatoneFast          - Produce an array of responses from gammatone filters via FFT
%   iosr.auditory.hz2erbRate             - Convert Hz to ERB rate
%   iosr.auditory.iso226                 - ISO 226:2003 Normal equal-loudness-level contours
%   iosr.auditory.itd2azimuth            - Convert ITD to azimuth
%   iosr.auditory.lindemannInh           - Signal pre-processing for Lindemann's cross-correlation
%   iosr.auditory.loudWeight             - Calculate loudness weighting coefficients
%   iosr.auditory.makeErbCFs             - Make a series of center frequencies equally spaced in ERB-rate
%   iosr.auditory.meddisHairCell         - Calculate Ray Meddis' hair cell model for a number of channels
%   iosr.auditory.perceptualCentroid     - Perceptual spectral centroid
%   iosr.auditory.perceptualCentroid2    - Alternative perceptual spectral centroid
%   iosr.auditory.xcorrLindemann         - Cross-correlation based on Lindemann's precedence model
%   xcorrLindemann_c.c
%
%   +IOSR/+BSS
%   iosr.bss.applyIdealMasks             - Calculate and apply ideal masks via STFT
%   iosr.bss.applyMask                   - Apply a time-frequency mask to an STFT
%   iosr.bss.calcImr                     - Calculates the Ideal Mask Ratio (IMR)
%   iosr.bss.calcSnr                     - Calculate the separation SNR
%   iosr.bss.cfs2fcs                     - Calculate gammatone crossover frequencies
%   iosr.bss.example                     - Determine STFT parameters
%   iosr.bss.generateMixtures            - Generate arrays of mixtures from targets and interferers
%   iosr.bss.getFullMask                 - Convert frame rate mask to a sample-by-sample mask
%   iosr.bss.idealMasks                  - Calculate ideal time-frequency masks from STFTs
%   iosr.bss.mixture                     - Class of sound source separation mixture
%   iosr.bss.resynthesise                - Resynthesise a target from a time-frequency mask
%   iosr.bss.source                      - Class of sound source separation source
%
%   +IOSR/+DSP
%   iosr.dsp.audio                       - Abstract superclass providing audio-related properties and methods
%   iosr.dsp.autocorr                    - Perform autocorrelation via FFT
%   iosr.dsp.convFft                     - Convolve two vectors using FFT multiplication
%   iosr.dsp.istft                       - Calculate the Inverse Short-Time Fourier Transform
%   iosr.dsp.lapwin                      - Laplace window
%   iosr.dsp.localpeaks                  - Find local peaks and troughs in a vector
%   iosr.dsp.ltas                        - Calculate the long-term average spectrum of a signal
%   iosr.dsp.matchEQ                     - Match the LTAS of a signal to an arbitrary spectral magnitude
%   iosr.dsp.rcoswin                     - Raised cosine window
%   iosr.dsp.rms                         - Calculate the rms of a vector or matrix
%   iosr.dsp.sincFilter                  - Apply a near-ideal low-pass or band-pass brickwall filter
%   iosr.dsp.smoothSpectrum              - Apply 1/N-octave smoothing to a frequency spectrum
%   iosr.dsp.stft                        - Calculate the short-time Fourier transform of a signal
%   iosr.dsp.vsmooth                     - Smooth a vector using mathematical functions
%
%   +IOSR/+FIGURES
%   iosr.figures.chMap                   - Create a monochrome-compatible colour map
%   iosr.figures.cmrMap                  - Create a monochrome-compatible colour map
%   iosr.figures.multiwaveplot           - Stacked line plots from a matrix or vectors
%   iosr.figures.subfigrid               - Create axis positions for subfigures
%
%   +IOSR/+GENERAL
%   iosr.general.cell2csv                - Output a cell array to a CSV file
%   iosr.general.checkMexCompiled        - Check if mex file is compiled for system
%   iosr.general.getContents             - Get the contents of a specified directory
%   iosr.general.updateContents          - Create a Contents.m file including subdirectories
%   iosr.general.urn                     - Generate random number sequence without duplicates
%
%   +IOSR/+STATISTICS
%   iosr.statistics.boxPlot              - Draw a box plot
%   iosr.statistics.functionalBoxPlot    - Draw a functional boxplot
%   iosr.statistics.functionalPlot       - Abstract superclass for functional plots
%   iosr.statistics.functionalSpreadPlot - Draw a functional plot showing data spread
%   iosr.statistics.getRmse              - Calculate the root-mean-square error between input data
%   iosr.statistics.laprnd               - Pseudorandom numbers drawn from the Laplace distribution
%   iosr.statistics.qqPlot               - Quantile-quantile plot with patch option
%   iosr.statistics.quantile             - Quantiles of a sample via various methods
%   iosr.statistics.statsPlot            - An abstract superclass for classes that plot statistics
%   iosr.statistics.tab2box              - Prepare tabular data for boxPlot function
%   iosr.statistics.trirnd               - Pseudorandom numbers drawn from the triangular distribution
%
%   +IOSR/+SVN
%   iosr.svn.buildSvnProfile             - Read data from files tagged with SVN keywords
%   iosr.svn.headRev                     - Retrieve the head revision for specified files
%   iosr.svn.readSvnKeyword              - Read data from a file tagged with an SVN keyword
%
%   This file was generated by updateContents.m on 31 May 2017 at 17:06:32.


function depthRefined = SiftFuv2warp(sequenceName,frameIDtarget, interval, renderK, renderW, renderH)

if ~exist('sequenceName','var')
    sequenceName = 'Shuran/bedroom_funiturestore/2014-05-26_14-41-22_260595134347';
end

if ~exist('frameIDtarget','var')
    frameIDtarget = 34; %200;
end

if ~exist('interval','var')
    interval = 150;
end

data = loadSUN3Dv2(sequenceName);

frameIDs = max(frameIDtarget-interval,1):min(data.imageTotalFrames,frameIDtarget+interval);

frames = getRGBDframe(data,frameIDs);

Rts = repmat([eye(3) zeros(3,1)],[1,1,length(frameIDs)]);

itarget = find(frameIDs==frameIDtarget);

%{
depthOriginal = get_depth(imread(data.depth{frameIDs(itarget)}));
depth = denoise(depthOriginal,data.camera.D);
PCtarget(1,:)=reshape(data.camera.D.X .* depth,1,[]);
PCtarget(2,:)=reshape(data.camera.D.Y .* depth,1,[]);
PCtarget(3,:)=reshape(depth .* (~isnan(data.camera.D.X) & ~isnan(data.camera.D.Y)),1,[]);
PCtarget = PCtarget(:, PCtarget(3,:)>0);
%}

matched = false(1,length(frameIDs));
for i = 1:length(frameIDs)
    if i~=itarget
        fprintf('matching frame %d and frame %d\n',frameIDs(itarget),frameIDs(i));
        Rts(:,:,i) = align2RGBD(frames(:,:,:,itarget), frames(:,:,:,i));
        matched(i) = true;
        %{
        depth = get_depth(imread(data.depth{frameIDs(i)}));
        depth = denoise(depth,data.camera.D);
        clear PCi
        PCi(1,:)=reshape(data.camera.D.X .* depth,1,[]);
        PCi(2,:)=reshape(data.camera.D.Y .* depth,1,[]);
        PCi(3,:)=reshape(depth .* (~isnan(data.camera.D.X) & ~isnan(data.camera.D.Y)),1,[]);
        PCi = PCi(:, PCi(3,:)>0);

        try
            Rts(:,:,i) = align2RGBD(frames(:,:,:,itarget), frames(:,:,:,i), PCtarget, PCi);
            matched(i) = true;
        catch
        end
        %}
    end
end

% old Kinect
%renderK = [519.1638 0 320; 0 519.1638 240; 0 0 1];
if ~exist('renderK','var')
    renderK = data.camera.RGB.K2render; %[519 0 320; 0 519 240; 0 0 1];
end
if ~exist('renderW','var')
    renderW = data.camera.RGB.width; %640;
end
if ~exist('renderH','var')
    renderH = data.camera.RGB.height; %480;
end

% new Kinect
%{
renderK = data.camera.D.KK;
renderW = data.camera.D.width;
renderH = data.camera.D.height;
%}

for i=1:length(frameIDs)
    if matched(i) || i==itarget
        frameID=frameIDs(i);

        XYZcamera = frames(:,:,[5 6 4],i);
        XYZcamera(:,:,4) = XYZcamera(:,:,3)>0;
        %{
        depth = get_depth(imread(data.depth{frameID}));
        XYZcamera(:,:,1)=data.camera.D.X .* depth;
        XYZcamera(:,:,2)=data.camera.D.Y .* depth;
        XYZcamera(:,:,3)=depth .* (~isnan(data.camera.D.X) & ~isnan(data.camera.D.Y));
        XYZcamera(:,:,4)=depth>0 & ~isnan(data.camera.D.X) & ~isnan(data.camera.D.Y);
        %}

        [~,undistortDepth(:,:,i)] = WarpDepthMatlab(XYZcamera, renderK, Rts(:,:,i), renderW, renderH);
    end
end

undistortDepth(undistortDepth(:)==0) = NaN;

%depthRefined = nanmean(undistortDepth,3);
depthMedian = nanmedian(undistortDepth,3);

% to preserve details: check the value and the range of all values. if it is 25%-75%, keep the original values
minV = prctile(undistortDepth,75,3);
maxV = prctile(undistortDepth,25,3);
depthRaw = undistortDepth(:,:,itarget);

selV = (depthRaw < minV) | (depthRaw > maxV) | isnan(depthRaw);
ind = find(selV);
depthRefined = depthRaw;
depthRefined(ind) = depthMedian(ind);

depthRefined(isnan(depthRefined(:)))=0;

%{
[x,y] = meshgrid(1:renderW, 1:renderH);
clear X
X(1,:) = reshape((x-renderK(1,3)).*depthRefined/renderK(1,1),1,[]);
X(2,:) = reshape((y-renderK(2,3)).*depthRefined/renderK(2,2),1,[]);
X(3,:) = reshape(depthRefined,1,[]);
X = X(:,~isnan(depthRefined(:)));

% turn

figure;
subplot(2,2,1);
imagesc(depthOriginal,[0 20]); axis equal; axis tight; axis off; title('raw TOF depth');

subplot(2,2,2);
imagesc(depthRefined,[0 20]); axis equal; axis tight; axis off; title('undistorted denoised depth');

points2ply('pt_denoise101.ply', X);
%}


% DEMO2 - Subsetting ncdataset data
echo('on')
% STARTING DEMO2 ----------------------------------------------------------
% An example of subsetting data using ncdataset

%% ---- Open the dataset
ds = ncdataset('http://geoport.whoi.edu/thredds/dodsC/examples/OS_M1_20081008_TS.nc');

% You can view the variables available to you
ds.variables

%% Plot all the data
figure;
plot(ds.time('TIME'), ds.data('TEMP', [1 1 1 1], [max(ds.size('TEMP')) 1 1 1], [1 1 1 1]))
hold('on')

%% ---- Lets fetch a subset of time in Matlab's native format
startIdx = 100;
endIdx = max(ds.size('TIME'));
stride = 10;
t = ds.data('TIME', startIdx, endIdx, stride);
t = ds.time('TIME', t); % Convert time data to matlab format. See help ncdataset.time

%% ---- Now lets get a subset of the temperature data.
% NOTE: The shape of the variables size is important for subsetting
ds.size('TEMP')
% Use variable, start, end, stride to subset
temp = ds.data('TEMP', [startIdx 1 1 1], [endIdx 1 1 1], [stride 1 1 1]);

%% ---- Add Subsetted Data to Plot
plot(t, temp, 'r.');...
datetick('x', 2);grid;...
legend('All Data', 'Decimated Data');...
title({'Surface Temperature at M1 Mooring in Monterey Bay',ds.attribute('references'),ds.location},'interpreter','none');...
ylabel('Temperature [^oC]');
hold('off');
shg

echo('off') % ENDING DEMO2 ------------------------------------------------


% Function of Msg(tri)
function a = msg1(t,Ta)

t1 = -0.02:1.e-4:0;
t2 = 0:1.e-4:0.02;

m1 = 1 - abs((t1+Ta)/Ta);
m1 = [zeros([1 200]),m1,zeros([1 400])];
m2 = 1 - abs((t2-Ta)/Ta);
m2 = [zeros([1 400]),m2,zeros([1 200])];

a = m1 - m2;

end


% pop_resample() - resample dataset (pop up window).
%
% Usage:
%   >> [OUTEEG] = pop_resample( INEEG ); % pop up interactive window
%   >> [OUTEEG] = pop_resample( INEEG, freq);
%
% Graphical interface:
%   The edit box entitled "New sampling rate" contains the frequency in
%   Hz for resampling the data. Entering a value in this box  is the same
%   as providing it in the 'freq' input from the command line.
%
% Inputs:
%   INEEG      - input dataset
%   freq       - frequency to resample (Hz)
%
% Outputs:
%   OUTEEG     - output dataset
%
% Author: Arnaud Delorme, CNL/Salk Institute, 2001
%
% Note: uses the resample() function from the signal processing toolbox
%       if present. Otherwise use griddata interpolation method (it should be
%       reprogrammed using spline interpolation for speed up).
%
% See also: resample(), eeglab()

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

% 01-25-02 reformated help & license -ad
% 03-08-02 remove ica activity resampling (now set to []) -ad
% 03-08-02 debug call to function help -ad
% 04-05-02 recompute event latencies -ad

function [EEG, command] = pop_resample( EEG, freq);

command = '';
if nargin < 1
    help pop_resample;
    return;
end;
if isempty(EEG(1).data)
    disp('Pop_resample error: cannot resample empty dataset'); return;
end;

if nargin < 2

	% popup window parameters
	% -----------------------
	promptstr    = {['New sampling rate']};
	inistr       = { num2str(EEG(1).srate) };
	result       = inputdlg2( promptstr, 'Resample current dataset -- pop_resample()', 1,  inistr, 'pop_resample');
	if length(result) == 0 return; end;
	freq         = eval( result{1} );

end;

% process multiple datasets
% -------------------------
if length(EEG) > 1
    [ EEG command ] = eeg_eval( 'pop_resample', EEG, 'warning', 'on', 'params', { freq } );
    return;
end;

% finding the best ratio
[p,q] = rat(freq/EEG.srate, 0.0001); % not used right now

% set variable
% ------------
EEG.data = reshape(EEG.data, EEG.nbchan, EEG.pnts, EEG.trials);
oldpnts   = EEG.pnts;

% resample for multiple channels
% -------------------------
if isfield(EEG, 'event') & isfield(EEG.event, 'type') & isstr(EEG.event(1).type)
    tmpevent = EEG.event;
    bounds = strmatch('boundary', { tmpevent.type });
    if ~isempty(bounds),
        disp('Data break detected and taken into account for resampling');
        bounds = [ tmpevent(bounds).latency ];
        if bounds(1) < 0, bounds(1) = []; end; % remove initial boundary if any
    end;
    bounds = [1 round(bounds-0.5)+1 size(EEG.data,2)+1];
    bounds(find(bounds(2:end)-bounds(1:end-1)==0))=[]; % remove doublet boundary if any
else
    bounds = [1 size(EEG.data,2)+1]; % [1:size(EEG.data,2):size(EEG.data,2)*size(EEG.data,3)+1];
end;
if exist('resample') == 2
     usesigproc = 1;
else usesigproc = 0;
    disp('Signal Processing Toolbox absent: using custom interpolation instead of resample() function.');
    disp('This method uses cubic spline interpolation after anti-aliasing (see >> help spline)');
end;

fprintf('resampling data %3.4f Hz\n', EEG.srate*p/q);
for index1 = 1:size(EEG.data,1)
    fprintf('%d ', index1);
    sigtmp = reshape(EEG.data(index1,:, :), oldpnts, EEG.trials);

    if index1 == 1
        tmpres = [];
        indices = [1];
        for ind = 1:length(bounds)-1
            tmpres  = [ tmpres; myresample( double( sigtmp(bounds(ind):bounds(ind+1)-1,:)), p, q, usesigproc ) ];
            indices = [ indices size(tmpres,1)+1 ];
        end;
        if size(tmpres,1) == 1, EEG.pnts  = size(tmpres,2);
        else                    EEG.pnts  = size(tmpres,1);
        end;
        tmpeeglab = zeros(EEG.nbchan, EEG.pnts, EEG.trials);
    else
        for ind = 1:length(bounds)-1
            tmpres(indices(ind):indices(ind+1)-1,:) = myresample( double( sigtmp(bounds(ind):bounds(ind+1)-1,:) ), p, q, usesigproc );
        end;
    end;
    tmpeeglab(index1,:, :) = tmpres;
end;
fprintf('\n');
EEG.srate   = EEG.srate*p/q;
EEG.data = tmpeeglab;

% recompute all event latencies
% -----------------------------
if isfield(EEG.event, 'latency')
    fprintf('resampling event latencies...\n');
    for index1 = 1:length(EEG.event)
        EEG.event(index1).latency = EEG.event(index1).latency * EEG.pnts /oldpnts;
    end;
    if isfield(EEG, 'urevent') & isfield(EEG.urevent, 'latency')
        try,
            for index1 = 1:length(EEG.event)
                EEG.urevent(index1).latency = EEG.urevent(index1).latency * EEG.pnts /oldpnts;
            end;
        catch,
            disp('pop_resample warning: ''urevent'' problem, reinitializing urevents');
            EEG = rmfield(EEG, 'urevent');
        end;
    end;
    EEG = eeg_checkset(EEG, 'eventconsistency');
end;

% resample for multiple channels ica
EEG.icaact = [];

% store dataset
fprintf('resampling finished\n');

EEG.setname = [EEG.setname ' resampled'];
EEG.pnts    = size(EEG.data,2);
EEG.xmax = EEG.xmin + (EEG.pnts-1)/EEG.srate; % cko: recompute xmax, since we may have removed a few of the trailing samples

command = sprintf('EEG = pop_resample( %s, %d);', inputname(1), freq);
return;

% resample if resample is not present
% -----------------------------------
function tmpeeglab = myresample(data, pnts, new_pnts, usesigproc);

    if usesigproc
        tmpeeglab = resample(data, pnts, new_pnts);
        return;
    end;

    % anti-alias filter
    % -----------------
    data         = eegfiltfft(data', 256, 0, 128*pnts/new_pnts);

    % spline interpolation
    % --------------------
    X            = [1:length(data)];
    nbnewpoints  = length(data)*pnts/new_pnts;
    nbnewpoints2 = ceil(nbnewpoints);
    lastpointval = length(data)/nbnewpoints*nbnewpoints2;
    XX = linspace( 1, lastpointval, nbnewpoints2);

    cs = spline( X, data);
    tmpeeglab = ppval(cs, XX)';


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

function z = numeric_array_to_sym(A)
%private helper for sym ctor
%   convert an array to syms, currently on 1D, 2D.

  [n, m] = size(A);

  if (n == 0 || m == 0)
    cmd = { sprintf('return sp.Matrix(%d, %d, []),', n, m) };
    z = pycall_sympy__ (cmd);
    return
  end

  Ac = cell(n,1);
  for i=1:n
    % we want all sym creation to go through the ctor.
    Ac{i} = cell(m,1);
    for j=1:m
      Ac{i}{j} = sym(A(i,j));
    end
  end

  %Ac = {{x 2}; {3 4}; {8 9}};

  d = size(A);
  if (length(d) > 2)
    error('conversion not supported for arrays of dim > 2');
  end

  cmd = { 'L = _ins[0]'
          'M = sp.Matrix(L)'
          'return M,' };
  z = pycall_sympy__ (cmd, Ac);


classdef AcademicProblem < handle

    properties (Access = public)
        result
    end

    properties (Access = private)
        cost
        constraint
        optimizer
        filename
    end

    methods (Access = public)

        function obj = AcademicProblem(cParams)
            obj.init(cParams);
            obj.compute();
        end

        function compute(obj)
            obj.createOptimizer();
        end

    end

    methods (Access = private)

        function init(obj, cParams)
            obj.filename = cParams.filename;
        end

        function createOptimizer(obj)
            run(obj.filename);
            d                            = DesignVariableAcademic();
            d.init(x0);
            j.dV                         = d;
            c.dV                         = d;
            s.designVar                  = d;
            s.cost                       = AcademicCost(j);
            s.constraint                 = AcademicConstraint(c);
            s.constraint.nSF             = nConstr;
            s.nConstraints               = nConstr;
            s.dualVariable               = DualVariable(s);
            s.outputFunction.type        = "Academic";
            s.outputFunction.iterDisplay = "off";
            s.outputFunction.monitoring  = MonitoringManager(s);
            s.optimizerNames.primal     = 'PROJECTED GRADIENT';
            opt = Optimizer.create(s);
            opt.solveProblem();
            obj.result = d.value;
            close all;
        end

    end

end


function status = checkGamma(Gamma,T,train,subj)
% Check that the state time courses are well-defined (no NaNs)
% and that the HMM inference wasn't trapped in a trivial local minima

if nargin<4, subj = 0; end

if any(isnan(sum(Gamma,2)))
    t = find(isnan(sum(Gamma,2)),1);
    if train.order>0
        d = train.order;
        Td = T-d;
    elseif length(train.embeddedlags)>1
        d = length(train.embeddedlags)-1;
        Td = T;
    else
        d = 0;
        Td = T;
    end
    cT = cumsum(Td);
    i = find(cT>t,1);
    t = t + i*d;
    if length(train.embeddedlags)>1, t = t - max(train.embeddedlags); end
    if subj > 0
        str = [' in subject ' num2str(subj) ', '];
    else
        str = ', ';
    end
    disp(['The state time courses have NaN in t=' num2str(t) str 'where t indexes time in the data.'])
    disp('This is probably due to an artifact or an event too extreme to model around that time point.')
    disp('Please check your data arount that time point, and remove or smooth this event')
	error('Issue of precision')
end

K = size(Gamma,2);
if train.episodic % no checking
    status = 0;
else
    status = (all(max(Gamma)<0.6) && all(min(Gamma)>(1/K/2)));
end

end


classdef TestImageCoordinateUtilities < CoreTest
    % TestImageCoordinateUtilities. Tests for the MimImageCoordinateUtilities class.
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2012.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    methods
        function obj = TestImageCoordinateUtilities
            mock_reporting = CoreMockReporting;

            obj.TestGetDimensionPermutationVectorFromDicomOrientation(mock_reporting);
            obj.TestGetDimensionIndicesAsArray(mock_reporting);
            obj.TestGetDimensionIndicesFromOrientations(mock_reporting);
        end

        function TestGetDimensionPermutationVectorFromDicomOrientation(obj, mock_reporting)

            % Test GetDimensionPermutationVectorFromDicomOrientation
            obj.Assert(isequal(MimImageCoordinateUtilities.GetDimensionPermutationVectorFromDicomOrientation([1 0 0 0 1 0]', mock_reporting), [1, 2, 3]), 'Expected result');
            obj.Assert(isequal(MimImageCoordinateUtilities.GetDimensionPermutationVectorFromDicomOrientation([1 0 0 0 0 1]', mock_reporting), [3, 2, 1]), 'Expected result');
            obj.Assert(isequal(MimImageCoordinateUtilities.GetDimensionPermutationVectorFromDicomOrientation([0 1 0 0 0 1]', mock_reporting), [2, 3, 1]), 'Expected result');
            obj.Assert(isequal(MimImageCoordinateUtilities.GetDimensionPermutationVectorFromDicomOrientation([0.9964, -0.0851, 0, 0, 0, -1.0000]', mock_reporting), [3, 2, 1]), 'Expected result');

        end

        function TestGetDimensionIndicesAsArray(obj, mock_reporting)

            % Test with rows
            obj.Assert(isequal([1,2,3],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([1,0,0], [0,1,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([2,1,3],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,1,0], [1,0,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([3,1,2],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,0,1], [1,0,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([1,3,2],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([1,0,0], [0,0,1], mock_reporting)), 'Expected result');
            obj.Assert(isequal([2,3,1],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,1,0], [0,0,1], mock_reporting)), 'Expected result');
            obj.Assert(isequal([3,2,1],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,0,1], [0,1,0], mock_reporting)), 'Expected result');

            % Test with columns
            obj.Assert(isequal([1,2,3],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([1,0,0]', [0,1,0]', mock_reporting)), 'Expected result');
            obj.Assert(isequal([2,1,3],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,1,0]', [1,0,0]', mock_reporting)), 'Expected result');
            obj.Assert(isequal([3,1,2],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,0,1]', [1,0,0]', mock_reporting)), 'Expected result');
            obj.Assert(isequal([1,3,2],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([1,0,0]', [0,0,1]', mock_reporting)), 'Expected result');
            obj.Assert(isequal([2,3,1],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,1,0]', [0,0,1]', mock_reporting)), 'Expected result');
            obj.Assert(isequal([3,2,1],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,0,1]', [0,1,0]', mock_reporting)), 'Expected result');

            % Test with negatives
            obj.Assert(isequal([1,2,3],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([-1,0,0], [0,-1,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([2,1,3],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,-1,0], [-1,0,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([3,1,2],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,0,-1], [-1,0,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([1,3,2],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([-1,0,0], [0,0,-1], mock_reporting)), 'Expected result');
            obj.Assert(isequal([2,3,1],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,-1,0], [0,0,-1], mock_reporting)), 'Expected result');
            obj.Assert(isequal([3,2,1],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,0,-1], [0,-1,0], mock_reporting)), 'Expected result');

            obj.Assert(isequal([1,2,3],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([-1,0,0], [0,1,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([2,1,3],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,-1,0], [1,0,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([3,1,2],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,0,-1], [1,0,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([1,3,2],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([-1,0,0], [0,0,1], mock_reporting)), 'Expected result');
            obj.Assert(isequal([2,3,1],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,-1,0], [0,0,1], mock_reporting)), 'Expected result');
            obj.Assert(isequal([3,2,1],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,0,-1], [0,1,0], mock_reporting)), 'Expected result');

            obj.Assert(isequal([1,2,3],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([1,0,0], [0,-1,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([2,1,3],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,1,0], [-1,0,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([3,1,2],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,0,1], [-1,0,0], mock_reporting)), 'Expected result');
            obj.Assert(isequal([1,3,2],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([1,0,0], [0,0,-1], mock_reporting)), 'Expected result');
            obj.Assert(isequal([2,3,1],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,1,0], [0,0,-1], mock_reporting)), 'Expected result');
            obj.Assert(isequal([3,2,1],TestImageCoordinateUtilities.GetDimensionIndicesAsArray([0,0,1], [0,-1,0], mock_reporting)), 'Expected result');
        end

        function TestGetDimensionIndicesFromOrientations(obj, mock_reporting)
            obj.Assert(isequal([1,2,3,0,0,1],TestImageCoordinateUtilities.GetCombinedDimensionPermutationVectorFromDicomOrientation([1,0,0,0,1,0], mock_reporting)), 'Expected result');
        end
    end

    methods (Static, Access = private)
        function dims_array = GetDimensionIndicesAsArray(v1, v2, reporting)
            [d1, d2, d3] = MimImageCoordinateUtilities.GetDimensionIndicesFromOrientations(v1, v2, reporting);
            dims_array = [d1, d2, d3];
        end

        function combined_array = GetCombinedDimensionPermutationVectorFromDicomOrientation(orientation, reporting)
            [permutation_vector, flip] = MimImageCoordinateUtilities.GetDimensionPermutationVectorFromDicomOrientation(orientation, reporting);
            combined_array = [permutation_vector, flip];
        end
    end
end


function [fMshift, fProbability, fAICc, mProblikelihood, bH, bH2] = calc_loglikelihood_dM2(mCat1, mCat2)
% function [fMshift, fProbability, fAICc, mProblikelihood, bH] = calc_loglikelihood_dM2(mCat1, mCat2);
% ----------------------------------------------------------------------------------------------------
% Calculate log-likelihood estimation of magnitude shift dM between to periods; use power-law
% approximation to first time period for comparison
%
% Incoming variable
% mCat1 : EQ catalog period 1
% mCat2 : EQ catalog period 2 (Observed catalog)
%
% Outgoing variable
% fProbability    : log-likelihood probabilty
% fMshift         : Magnitude shift with the lowest  max. lieklihood score
% fAICc           : Corrected Akaike Information Criterion
% mProblikelihood : Solution matrix shift and likelihood score
% bH              : Result of KSTEST2 hypothesis test at 0.05 significance level
% bH2             : Result of KSTEST2 hypothesis test at 0.05 significance level on EMR-model
%
% Author: J. Woessner, woessner@seismo.ifg,.ethz.ch
% last update: 02.02.04

% Initialize
mProblikelihood = [];
vfProbability = [];
vMshift = [];
vMc = [];
fBinning = 0.1;

% Determine exact time period
fPeriod1 = max(mCat1(:,3)) - min(mCat1(:,3));
fPeriod2 = max(mCat2(:,3)) - min(mCat2(:,3));

mCat1Mod = mCat1;

for fMshift = -0.4:0.1:0.4
    % Apply shift
    mCat1Mod(:,6) = mCat1(:,6)+fMshift;
    % Initialize values
    fMinMag = floor(min([min(mCat1Mod(:,6)) min(mCat2(:,6))]));
    fMaxMag = ceil(max([max(mCat1Mod(:,6)) max(mCat2(:,6))]));
    %% Calculate model for best fitting Mc
     try
        [mResult, fMls, fMc, fMu, fSigma, mDataPred, vPredBest, fBvalue] = calc_McCdfnormal(mCat1Mod, fBinning);
        vPredFMD = mDataPred(:,1)'./fPeriod1;
        vMags = mDataPred(:,2)';
        [vModFMD,vBin1] = hist(mCat1Mod(:,6),fMinMag:0.1:fMaxMag);
        [vObsFMD,vBin2] = hist(mCat2(:,6),min(vMags):0.1:max(vMags));
%             figure_w_normalized_uicontrolunits(40)
%             plot(vBin2, vObsFMD./fPeriod2,'bo')
%             hold on
%             plot(vBin1, vModFMD./fPeriod1,'go')
%             plot(vMags,vPredFMD,'r*')
%             hold off
%             drawnow
        % Time normalization and round due to Poisson distribution calculation in calc_log10poisspdf
        vObsFMD = ceil(vObsFMD./fPeriod2);
        % Calculate the likelihoods for both models
        vProb_ = calc_log10poisspdf2(vObsFMD',vPredFMD');
        % Sum the probabilities
        fProbability = (-1) * sum(vProb_);
        vfProbability = [vfProbability; fProbability];
        vMshift = [vMshift; fMshift];
        vMc = [vMc; fMc];
    catch
        vfProbability = [vfProbability; NaN];
        vMshift = [vMshift; NaN];
        vMc = [vMc; NaN];
    end; % of try-catch
end

try
    %%% Find the minimum loglikelihood score: if the minimum score is obtained several times, calculate MEAN
    %%% of the magnitude shift
    vdMloglikeli = [vfProbability vMshift];
    vSel = (vdMloglikeli == nan(vdMloglikeli(:,1)));
    vdMloglikeli = vdMloglikeli(vSel,:);
    if length(vdMloglikeli(:,1)) > 1
        fProbability = min(vdMloglikeli(:,1));
        fMshift = roundn(mean(vdMloglikeli(:,2)),-1);
    else
        fProbability = vdMloglikeli(:,1);
        fMshift = vdMloglikeli(:,2);
    end
    % KS-Test
    [bH,fPval,fKsstat] = kstest2(roundn(mCat2(:,6),-1),roundn(mCat1(:,6)+fMshift,-1),0.05,0);
    % Solution matrix
    mProblikelihood = [vMc vMshift vfProbability];
    nDegFree = 1; % Magnitude shift is the degree of freedom
    n_samples = length(mCat1(:,6))+length(mCat2(:,6));
    %% Corrected Akaike Information Criterion (AICc)
    fAICc = -2*(-fProbability)+2*nDegFree+2*nDegFree*(nDegFree+1)/(n_samples-nDegFree-1);

    % KSTest on Model
    vMag1 = [];
    mCat1Mod(:,6) = mCat1(:,6)+fMshift;
    [mResult, fMls, fMc, fMu, fSigma, mDataPred, vPredBest, fBvalue] = calc_McCdfnormal(mCat1Mod, fBinning);
    mPredFMD = mDataPred;
    %mPredFMD(:,1) = ceil(mDataPred(:,1)./fPeriod1);
    vSel = (mPredFMD(:,2) ~= 0); % Remove bins with zero frequency of zero events
    mData2 = mPredFMD(vSel,:);
    for nCnt=1:length(mData2(:,1))
        fM = repmat(mData2(nCnt,2),mData2(nCnt,1),1);
        vMag1 = [vMag1; fM];
    end
    [bH2,fPval2,fKsstat2] = kstest2(roundn(mCat2(:,6),-1),roundn(vMag1,-1),0.05,0);

catch
    mProblikelihood = [NaN NaN NaN];
    fAICc = NaN;
    fMshift = NaN;
    fProbability = NaN;
    bH = NaN;
    bH2 = NaN;
end; % of try-catch


function mpc = case9target
%CASE9TARGET    Target injection power flow data for 9 bus, 3 generator case.
%   Please see CASEFORMAT for details on the case file format.
%
%   Modified version of case9.m used as target for example CPF.

%   MATPOWER

%% MATPOWER Case Format : Version 2
mpc.version = '2';

%%-----  Power Flow Data  -----%%
%% system MVA base
mpc.baseMVA = 100;

%% bus data
%	bus_i	type	Pd	Qd	Gs	Bs	area	Vm	Va	baseKV	zone	Vmax	Vmin
mpc.bus = [
	1	3	0	0	0	0	1	1	0	345	1	1.1	0.9;
	2	2	0	0	0	0	1	1	0	345	1	1.1	0.9;
	3	2	0	0	0	0	1	1	0	345	1	1.1	0.9;
	4	1	0	0	0	0	1	1	0	345	1	1.1	0.9;
	5	1	305.4	123.15	0	0	1	1	0	345	1	1.1	0.9;
	6	1	0	0	0	0	1	1	0	345	1	1.1	0.9;
	7	1	214.11	71.09	0	0	1	1	0	345	1	1.1	0.9;
	8	1	0	0	0	0	1	1	0	345	1	1.1	0.9;
	9	1	235.61	81.44	0	0	1	1	0	345	1	1.1	0.9;
];

%% generator data
%	bus	Pg	Qg	Qmax	Qmin	Vg	mBase	status	Pmax	Pmin	Pc1	Pc2	Qc1min	Qc1max	Qc2min	Qc2max	ramp_agc	ramp_10	ramp_30	ramp_q	apf
mpc.gen = [
	1	72.3	27.03	300	-300	1.04	100	1	250	10	0	0	0	0	0	0	0	0	0	0	0;
	2	248	0	300	-300	1.025	100	1	300	10	0	0	0	0	0	0	0	0	0	0	0;
	3	124.59	0	300	-300	1.025	100	1	270	10	0	0	0	0	0	0	0	0	0	0	0;
];

%% branch data
%	fbus	tbus	r	x	b	rateA	rateB	rateC	ratio	angle	status	angmin	angmax
mpc.branch = [
	1	4	0	0.0576	0	250	250	250	0	0	1	-360	360;
	4	5	0.017	0.092	0.158	250	250	250	0	0	1	-360	360;
	5	6	0.039	0.17	0.358	150	150	150	0	0	1	-360	360;
	3	6	0	0.0586	0	300	300	300	0	0	1	-360	360;
	6	7	0.0119	0.1008	0.209	150	150	150	0	0	1	-360	360;
	7	8	0.0085	0.072	0.149	250	250	250	0	0	1	-360	360;
	8	2	0	0.0625	0	250	250	250	0	0	1	-360	360;
	8	9	0.032	0.161	0.306	250	250	250	0	0	1	-360	360;
	9	4	0.01	0.085	0.176	250	250	250	0	0	1	-360	360;
];

%%-----  OPF Data  -----%%
%% generator cost data
%	1	startup	shutdown	n	x1	y1	...	xn	yn
%	2	startup	shutdown	n	c(n-1)	...	c0
mpc.gencost = [
	2	1500	0	3	0.11	5	150;
	2	2000	0	3	0.085	1.2	600;
	2	3000	0	3	0.1225	1	335;
];


%
% Usage:   AAt =mexCalcAAt(A);
%
% Name: mexCalcAAt
%
% Description: Compute efficiently AAt = A*A', when A is sparse
%   and has a lot more columns than rows. In some cases, it is
%   up to 20 times faster than the equivalent Matlab expression
%   AAt=A*A';
%
% Inputs: A:  double sparse m x n matrix
%
% Output: AAt: double m x m matrix
%
% Author: Julien Mairal, 2009