function gaps = findRootNPmets(model, findNCmets)
% Finds the root no production (and no consumption)
% metabolites in a model, used by `gapFind`
%
% USAGE:
%
%    gaps = findRootNPmets(model, findNCmets)
%
% INPUT:
%    model          a COBRA model
%
% OPTIONAL INPUT:
%    findNCmets:    find no consumption mets as well as no production (default = false)
%
% OUTPUT:
%    gaps:          all root no production metabolites
%
% .. Author: - Jeff Orth 7/15/09

if nargin < 2
    findNCmets = false;
end

isRootNPmet = zeros(length(model.mets),1);

for i = 1:length(model.mets)
    row = find(model.S(i,:)); %which rxns this met participates in
    rowR = ismember(row,find(model.lb < 0)); %reversible rxns
    if any(model.S(i,row) > 0) %if met is produced by any reaction
        %don't do anything
    elseif any(rowR) %if met is in any reverible rxns
        %don't do anything
    else
        isRootNPmet(i) = 1;
    end
end

if findNCmets

    isRootNCmet = zeros(length(model.mets),1);

    for i = 1:length(model.mets)
        row = find(model.S(i,:)); %which rxns this met participates in
        rowR = ismember(row,find(model.lb < 0)); %reversible rxns
        if any(model.S(i,row) < 0) %if met is consumed by any reaction
            %don't do anything
        elseif any(rowR) %if met is in any reverible rxns
            %don't do anything
        else
            isRootNCmet(i) = 1;
        end
    end
end

if findNCmets
    gaps = model.mets((isRootNPmet+isRootNCmet)>=1);
else
    gaps = model.mets(isRootNPmet==1);
end


function a = lt( x, y )

%   Disciplined convex programming information for LT (<):
%      The left-hand side of a less-than constraint must be convex. The
%      right-hand side must be concave. Of course, real constant and
%      affine expressions are both convex and concave and can be used on
%      either side as well.
%
%   Disciplined geometric programming information for LT (<):
%      The left-hand side of a less-than constraint must be log-convex,
%      including positive constants, monomials, posynomials, generalized
%      posynomials, and products thereof. The right-hand side must be
%      log-concave---including positive constants, monomials,
%      reciprocals of log-convex expressions, and products thereof.
%
%   Note that CVX does not distinguish between strict less-than (<) and
%   less-than-or-equal (<=) constraints; they are treated identically.
%   Feasible interior-point solvers tend to return points which satisfy
%   strict inequality, but not all solvers do.

evalin( 'caller', 'cvx_verify' );
b = cvx_pushcnstr( x, y, '<' );
if nargout, a = b; end

% Copyright 2005-2014 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


% NIFTI Object
%
%   create     - Create a NIFTI-1 file
%   disp       - Disp a NIFTI-1 object
%   display    - Display a NIFTI-1 object
%   fieldnames - Fieldnames of a NIFTI-1 object
%   nifti      - Create a NIFTI-1 object
%   subsasgn   - Subscript assignment
%   subsref    - Subscript referencing
%
%   other operations are unlikely to work.
%
% Example usage.
%
% % Example of creating a simulated .nii file.
% dat            = file_array;
% dat.fname = 'junk.nii';
% dat.dim     = [64 64 32];
% dat.dtype  = 'FLOAT64-BE';
% dat.offset  = ceil(348/8)*8;
%
% % alternatively:
% % dat = file_array( 'junk.nii',dim,dtype,off,scale,inter)
%
% disp(dat)
%
% % Create an empty NIFTI structure
% N = nifti;
%
% fieldnames(N) % Dump fieldnames
%
% % Creating all the NIFTI header stuff
% N.dat = dat;
% N.mat = [2 0 0 -110 ; 0 2 0 -110; 0 0 -2 92; 0 0 0 1];
% N.mat_intent = 'xxx'; % dump possibilities
% N.mat_intent = 'Scanner';
% N.mat0 = N.mat;
% N.mat0_intent = 'Aligned';
%
% N.diminfo.slice = 3;
% N.diminfo.phase = 2;
% N.diminfo.frequency = 2;
% N.diminfo.slice_time.code='xxx'; % dump possibilities
% N.diminfo.slice_time.code = 'sequential_increasing';
% N.diminfo.slice_time.start = 1;
% N.diminfo.slice_time.end = 32;
% N.diminfo.slice_time.duration = 3/32;
%
% N.intent.code='xxx' ; % dump possibilities
% N.intent.code='FTEST'; % or N.intent.code=4;
% N.intent.param = [4 8];
%
% N.timing.toffset = 28800;
% N.timing.tspace=3;
% N.descrip = 'This is a NIFTI-1 file';
% N.aux_file='aux-file-name.txt';
% N.cal = [0 1];
%
% create(N); % Writes hdr info
%
% dat(:,:,:)=0; % Write out the data as all zeros
%
% [i,j,k] = ndgrid(1:64,1:64,1:32);
% dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 30^2))=1; % Write some ones in the file
% dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 15^2))=2;
%
%
% % displaying a slice
% imagesc(dat(:,:,12));colorbar
%
% % get a handle to 'junk.nii';
% M=nifti('junk.nii');
%
% imagesc(M.dat(:,:,12));
%
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

%
% $Id: Contents.m 2696 2009-02-05 20:29:48Z guillaume $


%MDL_IRB140 Create model of ABB IRB 140 manipulator
%
% MDL_IRB140 is a script that creates the workspace variable robot which
% describes the kinematic characteristics of an ABB IRB 140 manipulator
% using standard DH conventions.
%
% Also define the workspace vectors:
%   qz         zero joint angle configuration
%   qr         vertical 'READY' configuration
%   qd         lower arm horizontal as per data sheet
%
% Reference::
% - "IRB 140 data sheet", ABB Robotics.
% - "Utilizing the Functional Work Space Evaluation Tool for Assessing a
%   System Design and Reconfiguration Alternatives"
%   A. Djuric and R. J. Urbanic
%
% Notes::
% - SI units of metres are used.
% - Unlike most other mdl_xxx scripts this one is actually a function that
%   behaves like a script and writes to the global workspace.
%
% See also SerialLink, mdl_fanuc10l, mdl_m16, mdl_motormanHP6, mdl_S4ABB2p8, mdl_puma560.

% MODEL: ABB, IRB140, 6DOF, standard_DH

% Copyright (C) 1993-2015, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com

function r = mdl_irb140()

    deg = pi/180;

    % robot length values (metres)
    d1 = 0.352;
    a1 = 0.070;
    a2 = 0.360;
    d4 = 0.380;
    d6 = 0.065;

    % DH parameter table
    %     theta d a alpha
    dh = [0 d1 a1  -pi/2
          0 0  a2  0
          0 0  0   pi/2
          0 d4 0   -pi/2
          0 0  0   pi/2
          0 d6 0   pi/2];

    % and build a serial link manipulator

    robot = SerialLink(dh, 'name', 'IRB 140', ...
        'manufacturer', 'ABB', 'ikine', 'nooffset');

    % place the variables into the global workspace
    if nargin == 1
        r = robot;
    elseif nargin == 0
        assignin('base', 'irb140', robot);
        assignin('base', 'qz', [0 0 0 0 0 0]); % zero angles
        assignin('base', 'qd', [0 -90 180 0 0 -90]*deg); % data sheet pose, horizontal
        assignin('base', 'qr', [0 -90 90 0 90 -90]*deg); % ready pose, arm up
    end
end


function origin = get_origin(this)
% Computes the origin of this image geometry.
%
%   Y = MrImageGeometry()
%   Y.get_origin()
%
% This is a method of class MrImageGeometry.
%
% OUT   Voxel indices x, y, z of the origin, i.e. those voxel who are
%       at location [0 0 0].
%
% EXAMPLE
%   origin = Y.get_origin()
%
%   See also MrImageGeometry demo/MrImageGeometry/definition_of_geometry

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

invA = inv(this.get_affine_matrix());
origin = invA(1:3,4);
end


