%% DEMO_febio_0073_deformable_cylinders_contact_01
% Below is a demonstration for:
%
% * Building geometry for a slab with hexahedral elements, and a
% triangulated sphere.
% * Defining the boundary conditions
% * Coding the febio structure
% * Running the model
% * Importing and visualizing the displacement results

%% Keywords
%
% * febio_spec version 3.0
% * febio, FEBio
% * indentation
% * contact, sliding, sticky, friction
% * rigid body constraints
% * hexahedral elements, hex8
% * triangular elements, tri3
% * slab, block, rectangular
% * sphere
% * static, solid
% * hyperelastic, Ogden
% * displacement logfile
% * stress logfile

%%

clear; close all; clc;

%% Plot settings
fontSize=15;
faceAlpha1=0.8;
faceAlpha2=0.3;
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=[febioFebFileNamePart,'.txt']; %FEBio log file name
febioLogFileName_disp=[febioFebFileNamePart,'_disp_out.txt']; %Log file name for exporting displacement
febioLogFileName_force=[febioFebFileNamePart,'_force_out.txt']; %Log file name for exporting force
febioLogFileName_stress=[febioFebFileNamePart,'_stress_out.txt']; %Log file name for exporting stress

%Geometry parameters
cylRadius1=0.5;
cylRadius2=1;
cylLength=1;
pointSpacing1=(cylRadius1*2*pi)/10*[1 1];
pointSpacing2=(cylRadius1*2*pi)/10*[1 1];

appliedForce=-0.0025;

%Material parameter set
E_youngs1=0.1; %Material Young's modulus
nu1=0.35; %Material Poisson's ratio

E_youngs2=0.1; %Material Young's modulus
nu2=0.35; %Material Poisson's ratio

materialDensity=1e-9;

% FEA control settings
tTotal=1;
numTimeSteps=50; %Number of time steps desired
max_refs=50; %Max reforms
max_ups=0; %Set to zero to use full-Newton iterations
opt_iter=15; %Optimum number of iterations
max_retries=5; %Maximum number of retires
dtmin=(tTotal/numTimeSteps)/100; %Minimum time step size
dtmax=(tTotal/numTimeSteps); %Maximum time step size
symmetric_stiffness=0;
analysisType='STATIC';%'DYNAMIC';

%Contact parameters
contactPenalty=10;
laugon=0;
minaug=1;
maxaug=10;
fric_coeff=0.01;

%% Creating model geometry and mesh

[meshOutput1]=hexMeshCylinder(cylRadius1,cylLength,pointSpacing1);
E1=meshOutput1.elements;
V1=meshOutput1.nodes;
F1=meshOutput1.faces;
Fb1=meshOutput1.facesBoundary;
Cb1=meshOutput1.boundaryMarker;

[meshOutput2]=hexMeshCylinder(cylRadius2,cylLength,pointSpacing2);
E2=meshOutput2.elements;
V2=meshOutput2.nodes;
F2=meshOutput2.faces;
Fb2=meshOutput2.facesBoundary;
Cb2=meshOutput2.boundaryMarker;

R=euler2DCM([0.5*pi 0 0]);

V1=V1*R;
V1(:,3)=V1(:,3)+cylRadius1;

V2=V2*R;
V2(:,3)=V2(:,3)-cylRadius2;

%% Join node sets

V=[V1;V2]; %Join nodes
E2=E2+size(V1,1); %Shift indices for second set
F2=F2+size(V1,1); %Shift indices for second set
Fb2=Fb2+size(V1,1); %Shift indices for second set
Fb=[Fb1;Fb2];
Cb=[Cb1;Cb2+1+max(Cb1(:))];
Nb1=patchNormal(Fb1,V);
Nb2=patchNormal(Fb2,V);
F=[F1;F2];
E=[E1;E2];

[F,V,~,indFix]=mergeVertices(F,V);
E=indFix(E);
E1=indFix(E1);
E2=indFix(E2);
Fb1=indFix(Fb1);
Fb2=indFix(Fb2);
Fb=indFix(Fb);

%%
% Visualization

cFigure; hold on;

gpatch(Fb1,V,Cb1,'k',faceAlpha1);
patchNormPlot(Fb1,V);

gpatch(Fb2,V,Cb2,'k',faceAlpha1);
patchNormPlot(Fb2,V);

axisGeom(gca,fontSize); camlight headlight;
colormap(gjet(250)); icolorbar;
gdrawnow;

%% Define contact surfaces

nz=[0 0 1];
logicDown1=dot(Nb1,nz(ones(size(Nb1,1),1),:),2)<0;
logicUp2=dot(Nb2,nz(ones(size(Nb2,1),1),:),2)>0;

F_contact_primary=Fb2(Cb2==0 & logicUp2,:) ;
F_contact_secondary=Fb1(Cb1==0 & logicDown1,:);

% Plotting surface models
cFigure; hold on;
title('Contact sets and normal directions','FontSize',fontSize);

gpatch(Fb,V,'kw','none',faceAlpha2);
hl(1)=gpatch(F_contact_secondary,V,'g','k',1);
patchNormPlot(F_contact_secondary,V);
hl(2)=gpatch(F_contact_primary,V,'b','k',1);
patchNormPlot(F_contact_primary,V);

legend(hl,{'Secondary','Primary'});

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

%% Define boundary conditions

VFb1=patchCentre(Fb1,V);
VFb2=patchCentre(Fb2,V);

%Supported nodes
logicPrescribe1=VFb1(:,3)>=cylRadius1 & Cb1==0;
logicSupport2=VFb2(:,3)<=-cylRadius2 & Cb2==0;

bcPrescribeList=unique(Fb1(logicPrescribe1,:));
bcSupportList=unique(Fb2(logicSupport2,:));

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

gpatch(Fb,V,Cb,'none',faceAlpha2);

hl2(1)=plotV(V(bcSupportList,:),'k.','MarkerSize',markerSize);
hl2(2)=plotV(V(bcPrescribeList,:),'r.','MarkerSize',markerSize);

