function graphs = makeConnectivityCircle(hmm,k,labels,...
    centergraphs,scalegraphs,partialcorr,threshold,ColorMap,figure_number)
% Plot HMM connectomes in connectivity circle format
%   (not to be used on an HMM-TDE model or an HMM-MAR model directly;
%   for this use makeSpectralConnectivityCircle)
%
% hmm: hmm struct as comes out of hmmmar
% k: which state or states to plot, e.g. 1:4. If left empty, then all of them
% labels : names of the regions
% centergraphs: whether to center the graphs according to the across-map average
% scalegraphs: whether to scale the graphs so that each voxel has variance
%       equal 1 across maps
% partialcorr: whether to use a partial correlation matrix or a correlation
%   matrix (default: 0)
% threshold: proportion threshold above which graph connections are
%       displayed (between 0 and 1, the higher the fewer displayed connections)
% ColorMap: a (nodes by 3) matrix of [r g b] triples, with colours
%           to be used for the nodes
% figure_number: number of figure to display
%
% OUTPUT:
% graph: (regions by regions by state) array with the estimated connectivity maps
%
% Notes:
% It needs the circularGraph toolbox from Matlab in the path:
%   https://github.com/paul-kassebaum-mathworks/circularGraph
%
% Diego Vidaurre (2020)

if nargin < 4 || isempty(centergraphs), centergraphs = 0; end
if nargin < 5 || isempty(scalegraphs), scalegraphs = 0; end
if nargin < 6 || isempty(partialcorr), partialcorr = 0; end
if nargin < 7 || isempty(threshold), threshold = 0.95; end
if nargin < 8 || isempty(ColorMap), ColorMap = []; end
if nargin < 9 || isempty(figure_number), figure_number = randi(100); end

do_HMM_pca = strcmpi(hmm.train.covtype,'pca');
if ~do_HMM_pca && ~strcmp(hmm.train.covtype,'full')
    error('Cannot great a brain graph because the states do not contain any functional connectivity')
end

K = length(hmm.state);
if ~isempty(k), index_k = k; else, index_k = 1:K; end
if do_HMM_pca
    ndim = size(hmm.state(1).W.Mu_W,1);
else
    if isfield(hmm.train,'A'), ndim = size(hmm.train.A,1);
    else, ndim = size(hmm.state(1).Omega.Gam_rate,1);
    end
end

if nargin < 3 || isempty(labels)
    labels = cell(ndim,1);
    for j = 1:ndim
        if ndim < 200
            labels{j} = ['Parcel ' num2str(j)];
        else
            labels{j} = num2str(j);
        end
    end
end

graphs = zeros(ndim,ndim,K);

for k = 1:K
    if partialcorr
        [~,~,~,C] = getFuncConn(hmm,k,1);
    else
        [~,C,] = getFuncConn(hmm,k,1);
    end
    C(eye(ndim)==1) = 0;
    graphs(:,:,k) = C;
end

if centergraphs
    graphs = graphs - repmat(mean(graphs,3),[1 1 K]);
end
if scalegraphs
    graphs = graphs ./ repmat(std(graphs,[],3),[1 1 K]);
end

for ik = 1:length(index_k)
    k = index_k(ik);
    C = graphs(:,:,k);
    c = C(triu(true(ndim),1)==1); c = sort(c); c = c(end-1:-1:1);
    th = c(round(length(c)*(1-threshold)));
    C(C<th) = 0;
    try
        figure(k+figure_number)
        if isempty(ColorMap)
            circularGraph(C,'Label',labels);
        else
            circularGraph(C,'Label',labels,'Colormap',ColorMap);
        end
    catch
        error('Please get the Matlab circularGraph toolbox first')
    end
end

graphs = graphs(:,:,index_k);

end
%
%
%
% function nets_netweb_2(netF,netP,sumpics,outputdir)
% % borrowed from Steve's fslnets
%
% % replicate functionality from nets_hierarchy
% grot=prctile(abs(netF(:)),99); netmatL=netF/grot; netmatH=netP/grot;
% usenet=netmatL;  usenet(usenet<0)=0;
% N=size(netmatL,1);  grot=prctile(abs(usenet(:)),99); usenet=max(min(usenet/grot,1),-1)/2;
% DD = 1:N;
% for J = 1:N, for I = 1:J-1,   y((I-1)*(N-I/2)+J-I) = 0.5 - usenet(I,J);  end; end;
% linkages=linkage(y,'ward');
% set(0,'DefaultFigureVisible','off');
% figure;[~,~,hier]=dendrogram(linkages,0,'colorthreshold',0.75);
% close;set(0,'DefaultFigureVisible','on');
% clusters=cluster(linkages,'maxclust',10)';
%
% mkdir(outputdir)
% netjs = [fileparts(which('makeConnectivityCircle')) '/netjs'];
% copyfile(netjs,outputdir) % copy javascript stuff into place
% NP=sprintf('%s/data/dataset1',outputdir);
% save(sprintf('%s/Znet1.txt',NP),'netF','-ascii');
% save(sprintf('%s/Znet2.txt',NP),'netP','-ascii');
% save(sprintf('%s/hier.txt',NP),'hier','-ascii');
% save(sprintf('%s/linkages.txt',NP),'linkages','-ascii');
% save(sprintf('%s/clusters.txt',NP),'clusters','-ascii');
% mkdir(sprintf('%s/melodic_IC_sum.sum',NP));
% for i=1:length(DD)
%   system(sprintf('/bin/cp %s.sum/%.4d.png %s/melodic_IC_sum.sum/%.4d.png',sumpics,DD(i)-1,NP,i-1));
% end
%
% end
%


function d = getdict
% Dictionary of NIFTI stuff
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

%
% $Id$

persistent dict;
if ~isempty(dict),
    d = dict;
    return;
end;

% Datatype
t = true;
f = false;
table = {...
    0   ,'UNKNOWN'   ,'uint8'   ,@uint8  ,1,1  ,t,t,f
    1   ,'BINARY'    ,'uint1'   ,@logical,1,1/8,t,t,f
    256 ,'INT8'      ,'int8'    ,@int8   ,1,1  ,t,f,t
    2   ,'UINT8'     ,'uint8'   ,@uint8  ,1,1  ,t,t,t
    4   ,'INT16'     ,'int16'   ,@int16  ,1,2  ,t,f,t
    512 ,'UINT16'    ,'uint16'  ,@uint16 ,1,2  ,t,t,t
    8   ,'INT32'     ,'int32'   ,@int32  ,1,4  ,t,f,t
    768 ,'UINT32'    ,'uint32'  ,@uint32 ,1,4  ,t,t,t
    1024,'INT64'     ,'int64'   ,@int64  ,1,8  ,t,f,f
    1280,'UINT64'    ,'uint64'  ,@uint64 ,1,8  ,t,t,f
    16  ,'FLOAT32'   ,'float32' ,@single ,1,4  ,f,f,t
    64  ,'FLOAT64'   ,'double'  ,@double ,1,8  ,f,f,t
    1536,'FLOAT128'  ,'float128',@crash  ,1,16 ,f,f,f
    32  ,'COMPLEX64' ,'float32' ,@single ,2,4  ,f,f,f
    1792,'COMPLEX128','double'  ,@double ,2,8  ,f,f,f
    2048,'COMPLEX256','float128',@crash  ,2,16 ,f,f,f
    128 ,'RGB24'     ,'uint8'   ,@uint8  ,3,1  ,t,t,f};

dtype = struct(...
    'code'     ,table(:,1),...
    'label'    ,table(:,2),...
    'prec'     ,table(:,3),...
    'conv'     ,table(:,4),...
    'nelem'    ,table(:,5),...
    'size'     ,table(:,6),...
    'isint'    ,table(:,7),...
    'unsigned' ,table(:,8),...
    'min',-Inf,'max',Inf',...
    'supported',table(:,9));
for i=1:length(dtype),
    if dtype(i).isint
        if dtype(i).unsigned
            dtype(i).min =  0;
            dtype(i).max =  2^(8*dtype(i).size)-1;
        else
            dtype(i).min = -2^(8*dtype(i).size-1);
            dtype(i).max =  2^(8*dtype(i).size-1)-1;
        end;
    end;
end;
% Intent
table = {...
    0   ,'NONE'         ,'None',{}
    2   ,'CORREL'       ,'Correlation statistic',{'DOF'}
    3   ,'TTEST'        ,'T-statistic',{'DOF'}
    4   ,'FTEST'        ,'F-statistic',{'numerator DOF','denominator DOF'}
    5   ,'ZSCORE'       ,'Z-score',{}
    6   ,'CHISQ'        ,'Chi-squared distribution',{'DOF'}
    7   ,'BETA'         ,'Beta distribution',{'a','b'}
    8   ,'BINOM'        ,'Binomial distribution',...
        {'number of trials','probability per trial'}
    9   ,'GAMMA'        ,'Gamma distribution',{'shape','scale'}
    10  ,'POISSON'      ,'Poisson distribution',{'mean'}
    11  ,'NORMAL'       ,'Normal distribution',{'mean','standard deviation'}
    12  ,'FTEST_NONC'   ,'F-statistic noncentral',...
        {'numerator DOF','denominator DOF','numerator noncentrality parameter'}
    13  ,'CHISQ_NONC'   ,'Chi-squared noncentral',{'DOF','noncentrality parameter'}
    14  ,'LOGISTIC'     ,'Logistic distribution',{'location','scale'}
    15  ,'LAPLACE'      ,'Laplace distribution',{'location','scale'}
    16  ,'UNIFORM'      ,'Uniform distribition',{'lower end','upper end'}
    17  ,'TTEST_NONC'   ,'T-statistic noncentral',{'DOF','noncentrality parameter'}
    18  ,'WEIBULL'      ,'Weibull distribution',{'location','scale','power'}
    19  ,'CHI'          ,'Chi distribution',{'DOF'}
    20  ,'INVGAUSS'     ,'Inverse Gaussian distribution',{'mu','lambda'}
    21  ,'EXTVAL'       ,'Extreme Value distribution',{'location','scale'}
    22  ,'PVAL'         ,'P-value',{}
    23  ,'LOGPVAL'      ,'Log P-value',{}
    24  ,'LOG10PVAL'    ,'Log_10 P-value',{}
    1001,'ESTIMATE'     ,'Estimate',{}
    1002,'LABEL'        ,'Label index',{}
    1003,'NEURONAMES'   ,'NeuroNames index',{}
    1004,'MATRIX'       ,'General matrix',{'M','N'}
    1005,'MATRIX_SYM'   ,'Symmetric matrix',{}
    1006,'DISPLACEMENT' ,'Displacement vector',{}
    1007,'VECTOR'       ,'Vector',{}
    1008,'POINTS'       ,'Pointset',{}
    1009,'TRIANGLE'     ,'Triangle',{}
    1010,'QUATERNION'   ,'Quaternion',{}
    1011,'DIMLESS'      ,'Dimensionless',{}
};
intent = struct('code',table(:,1),'label',table(:,2),...
    'fullname',table(:,3),'param',table(:,4));

% Units
table = {...
     0,   1,'UNKNOWN'
     1,1000,'m'
     2,   1,'mm'
     3,1e-3,'um'
     8,   1,'s'
    16,1e-3,'ms'
    24,1e-6,'us'
    32,   1,'Hz'
    40,   1,'ppm'
    48,   1,'rads'};
units = struct('code',table(:,1),'label',table(:,3),'rescale',table(:,2));

% Reference space
% code  = {0,1,2,3,4};
table = {...
    0,'UNKNOWN'
    1,'Scanner Anat'
    2,'Aligned Anat'
    3,'Talairach'
    4,'MNI_152'};
anat  = struct('code',table(:,1),'label',table(:,2));

% Slice Ordering
table = {...
    0,'UNKNOWN'
    1,'sequential_increasing'
    2,'sequential_decreasing'
    3,'alternating_increasing'
    4,'alternating_decreasing'};
sliceorder = struct('code',table(:,1),'label',table(:,2));

% Q/S Form Interpretation
table = {...
    0,'UNKNOWN'
    1,'Scanner'
    2,'Aligned'
    3,'Talairach'
    4,'MNI152'};
xform = struct('code',table(:,1),'label',table(:,2));

dict = struct('dtype',dtype,'intent',intent,'units',units,...
    'space',anat,'sliceorder',sliceorder,'xform',xform);

d = dict;
return;

function varargout = crash(varargin)
error('There is a NIFTI-1 data format problem (an invalid datatype).');


function fk_body = autoGen_fk_body(q1,q2,q3)
%AUTOGEN_FK_BODY
%    FK_BODY = AUTOGEN_FK_BODY(Q1,Q2,Q3)

%    This function was generated by the Symbolic Math Toolbox version 8.4.
%    01-Jun-2020 11:59:03

t2 = cos(q1);
t3 = cos(q2);
t4 = sin(q1);
t5 = q2+q3;
t6 = cos(t5);
t7 = sin(t5);
t8 = t3.*3.2e+1;
t9 = t6.*5.7e+1;
t10 = t8+t9;
fk_body = reshape([t2.*t6,t4.*t6,-t7,0.0,-t4,t2,0.0,0.0,t2.*t7,t4.*t7,t6,0.0,(t2.*t10)./2.0e+2,(t4.*t10)./2.0e+2,t7.*(-5.7e+1./2.0e+2)-sin(q2).*(4.0./2.5e+1),1.0],[4,4]);