function [W,BC,DV,Q,r,B] = voxelize(V,F,side,varargin)
  % VOXELIZE Given a mesh compute a voxelization of that mesh on a regular grid
  % fit to the bounding box.
  %
  % W = voxelize(V,F,side)
  % [W,BC,DV,Q] = voxelize(V,F,side,'ParameterName',ParameterValue, ...)
  %
  % Inputs:
  %   V  #V by 3 list of vertex positions
  %   F  #F by 3 list of triangle indices into V, expects counterclockwise
  %     orientation to produce outward pointing normal
  %   side  either the number of cells in the x direction or a triple
  %     containing the number of cells in each dimension
  %   Optional:
  %     'Pad'  followed by number of padding to add to each side. 1 would mean
  %       add one extra cell on the top, bottom, left, right, front, and back
  %       of bounding box lattice {0}.
  %     'Boundary'  followed by wether to consider any cell intersecting the
  %       mesh as inside {true}.
  %     'Interior'  followed by whether to consider any cell full inside the
  %        mesh as inside {true}
  %     'Closed'  followed by whether to assume mesh is closed when determining
  %       interior (avoid winding number computation, use flood filling)
  %     'Centers'  followed by prod(side) centers (e.g., already produced by
  %       call to previous call to voxel_grid.m)
  % Outputs:
  %   W  side(1) by side(2) by side(3) matrix with W(i,j,k) ~= if location
  %     cell centered at BC(i,j,k) overlaps with the volume of (V,F)
  %   BC  prod(side) by dim matrix of cell barycenters
  %   DV  side(1)+1 by side(2)+1 by side(3)+1 matrix of cell corner locations
  %   Q  #Q by 4 list of quads indexing DV
  %   r  dim-long list of voxel widths in each direction
  %
  % Known issues: the ouput surface mesh will contain non-manifold edges and
  % vertices at voxels that meet at such edges or vertices.
  %
  % Example:
  %   [W,BC,DV,Q] = voxelize(V,F,50);
  %   % Get triangles from quads
  %   DF = [Q(:,[1 2 3]);Q(:,[1 3 4])];
  %   % Remove unreferenced corners
  %   [SV,IM] = remove_unreferenced(DV,DF);
  %   % re-index
  %   SF = IM(DF);
  %   SQ = IM(Q);
  %
  %   [W,BC] = voxelize(V,F,50,'Pad',1);
  %   % Use matlab's isosurface to extract surface as triangle mesh
  %   BC = reshape(BC,[size(W) 3]);
  %   surf = isosurface(BC(:,:,:,1),BC(:,:,:,2),BC(:,:,:,3),W,0.5);
  %   DV = bsxfun(@plus,bsxfun(@times,bsxfun(@rdivide,surf.vertices-1, ...
  %     [size(W,2) size(W,1) size(W,3)]-1),max(BC)-min(BC)),min(BC));
  %   DF = surf.faces;
  %
  %
  % See also: bwboundaries, isosurface

  with_boundary = true;
  with_interior = true;
  pad_count = 0;
  closed = [];
  BC = [];
  % default values
  % Map of parameter names to variable names
  params_to_variables = containers.Map( ...
    {'Boundary','Interior','Pad','Centers','Closed'}, ...
    {'with_boundary','with_interior','pad_count','BC','closed'});
  v = 1;
  while v <= numel(varargin)
    param_name = varargin{v};
    if isKey(params_to_variables,param_name)
      assert(v+1<=numel(varargin));
      v = v+1;
      % Trick: use feval on anonymous function to use assignin to this workspace
      feval(@()assignin('caller',params_to_variables(param_name),varargin{v}));
    else
      error('Unsupported parameter: %s',varargin{v});
    end
    v=v+1;
  end
  if isempty(closed)
    closed = isempty(boundary_faces(F));
  end

  assert(any(size(side) == 1),'side should be a vector');
  % Make sure we have a row vector
  side = side(:)';

  dim = size(V,2);

  if isempty(BC)
    [BC,side,r] = voxel_grid(V,side,'Pad',pad_count);
  else
    assert(prod(side) == size(BC,1),'side dims must match BC');
    r = (max(BC)-min(BC))./(side-1);
  end
  NV = min(BC);
  XV = max(BC);

  switch dim
  case 2
    W  = zeros([side(2) side(1)]);
    [DV,~,QT,QL] = voxel_surface(W,'Centers',BC);

    if with_interior && ~closed
      WDV = reshape(winding_number(V,F,DV),[side(2) side(1)]+1);
      WDV = abs(WDV) >= 0.5;
      W = ( ...
        WDV(1:end-1,1:end-1) | ...
        WDV(1:end-1,  2:end) | ...
        WDV(  2:end,1:end-1) | ...
        WDV(  2:end,  2:end));
    end
    Q = [QT;QL];
    if with_boundary
      for ei = 1:size(F,1)

        sqrD = segment_segment_squared_distance( ...
          V(F(ei,1),:), V(F(ei,2),:), ...
          DV(Q(:,1),:), DV(Q(:,2),:));
        IF = mod(find(sqrD<eps)-1,size(Q,1))+1;
        iQT = IF(IF<=size(QT,1));
        iQL = IF(IF>size(QT,1))-size(QT,1);

        [II,JJ] = ind2sub([side(2) side(1)]+1,max(QT(iQT,:),[],2));
        W(sub2ind(side([2 1]),II-1,JJ-1)) = 1;
        W(sub2ind(side([2 1]),II  ,JJ-1)) = 1;

        [II,JJ] = ind2sub([side(2) side(1)]+1,max(QL(iQL,:),[],2));
        W(sub2ind(side([2 1]),II-1,JJ-1)) = 1;
        W(sub2ind(side([2 1]),II-1,JJ  )) = 1;

        %clf;
        %hold on;
        %surf(reshape(BC(:,1),size(W)),reshape(BC(:,2),size(W)),reshape(BC(:,1)*0,size(W)),'CData',W*1,fphong,'EdgeColor','none');
        %plot_edges(V,F(ei,:),'y','LineWidth',8);
        %plot_edges(V,F,'g','LineWidth',4);
        %text(BC(:,1),BC(:,2),num2str((1:size(BC,1))'),'BackgroundCOlor',[0.8 0.8 0.8]);
        %text(DV(:,1),DV(:,2),num2str((1:size(DV,1))'),'BackgroundCOlor',[0.8 0.1 0.1]);
        %plot_edges(DV,QT,'--r','LineWidth',1);
        %plot_edges(DV,QL,'--b','LineWidth',1);
        %plot_edges(DV,QT(iQT,:),'r','LineWidth',3);
        %plot_edges(DV,QL(iQL,:),'b','LineWidth',3);
        %hold off;
        %axis equal;
        %colormap([zeros(20,3);1 1 1]);
        %drawnow;

      end
    end
    if with_interior && closed
      W = imfill(W,'holes');
    end
    % Pad winding number with 0s and take differences in all 6 directions
    Wp = padarray(W,[1 1],0);
    Dy = diff(Wp,1,1);
    Dx = diff(Wp,1,2);
    Q = [ ...
      QL(Dx(2:end-1,1:end,2:end-1)>0.5,:); ...
      QT(Dy(1:end,2:end-1,2:end-1)>0.5,:); ...
      fliplr(QL(Dx(2:end-1,1:end,2:end-1)<-0.5,:)); ...
      fliplr(QT(Dy(1:end,2:end-1,2:end-1)<-0.5,:)); ...
      ];
  case 3
    W = zeros([side(2) side(1) side(3)]);
    [DV,~,QT,QF,QL] = voxel_surface(W,'Centers',BC);

    if with_interior && ~closed
      % Winding number is a heavy handed way of determining inside/outside for a
      % simple closed polyhedron.  If the boundary has already been detected then
      % this should be floodfilling instead.

      %W = winding_number(V,F,BC);
      WDV = reshape(winding_number(V,F,DV,'Fast',true),[side(2) side(1) side(3)]+1);
      WDV = abs(WDV) >= 0.5;
      W = ( ...
        WDV(1:end-1,1:end-1,1:end-1) | ...
        WDV(1:end-1,1:end-1,2:end) | ...
        WDV(1:end-1,  2:end,1:end-1) | ...
        WDV(1:end-1,  2:end,2:end) | ...
        WDV(  2:end,1:end-1,1:end-1) | ...
        WDV(  2:end,1:end-1,2:end) | ...
        WDV(  2:end,  2:end,1:end-1) | ...
        WDV(  2:end,  2:end,2:end));
    end

    Q = [QT;QF;QL];

    if with_boundary
      % TODO: Could at least ignore already-inside cells.
      DF = [Q(:,[3 2 1]);Q(:,[4 3 1])];
      IF = intersect_other(V,F,DV,DF);
      JF = IF(:,1);
      IF = mod(IF(:,2)-1,size(Q,1))+1;
      B = zeros(side(2),side(1),side(3));
      % Force winding number to mark voxels intersecting boundary as inside
      % (This should just be replaced with rasterizing the surface)
      iQ = cell(3,1);
      iQ{1} = IF(IF<=size(QT,1));
      iQ{3} = IF(IF>size(QT,1) & IF<=size(QT,1)+size(QF,1))-size(QT,1);
      iQ{2} = IF(IF>size(QT,1)+size(QF,1))-size(QT,1)-size(QF,1);
      jQ{1} = JF(IF<=size(QT,1));
      jQ{3} = JF(IF>size(QT,1) & IF<=size(QT,1)+size(QF,1));
      jQ{2} = JF(IF>size(QT,1)+size(QF,1));

      side123 = side([2 1 3]);
      for d = 1:3
        sz = side123;
        sz(d) = sz(d)+1;
        II = cell(3,1);
        [II{1},II{2},II{3}] = ind2sub(sz,iQ{d});
        for pass = 0:1
          II{d} = II{d}-pass;
          keep = II{d}<=side123(d);
          B(sub2ind(side123,II{1}(keep),II{2}(keep),II{3}(keep))) = jQ{d}(keep);
        end
      end

      W = W | B;
    end

    if with_interior && closed
      W = imfill(W,'holes');
    end

    %trisurf(Q(IF,:),DV(:,1),DV(:,2),DV(:,3),'FaceColor','r');
    %hold on;
    %tsurf(F,V,'FaceColor','g','FaceAlpha',0.2,'EdgeAlpha',0.2);
    %hold off;

    %% From cells to faces:
    %[II,JJ,KK] = ind2sub([side(2) side(1) side(3)],find(abs(W)>0.5));
    %Q = [ ...
    %  QT(sub2ind([side(2)+1 side(1)   side(3)  ],II+1,JJ,KK),:); ...
    %  QT(sub2ind([side(2)+1 side(1)   side(3)  ],II+0,JJ,KK),:); ...
    %  QF(sub2ind([side(2)   side(1)   side(3)+1],II,JJ,KK+1),:); ...
    %  QF(sub2ind([side(2)   side(1)   side(3)+1],II,JJ,KK+0),:); ...
    %  QL(sub2ind([side(2)   side(1)+1 side(3)  ],II,JJ+1,KK),:); ...
    %  QL(sub2ind([side(2)   side(1)+1 side(3)  ],II,JJ+0,KK),:); ...
    %  ];
    %trisurf(Q,DV(:,1),DV(:,2),DV(:,3),'FaceAlpha',0.5,'EdgeAlpha',0.5);
    %hold on;
    %tsurf(F,V,'FaceColor','g','FaceAlpha',0.2,'EdgeAlpha',0.2);
    %hold off;
    %axis equal
    %
    %error

    % Pad winding number with 0s and take differences in all 6 directions
    Wp = padarray(W,[1 1 1],0);
    Dy = diff(Wp,1,1);
    Dx = diff(Wp,1,2);
    Dz = diff(Wp,1,3);
    Q = [ ...
      QF(Dz(2:end-1,2:end-1,1:end)>0.5,:); ...
      QL(Dx(2:end-1,1:end,2:end-1)>0.5,:); ...
      QT(Dy(1:end,2:end-1,2:end-1)>0.5,:); ...
      fliplr(QF(Dz(2:end-1,2:end-1,1:end)<-0.5,:)); ...
      fliplr(QL(Dx(2:end-1,1:end,2:end-1)<-0.5,:)); ...
      fliplr(QT(Dy(1:end,2:end-1,2:end-1)<-0.5,:)); ...
      ];
  end
end


filename = 'SquareCantilever6400';%'CantileverSquareNew';%'CantileverSquareSym';%'CantileverSquareNewFine';%'LshapeTriFine';%'CantileverSquareNew';'ArchTriFine';%'CantileverSquare';%'ArchTriFine';%'CantileverSquare';%'Lshape';%'LshapeTriFine';%'CantileverSquareSmall';%'';%'Lshape';'CantileverSquare';'Lshape';%'CantileverSquare';%'LshapeFine';%'Bridge_quad_coarse';%'Arch_quad_coarse';%'BridgeCool_Quadrilateral_Bilinear_Structured_Coarse';%'Bridge';%'CantileverSquareSmall';
ptype = 'MACRO';
initial_case = 'given';
m1 = 0.0101;
m2 = 0.0101;
cost = {'compliance'};
%cost = {'stressNorm'};
%cost = {'stressNorm','compliance'};
%weights = [0.55,0.45];
weights = 1;
constraint = {'volumeConstraint'};
filterType = 'PDE';
constraint_case = 'EQUALITY';

Vfrac_initial = 0.3;
optimality_initial = 1e-5;
constr_initial = 1e-5;

Vfrac_final = 0.3;
optimality_final = 1e-5;
constr_final = 1e-5;

stressNormExponent_initial = 2;
stressNormExponent_final = 16;

optimizer = 'DualNestedInPrimal';
optimizerUnconstrained = 'PROJECTED GRADIENT';

designVariable = 'MicroParams';
ub = 0.989;
lb = 0.011;
homegenizedVariablesComputer = 'ByVademecum';
%
%vademecumFileName = 'SuperEllipseQMax';
%vademecumFileName = 'SuperEllipseQ2';
vademecumFileName = 'SuperEllipseQOptAnalytic';
%
% designVariable = 'Density';
% homegenizedVariablesComputer = 'ByInterpolation';
% method = 'SIMPALL';
% materialType = 'ISOTROPIC';

line_search_initiator = 'INCREASING LAST STEP';
incrementFactor = 1.95;
%

%kfrac = 2;
nsteps = 8;%17;

plotting = true;
printing = true;
monitoring = true;
monitoring_interval = 3;
maxiter = 800;

%
%
% % % %
% isDirichletPartX = @(x) x > -1e-12 & x < 0.1;
% %isDirichletPart1 = @(y) y > 0.20 & y < 0.30;
% isDirichletPart1 = @(y) y > 0.30 & y < 0.50;
% isDirichletPartY = @(y) isDirichletPart1(y) ;%| isDirichletPart2(y);
% isDirichletPart = @(x,y) isDirichletPartX(x) & isDirichletPartY(y);
% isNeumannPartX = @(x) x > (2-0.1) & x < (2+1e-12);
% isNeumannPartY = @(y) y > 0.00 & y < 0.1;
% isNeumannPart = @(x,y) isNeumannPartX(x) & isNeumannPartY(y);
%
% iNotOptimizable = @(coord) isDirichletPart(coord(:,1),coord(:,2)) | isNeumannPart(coord(:,1),coord(:,2));
%
% costDomainNotOptimizable       = {iNotOptimizable};
% constraintDomainNotOptimizable = {[]};
%
% isDesignVariableFixed.nodes  = iNotOptimizable;
% isDesignVariableFixed.values = @(x) [m1*ones(size(x,1),1);m2*ones(size(x,1),1)];


%

dbName = '/home/admin/databases/PLUTONS/wf/plutons';
ds = datasource('antelope',dbName);

%t1 = datenum('2010/2/27 6:35');
%t2 = datenum('2010/2/27 6:55');
%filterObj = filterobject('b',[0.033 0.2],3);
%stachan = {
% 'UTLO'   'BHZ'
% 'UTKH'   'BHZ'
% 'UTSA'   'BHZ'
% 'UTQU'   'BHZ'
% 'UTLV'   'BHZ'
% 'UTSM'   'BHZ'
% 'UTLL'   'SHZ'
% 'UTSS'   'SHZ'
% 'UTLA2'  'SHZ'
% 'UTSW'   'SHZ'
% 'UTMK'   'SHZ'
% 'UTCM'   'SHZ'
% 'UTCA'   'SHZ'
% 'UTZN'   'SHZ'
% 'UTTM'   'SHZ'}

%t1 = datenum('2009/9/22 22:47:10');
%t2 = datenum('2009/9/22 22:47:30');
t1 = datenum('2010/02/27 22:47:10');
t2 = datenum('2010/02/27 22:47:30');

filterObj = filterobject('b',[0.5 10],2);
stachan = {
'UTSM'   'BHZ'
'UTQU'   'BHZ'
'UTTM'   'SHZ'
'UTLA2'  'SHZ'
'UTCA'   'SHZ'
'UTLV'   'BHZ'
'UTCM'   'SHZ'
'UTSW'   'SHZ'
'UTSA'   'BHZ'
'UTZN'   'SHZ'
'UTSS'   'SHZ'
'UTMK'   'SHZ'
'UTLO'   'BHZ'
'UTLL'   'SHZ'
'UTKH'   'BHZ'
}

for n = 1:size(stachan,1)
    scnl = scnlobject(stachan(n,1),stachan(n,2),'','');
    try
        w(n) = waveform(ds,scnl,t1,t2);
    catch
        w(n) = waveform;
    end
end
f = find(get(w,'DATA_LENGTH')~=0);
w = w(f);

% APPLY RESPONSES TO ORIGINAL WAVEFORMS (SHORT PERIOD)

wFilt = filtfilt(filterObj,w);
wNew = response_apply(wFilt,filterObj,'antelope',dbName);

% for n =1:numel(w)
%     n
%     wFilt(n) = filtfilt(filterObj,w(n));
%     wNew(n) = response_apply(wFilt(n),filterObj,dbName);
% end
save

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% check one channel
n = 3;
figure
plot(wFilt(n),'r');
hold on;
plot(wNew(n),'b');
response_plot(get(wNew(n),'RESPONSE'),[0.01 50])

load
% compare all channels
cNew = correlation(wNew);
%cNew = xcorr(cNew);
%cNew = adjusttrig(cNew);
plot(cNew,'wig',0.6)
title('Filtered and corrected for instrument response','FontSize',16);
%print(gcf,'-dpsc2','demo_corrected.ps');

cFilt = correlation(wFilt);
plot(cFilt,'wig',.6)
title('Filtered only (30.5 - 10 Hz)','FontSize',16);
%print(gcf,'-dpsc2','demo_filtered.ps');

c = correlation(w);
plot(c,'wig',.6)
title('Raw','FontSize',16);
%print(gcf,'-dpsc2','demo_raw.ps');

%
% % compare all channels
% cNew = correlation(wNew);
% cNew = crop(cNew,[0 600]);
% cNew = xcorr(cNew,[100 300]);
% cNew = adjusttrig(cNew);
% plot(cNew,'wig',0.6)
% title('Filtered and corrected for instrument response','FontSize',16);
% print(gcf,'-dpsc2','demo_corrected.ps');
%
% cFilt = correlation(wFilt);
% cNew = crop(cFilt,[0 600]);
% plot(cFilt,'wig',.6)
% title('Filtered only (30-5 s)','FontSize',16);
% print(gcf,'-dpsc2','demo_filtered.ps');
%
% c = correlation(w);
% cNew = crop(c,[0 600]);
% plot(c,'wig',.6)
% title('Raw','FontSize',16);
% print(gcf,'-dpsc2','demo_raw.ps');
%
%


classdef linopConstraint
%LINOPCONSTRAINT Class for linop constraints.
%
%   A linop operates on a set of chebfuns and scalars (the "variables" of the
%   linop). An instance of this class may be assigned to the 'constraint'
%   property of a linop in order to impose a constraint on that variable (for
%   purposes of solving a linear system or eigenvalue problem).
%
%   Each LINOPCONSTRAINT object has a 'functional' property, which is a
%   chebmatrix of vertically concatenated functionalBlocks, and a 'values'
%   property, a vector of the same length. If u is the variable of the
%   linop, then the constraint imposed by object C is:
%
%        C.functional * u = C.values.
%
%   The preferred way to add contraints to a linop is through LINOP.ADDBC,
%   not through direct use of this class.
%
% See also LINOP, LINOP.ADDBC.

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

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %% CLASS PROPERTIES:
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    properties ( Access = public )
        functional    % applied to the variable to get values
        values        % constraint on the result of the functional
    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %% CLASS CONSTRUCTOR:
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    methods ( Access = public, Static = false )

        % Input a functional and a value to create a constraint, or create
        % an empty constraint if no inputs.
        function C = linopConstraint(op, vals)
            if ( nargin == 0 )
                return
            end
            C.functional = op;
            C.values = vals;
        end

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %% CLASS METHODS:
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    methods ( Access = public, Static = false )

        function n = length(C)
        %LENGTH    Number of constraints in the object.
            n = size(C.functional, 1);
        end

        function e = isempty(C)
        %ISEMPTY   True if no constraints in the object.
            e = isempty(C.functional);
        end

        function C = append(C, func, value)
        %APPEND    Insert an additional constraint.
        %   C = APPEND(C, FUNC, VAL) appends the constraint FUNC*u=VAL to the
        %   current list. If VAL is omitted, it defaults to zero.

            % Appending empty does nothing:
            if ( isempty(func) )
                return
            end

            % Check if func is of an allowed class.
            validateattributes(func, {'linBlock', 'chebmatrix'}, {})

            % Check the value.
            if ( nargin < 3 )
                value = 0;
            end
            validateattributes(value, {'double'}, {})

            C.functional = [ C.functional ; func ];
            C.values = [ C.values ; value ];
        end

        function C = uminus(C)
        %-   Negate the VALUES property of a LINOPCONSTRAINT.
        %   This is useful at the CHEBOP level, where we need different signs
        %   for the boundary conditions of a LINOP when we call LINOP(N) where N
        %   is a CHEBOP, compared to what we want when we call LINEARIZE() from
        %   within a Newton iteration. This is because when problems are solved
        %   with LINOP backslash, the solution to the problem is the output
        %   itself, while in a Newton iteration, we have to add the output of
        %   the LINOP solution to the current guess.
            C.values = -C.values;
        end

    end

end


function [text,AIC,BIC]=agarch_display(parameters,ll,vcv,epsilon,p,q,modelType,errorType)
% Display parameters, tstats, pvals, log-likelihood and AIC/BIC
% from estimates of a AGARCH(P,Q) or NAGARCH(P,Q) produced using agarch
%
% USAGE:
%   [TEXT] = agarch_display(PARAMETERS,LL,VCV,DATA,P,Q)
%   [TEXT,AIC,BIC] = agarch_display(PARAMETERS,LL,VCV,DATA,P,Q,MODELTYPE,ERRORTYPE)
%
% INPUTS:
%   PARAMETERS    - A 2+p+q column vector of parameters with
%                   [omega alpha(1) ... alpha(p) gamma beta(1) ... beta(q) [nu lambda]]'
%   LL            - The log likelihood at the optimum
%   VCV           - Variance-covariance matrix (Robust or inverse Hessian)
%   EPSILON       - Column of mean zero data used to fit the model
%   P             - Positive, scalar integer representing the number of
%                   symmetric innovations
%   Q             - Non-negative, scalar integer representing the number
%                   of lags of conditional variance (0 for ARCH)
%   MODEL_TYPE    - [OPTIONAL] The type of variance process, either
%                     'AGARCH'  - Asymmetric GARCH, Engle (1990) [DEFAULT]
%                     'NAGARCH' - Nonlinear Asymmetric GARCH, Engle & Ng (1993)
%   ERRORTYPE     - [OPTIONAL] The error distribution used, valid types are:
%                     'NORMAL'    - Gaussian Innovations [DEFAULT]
%                     'STUDENTST' - T distributed errors
%                     'GED'       - Generalized Error Distribution
%                     'SKEWT'     - Skewed T distribution
%
% OUTPUTS:
%   TEXT          - Character matrix with the formatted parameters of the model
%   AIC           - Aikake Information Criteria computed from the LL
%   BIC           - Schwartz/Bayesian Information Criteria computed from the LL
%
%  See also AGGARCH

% Copyright: Kevin Sheppard
% kevin.sheppard@economics.ox.ac.uk
% Revision: 1    Date: 7/12/2005

%%%%%%%%%%%%%%%%%%%%%%%%%%
% PARAMETER CHECKING
%%%%%%%%%%%%%%%%%%%%%%%%%%
switch nargin
    case 5
        q=0;
        modelType = 'AGARCH';
        errorType = 'NORMAL';
    case 6
        modelType = 'AGARCH';
        errorType = 'NORMAL';
    case 7
        errorType = 'NORMAL';
    case 8
    otherwise
        error('5 to 8 inputs required')
end

% parameters, N by 1, real
if any(~isreal(parameters)) || size(parameters,2)~=1
    error('PARAMETERS must be a column vector.')
end
% LL
if ~isscalar(ll) || ~isreal(ll)
    error('LL must be a scalar.')
end
% VCV
if size(vcv,2)~=size(vcv,1) || any(min(eig(vcv))<=0) || size(vcv,1)~=length(parameters)
    error('VCV must be a square positive definite matrix compatible with PARAMETERS.')
end
% epsilon
if any(~isreal(epsilon)) || size(epsilon,2)~=1
    error('EPSILON must be a T by 1 column vector.')
end
% p
if ~isscalar(p) || p<1 || floor(p)~=p
    error('P must be a postitive scalar integer')
end
% q
if ~isscalar(q) || q<0 || floor(q)~=q
    error('Q must be a non-negative scalar integer')
end
% errorType
if ~ischar(errorType)
    errorType=[];
end
if isempty(errorType)
    errorType='NORMAL';
end
errorType = upper(errorType);
switch errorType
    case 'NORMAL'
        errorType=1;
        extraP=0;
    case 'STUDENTST'
        errorType=2;
        extraP=1;
    case 'GED'
        errorType=3;
        extraP=1;
    case 'SKEWT'
        errorType=4;
        extraP=2;
    otherwise
        error('ERRORTYPE is not one of the supported distributions')
end
% modelType
modelType
if ~ischar(modelType)
    modelType=[];
end
modelType = upper(modelType);
if isempty(modelType)
    modelType='AGARCH';
end
switch modelType
    case 'AGARCH'
        modelType=1;
    case 'NAGARCH'
        modelType=2;
    otherwise
        error('MODELTYPE must be either ''AGARCH'' or ''NAGARCH''.')
end

if length(parameters)~=(2+p+q+extraP)
    error('Size of PARAMETERS is not compatible with input P and Q')
end
%%%%%%%%%%%%%%%%%%%%%%%%%%
% PARAMETER CHECKING
%%%%%%%%%%%%%%%%%%%%%%%%%%

if modelType == 1
    model_name = ['AGARCH(' num2str(p) ',' num2str(q) ')'];
else
    model_name = ['NAGARCH(' num2str(p) ',' num2str(q) ')'];
end

parameters_text=num2str(parameters,'%4.4f');
stderr=sqrt(diag(vcv));
stderr_text=num2str(stderr,'%4.4f');
tstats=parameters./stderr;
tstats_text=num2str(tstats,'%4.4f');
pvals=2-2*normcdf(abs(tstats));
pvals_text=num2str(pvals,'%4.4f');

T=length(epsilon);
AIC = -ll/T+2*length(parameters)/T;
BIC = -ll/T+log(T)*length(parameters)/T;

% Format the output
text=[];
text{1,1}= ' ';
text{2,1}= ' ';
text{3,1}=repmat('-',1,50);
text{4,1}=model_name;
text{5,1}=repmat('-',1,50);
text{6,1}=' ';
text{7,1}=['Loglikelihood: ' sprintf('%1.2f',ll)];
text{8,1}=['AIC: ' sprintf('%1.4f',AIC)];
text{9,1}=['BIC: ' sprintf('%1.4f',BIC)];
text{10,1}=' ';

for i=1:size(text,1);
    disp(text{i,1})
end

% Format the parameter table, need to right align everything
K=size(parameters_text,1);
for i=1:K
    N=size(parameters_text,2);
    if any(parameters_text(i,:)==' ')
        numSpace=sum(parameters_text(i,:)==' ');
        parameters_text(i,:)=[repmat(' ',1,numSpace) parameters_text(i,1:N-numSpace)];
    end
    N=size(stderr_text,2);
    if any(stderr_text(i,:)==' ')
        numSpace=sum(stderr_text(i,:)==' ');
        stderr_text(i,:)=[repmat(' ',1,numSpace) stderr_text(i,1:N-numSpace)];
    end
    N=size(tstats_text,2);
    if any(tstats_text(i,:)==' ')
        numSpace=sum(tstats_text(i,:)==' ');
        tstats_text(i,:)=[repmat(' ',1,numSpace) tstats_text(i,1:N-numSpace)];
    end
    N=size(pvals_text,2);
    if any(pvals_text(i,:)==' ')
        numSpace=sum(pvals_text(i,:)==' ');
        pvals_text(i,:)=[repmat(' ',1,numSpace) pvals_text(i,1:N-numSpace)];
    end
end
% Append column labels
labels={' Parameters','   Std. Err.','     T-stat','      P-val'};
cols = {parameters_text,stderr_text,tstats_text,pvals_text};
for i=1:length(labels);
    text1=labels{i};
    text2=cols{i};
    maxcols=max(size(text1,2),size(text2,2));
    if size(text1,2)<maxcols
        labels{i} = [repmat(' ',1,maxcols-size(text1,2)) text1 ];
    end
    if size(text2,2)<maxcols
        cols{i} = [repmat(' ',size(text2,1),maxcols-size(text2,2)) text2 ];
    end
end

% Finally variable names
variable_names=cell(length(parameters),1);
variable_names{1}='omega';
index=2;
for i=1:p
    variable_names{index}=['alpha(' num2str(i) ')'];
    index=index+1;
end
variable_names{index}=['gamma'];
index=index+1;
for i=1:q
    variable_names{index}=['beta(' num2str(i) ')'];
    index=index+1;
end

maxVarNameLength=max(cellfun('length',variable_names));
for i=1:length(variable_names)
    variable_names{i} = [repmat(' ',1,maxVarNameLength-length(variable_names{i})) variable_names{i}];
end
variable_names=cell2mat(variable_names(:));

% Output the parameters
outmat=strvcat(' ',variable_names);
for i=1:4
    outmat=[outmat repmat('  ',size(outmat,1),1) strvcat(labels{i},cols{i})];
end

text2=[];
for i=1:length(text)
    text2=strvcat(text2,text{i});
end
text=strvcat(text2,outmat);

disp(outmat)


function opt = hmc2_opt(opt)
%HMC2_OPT  Default options for Hybrid Monte Carlo sampling.
%
%  Description
%    OPT = HMC2_OPT
%      return default options
%    OPT = HMC2_OPT(OPT)
%      fill empty options with default values
%
%  The options and defaults are
%    display (0)
%      1 to display the energy values and rejection threshold at
%        each step of the Markov chain
%      2 to display also position vectors at each step
%    checkgrad (0)
%      1 to check the user defined gradient function
%    steps (10)
%      Defines the trajectory length (i.e. the number of leapfrog
%      steps at each iteration)
%    nsamples (1)
%      the number of samples retained from the Markov chain
%    nomit (0)
%      the number of samples omitted from the start of the chain
%    persistence (0)
%      0 for complete replacement of momentum variables
%      1 if momentum persistence is used
%    decay (0.9)
%      defines the decay used when a persistent update of
%      (leap-frog) momentum is used. Bounded to the interval [0, 1.)
%    stepadj (0.1)
%      the step adjustment used in leap-frogs
%    stepsf ([])
%      the step size function
%    window (1)
%      the size of the acceptance window
%
%  See also
%    HMC2

%	Copyright (c) Aki Vehtari (1998)

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

if nargin < 1
  opt=[];
end

if ~isfield(opt,'display')
  opt.display=0;
end
if ~isfield(opt,'checkgrad')
  opt.checkgrad=0;
end
if ~isfield(opt,'steps') | opt.steps < 1
  opt.steps=10;
end
if ~isfield(opt,'nsamples') | opt.nsamples < 1
  opt.nsamples=1;
end
if ~isfield(opt,'nomit') | opt.nomit < 0
  opt.nomit=0;
end
if ~isfield(opt,'persistence')
  opt.persistence=0;
end
if ~isfield(opt,'decay') | opt.decay < 0 | opt.decay > 1
  opt.decay=0.9;
end
if ~isfield(opt,'stepadj')
  opt.stepadj=0.1;
end
if ~isfield(opt,'stepsf')
  opt.stepsf=[];
end
if ~isfield(opt,'window') | opt.window < 0
  opt.window=1;
end
if opt.window > opt.steps
  opt.window=opt.steps;
end


function [l,m] =  findnei(k)
    % This script finds overlapping alarms in space-time
    % and groups them togetehr
    %
    % Stefan Wiemer    4/95
    global abo iala

    report_this_filefun(mfilename('fullpath'));

    d = sqrt(((abo(k,1) - abo(:,1))).^2 + ((abo(k,2) - abo(:,2))).^2);
    m = d < abo(:,3)+abo(k,3) &  abs(abo(:,5)-abo(k,5)) < iala;
    l = find(m == 1);


function [P,Y] = preprocess_data(Y,p,options)
% PREPROCESS_DATA - Preprocess data for CNMF analysis of image signals
%
%   [P_PARMS,Y] = PREPROCESS_DATA(Y, P_ORDER, OPTIONS)
%
% Inputs:
%    Y - the image data to be examined
%    P_ORDER - The order of the autoregressive system
%    OPTIONS - A structure of options (see help CNMFSetParms)
%
% Outputs:
%    P_PARMS - A structure of parameters extracted from the pre-processed data
%    P_PARMS has the following fields:
%
%       Fieldname:                       | Description
%       --------------------------------------------------------------------------
%       p                                |  P_ORDER as above
%       mis_data                         |  Index locations of missing (NaN) values in Y
%       mis_values                       |  Interpolated values at the missing index locations
%       pixels                           |  Index values of pixels that are not saturated
%       sn                               |  Noise power of each pixel
%       g                                |  Autoregressive model parameters
%
%    Y - A processed version of the data Y with the following changes:
%      (i)   identifying and interpolating missing entries (assumed to have the
%            value NaN). Interpolated entries are passed back to Y.
%      (ii)  identifying saturated pixels
%      (iii) estimating noise level for every pixel
%      (iv)  estimating global discrete time constants (if needed)
%
% This function replaces ARPFIT, present in the previous versions of the code.
%

% Author: Eftychios A. Pnevmatikakis
%           Simons Foundation, 2015

defoptions = CNMFSetParms;

if nargin < 3 || isempty(options); options = defoptions; end
if nargin < 2 || isempty(p); p = 2; end
P.p = p;

if ~isfield(options,'noise_range'); options.noise_range = defoptions.noise_range; end
if ~isfield(options,'noise_method'); options.noise_method = defoptions.noise_method; end
if ~isfield(options,'block_size'); options.block_size = defoptions.block_size; end
if ~isfield(options,'flag_g'); options.flag_g = defoptions.flag_g; end
if ~isfield(options,'lags'); options.lags = defoptions.lags; end
if ~isfield(options,'include_noise'); options.include_noise = defoptions.include_noise; end; include_noise = options.include_noise;
if ~isfield(options,'split_data'); split_data = defoptions.split_data; else split_data = options.split_data; end
if ~isfield(options,'cluster_pixels'); cluster_pixels = defoptions.cluster_pixels; else cluster_pixels = options.cluster_pixels; end
if ~isfield(options,'extract_max'); extract_max = defoptions.extract_max; else extract_max = options.extract_max; end
if ~isfield(options,'max_nlocs'); options.max_nlocs = defoptions.max_nlocs; end
if ~isfield(options,'max_width'); options.max_width = defoptions.max_width; end

%% interpolate missing data

if any(isnan(Y(:)))
    Y_interp = interp_missing_data(Y);      % interpolate missing data
    mis_data = find(Y_interp);
    Y(mis_data) = Y_interp(mis_data);       % introduce interpolated values for initialization
else
    Y_interp = sparse(size(Y));
    mis_data = [];
end
P.mis_values = full(Y_interp(mis_data));
P.mis_entries = mis_data;

%% indentify saturated pixels

P.pixels = find_unsaturatedPixels(Y);                % pixels that do not exhibit saturation

%% estimate noise levels

fprintf('Estimating the noise power for each pixel from a simple PSD estimate...');
[sn,psx] = get_noise_fft(Y,options);
P.sn = sn(:);
fprintf('  done \n');

%% cluster pixels based on PSD
if cluster_pixels
    psdx = sqrt(psx(:,3:end-1));
    X = psdx(:,1:min(size(psdx,2),1500));
    P.psdx = X;
    X = bsxfun(@minus,X,mean(X,2));     % center
    X = bsxfun(@times,X,1./sqrt(mean(X.^2,2)));
    [L,Cx] = kmeans_pp(X',2);
    [~,ind] = min(sum(Cx(max(1,end-49):end,:),1));
    P.active_pixels = (L==ind);
    P.centroids = Cx;

    if (0) % not necessary at the moment
        %[P.W,P.H] = nnmf(psdx,2); %,'h0',H0);
        psdx = psdx(:,1:min(size(psdx,2),600));
        r = sort(rand(1,size(psdx,2)),'descend');
        er = ones(1,length(r))/sqrt(length(r));
        H = [r/norm(r); er];
        W_ = rand(size(psdx,1),2);
        for iter = 1:100
            W = max((H*H')\(H*psdx'),0)';
            %H = max((W'*W)\(W'*psdx),0);
            r = max((W(:,1)'*psdx - (W(:,1)'*W(:,2))*er)/norm(W(:,1))^2,0);
            H = [r/norm(r); er];
            if norm(W-W_,'fro')/norm(W_,'fro') < 1e-3
                break;
            else
                W_ = W;
            end
        end
        disp(iter)
        W = max((H*H')\(H*psdx'),0)';
        P.W = W;
        P.H = H;
    end
end

%% extract maximum activity for each pixel
if extract_max
    [LOCS,Ym] = extract_max_activity(Y,options.max_nlocs,options.max_width);
    P.max_locs = LOCS;
    P.max_data = Ym;
end
%% estimate global time constants

if options.flag_g
    if ndims(Y) == 3
        Y = reshape(Y,size(Y,1)*size(Y,2),size(Y,3));
    end

    ff = options.pixels;
    np = length(ff);

    fprintf('Estimating time constant through autocorrelation function.. \n');
    tt1 = tic;
    mp = max(p);
    lags = options.lags + mp;
    if split_data
        Ycl = mat2cell(Y(ff,:),ones(np,1),size(Y,2));
        XC = cell(np,1);
        parfor j = 1:np
            XC{j} = xcov(Ycl{j},lags,'biased');
        end
        XC = cell2mat(XC);
    else
        XC = zeros(np,2*lags+1);
        for j = 1:np
            XC(j,:) = xcov(Y(ff(j),:),lags,'biased');
        end
    end

    gv = zeros(np*lags,1);
    if ~include_noise
        g =  XC(:,lags:-1:1);
        clear XC;
        lags = lags - p;
    end
    A = zeros(np*lags,p);
    for i = 1:np
        if ~include_noise
            A((i-1)*lags + (1:lags),:) = toeplitz(g(i,p:p+lags-1),g(i,p:-1:1));
        else
            A((i-1)*lags + (1:lags),:) = toeplitz(XC(i,lags+(1:lags)),XC(i,lags+(1:p))) - sn(i)^2*eye(lags,p);
            gv((i-1)*lags + (1:lags)) = XC(i,lags+2:end)';
        end
    end
    if ~include_noise
        gv = g(:,p+1:end)';
    end
    %ph = pinv(A)*gv(:);
    ph = A\gv(:);
    disp(ph);
    fprintf('Done after %2.2f seconds. \n',toc(tt1));
    P.g = ph(:);
end


% This subroutine assigns Parameter values for the grid
% which is used to calculate a Max Z value map.
% dx, dy is the grid spacing in degrees.
% For each one of the grid points, Ni events are counted.
%

report_this_filefun(mfilename('fullpath'));

% initial values
%
dx = 1.00;
dy = 1.00 ;
dz = 10.00 ;
ni = 100;

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

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

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

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

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

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

uicontrol('Units','normal','Position',[.1 .90 .15 .12],'String','LoadGrid', 'Callback','close;loadgrid')

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

go_button1=uicontrol('Style','Pushbutton',...
    'Position',[.20 .05 .15 .12 ],...
    'Units','normalized',...
    'Callback',' gomakegr',...
    'String','ZmapGrid');

go_button2=uicontrol('Style','Pushbutton',...
    'Position',[.40 .05 .15 .12 ],...
    'Units','normalized',...
    'Callback','close;think; genascum',...
    'String','GenasGrid');

txt3 = text(...
    'Color',[0 0 0 ],...
    'EraseMode','normal',...
    'Position',[0.30 0.94 0 ],...
    'Rotation',0 ,...
    'FontSize',ZmapGlobal.Data.fontsz.l ,...
    'FontWeight','bold',...
    'String',' Grid Parameter ');

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

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

text(...
    'Color',[0 0 0 ],...
    'EraseMode','normal',...
    'Position',[0. 0.20 0 ],...
    'Rotation',0 ,...
    'FontSize',ZmapGlobal.Data.fontsz.m ,...
    'FontWeight','bold',...
    'String','Time steps in days:');

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

text(...
    'Color',[0 0 0 ],...
    'EraseMode','normal',...
    'Position',[0. 0.63 0 ],...
    'Rotation',0 ,...
    'FontSize',ZmapGlobal.Data.fontsz.m,...
    'FontWeight','bold',...
    'String','Depth increment in (km) :');

set(gcf,'visible','on');
watchoff


function [result_features]=back_find_high_node(W,C,nROI,w,midw_lasso,IDX,opt_t)

% This function aims to find features used in the classification, suitable
% for the dHOFC network construction method. And it is also
% suitable for the LOOCV or the 10-fold cross validation. The found
% features can be applied on the visualization software to present the
% important high-order nodes (a set of links in each high-order node).
% Input:
%         W: window length
%         C: number of cluster
%         nROI: number of ROIs
%         w: weight of each selected features;
%         midw_lasso: the feature selection indexes of lasso;
%         IDX: the index in clustering;
%         opt_t: the selected feat in each outer LOOCV;
% Output:
%        result_features: cell array, consisting of occurrence of the features,
%        node number, the cluster matrix and weight of the cluster;

% Written by Zhen Zhou, zzstefan@email.unc.edu
% IDEA lab, https://www.med.unc.edu/bric/ideagroup
% Department of Radiology and BRIC, University of North Carolina at Chapel Hill

%
% load dHOFC_loocv_middle.mat;
%load dHOFC_kfold_middle.mat;
fprintf('Begin contributing feature identification\n');

for i =1:size(midw_lasso,1)
    for j=1:size(midw_lasso,2)
        which_C=ceil(opt_t(i,j)/length(W));
        which_W=mod(opt_t(i,j),length(W));
        if which_W ==0
            which_W=length(W);
        end
        index{i,j}=IDX{which_W,which_C};
        high_index{i,j}=find(midw_lasso{i,j}~=0);
    end
end
%% index means the corresponding cluster number of each of the 6670 lines in the original low-order FC;
%% high_index ,each LOOCV ,there is one combination of hyper-parameter constructed brain network being choosen,
%% find the cluster number after feature selection

index=index(:);
high_index=high_index(:);
for i=1:length(high_index)
    for j=1:length(high_index{i})
        tmp{i,j}=find(index{i}==high_index{i}(j));
    end
    %length_test(i)=length(find(~cellfun(@isempty,tmp(i,:))));
end

% B=unique(length_test);
% for i=1:length(B)
%     A(i)=length(find(length_test==B(i)));
% end

%% find the frequency of each element in the cell array
tmp=cellfun(@(x) x',tmp,'UniformOutput',false);
temp=tmp(:);

[a1,b,c]=unique(cellfun(@char,temp,'un',0));
lo=histc(c,1:max(c));
loo=lo(:)>1;
out=[temp(b(loo)),num2cell(lo(loo))];
out(1,:)=[];
new_out=out;

%% find the weight of each cluster and the averaged accuracy would be the mean weight for each cluster.
for k=1:length(new_out)
    weight=[];
    test{k}=cellfun(@(x)isequal(x,new_out{k}),tmp,'un',0);
    [location{k}(:,1),location{k}(:,2)]=find(cell2mat(test{k}));
    for j=1:length(location{k})
        weight=[weight,w{location{k}(j,1)}(location{k}(j,2))];
    end
    W(k)=mean(weight);
end

for j=1:length(new_out)
    inner_tmp=new_out{j};
    for i=1:length(inner_tmp)
        [first{j}(i,1),first{j}(i,2)]=find_elements(116,new_out{j,1}(i));
    end
    new_out(j,3)=first(j);
end

%%according to the connection between ROI, create the 0-1 matrix for the
%%convenience of drawing in brainnet viewer

%Matrix=create_matrix(first);

for m=1:length(first)
    node_matrix{m}=zeros(nROI,nROI);
    for n=1:length(first{m})
        node_matrix{m}(first{m}(n,1),first{m}(n,2))=1;
        node_matrix{m}(first{m}(n,2),first{m}(n,1))=1;
    end
end

% nROI=116;
% node_matrix=eye(nROI,nROI);
% for m=1:length(test)
%
%         node_matrix(test{m}(:,1),test{m}(:,2))=1;
%         node_matrix(test{m}(:,2),test{m}(:,1))=1;
%
% end

result_features(:,1)=new_out(:,2);
result_features(:,2)=new_out(:,3);
result_features(:,3)=node_matrix';
result_features(:,4)=num2cell(W);
%result_features=sortrows(result_features,1,'descend');%% sort according to the frequency of each cluster ,descend
result_features=sortrows(result_features,-1);

fprintf('End contributing feature identification\n');


function [img, mmPerVoxNew, dimOrder, dimFlip] = applyCannonicalXform(img, img2std, mmPerVox, insertMarkerFlag)
% Applies the cannonical xform specified in img2std to img
%
%  [img, mmPerVoxNew, dimOrder, dimFlip] = ...
%   applyCannonicalXform(img, img2std, mmPerVox, insertMarkerFlag)
%
% Applies the cannonical xform specified in img2std. NOTE! This function
% does not do a full affine transform- it assumes that the transform
% specified is a set of simple rotations and flips.
%
% When used with computeCannonicalXformFromIfile, img is reoriented to a
% standard axial orientation. That is, the image will be reoriented so that
% left-right is along the x-axis, anterior-posterior is along the y-axis,
% superior-inferior is along the z-axis, and the leftmost, anterior-most,
% superior-most point is at 0,0,0 (which, for Analyze, is the lower
% left-hand corner of the last slice).
%
% To help you find the 0,0,0 point, a 4-pixel rectange is drawn there with a pixel
% value equal to the maximum image intensity. Set insertMarkerFlag to
% false to disbale this. Also, if ndims(img)>3, this is automatically
% diabled.
%
% To adjust an img-to-standard space xofrm, use:
%
%    newXform = inv(canXform*inv(imToScanXform));
%
% SEE ALSO: computeCannonicalXformFromIfile
%
% HISTORY:
%   2003.06.19 RFD (bob@white.stanford.edu): wrote it.
%%

if(nargin<2)
    help(mfilename);
    return;
end
if(~exist('insertMarkerFlag','var')||isempty(insertMarkerFlag))
    insertMarkerFlag = true;
end

% Extract rotation & scale matrix. We have set things up so that the scales
% should be 1.
img2stdRot = round(img2std(1:3,1:3));

% Note that we have constructed this transform matrix so that it will only
% involve cannonical rotations. We did this by specifying corresponding
% points from cannonical locations (the corners of the volume- see
% stdCoords and volCoords).

% We use shortcuts to apply the transform. Since all rotations are
% cannonical, we can achieve them efficiently by swapping dimensions with
% 'permute'. The dimension permutation logic- we want to know which of the
% current dimensions should be x, which should be y, and which should be z:
xdim = find(abs(img2stdRot(1,:))==1);
ydim = find(abs(img2stdRot(2,:))==1);
zdim = find(abs(img2stdRot(3,:))==1);
dimOrder = [xdim, ydim, zdim];
dimFlip = [0 0 0];
if exist('mmPerVox','var')
    mmPerVoxNew = [mmPerVox(xdim), mmPerVox(ydim), mmPerVox(zdim)];
else
    mmPerVoxNew = [];
end

% Allow >3 dims- just leave the extra dims alone.
img = permute(img, [dimOrder, 4, 5]);

% Now do any necessary mirror flips (indicated by negative rotation matrix values).
if img2stdRot(1,xdim)<0
    dimFlip(xdim) = 1;
    % flip each slice ud (ie. along matlab's first dimension- our x-axis)
    %for(jj=1:size(img,3)) img(:,:,jj) = flipud(squeeze(img(:,:,jj))); end
    img = flipdim(img, 1);
end
if img2stdRot(2,ydim)<0
    dimFlip(ydim) = 1;
    % flip each slice lr (ie. along matlab's second dimension- our y-axis)
    %for(jj=1:size(img,3)) img(:,:,jj) = fliplr(squeeze(img(:,:,jj))); end
    img = flipdim(img, 2);
end
if img2stdRot(3,zdim)<0
    dimFlip(zdim) = 1;
    % reorder slices (ie. flip along the 3rd dim)
    %for(jj=1:size(img,1)) img(jj,:,:) = fliplr(squeeze(img(jj,:,:))); end
    img = flipdim(img, 3);
end

if insertMarkerFlag&&ndims(img)==3
    % insert a marker at 1,end,end (should be left, anterior, superior
    % given stdCoords of [0,0,0; 0,-1,0; 0,0,-1; -1,0,0])
    img(1,end,end) = max(img(:));
    img(2,end,end) = img(end,1,end);
    img(1,end-1,end) = img(end,1,end);
    img(2,end-1,end) = img(end,1,end);
end

return;

%%


function train_id_net_vgg16(varargin)
% -------------------------------------------------------------------------
% Part 4.1: prepare the data
% -------------------------------------------------------------------------

imdb = load('./dataset/CUHK-PEDES-prepare/url_data.mat');
imdb = imdb.imdb;
imdb.images.set(imdb.images.set==2)=3;
load('./dataset/CUHK-PEDES-prepare/cuhk_word2.mat');
imdb.charcnn = wordcnn;
%imdb.charmean = mean(imdb.charcnn(:,:,:,imdb.images.set==1),4);
% -------------------------------------------------------------------------
% Part 4.2: initialize a CNN architecture
% -------------------------------------------------------------------------
net = cuhk_word2_Rankloss_vgg16();
net.conserveMemory = true;
im_mean = imdb.rgbMean;
net.meta.normalization.averageImage = im_mean;
%net.meta.normalization.charmean = imdb.charmean;
% -------------------------------------------------------------------------
% Part 4.3: train and evaluate the CNN

% -------------------------------------------------------------------------
opts.train.averageImage = net.meta.normalization.averageImage;
opts.train.batchSize = 32;
opts.train.continue = true;
opts.train.gpus = 1;
opts.train.prefetch = false ;
opts.train.nesterovUpdate = true ;
opts.train.expDir = './data/vgg16_cuhk_batch32_Rankloss_2:1:0.5_margin1_re';
opts.train.derOutputs = {'objective_f',2,'objective_img',1,'objective_txt',0.5} ;
%opts.train.gamma = 0.9;
opts.train.momentum = 0.9;
%opts.train.constraint = 100;
opts.train.learningRate = [0.1*ones(1,40),0.01*ones(1,20)] ;
opts.train.weightDecay = 0.0001;
opts.train.numEpochs = numel(opts.train.learningRate) ;
[opts, ~] = vl_argparse(opts.train, varargin) ;
% Call training function in MatConvNet
[net,info] = cnn_train_dag_batchsize(net, imdb, @getBatch,opts) ;

% --------------------------------------------------------------------
function inputs = getBatch(imdb,batch,opts)
% --------------------------------------------------------------------
batchsize = numel(batch);
half = batchsize/2;
label_img =  imdb.images.label(batch(1:half));
txt_batch = zeros(1,batchsize,'single');
for i= 1:half  % Yp ~ Xp
    txt_batch(i) = rand_same_class(imdb, label_img(i));
end
for i= half+1:batchsize   % Yn ~ Xp
    txt_batch(i) = rand_diff_class2(imdb, label_img(i-half));   %negative pair
end
for i= half+1:batchsize   % Xn ~ Xp
    if(imdb.images.label(batch(i))== imdb.images.label(batch(i-half)))
        batch(i) = rand_diff_class3(imdb, label_img(i-half));
    end
end
%-- img data
im_url = imdb.images.data(batch) ;
im = vl_imreadjpeg(im_url,'Pack','Resize',[224,224],'Flip',...
    'CropLocation','random','CropSize',[0.8,1],...
    'Interpolation', 'bicubic','NumThreads',16,... %'Brightness', double(0.1*imdb.rgbCovariance),...
    'SubtractAverage',imdb.rgbMean,...
    'CropAnisotropy',[3/4,4/3]);
oim = im{1};
label_img =  imdb.images.label(batch);
%-- txt data
label_txt =  imdb.images.label2(txt_batch);
txt = single(imdb.charcnn(:,txt_batch));
txtinput = zeros(1,56,7263,batchsize,'single');
for i=1:batchsize
    len = sum(txt(:,i)>0);
    location = randi(57-len);
    for j=1:len
        v = txt(j,i);
       txtinput(1,location,v,i)=1;
       location = location+1;
    end
end
txtinput = gpuArray(txtinput);
%--
inputs = {'x0',gpuArray(oim),'data2',txtinput,'label_img',label_img,'label_txt',label_txt};


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

% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA  (since 1.1)
%
% Copyright (C) 2001 Jos F. Sturm (up to 1.05R5)
%   Dept. Econometrics & O.R., Tilburg University, the Netherlands.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% Affiliation SeDuMi 1.03 and 1.04Beta (2000):
%   Dept. Quantitative Economics, Maastricht University, the Netherlands.
%
% Affiliations up to SeDuMi 1.02 (AUG1998):
%   CRL, McMaster University, Canada.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
% 02110-1301, USA

y = bwblkslv(L,b);
%y(L.perm,:) = L.L'\b;


function [dv, rp, orbitIn, orbitOut, deltaVVect, vInfDNorm, vInfDepart, vInfArrive, totDV, r1B, r2B, v1Output, v2Output, xferRp] =  multiFlybyObjFunc(x, numRevsArr,bodiesInfo,includeDepartVInf,includeArrivalVInf,celBodyData)
%multiFlybyObjFunc Summary of this function goes here
%   Detailed explanation goes here
    numX = size(x,1);

    if(numX==0)
        dv = 9E99;
        rp = [];
        orbitIn = [];
        orbitOut = [];
        deltaVVect = [];
        vInfDNorm = [];
        vInfDepart = [];
        vInfArrive = [];
        totDV = [];
        r1B = [];
        r2B = [];
        v1Output = [];
        v2Output = [];
        xferRp = [];
        return;
    end

    flybyBodies = bodiesInfo(2:end-1);
    numFB = length(flybyBodies);
    numREVS = length(bodiesInfo) - 1;

    tm = x(:,end-numREVS-numFB:end-numREVS);
    tm = round(tm);
    tm(tm==2) = -1;
    numTM = size(tm,2);

    numRevInds = x(:,end-numREVS+1:end);

    x = x(:,1:end-numTM-numREVS);
    daTimes = cumsum(x,2);

    gmu = zeros(length(bodiesInfo),numX);
    rVectsB = zeros(3,numX,size(x,2));
    vVectsB = zeros(3,numX,size(x,2));
    for(i=1:length(bodiesInfo)) %#ok<*NO4LP>
        bodyInfo = bodiesInfo{i};
        [rVect, vVect] = getStateAtTime(bodyInfo, daTimes(:,i)', getParentGM(bodyInfo, celBodyData));

        rVectsB(:,:,i) = rVect;
        vVectsB(:,:,i) = vVect;

        gmu(i,:) = bodyInfo.gm * ones(1,numX);

        if(i==1)
            vBDepart = vVect;
        elseif(i==length(bodiesInfo))
            vBArrive = vVect;
        end
    end
    gmu(1,:) = [];
    gmu(end,:) = [];
    gmu = reshape(gmu',1,numel(gmu'));

    rVectsB = reshape(rVectsB,3,length(bodiesInfo)*numX);
    r1B = rVectsB(:,1:end-size(x,1));
    r2B = rVectsB(:,size(x,1)+1:end);

    vVectsB = reshape(vVectsB,3,length(bodiesInfo)*numX);
    vB = vVectsB(:,size(x,1)+1:end-size(x,1));

    tempXferGmu = zeros(1,length(bodiesInfo)-1);
    for(i=1:length(bodiesInfo)-1)
        parentBodyInfo = bodiesInfo{i}.getParBodyInfo(celBodyData);
        tempXferGmuScalar = parentBodyInfo.gm;

%         tempXferGmuScalar = getParentGM(bodiesInfo{i}, celBodyData);
        tempXferGmu((i-1)*numX+1:i*numX) = tempXferGmuScalar;
    end
    xferGmuL = tempXferGmu;

%     xferGmuL = xferGmu * ones(1,(length(bodiesInfo)-1)*numX);

    dt = x(:,2:end) .* tm;
    dt = reshape(dt,1,numel(dt));

    popSize = size(r1B,2) / (length(bodiesInfo)-1);

    for(i=1:size(numRevInds,2))
        numRevInd = round(numRevInds(:,i));
        numRev((i-1)*popSize+1 : i*popSize) = numRevsArr{i}(numRevInd);
    end

    bool = numRev == 0;

    v1 = zeros(size(r1B));
    v2 = v1;

    xferRp = zeros(1,size(r1B,2));

    if(any(bool)) %use the faster vectorized solver
        [v1(:,bool), v2(:,bool)] = lambertBattinVector(r1B(:,bool), r2B(:,bool), dt(bool), numRev(bool), xferGmuL(bool));

        [xferSma, xferEcc, ~, ~, ~, ~] = vect_getKeplerFromState(r1B(:,bool),v1(:,bool),xferGmuL(bool), true);
        [~, xferRp(bool)] = computeApogeePerigee(xferSma, xferEcc);
    end
    if(any(~bool))                      %use the slower but multi-rev capable lambert loop
        bool = ~bool;
        inds = find(bool);

        for(i=1:length(inds))
            ind = inds(i);
            try
                [v1L, v2L, ~, exitflag] = orbit.lambert(r1B(:,ind)', r2B(:,ind)', dt(ind)/86400, numRev(ind), xferGmuL(ind));

                [xferSma, xferEcc, ~, ~, ~, ~] = getKeplerFromState(r1B(:,ind),v1L,xferGmuL(ind), true);
                [~, xferRp(ind)] = computeApogeePerigee(xferSma, xferEcc);

                if(any(isnan(v1L)) || any(isnan(v2L)) || exitflag == -1 || exitflag == -2)
                    v1L(isnan(v1L)) = 9E99;
                    v2L(isnan(v2L)) = 9E99;
                end
            catch ME %#ok<NASGU>
                v1L = 9E99 * ones(1,3);
                v2L = 9E99 * ones(1,3);
            end

            v1(:,ind) = v1L';
            v2(:,ind) = v2L';
        end
    end

    xferRp(isnan(xferRp)) = Inf;

    v1Output = v1;
    v2Output = v2;

    v1D = v1(:,1:numX);
    v1 = v1(:,numX+1:end);
    v2A = v2(:,end-numX+1:end);
    v2 = v2(:,1:end-numX);

    vInfIn = v2 - vB;
    vInfOut = v1 - vB;

    vInfDepart = v1D - vBDepart;
    vInfDNorm = sqrt(sum(abs(vInfDepart).^2,1));
    vInfDNorm = (vInfDNorm');

    vInfArrive = v2A - vBArrive;
    vInfANorm = sqrt(sum(abs(vInfArrive).^2,1));
    vInfANorm = (vInfANorm');

    [smaIn, eIn, hHat, sHat, smaOut, eOut, oHat] = computeMultiFlyByParameters(vInfIn, vInfOut, gmu);
    [hSMAIn, hEccIn, hIncIn, hRAANIn, hArgIn, ~, ~, rp] = computeHyperOrbitFromMultiFlybyParams(smaIn, eIn, hHat, sHat, true);
    [hSMAOut, hEccOut, hIncOut, hRAANOut, hArgOut, ~, ~, ~] = computeHyperOrbitFromMultiFlybyParams(smaOut, eOut, hHat, oHat, false);

%     if(any(abs(rp-rp2)>1E-6))
%         warning(num2str(abs(rp-rp2)));
%     end

    orbitIn = [hSMAIn', hEccIn', hIncIn', hRAANIn', hArgIn', zeros(size(hSMAIn')), ((1-eIn).*smaIn)'];
    orbitOut = [hSMAOut', hEccOut', hIncOut', hRAANOut', hArgOut', zeros(size(hSMAOut')), ((1-eOut).*smaOut)'];

    [~,vVectIn]=vect_getStatefromKepler(hSMAIn, hEccIn, hIncIn, hRAANIn, hArgIn, zeros(size(hArgIn)), gmu);
    [~,vVectOut]=vect_getStatefromKepler(hSMAOut, hEccOut, hIncOut, hRAANOut, hArgOut, zeros(size(hArgOut)), gmu);
    deltaVVect = vVectOut-vVectIn;
    deltaV = sqrt(sum(abs(deltaVVect).^2,1));
    totDV = sum(reshape(deltaV,numX,length(flybyBodies)),2);

    dv = totDV;

    if(includeDepartVInf)
        dv = dv + vInfDNorm;
    end

    if(includeArrivalVInf)
        dv = dv + vInfANorm;
    end

%     dv = vInfDNorm + totDV + vInfANorm;

    dv(dv>=1E99) = NaN;
    dv(isnan(dv)) = max(dv)+10;
end


function [net, info] = cnn_cifar(varargin)
% CNN_CIFAR   Demonstrates MatConvNet on CIFAR-10
%    The demo includes two standard model: LeNet and Network in
%    Network (NIN). Use the 'modelType' option to choose one.

run(fullfile(fileparts(mfilename('fullpath')), ...
  '..', '..', 'matlab', 'vl_setupnn.m')) ;

opts.modelType = 'lenet' ;
[opts, varargin] = vl_argparse(opts, varargin) ;

opts.expDir = fullfile('data', sprintf('cifar-%s', opts.modelType)) ;
[opts, varargin] = vl_argparse(opts, varargin) ;

opts.dataDir = fullfile('data','cifar') ;
opts.imdbPath = fullfile(opts.expDir, 'imdb.mat');
opts.whitenData = true ;
opts.contrastNormalization = true ;
opts.networkType = 'simplenn' ;
opts.train = struct() ;
opts = vl_argparse(opts, varargin) ;

% -------------------------------------------------------------------------
%                                                    Prepare model and data
% -------------------------------------------------------------------------

switch opts.modelType
  case 'lenet'
    net = cnn_cifar_init('networkType', opts.networkType) ;
  case 'nin'
    net = cnn_cifar_init_nin('networkType', opts.networkType) ;
  otherwise
    error('Unknown model type ''%s''.', opts.modelType) ;
end

if exist(opts.imdbPath, 'file')
  imdb = load(opts.imdbPath) ;
else
  imdb = getCifarImdb(opts) ;
  mkdir(opts.expDir) ;
  save(opts.imdbPath, '-struct', 'imdb') ;
end

net.meta.classes.name = imdb.meta.classes(:)' ;

% -------------------------------------------------------------------------
%                                                                     Train
% -------------------------------------------------------------------------

switch opts.networkType
  case 'simplenn', trainfn = @cnn_train ;
  case 'dagnn', trainfn = @cnn_train_dag ;
end

[net, info] = trainfn(net, imdb, getBatch(opts), ...
  'expDir', opts.expDir, ...
  net.meta.trainOpts, ...
  opts.train, ...
  'val', find(imdb.images.set == 3)) ;

% -------------------------------------------------------------------------
function fn = getBatch(opts)
% -------------------------------------------------------------------------
switch lower(opts.networkType)
  case 'simplenn'
    fn = @(x,y) getSimpleNNBatch(x,y) ;
  case 'dagnn'
    bopts = struct('numGpus', numel(opts.train.gpus)) ;
    fn = @(x,y) getDagNNBatch(bopts,x,y) ;
end

% -------------------------------------------------------------------------
function [images, labels] = getSimpleNNBatch(imdb, batch)
% -------------------------------------------------------------------------
images = imdb.images.data(:,:,:,batch) ;
labels = imdb.images.labels(1,batch) ;
if rand > 0.5, images=fliplr(images) ; end

% -------------------------------------------------------------------------
function inputs = getDagNNBatch(opts, imdb, batch)
% -------------------------------------------------------------------------
images = imdb.images.data(:,:,:,batch) ;
labels = imdb.images.labels(1,batch) ;
if rand > 0.5, images=fliplr(images) ; end
if opts.numGpus > 0
  images = gpuArray(images) ;
end
inputs = {'input', images, 'label', labels} ;

% -------------------------------------------------------------------------
function imdb = getCifarImdb(opts)
% -------------------------------------------------------------------------
% Preapre the imdb structure, returns image data with mean image subtracted
unpackPath = fullfile(opts.dataDir, 'cifar-10-batches-mat');
files = [arrayfun(@(n) sprintf('data_batch_%d.mat', n), 1:5, 'UniformOutput', false) ...
  {'test_batch.mat'}];
files = cellfun(@(fn) fullfile(unpackPath, fn), files, 'UniformOutput', false);
file_set = uint8([ones(1, 5), 3]);

if any(cellfun(@(fn) ~exist(fn, 'file'), files))
  url = 'http://www.cs.toronto.edu/~kriz/cifar-10-matlab.tar.gz' ;
  fprintf('downloading %s\n', url) ;
  untar(url, opts.dataDir) ;
end

data = cell(1, numel(files));
labels = cell(1, numel(files));
sets = cell(1, numel(files));
for fi = 1:numel(files)
  fd = load(files{fi}) ;
  data{fi} = permute(reshape(fd.data',32,32,3,[]),[2 1 3 4]) ;
  labels{fi} = fd.labels' + 1; % Index from 1
  sets{fi} = repmat(file_set(fi), size(labels{fi}));
end

set = cat(2, sets{:});
data = single(cat(4, data{:}));

% remove mean in any case
dataMean = mean(data(:,:,:,set == 1), 4);
data = bsxfun(@minus, data, dataMean);

% normalize by image mean and std as suggested in `An Analysis of
% Single-Layer Networks in Unsupervised Feature Learning` Adam
% Coates, Honglak Lee, Andrew Y. Ng

if opts.contrastNormalization
  z = reshape(data,[],60000) ;
  z = bsxfun(@minus, z, mean(z,1)) ;
  n = std(z,0,1) ;
  z = bsxfun(@times, z, mean(n) ./ max(n, 40)) ;
  data = reshape(z, 32, 32, 3, []) ;
end

if opts.whitenData
  z = reshape(data,[],60000) ;
  W = z(:,set == 1)*z(:,set == 1)'/60000 ;
  [V,D] = eig(W) ;
  % the scale is selected to approximately preserve the norm of W
  d2 = diag(D) ;
  en = sqrt(mean(d2)) ;
  z = V*diag(en./max(sqrt(d2), 10))*V'*z ;
  data = reshape(z, 32, 32, 3, []) ;
end

clNames = load(fullfile(unpackPath, 'batches.meta.mat'));

imdb.images.data = data ;
imdb.images.labels = single(cat(2, labels{:})) ;
imdb.images.set = set;
imdb.meta.sets = {'train', 'val', 'test'} ;
imdb.meta.classes = clNames.label_names;


function model = ml_traincov(varargin)
% Learn a linear predictive model using covariance-based classification.
% Model = ml_traincov(Trials, Targets, Options...)
%
% This method assumes that the given trials values represent covariance matrices and offers various
% methods, including information geometric approaches, to classify them. This implementation uses
% the covariance toolbox by Alexandre Barachant.
%
% In:
%   Trials       : training data, as in ml_train
%
%   Targets      : target variable, as in ml_train
%
% Out:
%   Model   : the predictive model; can be used with ml_predictcov
%
% Examples:
%   % learn a model using the defaults
%   model = ml_traincov(trials,targets);
%
% See also:
%   ml_predictcov
%
%                           Christian Kothe, Syntrogi
%                           2015-04-21
dp;

arg_define([0 3],varargin, ...
    arg_norep('trials'), ...
    arg_norep('targets'), ...
    arg({'classifier','ClassificationMethod'},'mdm',{'mdm','fgmdm','tslda'}, 'Classification method to use. The mdm method (minimum distance to mean) is based on minimum distance to class mean using a given distance metric and mean estimation metric. The fgmdm (filtered geodesic mdm) method additionally performs geodesic filtering. The tslda method (tangent-space linear discriminant analysis) is an LDA implementation that respects the Riemannian geometry of the data.'), ...
    arg({'mean_est','MeanEstimator'},'riemann',{'arithmetic','riemann','riemanndiag','riemanntrim','median','riemannmed','logeuclid','opttransp','ld','geodesic','harmonic','geometric'},'Method to average covariance matrices. Various methods are supported, including Riemannian mean/median/trimmed mean, log-euclidean mean, optimal transportation mean, log determinant mean, and geodesic iterative mean.'), ...
    arg({'distance_metric','DistanceMetric'},'riemann',{'euclid','riemann','kullback','logeuclid','opttransp','ld'},'Distance metric to use. This is only used for the mdm and fgmdm methods. Different distance metrics are supported, including the Euclidean metric, the Riemannian distance, Kullback-Leibler divergence, log-euclidean distance, optimal transportation distance, and log determinant distance'));

% find the class labels
classes = unique(targets);
if length(classes) == 1
    error('BCILAB:only_one_class','Your training data set has no trials for one of your classes; you need at least two classes to train a classifier.\n\nThe most likely reasons are that one of your target markers does not occur in the data, or that all your trials of a particular class are concentrated in a single short segment of your data (10 or 20 percent). The latter would be a problem with the experiment design.');
else
    % reformat feature shape to DxDxN
    if ndims(trials) == 2 %#ok<ISMAT,NODEF>
        [N,F] = size(trials);
        D = sqrt(F);
        if abs(D-round(D)) > 0
            error('The number of features in your trials must be a square of an integer.'); end
        trials = reshape(trials',[D,D,N]);
    else
        [U,V,N] = size(trials); %#ok<ASGLU>
        if U ~= V
            error('Your feature matrices are not square, i.e., cannot be covariance matrices.'); end
    end

    model.classes = classes;
    switch classifier
        case 'mdm'
            % minimum distance to mean: estimate class means
            for c=length(classes):-1:1
                model.C{c} = mean_covariances(trials(:,:,targets==classes(c)),mean_est); end
        case 'fgmdm'
            % filtered geodesic minimum distance to mean
            % geodesic filtering
            [model.W,model.Cg] = fgda(trials,targets,mean_est,{},'shcov',{});
            trials = geodesic_filter(trials,model.Cg,model.W(:,1:length(model.classes)-1));
            % estimate class means
            for c=length(classes):-1:1
                model.C{c} = mean_covariances(trials(:,:,targets==classes(c)),mean_est); end
        case 'tslda'
            error('This variant is not yet implemented!');
        otherwise
            error('Unsupported classification method: %s',hlp_tostring(classifier));
    end
end

model.classifier = classifier;
model.mean_est = mean_est;
model.distance_metric = distance_metric;


%IPAD Pad an image with constants
%
% OUT = IPAD(IM, SIDES, N) is a padded version of the image IM with a block
% of NaN values N pixels wide on the sides of IM as specified by SIDES.
%
% OUT = IPAD(IM, SIDES, N, V) as above but pads with pixels of value V.
%
% SIDES is a string containing one or more of the characters:
% 't'   top
% 'b'   bottom
% 'l'   left
% 'r'   right
%
% Examples::
%
% Add a band of zero pixels 20 pixels high across the top of the image:
%     ipad(im, 't', 20, 0)
%
% Add a band of white pixels 10 pixels wide on all sides of the image:
%     ipad(im, 'tblr', 10, 255)
%
% Notes::
% - Not a tablet computer.

% Copyright (C) 1993-2011, by Peter I. Corke
%
% This file is part of The Machine Vision Toolbox for Matlab (MVTB).
%
% MVTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% MVTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with MVTB.  If not, see <http://www.gnu.org/licenses/>.

function out = ipad(in, sides, n, val)

    if nargin < 4
        val = NaN;
    end

    if ndims(in) > 2
        % multiplane case
        d = size(in);
        nimages = prod(d(3:end));
        out = [];
        for i=1:nimages
            out(:,:,i) = ipad(in(:,:,i), sides, n, val);
        end

        d2 = size(out);
        out = reshape(out, [d2(1) d2(2) d(3:end)]);
        return
    end

    out = in;
    for side=sides
        [w,h] = isize(out);

        switch side
            case 't'
                out = [val*ones(n,w); out];
            case 'b'
                out = [out; val*ones(n,w)];
            case 'l'
                out = [val*ones(h,n) out];
            case 'r'
                out = [out val*ones(h,n)];
        end
    end


function varargout = showXSlice(img, sliceIndex)
%SHOWXSLICE Show YZ slice of a 3D image
%
%   showXSlice(IMG, INDEX)
%   Display the given slice as a 3D planar image. INDEX is the slice index,
%   between 1 and stackSize(img, 1).
%
%   Example
%   % Display 3D orthoslices of a humain head
%   img = analyze75read(analyze75info('brainMRI.hdr'));
%   figure(1); clf; hold on;
%   showZSlice(img, 13);
%   showXSlice(img, 60);
%   showYSlice(img, 80);
%   axis equal
%   xlabel('x'); ylabel('y'); zlabel('z');
%
%   See also
%   showYSlice, showZSlice, getSlice

% ------
% Author: David Legland
% e-mail: david.legland@inra.fr
% Created: 2010-06-30,    using Matlab 7.9.0.529 (R2009b)
% http://www.pfl-cepia.inra.fr/index.php?page=slicer
% Copyright 2010 INRA - Cepia Software Platform.

%% Extract image info

dim = stackSize(img);

% compute voxel positions
lx = 1:dim(1);

% position vectors of voxel corners
vy = ((0:dim(2)) + .5);
vz = ((0:dim(3)) + .5);

% global parameters for surface display
params = {'facecolor', 'texturemap', 'edgecolor', 'none'};

% compute position of voxel vertices in 3D space
[yz_y, yz_z] = meshgrid(vy, vz);
yz_x = ones(size(yz_y)) * lx(sliceIndex);

% extract slice in x direction
slice = stackSlice(img, 'x', sliceIndex);

% eventually converts to uint8, rescaling data between 0 and max value
if ~isa(slice, 'uint8')
    slice = double(slice);
    slice = uint8(slice * 255 / max(slice(:)));
end

% convert grayscale to rgb (needed by 'surface' function)
if length(size(slice)) == 2
    slice = repmat(slice, [1 1 3]);
end

% display voxel values in appropriate reference space
hs = surface(yz_x, yz_y, yz_z, slice, params{:});

%% process output arguments

if nargout > 0
    varargout = {hs};
end


function f = filterobject(anything, cutoff, poles)
% FILTEROBJECT constructor for a filter object
%   f = filterobject() creates a new default filterobject
%   f = filterobject(filterobject) duplicates a filterobject
%   f = filterobject(type, cutoff, poles) create user-defined filterobject
%
%   TYPE:  'B' : Bandpass, 'H' : Highpass, 'L' : Lowpass
%   CUTOFF: [low, high] for bandpass, single value for others
%   POLES: number of poles used in the filter
%
%   default new object: Bandpass from 0.8 Hz to 5Hz, 2 poles (as dictated
%   by this constructor file

% VERSION: 1.0 of filter objects
% AUTHOR: Celso Reyes
% LASTUPDATE: 1/30/2007

load_global_namespace;

switch nargin
    case 0
            %create a fresh filterobject
            f.type = 'B';
            f.cutoff = [0.8 5];
            f.poles = 2;
            f = class(f, 'filterobject');

    case 1
        if isa(anything, 'filterobject')
            f = anything;
        else
            error(['trying to use filterobject(' class(anything) ')']);
        end

    case 3
        f = filterobject;
        f = set(f,'type',anything, 'cutoff', cutoff,'poles',poles);

    otherwise
        disp('Invalid arguments in filterobject constructor');
end;

%% LOAD filterobject's global namespace
% replaces SUITE_STUFF
function load_global_namespace()

persistent FILTER_NAMESPACE

if FILTER_NAMESPACE
    return
else
    FILTER_NAMESPACE = true;
end
%
% global FILTER_LONG
% global FILTER_STANDARD
%
% FILTER_LONG = filterobject('L',0.999,2);
% FILTER_STANDARD = filterobject('B', [0.8 5.0] ,2);


function varargout = drawDirectedEdges(p, e, varargin)
%DRAWDIRECTEDEDGES Draw edges with arrow indicating direction
%
%   usage:
%   drawDirectedEdges(NODES, EDGES);
%
%   drawDirectedEdges(NODES, EDGES, STYLE);
%   specifies style of arrrows. Can be one of:
%   'left'
%   'right'
%   'arrow'
%   'triangle'
%   'fill'
%
%   drawDirectedEdges(NODES, EDGES, STYLE, DIRECT) : also specify the base
%   direction of all edges. DIRECT is true by default. If DIRECT is false
%   all edges are inverted.
%
%   H = drawDirectedEdges(NODES, EDGES) : return handles to each of the
%   lines created.
%
%   TODO: now only style 'arrow' is implemented ...
%
%   -----
%
%   author : David Legland
%   INRA - TPV URPOI - BIA IMASTE
%   created the 12/03/2003.
%

%   HISTORY

b=1;

if ~isempty(varargin)
    b = varargin{1};
end

h = zeros(length(e),1);
hold on;
for l=1:length(e)
    p1 = e(l, 1);
    p2 = e(l, 2);
    h(l*4) = line([p(p1,1) p(p2,1)], [p(p1,2) p(p2,2)]);

    % position of middles of edge
    xm = (p(p1,1) + p(p2,1))/2;
    ym = (p(p1,2) + p(p2,2))/2;

    % orientation of edge
    theta = atan2(p(p2,2) - p(p1,2), p(p2,1) - p(p1,1)) + (b==0)*pi;

    % pin of the arrow
    xa0 = xm + 10*cos(theta);
    ya0 = ym + 10*sin(theta);

    % right side of the arrow
    xa1 = xm + 3*cos(theta-pi/2);
    ya1 = ym + 3*sin(theta-pi/2);

    % left side of the arrow
    xa2 = xm + 3*cos(theta+pi/2);
    ya2 = ym + 3*sin(theta+pi/2);

    h(l*4+1) = line([xa1 xa0], [ya1 ya0]);
    h(l*4+2) = line([xa2 xa0], [ya2 ya0]);
end

if nargout==1
    varargout(1) = {h};
end


function [resampSigM,TTHPv,SHPv,timeOutV] = halfPeak(ROIDataM,timeV,smoothFlag,resampFlag)
% =======================================================================================
% AI  09/28/16
% AI  10/20/16  Added smoothing/resampling options.
% ======================================================================================
% INPUTS
% ROIDataM   : (no. voxels x time pts) Matrix of temporal signals of
%              raster-ordered voxels along rows
% timeV      : Vector of time pts of DCE image acquisition.
% smoothFlag : Flag (1-Smooth    0-No smoothing )
% resampFlag : Flag (1-Resample  0-No resampling )
% =====================================================================================

%% Smooth/resample if selected
nVox = size(ROIDataM,1);
[resampSigM,timeOutV] = smoothResamp(ROIDataM,timeV,smoothFlag,resampFlag);
normalizedBaseline = 1;
relSigEnhM = resampSigM - normalizedBaseline;

%% Compute TTHP, SHP
%Identify first time point where changeSig > half-peak
gts50 = bsxfun(@ge,relSigEnhM,(max(resampSigM,[],2) - normalizedBaseline)/2);
[~,SHPcolIdx] = max(gts50,[],2);
SHProwIdx = (1:nVox).';
SHPidx = sub2ind([nVox,numel(timeOutV)],SHProwIdx,SHPcolIdx);
%Get signal at half-peak
SHPv = resampSigM(SHPidx).';
%Get time to half-peak
TTHPv = timeOutV(1,SHPcolIdx);

end

github-repos/MATLAB/cerr-CERR/CERR-d320754abad9dcb78508ab69f33ae9f644202114/CERR_core/PlanAnalysis/DCE-MR analysis/TTHP analysis for DCE-MR/halfPeak.m


function data = read_asa_msr(fn);

% READ_ASA_MSR reads EEG or MEG data from an ASA data file
% converting the units to uV or fT

% Copyright (C) 2002, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip
% for the documentation and details.
%
%    FieldTrip 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.
%
%    FieldTrip 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 FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id: read_asa_msr.m 945 2010-04-21 17:41:20Z roboos $

Npnt      = read_asa(fn, 'NumberPositions=', '%d');
Ntime     = read_asa(fn, 'NumberTimesteps=', '%d');
UnitT     = read_asa(fn, 'UnitTime', '%s');
UnitM     = read_asa(fn, 'UnitMeas', '%s');
Timesteps = read_asa(fn, 'Timesteps', '%s');
lab       = read_asa(fn, 'Labels', '%s', Npnt);

val = read_asa(fn, 'Values', '%f');
if any(size(val)~=[Npnt,Ntime])
  msm_file = read_asa(fn, 'Values', '%s');
  [path, name, ext] = fileparts(fn);
  fid = fopen(fullfile(path, msm_file), 'rb', 'ieee-le');
  val = fread(fid, [Ntime, Npnt], 'float32')';
  fclose(fid);
end

tmp = sscanf(Timesteps, '%f(%f)%f');
time = linspace(tmp(1), tmp(3), Ntime);

if strcmpi(UnitT,'ms')
  time = 1*time;
elseif strcmpi(UnitT,'s')
  time = 1000*time;
elseif ~isempty(UnitT)
  error(sprintf('Unknown unit of time (%s)', UnitT));
end

if strcmpi(UnitM,'uv')
  val = 1*val;
elseif strcmpi(UnitM,'?v')
  val = 1*val;
elseif strcmpi(UnitM,'mv')
  val = 1000*val;
elseif strcmpi(UnitM,'v')
  val = 1000000*val;
elseif strcmpi(UnitM,'ft')
  val = 1*val;
elseif strcmpi(UnitM,'pt')
  val = 1000*val;
elseif ~isempty(UnitM)
  error(sprintf('Unknown unit of measurement (%s)', UnitM));
end

if length(size(lab))==2
  lab = tokenize(lab{1});
end

data.time  = time;
data.data  = val;
data.label = lab;


function [pOutIdxs,chOutIdxs] = treeWpBFrange(wt)
%TREEWPBFRANGE Wavelet packet tree output ranges in BF order
%   Usage: [pOutIdxs,chOutIdxs] = treeBFranges(wt);
%
%   Input parameters:
%         wt       : Filterbank tree struct.
%   Output parameters:
%         pOutIdxs  : Array of parent nodes in BF order
%         chOutIdxs : Cell array of children nodes in BF order
%
%   `[pOutIdxs,chOutIdxs] = treeBFranges(wt)` is a helper function
%   determining direct relationship between nodes in tree *wt*.
%   Elements in both returned arrays are ordered according to the BF order.
%   `pOutIdxs` is array of indices in the subbands
%

treePath = nodeBForder(0,wt);
trLen = numel(treePath);
pOutIdxs = zeros(1,trLen);
chOutIdxs = cell(1,trLen);
pRunIdx = [0];
chRunIdx = 1;
% do trough tree and look for nodeNo and its parent
for ii=1:trLen
    tmpfiltNo = length(wt.nodes{treePath(ii)}.g);
    locRange = nodesLocOutRange(treePath(ii),wt);
    diffRange = 1:tmpfiltNo;
    diffRange(locRange{1})=[];
    chOutIdxs{ii} = chRunIdx:chRunIdx+tmpfiltNo-1;
    chRunIdx = chRunIdx + tmpfiltNo;
    pOutIdxs(ii) = pRunIdx(1);
    pRunIdx = [pRunIdx(2:end),chOutIdxs{ii}(diffRange)];
end

pOutIdxs = pOutIdxs(end:-1:1);
chOutIdxs = chOutIdxs(end:-1:1);


function [ y2, m2, d2, f2 ] = ymdf_inc_hebrew ( y1, m1, d1, f1, days )

%*****************************************************************************80
%
%% YMDF_INC_HEBREW increments a Hebrew YMDF date by DAYS days.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 April 2103
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer Y1,  M1, D1, real F1,
%    the YMDF date.
%
%    Input, real DAYS, the number of days to advance the date.
%
%    Output, integer Y2, M2, D2, real F2,
%    the incremented YMDF date.
%

%
%  Copy the parameters.
%
  y2 = y1;
  m2 = m1;
  d2 = d1;
  f2 = f1 + days;
%
%  Check the parameters.
%
  [ y2, m2, d2, f2, ierror ] = ymdf_check_hebrew ( y2, m2, d2, f2 );

  return
end


function xyb = Xb(s)

x = s ;

if s <= 0.5
    y = -s ;
elseif s>0.5
    y = s-1 ;
end

xyb = [x ; y] ;


function msns_l_i
%
%  Generates the data used in 'msns_l'. Data are stored in global
%  variables.
%
%  Calling sequence:
%
%    msns_l_i
%
%  Remarks:
%
%    Call 'msns_m_i' before calling this routine.
%
%
%  LYAPACK 1.0 (Thilo Penzl, October 1999)

global LP_N LP_NU

if ~length(LP_N)
  error('This routine needs global data which must be generated by calling ''msns_m_i'' first.');
end

[LP_NU,t] = chol(-LP_N);        % Note the minus!

if t~=0
  error('N is not (numerically) negative definite!');
end


function [idx dst] = prisearch(ann, query, k, epsl, asm)
%
% kNN search
%   Usage:
%     [idx dst] = prisearch(ann, query, k, asm, eps)
%
% Inputs:
%   ann - ann class object
%   query - (d)x(N) query points
%   k - number of nearest nieghbors (if points in ann < k than less than k
%                                    points are returned)
%   epsl - epsilon search precision
%   asm - allow self match flag, if false points with dst = 0 are ignored
%         (defualt is true)
%
if nargin == 4
    asm = true;
end

if ~asm
    k = k+1;
end

if ~isa(query, ann.ccls)
    query = ann.cfun(query);
end

[idx dst] = annmex(ann.modes.PRISEARCH, ann.kd_ptr, query, k, epsl);

if ~asm
    gsm = dst(1,:)==0;
    dst(1:end-1,gsm) = dst(2:end,gsm);
    idx(1:end-1,gsm) = idx(2:end,gsm);
    dst(end,:) = [];
    idx(end,:) = [];
end
idx = idx + 1; % fix zero indexing of ann


% This script test under 10-fold Cross Validation, divided by ID, how dtfv works
function [AUC, tt, tf, ft, ff] = auc_fun(label, score, pred)
lie_id = find(score<0);
if ~isempty(lie_id)
    if pred(lie_id(1)) == 0
        isign = -1;
    else
        isign = 1;
    end
else
    if pred(1) == 1
        isign = -1;
    else
        isign = 1;
    end
end
[~,~,~,AUC] = perfcurve(label,isign*score,0);
tt = sum(pred(label==1)==1);
tf = sum(pred(label==1)==0);
ft = sum(pred(label==0)==1);
ff = sum(pred(label==0)==0);

%fprintf('Partation:%d\tacc is %f, auc is %f, tt:%d, tf:%d, ft:%d, ff:%d\n',part, acc(1),AUC,tt,tf,ft,ff);
end


% SYNTAX:
% yAvgStd = hmrS_SessAvgStd2_oldversion_nirs(yAvgRuns, ySum2Runs, mlActRuns, nTrialsRuns)
%
% UI NAME:
% Run_Average_Standard_Deviation
%
% DESCRIPTION:
% Calculate avearge HRF standard deviation of all runs for one subject.
%
% INPUTS:
% yAvgRuns:
% ySum2Runs:
% mlActRuns:
% nTrialsRuns:
%
% OUTPUTS:
% yAvgStdOut: the standard deviation across runs
%
% USAGE OPTIONS:
% Run_Average_Standard_Deviation_on_Concentration_Data:  dcAvgStd  = hmrS_SessAvgStd2_oldversion_nirs(dcAvgRuns, dcSum2Runs, mlActRuns, nTrialsRuns)
% Run_Average_Standard_Deviation_on_Delta_OD_Data:       dodAvgStd = hmrS_SessAvgStd2_oldversion_nirs(dodAvgRuns, dodSum2Runs, mlActRuns, nTrialsRuns)
%

function yAvgStdOut = hmrS_SessAvgStd2_oldversion_nirs(yAvgRuns, ySum2Runs, mlActRuns, nTrialsRuns)

yAvgStdOut = DataClass().empty();

nDataBlks = length(yAvgRuns{1});
nTrials_tot = cell(nDataBlks,1);

for iBlk = 1:nDataBlks

    grp1 = [];

    for iRun = 1:length(yAvgRuns)

        yAvgStdOut(iBlk) = DataClass();

        yAvg    = yAvgRuns{iRun}(iBlk).GetDataTimeSeries('reshape');
        if isempty(yAvg)
            continue;
        end

        yAvgStd = zeros(size(yAvg,1), size(yAvg,2), size(yAvg,3), size(yAvg,4));
        ySum2   = ySum2Runs{iRun}(iBlk).GetDataTimeSeries('reshape');
        tHRF    = yAvgRuns{iRun}(iBlk).GetTime();
        nTrials = nTrialsRuns{iRun}{iBlk};
        if isempty(mlActRuns{iRun})
            mlActRuns{iRun} = cell(length(nDataBlks),1);
        end

        %
        datatype  = yAvgRuns{iRun}(iBlk).GetDataTypeLabel();
        if strncmp(datatype{1}, 'HRF Hb', length('HRF Hb'))
            ml    = yAvgRuns{iRun}(iBlk).GetMeasListSrcDetPairs('reshape');
        elseif strcmp(datatype{1}, 'HRF dOD')
            ml    = yAvgRuns{iRun}(iBlk).GetMeasList('reshape');
        end
        if isempty(mlActRuns{iRun}{iBlk})
            mlActRuns{iRun}{iBlk} = ones(size(ml,1),1);
        end
        mlAct = mlActRuns{iRun}{iBlk}(1:size(ml,1));

        nCond = size(nTrials,2);
        yAvgStdOut(iBlk).SetTime(tHRF);

        if strcmp(datatype{1}, 'HRF dOD')

            if isempty(grp1)
                grp1 = zeros(size(yAvg,1), size(yAvg,2), nCond);
                grp1Sum2 = zeros(size(yAvg,1), size(yAvg,2), nCond);
                nTrials_tot{iBlk} = zeros(size(yAvg,2), nCond);
            end

            lstChInc = find(mlAct==1);
            for iC = 1:nCond
                nT = nTrials(iC);
                if nT>0
                    if iRun==1
                        grp1(:,lstChInc,iC) = yAvg(:,lstChInc,iC) * nT;
                        grp1Sum2(:,lstChInc,iC) = ySum2(:,lstChInc,iC);
                        nTrials_tot{iBlk}(lstChInc,iC) = nT;
                    else
                        for iCh=1:length(lstChInc) %size(yAvg,2)
                            % Make sure 3rd arg to interp1 is column vector to guarauntee interp1 output is column vector
                            % which matches grp1 dimensions when adding the two.
                            grp1(:,lstChInc(iCh),iC) = grp1(:,lstChInc(iCh),iC) + interp1(tHRF,yAvg(:,lstChInc(iCh),iC),tHRF(:)) * nT;
                            grp1Sum2(:,lstChInc(iCh),iC) = grp1Sum2(:,lstChInc(iCh),iC) + interp1(tHRF,ySum2(:,lstChInc(iCh),iC),tHRF(:));
                            nTrials_tot{iBlk}(lstChInc(iCh),iC) = nTrials_tot{iBlk}(lstChInc(iCh),iC) + nT;
                        end
                    end
                end
            end

            if ~isempty(grp1)
                for iC = 1:size(grp1,3)
                    for iCh = 1:size(grp1,2)
                        yAvg(:,iCh,iC) = grp1(:,iCh,iC) / nTrials_tot{iBlk}(iCh,iC);

                        % We want to distinguish between no trials and 1 trial:
                        % If there are no trials, we have no HRF data and no std which
                        % the first case will calculate as opposed to one trial (2nd case)
                        % where we have all zeros.
                        if(nTrials_tot{iBlk}(iCh,iC)~=1)
                            yAvgStd(:,iCh,iC) = ( (1/(nTrials_tot{iBlk}(iCh,iC)-1))*grp1Sum2(:,iCh,iC) - (nTrials_tot{iBlk}(iCh,iC)/(nTrials_tot{iBlk}(iCh,iC)-1))*(grp1(:,iCh,iC) / nTrials_tot{iBlk}(iCh,iC)).^2).^0.5 ;
                        else
                            yAvgStd(:,iCh,iC) = zeros(size(grp1Sum2(:,iCh,iC)));
                        end

                        %%%% Snirf stuff: Once we get to the last run, we've accumulated our averages.
                        %%%% Now we can set channel descriptors for avg and standard deviation
                        if iRun == length(yAvgRuns)
                            yAvgStdOut(iBlk).AddChannelDod(ml(iCh,1), ml(iCh,2), ml(iCh,4), iC);
                        end
                    end

                    %%%% Snirf stuff: Once we get to the last run, we've accumulated our averages.
                    %%%% Now we can set channel descriptors for avg and standard deviation
                    if iRun == length(yAvgRuns)
                        yAvgStdOut(iBlk).AppendDataTimeSeries(yAvgStd(:,:,iC));
                    end
                end
            end

        elseif strncmp(datatype{1}, 'HRF Hb', length('HRF Hb'))

            if isempty(grp1)
                grp1 = zeros(size(yAvg,1), size(yAvg,2), size(yAvg,3), nCond);
                grp1Sum2 = zeros(size(yAvg,1), size(yAvg,2), size(yAvg,3), nCond);
                nTrials_tot{iBlk} = zeros(size(yAvg,3), nCond);
            end

            lstChInc = find(mlAct==1);
            for iC = 1:1:nCond
                nT = nTrials(iC);
                if nT>0
                    if iRun==1
                        grp1(:,:,lstChInc,iC) = yAvg(:,:,lstChInc,iC) * nT;
                        grp1Sum2(:,:,lstChInc,iC) = ySum2(:,:,lstChInc,iC);
                        nTrials_tot{iBlk}(lstChInc,iC) = nT;
                    else
                        for iCh=1:length(lstChInc) %size(yAvg,3)
                            for iHb=1:size(yAvg,2)
                                % Make sure 3rd arg to interp1 is column vector to guarauntee interp1 output is column vector
                                % which matches grp1 dimensions when adding the two.
                                grp1(:,iHb,lstChInc(iCh),iC) = grp1(:,iHb,lstChInc(iCh),iC) + interp1(tHRF,yAvg(:,iHb,lstChInc(iCh),iC),tHRF(:)) * nT;
                                grp1Sum2(:,iHb,lstChInc(iCh),iC) = grp1Sum2(:,iHb,lstChInc(iCh),iC) + interp1(tHRF,ySum2(:,iHb,lstChInc(iCh),iC),tHRF(:));
                            end
                            nTrials_tot{iBlk}(lstChInc(iCh),iC) = nTrials_tot{iBlk}(lstChInc(iCh),iC) + nT;
                        end
                    end
                end
            end

            if ~isempty(grp1)
                for iC = 1:size(grp1,4)
                    for iCh = 1:size(grp1,3)
                        yAvg(:,:,iCh,iC) = grp1(:,:,iCh,iC) / nTrials_tot{iBlk}(iCh,iC);

                        % We want to distinguish between no trials and 1 trial:
                        % If there are no trials, we have no HRF data and no std which
                        % the first case will calculate as opposed to one trial (2nd case)
                        % where we have all zeros.
                        if(nTrials_tot{iBlk}(iCh,iC)~=1)
                            yAvgStd(:,:,iCh,iC) = ( (1/(nTrials_tot{iBlk}(iCh,iC)-1))*grp1Sum2(:,:,iCh,iC) - (nTrials_tot{iBlk}(iCh,iC)/(nTrials_tot{iBlk}(iCh,iC)-1))*(grp1(:,:,iCh,iC) / nTrials_tot{iBlk}(iCh,iC)).^2).^0.5 ;
                        else
                            yAvgStd(:,:,iCh,iC) = zeros(size(grp1Sum2(:,:,iCh,iC)));
                        end

                        %%%% Snirf stuff: Once we get to the last run, we've accumulated our averages.
                        %%%% Now we can set channel descriptors for avg and standard deviation
                        if iRun == length(yAvgRuns)
                            yAvgStdOut(iBlk).AddChannelHbO(ml(iCh,1), ml(iCh,2), iC);
                            yAvgStdOut(iBlk).AddChannelHbR(ml(iCh,1), ml(iCh,2), iC);
                            yAvgStdOut(iBlk).AddChannelHbT(ml(iCh,1), ml(iCh,2), iC);
                        end
                    end

                    %%%% Snirf stuff: Once we get to the last run, we've accumulated our averages.
                    %%%% Now we can set channel descriptors for avg and standard deviation
                    if iRun == length(yAvgRuns)
                        yAvgStdOut(iBlk).AppendDataTimeSeries(yAvgStd(:,:,:,iC));
                    end
                end
            end
        end
    end
end


function density = p02_density ( m, n, point )

%*****************************************************************************80
%
%% P02_DENSITY returns the density for problem 02.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Per-Olof Persson and Gilbert Strang,
%    A Simple Mesh Generator in MATLAB,
%    SIAM Review,
%    Volume 46, Number 2, June 2004, pages 329-345.
%
%  Parameters:
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, real POINT(M,N), the coordinates of the points.
%
%    Output, real DENSITY(N), the mesh density at each point.
%
  density = ones ( 1, n );

  return
end


function v = isnaturalnumber(x)

v = isnumeric(x) & x > 0 & round(x) == x;