legend(hl2,{'BC support','BC 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='3.0';

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

%Control section
febio_spec.Control.analysis=analysisType;
febio_spec.Control.time_steps=numTimeSteps;
febio_spec.Control.step_size=tTotal/numTimeSteps;
febio_spec.Control.solver.max_refs=max_refs;
febio_spec.Control.solver.max_ups=max_ups;
febio_spec.Control.solver.symmetric_stiffness=symmetric_stiffness;
febio_spec.Control.time_stepper.dtmin=dtmin;
febio_spec.Control.time_stepper.dtmax=dtmax;
febio_spec.Control.time_stepper.max_retries=max_retries;
febio_spec.Control.time_stepper.opt_iter=opt_iter;

%Material section
materialName1='Material1';
febio_spec.Material.material{1}.ATTR.name=materialName1;
febio_spec.Material.material{1}.ATTR.type='neo-Hookean';
febio_spec.Material.material{1}.ATTR.id=1;
febio_spec.Material.material{1}.E=E_youngs1;
febio_spec.Material.material{1}.v=nu1;
febio_spec.Material.material{1}.density=materialDensity;

materialName2='Material2';
febio_spec.Material.material{2}.ATTR.name=materialName2;
febio_spec.Material.material{2}.ATTR.type='neo-Hookean';
febio_spec.Material.material{2}.ATTR.id=2;
febio_spec.Material.material{2}.E=E_youngs2;
febio_spec.Material.material{2}.v=nu2;
febio_spec.Material.material{2}.density=materialDensity;

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

% -> Elements
partName1='Part1';
febio_spec.Mesh.Elements{1}.ATTR.name=partName1; %Name of this part
febio_spec.Mesh.Elements{1}.ATTR.type='hex8'; %Element type
febio_spec.Mesh.Elements{1}.elem.ATTR.id=(1:1:size(E1,1))'; %Element id's
febio_spec.Mesh.Elements{1}.elem.VAL=E1; %The element matrix

partName2='Part2';
febio_spec.Mesh.Elements{2}.ATTR.name=partName2; %Name of this part
febio_spec.Mesh.Elements{2}.ATTR.type='hex8'; %Element type
febio_spec.Mesh.Elements{2}.elem.ATTR.id=size(E1,1)+(1:1:size(E2,1))'; %Element id's
febio_spec.Mesh.Elements{2}.elem.VAL=E2; %The element matrix

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

nodeSetName2='bcPrescribeList';
febio_spec.Mesh.NodeSet{2}.ATTR.name=nodeSetName2;
febio_spec.Mesh.NodeSet{2}.node.ATTR.id=bcPrescribeList(:);

%MeshDomains section
febio_spec.MeshDomains.SolidDomain{1}.ATTR.name=partName1;
febio_spec.MeshDomains.SolidDomain{1}.ATTR.mat=materialName1;

febio_spec.MeshDomains.SolidDomain{2}.ATTR.name=partName2;
febio_spec.MeshDomains.SolidDomain{2}.ATTR.mat=materialName2;

% -> Surfaces
surfaceName1='contactSurface1';
febio_spec.Mesh.Surface{1}.ATTR.name=surfaceName1;
febio_spec.Mesh.Surface{1}.quad4.ATTR.id=(1:1:size(F_contact_secondary,1))';
febio_spec.Mesh.Surface{1}.quad4.VAL=F_contact_secondary;

surfaceName2='contactSurface2';
febio_spec.Mesh.Surface{2}.ATTR.name=surfaceName2;
febio_spec.Mesh.Surface{2}.quad4.ATTR.id=(1:1:size(F_contact_primary,1))';
febio_spec.Mesh.Surface{2}.quad4.VAL=F_contact_primary;

% -> Surface pairs
contactPairName='Contact1';
febio_spec.Mesh.SurfacePair{1}.ATTR.name=contactPairName;
febio_spec.Mesh.SurfacePair{1}.primary=surfaceName2;
febio_spec.Mesh.SurfacePair{1}.secondary=surfaceName1;

%Boundary condition section
% -> Fix boundary conditions
febio_spec.Boundary.bc{1}.ATTR.type='fix';
febio_spec.Boundary.bc{1}.ATTR.node_set=nodeSetName1;
febio_spec.Boundary.bc{1}.dofs='x,y,z';

febio_spec.Boundary.bc{2}.ATTR.type='fix';
febio_spec.Boundary.bc{2}.ATTR.node_set=nodeSetName2;
febio_spec.Boundary.bc{2}.dofs='x,y';

% febio_spec.Boundary.bc{3}.ATTR.type='prescribe';
% febio_spec.Boundary.bc{3}.ATTR.node_set=nodeSetName2;
% febio_spec.Boundary.bc{3}.dof='z';
% febio_spec.Boundary.bc{3}.scale.ATTR.lc=1;
% febio_spec.Boundary.bc{3}.scale.VAL=-1;
% febio_spec.Boundary.bc{3}.relative=0;

febio_spec.Loads.nodal_load{1}.ATTR.name='PrescribedForceZ';
febio_spec.Loads.nodal_load{1}.ATTR.type='nodal_load';
febio_spec.Loads.nodal_load{1}.ATTR.node_set=nodeSetName2;
febio_spec.Loads.nodal_load{1}.dof='z';
febio_spec.Loads.nodal_load{1}.scale.ATTR.lc=1;
febio_spec.Loads.nodal_load{1}.scale.VAL=appliedForce/numel(bcPrescribeList);

%Contact section
febio_spec.Contact.contact{1}.ATTR.type='sliding-elastic';
febio_spec.Contact.contact{1}.ATTR.surface_pair=contactPairName;
febio_spec.Contact.contact{1}.two_pass=1;
febio_spec.Contact.contact{1}.laugon=laugon;
febio_spec.Contact.contact{1}.tolerance=0.2;
febio_spec.Contact.contact{1}.gaptol=0;
febio_spec.Contact.contact{1}.minaug=minaug;
febio_spec.Contact.contact{1}.maxaug=maxaug;
febio_spec.Contact.contact{1}.search_tol=0.01;
febio_spec.Contact.contact{1}.search_radius=0.01*sqrt(sum((max(V,[],1)-min(V,[],1)).^2,2));
febio_spec.Contact.contact{1}.symmetric_stiffness=0;
febio_spec.Contact.contact{1}.auto_penalty=1;
febio_spec.Contact.contact{1}.penalty=contactPenalty;
febio_spec.Contact.contact{1}.fric_coeff=fric_coeff;

%LoadData section
% -> load_controller
febio_spec.LoadData.load_controller{1}.ATTR.id=1;
febio_spec.LoadData.load_controller{1}.ATTR.type='loadcurve';
febio_spec.LoadData.load_controller{1}.interpolate='LINEAR';
febio_spec.LoadData.load_controller{1}.points.point.VAL=[0 0; tTotal 1];

%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{2}.ATTR.file=febioLogFileName_force;
febio_spec.Output.logfile.node_data{2}.ATTR.data='Rx;Ry;Rz';
febio_spec.Output.logfile.node_data{2}.ATTR.delim=',';

febio_spec.Output.logfile.element_data{1}.ATTR.file=febioLogFileName_stress;
febio_spec.Output.logfile.element_data{1}.ATTR.data='s3';
febio_spec.Output.logfile.element_data{1}.ATTR.delim=',';

%% 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.runMode='internal';%'internal';

[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)]);

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

    %Access data
    E_stress_mat=dataStruct.data;

    %%

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

        %%
    % 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_{3}$ [MPa]','Interpreter','Latex')
    hp=gpatch(Fb,V_DEF(:,:,end),CV,'k',0.8); %Add graphics object to animate
    hp.Marker='.';
    hp.MarkerSize=markerSize2;
    hp.FaceColor='interp';

    axisGeom(gca,fontSize);
    colormap(flipud(turbo(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;

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 Stats = stat_getSecondOrderStats(PConn,alpha)
% Return the mean, standard deviation, and confidence intervals of a
% surrogate distribution
%
% Inputs:
%
%       PConn:     connectivity distribution returned from stat_bootstrap()
%       alpha:     significance level for empircal confidence intervals
%                  (e.g. alpha=0.95 for 95% confidence intervals)
% Outputs:
%
%       Stats:     Structure containing
%                  .mean
%                  .stdev
%                  .ci
%                  for each connectivity measure
%
% See Also: stat_surrogate(), stat_surrogateStats()
%
% References:
%
% [1] Mullen T (2010) The Source Information Flow Toolbox (SIFT):
%   Theoretical Handbook and User Manual. Chapter 6.8
%   Available at: http://www.sccn.ucsd.edu/wiki/SIFT
%
% Author: Tim Mullen, 2011, SCCN/INC, UCSD.
% Email:  tim@sccn.ucsd.edu

% This function is part of the Source Information Flow Toolbox (SIFT)
%
% 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, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

connmethods = hlp_getConnMethodNames(PConn);

for cnd=1:length(PConn)

    for m=1:length(connmethods)

        sz = size(PConn(cnd).(connmethods{m}));

        Stats(cnd).(connmethods{m}).mean  = mean(PConn(cnd).(connmethods{m}),length(sz));
        Stats(cnd).(connmethods{m}).stdev = std(PConn(cnd).(connmethods{m}),0,length(sz));
        Stats(cnd).(connmethods{m}).ci(1,:,:,:,:,:) = ...
            single(prctile(PConn(cnd).(connmethods{m}),(100*alpha)/2,length(sz)));     % lower ci
        Stats(cnd).(connmethods{m}).ci(2,:,:,:,:,:) = ...
            single(prctile(PConn(cnd).(connmethods{m}),100-100*alpha/2,length(sz)));   % upper ci

    end

end


% This subroutine assigns creates a grid with
% spacing dx,dy (in degrees). The size will
% be selected interactively. The bvalue in each
% volume around a grid point containing ni earthquakes
% will be calculated as well as the magnitude
% of completness
%   Stefan Wiemer 1/95

% TODO delete this. I'm higly suspicious this plays a role in anything. Message2 was not fully defined -CGR
report_this_filefun(mfilename('fullpath'));

if sel == 'in'
    % get the grid parameter
    % initial values
    %
    dx = 1.00;
    dy = 1.00 ;
    ni = 100;

    % make the interface
    %
    figure_w_normalized_uicontrolunits(...
        'Name','Grid Input Parameter',...
        'NumberTitle','off', ...
        'MenuBar','none', ...
        'NextPlot','new', ...
        'units','points',...
        'Visible','off', ...
        'Position',[ wex+200 wey-200 450 250]);
    axis off

    % creates a dialog box to input grid parameters
    %
    freq_field=uicontrol('Style','edit',...
        'Position',[.60 .50 .22 .10],...
        'Units','normalized','String',num2str(ni),...
        'Callback','ni=str2double(get(freq_field,''String'')); set(freq_field,''String'',num2str(ni));');

    freq_field2=uicontrol('Style','edit',...
        'Position',[.60 .40 .22 .10],...
        'Units','normalized','String',num2str(dx),...
        'Callback','dx=str2double(get(freq_field2,''String'')); set(freq_field2,''String'',num2str(dx));');

    freq_field3=uicontrol('Style','edit',...
        'Position',[.60 .30 .22 .10],...
        'Units','normalized','String',num2str(dy),...
        'Callback','dy=str2double(get(freq_field3,''String'')); set(freq_field3,''String'',num2str(dy));');

    close_button=uicontrol('Style','Pushbutton',...
        'Position',[.60 .05 .15 .12 ],...
        'Units','normalized','Callback','close;done','String','Cancel');

    go_button1=uicontrol('Style','Pushbutton',...
        'Position',[.20 .05 .15 .12 ],...
        'Units','normalized',...
        'Callback','close,sel =''ca'', bvalgrid',...
        'String','Go');

    txt3 = text(...
        'Color',[0 0 0 ],...
        'EraseMode','normal',...
        'Position',[0.30 0.74 0 ],...
        'Rotation',0 ,...
        'FontSize',ZmapGlobal.Data.fontsz.l ,...
        'FontWeight','bold',...
        'String',' Grid Parameter');
    txt5 = text(...
        'Color',[0 0 0 ],...
        'EraseMode','normal',...
        'Position',[0. 0.42 0 ],...
        'Rotation',0 ,...
        'FontSize',ZmapGlobal.Data.fontsz.m ,...
        'FontWeight','bold',...
        'String','Spacing in x (dx) in deg:');

    txt6 = text(...
        'Color',[0 0 0 ],...
        'EraseMode','normal',...
        'Position',[0. 0.32 0 ],...
        'Rotation',0 ,...
        'FontSize',ZmapGlobal.Data.fontsz.m ,...
        'FontWeight','bold',...
        'String','Spacing in y (dy) in deg:');

    txt1 = text(...
        'Color',[0 0 0 ],...
        'EraseMode','normal',...
        'Position',[0. 0.53 0 ],...
        'Rotation',0 ,...
        'FontSize',ZmapGlobal.Data.fontsz.m,...
        'FontWeight','bold',...
        'String','Number of Events (Ni):');
    set(gcf,'visible','on');
    watchoff

end   % if nargin ==0

% get the grid-size interactively and
% calculate the b-value in the grid by sorting
% thge seimicity and selectiong the ni neighbors
% to each grid point

if sel == 'ca'
    message2 = ['right corner (with same mouse button). Allow  '
        'some time to complete calculation of curves.  '];
    try
        zmap_message_center.set_message(' ',message2);
    end

    figure_w_normalized_uicontrolunits(map)
    [x0,y0]  = ginput(1);
    mark1 =    plot(x0,y0,'ro','era','normal');
    set(mark1,'MarkerSize',10,'LineWidth',2.0)
    [x1,y1]  = ginput(1);
    f = [x0 y0 ; x1 y0 ; x1 y1 ; x0 y1 ; x0 y0];

    fplo = plot(f(:,1),f(:,2),'r','era','normal');
    set(fplo,'LineWidth',2)
    gx = x0:dx:x1;
    gy = y0:dy:y1;
    itotal = length(gx) * length(gy);

    zmap_message_center.set_info(' ','Running... ');think
    %  make grid, calculate start- endtime etc.  ...
    %
    t0b = min(a.Date)  ;
    n = a.Count;
    teb = a(n,3) ;
    tdiff = round((teb - t0b)*365/par1);
    cumu = zeros(length(t0b:par1/365:teb)+2);
    ncu = length(cumu);
    cumuall = zeros(ncu,length(gx)*length(gy));
    loc = zeros(3, length(gx)*length(gy));

    % loop over  all points
    %
    i2 = 0.;
    i1 = 0.;
    bvg = [];
    allcount = 0.;
    wai = waitbar(0,' Please Wait ...  ');
    set(wai,'NumberTitle','off','Name','b-value grid - percent done');;
    drawnow
    %
    % longitude  loop
    %
    for x =  x0:dx:x1
        i1 = i1+ 1;

        % latitude loop
        %
        for  y = y0:dy:y1
            allcount = allcount + 1.;
            i2 = i2+1;

            % calculate distance from center point and sort wrt distance
            l = sqrt(((a.Longitude-x)*cos(pi/180*y)*111).^2 + ((a.Latitude-y)*111).^2) ;
            [s,is] = sort(l);
            b = a(is(:,1),:) ;       % re-orders matrix to agree row-wise

            % take first ni points
            b = b(1:ni,:);      % new data per grid point (b) is sorted in distance

            % call the b-value function
            [bv, magco] =  bvalcalc(b);
            l = sort(l);
            bvg = [bvg ; bv magco x y l(ni)];
            waitbar(allcount/itotal)
        end  % for y0
        i2 = 0;
    end  % for x0

    save  bvalgrid.mat bvg gx gy ni dx dy

    close(wai)
    watchoff

    % plot the results
    %
    % old and re3 (initially ) is the b-value matrix
    re3 = reshape(bvg(:,1),length(gy),length(gx));
    r = reshape(bvg(:,5),length(gy),length(gx));
    old = re3;
    % old1 is the magnitude of completness matrx
    old1 = reshape(bvg(:,2),length(gy),length(gx));
    view_bva

end   % if nargin ==3


function mask = pm_mask(angvar,mthres,ndil)
% Creating a mask that will determine how far
% we should proceed with phase unwrapping.
% FORMAT: mask = pm_mask(angvar,mthrea,ndil)
%
% Input:
% angvar     : Map of variance of angle estimate.
% mthres     : Threshold for variance beyond which
%              phase unwrapping is considered too
%              uncertain. Default value (pi^2)/6
%              is half the variance of a U[-pi,pi]
%              distribution.
% ndil       : We can optionally specify a no. of
%              erodes-dilates to apply to the mask
%              in order to exclude areas connected
%              only by thin bridges to the rest of
%              the brain.
%
% Output:
% mask       : Well...
%
% Jesper Andersson 26/9-03.
%_______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Jesper Andersson
% $Id: pm_mask.m 1317 2008-04-08 16:16:38Z chloe $

if nargin < 2
   mthres = (pi^2)/6;
end
if nargin < 3
   ndil = 0;
end

%
% Threshold map of angular variance and pick
% largest connected component.
%
mask = double(angvar < mthres);
[lmask,num] = spm_bwlabel(mask,6);
n = histc(lmask(:),[0:num]+0.5);
[mv,mi] = max(n);
indx = lmask(:)==mi;
mask(~indx) = 0;

if ndil
   dmask = mask;
   for i=1:ndil
      dmask = spm_erode(dmask);
   end
   [lmask,num] = spm_bwlabel(dmask,6);
   n = histc(lmask(:),[0:num]+0.5);
   [mv,mi] = max(n);
   indx = lmask(:)==mi;
   dmask(~indx) = 0;
   for i=1:ndil
      dmask = spm_dilate(dmask);
   end
   mask = mask.*dmask;
end

return


function varargout = sqrt(varargin)
%SQRT   Square root.
%   SQRT(F) returns the square root of a positive CHEBFUN2 F.

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

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

end


function g = linearOutputGradX(model, X)

% LINEAROUTPUTGRADX Evaluate derivatives of linear model outputs with respect to inputs.
% FORMAT
% DESC returns the derivatives of the outputs of an LINEAR model with
% respect to the inputs to the model.
% ARG model : the model for which the derivatives will be computed.
% ARG X : the locations at which the derivatives will be computed.
% RETURN g : the gradient of the output with respect to the inputs, in
%
% SEEALSO : linearOutputGrad, modelOutputGradX
%
% COPYRIGHT : Neil D. Lawrence, 2006

% MLTOOLS

g = repmat(shiftdim(model.W, -1), [size(X, 1) 1 1]);


function outputImage = kfilter(this, filterType, applicationDimensions, varargin)
% Filters by multiplication of a specified window function in k-space
%
%   Y = MrDataNd()
%   outputImage = Y.kfilter(filterType, applicationDimensions)
%
% This is a method of class MrDataNd.
%
% IN
%   filterType  string of filter to be applied, possible values are
%               'hamming' (default)
%               'hanning'
%               'raised_cosine'
%   applicationDimensions
%               '2D' or '3D'
%                   default: '2D' for single slices, '3D' otherwise
%               '2D' performs the filter slice-wise with the same filter,
%               '3D' performs the filter for a 3D symmetric version of the
%                    filter
%   varargin
%               extra filter parameters, depending on the chosen filter
%               'raised_cosine'
%               kfilter('raised_cosine', '2D' or '3D', 'fractionFOV', 0.5, ...
%               'beta', 0.5)
%                   fractionFOV  - fraction of FOV (1-dim!) where filter
%                                  reaches half Maximum
%                                  default: 0.5
%                   beta         - roll-off factor between 0 and 1 for the
%                                  raised-cosine window
%                                  (0 giving a box-car function,
%                                  and 1 a cosine without plateau)
%                                  default: 0.5
%   doPlotFilter    true of false (default)
%                   if true, an extra plot is generated, showing the
%                   filter response in k-space alongside central x- and
%                   y-line profiles of the image
%
% OUT
%
% EXAMPLE
%   kfilter
%
%   See also MrDataNd

% Author:   Lars Kasper, based on code by Johanna Vannesjo for 1D filtering
% Created:  2018-11-07
% Copyright (C) 2018 Institute for Biomedical Engineering
%                    University of Zurich and ETH Zurich
%
% This file is part of the TAPAS UniQC Toolbox, which is released
% under the terms of the GNU General Public License (GPL), version 3.
% You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version).
% For further details, see the file COPYING or
%  <http://www.gnu.org/licenses/>.

defaults.fractionFOV = 0.5;
defaults.beta = 0.5;
defaults.doPlotFilter = false;

args = tapas_uniqc_propval(varargin, defaults);
tapas_uniqc_strip_fields(args);

is3D = ndims(this) >= 2;

if nargin < 2
    filterType = 'hamming';
end

if nargin < 3
    if is3D
        applicationDimensions = '3D';
    else
        applicationDimensions = '2D';
    end
end

switch filterType
    case 'raised_cosine'
        % from J. Vannesjo, utils/general/raised_cosine.m Recon5-6, IBT
        funFilter = @(x) tapas_uniqc_raised_cosine((1:x) - floor(x/2), ...
            1/(fractionFOV*x), beta);
    otherwise
        funFilter = str2func(filterType);
end

dimInfoFilter = this.dimInfo.copyobj();

% column vector * row vector = matrix coordinate-wise product
filterMatrix = reshape(funFilter(this.dimInfo.nSamples(1)), [],1)*...
    reshape(funFilter(this.dimInfo.nSamples(2)), 1, []);

if doPlotFilter
    filterProfile = reshape(funFilter(this.dimInfo.nSamples(1)),[],1);
    figure('Name', 'k-filter profile');
    plot(filterProfile);
    xlim([1,this.dimInfo.nSamples(1)]);
    hold all;
    kDataProfile = this.image2k.abs.data(:,round(this.dimInfo.nSamples(2)/2), ...
        round(this.dimInfo.nSamples(3)/2));
    plot(kDataProfile/max(kDataProfile));
    plot(kDataProfile/max(kDataProfile).*filterProfile);
    legend('kfilter', 'unfiltered kx-profile of central slice', 'kfiltered kx-profile');
end

% replicate same filter for all slices
if is3D
    filterMatrix = repmat(filterMatrix, 1, 1, this.dimInfo.nSamples(3));
    dimInfoFilter.remove_dims(4:dimInfoFilter.nDims);

    switch applicationDimensions
        case '3D'
            % create the filter in 3rd dimension by replicating in other 2
            % dims and multiplying with slice-replicated 2D-filter
            filterMatrixThirdDim = reshape(funFilter(this.dimInfo.nSamples(3)), 1, 1, []);
            filterMatrix = filterMatrix.*repmat(filterMatrixThirdDim,...
                dimInfoFilter.nSamples(1), dimInfoFilter.nSamples(2), 1);
        case '2D'
            % everything fine, we just replicated for all slices
    end

else
    dimInfoFilter.remove_dims(3:dimInfoFilter.nDims);
end

filterImage = MrImage(filterMatrix, 'dimInfo', dimInfoFilter);
outputImage = k2image(image2k(this, applicationDimensions).*filterImage, ...
    applicationDimensions);


%% DEMO_febio_0019_vessel_pressure_inflate
% Below is a demonstration for:
%
% * Building geometry for a cylindrical vessel with tetrahedral elements
% * Defining the boundary conditions
% * Coding the febio structure
% * Running the model
% * Importing and visualizing the displacement results

%% Keywords
%
% * febio_spec version 3.0
% * febio, FEBio
% * vessel, cylinder
% * prescribed pressure
% * tetrahedral elements, tet4
% * tube, cylindrical
% * 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=[febioFebFileNamePart,'.txt']; %FEBio log file name
febioLogFileName_disp=[febioFebFileNamePart,'_disp_out.txt']; %Log file name for exporting displacement
febioLogFileName_stress_prin=[febioFebFileNamePart,'_stress_prin_out.txt']; %Log file name for exporting principal stress

%Specifying geometry parameters
pointSpacing=1;

radiusInner1=9;
radiusInner2=10;

radiusOuter1=10;
radiusOuter2=12;

vesselLength=50;

%Load
appliedPressure=0.1; %MPa

%Material parameter set
c1=1; %Shear-modulus-like parameter
m1=2; %Material parameter setting degree of non-linearity
k_factor=1e2; %Bulk modulus factor
k=c1*k_factor; %Bulk modulus

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

%% Creating model boundary polygons
%

nRad=round((2*pi*mean([radiusInner1 radiusInner2]))/pointSpacing); %Number of radial steps

t=linspace(0,2*pi,nRad)'; %Angles
t=t(1:end-1); %take away last which equals start
v1_Inner=[-(vesselLength/2)*ones(size(t)) radiusInner1*sin(t) radiusInner1*cos(t)]; %Circular coordinates

t=linspace(0,2*pi,nRad)'; %Angles
t=t(1:end-1); %take away last which equals start
v2_Inner=[(vesselLength/2)*ones(size(t)) radiusInner2*sin(t) radiusInner2*cos(t)]; %Circular coordinates

%% Creating model boundary surfaces

% controlStructLoft.numSteps=17;
controlStructLoft.closeLoopOpt=1;
controlStructLoft.patchType='quad';

%Meshing outer surface
[F1,V1]=polyLoftLinear(v1_Inner,v2_Inner,controlStructLoft);
F1=fliplr(F1); %Invert orientation

%%

outerRadii=V1(:,1); %x
outerRadii=outerRadii-min(outerRadii(:)); %[0 - ...]
outerRadii=outerRadii./max(outerRadii(:)); %[0 - 1]
outerRadii=radiusOuter1+(outerRadii.*(radiusOuter2-radiusOuter1)); %[0 - 1]

innerRadii=V1(:,1); %x
innerRadii=innerRadii-min(innerRadii(:)); %[0 - ...]
innerRadii=innerRadii./max(innerRadii(:)); %[0 - 1]
innerRadii=radiusInner1+(innerRadii.*(radiusInner2-radiusInner1)); %[0 - 1]

wallThickness=outerRadii-innerRadii;

%%
% Plotting model boundary polygons

cFigure; hold on;
title('Inner surface and polygons','FontSize',fontSize);
gpatch(F1,V1,outerRadii);
plotV(v1_Inner,'g.-','LineWidth',3);
plotV(v2_Inner,'g.-','LineWidth',3);
axisGeom(gca,fontSize); camlight headlight;
colormap gjet; colorbar;
gdrawnow;

%%

numSteps=ceil(max(wallThickness)./pointSpacing);
[E,V,Fp1,Fp2]=patchThick(F1,V1,1,wallThickness,numSteps);

[F,~,C_type]=element2patch(E,[],'hex8');
indBoundary=tesBoundary(F);
Fb=F(indBoundary,:);
Cb=C_type(indBoundary,:);

%%
% Plotting model boundary surfaces

cFigure;
hold on;
title('Model boundary surfaces','FontSize',fontSize);

gpatch(Fb,V,Cb);

axisGeom(gca,fontSize); camlight headlight;
colormap gjet; icolorbar;
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 set
bcSupportList=unique(Fb(ismember(Cb,[3 4]),:)); %Node set part of selected face

F_pressure=Fb(Cb==1,:);

%%
% 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','none',0.5);

hl(1)=plotV(V(bcSupportList,:),'k.','MarkerSize',markerSize);
hl(2)=gpatch(F_pressure,V,'rw','r',1);
patchNormPlot(F_pressure,V);

legend(hl,{'BC support','Pressure surface'});

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='3.0';

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

%Control section
febio_spec.Control.analysis='STATIC';
febio_spec.Control.time_steps=numTimeSteps;
febio_spec.Control.step_size=1/numTimeSteps;
febio_spec.Control.solver.max_refs=max_refs;
febio_spec.Control.solver.max_ups=max_ups;
febio_spec.Control.solver.min_residual=min_residual;
febio_spec.Control.time_stepper.dtmin=dtmin;
febio_spec.Control.time_stepper.dtmax=dtmax;
febio_spec.Control.time_stepper.max_retries=max_retries;
febio_spec.Control.time_stepper.opt_iter=opt_iter;

%Material section
materialName1='Material1';
febio_spec.Material.material{1}.ATTR.name=materialName1;
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;

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

% -> Elements
partName1='Part1';
febio_spec.Mesh.Elements{1}.ATTR.name=partName1; %Name of this part
febio_spec.Mesh.Elements{1}.ATTR.type='hex8'; %Element type
febio_spec.Mesh.Elements{1}.elem.ATTR.id=(1:1:size(E,1))'; %Element id's
febio_spec.Mesh.Elements{1}.elem.VAL=E; %The element matrix

% -> Surfaces
surfaceName1='LoadedSurface';
febio_spec.Mesh.Surface{1}.ATTR.name=surfaceName1;
febio_spec.Mesh.Surface{1}.tri3.ATTR.id=(1:1:size(F_pressure,1))';
febio_spec.Mesh.Surface{1}.tri3.VAL=F_pressure;

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

%MeshDomains section
febio_spec.MeshDomains.SolidDomain.ATTR.name=partName1;
febio_spec.MeshDomains.SolidDomain.ATTR.mat=materialName1;

%Boundary condition section
% -> Fix boundary conditions
febio_spec.Boundary.bc{1}.ATTR.type='fix';
febio_spec.Boundary.bc{1}.ATTR.node_set=nodeSetName1;
febio_spec.Boundary.bc{1}.dofs='x,y,z';

%Loads section
% -> Surface load
febio_spec.Loads.surface_load{1}.ATTR.type='pressure';
febio_spec.Loads.surface_load{1}.ATTR.surface=surfaceName1;
febio_spec.Loads.surface_load{1}.pressure.ATTR.lc=1;
febio_spec.Loads.surface_load{1}.pressure.VAL=appliedPressure;
febio_spec.Loads.surface_load{1}.symmetric_stiffness=1;

%LoadData section
% -> load_controller
febio_spec.LoadData.load_controller{1}.ATTR.id=1;
febio_spec.LoadData.load_controller{1}.ATTR.type='loadcurve';
febio_spec.LoadData.load_controller{1}.interpolate='LINEAR';
febio_spec.LoadData.load_controller{1}.points.point.VAL=[0 0; 1 1];

%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_prin;
febio_spec.Output.logfile.element_data{1}.ATTR.data='s1;s2;s3';
febio_spec.Output.logfile.element_data{1}.ATTR.delim=',';

%% 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|
% febView(febio_spec)

%% 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)]);

    %%
    % Importing element principal stresses from a log file
    dataStruct=importFEBio_logfile(fullfile(savePath,febioLogFileName_stress_prin),1,1);

    %Access data
    E_stress_prin_mat=dataStruct.data;
    S1_mat=E_stress_prin_mat(:,1,:);
    S2_mat=E_stress_prin_mat(:,2,:);
    S3_mat=E_stress_prin_mat(:,3,:);
    S_vm = sqrt(((S1_mat-S2_mat).^2+(S2_mat-S3_mat).^2+(S3_mat-S1_mat).^2)./2);

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

    [~,CF_S_vm,~]=element2patch(E,S_vm(:,:,end),'hex8');
    Cb_S_vm=CF_S_vm(indBoundary,:);

    % Create basic view and store graphics handle to initiate animation
    hf=cFigure; %Open figure
    gtitle([febioFebFileNamePart,': Press play to animate']);
    title('Von Mises stres [MPa]','Interpreter','Latex')
    hp=gpatch(Fb,V_DEF(:,:,end),Cb_S_vm,'k',1); %Add graphics object to animate

    axisGeom(gca,fontSize);
    colormap(gjet(250)); colorbar;
    caxis([0 max(S_vm(:))]);
    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
        [~,CF_S_vm,~]=element2patch(E,S_vm(:,:,qt),'hex8');
        Cb_S_vm=CF_S_vm(indBoundary,:);

        %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),Cb_S_vm}; %Property values for to set in order to animate
    end
    anim8(hf,animStruct); %Initiate animation feature
    drawnow;

    %%
    % Importing element principal stresses from a log file
    dataStruct=importFEBio_logfile(fullfile(savePath,febioLogFileName_stress_prin),1,1);

    %Access data
    E_stress_prin_mat=dataStruct.data;

    time_vec=dataStruct.time;

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 [crop,crop_norm,crop_mean,crop_std] = corner2image(img, p, tsize)
%   (r1,c1) ***** (r3,c3)            (1,1) ***** (1,cols)
%     *             *                  *           *
%      *             *       ----->     *           *
%       *             *                  *           *
%     (r2,c2) ***** (r4,c4)              (rows,1) **** (rows,cols)
afnv_obj = corners2affine(p, tsize);
map_afnv = afnv_obj.afnv;