%+========================================================================+
%|                                                                        |
%|            This script uses the GYPSILAB toolbox for Matlab            |
%|                                                                        |
%| COPYRIGHT : Matthieu Aussal, Marc Bakry (c) 2017-2019.                 |
%| PROPERTY  : Centre de Mathematiques Appliquees, Ecole polytechnique,   |
%| route de Saclay, 91128 Palaiseau, France. All rights reserved.         |
%| LICENCE   : This program is free software, distributed in the hope that|
%| it will be useful, but WITHOUT ANY WARRANTY. Natively, you can use,    |
%| redistribute and/or modify it under the terms of the GNU General Public|
%| License, as published by the Free Software Foundation (version 3 or    |
%| later,  http://www.gnu.org/licenses). For private use, dual licencing  |
%| is available, please contact us to activate a "pay for remove" option. |
%| CONTACT   : matthieu.aussal@polytechnique.edu                          |
%|             marc.bakry@polytechnique.edu                               |
%| WEBSITE   : www.cmap.polytechnique.fr/~aussal/gypsilab                 |
%|                                                                        |
%| Please acknowledge the gypsilab toolbox in programs or publications in |
%| which you use it.                                                      |
%|________________________________________________________________________|
%|   '&`   |                                                              |
%|    #    |   FILE       : nrtVibroSlab2d.m                              |
%|    #    |   VERSION    : 0.55                                          |
%|   _#_   |   AUTHOR(S)  : Matthieu Aussal & Marc Bakry                  |
%|  ( # )  |   CREATION   : 14.03.2019                                    |
%|  / 0 \  |   LAST MODIF :                                               |
%| ( === ) |   SYNOPSIS   :                                               |
%|  `---'  |                                                              |
%+========================================================================+

% Cleaning
clear all
close all
clc

% Gypsilab path
run('../../addpathGypsilab.m')

% Width of the slab
e = 0.5

% Frequency
f = 900:500:4000

% Incident direction (from bottom)
X0  = [0 1 0];

% Exterior domain (water)
rho0 = 1000;         % density      (kg.m3)
c0   = 1500;         % celerity     (m.s-1)
k0   = 2*pi/c0.*f;   % wave-number  (m-1)
lam0 = c0./f;        % wave-length  (m)

% Interior domain (different from water)
rhoS = 2*rho0;                                 % density                             (kg.m3)
cL   = 2*c0;                                   % celerity of longitudinal waves      (m.s-1)
kL   = 2*pi.*f./cL;                            % wave-number of longitudinal waves   (m-1)
lamL = real(cL)./f;                            % wavelength of longitudinal waves    (m)
cT   = 0;                                      % celerity of transverse waves        (m.s-1)
kT   = 2*pi.*f./cT;                            % wave-number of transverse waves     (m-1)
lamT = real(cT)./f;                            % wavelength of transverse waves      (m)

% Solution (pressure)
sol = zeros(2,length(f));

% Loop for each frequency
for i = 1:length(f)
    % Minimum wavelength
    tmp  = [lam0(i),lamL(i),lamT(i)];
    lmin = min(tmp(tmp>0));

    % Slab mesh
    L    = 20 * lmin;            % 20 wavelength to simulate infinite slab
    nx   = ceil(L/lmin * 6)+1;   % 6 node per wavelength for L
    ny   = ceil(e/lmin * 12)+1;  % 12 node per wavelength for e
    N    = nx * ny;              % Total number of nodes
    mesh = mshSquare(N,[L e])

    % Radiative mesh (fixed number of nodes)
    radiat = mshSquare(1e3,[L L]);

    % Boundary
    bound = swap(mesh.bnd)

    % Measurement points for trans and refl coeff (1 wavelenth from bound)
    Xmes = [0 -e/2-lmin 0 ; 0 e/2+lmin 0];

    % Cut-off function (50% full, 10% decrease)
    cutoff = vibsCutoff(1,L/5,L/10);

    % Green kernel function
    Gxy         = @(X,Y) femGreenKernel(X,Y,'[H0(kr)]',k0(i));
    gradyGxy{1} = @(X,Y) femGreenKernel(X,Y,'grady[H0(kr)]1',k0(i));
    gradyGxy{2} = @(X,Y) femGreenKernel(X,Y,'grady[H0(kr)]2',k0(i));
    gradyGxy{3} = @(X,Y) femGreenKernel(X,Y,'grady[H0(kr)]3',k0(i));

    % Plane wave function
    PW         = @(X) exp(1i*k0(i)*X*X0') .* cutoff(X);
    gradxPW{1} = @(X) 1i*k0(i)*X0(1) .* PW(X);
    gradxPW{2} = @(X) 1i*k0(i)*X0(2) .* PW(X);
    gradxPW{3} = @(X) 1i*k0(i)*X0(3) .* PW(X);

    % Coupling coeff for Brackage-Werner simulation
    beta = 1i*k0(i);

    % Graphical representation
    figure(1); clf;
    plot(radiat,real(PW(radiat.vtx)))
    hold on
    plot(mesh)
    plot(bound,'r')
    %     plotNrm(bound,'r')
    plot(msh(Xmes))
    axis equal
    colorbar
    title('Incident Wave')
    hold off

    % Quadrature and finite elements (volumn)
    omega = dom(mesh,3);
    U     = fem(mesh,'P1');

    % Quadrature and finite elements (boundary)
    sigma = dom(bound,3);
    u     = fem(bound,'P1');

    % Left-hand side
    tic
    [A,B,C,D] = vibsBlockOperator(omega,U,sigma,u,cL,cT,rhoS,c0,rho0,f(i));
    toc

    % Add dirichlet condition to x unknows (penalization)
    A(sub2ind(size(A),1:length(U),1:length(U))) = 1e15;

    % Right-hand side
    V    = cell(3,1);
    V{1} = - integral(sigma,ntimes(U,1),PW);
    V{2} = - integral(sigma,ntimes(U,2),PW);
    V{3} = integral(sigma,ntimes(u),gradxPW);

    % Resolution with Schur complement
    tic
    LHS    = [A B ; C D];
    RHS    = cell2mat(V);
    mu     = LHS \ RHS;
    mu     = mu(2*length(U)+1:end,:);
    lambda = beta*mu;
    toc

    % Measure of refexive and transmitted coeff
    tic
    Pmes = 1i/4 .* integral(Xmes,sigma,Gxy,u)*lambda - ...
        1i/4 .* integral(Xmes,sigma,gradyGxy,ntimes(u))*mu;
    Pmes(2) = Pmes(2) + PW(Xmes(2,:));
    toc

    % Save solution
    sol(:,i) = Pmes;

    % Finite element radiative operator --> \int_Sy G(x,y) psi(y) dy
    tic
    Srad = 1i/4 .* integral(radiat.vtx,sigma,Gxy,u);
    Srad = Srad - 1/(2*pi) .* regularize(radiat.vtx,sigma,'[log(r)]',u);

    % Finite element radiative operator --> \int_Sy dnyG(x,y) psi(y) dy
    Drad = 1i/4 .* integral(radiat.vtx,sigma,gradyGxy,ntimes(u));
    Drad = Drad - 1/(2*pi) .* regularize(radiat.vtx,sigma,'grady[log(r)]',ntimes(u));
    toc

    % Domain solution
    Psca = Srad*lambda - Drad*mu;
    Pinc = PW(radiat.vtx);
    Ptot = Psca + Pinc;

    % Graphical repesentation
    figure(10); clf;
    subplot(1,2,1)
    plot(bound)
    hold on
    plot(radiat,abs(Psca))
    plot(msh(Xmes),abs(Pmes))
    title('Scattered')
    axis equal
    colorbar
    hold off

    subplot(1,2,2)
    plot(bound)
    hold on
    plot(radiat,abs(Ptot))
    plot(msh(Xmes),abs(Pmes))
    title('Total')
    axis equal
    colorbar
    hold off
end

% Analytical solution
tic
c     = ones(length(f),1) * [c0 cL c0];
rho   = [rho0 rhoS rho0];
[R,T] = slabVibro(f,rho,c,e);
toc

% Comparison (db)
ref = 20*log10(abs([R ; T]));
sol = 20*log10(abs(sol));

norm(ref-sol)/norm(ref)

% Graphical representation
figure(100)
subplot(1,2,1)
plot(f,ref(1,:),'r',f,sol(1,:),'b+')
grid on
title('Reflexion coeffiscient')
legend({'Analytical','Numerical'})
xlabel('Frequency (Hz)')
ylabel('Amplitude (dB)')

subplot(1,2,2)
plot(f,ref(2,:),'r',f,sol(2,:),'b+')
grid on
title('Transmission coeffiscient')
legend({'Analytical','Numerical'})
xlabel('Frequency (Hz)')
ylabel('Amplitude (dB)')

disp('~~> Michto gypsilab !')


% iirfilt() -  (high|low|band)-pass filter data using an elliptic IIR filter
%              Multiple data channels and epochs are supported. Forward and
%              reverse filtering are used to avoid phase distortions.
% Usage:
%  >> [smoothdata] = iirfilt(data,srate,locutoff,hicutoff);
%  >> [smoothdata,filtwts] = iirfilt(data,srate,locutoff,hicutoff, ...
%                                    epochframes, trans_bw, revfilt,rp,rs)
% Inputs:
%   data        = (channels,frames*epochs) data to filter
%   srate       = data sampling rate (Hz)
%   locutoff    = low-edge frequency in pass band (Hz).  If 0, lowpass only.
%   hicutoff    = high-edge frequency in pass band (Hz). If 0, highpass only.
%   epochframes = frames per epoch (filter each epoch separately)
%                 {default|0: data is 1 epoch}
%   trans_bw    = width (in Hz) of transition interval between stop and
%                 pass bands {default: 1 Hz, or if pass band f < 5 Hz, f/3 Hz}.
%                 Enter 0 to use default.
%   revfilt     = [0|1] reverse filter (i.e. bandpass filter to notch
%                 or band-reject filter). {0}
%   rp          = ripple amplitude in dB in the pass band {default: 0.0025 dB,
%                 or if pass band f < 5 Hz, 0.01 dB}
%   rs          = ripple amplitude in dB in the stop band {default: 40 dB,
%                 or if pass band f < 5 Hz, 30 dB}
%   causal      = ['on'|'off'] use causal filter. Default 'off'.
%
% Note: Requires the MATLAB Signal Processing Toolbox.
%
% Authors: Maksym Pozdin (mpozdin.ece04@gtalumni.org, IOL/ONRC,2004),
%          with Arnaud Delorme and Scott Makeig (SCCN/INC/UCSD, La Jolla CA)
%
% See also: eegfilt(), eegfiltfft()

% 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

% Notes:
% Currently, with cutoff less then 5 Hz, both HPF and LPF use more 'relaxed'
% filter parameters to achieve best results.

function [smoothdata,filtwts] = iirfilt(data,srate,locutoff,hicutoff,epochframes, trans_bw, revfilt, rp, rs, causal)

if nargin<4
    fprintf('');
    help iirfilt
    return
end

data = double(data);

if exist('ellipord') ~= 2 | exist('ellip') ~= 2
   error('*** ellip() requires the Matlab Signal Processing toolbox. ***');
end

[chans frames] = size(data);
if chans > 1 & frames == 1,
    help iirfilt
    error('input data should be a row vector.');
end
nyq            = srate*0.5;  % Nyquist frequency
MINFREQ = 5;

if locutoff>0 & hicutoff > 0 & locutoff > hicutoff,
    error('locutoff > hicutoff ???');
end
if locutoff < 0 | hicutoff < 0,
   error('locutoff | hicutoff < 0 ???');
end

if locutoff>nyq,
    error('locutoff cannot be > srate/2');
end

if hicutoff>=nyq
   hicutoff = 0;
end
if nargin < 6
    trans_bw = 0;
end;

if trans_bw==0

    if locutoff < MINFREQ & locutoff > 0
        trans_bw=locutoff/3;
    elseif hicutoff < MINFREQ & hicutoff > 0
        trans_bw=hicutoff/3;
        %rp=0.01;
        %rs=30;
    else
        % Default transition bandwidth is 1 Hz
        trans_bw=1;
    end;
end

if nargin<7
   revfilt = 0;
end
if nargin<8 || isempty(rp)
   % Ripple in the passband
   rp=0.0025;
end
if nargin<9 || isempty(rs)
   % Ripple in the stopband
   rs=40;
end
if nargin<10
   causal = 'off';
end

if nargin<5
        epochframes = 0;
end
if epochframes ==0,
    epochframes = frames;    % default
end
epochs = fix(frames/epochframes);
if epochs*epochframes ~= frames,
    error('epochframes does not divide frames.\n');
end

if locutoff > 0 & hicutoff ==0 & revfilt==0              % highpass filter

    ws=(locutoff-trans_bw)/nyq;
    wp=(locutoff)/nyq;
    [N,wn] = ellipord(wp,ws,rp,rs);
    fprintf('HPF has been designed.\n');
    fprintf('HPF has cutoff of %1.1f Hz, transition bandwidth of %1.1f Hz and its order is %1.1f\n',locutoff, trans_bw,N);
    [b,a]=ellip(N,rp,rs,wn,'high');

elseif hicutoff > 0 & locutoff==0 & revfilt==0                %  lowpass filter

    ws=(hicutoff+trans_bw)/nyq;
    wp=(hicutoff)/nyq;
    [N,wn] = ellipord(wp,ws,rp,rs);
    fprintf('LPF has been designed.\n');
    fprintf('LPF has cutoff of %1.1f Hz, transition bandwidth of %1.1f Hz and its order is %1.1f\n',hicutoff, trans_bw,N);
    [b,a]=ellip(N,rp,rs,wn);

elseif hicutoff > 0 & locutoff> 0 & revfilt==0               %  bandpass filter

    %first part LPF
    ws=(hicutoff+trans_bw)/nyq;
    wp=(hicutoff)/nyq;
    [N,wn] = ellipord(wp,ws,rp,rs);
    fprintf('BPF has been designed.\n');
    fprintf('LPF has cutoff of %1.1f Hz, transition bandwidth of %1.1f Hz and its order is %1.1f\n',hicutoff, trans_bw,N);
    %[zl, pl, kl]=ellip(N,rp,rs,wn);
    %[lpf_sos,lpf_g] = zp2sos(zl,pl, kl);
    [bl,al]=ellip(N,rp,rs,wn);

    %second part HPF
    ws=(locutoff-trans_bw)/nyq;
    wp=(locutoff)/nyq;
    [N,wn] = ellipord(wp,ws,rp,rs);
    fprintf('HPF has cutoff of %1.1f Hz, transition bandwidth of %1.1f Hz and its order is %1.1f\n',locutoff, trans_bw,N);
    %[zh, ph, kh]=ellip(N,rp,rs,wn);
    %[hpf_sos,hpf_g] = zp2sos(zh,ph, kh);
    [bh,ah]=ellip(N,rp,rs,wn,'high');
    %help fvtool
    %b=conv(bh,bl);a=conv(ah,al);
    b.bl=bl;b.bh=bh; a.al=al;a.ah=ah;

elseif hicutoff > 0 & locutoff> 0 & revfilt==1               %  bandreject filter

    %first part LPF
    ws=(locutoff+trans_bw)/nyq;
    wp=(locutoff)/nyq;
    [N,wn] = ellipord(wp,ws,rp,rs);
    fprintf('BRF has been designed.\n');
    fprintf('LPF has cutoff of %1.1f Hz, transition bandwidth of %1.1f Hz and its order is %1.1f\n',locutoff, trans_bw,N);
    [bl,al]=ellip(N,rp,rs,wn);

    %second part HPF
    ws=(hicutoff-trans_bw)/nyq;
    wp=(hicutoff)/nyq;
    [N,wn] = ellipord(wp,ws,rp,rs);
    fprintf('HPF has cutoff of %1.1f Hz, transition bandwidth of %1.1f Hz and its order is %1.1f\n',hicutoff, trans_bw,N);
    [bh,ah]=ellip(N,rp,rs,wn,'high');
    b.bl=bl;b.bh=bh; a.al=al;a.ah=ah;

else
    error('You must provide a non-0 low or high cut-off frequency');
end

smoothdata = zeros(chans,frames);
for e = 1:epochs                % filter each epoch, channel
    for c=1:chans
        if isstruct(a) & isstruct(b) & revfilt==0            %BPF - filter with LPF and HPF in series

            if strcmpi(causal, 'on')
                smoothdata1(c,(e-1)*epochframes+1:e*epochframes) = filter(b.bl,a.al,data(c,(e-1)*epochframes+1:e*epochframes));
                smoothdata( c,(e-1)*epochframes+1:e*epochframes) = filter(b.bh,a.ah,smoothdata1(c,(e-1)*epochframes+1:e*epochframes));
            else
                smoothdata1(c,(e-1)*epochframes+1:e*epochframes) = filtfilt(b.bl,a.al,data(c,(e-1)*epochframes+1:e*epochframes));
                smoothdata( c,(e-1)*epochframes+1:e*epochframes) = filtfilt(b.bh,a.ah,smoothdata1(c,(e-1)*epochframes+1:e*epochframes));
            end;

        elseif isstruct(a) & isstruct(b) & revfilt==1         %BRF - filter with LPF and HPF in parallel
            if strcmpi(causal, 'on')
                smoothdata1(c,(e-1)*epochframes+1:e*epochframes) = filter(b.bl,a.al,data(c,(e-1)*epochframes+1:e*epochframes));
                smoothdata2(c,(e-1)*epochframes+1:e*epochframes) = filter(b.bh,a.ah,data(c,(e-1)*epochframes+1:e*epochframes));
            else
                smoothdata1(c,(e-1)*epochframes+1:e*epochframes) = filtfilt(b.bl,a.al,data(c,(e-1)*epochframes+1:e*epochframes));
                smoothdata2(c,(e-1)*epochframes+1:e*epochframes) = filtfilt(b.bh,a.ah,data(c,(e-1)*epochframes+1:e*epochframes));
            end;
            smoothdata=smoothdata1+smoothdata2;               %combine final results
        else
            if strcmpi(causal, 'on')
                smoothdata(c,(e-1)*epochframes+1:e*epochframes) = filter(b,a,data(c,(e-1)*epochframes+1:e*epochframes));
            else
                smoothdata(c,(e-1)*epochframes+1:e*epochframes) = filtfilt(b,a,data(c,(e-1)*epochframes+1:e*epochframes));
            end;
        end;
        if epochs == 1
            if rem(c,20) ~= 0
                fprintf('.');
            else
                fprintf('%d',c);
            end
        end
    end
end
fprintf('\n');

%% To test my filter: draws Frequency response
% N=10001; n=1:N;
% xx=zeros(size(n));
% xx(ceil(length(xx)/2))=1;
% if isstruct(a) & isstruct(b)
%     yy1=filtfilt(b.bl,a.al,xx);
%     yy=filtfilt(b.bh, a.ah,yy1);
% else
%     yy=filtfilt(b,a,xx);
% end;
% YY=fft(yy,100000);
% ff=-nyq:2*nyq/length(YY):nyq-2*nyq/length(YY);
% figure;plot(ff,abs(fftshift(YY)));grid on;title('Frequency response');


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%              Launch code for static input (sample)               %
%      code by Fabrizio Conso, university of pavia, student        %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                launch code example                    %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                       %
 format short;
 f_s=1;            % normalized sampling frequency
 f_bw=5;                    % DAC's bandwidth
 sr=2;                      % DAC's slew-rate
 nbit=12;                   % converter bits
 input=0.7;                 % sample value

 [counter,tresholds]  =Approx(input,nbit,f_bw,sr,f_s)
 [counter2,tresholds2]=Approx_2(input,nbit,f_bw,sr,f_s)
 bitstream=dec2bin(counter)
 bitstream2=dec2bin(counter2)
%                                                       %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


function  bdiff_bdepth(mycat)
    %  This routine etsimates the b-value of a curve automatically
    %  The b-valkue curve is differenciated and the point
    %  of maximum curvature marked. The b-value will be calculated
    %  using this point and the point half way toward the high
    %  magnitude end of the b-value curve.

    %  originally, "mycat" was "newcat"
    %  Stefan Wiemer 1/95
    %
    global cluscat mess bfig backcat magsteps_desc bvalsum3  bval aw bw t1 t2 t3 t4 dloop leg1 leg2
    global teb t0b cua  ew onesigma mrt bvalsumhold
    global gBdiff % contains b1, n1, b2, n2
    global mxlkbt lsbt ni
    ZG=ZmapGlobal.Data;

    report_this_filefun();

    bfig=findobj('Type','Figure','-and','Name','frequency-magnitude distribution');
    if ~isempty(bfig)
        if dloop == 2
            ZG.hold_state=true;
        end
    else
        bfig=figure_w_normalized_uicontrolunits(...                  %build figure for plot
            'Units','normalized','NumberTitle','off',...
            'Name','frequency-magnitude distribution',...
            'visible','off',...
            'pos',[ 0.300  0.3 0.4 0.6]);
        ZG.hold_state=false;

        uicontrol('Units','normal',...
            'Position',[.0 .85 .08 .06],'String','Info ',...
            'callback',@(~,~)infoz(1));
        uicontrol('Units','normal',...
            'Position',[.0 .45 .10 .06],'String','Manual ',...
            'callback',@(~,~)bfitnew(mycat));

        uicontrol('Units','normal',...
            'Position',[.0 .35 .10 .06],'String','RecTime ',...
            'callback',@callbackfun_003);

        uicontrol('Units','normal',...
            'Position',[.0 .25 .10 .06],'String','TimePlot ',...
            'callback',@cb_timeplot);

        uicontrol('Units','normal',...
            'Position',[.0 .65 .08 .06],'String','Save ',...
            'Callback',{@calSave9,magsteps_desc, bvalsum3});
    end

    maxmag = ceil(10*max(mycat.Magnitude))/10;
    mima = min(mycat.Magnitude);
    mima = min(mima, 0);

    % number of mag units
    nmagu = (maxmag*10)+1;

    [bval,xt2] = hist(mycat.Magnitude,(mima:0.1:maxmag));
    bvalsum = cumsum(bval); % N for M <=
    bval2 = bval(end:-1:1);
    bvalsum3 = cumsum(bval(end:-1:1));    % N for M >= (counted backwards)
    magsteps_desc = (maxmag:-0.1:mima);

    backg_ab = log10(bvalsum3);
    orient tall

    if ZG.hold_state
        axes(cua)
        disp("set(gca,'NextPlot','add')")
        set(gca,'NextPlot','add')
    else
        figure(bfig);delete(findobj(bfig,'Type','axes'));
        rect = [0.2,  0.3, 0.70, 0.6];           % plot Freq-Mag curves
        axes('position',rect);
    end

    pldepth =semilogy(magsteps_desc,bvalsum3,'sb');
    set(pldepth,'LineWidth',1.0,'MarkerSize',6,...
        'MarkerFaceColor','r','MarkerEdgeColor','b');
    set(gca,'NextPlot','add')
    difb = [0 diff(bvalsum3) ];

    % Marks the point of maximum curvature
    %
    i = find(difb == max(difb));
    i = max(i);
    te = semilogy(magsteps_desc(i),bvalsum3(i),'xk');
    set(te,'LineWidth',1.5,'MarkerSize',ms10)

    % Estimate the b-value
    %
    i2 = 1 ;
    te = semilogy(magsteps_desc(i2),difb(i2),'xk');
    set(te,'LineWidth',1.5,'MarkerSize',ms10)
    te = semilogy(magsteps_desc(i2),bvalsum3(i2),'xk');
    set(te,'LineWidth',1.5,'MarkerSize',ms10)

    xlabel('Magnitude','FontWeight','normal','FontSize',ZmapGlobal.Data.fontsz.s)
    ylabel('Cumulative Number','FontWeight','normal','FontSize',ZmapGlobal.Data.fontsz.s)
    %set(gca,'Color',color_bg)
    set(gca,'visible','on','FontSize',ZmapGlobal.Data.fontsz.s,'FontWeight','normal',...
        'FontWeight','normal','LineWidth',1.0,...
        'Box','on','Tag','cufi')

    cua = gca;

    M1b = [];
    M1b = [magsteps_desc(i) bvalsum3(i)];
    tt3=num2str(fix(100*M1b(1))/100);

    M2b = [];
    M2b =  [magsteps_desc(i2) bvalsum3(i2)];
    tt4=num2str(fix(100*M2b(1))/100);

    ll = magsteps_desc >= M1b(1)-0.05  & magsteps_desc <= M2b(1) +0.05;
    x = magsteps_desc(ll);

    l2 = mycat.Magnitude >= M1b(1)- 0.05  & mycat.Magnitude <= M2b(1)+ 0.05;
    [ bv, onesigma, av] = calc_bmemag(mycat.Magnitude(l2), 0.1) ;

    bv = -bv;

    pause(0.1)

    y = backg_ab(ll);
    [aw bw,  S, ew] = wls(x',y');
    p = [bw aw];
    %[p,S] = polyfit(x,y,1)                    % fit a line to background
    p2 = [bw+onesigma aw];
    p3 = [bw-onesigma aw];
    x2 = 1:0.1:6;
    f = polyval(p,x);
    f2 = polyval(p2,x);
    f3 = polyval(p3,x);
    [f4,delta] = polyval(p,x,S);
    Tr  = (teb-t0b)/(10.^ polyval(p,mrt));
    fprintf('Recurrence time Tr(M%g) = %g years\n', mrt, Tr);
    f = 10.^f;
    f2 = 10.^f2;
    f3 = 10.^f3;
    f4 = 10.^f4;
    delta = 10.^delta;
    set(gca,'NextPlot','add')
    ttm= semilogy(x,f,'r');                         % plot linear fit to backg
    set(ttm,'LineWidth',1)
    ttm= semilogy(x,f2,'k');                         % plot linear fit to backg
    set(ttm,'LineWidth',1)
    ttm= semilogy(x,f3,'k');                         % plot linear fit to backg
    set(ttm,'LineWidth',1)
    ttm= semilogy(x,f4-delta,'k-.');                         % plot linear fit to backg
    set(ttm,'LineWidth',1)
    ttm= semilogy(x,f4+delta,'k-.');
    set(ttm,'LineWidth',1)
    set(gca,'XLim',[min(mycat.Magnitude)-0.5  max(mycat.Magnitude)+0.5])
    set(gca,'YLim',[1 (mycat.Count+20)*1.4]);

    r = corrcoef(x,y);
    r = r(1,2);
    %std_backg = std(y - polyval(p,x));      % standard deviation of fit
    std_backg = ew;      % standard deviation of fit

    p=-p(1,1);
    p=fix(100*p)/100;
    std_backg=fix(100*std_backg)/100;
    tt1=num2str(bw,3);
    tt2=num2str(std_backg);
    tt4=num2str(bv,3);
    tt5=num2str(onesigma,2);

    rect=[0 0 1 1];
    h2=axes('position',rect);
    set(h2,'visible','off');

    %if ZG.hold_state
    ge_symbol = char(8805);
    if dloop == 2
        set(pldepth,'LineWidth',1.0,'MarkerSize',6,...
            'MarkerFaceColor','y','MarkerEdgeColor','g','Marker','o');
        set(cua,'Ylim',[ 1   ni ] );

        txt1=text(.10, .08,['Bottom Zone b-value (w LS, M  ', ge_symbol, ' ', num2str(M1b(1)) '): ',tt1, ' +/- ', tt2 ',a-value = ' , num2str(aw) ]);
        set(txt1,'FontWeight','normal','FontSize',ZmapGlobal.Data.fontsz.s,'Color','r')
        txt1=text(.10, .04,['Bottom Zone b-value (max lik, M ', ge_symbol, ' ', num2str(min(mycat.Magnitude)) '): ',tt4, ' +/- ', tt5,',a-value = ' , num2str(av)]);
        set(txt1,'FontWeight','normal','FontSize',ZmapGlobal.Data.fontsz.s, 'Color', 'r')
        lsbb = bw; mxlkbb = bv;

        lsb = lsbt/lsbb; mxlkb = mxlkbt/mxlkbb;
        slsb = num2str(lsb);
        smxlkb = num2str(mxlkb);
        txt3 = text(.25, .94,['LS b ratio = ', slsb,'           max lik b ratio = ',smxlkb]);
        set(txt3,'FontWeight','normal','FontSize',ZmapGlobal.Data.fontsz.s,'Color','b')
        %  leg(2)=pldepth
    else
        txt1=text(.10, .18,['Top Zone b-value (w LS, M  ', ge_symbol, ' ', num2str(M1b(1)) '): ',tt1, ' +/- ', tt2, ',a-value = ' , num2str(aw) ]);
        set(txt1,'FontWeight','normal','FontSize',ZmapGlobal.Data.fontsz.s)
        txt1=text(.10, .14,['Top Zone b-value (max lik, M ', ge_symbol, ' ', num2str(min(mycat.Magnitude)) '): ',tt4, ' +/- ', tt5,',a-value = ' , num2str(av)]);
        set(txt1,'FontWeight','normal','FontSize',ZmapGlobal.Data.fontsz.s)
        set(gcf,'PaperPosition',[0.5 0.5 4.0 5.5])
        lsbt = bw; mxlkbt = bv;
    end

    if dloop == 1
        leg1 = pldepth;
    end
    if dloop == 2
        leg2 = pldepth;
        legend([leg1,leg2],'Top depth zone','Bottom depth zone');
    end
    set(gcf,'visible','on');

    if ZG.hold_state
        % calculate the probability that the two distributions are different
        l = mycat.Magnitude >=  M1b(1);
        gBdiff.b2 = str2double(tt1); gBdiff.n2 = M1b(2);
        n = gBdiff.n1+gBdiff.n2;
        da = -2*n*log(n) + 2*gBdiff.n1*log(gBdiff.n1+gBdiff.n2*gBdiff.b1/gBdiff.b2) + 2*gBdiff.n2*log(gBdiff.n1*gBdiff.b2/gBdiff.b1+gBdiff.n2) -2;
        pr = exp(-da/2-2);
        fprintf('Probability: %g\n', pr);
        txt1=text(.60, .75,['p=  ', num2str(pr,2)],'Units','normalized');
        set(txt1,'FontWeight','normal','FontSize',ZmapGlobal.Data.fontsz.s)
        txt1=text(.60, .70, sprintf('gBdiff.n1: %g, gBdiff.n2: %g, gBdiff.b1: %g, gBdiff.b2: %g', ...
            gBdiff.n1, gBdiff.n2, gBdiff.b1, gBdiff.b2));
        set(txt1,'FontSize',8,'Units','normalized')
    else
        gBdiff.b1 = str2double(tt1); gBdiff.n1 = M1b(2);
    end

    bvalsumhold = bvalsum3;
    da = 10^(aw+bw*6.5);
    db = 10^(aw+bw*6.5)*(-6.5);
    dp = sqrt(da^2*ew^2+db^2*0.05^2);
    dr = 1/dp;

    set(gca,'NextPlot','replace');

    function callbackfun_003(mysrc,myevt)

        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        est_recurrence_time_prob(mhcat, onesigma, aw, bw);
    end

    function cb_timeplot(mysrc,myevt)
        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        ZG=ZmapGlobal.Data;
        ZG.newt2 = mycat;
        ctp=CumTimePlot(mycat);
        ctp.plot();
    end
end


function gd=ref_tgabdual(ttype,g,L,a,M)
%REF_WIN   Compute appropriate dual window for transform
%

if nargin<5
  error('Too few input parameters.');
end;

info=ref_transforminfo(ttype,L,a,M);

gd=info.winscale*gabdual(g,info.a,info.M);


function blas1_d_test05 ( )

%*****************************************************************************80
%
%% TEST05 demonstrates DMACH.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 May 2006
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST05\n' );
  fprintf ( 1, '  DMACH returns some approximate machine numbers.\n' );
  fprintf ( 1, '\n' );
  job = 1;
  fprintf ( 1, '  DMACH(1) = EPS =  %e\n', dmach ( job ) );
  job = 2;
  fprintf ( 1, '  DMACH(2) = TINY = %e\n', dmach ( job ) );
  job = 3;
  fprintf ( 1, '  DMACH(3) = HUGE = %e\n', dmach ( job ) );

  return
end


function f = dejongsfcn(x)

if strcmpi(x,'init')
    f.Vectorized = 'on' ;
    f.PopInitRange = [-5; 5] ;
    f.KnownMin = [0 0] ; % For plotting only
else
    f = sum(x.*x,2) ;
end


function [M,Q]=community_louvain(W,gamma,M0,B)
%COMMUNITY_LOUVAIN     Optimal community structure
%
%   M     = community_louvain(W);
%   [M,Q] = community_louvain(W,gamma);
%   [M,Q] = community_louvain(W,gamma,M0);
%   [M,Q] = community_louvain(W,gamma,M0,'potts');
%   [M,Q] = community_louvain(W,gamma,M0,'negative_asym');
%   [M,Q] = community_louvain(W,[],[],B);
%
%   The optimal community structure is a subdivision of the network into
%   nonoverlapping groups of nodes which maximizes the number of within-
%	group edges, and minimizes the number of between-group edges.
%
%   This function is a fast and accurate multi-iterative generalization of
%   the Louvain community detection algorithm. This function subsumes and
%   improves upon,
%		modularity_louvain_und.m, modularity_finetune_und.m,
%		modularity_louvain_dir.m, modularity_finetune_dir.m,
%       modularity_louvain_und_sign.m
%	and additionally allows to optimize other objective functions (includes
%	built-in Potts-model Hamiltonian, allows for custom objective-function
%	matrices).
%
%   Inputs:
%       W,
%           directed/undirected weighted/binary connection matrix with
%           positive and possibly negative weights.
%       gamma,
%           resolution parameter (optional)
%               gamma>1,        detects smaller modules
%               0<=gamma<1,     detects larger modules
%               gamma=1,        classic modularity (default)
%       M0,
%           initial community affiliation vector (optional)
%       B,
%           objective-function type or custom objective matrix (optional)
%           'modularity',       modularity (default)
%           'potts',            Potts-model Hamiltonian (for binary networks)
%           'negative_sym',     symmetric treatment of negative weights
%           'negative_asym',    asymmetric treatment of negative weights
%           B,                  custom objective-function matrix
%
%           Note: see Rubinov and Sporns (2011) for a discussion of
%           symmetric vs. asymmetric treatment of negative weights.
%
%   Outputs:
%       M,
%           community affiliation vector
%       Q,
%           optimized community-structure statistic (modularity by default)
%
%   Example:
%       % Iterative community finetuning.
%       % W is the input connection matrix.
%       n  = size(W,1);             % number of nodes
%       M  = 1:n;                   % initial community affiliations
%       Q0 = -1; Q1 = 0;            % initialize modularity values
%       while Q1-Q0>1e-5;           % while modularity increases
%           Q0 = Q1;                % perform community detection
%           [M, Q1] = community_louvain(W, [], M);
%       end
%
%   References:
%       Blondel et al. (2008)  J. Stat. Mech. P10008.
%       Reichardt and Bornholdt (2006) Phys. Rev. E 74, 016110.
%       Ronhovde and Nussinov (2008) Phys. Rev. E 80, 016109
%       Sun et al. (2008) Europhysics Lett 86, 28004.
%       Rubinov and Sporns (2011) Neuroimage 56:2068-79.
%
%   Mika Rubinov, U Cambridge 2015-2016

%   Modification history
%   2015: Original
%   2016: Included generalization for negative weights.
%         Enforced binary network input for Potts-model Hamiltonian.
%         Streamlined code and expanded documentation.

W=double(W);                                % convert to double format
n=length(W);                                % get number of nodes
s=sum(sum(W));                              % get sum of edges

if ~exist('B','var') || isempty(B)
    type_B = 'modularity';
elseif ischar(B)
    type_B = B;
else
    type_B = 0;
    if exist('gamma','var') && ~isempty(gamma)
        warning('Value of gamma is ignored in generalized mode.')
    end
end
if ~exist('gamma','var') || isempty(gamma)
    gamma = 1;
end

if strcmp(type_B,'negative_sym') || strcmp(type_B,'negative_asym')
    W0 = W.*(W>0);                          %positive weights matrix
    s0 = sum(sum(W0));                      %weight of positive links
    B0 = W0-gamma*(sum(W0,2)*sum(W0,1))/s0; %positive modularity

    W1 =-W.*(W<0);                          %negative weights matrix
    s1 = sum(sum(W1));                      %weight of negative links
    if s1                                   %negative modularity
        B1 = W1-gamma*(sum(W1,2)*sum(W1,1))/s1;
    else
        B1 = 0;
    end
elseif min(min(W))<-1e-10
    err_string = [
        'The input connection matrix contains negative weights.\nSpecify ' ...
        '''negative_sym'' or ''negative_asym'' objective-function types.'];
    error(sprintf(err_string))              %#ok<SPERR>
end
if strcmp(type_B,'potts') && any(any(W ~= logical(W)))
    error('Potts-model Hamiltonian requires a binary W.')
end

if type_B
    switch type_B
        case 'modularity';      B = (W-gamma*(sum(W,2)*sum(W,1))/s)/s;
        case 'potts';           B =  W-gamma*(~W);
        case 'negative_sym';    B = B0/(s0+s1) - B1/(s0+s1);
        case 'negative_asym';   B = B0/s0      - B1/(s0+s1);
        otherwise;              error('Unknown objective function.');
    end
else                            % custom objective function matrix as input
    B = double(B);
    if ~isequal(size(W),size(B))
        error('W and B must have the same size.')
    end
end
if ~exist('M0','var') || isempty(M0)
    M0=1:n;
elseif numel(M0)~=n
    error('M0 must contain n elements.')
end

[~,~,Mb] = unique(M0);
M = Mb;

B = (B+B.')/2;                                          % symmetrize modularity matrix
Hnm=zeros(n,n);                                         % node-to-module degree
for m=1:max(Mb)                                         % loop over modules
    Hnm(:,m)=sum(B(:,Mb==m),2);
end

Q0 = -inf;
Q = sum(B(bsxfun(@eq,M0,M0.')));                        % compute modularity
first_iteration = true;
while Q-Q0>1e-10
    flag = true;                                        % flag for within-hierarchy search
    while flag;
        flag = false;
        for u=randperm(n)                               % loop over all nodes in random order
            ma = Mb(u);                                 % current module of u
            dQ = Hnm(u,:) - Hnm(u,ma) + B(u,u);
            dQ(ma) = 0;                                 % (line above) algorithm condition

            [max_dQ,mb] = max(dQ);                      % maximal increase in modularity and corresponding module
            if max_dQ>1e-10;                            % if maximal increase is positive
                flag = true;
                Mb(u) = mb;                             % reassign module

                Hnm(:,mb) = Hnm(:,mb)+B(:,u);           % change node-to-module strengths
                Hnm(:,ma) = Hnm(:,ma)-B(:,u);
            end
        end
    end
    [~,~,Mb] = unique(Mb);                              % new module assignments

    M0 = M;
    if first_iteration
        M=Mb;
        first_iteration=false;
    else
        for u=1:n                                       % loop through initial module assignments
            M(M0==u)=Mb(u);                             % assign new modules
        end
    end

    n=max(Mb);                                          % new number of modules
    B1=zeros(n);                                        % new weighted matrix
    for u=1:n
        for v=u:n
            bm=sum(sum(B(Mb==u,Mb==v)));                % pool weights of nodes in same module
            B1(u,v)=bm;
            B1(v,u)=bm;
        end
    end
    B=B1;

    Mb=1:n;                                             % initial module assignments
    Hnm=B;                                              % node-to-module strength

    Q0=Q;
    Q=trace(B);                                         % compute modularity
end


function ori = byAxisAngle(axis,angle,varargin)
% define orientations by rotational axis and rotational angle
%
% Syntax
%   ori = orientation.byAxisAngle(v,omega,CS) % an orientation
%   ori = orientation.byAxisAngle(h,omega) % a misorientation
%
% Input
%  v     - rotational axis @vector3d
%  m     - rotational axis @Miller
%  omega - rotation angle
%  CS    - @crystalSymmetry
%
% Output
%  ori - @orientation
%
% See also
% orientation/orientation orientation/byEuler orientation/byMatrix orientation/map

% TODO: better implementation required, call byAxisAngle@rotattion

ori = orientation(axis2quat(axis,angle),varargin{:});

% copy crystal symmetry if possible
if isa(axis,'Miller'), ori.CS = axis.CS; ori.SS = axis.CS; end


function f=comp_iwpfbt(c,wtNodes,pOutIdxs,chOutIdxs,Ls,ext,interscaling)
%COMP_IWFBT Compute Inverse Wavelet Packet Filter-Bank Tree
%   Usage:  f=comp_iwpfbt(c,wtNodes,pOutIdxs,chOutIdxs,Ls,ext)
%
%   Input parameters:
%         c          : Coefficients stored in cell array.
%         wtNodes    : Filterbank tree nodes (elementary filterbans) in
%                      reverse BF order. Cell array of structures of length *nodeNo*.
%         pOutIdxs   : Idx of each node's parent. Array of length *nodeNo*.
%         chOutIdxs  : Idxs of each node children. Cell array of vectors of
%                      length *nodeNo*.
%         ext        : Type of the forward transform boundary handling.
%
%   Output parameters:
%         f          : Reconstructed data in L*W array.
%

% Do non-expansve transform if ext=='per'
doPer = strcmp(ext,'per');

interscalingfac = 1;
if strcmp('intscale',interscaling)
    interscalingfac = 1/2;
elseif strcmp('intsqrt',interscaling)
    interscalingfac = 1/sqrt(2);
end

% For each node in tree in the BF order...
 for jj=1:length(wtNodes)
    % Node filters to a cell array
    %gCell = cellfun(@(gEl)conj(flipud(gEl.h(:))),wtNodes{jj}.g(:),'UniformOutput',0);
    gCell = cellfun(@(gEl)gEl.h(:),wtNodes{jj}.g(:),'UniformOutput',0);
    % Node filters subs. factors
    a = wtNodes{jj}.a;
    % Node filters initial skips
    if(doPer)
       %offset = cellfun(@(gEl) 1-numel(gEl.h)-gEl.offset,wtNodes{jj}.g);
       offset = cellfun(@(gEl) gEl.offset,wtNodes{jj}.g);
    else
       offset = -(a-1);
    end

    if(pOutIdxs(jj))
       % Run filterbank and add to the existing subband.
       ctmp = comp_ifilterbank_td(c(chOutIdxs{jj}),gCell,a,size(c{pOutIdxs(jj)},1),offset,ext);
       c{pOutIdxs(jj)} = c{pOutIdxs(jj)}+ctmp;

       c{pOutIdxs(jj)} = interscalingfac*c{pOutIdxs(jj)};

    else
       % We are at the root.
       f = comp_ifilterbank_td(c(chOutIdxs{jj}),gCell,a,Ls,offset,ext);
    end
 end


function Vdata = voltageCurve(Tdata,x,Res,ThVal,ThBeta)
%% Calculate Voltage Curve given Indices (x)
% Copyright (c) 2012, MathWorks, Inc.
%% Index into Resistor and Thermistor arrays to extract component values
y(1) = Res(x(1));
y(2) = Res(x(2));
y(3) = Res(x(3));
y(4) = Res(x(4));
y(5) = ThVal(x(5));
y(6) = ThBeta(x(5));
y(7) = ThVal(x(6));
y(8) = ThBeta(x(6));

%% Calculate temperature curve for a particular set of components
Vdata = tempCompCurve(y, Tdata);


function circle_integrals_test ( )

%*****************************************************************************80
%
%% CIRCLE_INTEGRALS_TEST tests the CIRCLE_INTEGRALS library.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 January 2014
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'CIRCLE_INTEGRALS_TEST\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Test the CIRCLE_INTEGRALS library.\n' );

  circle_integrals_test01 ( );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'CIRCLE_INTEGRALS_TEST\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end


function dat = index_loss(algo,dat)

  [x y]=get_xy(dat);
  res = sum((x-y).^2,2);
  lss = length(find(res > 0))/max(size(res));

  dat=data([get_name(dat) ' -> index_loss=' num2str(lss,4) ],[],lss);


%% (Internal) Replace NaN from PRdatasets
%
%   dsOut = deNaN_dataset(dsIn, type)
%
% Arguments:
%
%      + dsIn: paths to add
%
%      + type: Choose the type of replacement:
%
%             - 'remove', remove the whole vector which includes NaN
%
%             - 'change', change NaNs for repeated values of the same
%             feature, added an small variance, estimated ignoring this nan
%             values.
%
%             - 'change_same_class' change NaNs for repeated values of the
%             same feature, same class, added an small variance, estimated
%             ignoring this nan values.
%
%      + func_ptr: A pointer to an isX function. Default @isnan
%
% Output:
%
%      + dsOut: the clean PRdataset
%
% Example:
%
% Author: Mariano Llamedo Soria llamedom@electron.frba.utn.edu.ar
% Version: 0.1 beta
% Last update: 14/5/2014
% Birthdate  : 21/4/2015
% Copyright 2008-2015
%
function dsOut = deNaN_dataset(dsIn, type, func_ptr)

    if( nargin < 2 || isempty(type) )
        type = 'remove';
    end

    if( nargin < 3 || isempty(func_ptr) )
        func_ptr = @isnan;
    end

    features_with_nans = find(any(func_ptr(+dsIn)));
    rows_without_nans = ~any(func_ptr(+dsIn),2);

    if( any(~rows_without_nans) )

        rows_without_nans_idx = find(rows_without_nans);

        switch(type)

            case 'remove'
                % just remove nans

                dsOut = dsIn(rows_without_nans_idx,:);

            case 'change'

                % change NaNs for repeated values of the same feature, added an small variance, estimated ignoring this nan
                % values.
                dsOut = dsIn;

                robust_std = nanmeda(+dsIn(rows_without_nans_idx,:));

                for kk = rowvec(features_with_nans)

                    nan_idx = find(func_ptr(+(dsIn(:,kk))));
                    not_nan_idx = find(~func_ptr(+(dsIn(:,kk))));
                    laux_idx = length(nan_idx);

                    dsIn(nan_idx,kk) = randsample( +dsIn(not_nan_idx,kk), laux_idx, true ) + 1/100*robust_std(kk)*rand(laux_idx,1);

                    dsOut(:,kk) = dsIn(:,kk);

                end

            case 'change_same_class'

                % change NaNs for repeated values of the same feature, same
                % class, added an small variance, estimated ignoring this nan
                % values.
                dsOut = dsIn;

                dsIn = seldat(dsIn);

                ds_aux = dsIn(rows_without_nans_idx,:);
                ds_aux = setprior(ds_aux, 0);

                w_aux = qdc(ds_aux);
                w_aux = +w_aux;
                Class_indexes = getnlab(dsIn);

                for kk = rowvec(features_with_nans)
                    nan_idx = find(func_ptr(+(dsIn(:,kk))));

                    classes_involved = unique(Class_indexes(nan_idx));

                    for ll = rowvec(classes_involved)

                        aux_idx = find(Class_indexes(nan_idx) == ll);
                        this_class_not_nan_idx = find(Class_indexes == ll);
                        this_class_not_nan_idx = setdiff(this_class_not_nan_idx, nan_idx(aux_idx) );

                        laux_idx = length(aux_idx);

                        dsIn(nan_idx(aux_idx),kk) = randsample( +dsIn(this_class_not_nan_idx,kk), laux_idx, true ) + 1/100*w_aux.cov(kk,kk,ll)*rand(laux_idx,1);

                    end

                    dsOut(:,kk) = dsIn(:,kk);

                end

        end
    else

        dsOut = dsIn;

    end


function test_bug2560

% MEM 2gb
% WALLTIME 00:15:00
% DEPENDENCY ft_sourceplot ft_plot_slice

% this function is meant to test the correctness of the 'ortho' method in
% sourceplot. It relies on ft_plot_ortho and ft_plot_slice. there may be a
% slight problem in dealing with the functional data/mask

% investigate the issue by creating some data
[x,y,z] = ndgrid(1:7,1:8,1:9);
inside  = zeros(7,8,9);
inside(2:6,2:7,2:8) = 1;
outside = find(inside==0);
inside  = find(inside==1);

source = [];
source.pos = [x(:) y(:) z(:)]; clear x y z
source.dim = [7 8 9];
source.inside  = inside;
source.outside = outside;
source.avg.pow = zeros(7,8,9);
source.avg.pow(inside) = 1;

cfg = [];
cfg.funparameter = 'avg.pow';
cfg.method       = 'ortho';
cfg.funcolormap  = 'jet';
ft_sourceplot(cfg, source);

% the code above confirms an the hunch I had: the inside mask is shifted
% relative to the functional data


function net = init_resnet_toyDigitV2(varargin)
%CNN_IMAGENET_INIT_RESNET  Initialize the ResNet-50 model for ImageNet classification

opts.classNames = {} ;
opts.classDescriptions = {} ;
opts.averageImage = zeros(3,1) ;
opts.colorDeviation = zeros(3) ;
opts.cudnnWorkspaceLimit = 1024*1024*1204 ; % 1GB
opts = vl_argparse(opts, varargin) ;

net = dagnn.DagNN() ;

lastAdded.var = 'input' ;
lastAdded.depth = 3 ;

    function Conv(name, ksize, depth, varargin)
        % Helper function to add a Convolutional + BatchNorm + ReLU
        % sequence to the network.
        args.relu = true ;
        args.downsample = false ;
        args.bias = false ;
        args = vl_argparse(args, varargin) ;
        if args.downsample, stride = 2 ; else stride = 1 ; end
        if args.bias, pars = {[name '_f'], [name '_b']} ; else pars = {[name '_f']} ; end
        net.addLayer([name  '_conv'], ...
            dagnn.Conv('size', [ksize ksize lastAdded.depth depth], ...
            'stride', stride, ....
            'pad', (ksize - 1) / 2, ...
            'hasBias', args.bias, ...
            'opts', {'cudnnworkspacelimit', opts.cudnnWorkspaceLimit}), ...
            lastAdded.var, ...
            [name '_conv'], ...
            pars) ;
        net.addLayer([name '_bn'], ...
            dagnn.BatchNorm('numChannels', depth, 'epsilon', 1e-5), ...
            [name '_conv'], ...
            [name '_bn'], ...
            {[name '_bn_w'], [name '_bn_b'], [name '_bn_m']}) ;
        lastAdded.depth = depth ;
        lastAdded.var = [name '_bn'] ;
        if args.relu
            net.addLayer([name '_relu'] , ...
                dagnn.ReLU(), ...
                lastAdded.var, ...
                [name '_relu']) ;
            lastAdded.var = [name '_relu'] ;
        end
    end

% -------------------------------------------------------------------------
% Add input section
% -------------------------------------------------------------------------

Conv('conv1', 3, 32, ...
    'relu', true, ...
    'bias', false, ...
    'downsample', 0) ;

% net.addLayer(...
%   'conv1_pool' , ...
%   dagnn.Pooling('poolSize', [3 3], ...
%                 'stride', 2, ...
%                 'pad', 1,  ...
%                 'method', 'max'), ...
%   lastAdded.var, ...
%   'conv1') ;
lastAdded.var = 'conv1_relu' ;

% -------------------------------------------------------------------------
% Add intermediate sections
% -------------------------------------------------------------------------

for s = 2:5

    switch s
        case 2, sectionLen = 3 ;
        case 3, sectionLen = 3 ; % 4 8 ;
        case 4, sectionLen = 3 ; % 6 23 ; % 36 ;
        case 5, sectionLen = 3 ;
    end

    % -----------------------------------------------------------------------
    % Add intermediate segments for each section
    for l = 1:sectionLen
        depth = 2^(s+2) ;
        sectionInput = lastAdded ;
        name = sprintf('conv%d_%d', s, l)  ;

        % Optional adapter layer
        if l == 1
%             Conv([name '_adapt_conv'], 1, 2^(s+6), 'downsample', s >= 3, 'relu', false) ;
            Conv([name '_adapt_conv'], 1, 2^(s+4), 'downsample', 0, 'relu', false) ;
        end
        sumInput = lastAdded ;

        % ABC: 1x1, 3x3, 1x1; downsample if first segment in section from
        % section 2 onwards.
        lastAdded = sectionInput ;
        %Conv([name 'a'], 1, 2^(s+4), 'downsample', (s >= 3) & l == 1) ;
        %Conv([name 'b'], 3, 2^(s+4)) ;
        Conv([name 'a'], 1, 2^(s+2)) ;
%         Conv([name 'b'], 3, 2^(s+4), 'downsample', (s >= 3) & l == 1) ;
        Conv([name 'b'], 3, 2^(s+2), 'downsample', 0 ) ;
        Conv([name 'c'], 1, 2^(s+4), 'relu', false) ;

        % Sum layer
        net.addLayer([name '_sum'] , ...
            dagnn.Sum(), ...
            {sumInput.var, lastAdded.var}, ...
            [name '_sum']) ;
        net.addLayer([name '_relu'] , ...
            dagnn.ReLU(), ...
            [name '_sum'], ...
            name) ;
        lastAdded.var = name ;
    end
end

% net.addLayer('prediction_avg' , ...
%     dagnn.Pooling('poolSize', [7 7], 'method', 'avg'), ...
%     lastAdded.var, ...
%     'prediction_avg') ;
%
% net.addLayer('prediction' , ...
%     dagnn.Conv('size', [1 1 2048 1000]), ...
%     'prediction_avg', ...
%     'prediction', ...
%     {'prediction_f', 'prediction_b'}) ;
%
% net.addLayer('loss', ...
%     dagnn.Loss('loss', 'softmaxlog') ,...
%     {'prediction', 'label'}, ...
%     'objective') ;
%
% net.addLayer('top1error', ...
%     dagnn.Loss('loss', 'classerror'), ...
%     {'prediction', 'label'}, ...
%     'top1error') ;
%
% net.addLayer('top5error', ...
%     dagnn.Loss('loss', 'topkerror', 'opts', {'topK', 5}), ...
%     {'prediction', 'label'}, ...
%     'top5error') ;

% -------------------------------------------------------------------------
%                                                           Meta parameters
% -------------------------------------------------------------------------

% net.meta.normalization.imageSize = [224 224 3] ;
% net.meta.inputSize = [net.meta.normalization.imageSize, 32] ;
% net.meta.normalization.cropSize = net.meta.normalization.imageSize(1) / 256 ;
% net.meta.normalization.averageImage = opts.averageImage ;
%
% net.meta.classes.name = opts.classNames ;
% net.meta.classes.description = opts.classDescriptions ;
%
% net.meta.augmentation.jitterLocation = true ;
% net.meta.augmentation.jitterFlip = true ;
% net.meta.augmentation.jitterBrightness = double(0.1 * opts.colorDeviation) ;
% net.meta.augmentation.jitterAspect = [3/4, 4/3] ;
% net.meta.augmentation.jitterScale  = [0.4, 1.1] ;
% %net.meta.augmentation.jitterSaturation = 0.4 ;
% %net.meta.augmentation.jitterContrast = 0.4 ;
%
% net.meta.inputSize = {'input', [net.meta.normalization.imageSize 32]} ;
%
% %lr = logspace(-1, -3, 60) ;
% lr = [0.1 * ones(1,30), 0.01*ones(1,30), 0.001*ones(1,30)] ;
% net.meta.trainOpts.learningRate = lr ;
% net.meta.trainOpts.numEpochs = numel(lr) ;
% net.meta.trainOpts.momentum = 0.9 ;
% net.meta.trainOpts.batchSize = 256 ;
% net.meta.trainOpts.numSubBatches = 4 ;
% net.meta.trainOpts.weightDecay = 0.0001 ;

% Init parameters randomly
net.initParams() ;

% For uniformity with the other ImageNet networks, t
% the input data is *not* normalized to have unit standard deviation,
% whereas this is enforced by batch normalization deeper down.
% The ImageNet standard deviation (for each of R, G, and B) is about 60, so
% we adjust the weights and learing rate accordingly in the first layer.
%
% This simple change improves performance almost +1% top 1 error.
% p = net.getParamIndex('conv1_f') ;
% net.params(p).value = net.params(p).value / 100 ;
% net.params(p).learningRate = net.params(p).learningRate / 100^2 ;
%
% for l = 1:numel(net.layers)
%     if isa(net.layers(l).block, 'dagnn.BatchNorm')
%         k = net.getParamIndex(net.layers(l).params{3}) ;
%         net.params(k).learningRate = 0.3 ;
%     end
% end

end


filename='Cantileverbeam_Tetrahedra_Linear_Structured';
 ptype = 'MACRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'full';
cost = {'compliance'};
weights = [1];
constraint = {'volume'};
optimizer = 'MMA';
incrementFactor = 1;
designVariable = 'Density';
filterType = 'P1';
constraint_case = 'INEQUALITY';
line_search_initiator = 'STANDARD';
showBC = true;

nsteps = 10;
Vfrac_final = 0.1;
Perimeter_target = 1;
optimality_final = 1e-3;
constr_final =1e-3;

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


function [err,testShift] = CMFfitOneMeridianFun( testShift, uDistTemplate, mnPhTemplate, uDist, mnPh)
%
% AUTHOR:  Wandell, Brewer
% PURPOSE:
%
%   The CMF data have an observed relative uDist and complex phase (mnPh).
% The absolute value of the distance, however, is not meaningful.
% We can add or subtract a constant from each of the meridia because
% they don't start in exactly the same place.
%
%   This routine slides the distance of the data to be in
% register with a template function.  Usually one of the
% the data sets themselves is used as the template.
%
% We search for a distance shift (testShift) that
% brings the data into register with the template data.
%
% DEBUG:
% template = meridia(1);
% testShift = 3; uDist = meridia(2).uDist; mnPh = meridia(2).mnPh;
% CMFfitOneMeridianFun( testShift, template, uDist,mnPh)

warning('Not used, we think.');

% Interpolate the test data set using the testShift parameter
% This uses the existing data to predict the values at the template
% The mnPh data are complex.
%
predicted = interp1(uDist + testShift, mnPh, uDistTemplate, 'linear');
% try adding 'extrap' option to interp1?

% A few of the data may be out of range.  These produce NaNs in the
% interpolation.  Count these;  if there are too many send a big error
% back.  Otherwise, send back the norm difference, but accounting for
% the number of points used to do the fit.
% I wish I had a reason for using 0.65.
%
l = ~isnan(predicted);
if sum(l) > 0.65*length(uDistTemplate)
   err = norm(predicted(l) - mnPhTemplate(l))/sqrt(length(l));
else
   err = 1000;  % A large number
end

return;


function graph = prtGraphDataGenKarate
% graph = prtGraphDataGenKarate
%   Read karate.gml
%
% From the README:
%
% The file karate.gml contains the network of friendships between the 34
% members of a karate club at a US university, as described by Wayne
% Zachary in 1977.  If you use these data in your work, please cite W. W.
% Zachary, An information flow model for conflict and fission in small
% groups, Journal of Anthropological Research 33, 452-473 (1977).

baseDir = prtGraphDataDir;
gmlFile = 'karate.gml';
file = fullfile(baseDir,gmlFile);

[sparseGraph,names] = prtUtilReadGml(file);
graph = prtDataTypeGraph(sparseGraph,names);


function assertAlmostEqual(A, B, reltol, message)
%assertEqual Assert that inputs are equal within relative tolerance
%   assertEqual(A, B, RELTOL) throws an exception of any of the values in A and
%   B are not equal within the specified tolerance.  NaN values are considered
%   to be equal.  A and B have to have the same class and sparsity to be
%   considered equal.
%
%   assertEqual(A, B) uses the following relative tolerance value:
%
%       100 * eps(class(A))
%
%   assertEqual(A, B, RELTOL, MESSAGE) uses the specified message string when
%   throwing the exception.  With this syntax, use RELTOL = [] to specify the
%   default relative tolerance.
%
%   Note that if either A or B are not floating-point arrays, then A and B are
%   compared using ISEQUALWITHEQUALNANS and the relative tolerance value is not
%   used.
%
%   Examples
%   --------
%   % This call returns silently.
%   assertAlmostEqual(1.0, 1.0 + eps);
%
%   % This call throws an error.
%   assertAlmostEqual(1.0, 1.1);
%
%   See also assertEqual, mtest.utils.isAlmostEqual

%   Steven L. Eddins
%   Copyright 2008-2009 The MathWorks, Inc.

if ~(issparse(A) == issparse(B))
   throw(MException('assertAlmostEqual:sparsityNotEqual', message));
end

if ~strcmp(class(A), class(B))
   throw(MException('assertAlmostEqual:classNotEqual', message));
end

if nargin < 3 || isempty(reltol)
    reltol = 100 * eps(class(A));
end

if nargin < 4
    message = sprintf('Inputs are not equal within relative tolerance: %g', ...
        reltol);
end

if ~mtest.utils.isAlmostEqual(A, B, reltol)
   throw(MException('assertAlmostEqual:tolExceeded', message));
end


function box = minandmax2est(f, N)
%MINANDMAX2EST   Estimates the range of a DISKFUNV.
%   BOX = MINANDMAX2EST(F) returns estimates for the minimum and maximum of each
%   component of the DISKFUNV F over its domain.  BOX is a vector of length
%   four, containing the estimated minimum and maximum of each component.
%
%   BOX = MINANDMAX2EST(F, N) returns estimates for the minimum and maximum of
%   each component of the DISKFUNV F over its domain, based on samples on
%   an N by N grid (N = 33 by default).
%
% See also DISKFUN/MINANDMAX2EST.

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

box = [];

if ( isempty(f) )
    return
end

if ( ( nargin < 2 ) || isempty(N) )
    % Default to N = 33:
    N = 33;
end

for jj = 1:2
    box = [ box, minandmax2est(f.components{jj}, N) ];
end

end


function x = emailFeatures(word_indices)
%EMAILFEATURES takes in a word_indices vector and produces a feature vector
%from the word indices
%   x = EMAILFEATURES(word_indices) takes in a word_indices vector and
%   produces a feature vector from the word indices.

% Total number of words in the dictionary
n = 1899;

% You need to return the following variables correctly.
x = zeros(n, 1);

% ====================== YOUR CODE HERE ======================
% Instructions: Fill in this function to return a feature vector for the
%               given email (word_indices). To help make it easier to
%               process the emails, we have have already pre-processed each
%               email and converted each word in the email into an index in
%               a fixed dictionary (of 1899 words). The variable
%               word_indices contains the list of indices of the words
%               which occur in one email.
%
%               Concretely, if an email has the text:
%
%                  The quick brown fox jumped over the lazy dog.
%
%               Then, the word_indices vector for this text might look
%               like:
%
%                   60  100   33   44   10     53  60  58   5
%
%               where, we have mapped each word onto a number, for example:
%
%                   the   -- 60
%                   quick -- 100
%                   ...
%
%              (note: the above numbers are just an example and are not the
%               actual mappings).
%
%              Your task is take one such word_indices vector and construct
%              a binary feature vector that indicates whether a particular
%              word occurs in the email. That is, x(i) = 1 when word i
%              is present in the email. Concretely, if the word 'the' (say,
%              index 60) appears in the email, then x(60) = 1. The feature
%              vector should look like:
%
%              x = [ 0 0 0 0 1 0 0 0 ... 0 0 0 0 1 ... 0 0 0 1 0 ..];
%
%

for i = 1:length(word_indices)
    x(word_indices(i)) = 1
end

% =========================================================================

end


function A = slinitarray(type, size)
%SLINITARRAY Initialize an array of specified type and size
%
% $ Syntax $
%   - A = slinitarray(type, size)
%
% $ Arguments $
%   - type          the string representing the element type of the array
%   - size          the vector representing the size of the array
%   - A             the initialized array
%
% $ Description $
%   - A = slinitarray(type, size) creates an array of specified type and
%     given size, with all elements being zeros.
%
%   - The typenames supported are listed below:
%       - 'double'
%       - 'single'
%       - 'float'
%       - 'uint8'
%       - 'uint16'
%       - 'uint32'
%       - 'uint64'
%       - 'int8'
%       - 'int16'
%       - 'int32'
%       - 'int64'
%       - 'logical'
%       - 'char'
%
% $ History $
%   - Created by Dahua Lin on Dec 7th, 2005
%

switch type
    case 'double'
        A = zeros(size);
    case {'single', 'float'}
        A = zeros(size, 'single');
    case {'uint8', 'uint16', 'uint32', 'uint64', ...
          'int8', 'int16', 'int32', 'int64'}
        A = zeros(size, type);
    case 'logical'
        A = false(size);
    case 'char'
        A = char(zeros(size, 'uint8'));
    otherwise
        error('sltoolbox:invalid_type', ...
            'Unsupported typename %s', typename);
end


classdef MulConst < dagnn.ElementWise
% MulConst multiplies its input by its parameter.

    properties
    end

    methods
        function outputs = forward(obj, inputs, params)
            assert(numel(inputs) == 1, 'one input is needed');
            assert(numel(params) == 1, 'one param is needed');
            outputs{1} = mul_const(inputs{1}, params{1});
        end

        function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
            assert(numel(inputs) == 1, 'one input is needed');
            assert(numel(params) == 1, 'one param is needed');
            assert(numel(derOutputs) == 1, 'expect one gradient');
            [derInputs{1}, derParams{1}] = mul_const(...
                inputs{1}, params{1}, derOutputs{1});
        end

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


function issquare=issquare(X)
%ISSQUARE Check if variable is square

n = X.dim(1);
m = X.dim(2);
issquare = (n==m);


function x = TT_to_TTeMPS( tt )
    %TT_to_TTeMPS Convert from TT Toolbox format.
    %   A = TT_to_TTeMPS( tt ) takes the tt_tensor object tt created using the
    %   TT Toolbox 2.x from Oseledets et al. and converts it into a TTeMPS tensor.
    %   Toolbox needs to be installed, of course.
    %
    %   See also TTeMPS_to_TT.

    %   TTeMPS Toolbox.
    %   Michael Steinlechner, 2013-2016
    %   Questions and contact: michael.steinlechner@epfl.ch
    %   BSD 2-clause license, see LICENSE.txt

    cores = {};
    ps = tt.ps;
    for i = 1:tt.d
        cores{i} = reshape( tt.core( ps(i):ps(i+1)-1 ), ...
                                [tt.r(i), tt.n(i), tt.r(i+1)] );
    end

    x = TTeMPS( cores );

end


  function [grad, out, com] = ir_hct_rgrad(x, varargin)
%|function [grad, out, com] = ir_hct_rgrad(x, varargin)
%|
%| compute 3D regularizer gradient using hct binary
%| for UM testing only
%|
%| in
%|	x	in xyz order
%| option
%|	(many - see below)
%|
%| Notes: because hct2 uses 'zxy' order, it is essential to use Reg1
%| with zxy order also, to ensure gradient matches over entire object.
%| If Reg1 uses the usual xyz order, then slices [1 end] do not match.
%|
%| Jeff Fessler, 2012-06-15

if nargin == 1 && streq(x, 'test'), ir_hct_rgrad_test, return, end
if nargin < 2, ir_usage(), end

arg.R = [];
arg.bij_center = '';
arg.bij_above = '';
arg.log2reg_x = 0; % 0 by default because beta built into R.beta
arg.log2reg_z = []; % ""
arg.kappa_min = 0;
arg.clean = true; % remove files after?
arg.dir = ''; % work directory
arg.file_x = 'ir-hct-rgrad-x.fld'; % work file for x
arg.file_grad = 'ir-hct-rgrad-grad.fld'; % work file for grad
arg.file_mask = 'ir-hct-rgrad-mask.fld'; % work file for mask
arg.file_kappa = 'ir-hct-rgrad-kappa.fld'; % work file for kappa
arg.chat = 0;

arg = vararg_pair(arg, varargin);
if isempty(arg.dir)
	arg.dir = test_dir;
end

R = arg.R;

if isempty(arg.log2reg_z)
	arg.log2reg_z = arg.log2reg_x;
end

arg.file_x = [arg.dir arg.file_x];
arg.file_grad = [arg.dir arg.file_grad];
arg.file_mask = [arg.dir arg.file_mask];
arg.file_kappa = [arg.dir arg.file_kappa];

pn = jf_protected_names;
if ~pn.has_hct2
	fail 'need hct2'
end

if ~streq(R.type_penal, 'zxy') || ~R.offsets_is_zxy
	fail 'zxy required to ensure match'
end

% write files
tox = @(z) permute(z, [2 3 1]);
fld_write(arg.file_x, x)
fld_write(arg.file_mask, tox(R.mask), 'type', 'byte')
fld_write(arg.file_kappa, tox(R.wt.kappa))

if exist(arg.file_grad, 'file')
	eval(['!/bin/rm ' arg.file_grad])
end

if ~isempty(R.pot_params)
	delta = R.pot_params(1);
	qgg_q = R.pot_params(2);
else
	delta = 0;
	qgg_q = 0;
end

if isempty(arg.bij_center)
	if isfield(R, 'beta') && numel(R.beta) > 1
		beta = R.beta;
		displace_zxy = penalty_displace(R.offsets, R.dim);
		oz = displace_zxy(:,1);
		ox = displace_zxy(:,2);
		oy = displace_zxy(:,3);
		bij = zeros(3,3,3);
		ii = sub2ind([3 3 3], 2+ox, 2+oy, 2+oz);
		bij(ii) = beta;
		ii = sub2ind([3 3 3], 2-ox, 2-oy, 2-oz);
		bij(ii) = beta;
		bij = bij / 2^arg.log2reg_x; % scale to match ge style in hct2
		if arg.log2reg_x ~= arg.log2reg_z, fail 'not done', end
		jf_equal(bij(:,:,1), bij(:,:,3)) % verify symmetry
		b = @(i,j) bij(1+i, 1+j, 1); % above
		arg.bij_above = sprintf('%g,%g,%g,%g,%g,%g,%g,%g,%g', ...
                        b(0,0), b(0,1), b(0,2), ...
                        b(1,0), b(1,1), b(1,2), ...
                        b(2,0), b(2,1), b(2,2));
		b = @(i,j) bij(1+i, 1+j, 2); % center
		arg.bij_center = sprintf('%g,%g,%g,%g,%g,%g,%g,%g,%g', ...
                        b(0,0), b(0,1), b(0,2), ...
                        b(1,0), b(1,1), b(1,2), ...
                        b(2,0), b(2,1), b(2,2));
	else
		arg.bij_center = '-';
		arg.bij_above = '-';
	end
end

% trick due to zxy order:
nx = R.dim(2);
ny = R.dim(3);
nz = R.dim(1);

com = sprintf(['hct2 what rgrad chat %d ' ...
	'ns 8 nt 16 na 12 ', ... % fake
	'nx %d ny %d nz %d ' ...
	'bij_center %s bij_above %s ' ...
	'distance_power %g ', ...
	'pot %s delta %g qgg_q %g use_reg_zxy 1 ' ...
	'log2reg_x %.6f log2reg_z %.6f kappa_min %g ' ...
	'file_kappa %s file_mask %s file_init %s file_xh %s'], ...
	...
	arg.chat, nx, ny, nz, ...
	arg.bij_center, arg.bij_above, ...
	R.distance_power, ...
	R.pot_type, delta, qgg_q, ...
	arg.log2reg_x, arg.log2reg_z, arg.kappa_min, ...
	arg.file_kappa, arg.file_mask, arg.file_x, arg.file_grad);

out = os_run(com); % run hct2

grad = fld_read(arg.file_grad);

if arg.clean
	clean = ['!/bin/rm ' arg.file_x ' ' arg.file_grad ' ' arg.file_mask ' ' arg.file_kappa];
	eval(clean)
end

% ir_hct_rgrad_test()
function ir_hct_rgrad_test

rng(0)
kappa = 2 + rand(18,20,10);
%kappa = ones(18,20,10);
kappa([1 end],:,:) = 0; % zero border required for zxy
kappa(:,[1 end],:) = 0;

toz = @(x) permute(x, [3 1 2]);
tox = @(z) permute(z, [2 3 1]);
R = Reg1(toz(kappa), 'beta', 4, 'nthread', jf('ncore'), ...
	'type_penal', 'zxy', ...
	'offsets', '3d:26', ...
	'type_wt', 'fly', ...
	'pot_arg', {'qgg2', 10, 1.2}, ...
	'distance_power', 0);
Rx = Reg1(kappa, 'beta', 4, 'nthread', jf('ncore'), ...
	'offsets', '3d:26', ...
	'type_wt', 'fly', ...
	'pot_arg', {'qgg2', 10, 1.2}, ...
	'distance_power', 0);
%x = zeros(size(kappa));
%x(end/2,end/2,end/2) = 0;
%x(end/2,end/4,1) = 1;
rng(0)
x = randn(size(kappa)) .* (kappa ~= 0);
if 0 % kludge to make penalty value match
	x(:,:,1) = 0;
	x(:,:,end) = 0;
end
mat = R.cgrad(R, toz(x));
mat = tox(mat);

xlim = [-1 1] * 3;
clim = [-1 1] * 1000;
im plc 2 2

im(1, x, xlim)
im(mat, clim)

printm 'calling hct'
%tic
[hct, out] = ir_hct_rgrad(x, 'R', R, 'log2reg_x', 4, 'chat', 99);
%toc
printm(['hct2 output: \n ' out])
pr Rx.penal(Rx, x);

im(hct, clim)
im(hct - mat)
equivs(hct, mat, 'thresh', 2e-6)


function displaySegmentGraph(im, segimage, adjlist)

stats = regionprops(segimage, 'Centroid');
centroids = cat(1, stats.Centroid);

segimage = double(segimage) / double(max(segimage(:)));

[gx, gy] = gradient(segimage);

edges = find((gx ~= 0) | (gy ~= 0));

[imh, imw, imb] = size(im);

for b = 1:imb
    im(edges+(b-1)*imh*imw) = 1*(b==1); % make edges red
end

hold off, imagesc(im), axis image, hold on

% convert adjacency matrix to adjacency list if necessary
if size(adjlist, 1) == size(adjlist, 2)
    adjmat = adjlist;
    [s1, s2] = find(adjmat);
    adjlist = [s1 s2];
    ind = find(adjlist(:, 1) < adjlist(:, 2));
    adjlist = adjlist(ind, :);
end

if size(adjlist, 2) == 2
    for k = 1:size(adjlist, 1)
        plot(centroids(adjlist(k, :), 1), centroids(adjlist(k, :), 2), 'g', 'LineWidth', 1);
    end
end


function [varargout]=regionTriMesh3D(varargin)

% function [F,V,boundaryInd]=regionTriMesh3D(regionCell,pointSpacing,resampleCurveOpt,interpMethod)
% ------------------------------------------------------------------------
% This function creates a 3D triangulation for the region specified in the
% variable regionCell. The mesh aims to obtain a point spacing as defined
% by the input pointSpacing.
% The function output contains the triangular faces in F, the vertices in V
% and the per triangle region indices in regionInd. By setting plotOn to 0
% or 1 plotting can be switched on or off.
%
% More on the specification of the region:
% The input variable regionCell is a cell array containing all the boundary
% curves, e.g. for a two curve region 1 we would have something like
% regionSpec{1}={V1,V2} where V1 and V2 are the boundary curves. Multiple
% curves may be given here. The first curve should form the outer boundary
% of the entire region, the curves that follow should define holes inside
% this boundary and the space inside them is therefore not meshed.
%
% See also: regionTriMesh2D
%
% Kevin Mattheus Moerman
% gibbon.toolbox@gmail.com
%
% 2013/11/21: Created
% 2013/11/21: Added varargin input parsing
%------------------------------------------------------------------------

%% Parse input

switch nargin
    case 1
        regionCell=varargin{1};
        pointSpacing=[];
        resampleCurveOpt=[];
        interpMethod=[];
    case 2
        regionCell=varargin{1};
        pointSpacing=varargin{2};
        resampleCurveOpt=[];
        interpMethod=[];
    case 3
        regionCell=varargin{1};
        pointSpacing=varargin{2};
        resampleCurveOpt=varargin{3};
        interpMethod=[];
    case 4
        regionCell=varargin{1};
        pointSpacing=varargin{2};
        resampleCurveOpt=varargin{3};
        interpMethod=varargin{4};
end

if isempty(pointSpacing)
    D=zeros(1,numel(regionCell));
    for q=1:1:numel(regionCell)
        D(q)=mean(diff(polyCurveLength(regionCell{1})));
    end
    pointSpacing=mean(D);
end

if isempty(resampleCurveOpt)
    resampleCurveOpt=0;
end

if isempty(interpMethod)
    interpMethod='natural';
end

%% Parse 3D regions and convert to planar 2D

% TO DO: get sizes and do it properly, hint cellfun(@(x) size(x,1),regionCell)
npSets=cellfun(@(x) size(x,1),regionCell);
npTotal=sum(npSets);

%Collect all points
Vt=zeros(npTotal,3);
startInd=1;
endInd=npSets(1);
for qCurve=1:1:numel(regionCell)
    Vs=regionCell{qCurve};
    Vt(startInd:endInd,:)=Vs;
    startInd=startInd+npSets(qCurve);
    if qCurve<numel(regionCell)
        endInd=startInd+npSets(qCurve+1)-1;
    end
end

Vt_mean=mean(Vt,1);
Vtc=Vt-Vt_mean(ones(size(Vt,1),1),:);

%Get orientation
[R_fit]=pointSetPrincipalDir(Vtc);

%Create planar 2D sets
Vtcr=Vt;
startInd=1;
endInd=npSets(1);
regionCell2D=regionCell;
for qCurve=1:1:numel(regionCell)
    Vs=Vt(startInd:endInd,:);
    Vs=Vs-Vt_mean(ones(size(Vs,1),1),:);
    Vs=(R_fit'*Vs')';
    regionCell2D{qCurve}=Vs(:,[1 2]);
    Vtcr(startInd:endInd,:)=Vs;
    startInd=startInd+npSets(qCurve);
    if qCurve<numel(regionCell)
        endInd=startInd+npSets(qCurve+1)-1;
    end
end

%% Use regionTriMesh2D to mesh region in 2D

[F,V,boundaryInd]=regionTriMesh2D(regionCell2D,pointSpacing,resampleCurveOpt,0);

%% Interpolate to obtain Z coordinates

interpFunc = scatteredInterpolant(Vtcr(:,[1 2]),Vtcr(:,3),interpMethod);
V(:,3)=interpFunc(V(:,[1 2]));
V=(R_fit*V')';
V=V+Vt_mean(ones(size(V,1),1),:);

%% Check normal directions against input curve(s)

% V_test=regionCell{1};
% V_test=V_test(1:2,:);

% [~,e]=minDist(V_test,V);
% E=patchEdges(F,1);
% if ~any(E(:,1)==e(1) & E(:,2)==e(2))
%    F=fliplr(F); %Invert if edge does not seem member of faces
% end

%% Collect ouput
varargout{1}=F;
varargout{2}=V;
varargout{3}=boundaryInd;

%%
% _*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 nsm3d_test01 ( prefix )

%*****************************************************************************80
%
%% NSM3D_TEST01 examines a mesh from the NAVIER_STOKES_MESH3D data.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 May 2013
%
%  Author:
%
%    John Burkardt
%
  mesh_filename = sprintf ( '%s.mat', prefix );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'NSM3D_TEST01:\n' );
  fprintf ( 1, '  "%s"\n', mesh_filename );

  [ nodeco, elnode, bdynde ] = mesh3d_extract ( mesh_filename );
%
%  NODECO has an unused 4th dimension.  Suppress it.
%
  nodeco = nodeco(:,1:3);
  [ node_num, node_dim ] = size ( nodeco );
  [ element_num, element_order ] = size ( elnode );
  [ bdynde_num, ~ ] = size ( bdynde );

  fprintf ( 1, '  NODECO = %d nodes x %d spatial dimensions,\n', ...
    node_num, node_dim );
  fprintf ( 1, '  ELNODE = %d elements x %d nodes per element,\n', ...
    element_num, element_order );
  fprintf ( 1, '  BDYNDE = %d boundary nodes\n', bdynde_num );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Dim       Min          Max\n' );
  fprintf ( 1, '\n' );
  for j = 1 : node_dim
    xmin = min ( nodeco(:,j) );
    xmax = max ( nodeco(:,j) );
    fprintf ( 1, '  %d  %12f  %12f\n', j, xmin, xmax );
  end
%
%  Write the nodes to a file.
%
  node_filename = sprintf ( '%s_nodes.txt', prefix );
  nodeco = nodeco';
  r8mat_write ( node_filename, node_dim, node_num, nodeco );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Created the node file "%s".\n', node_filename );

  element_filename = sprintf ( '%s_elements.txt', prefix );
  elnode = elnode';
  i4mat_write ( element_filename, element_order, element_num, elnode );
  fprintf ( 1, '  Created the element file "%s".\n', element_filename );

  return
end


function [c,s,px,py,pz,rho,u,lambda] = unbalance3d_dose_2( source,target,gamma,H,reverse)

layer1=0.4;
layer2=1.0;

%profile on;
%% Input
%Source/Target

%load('deformedDoseOutputForLung_490pts_new/doseGrid.mat');
% Parameters
[nx,ny,nz]=size(source);
Hx=H.Hx;
Hy=H.Hy;
Hz=H.Hz;
% Hx=abs(xDoseV(length(xDoseV))-xDoseV(1))/10;
% Hy=abs(yDoseV(length(yDoseV))-yDoseV(1))/10;
% Hz=abs(zDoseV(length(zDoseV))-zDoseV(1))/10;

n=2;
nt    = 10;
hx    = Hx/nx;
hy    = Hy/ny;
hz    = Hz/nz;
ht    = 1/nt;

%% Input Normalization
source=double(source);
target=double(target);
if reverse=='r'
    source=255-source;
    target=255-target;
end
tr0  = sum(source(:));
tr1  = sum(target(:));
source = source+tr0/nx/ny/nz/15;
target = target+tr0/nx/ny/nz/15;

g=0;
g0=g+tr1/nx/ny/nz;
g1=g+tr0/nx/ny/nz;

rho0=g0*ones([size(source),2]);
rho0(:,:,:,1) = source;
rho1=g1*ones([size(target),2]);
rho1(:,:,:,1) = target;

%% Parameters Initialization
dim   = [n,nx,ny,nz,nt];
dim1=[n,round(nx*layer1),round(ny*layer1),round(nz*layer1),nt];
h     = [hx,hy,hz,ht];
h1=[Hx/dim1(2),Hy/dim1(3),Hz/dim1(4),ht];
param = paraminit(rho0(:),rho1(:),dim,h,gamma);
rho0_0 = fastResample3d(rho0,[dim1(2),dim1(3),dim1(4)]);
rho1_0 = fastResample3d(rho1,[dim1(2),dim1(3),dim1(4)]);
param1 = paraminit(rho0_0,rho1_0, dim1, h1, gamma);

m=param.m;
%% Set initial values for p rho u
px1     = zeros(n,dim1(2)-1,dim1(3),dim1(4),nt);
py1     = zeros(n,dim1(2),dim1(3)-1,dim1(4),nt);
pz1     = zeros(n,dim1(2),dim1(3),dim1(4)-1,nt);
u1      = zeros(m,dim1(2),dim1(3),dim1(4),nt);

tc=linspace(ht*3/2,1-ht/2,nt-1);
rho0_1 = fastResample3d(rho0,[dim1(2),dim1(3),dim1(4)]);
rho1_1 = fastResample3d(rho1,[dim1(2),dim1(3),dim1(4)]);
rho_1=ones(1,nt-1).*rho0_1(:)+tc.*(rho1_1(:)-rho0_1(:));

lambda1=zeros(dim1);
% initial values
init1.px     = px1;
init1.py     = py1;
init1.pz     = pz1;
init1.rho    = rho_1;
init1.u      = u1;
init1.lambda=lambda1;
%% iterations
max_iter=30;
tic
[px1,py1,pz1,rho_1,u1,lambda1,errorhist1] = SQPOPT(@(px,py,pz,rho,u,param) costgradf(px,py,pz,rho,u,param),init1,max_iter,param1);
toc
optcost=errorhist1(end,1);
iter_num=errorhist1(end,2);
fprintf('layer 1 Computed cost is: %f, iteration number=%d\n',optcost,iter_num);

%% results1
px1     = reshape(px1,[n,dim1(2)-1,dim1(3),dim1(4),nt]);
py1     = reshape(py1,[n,dim1(2),dim1(3)-1,dim1(4),nt]);
pz1     = reshape(pz1,[n,dim1(2),dim1(3),dim1(4)-1,nt]);
rho_1    = reshape(rho_1,[n,dim1(2),dim1(3),dim1(4),(nt-1)]);
u1      = reshape(u1,[m,dim1(2),dim1(3),dim1(4),nt]);
lambda1 = reshape(lambda1,[n,dim1(2),dim1(3),dim1(4),nt]);

px2     = zeros(n,dim(2)-1,dim(3),dim(4),nt);
py2     = zeros(n,dim(2),dim(3)-1,dim(4),nt);
pz2     = zeros(n,dim(2),dim(3),dim(4)-1,nt);
u2      = zeros(m,dim(2),dim(3),dim(4),nt);
rho_2    = zeros(n,dim(2),dim(3),dim(4),(nt-1));
lambda2=zeros(dim);
for k=1:nt
    temp=px1(:,:,:,:,k);
    temp=permute(temp,[2,3,4,1]);
    interp4M = fastResample3d(temp,[dim(2)-1,dim(3),dim(4)]);
    px2(:,:,:,:,k) = permute(interp4M,[4,1,2,3]);

    temp=py1(:,:,:,:,k);
    temp=permute(temp,[2,3,4,1]);
    interp4M = fastResample3d(temp,[dim(2),dim(3)-1,dim(4)]);
    py2(:,:,:,:,k) = permute(interp4M,[4,1,2,3]);

    temp=pz1(:,:,:,:,k);
    temp=permute(temp,[2,3,4,1]);
    interp4M = fastResample3d(temp,[dim(2),dim(3),dim(4)-1]);
    pz2(:,:,:,:,k) = permute(interp4M,[4,1,2,3]);

    if(k~=nt)
        temp=rho_1(:,:,:,:,k);
        temp=permute(temp,[2,3,4,1]);
        interp4M = fastResample3d(temp,[dim(2),dim(3),dim(4)]);
        rho_2(:,:,:,:,k) = permute(interp4M,[4,1,2,3]);
    end
    temp=u1(:,:,:,:,k);
    temp=permute(temp,[2,3,4,1]);
    interp4M = fastResample3d(temp,[dim(2),dim(3),dim(4)]);
    u2(:,:,:,:,k) = permute(interp4M,[4,1,2,3]);

    temp=lambda1(:,:,:,:,k);
    temp=permute(temp,[2,3,4,1]);
    interp4M = fastResample3d(temp,[dim(2),dim(3),dim(4)]);
    lambda2(:,:,:,:,k) = permute(interp4M,[4,1,2,3]);

end

% initial values
init.px     = px2;
init.py     = py2;
init.pz     = pz2;
init.rho    = rho_2;
init.u      = u2;
init.lambda=lambda2;
%% iterations
max_iter=20;
tic
[px,py,pz,rho,u,lambda,errorhist] = SQPOPT(@(px,py,pz,rho,u,param) costgradf(px,py,pz,rho,u,param),init,max_iter,param);
toc
optcost=errorhist(end,1);
iter_num=errorhist(end,2);
fprintf('layer 2 Computed cost is: %f, iteration number=%d\n',optcost,iter_num);

[c,s]=cs_results(px,py,pz,rho,u,param);
%% results
px     = reshape(px,[n,(nx-1),ny,nz,nt]);
py     = reshape(py,[n,nx,(ny-1),nz,nt]);
pz     = reshape(pz,[n,nx,ny,(nz-1),nt]);
rho    = reshape(rho,[n,nx,ny,nz,(nt-1)]);
u      = reshape(u,[m,nx*ny*nz*nt]);
lambda = reshape(lambda,[n,nx*ny*nz*nt]);

end


function dataOut=plotMultipleProjectedAmps_SingleCondition(view,scanToPlot,projectionPhase)
%
% plotMultipleProjectedAmps_SingleCondition(view,projectionPhase)
%
% Bar plot of the amplitudes for each scan, averaging across
% all pixels (in all slices) in a selection of ROIs. All y-axes are made the same. The bar heights
% and a coarse SEM can be obtained from get(gca,'UserData').
% Amplitudes are projected against a single phase (supplied).

% gmb  5/25/98
% bw   2/19/99  Added seY field to the UserData field.
%	    seY is an estimate of the variability in the
%      amplitudes.  It is the SEM of the in the complex
%      (amp*exp(-i*ph)) representation.  The values are
%      computed in vectorMean.m
% fwc   11/07/02 plots data relative to current view
%       added plotting of multiple ROIs
%       ROI selection copied from plotMultipleTSeries.m
% arw   042505 Correctly extracts projections phase from current scan if
%   none is sprcified.
%   Projection phase is in radians.
%

mrGlobals;

refScan = getCurScan(view);
if (~exist('projectionPhase','var'))
    computeProjPhase=1;
else
    if (isnan(projectionPhase))
        % User input requested
        projectionPhase=input('Enter projection phase in radians:');
    end

    computeProjPhase=0;
end

% Select ROIs
nROIs=size(view.ROIs,2);
roiList=cell(1,nROIs);
for r=1:nROIs
    roiList{r}=view.ROIs(r).name;
end
selectedROIs = find(buttondlg('ROIs to Plot',roiList));
nROIs=length(selectedROIs);
if (nROIs==0)
    error('No ROIs selected');
end

% Plot it
selectGraphWin
clf
fontSize = 8;
headerStr = ['Mean Amplitudes'];
set(gcf,'Name',headerStr);

minylim=0;
maxylim=0;
nrows=0;
ncols=0;

nscans = numScans(view);
ROIamps=zeros(nROIs,1);
ROIseZ=zeros(nROIs,1);
ROImeanPhs=zeros(nROIs,1);

for r=1:nROIs

    n=selectedROIs(r);
    view = selectROI(view,n); % is there another way? Well yes - we could be opening up a hidden window and doing all this invisibly.

    [meanAmps,meanPhs,seZ] = vectorMeans(view);
    meanAmps=meanAmps(scanToPlot);
    meanPhs=meanPhs(scanToPlot);
    seZ=seZ(scanToPlot);

    if (computeProjPhase)
        projectionPhase=meanPhs(refScan);
    end

    % Compute the amplitude projected onto the reference phase
    meanAmps = meanAmps.*cos(meanPhs-projectionPhase);

    ROIamps(r)=meanAmps;
    ROIseZ(r)=seZ;

    ROImeanPhs(r)=meanPhs;
    %xstr{r}=[view.ROIs(selectedROIs(r)).name];
    xstr{r}=int2str(r);
    roiName{r}=view.ROIs(selectedROIs(r)).name;
    fprintf(['\n#%d :',roiName{r}],r);
end

dataOut.ROIamps=ROIamps;
dataOut.ROIseZ=ROIseZ;
dataOut.ROIname=roiName;

% Now do the plotting

    nrows=1;
    ncols=1;

    subplot(nrows,ncols,1);

    %plot the bar graph
    size(ROIamps)
    size(ROIseZ)
    size(xstr)

    h=mybar(ROIamps,ROIseZ,xstr,'');

    xlabel('ROI','FontSize',fontSize);
    ylabel('Mean Amplitude','FontSize',fontSize);
    set(gca,'FontSize',ceil(fontSize*1.2));
    conditionName=dataTYPES(view.curDataType).scanParams(scanToPlot).annotation;
    fprintf('\nCondition #%d :',scanToPlot);

    title(['Condition #: ' int2str(scanToPlot)]);

end

%Save the data in gca('UserData')
data.y =ROIamps(:);
data.refScan = refScan;
data.seY = ROIseZ(:); % this should probably be adapted

set(gca,'UserData',data);

% give all plots same y-axis

return;


function [scr_lin,scr_qual] = linear_and_quality_fusion_scores(key,scores_obj_array,qual_obj_array,Qtrans,...
                                                    prior,niters,obj_func,cstepHessian,quiet)
% Fuses scores (using linear fusion) and then fuses in quality
% measures.  The fusion is applied to the same scores as those used
% to train the fusion function.  The input scores and key must
% already be loaded.  Use 'linear_and_quality_fusion_scores_from_files' if you
% want the script to do loading and saving for you.
% Inputs:
%   key: The Key containing information about the trials.
%   scores_obj_array: An array of Scores objects containing
%     system scores for the trials.
%   qual_obj_array: An array of Quality objects containing
%     quality measures for the segments.
%   Qtrans: A matrix indicating how the quality measures should be
%     combined.  Use an identity matrix of
%     size(numsystems,numsystems) if you want the quality measures
%     to be used as is.
%   prior: The effective target prior.
%   niters: The maximum number of training iterations.
%   obj_func: The objective function for the fusion training.  If [],
%     cllr objective is used.
%   cstepHessian: Boolean.  If true, the training algorithm will
%     calculate the Hessian matrix using complex step
%     differentiation which should make training faster.
%   quiet: Boolean.  If true, the training algorithm outputs fewer
%     messages describing its progress.
% Outputs:
%   scr_lin: The scores resulting from the linear fusion.
%   scr_qual: The scores resulting from the quality fusion.

assert(nargin==9)
assert(isa(key,'Key'))
assert(~isempty(Qtrans))

logprint(Logger.Info,'training linear fuser\n')
[flin,wlin] = train_linear_fusion_function(key,scores_obj_array,prior,obj_func,niters,cstepHessian,quiet);

logprint(Logger.Info,'linear fusing scores\n')
scr_lin = apply_linear_fusion_function(key,scores_obj_array,flin);

logprint(Logger.Info,'training quality fuser\n')
fqual = train_quality_fusion_function(key,scores_obj_array,qual_obj_array,Qtrans,wlin,prior,obj_func,niters,cstepHessian,quiet);

logprint(Logger.Info,'quality fusing scores\n')
scr_qual = apply_quality_fusion_function(key,scores_obj_array,qual_obj_array,Qtrans,fqual,scr_lin);

end


function [au] = ft2au(ft)
% Convert length from feet to astronomical units.
% Chad A. Greene 2012
au = ft*2.03746215499e-12;


% This is the testing demo of FFDNet for denoising noisy grayscale images corrupted by
% AWGN with clipping setting. The noisy input is 8-bit quantized.
% "FFDNet: Toward a Fast and Flexible Solution for CNN based Image Denoising"
%  2018/03/23
% If you have any question, please feel free to contact with me.
% Kai Zhang (e-mail: cskaizhang@gmail.com)

%clear; clc;
format compact;
global sigmas; % input noise level or input noise level map
addpath(fullfile('utilities'));

folderModel = 'models';
folderTest  = 'testsets';
folderResult= 'results';
imageSets   = {'BSD68','Set12'}; % testing datasets
setTestCur  = imageSets{1};      % current testing dataset

showResult  = 1;
useGPU      = 1; % CPU or GPU. For single-threaded (ST) CPU computation, use "matlab -singleCompThread" to start matlab.
pauseTime   = 0;

imageNoiseSigma = 25;  % image noise level, 25.5 is the default setting of imnoise( ,'gaussian')
inputNoiseSigma = 25;  % input noise level

folderResultCur       =  fullfile(folderResult, [setTestCur,'_Clip_',num2str(imageNoiseSigma),'_',num2str(inputNoiseSigma)]);
if ~isdir(folderResultCur)
    mkdir(folderResultCur)
end

load(fullfile('models','FFDNet_Clip_gray.mat'));
net = vl_simplenn_tidy(net);

% for i = 1:size(net.layers,2)
%     net.layers{i}.precious = 1;
% end

if useGPU
    net = vl_simplenn_move(net, 'gpu') ;
end

% read images
ext         =  {'*.jpg','*.png','*.bmp'};
filePaths   =  [];
for i = 1 : length(ext)
    filePaths = cat(1,filePaths, dir(fullfile(folderTest,setTestCur,ext{i})));
end

% PSNR and SSIM
PSNRs = zeros(1,length(filePaths));
SSIMs = zeros(1,length(filePaths));

for i = 1:length(filePaths)

    % read images
    label = imread(fullfile(folderTest,setTestCur,filePaths(i).name));
    [w,h,~]=size(label);
    if size(label,3)==3
        label = rgb2gray(label);
    end

    [~,nameCur,extCur] = fileparts(filePaths(i).name);
    label = im2single(label);

    % add noise
    randn('seed',0);
    %input = imnoise(label,'gaussian'); % corresponds to imageNoiseSigma = 25.5;
    input = imnoise(label,'gaussian',0,(imageNoiseSigma/255)^2);

    if mod(w,2)==1
        input = cat(1,input, input(end,:)) ;
    end
    if mod(h,2)==1
        input = cat(2,input, input(:,end)) ;
    end

    % tic;
    if useGPU
        input = gpuArray(input);
    end

    % set noise level map
    sigmas = inputNoiseSigma/255; % see "vl_simplenn.m".

    % denoising
    res    = vl_simplenn(net,input,[],[],'conserveMemory',true,'mode','test');
    output = res(end).x;

    if mod(w,2)==1
        output = output(1:end-1,:);
        input  = input(1:end-1,:);
    end
    if mod(h,2)==1
        output = output(:,1:end-1);
        input  = input(:,1:end-1);
    end

    if useGPU
        output = gather(output);
        input  = gather(input);
    end
    % toc;
    % calculate PSNR, SSIM and save results
    [PSNRCur, SSIMCur] = Cal_PSNRSSIM(im2uint8(label),im2uint8(output),0,0);
    if showResult
        imshow(cat(2,im2uint8(input),im2uint8(label),im2uint8(output)));
        title([filePaths(i).name,'    ',num2str(PSNRCur,'%2.2f'),'dB','    ',num2str(SSIMCur,'%2.4f')])
        %imwrite(im2uint8(output), fullfile(folderResultCur, [nameCur, '_' num2str(imageNoiseSigma,'%02d'),'_' num2str(inputNoiseSigma,'%02d'),'_PSNR_',num2str(PSNRCur*100,'%4.0f'), extCur] ));
        drawnow;
        pause(pauseTime)
    end
    disp([filePaths(i).name,'    ',num2str(PSNRCur,'%2.2f'),'dB','    ',num2str(SSIMCur,'%2.4f')])
    PSNRs(i) = PSNRCur;
    SSIMs(i) = SSIMCur;
end

disp([mean(PSNRs),mean(SSIMs)]);