img_map = IMGaffine_c(double(img), map_afnv, tsize);

[crop, crop_mean, crop_std] = whitening( reshape(img_map, prod([tsize 3]), 1) ); % crop is a vector
crop_norm = norm(crop);
crop = crop/crop_norm;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Spherical Harmonic Modeling and Analysis Toolkit (SPHARM-MAT) is a 3D
% shape modeling and analysis toolkit.
% It is a software package developed at Shenlab in Center for Neuroimaging,
% Indiana University (SpharmMat@gmail.com, http://www.iupui.edu/~shenlab/)
% It is available to the scientific community as copyright freeware
% under the terms of the GNU General Public Licence.
%
% Copyright 2009, 2010, ShenLab, Center for Neuroimaging, Indiana University
%
% This file is part of SPHARM-MAT.
%
% SPHARM-MAT 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.
%
% SPHARM-MAT 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 SPHARM-MAT. If not, see <http://www.gnu.org/licenses/>.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%
% use icp to align object together first
%

function [rvec, M] = match_icp(fvec,atlas,max_d);

dg = [0 max_d]; meshsize = -3;
[X, fs] = surf_spharm(atlas,dg,meshsize);
[P, fs] = surf_spharm(fvec,dg,meshsize);

% align P to X
[P,M] = align_icp(P,X);
rvec = (M(1:3,1:3)*fvec')';
rvec(1,:) = fvec(1,:) + M(1:3,4)'*2*sqrt(pi); % Y00 = 1/(2*sqrt(pi))

rmsd(1) = SPHARM_rmsd(fvec, atlas);
rmsd(2) = SPHARM_rmsd(rvec, atlas);

if rmsd(1)<rmsd(2)
    rvec = fvec;
end

return;


function y = fwd(net,x)

% FWD
%
% Compute the output of a support vector classification network.
%
%    y = fwd(net, x);
%
% where x is a matrix of input patterns, where each column represents a
% variable and each row represents and observation.

%
% File        : @svc/fwd.m
%
% Date        : Tuesday 12th September 2000
%
% Author      : Dr Gavin C. Cawley
%
% Description : Part of an object-oriented implementation of Vapnik's Support
%               Vector Machine, as described in [1].
%
% References  : [1] V.N. Vapnik,
%                   "The Nature of Statistical Learning Theory",
%                   Springer-Verlag, New York, ISBN 0-387-94559-8,
%                   1995.
%
% History     : 17/08/1999 - v1.00
%               12/09/2000 - v1.01 minor improvments to comments and help
%                                  messages
%
% Copyright   : (c) Dr Gavin C. Cawley, September 2000.
%
%    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
%

w = repmat(net.w, size(x,1), 1);

y = sum((w.*evaluate(net.kernel,x,net.sv))') - net.bias;

y = y';

% bye bye...


% CONVERT SPHERICAL TO CARTESIAN
function [p] = GetCartesianFromSpherical(r,psi,theta)
% This function calculates the relative position from a spherical
% coordinate system that assumes angles are measured from the
% agents heading vector Xref.
% INPUTS:
% range     - The objects radial seperation (m)
% azimuth   - The objects relative azimuth angle (rad)
% elevation - The objects relative elevation (rad)
% OUTPUTS:
% cartesianPosition  - The new 3D position in local coordinates (m)

% DEFINE THE POSITION AS A VECTOR INTERVAL
p = [cos(psi)*cos(theta);...
     sin(psi)*cos(theta);...
              sin(theta)]*r;
end


function vectors=VectorIndexing3D(tensor_in,idx)
% indexing vectors from a 3D tensor,
%2016-10-15 jlfeng
if  ndims(tensor_in)~=3
    return
end
dims=size(tensor_in);
data=reshape(tensor_in,[dims(1)*dims(2), dims(3)]);
vectors=data(idx(:),:);


function e = maxdiff(a,b,rel)
% MAXDIFF(A,B) returns the maximum difference in any field or element.
% Matching infinities or NaNs do not count.
%
% MAXDIFF(A,B,REL) measures the per-element relative difference (A-B)/(REL + A)
%
% Examples:
%   maxdiff([1 2 3 nan inf -inf],[1 2 4 nan inf -inf]) % = 1

% Written by Tom Minka
% (c) Microsoft Corporation. All rights reserved.

if nargin < 3
  rel = [];
end

e = 0;
if ~isequal(class(a), class(b))
  fprintf('maxdiff: incompatible types\n');
  e = Inf;
  return
end
if isa(a,'struct')
  for f = fieldnames(a)'
    field = char(f);
    if ~isfield(b,field)
      fprintf('maxdiff: second argument lacks field %s\n', field);
      e = Inf;
      return
    end
    e = max(e,maxdiff(a.(field), b.(field), rel));
  end
  return
end
if ~isequal(size(a),size(b))
  fprintf('maxdiff: size mismatch\n');
  e = Inf;
  return
end
a = a(:);
b = b(:);
if iscell(a)
  for i = 1:numel(a)
    e = max(e,maxdiff(a{i},b{i}));
  end
  return
end
i = isnan(a);
if any(i ~= isnan(b))
  % mismatched NaNs
  e = Inf;
  return
elseif sum(i) > 0
  a = a(~i);
  b = b(~i);
end
i = ~isfinite(a);
if any(i ~= ~isfinite(b))
  % mismatched infs
  e = Inf;
  return
elseif ~isequal(a(i),b(i))
  e = Inf;
  return
else
  a = a(~i);
  b = b(~i);
end
if isempty(a)
  e = 0;
  return
end
e = abs(a(:) - b(:));
if ~isempty(rel)
  e = e ./ (rel + abs(a(:)));
end
e = max(e);


function h = quadsurf(x, y, z, c, varargin)
% QUADSURF  Quadrangular mesh surface plot
%
% quadsurf(X, Y, Z)
%
%   X, Y, Z are matrices with the coordinates of the mesh vertices. Note
%   that with this function it is possible to plot meshes that bend on
%   themselves or are rolled up. This is not possible with Matlab's
%   function surf(), that requires a unique value of Z for each (X,Y) pair.
%
%   This is an example of matrix X for a mesh with 10 rows and 7 columns.
%
%   X(1,1)-----X(1,2)---...---X(1,7)
%    |          |        |      |
%    |          |        |      |
%    |          |        |      |
%   X(2,1)-----X(2,2)---...---X(2,7)
%    |          |        |      |
%   ...        ...      ...    ...
%    |          |        |      |
%   X(10,1)----X(20,2)--...---X(20,7)
%
% quadsurf(X, Y, Z, C, <parameter/value pairs>)
%
%   C is a matrix of the same size as X, Y and Z, and specifies the colour
%   of the vertices by indexing into the colormap. By default, C=Z.
%
%   The X,Y,Z,C quad can be followed by parameter/value pairs to specify
%   additional properties of the Patch, e.g.
%
%     quadsurf(x, y, z, c, 'EdgeColor', 'white');
%
% H = quadsurf(...)
%
%   H returns a patch handle. Patches are children of AXES objects.
%
% See also: trisurf, trimesh, surf, mesh.

% Author: Ramon Casero <rcasero@gmail.com>
% Copyright © 2013 University of Oxford
% Version: 0.1.0
%
% University of Oxford means the Chancellor, Masters and Scholars of
% the University of Oxford, having an administrative office at
% Wellington Square, Oxford OX1 2JD, UK.
%
% This file is part of Gerardus.
%
% 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. The offer of this
% program under the terms of the License is subject to the License
% being interpreted in accordance with English Law and subject to any
% action against the University of Oxford being under the jurisdiction
% of the English Courts.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see
% <http://www.gnu.org/licenses/>.

% check arguments
narginchk(3, Inf);
nargoutchk(0, 1);

% defaults
if (nargin < 4)
    c = z;
end

% size of the inputs
[R, C] = size(x);
if (any(size(y)~=[R, C]) || any(size(z)~=[R, C]))
    error('X, Y, Z must have the same size')
end

% patch takes quadrangles as rows of 4 elements. Here we create matrices
% with the same size as X,Y,Z, for each of the 4 vertices of a quadrangle.
% Note that we have a lot of redundancy, but this is the patch convention
%
% vx1       vx2
%  ----------
%  |        |
%  |        |
%  |        |
%  |        |
%  ----------
% vx4       vx3
vx1 = x(1:R-1, 1:C-1);
vx2 = x(1:R-1, 2:C);
vx3 = x(2:R, 2:C);
vx4 = x(2:R, 1:C-1);
vy1 = y(1:R-1, 1:C-1);
vy2 = y(1:R-1, 2:C);
vy3 = y(2:R, 2:C);
vy4 = y(2:R, 1:C-1);
vz1 = z(1:R-1, 1:C-1);
vz2 = z(1:R-1, 2:C);
vz3 = z(2:R, 2:C);
vz4 = z(2:R, 1:C-1);
c1 = c(1:R-1, 1:C-1);
c2 = c(1:R-1, 2:C);
c3 = c(2:R, 2:C);
c4 = c(2:R, 1:C-1);

% format the vertices matrices, and create the patch image
h = patch([vx1(:)'; vx2(:)'; vx3(:)'; vx4(:)'], ...
    [vy1(:)'; vy2(:)'; vy3(:)'; vy4(:)'], ...
    [vz1(:)'; vz2(:)'; vz3(:)'; vz4(:)'], ...
    [c1(:)'; c2(:)'; c3(:)'; c4(:)'], varargin{:});


load -ascii heart

[N, m] = size(heart)

class = N

%rand('state',0); randn('state',0);
%heart = heart(:,randperm(m));

Napp = 150
Ntest = m-Napp

app  = heart(:,1:Napp);size(app)
test = heart(:,Napp+1:end);size(test)

unique(app(class,:))
unique(test(class,:))

ns = max(heart')
clear heart

% N, ns(class), Napp, Ntest, mean(ns),


% The COBRAToolbox: testMatrixCoherence.m
%
% Purpose:
%     - testMatriceCoherence tests the functionality of matrixCoherence.
%
% Authors:
%     - Sylvain Arreckx March 2017
%
% Exemple comes from http://stemblab.github.io/mutual-coherence/

% save the current path
currentDir = pwd;

% initialize the test
fileDir = fileparts(which('testMatrixCoherence'));
cd(fileDir);

% define the tolerance
tol = 1e-5;

A = [1, -1, 1;
     1,  2, 4];

[mu, Q] = matrixCoherence(A);

assert(abs(mu - 0.8575) < tol);

% change the directory
cd(currentDir)


if 0
	s = sparse([1 2],[1 2],[2 3]);
	%awf_sparse(int32([1 2]),int32([1 2]),[2 3])
	setnonzeros(s,[4 5])
	return
end

n = 1000;
s = rand(n,n);
[i,j,v] = find(s);
[m,n] = size(s);
tic, for iter = 1:10, s = sparse(i,j,v,m,n); end; t1=toc;
fprintf('time for sparse = %g\n', t1);
%tic, for iter = 1:10, s = awf_sparse(int32(i),int32(j),v); end; t1=toc;
%fprintf('time for awf_sparse = %g\n', t1);
tic, for iter = 1:10, s = setnonzeros(s,v); end; t2=toc;
fprintf('time for setnonzeros = %g (%g times faster)\n', t2, t1/t2);


function analyzePhase()
addpath('phase_feature_extraction');
fs = 16000;
if 1
    clean_root = 'F:\Data\ReverbChallenge\REVERB_WSJCAM0_et\data\cln_test\secondary_microphone\si_et_2\c3e';
    reverb_root = 'F:\Data\ReverbChallenge\REVERB_WSJCAM0_et\data\far_test\secondary_microphone\si_et_2\c3e';
    dereverb_root = 'F:\Data\ReverbChallenge\WavOutDNN_bigDNN19fr\REVERBWSJCAM0\SimData_et_for_1ch_far_room3_A';
    uttID = 'c3ec020a';

    wav_clean = audioread([clean_root '\' uttID '.wav']);
    wav_noisy = audioread([reverb_root '\' uttID '_ch1.wav']);
%     [grp_phase_clean, cep_clean] = modified_group_delay_feature([clean_root '\' uttID '.wav'], 0.4, 0.9, 12);
%     [grp_phase_noisy, cep_noisy] = modified_group_delay_feature([reverb_root '\' uttID '_ch1.wav'], 0.4, 0.9, 12);
else
    wav_clean = wavread('E:\Workspace2\Data\AURORA4\WAV\test_clean_wv1\440_16k\440c020a.wv1');
    wav_noisy = wavread('E:\Workspace2\Data\AURORA4\WAV\test_train_wv1\440_16k\440c020a.wv1');
end

frame_shift = 100/fs;
frame_length = 0.02;
[~,FT_clean] = wav2abs(wav_clean, fs, frame_shift, frame_length);
[~,FT_noisy] = wav2abs(wav_noisy, fs, frame_shift, frame_length);
FT_clean = FT_clean(1:257,:);
FT_noisy = FT_noisy(1:257,:);

mag_clean = abs(FT_clean);
mag_noisy = abs(FT_noisy);
phase_clean = angle(FT_clean);
phase_noisy = angle(FT_noisy);

[instan_freq_clean] = comp_instan_freq(phase_clean);
[instan_freq_noisy] = comp_instan_freq(phase_noisy);

[BPD_clean, IF_clean] = comp_BPD(phase_clean, 512, frame_shift*fs);
[BPD_noisy, IF_clean] = comp_BPD(phase_noisy, 512, frame_shift*fs);

[group_delay_clean] = comp_group_delay(phase_clean);
[group_delay_noisy] = comp_group_delay(phase_noisy);

[mgd_clean, log_mgd_clean] = modified_group_delay_feature(wav_clean, fs, 1, 1);
[mgd_noisy, log_mgd_noisy] = modified_group_delay_feature(wav_noisy, fs, 1, 1);

subplot(4,2,1); imagesc(log(mag_clean));
subplot(4,2,3); imagesc(log_mgd_clean);
subplot(4,2,5); imagesc(instan_freq_clean);
subplot(4,2,7); imagesc(BPD_clean);

subplot(4,2,2); imagesc(log(mag_noisy));
subplot(4,2,4); imagesc(log_mgd_noisy);
subplot(4,2,6); imagesc(instan_freq_noisy);
subplot(4,2,8); imagesc(BPD_noisy);

end


function check_unimodalGrad

%% test 1

cs1 = crystalSymmetry('-3m1');
cs2 = crystalSymmetry('m-3m');

center = orientation.rand(100,cs1,cs2);

odf = unimodalODF(center);

ori = orientation.rand(1000,odf.CS,odf.SS);

g1 = odf.grad(ori(:),'check','delta',0.001*degree);
g2 = odf.grad(ori(:));

if max(norm(g1-g2)./(1+norm(g1))) < 1e-1
  disp(' Unimoal gradient test passed');
else
  disp(' Unimoal gradient test failed');
end

%% test 2
odf = SantaFe;

ori = orientation.rand(1000,odf.CS,odf.SS);

g1 = odf.grad(ori(:),'check','delta',0.001*degree);
g2 = odf.grad(ori(:));

if max(norm(g1-g2)./norm(g1)) < 1e-2
  disp(' Unimoal gradient test passed');
else
  disp(' Unimoal gradient test failed');
end

end


function [tip1, tip2] = scimat_rv_crescent_tips(scimat, m)
% SCIMAT_RV_CRESCENT_TIPS  Extract the tips of the crescent-shaped curve
% in all slices of the Right Ventricle.
%
% [X1, X2] = scimat_rv_crescent_tips(SCIMAT, M)
%
%   X1, X2 are 3-colum matrices where each row are the real world
%   coordinates of each of the tips of the RV crescent shape.
%
%   SCIMAT is the struct with the RV segmentation mask (see "help scimat"
%   for details).
%
%   M is a 3-column matrix, where each row has the real world coordinates
%   of a centroid (typically, the central Left Ventricle's central curve
%   computed with scimat_centroids()). There must be as many centroids as
%   slices. Centroids with NaN coordinates will be skipped.
%
%   In the case of a RV slice that has no corresponding LV centroid, the
%   closest LV centroid will be used.

% Author: Ramon Casero <rcasero@gmail.com>
% Copyright © 2010,2014 University of Oxford
% Version: 0.2.1
%
% University of Oxford means the Chancellor, Masters and Scholars of
% the University of Oxford, having an administrative office at
% Wellington Square, Oxford OX1 2JD, UK.
%
% This file is part of Gerardus.
%
% 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. The offer of this
% program under the terms of the License is subject to the License
% being interpreted in accordance with English Law and subject to any
% action against the University of Oxford being under the jurisdiction
% of the English Courts.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.

% check arguments
narginchk(2, 2);
nargoutchk(0, 2);

% volume size
sz = [scimat.axis.size];

% if (size(m, 1) ~= sz(3))
%     error('There must be a centroid per slice in SCIMAT, even if the centroid in NaN')
% end
if (size(m, 2) ~= 3)
    error('M must be a 3-column matrix')
end

% init outputs
tip1 = nan(sz(3), 3);
tip2 = nan(sz(3), 3);

% iterate slices
for I = 1:sz(3)
    % extract slice
    im = scimat.data(:,:, I);

    % get linear indices of all pixels in current slice
    idx = find(im);

    % if RV slice is empty, skip it
    if isempty(idx)
        continue
    end

    % convert linear index to multiple subscripts
    [ir, ic] = ind2sub( sz(1:2), idx );

    % convert indices to real world coordinates and make colum vectors
    x = scimat_index2world([ir, ic, I+zeros(length(ir), 1) ], ...
        scimat);

    % compute a centroid for the slice
    xm = mean(x, 1);

    % compute the distance from the slice centroid to each axis centroid
    d = dmatrix(xm', m');

    % find closest axis centroid to the slice centroid
    [~, inn] = min(d);

    % center the slice points around the axis centroid
    x = x - m(inn * ones(size(x, 1), 1), :);

    % compute polar coordinates of the centered pixel coordinates
    [phi, th] = cart2pol(x(:,1), x(:,2));

    % assume that the point with the largest and smallest azimuth values
    % are the crescent tips
    [~, idx1] = max(phi);
    [~, idx2] = min(phi);

    % assign the tip points to the output variable, undoing the previous
    % centering
    tip1(I, :) = x(idx1, :) + m(inn, :);
    tip2(I, :) = x(idx2, :) + m(inn, :);

end


classdef Vector3D < AbstractTensor ...
                    & FirstOrderDescriptor ...
                    & Elasticity3dDescriptor

    methods (Access = public)

        function normalize(obj)
            d = obj.getValue();
            d = d/norm(d);
            obj.setValue(d);
        end

    end

    methods (Access = protected)

        function loadOrderVariable(obj)
            obj.order = 'first';
        end

        function loadTensorSize(obj)
            obj.tensorSize = [3 1];
        end

    end

end


% op_alignrcvrs.m
% Jamie Near, McGill University 2014.
%
% USAGE:
% [out,coilcombos]=op_alignrcvrs(in,point,mode,coilcombos);
%
% DESCRIPTION:
% phase align the receiver channels without combining them.
%
% INPTUS:
% in            = input spectrum in matlab structure format.
% point         = Index of point in time domain to use for phase reference.
%                 (optional.  Default = 1);
% mode          = Method for estimating the coil weights and phases (optional.  Default = 'w').
%                 -'w' performs amplitude weighting of channels based on the
%                 maximum signal of each coil channel.
%                 -'h' performs amplitude weighting of channels based on the
%                 maximum signal of each coil channel divided by the square of
%                 the noise in each coil channel (as described by Hall et al.
%                 Neuroimage 2014).
% coilcombos	= (optional)  The predetermined coil phases and amplitudes as
%                 generated by the op_getcoilcombos.m function.  If this
%                 argument is provided, the 'point', and 'mode', arguments
%                 will be ignored.
%
% OUTPUTS:
% out           = Output following alignment of rf channels.
% coilcombos    = Structure containing two fields:
%                   ph:  Vector of coil phases (in degrees) used for alignment.
%                   sig: Vector of coil weights.

function [out,coilcombos]=op_alignrcvrs(in,point,mode,coilcombos);

if in.flags.addedrcvrs
    error('ERROR:  Receivers have already been combined!  Aborting!');
end

%To get best possible SNR, add the averages together (if it hasn't already been done):
if in.dims.averages>0
    av=op_averaging(in);
else
    av=in;
end

%also, for best results, we will combine all subspectra:
if nargin<4
    if in.flags.isFourSteps
        av=op_fourStepCombine(av);
    end
    if in.dims.subSpecs>0
        av=op_combinesubspecs(av,'summ');
    end
    if nargin < 3
        mode='w';
        if nargin < 2
            point=1;
        end
    end

end
avfids=av.fids;
avspecs=av.specs;

%initialize phase matrix and the amplitude maxtrix that are the size of nPoints x Coils
ph=ones(in.sz(in.dims.t),in.sz(in.dims.coils));
sig=ones(in.sz(in.dims.t),in.sz(in.dims.coils));

if nargin<4
    coilcombos.ph=zeros(in.sz(in.dims.coils),1);
    coilcombos.sig=zeros(in.sz(in.dims.coils),1);
end

%now start finding the relative phases between the channels and populate
%the ph matrix
for n=1:in.sz(in.dims.coils)
    if nargin<4
        p=phase(avfids(point,n,1,1));
        coilcombos.ph(n)=p;
        ph(:,n)=p*ph(:,n);
        switch mode
            case 'w'
                S=abs(avfids(point,n,1,1));
                coilcombos.sig(n)=S;
                sig(:,n)=S*sig(:,n);
            case 'h'
                S=abs(avfids(point,n,1,1));
                N=std(avfids(end-100:end,n,1,1));
                sig(:,n)=(S/(N.^2))*sig(:,n);
                coilcombos.sig(n)=(S/(N.^2));
        end
    else
        ph(:,n)=coilcombos.ph(n)*ph(:,n);
        sig(:,n)=coilcombos.sig(n)*sig(:,n);
    end
end

%now replicate the phase matrix to equal the size of the original matrix:
replicate=in.sz;
replicate(1)=1;
replicate(2)=1;
ph=repmat(ph,replicate);
%sig=repmat(sig,replicate);
%sig=sig/max(max(max(max(sig))));

%now apply the phases by multiplying the data by exp(-i*ph);
fids=in.fids.*exp(-i*ph);
fids_presum=fids;
specs_presum=fftshift(ifft(fids,[],in.dims.t),in.dims.t);

%FILLING IN DATA STRUCTURE
out=in;
out.fids=fids_presum;
out.specs=specs_presum;


function varargout = asec(varargin)

switch class(varargin{1})

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

    case 'char'

        operator = CreateBasicOperator('callback');
        operator.bounds = @bounds;
        operator.derivative = @(x)(1./(x.*(x.^2-1).^0.5));

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

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

function [L,U] = bounds(xL,xU)
if xU <= -1 || xL >= 1
    L = asec(xL);
    U = asec(xU);
elseif xL < 0 & xU > 0
    L = 0;
    U = pi;
elseif xU < 0 || xL > 0
    L = real(asec(xL));
    U = real(asec(xU));
else
    L = 0;
    U = pi;
end


function value = year_length_common ( y )

%*****************************************************************************80
%
%% YEAR_LENGTH_COMMON returns the number of days in a Common year.
%
%  Discussion:
%
%    The "common" calendar is meant to be the calendar which is Julian up to
%    day JED = 2299160, and Gregorian from day JED = 2299161 and after.
%
%    If Y is 0, then the routine returns 0, reflecting the fact that
%    there was officially no year 0.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 September 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer Y, the year to be checked.
%
%    Output, integer VALUE, the number of
%    days in the year.
%
  if ( y == 0 )
    value = 0;
  elseif ( y == 1582 )
    value = 355;
  elseif ( year_is_leap_common ( y ) )
    value = 366;
  else
    value = 365;
  end

  return
end


function flo_i0 = genFlow(v0g, vig)

[h,w,~] = size(v0g);

minimum_flow_size = 200;         % length of the smaller dimension in the optical flow
DWNSMP = minimum_flow_size/min(h,w);
TAU = 0.2;                       % 0.25; (higher = faster, less accurate)
LAMBDA = 0.15;                   % 0.15; (smaller = smoother)
THETA = 0.3;
NSCALES = 6;                     % 5;
ZFACTOR = 0.5;
NWARPS = 7;                      % 5;
EPSILON = 0.01;
VERBOSE = 0;

flo_i0 = tvl1flow(v0g, vig, DWNSMP, TAU, LAMBDA, THETA,...
                    NSCALES, ZFACTOR, NWARPS, EPSILON, VERBOSE);

flo_i0_original_scale = zeros(h,w,2);
flo_i0_original_scale(:,:,1) = imresize(flo_i0(:,:,1), [h, w], 'bicubic');
flo_i0_original_scale(:,:,2) = imresize(flo_i0(:,:,2), [h, w], 'bicubic');
flo_i0 = flo_i0_original_scale;

flo_i0 = flo_i0/DWNSMP;


% SVMLOO - Computes the exact leave-one-out estimate of the error rate
%          for a two-class SVM using Cauwenbergh's method.
%
% Syntax: [loo_est,conf_matrix,g_loo] = svmloo;
%         (evaluates the current SVM in memory)
%
%         [loo_est,conf_matrix,g_loo] = svmloo(X,y,a,b,g,ind,type,scale,Rs,Q)
%         (evaluates the given SVM)
%
%     loo_est: number of leave-one-out error errors
% conf_matrix: confusion matrix
%       g_loo: the resulting g for each example after the example is unlearned
%           X: matrix of training vectors stored columnwise
%           y: column vector of class labels (-1/+1) for training vectors
%           a: alpha coefficients
%           b: bias
%           g: partial derivatives of cost function w.r.t. alpha coefficients
%         ind: cell array containing indices of margin, error and reserve vectors
%         		ind{1}: indices of margin vectors
%         		ind{2}: indices of error vectors
%         		ind{3}: indices of reserve vectors
%        type: kernel type
%                1: linear kernel        X'*Y
%              2-4: polynomial kernel    (scale*X'*Y + 1)^type
%                5: Gaussian kernel with variance 1/(2*scale)
%       scale: kernel scale
%          Rs: inverse of extended kernel matrix for margin vectors
%           Q: extended kernel matrix for all vectors
%      g_flag: flag indicating whether or not to compute g_loo for the error vectors with g < -1
%
% Version 3.22e -- Comments to diehl@alumni.cmu.edu
%

function [loo_est,conf_matrix,g_loo] = svmloo(varargin)

% flags for example state
MARGIN    = 1;
ERROR     = 2;
RESERVE   = 3;
UNLEARNED = 4;

if (nargin == 0)

   % define global variables
   global a;
   global b;
   global g;
   global ind;
   global Q;
   global Rs;
   global scale;
   global type;
   global X;
   global y;

else

   % define arguments
   X = varargin{1};
   y = varargin{2};
   a = varargin{3};
   b = varargin{4};
   g = varargin{5};
   ind = varargin{6};
   type = varargin{7};
   scale = varargin{8};
   Rs = varargin{9};
   Q = varargin{10};
   g_flag = varargin(11);

end;

% if the user wants g_loo, make sure to compute g_loo for the error vectors with initial g < -1.
% if we only care about the error rate, we don't need to unlearn these examples because they are
% guaranteed to be classified incorrectly.
if (nargout == 3)
   g_flag = 1;
else
   g_flag = 0;
end;

% initialize variables
num_MVs = length(ind{MARGIN});      % number of margin vectors
loo_est = 0;                        % number of leave-one-out errors
a_orig = a;                         % original value of a
b_orig = b;                         % original value of b
Rs_orig = Rs;                       % original value of Rs
Q_orig = Q;                         % original value of Q
g_orig = g;                         % original value of g
num_MVs_orig = num_MVs;             % original value of num_MVs
ind_orig = ind;                     % original value of ind
g_loo = g;

% initialize confusion matrix
conf_matrix = zeros(2,3);
if (length(ind{RESERVE}) > 0)
	conf_matrix(1,1) = sum(y(ind{RESERVE}) == 1);
	conf_matrix(2,2) = sum(y(ind{RESERVE}) == -1);
end;

% begin leave-one-out estimation
ind_loo = [ind{MARGIN} ind{ERROR}];
num_tested = 1;
disp('Beginning LOO error rate estimation.');
for i = 1:length(ind_loo)

   % select example to unlearn
   indc = ind_loo(i);

   % unlearn example
   if ((g(indc) >= -1) | (g_flag))
      unlearn(indc);
      g_loo(indc) = g(indc);
   end;

   if (mod(num_tested,50) == 0)
      s = sprintf('Unlearned and tested %d examples.',num_tested);
      disp(s);
   end;
   num_tested = num_tested + 1;

   % check to see if the example is now misclassified and record results
   loo_est = loo_est + (g(indc) < -1);
   if (y(indc) == 1)
      j = 1 + (g(indc) <= -1) + (g(indc) == -1);
      conf_matrix(1,j) = conf_matrix(1,j) + 1;
   else
      j = 1 + (g(indc) >= -1) + (g(indc) == -1);
      conf_matrix(2,j) = conf_matrix(2,j) + 1;
   end;

   % reset to original state prior to unlearning example
   a = a_orig;
   b = b_orig;
   Rs = Rs_orig;
   Q = Q_orig;
   g = g_orig;
   ind = ind_orig;
   num_MVs = num_MVs_orig;

end;
if (mod(num_tested-1,50) ~= 0)
   s = sprintf('Unlearned and tested %d examples.',num_tested-1);
   disp(s);
end;
s = sprintf('Process complete!\n');
disp(s);


function model = Expectation_MixHP(Seqs, model, alg)

Nk = sum(model.R,1); % 10.51
alpha = model.alpha+Nk; % Dirichlet
Elogpi = psi(0,alpha)-psi(0,sum(alpha)); % 10.66

% calculate responsibility
tic;
EX = zeros(length(Seqs), model.K);

% E-step: evaluate the responsibility using the current parameters
for c = 1:length(Seqs)

    Time = Seqs(c).Time;
    Event = Seqs(c).Mark;
    Tstart = Seqs(c).Start;

    if isempty(alg.Tmax)
        Tstop = Seqs(c).Stop;
    else
        Tstop = alg.Tmax;
        indt = Time < alg.Tmax;
        Time = Time(indt);
        Event = Event(indt);
    end

    N = length(Time);
    % calculate the integral decay function in the log-likelihood function
    G = Kernel_Integration(Tstop - Time, model);

    LL = Elogpi;

    for i = 1:N

        ui = Event(i);
        ti = Time(i);

        Elambdai = sqrt(pi/2).*model.b(ui,:)+eps;
        Vlambdai = (2-pi/2).*(model.b(ui,:)).^2;
        if i>1
            tj = Time(1:i-1);
            uj = Event(1:i-1);

            gij = Kernel(ti-tj, model);
            auiuj = model.beta(uj, :, :, ui);
            pij = repmat(gij, [1,1,model.K,1]).* auiuj;

            tmp = sum(sum(pij,1),2);
            Elambdai = Elambdai + tmp(:)';
            tmp = sum(sum(pij.^2, 1), 2);
            Vlambdai = Vlambdai + tmp(:)';
        end

        LL = LL+log(Elambdai) - Vlambdai./(2*Elambdai.^2);

    end
    LL = LL - (Tstop-Tstart).*sqrt(pi/2).*sum(model.b);
    tmp = sum(sum(repmat(G, [1,1,model.K]).*...
        sum(model.beta(Event,:,:,:),4),1),2);
    LL = LL- tmp(:)';

    XX = (LL - max(LL));
    EX(c,:)=(exp(XX))./sum(exp(XX));

end

model.R = EX;

end


function [U, S, V, details]  = lansvd(A, varargin)
    % We need to parse the options one by one
    params = inputParser;
    params.addRequired('A');
    % Number of singular values to compute
    params.addParameter('k', NaN);
    % Threshold for singular values
    params.addParameter('lambda', NaN);
    % Desired level of orthogonality
    params.addParameter('delta', -1);
    % Desired level of orthogonality after reorthogonalization
    params.addParameter('eta', -1);
    % Tolerance for iterated Gram-Schmidt procedure
    params.addParameter('gamma', -1);
    % Flag for classic/modified Gram-Schmidt
    params.addParameter('cgs', true);
    % Flag for extended local reorthogonalization
    params.addParameter('elr', false);
    % Verbosity level
    params.addParameter('verbosity', 0);
    % Maximum number of iterations
    params.addParameter('max_iters', -1);
    % Tolerance for convergence of singular values
    params.addParameter('tolerance', -1);
    % Initial vector specified by user
    params.addParameter('p0', []);
    % Parse the results
    params.parse(A, varargin{:});
    results = params.Results;
    options = struct;
    if(isobject(A))
        A = double(A);
    end
    if ~isnan(results.k)
        options.k = results.k;
    end
    if ~isnan(results.lambda)
        options.lambda = results.lambda;
    end
    if ~isfield(options, 'k') && ~isfield(options, 'lambda')
        % By default we compute 6 singular values
        options.k = 6;
    end
    options.delta  = results.delta;
    options.eta  = results.eta;
    options.gamma = results.gamma;
    options.cgs = results.cgs;
    options.elr = results.elr;
    options.verbosity = results.verbosity;
    options.max_iters = results.max_iters;
    options.tolerance = results.tolerance;
    if ~isempty(results.p0)
        options.p0 = results.p0;
    end
    if isstruct(A)
        M = A.M;
        N = A.N;
    elseif isnumeric(A)
        [M, N] = size(A);
    end
    details = struct;
    if min(M, N) < 1
        % A is empty
        U = []; S = []; V = []; ;
        if nargout == 1; U = zeros(0, 1); end;
        return;
    end
    if M*N == 1
        % This is the case of a singleton
        U = [1]; V = [1];
        a = A(1,1);
        S = [a];
        if nargout == 1; U = S; end;
        return;
    end
    if min(M, N) == 1
        % either a column vector or a row vector
        if isstruct(A)
            % function objects
            if N == 1
                % Single column
                A = A.A(1);
            else
                % Single row
                A = (A.At(1))';
            end
        end
        [U, S, V] = svd(full(A));
        if nargout == 1; U = S; end;
    end
    [U, S, V, alpha, beta, p, details] = mex_lansvd(A, options);
    % number of Lanczos vectors computed
    k_done = size(alpha, 1);
    p_norm = beta(k_done+1);
    if isfield(options, 'k')
        k = options.k;
    end
    if isfield(options, 'lambda')
        k = find(S <= options.lambda,1) - 1;
    end
    % Let's compute all the singular vectors if requested by caller
    if nargout>2 % computation of Ritz vectors
        % Form the k+1 x k bidiagonal matrix from alpha and beta
        B = spdiags([alpha(1:k_done) beta(2:k_done+1)], [0, -1], k_done+1, k_done);
        % Compute singular vectors
        [P,S,Q] = svd(full(B),0);
        % Singular values
        S = diag(S);
        % Keep the relevant K columns
        if size(Q,2)~=k
            Q = Q(:,1:k);
            P = P(:,1:k);
        end
        % Compute and normalize Ritz vectors (overwrites U and V to save memory).
        if p_norm~=0
            U = U*P(1:k_done,:) + (p/p_norm)*P(k_done+1,:);
        else
            U = U*P(1:k_done,:);
        end
        V = V*Q;
        % Make sure that the requested Ritz vectors are normalized
        for i=1:k
            nq = norm(V(:,i));
            if isfinite(nq) & nq~=0 & nq~=1
              V(:,i) = V(:,i)/nq;
            end
            nq = norm(U(:,i));
            if isfinite(nq) & nq~=0 & nq~=1
              U(:,i) = U(:,i)/nq;
            end
        end
    end % computation of Ritz vectors
    % Pick out desired part the spectrum
    S = S(1:k);
    if nargout == 1
        U = S;
    end
    if nargout >= 4
        details.alpha = alpha;
        details.beta = beta;
        details.p = p;
        details.k_done = k_done;
    end
end


% VL_LBP  Local Binary Patterns
%   F = VL_LBP(IM, CELLSIZE) computes the Local Binary Pattern (LBP)
%   features for image I.
%
%   IM is divided in cells of size CELLSIZE. F is a three-dimensional
%   array containing one histograms of quantized LBP features per
%   cell. The witdh of F is FLOOR(WIDTH/CELLSIZE), where WIDTH is the
%   width of the image. The same for the height. The third dimension
%   is 58.
%
%   See also: VL_HELP().

% AUTORIGHTS


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% [accu,prediction] = kernel_knn_classification(test_kernel,train_label,K,test_label)
% this function performs classification with given kernels and labels
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input parameters:
% test_kernel: the test kernel
% train_label: the training label
% K: Ks of knn classifier
% test_label: the test label
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Output parameters:
% accu: the classification accuracy
% prediction: the predicted label for the test data
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Jianjia Zhang, jz163@uowmail.edu.au Dec, 2014, all rights reserved
% For implementation details, please refer to:
% "Learning Discriminative Stein Kernel for SPD Matrices and Its Applications."
% arXiv preprint arXiv:1407.1974 (2014).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [accu,prediction] = kernel_knn_classification_new(test_kernel,train_label,K,test_label,options)
    ntest = size(test_kernel,2);
    if(size(test_kernel,1) ~= length(train_label))
        test_kernel = test_kernel';
        ntest = size(test_kernel,2);
    end
    test_label = test_label';
    train_label = train_label';
    nk = size(K,2);
    prediction = zeros(ntest,nk);
    for itest = 1:ntest
        cur_test = test_kernel(:,itest);
        [Y,I] = sort(cur_test,'descend');
        ttrain_label = train_label(I);
        for ik = 1:nk
            ktrain_label = ttrain_label(1:K(ik));

            ulabel = unique(ktrain_label);

            nlabel = size(ulabel,1);
            count = zeros(1,nlabel);
            for ilabel = 1:nlabel
                count(ilabel) = sum(ktrain_label==ulabel(ilabel));
            end
            [~,I] = max(count);
            prediction(itest,ik) = ulabel(I);
        end

       if options.verbose
            correct = (ulabel(I) == test_label(itest));
            fprintf('# Kernel kNN classifier: test:%03d, predict class: %03d --> ground truth :%03d (%d)\n', itest, ulabel(I), test_label(itest), correct);
       end

    end

    for ik = 1:nk
        accu(ik) = sum(prediction(:,ik) == test_label)/ntest;
    end
end


function kernel = SC_ASGkernel(sccalib, geo, dus, dvs)
%% Anti-sctter grid response function
% Reference: Improved scatter correction using adaptive scatter kernel superposition
% Input:
%           geo: geometry structure
%           dus: downsampled u vector
%           dvs: downsampled v vector
% Output:
%           kernel: anti-scatter grid
%
% Date: 2021-05-04
% Author: Yi Du (yi.du@hotmail.com)

%% Geometry
% unit mm
DSD = geo.DSD;

%% Anti-Scatter Grid along X direction
% vs dimension
gamma = abs(rad2deg(atan(dvs'./DSD)));

%% Transmission modelling
k = -0.15;
b = 1;

t_ratio = k.*abs(dvs'/10) + b;

%% Kernel: [nv, nu]
kernel = repmat(t_ratio, [1,length(dus)]);
efficiency = str2double(sccalib.CalibrationResults.ObjectScatterModels.ObjectScatterModel{1}.GridEfficiency.LamellaTransmission.Text);
kernel(kernel < efficiency) = efficiency;

end


function [irLin, irNonLin] = extractIR(sweep_response, invsweepfft)
% Extract impulse response from swept-sine response.
%   [irLin, irNonLin] = extractIR(sweep_response, invsweepfft)
%   Extracts the impulse response from the swept-sine response.  Use
%   synthSweep.m first to create the stimulus; then pass it through the
%   device under test; finally, take the response and process it with the
%   inverse swept-sine to produce the linear impulse response and
%   non-linear simplified Volterra diagonals.  The location of each
%   non-linear order can be calculated with the sweepRate - this will be
%   implemented as a future revision.
%
%   Developed at Oygo Sound LLC
%
%   Equations from Muller and Massarani, "Transfer Function Measurement
%   with Sweeps."
%
%   Modified by Jacob Donley (jrd089@uowmail.edu.au) (January 2017)

if diff(size(sweep_response))>0, sweep_response = sweep_response.'; end
if diff(size(invsweepfft))>0, invsweepfft = invsweepfft.'; end

N = length(invsweepfft);
sweepfft = fft(sweep_response,N);

%%% convolve sweep with inverse sweep (freq domain multiply)
invsweepfft = repmat(invsweepfft,1,size(sweepfft,2));
ir = real(ifft(invsweepfft.*sweepfft));

ir = circshift(ir, length(ir)/2, 1);

irLin = ir(end/2+1:end,:);
irNonLin = ir(1:end/2,:);


function [ctheta_f, theta_pre_f, L] = train_filter(ctheta_f, xlf, yf, ...
    theta_pre_f, params, output_sz, seq)

    for k = 1: numel(xlf)
        x_f = xlf{k};

        if (seq.frame == 1)
            theta_pre_f{k} = zeros(size(x_f));
            lambda_2 = 0;
        else
            lambda_2 = params.lambda2(k);
        end

        % intialisation
        theta_f = single(zeros(size(x_f)));
        theta_prime_f = theta_f;
        eta_f = theta_f;
        mu  = params.init_penalty_factor(k);
        mu_scale_step = params.penalty_scale_step(k);

        % pre-compute the variables
        T = prod(output_sz);
        S_xx = sum(conj(x_f) .* x_f, 3);
        Stheta_pre_f = sum(conj(x_f) .* theta_pre_f{k}, 3);
        Sfx_pre_f = bsxfun(@times, x_f, Stheta_pre_f);

        % solve via ADMM algorithm
        iter = 1;
        while (iter <= params.max_iterations)

            % solving theta
            B = S_xx + T * (mu + lambda_2);
            Sgx_f = sum(conj(x_f) .* theta_prime_f, 3);
            Shx_f = sum(conj(x_f) .* eta_f, 3);

            theta_f = ((1/(T*(mu + lambda_2)) * bsxfun(@times,  yf{k}, x_f)) ...
                - ((1/(mu + lambda_2)) * eta_f) +(mu/(mu + lambda_2)) ...
                * theta_prime_f) + (lambda_2/(mu + lambda_2)) * theta_pre_f{k} ...
                - bsxfun(@rdivide,(1/(T*(mu + lambda_2)) * bsxfun(@times, ...
                x_f, (S_xx .*  yf{k})) + (lambda_2/(mu + lambda_2)) * Sfx_pre_f - ...
                (1/(mu + lambda_2))* (bsxfun(@times, x_f, Shx_f)) +(mu/(mu ...
                + lambda_2))* (bsxfun(@times, x_f, Sgx_f))), B);

            % solving theta_prime
            X = real(ifft2(mu * theta_f+ eta_f));
            if (seq.frame == 1)
                X_temp = zeros(size(X));
                for i = 1:size(X,3)
                 X_temp(:,:,i) = X(:,:,i) ./  (params.reg_window{k} .^2 + mu);
                end
                L = 0;
            else
            X_temp=X;
            L{k} = max(0,1-1./(mu*numel(X)*sqrt(sum(X_temp.^2,3))));

            [~,b] = sort(L{k}(:),'descend');
            L{k}(b(ceil(params.fs_rate(k)*1/params.search_area_scale^2*numel(b)):end)) = 0;

            X_temp = repmat(L{k},1,1,size(X_temp,3)) .* X_temp;
            end

            theta_prime_f = fft2(X_temp);

            %   update eta
            eta_f = eta_f + (mu * (theta_f - theta_prime_f));

            %   update mu
            mu = min(mu_scale_step * mu, 0.1);

            iter = iter+1;
        end

        % save the trained filters
        theta_pre_f{k} = theta_f;

        if seq.frame == 1
            ctheta_f{k} = theta_f;
        else
            ctheta_f{k} = params.rl * theta_f + (1-params.rl) * ctheta_f{k};
        end
    end

end


function [m, o, lambda, eigv]  = mean(o,varargin)
% mean of a list of orientations, principle axes and moments of inertia
%
% Syntax
%   [m, q, lambda, V] = mean(ori)
%   [m, q, lambda, V] = mean(ori,'robust')
%   [m, q, lambda, V] = mean(ori,'weights',weights)
%
% Input
%  ori      - list of @orientation
%
% Options
%  weights  - list of weights
%
% Output
%  m      - mean @orientation
%  o      - crystallographic equivalent @orientation projected to fundamental region
%  lambda - principle moments of inertia
%  V      - principle axes of inertia (@orientation)
%
% See also
% BinghamODF

if isempty(o)
  m = o;
  m.a = NaN; m.b = NaN; m.c = NaN; m.d = NaN; m.i = false;
  if nargout > 2, lambda = zeros(1,4); end
  if nargout > 3, eigv = eye(4); end
  return
elseif length(o) == 1
  m = o;
  if nargout > 1
    eigv = eye(4);
    lambda = [1,0,0,0];
  end
  return;
end

if check_option(varargin,'noSymmetry')

  [m, lambda, eigv] = mean@quaternion(o,varargin{:});

else

  s = size(o);

  % first approximation
  m = get_option(varargin,'q0');
  if isempty(m), m = o.subSet(find(~isnan(o.a),1)); end

  % project around q_mean
  o = project2FundamentalRegion(o,m);

  % compute mean without symmetry
  [m, lambda, eigv] = mean@quaternion(o,varargin{:});

  d = abs(quat_dot(o,m));
  if min(d(:)) < cos(10*degree)
    o = project2FundamentalRegion(o,m);
    [m, lambda, eigv] = mean@quaternion(o,varargin{:});
  end

  if nargout > 1, o = reshape(project2FundamentalRegion(o,m),s); end

end
m.i = false;


function ecc = getEccFromRpAndSma(Sma, Rp)
%getEccFromRpAndSma Summary of this function goes here
%   Detailed explanation goes here
    ecc = 1 - Rp/Sma;
end


classdef nnscale < nntest
  methods (Test)

    function basic(test)
      batchSize = 10 ;
      x1 = test.randn([5 5 3 batchSize]) ;
      x2 = test.randn([1 1 3 1]) ; % match along non-singletons
      b = [] ;
      y = vl_nnscale(x1, x2, b) ;

      % check derivatives with numerical approximation
      dzdy = test.randn(size(y)) ;
      [dzdx1, dzdx2, dzdb] = vl_nnscale(x1, x2, b, dzdy) ;
      test.der(@(x1) vl_nnscale(x1, x2, b), x1, dzdy, dzdx1, 1e-3*test.range) ;
      test.der(@(x2) vl_nnscale(x1, x2, b), x2, dzdy, dzdx2, 1e-3*test.range) ;
      assert(isempty(dzdb), 'bias derivative should be empty') ;
    end

    function basicBias(test)
      batchSize = 10 ;
      x1 = test.randn([5 5 3 batchSize]) ;
      x2 = test.randn([1 1 3 1]) ; % match along non-singletons
      b = test.randn([1 1 3 1]) ; % match along non-singletons
      y = vl_nnscale(x1, x2, b) ;

      % check derivatives with numerical approximation
      dzdy = test.randn(size(y)) ;
      [dzdx1, dzdx2, dzdb] = vl_nnscale(x1, x2, b, dzdy) ;
      test.der(@(x1) vl_nnscale(x1, x2, b), x1, dzdy, dzdx1, 1e-3*test.range) ;
      test.der(@(x2) vl_nnscale(x1, x2, b), x2, dzdy, dzdx2, 1e-3*test.range) ;
      test.der(@(b) vl_nnscale(x1, x2, b), b, dzdy, dzdb, 1e-3*test.range) ;
    end

  end
end


% SPARFWSLV Solves block sparse upper-triangular system.
%    y = sparfwslv(L,b) yields the same result as
%              y = L.L\b(L.perm,:)
%    However, SPARFWSLV is faster than the built-in operator "\",
%    because it uses dense linear algebra and loop-unrolling on
%    supernodes.
%
%    For sparse b, one should use
%    y = sparfwslv(L,b,symbfwblk(L.L,L.xsuper, b));
%
%    Typical use, with X sparse m x m positive definite and b is m x n:
%            L = sparchol(symbchol(X),X);
%            L.d(L.dep) = inf;
%            y = sparbwslv(L,sparfwslv(L,b) ./ L.d);
%    Then y solves X*y=b.
%
% See also symbchol, sparchol, sparbwslv, mrdivide, mldivide.

function y = sparfwslv(L,b, ysymb)
%
% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA  (since 1.1)
%
% Copyright (C) 2001 Jos F. Sturm (up to 1.05R5)
%   Dept. Econometrics & O.R., Tilburg University, the Netherlands.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% Affiliation SeDuMi 1.03 and 1.04Beta (2000):
%   Dept. Quantitative Economics, Maastricht University, the Netherlands.
%
% Affiliations up to SeDuMi 1.02 (AUG1998):
%   CRL, McMaster University, Canada.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% 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
%

% ----------------------------------------
% Solve L.L * y = b
% ----------------------------------------
if nargin > 2
    y = fwblkslv(L,b,ysymb);
else
    y = fwblkslv(L,b);
end


function [Dimension,NodeCoord,NodeWeight,Name]=GetTSPData(infile)
if exist(infile,'file')
    fid=fopen(infile,'r');
else
    disp('Input file no exist!');
    return;
end
if fid<0
    disp('Error while open file!');
    return;
end
NodeWeight = [];
while feof(fid)==0
    temps=fgetl(fid);
    if strcmp(temps,'')
        continue;
    elseif strncmpi('NAME',temps,4)
        k=findstr(temps,':');
        Name=temps(k+1:length(temps));
    elseif strncmpi('DIMENSION',temps,9)
        k=findstr(temps,':');
        d=temps(k+1:length(temps));
        Dimension=str2double(d);
    elseif strncmpi('EDGE_WEIGHT_SECTION',temps,19)
        formatstr = [];
        for i=1:Dimension
            formatstr = [formatstr,'%g '];
        end
        NodeWeight=fscanf(fid,formatstr,[Dimension,Dimension]);
        NodeWeight=NodeWeight';
    elseif strncmpi('NODE_COORD_SECTION',temps,18) || strncmpi('DISPLAY_DATA_SECTION',temps,20)
        NodeCoord=fscanf(fid,'%g %g %g',[3 Dimension]);
        NodeCoord=NodeCoord';
    end
end
fclose(fid);


function [Gs, op, nodes] = mk_nbrs_of_dag(G0)
% MK_NBRS_OF_DAG Make all DAGs that differ from G0 by a single edge deletion, addition or reversal
% [Gs, op, nodes] = mk_nbrs_of_dag(G0)
%
% Gs{i} is the i'th neighbor.
% op{i} = 'add', 'del', or 'rev' is the operation used to create the i'th neighbor.
% nodes(i,1:2) are the head and tail of the operated-on arc.

Gs = {};
op = {};
nodes = [];

[I,J] = find(G0);
nnbrs = 1;
% all single edge deletions
for e=1:length(I)
  i = I(e); j = J(e);
  G = G0;
  G(i,j) = 0;
  Gs{nnbrs} = G;
  op{nnbrs} = 'del';
  nodes(nnbrs, :) = [i j];
  nnbrs = nnbrs + 1;
end

% all single edge reversals
for e=1:length(I)
  i = I(e); j = J(e);
  G = G0;
  G(i,j) = 0;
  G(j,i) = 1;
  if acyclic(G)
    Gs{nnbrs} = G;
    op{nnbrs} = 'rev';
    nodes(nnbrs, :) = [i j];
    nnbrs = nnbrs + 1;
  end
end

[I,J] = find(~G0);
% all single edge additions
for e=1:length(I)
  i = I(e); j = J(e);
  if i ~= j % don't add self arcs
    G = G0;
    G(i,j) = 1;
    if G(j,i)==0 % don't add i->j if j->i exists already
      if acyclic(G)
	Gs{nnbrs} = G;
	op{nnbrs} = 'add';
	nodes(nnbrs, :) = [i j];
	nnbrs = nnbrs + 1;
      end
    end
  end
end


% Let the user draw a square with the mouse,
% and then click on the corners to do a manual segmentation

ss = 6;
Q1 = 1; Q2 = 2; Q3 = 3; obsvel = 6;
CLOCKWISE = 1; ANTICLOCK = 2;
LR = 1; UD = 2; RL = 3; DU = 4;

% repeat this block manually incrementing the sequence number
% and setting ori.
% (since I don't know how to call getmouse as a call-return function).
seq = 4;
%ori = CLOCKWISE
ori = ANTICLOCK;
clear xpos ypos
getmouse
% end block

% manual segmentation with the mouse
startseg(1) = 1;
for i=2:4
  fprintf('click on start of segment %d\n', i);
  [x,y] = ginput(1);
  plot(x,y,'ro')
  d = dist2([xpos; ypos]', [x y]);
  startseg(i) = argmin(d);
end

% plot corners in green
%ti = first point in (i+1)st segment
t1 = startseg(1); t2 = startseg(2); t3 = startseg(3); t4 = startseg(4);
plot(xpos(t2), ypos(t2), 'g*')
plot(xpos(t3), ypos(t3), 'g*')
plot(xpos(t4), ypos(t4), 'g*')

xvel = xpos(2:end) - xpos(1:end-1);
yvel = ypos(2:end) - ypos(1:end-1);
speed = [xvel(:)'; yvel(:)'];
pos_data{seq} = [xpos(:)'; ypos(:)'];
vel_data{seq} = [xvel(:)'; yvel(:)'];
T = length(xvel);
Q1label{seq} = num2cell(repmat(ori, 1, T));
Q2label{seq} = zeros(1, T);
if ori == CLOCKWISE
  Q2label{seq}(t1:t2) = LR;
  Q2label{seq}(t2+1:t3) = UD;
  Q2label{seq}(t3+1:t4) = RL;
  Q2label{seq}(t4+1:T) = DU;
else
  Q2label{seq}(t1:t2) = RL;
  Q2label{seq}(t2+1:t3) = UD;
  Q2label{seq}(t3+1:t4) = LR;
  Q2label{seq}(t4+1:T) = DU;
end

% pos_data{seq}(:,t), vel_data{seq}(:,t) Q1label{seq}(t) Q2label{seq}(t)
save 'square4' pos_data vel_data Q1label Q2label

nseq = 4;
cases = cell(1,nseq);
for seq=1:nseq
  T = size(vel_data{seq},2);
  ev = cell(ss,T);
  ev(obsvel,:) = num2cell(vel_data{seq},1);
  ev(Q1,:) = Q1label{seq};
  ev(Q2,:) = num2cell(Q2label{seq});
  cases{seq} = ev;
end
save 'square4_cases' cases


function [varargout]=edgeVec(E,V)

% function [N,Vp,Nv]=edgeVec(E,V)
% ------------------------------------------------------------------------
%
% ------------------------------------------------------------------------

%% Compute edge vectors
Vp=V(E(:,1),:); %Edge vector origin
N=V(E(:,2),:)-Vp; %Edge vector

%% Collect output
varargout{1}=N;
varargout{2}=Vp;

if nargout==3
    Nv=faceToVertexMeasure(E,V,N); %Edge vectors at vertices
    varargout{3}=Nv;
end

%%
% _*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/>.


% Test file for ADCHEBFUN FRED

function pass = test_fred

K = @(s, t)  exp(-(s-t).^2);

% List of trigonometric functions to test.
func = @(u) fred(K, u);

% Tolerance for Taylor testing
tolOrder = 1e-2;
tolDiff = 1e-12;
% Initialise vector with pass information
pass = zeros(1, numel(func));

% Call the valueTesting method, which also returns linearity information
[err, lin] = adchebfun.valueTesting(func);

% First, check that the computed function values match what we expect
pass(1) = ( err == 0 );

% Call the taylorTesting method
[order1, order2, nDiff2] = adchebfun.taylorTesting(func,2);

% We expect all elements of ORDER1 to be close to 1. Since the methods being
% tested in this case are all linear, ORDER2 will be noise. However, since
% the methods are indeed linear, we should expect nDiff2 to have values all
% close to machine epsilon, which we can use to check for the correctness of
% the derivative computed.
pass(2) = ( (max(abs(order1 - 1)) < tolOrder) && ...
    (max(abs(nDiff2)) < tolDiff) );

% Check that we received the correct linearity information
pass(3) = ( lin == 1 );

end