function [VV,TT,FF,TN,IFF] = cdt(varargin)
  % CDT compute the constrained delaunay triangulation of a given mesh using
  % tetgen.
  %
  % [VV,TT,FF,TN,IFF] = cdt(V,F,'ParameterName',ParameterValue, ...)
  %
  % Inputs:
  %   V  #V by dim list of mesh positions
  %   F  #F by dim list of face indices
  %   Optional:
  %     'TriangleFlags' followed by a string of additional triangle flags, e.g.
  %       '-q'
  %     'TetgenFlags' followed by a string of additional tetgen flags, e.g.
  %       '-J'
  %     'UseBoundingBox' followed by whether to use an explicit bounding box
  %       rather than tetgen's convex hull
  %     'BoundingBoxPush' followed by a push factor to enlargen the bounding
  %       box around its centroid {1.01}
  %     'BoundingBoxUpsample' followed by a factor f, to upsample the bounding
  %       box faces until min(doublearea(BV,BF))<f*max(doublearea(V,F)) {inf}
  %     'Quiet' followed by true or {false}
  % Outputs:
  %   VV  #VV by dim list of vertices over which TT is defined, should
  %     contain V as a prefix and should be exactly V unless F self-intersects
  %   TT  #TT by dim+1 list of tetrahedra indices
  %   FF  #FF by dim list of F potentially subdivided to be defined over VV,
  %     should be exactly F unless F self-intersects
  %   TN  #TT by dim+1 list of tetrahedra neighbors
  %   IFF  #FF by 1 list of original facets indices corresponding to each facet
  %     in FF
  %

  % parse input
  V = varargin{1};
  if nargin>=2
    F = varargin{2};
  else
    F = [];
  end
  % default values for optional input
  tetgen_flags = '';
  triangle_flags = '';
  use_bounding_box = 0;
  bb_push = 1.01;
  bb_ups = inf;
  quiet = 0;

  % parse any optional input
  ii = 3;
  while(ii <= nargin)
    switch varargin{ii}
    case 'TriangleFlags'
      ii = ii + 1;
      assert(ii<=nargin);
      triangle_flags = varargin{ii};
    case 'TetgenFlags'
      ii = ii + 1;
      assert(ii<=nargin);
      tetgen_flags = varargin{ii};
    case 'UseBoundingBox'
      ii = ii+1;
      assert(ii<=nargin);
      use_bounding_box = 1*(varargin{ii});
    case 'BoundingBoxPush'
      ii = ii+1;
      assert(ii<=nargin);
      bb_push = varargin{ii};
    case 'BoundingBoxUpsample'
      ii = ii+1;
      assert(ii<=nargin);
      bb_ups = varargin{ii};
    case 'Quiet'
      ii = ii+1;
      assert(ii<=nargin);
      quiet = varargin{ii};
      quiet = quiet * 1;
    otherwise
      error(['Unsupported parameter: ' varargin{ii}]);
    end
    ii = ii + 1;
  end

  if quiet
    fid = fopen('/dev/null','w');
  else
    fid = 1;
  end

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Check for cached result, do NOT edit variables until cache is checked,
  % your function code comes later. See below
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  clear varargin;
  % get a list of current variables in this scope, this is the input "state"
  variables = who;
  % get a temporary file's name
  tmpf = [tempname('.') '.mat'];
  % save the "state" to file, so we can get a md5 checksum
  save(tmpf,'-regexp',sprintf('^%s$|',variables{:}),'-ascii');
  % get md5 checksum on input "state", we append .cache.mat to the check sum
  % because we'll use the checksum as the cache file name
  [s,cache_name] = system(['/sbin/md5 -r ' tmpf ' | awk ''{printf "."$1".cache.mat"}''']);
  % clean up
  delete(tmpf);
  clear s tmpf variables;
  % If the checksum cache file exists then we've seen this input "state"
  % before, load in cached output "state"
  if(exist(cache_name,'file'))
    fprintf_(fid,'Cache exists. Using cache...\n');
    % use cache
    load(cache_name);
  % Otherwise this is the first time we've seen this input "state", so we
  % execute the function as usual and save the output "state" to the cache
  else
    fprintf_(fid,'First time. Creating cache...\n');

    dim = size(V,2);
    assert(numel(F) ==0 || dim >= size(F,2), sprintf( ...
      'dimension of V (%d) < simplex size (%d)',dim,size(F,2)));
    switch dim
    case 2
      % we're dealing with edges
      E = F;
      if use_bounding_box
        [BV,BF] = bounding_box([max(V)+eps;min(V)-eps]);
        dir = [sign(bsxfun(@minus,BV,mean(BV)))];
        mag_max = max(sqrt(sum(bsxfun(@minus,BV,mean(BV)).^2,2)));
        BV = bsxfun(@plus,bb_push*mag_max*dir,mean(BV));
        BE = [];
        EmBE = E;
      else
        BV = [];
        BF = [];
        % explicitly add convex hull
        F = delaunay(V);
        BE = outline(F);
        EmBE = setdiff(sort(E,2),sort(BE,2),'rows');
      end
      [VV,TT] = triangle([V;BV],[BE;EmBE;size(V,1)+BF],[],'Flags',triangle_flags);

      % This is a bullshit hack way of determining which edges were subdivided
      % A better way is using boundary markers in triangle like in
      % diffcurves_test.m
      if nargout>=3
      % First determine which edges were not subdivided
      E_indices = 1:size(E,1);
      [maintained] = ismember(sort(E,2),sort(edges(TT),2),'rows');
      EE = E(maintained,:);
      IEE = E_indices(maintained);
      % and those that were
      ES = E(~maintained,:);
      IES = E_indices(~maintained);
      % hopefully #ES is small, let Alec know if it isn't, we should rewrite this
      if size(ES,1)>100
        warning('many (%d) edges to subdivide, this could be slow',size(ES,1));
      end
      % build edge-length adjacency matrix
      C = adjacency_edge_cost_matrix(VV,edges(TT));
      % average edge length for tolerances
      h = avgedge(VV,TT);
      % loop over edges that were subdivided
      for e = 1:size(ES,1)
        % get shortest path from source to dest
        [D,P] = dijk(C,ES(e,2),ES(e,1));
        % check that D is what a straight line path should be

        orig_len = sqrt(sum((V(ES(e,2),:)-V(ES(e,1),:)).^2,2));
        if abs(orig_len-D)>1e-13*h
          warning('path %d to %d may not be straight: |%g - %g| = %g', ...
            ES(e,2),ES(e,1),orig_len,D,abs(orig_len-D));
        end
        d = ES(e,1);
        NE = [];
        % trace back path
        while d~=ES(e,2)
          NE = [NE;d P(d)];
          d = P(d);
        end
        % append to edges
        EE = [EE;NE];
        IEE = [IEE(:);repmat(IES(e),size(NE,1),1)];
      end
      % rename to match output
      FF = EE;
      end
      if nargout >= 5
        IFF = IEE;
      end
      if nargout >= 4
        % Compute element neighbors
        TN = triangle_triangle_adjacency(TT);
      end
    case 3

      % It's really important that we have at least tetgen 1.5
      [status,result] = system([path_to_tetgen ' -help']);
      tetgen_version = ...
        str2double(regexprep(result,'.*Version ([0-9].[0-9]).*','$1'));
      if isnan(tetgen_version) || tetgen_version < 1.5
        error('%s version (%g) < 1.5',path_to_tetgen,tetgen_version);
      end

      FF = F;

      % Q: Should clean up be the caller's responsibility?
      % A: Yes, I think so. We can parse tetgen and give hints.

      %% number of input points
      %n = size(V,1);

      %% Deal with duplicate input points
      %[V,I,J] = remove_duplicate_vertices(V);
      %if n ~= size(V,1)
      %  warning('cdt: %d exactly duplicate points removed from input',n-size(V,1));
      %  n = size(V,1);
      %  % Remap faces
      %  FF = J(F);
      %end

      %if ~isempty(F)
      %  NF = F( (F(:,1) ~= F(:,2)) & (F(:,2) ~= F(:,3)) & (F(:,3) ~= F(:,1)),:);
      %  if size(NF,1) < size(F,1)
      %    warning('cdt: %d faces with combinatorally duplicate vertices removed\n', ...
      %      size(F,1)-size(NF,1));
      %    FF = NF;
      %  end
      %end

      % Try to mesh with all faces included directly
      BM = -ones(size(FF,1),1);

      if use_bounding_box
        [BV,BF] = bounding_box(V);
        % Subdivide
        if ~isempty(FF) && size(FF,2)==3
          max_dblA = max(doublearea(V,FF));
          while min(doublearea(BV,BF))> bb_ups*max_dblA
            [BV,BF] = upsample(BV,BF);
          end
        end
        % push a little a away
        BV = bsxfun(@plus,bb_push*bsxfun(@minus,BV,mean(BV)),mean(BV));
        BF = BF + size(V,1);
        V = [V;BV];
        FF = [FF;BF];
        % true boundary marker
        BM = [BM;ones(size(BF,1),1)];
      end

      prefix = tempname;
      poly_filename = [prefix '.poly'];
      writePOLY_tetgen(poly_filename,V,FF,[],'BoundaryMarkers',BM);

      % -p: mesh PLC
      % -C: check consistency of result
      % -c: retain convex hull, doesn't seem to play nicely with -q
      %% -O0: optimization level
      %% -Y: no steiner points on boundary
      %% -J: Do not jettison duplicate vertices (we should have already handled
      %%   these)
      % -n: output neighbor information
      %% -F: suppress output of face information
      %% -S0: specifies maximum number of added points (may still add schoenhardt
      %   points)
      % There seems to be a secret -o[val] flag that optimizes the max dihedral
      % angle
      delaunay_flags = '-pCn';
      if ~use_bounding_box
        % then retain convex hull. Note: this seems broken, hence the option to
        % use bounding box
        delaunay_flags = [delaunay_flags 'c'];
      end
      %delaunay_flags = '-pq0.75 -a0.0002 -O5YcJnFg';

      command = [path_to_tetgen ' ' delaunay_flags ' ' tetgen_flags ' ' poly_filename];
      fprintf_(fid,'%s\n',command);
      if quiet
        [status, result] = system(command);
      else
        [status, result] = system(command,'-echo');
      end
      fprintf_(fid,'%s',result);
      if status ~= 0
        fprintf_(fid,'%s',result);
      else
        % Print some warnings based on tetgen output
        if strfind(result,'Steiner points on boundary edges')
          fprintf_(fid,'%s',result);
          warning('Tetgen added steiner points on boundary');
        end
        if strfind(result,'Jettisoning redundants points.')
          fprintf_(fid,'%s',result);
          warning('Tetgen removed duplicate points');
        end

      end

      % See terminatetetgen() in tetgen.h
      switch(status)
      case 0
      case 3
        error('Self intersections. Try selfintersect() or remove self-intersections');
      %% Self-intersection
      %  warning('Throwing away self-intersecting facets');
      %  % Seems tetgen sets status=3 if self-intersecting
      %  % Rerun and detect self-intersecting faces
      %  % -p: mesh PLC, -d: detect all self intersections, -J: don't jettison
      %  % duplicate points (since we want self-intersecting faces defined over
      %  % original vertices)
      %  selfintersection_flags = '-pdJ ';
      %  command = [path_to_tetgen ' ' selfintersection_flags ' ' poly_filename];
      %  fprintf_(fid,command);
      %  [status, result] = system(command);
      %  if strfind(result,'No faces are intersecting.')
      %    fprintf_(fid,'%s',result);
      %    error('Tetgen unsure whether there are self-intersections');
      %  end
      %  assert(status==0);
      %  % tetgen always writes output to file:
      %  face_filename = [prefix '.1.face'];
      %  node_filename = [prefix '.1.node'];
      %  % faces participating in self-intersections
      %  % Faces will index new nodes, but they better be the input ones
      %  IF = readFACE(face_filename);
      %  % clean up temp files
      %  delete(face_filename);
      %  %VV = readNODE(node_filename);
      %  %assert(size(VV,1)==size(V,1));
      %  %delete(node_filename);

      %  % Segments aren't supported by tetgen the way I'd like them to be (i.e. I
      %  % get seg faults)
      %  %% Get edges of intersecting faces
      %  %IFE = edges(IF);
      %  %IFsegs = mat2cell(IFE,ones(size(IFE,1),1),[2]);

      %  % get orignal faces \ intersecting faces
      %  % Using sort like this assumes that tetgen ignores orientation
      %  FmIF = setdiff(sort(FF,2),sort(IF,2),'rows');
      %  Facets = [];
      %  Facets.facets = mat2cell(FmIF,ones(size(FmIF,1),1),[size(FmIF,2)]);
      %  Facets.boundary_marker = -ones(numel(Facets.facets),1);
      %  Facets.holes = cell(numel(Facets.facets),1);

      %  % Rewrite poly file
      %  writePOLY(poly_filename,V,Facets,[]);

      %  % shoot for the moon
      %  command = [path_to_tetgen ' ' delaunay_flags ' ' tetgen_flags ' ' poly_filename];
      %  fprintf_(fid,command);
      %  [status, result] = system(command);
      %  result
      %  status
      case 4
      % Small feature
        error('Try again with reduced T?');
      case 5
      % close input facets
        error('Try again with -Y');
      case 6
      % close input facets
        error('Input error. Check yo` input');
      otherwise
        error('Tetgen returned status %d != 0',status);
      end

      % tetgen always writes output to file:
      %   xxxx.1.ele  tetrahedra
      %   xxxx.1.node tetrahedra vertices
      ele_filename = [prefix '.1.ele'];
      face_filename = [prefix '.1.face'];
      node_filename = [prefix '.1.node'];
      neigh_filename = [prefix '.1.neigh'];

      %delete(poly_filename);

      VV = readNODE(node_filename);
      TT = readELE(ele_filename);
      TN = readNEIGH(neigh_filename);
      TN(TN>=0) = TN(TN>=0)-1;

      [FF,BF] = readFACE(face_filename);
      %FF = FF-1;
      FF = FF(BF==-1,:);

      %[VV1,TT1] = readMESH(mesh_filename);
      % TODO: handle duplicate input vertices in a reasonable way
      % TODO: Tetgen seems to add steiners when input has coplanar neighboring
      % triangles (aka triangulated planar quads). It seems its enough to do:
      % V = V+eps*rand(size(V));
      if ~quiet
        if size(VV,1) > size(V,1)
          warning('New mesh has extra %d vertices',size(VV,1)-size(V,1));
        elseif size(VV,1) < size(V,1)
          warning('New mesh has %d fewer vertices',size(V,1)-size(VV,1));
        elseif max(abs(VV-V))>eps
          warning('max(abs(VV-V)) = %g > %g',max(abs(VV-V)),eps);
          %% Remap to original vertex list
          %TT = I(TT);
          %VV = V;
        end
      end
      %%% Reverse order so that boundary_faces(TT) meets CCW convention
      %TT = TT(:,[3 2 1 4]);
      %TN = TN(:,[3 2 1 4]);

      %% remove bounding box facets
      %if use_bounding_box
      %  old_FF_count = size(FF,1);
      %  FF = ...
      %    FF(all(reshape(~ismember(VV(FF(:),:),BV,'rows'),size(FF,1),3),2),:);
      %  rm_count = old_FF_count-size(FF,1);
      %  switch rm_count
      %  case 0:11
      %    warning('Only removed %d boundary facets (instead of 12)');
      %  case 12
      %    % alles gut
      %  otherwise
      %    warning('Removed %d boundary facets (instead of 12)',rm_count);
      %  end
      %end
    otherwise
      error(sprintf('Unsupported dimension (%d)',dim));
    end

    if nargout>=3
    [IN] = in_elements(FF,TT);
    if ~all(IN)
       warning('%d faces not in elements',sum(~IN));
    end
    end

    % get list of variables present in this scope at finish of function code,
    % this is the output "state"
    variables = who;
    % save output "state" to file, using md5 checksum cache file name
    save(cache_name,'-regexp',sprintf('^%s$|',variables{:}));

  end
end

%% local fprint variant for cross-latform functionality
function fprintf_(fid,varargin)
    if fid < 0
        % on windows there is no dev/null
        return
    else
        fprintf(fid,varargin{:});
    end
end


function test
load trimesh2d;
zfe   = zeros(numel(xfe),1);
nodes = [xfe,yfe,zfe];
triangles = trife;
filename  = 'testSTL.stl';
writeSTL(nodes,triangles,filename);
%% 100k nodes and triangles test(~17MB stl file)
nodesOneM          = rand(100000,3);
trianglesOneM      = ones(100000,3);
trianglesOneM(:,2) = 2;
trianglesOneM(:,3) = 3;
filenameOneM       = 'test100k.stl';
a                  = clock;
writeSTL(nodesOneM,trianglesOneM,filenameOneM);
b                  = clock;
time               = b-a;
    %machine performance
    %http://www.mathworks.com/help/matlab/ref/bench.html(LU 0.54, FFT 0.651,
    %output for my machine:ODE 0.2263, Sparse 0.7735, 2D 1.4288, 3D 1.24)

end


function L = cmpndLikelihood(noise, mu, varsigma, y)

% CMPNDLIKELIHOOD Likelihood of data under compound noise model.

% NOISE

% NOISE

L = zeros(size(mu));
for i = 1:length(noise.comp)
  L(:, i) = noiseLikelihood(noise.comp{i},...
                mu(:, i), ...
                varsigma(:, i), ...
                y(:, i));
end


function stop = tfocs_stop( x, nonsmoothF, optTol )
% tfocs_stop : TFOCS stopping condition
%
%   $Revision: 0.1.2 $  $Date: 2012/09/15 $
%
  global subprob_Dg_y subprob_optim

  [ ~, x_prox ]   = nonsmoothF( x - subprob_Dg_y ,1);
    subprob_optim = norm( x_prox - x ,'inf');
    stop          = subprob_optim <= optTol;


function [ params ] = rnn_stack2params( stack, eI, W_t, sum_tied )
%RNN_STACK2PARAMS converts stack structure of RNN weights to single vector
%   Takes a stack strcutre with stack{l}.W and stack{l}.b for each layer
%   Also takes single matrix of temporal weights W_t
%   The flag sum_tied will sum tied encoder and decoder weights.
%       This is useful for gradient aggregation
%   Verifies the stack structure conforms to their descriptions in eI
%   Namely checks eI.layerSizes, eI.inputDim, and eI.temporalLayer

%% assume no weight tieing if parameter unset
if ~isfield(eI, 'tieWeights')
    eI.tieWeights = 0;
end;
if ~exist('sum_tied','var')
    sum_tied = false;
end;
%% default short circuits to false
if ~isfield(eI, 'shortCircuit')
    eI.shortCircuit = 0;
end;
% check short circuit consistency
assert( ~xor(eI.shortCircuit, isfield(stack{end},'W_ss')));
%% check first layer dimensions
assert( size(stack{1}.W,1) == eI.layerSizes(1));
assert( size(stack{1}.W,2) == eI.inputDim);
assert( size(stack{1}.b,1) == eI.layerSizes(1));
%% stack first layer
params = [ stack{1}.W(:); stack{1}.b(:)];
%% check and stack all layers. no special treatment of output layer
for l = 2 : numel(eI.layerSizes)
    assert( size(stack{l}.W,1) == eI.layerSizes(l));
    assert( size(stack{l}.W,2) == eI.layerSizes(l-1));
    assert( size(stack{l}.b,1) == eI.layerSizes(l));
    if ~eI.tieWeights || (l <= numel(eI.layerSizes)/2 ...
            || l == numel(eI.layerSizes))
        % untied layer, save the weights
        if eI.tieWeights && sum_tied && l < numel(eI.layerSizes)
            % sum decoder weights if its a tied encoder layer
            lDec = numel(eI.layerSizes) - l + 1 ;
            params = [ params; reshape(stack{l}.W + stack{lDec}.W',[],1)];
        else
            params = [ params; stack{l}.W(:)];
        end;
    end;
    % always aggregate bias
    params = [ params; stack{l}.b(:)];
end
%% append temporal weight matrix
if ~isempty(W_t) || eI.temporalLayer
    assert(size(W_t,1) == eI.layerSizes(eI.temporalLayer));
    assert(size(W_t,2) == eI.layerSizes(eI.temporalLayer));
    params = [ params; W_t(:)];
end
%% append short circuit matrix
if eI.shortCircuit
    params = [params; stack{end}.W_ss(:)];
end;


classdef mme_line3p < mp.mm_element

%   MATPOWER
%   Copyright (c) 2022, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

%     properties
%     end

    methods
        function name = name(obj)
            name = 'line3p';
        end

        function obj = data_model_update(obj, mm, nm, dm, mpopt)
            dme = obj.data_model_element(dm);
            nme = obj.network_model_element(nm);

            pp = nm.get_idx('port');
            nn = nme.np/2;

            %% branch active power flow
            for p = 1:nn
                s_fr = nm.soln.gs_(pp.i1.line3p(p):pp.iN.line3p(p)) * dm.base_kva;
                s_to = nm.soln.gs_(pp.i1.line3p(p+nn):pp.iN.line3p(p+nn)) * dm.base_kva;

                %% update in the data model
                dme.tab.(sprintf('pl%d_fr', p))(dme.on) = real(s_fr);
                dme.tab.(sprintf('ql%d_fr', p))(dme.on) = imag(s_fr);
                dme.tab.(sprintf('pl%d_to', p))(dme.on) = real(s_to);
                dme.tab.(sprintf('ql%d_to', p))(dme.on) = imag(s_to);
            end
        end
    end     %% methods
end         %% classdef


function [fgsegment keepFascicles] = dtiSegmentFiberWithNiftiRoi(fg, targetROIfile, targetROI2file, thresholdmm)

% Extracting streamlines terminating within a certain distance from ROIs (e.g. gray matter ROIs)
%
% INPUT:
% fg: fg structure
% targetROIfile: the name of first ROI nifti file
% targetROI2file: the name of second ROI nifti file
% thresholdmm: the distance threshold in mm; the streamlines with endpoint within the threshold will be selected.
%
% Example:
% fg = fgRead(wholebrainFG);
% targetROIfile = 'Left_V3A.nii.gz';
% targetROI2file = 'Left_hV4.nii.gz';
% thresholdmm = 4;
%  [fgsegment keepFascicles] = dtiSegmentFiberWithNiftiRoi(fg, targetROIfile, targetROI2file, thresholdmm)
% (C) Hiromasa Takemura, CiNet, 2017

if notDefined('thresholdmm')
thresholdmm = 4;
end

% Load ROIs
roi1 = niftiRead(targetROIfile);
roi2 = niftiRead(targetROI2file);

% Define threshold in image space (assuming isotropic)
% Note that the threshold is squared (we keep using squared number in subsequent process)
threshold = (thresholdmm./(roi1.pixdim(1)))^2;

% Get acpc to image transformation matrix
acpc2img = inv(roi1.qto_xyz);

% Transfer fg into image coordinate
fgImg = dtiXformFiberCoords(fg, acpc2img,'img');

%% Select fibers within a certain distance from each ROIs
fprintf('Segmenting tracts from Connectome ...\n')

streamlinenum = length(fgImg.fibers);
% Extract ACPC coordinate of tract endpoints
for kk = 1:streamlinenum
    fibercoordinate = cell2mat(fgImg.fibers(kk));
    fiberlength = size(fibercoordinate);
        firstfiberend(kk,1) = fibercoordinate(1,1);
        firstfiberend(kk,2) = fibercoordinate(2,1);
        firstfiberend(kk,3) = fibercoordinate(3,1);
        secondfiberend(kk,1) = fibercoordinate(1,fiberlength(2));
        secondfiberend(kk,2) = fibercoordinate(2,fiberlength(2));
        secondfiberend(kk,3) = fibercoordinate(3,fiberlength(2));

    clear fibercoordinate fiberlength
end

%% Extract coordinates of ROIs
[tcoords(:,1), tcoords(:,2), tcoords(:,3)]= ind2sub(size(roi1.data), find(roi1.data));
[t2coords(:,1), t2coords(:,2), t2coords(:,3)]= ind2sub(size(roi2.data), find(roi2.data));

% Chose streamlines in which one endpoint is closer to first ROI, and the other
% endpoint is close to second ROI
for kp = 1:streamlinenum
    [indices_ff(kp), bestSqDis_ff(kp)] = nearpoints(transpose(firstfiberend(kp,:)), transpose(tcoords));
    [indices_ss(kp), bestSqDis_ss(kp)] = nearpoints(transpose(secondfiberend(kp,:)),transpose(t2coords));
    [indices_fs(kp), bestSqDis_fs(kp)] = nearpoints(transpose(firstfiberend(kp,:)), transpose(t2coords));
    [indices_sf(kp), bestSqDis_sf(kp)] = nearpoints(transpose(secondfiberend(kp,:)),transpose(tcoords));
end

% Select fibers within the threshold, then create keepFascicles
% structure
fffiber = find(bestSqDis_ff <threshold);
ssfiber = find(bestSqDis_ss <threshold);
fsfiber = find(bestSqDis_fs <threshold);
sffiber = find(bestSqDis_sf <threshold);

ffssfiber  = intersect(fffiber,ssfiber); % First streamline endpoint is near first ROI, the another endpoint is near second ROI
fssffiber = intersect(fsfiber,sffiber); % First streamline endpoint is near second ROI, the another endpoint is near first ROI
bothfiber = transpose(union(transpose(ffssfiber), transpose(fssffiber),'rows'));
bothsize = size(bothfiber);

%% If the selected number of streamlines are non-zero, extract those streamlines
if bothsize(2)>0
    keepFascicles = zeros(streamlinenum,1);
    for ik = 1:length(bothfiber)
        keepFascicles(bothfiber(ik)) = 1;
    end
fgsegment = fgExtract(fg, logical(keepFascicles), 'keep');
else
fprintf('No streamlines satisfied criteria ...\n')
end
end


function p = addMultipliedEqualityCuts(p)

newRows = [];
for i =  p.linears
    for j = 1:p.K.f
        row = p.F_struc(j,:);
        used = find(row(2:end));
        if ~any(p.variabletype(used))
            % Linear constraint
            ok = 1;
            for k = 1:length(used)
                find1 = findrows(p.bilinears(:,2:end),[i used(k)]);
                find2 = findrows(p.bilinears(:,2:end),[used(k) i]);
                if (isempty(find1) & isempty(find2))
                    ok = 0;
                    break
                else
                    monom(k) = unique([find1 find2]);
                end
            end
            if ok
                monom = p.bilinears(monom,1);
                row(1+monom) = row(1+used);
                row(1+used) = 0;
                row(1+i) = row(1);
                row(1)=0;
                newRows = [newRows;row];
            end
        end
    end
end
if ~isempty(newRows)
    p.F_struc = [newRows;p.F_struc];
    p.K.f = p.K.f + size(newRows,1);
end


classdef StressNormPduringIterAsPostprocess < handle

    properties (Access = public)

    end

    properties (Access = private)
        mesh
        dataRes
        iterC
        cost
        fileNameIter
        finalIter
    end

    properties (Access = private)
        microCase
        path
        fileResName
        fileNameMesh
        pNorm
        valueT
        caseName
    end

    methods (Access = public)

        function obj = StressNormPduringIterAsPostprocess()
            obj.init();
            obj.obtainCost();
            value = zeros(length(obj.pNorm),obj.finalIter);
            for iter = 1:obj.finalIter
                fNameIter = [obj.fileResName,num2str(iter)];
                obj.wrapResAndMesh(fNameIter);
                value(:,iter) = obj.computeStressNorm();
                if mod(iter,1)== 0
                obj.plotValue(value,iter)
                end
            end
           obj.plotFinal(value);
        end

    end

    methods (Access = private)

        function init(obj)
            obj.valueT = 0.18324;
            %obj.valueT  = 34.6295;
            %obj.valueT = 0.5646;
            %obj.microCase = 'Rectangle';
            obj.microCase = 'SuperEllipse';
            meshType = 'Small';
            %meshType  = 'Medium';
            obj.finalIter = 73;%607;%20;%46;%607;%42;18;405;42;296;57;46;250;485;250;
%             fCase = [obj.microCase,meshType];
%             obj.caseName = ['ExperimentingPlot'];
%             obj.path = ['/media/alex/My Passport/LatticeResults/StressNorm',fCase,'/'];
%             obj.fileResName  = ['ExperimentingPlot'];

            fCase = [obj.microCase,meshType];
            obj.caseName = ['ExperimentingPlot7',fCase];
            obj.path = ['/media/alex/My Passport/LatticeResults/',obj.caseName,'/'];
            obj.fileResName  = ['ExperimentingPlot',obj.microCase];
            obj.fileNameMesh = ['CantileverSquare',meshType];
            obj.pNorm = 2:2:16;
        end

        function obtainCost(obj)
            fNameMon = fullfile(obj.path,'Monitoring.fig');
            h = openfig(fNameMon,'invisible');
            handles = findobj(h,'Type','line');
            iter = get(handles(5),'Xdata');
            c = get(handles(5),'Ydata');
            close all
            obj.iterC = iter;
            obj.cost  = c;
        end

        function plotValue(obj,value,iter)
            figure(1)
            clf
            plot(obj.iterC,obj.cost*obj.valueT)
            hold on
            plot(1:iter,value(:,1:iter))
            hold off
            drawnow
        end

        function plotFinal(obj,value)
            f = figure(1);
            clf
            p{1} = plot(obj.iterC,obj.cost*obj.valueT);
            hold on
            for i = 1:size(value,1)
              p{i+1} = plot(value(i,:));
            end
           pP = plotPrinter(f,p);
           fName = ['/home/alex/Dropbox/GregoireMeeting7Decembre/',obj.caseName];
           pP.print(fName)
        end

        function wrapResAndMesh(obj,fileNameIter)
            s.folderPath = obj.path;
            s.fileName   = fileNameIter;
            w = WrapperMshResFiles(s);
            w.compute();
            obj.mesh    = w.mesh;
            obj.dataRes = w.dataRes;
        end

         function value = computeStressNorm(obj)
            s.m1            = obj.dataRes.DesignVar1;
            s.m2            = obj.dataRes.DesignVar2;
            s.alpha         = obj.dataRes.AlphaGauss';
            switch obj.microCase
                case 'Rectangle'
                    s.vademecumName = 'SuperEllipseQMax';
                case 'SuperEllipse'
                    s.vademecumName = 'SuperEllipseQOptAnalytic';
            end
            s.mesh          = obj.mesh;
            s.fileName      = obj.fileNameMesh;
            s.pNorm         = obj.pNorm;
            sC = StressNormFromVademecumComputer(s);
            value = sC.compute();
         end

    end

end


function [endpos, maxlevel] = match_bracket(str,startpos,brackets)
%
% [endpos, maxlevel] = match_bracket(str,startpos,brackets)
%
% Looking for the position of a closing bracket token in a string
%
% authors:Qianqian Fang (q.fang <at> neu.edu)
%
% input:
%      str: the full string to be searched
%      startpos: the index in the string as the start position to search; the
%               startpos must be at least 1 greater than the opening bracket position
%      brackets: (optional), a string of length 2, with the first character
%               being the opening token and the 2nd being the closing token.
%               if not given, brackets is set to '[]' to find matching square-brackets;
%               for example, '{}' looks for a matching closing curly-bracket in
%               the string key(pos(startpos,:end))
%
% output:
%      endpos: if a matching bracket is found, return its position in the original
%              string
%      maxlevel: return the depth of the enclosed brackets between the searched pair,
%              includig the searching pair. For example, the matching closing-bracket
%              of the 1st square bracket (startpos=2) in  '[[[]],[]]' returns a
%              position of 9, with a maximum depth of 3; searching for the closing
%              bracket for the 2nd square bracket (startpos=3) returns a position of
%              5 and max-depth of 2.
%
% example:
%      str='[[ [1,2], 1], 10, [5,10] ]';
%      [p1,dep]=match_bracket(str,3)
%      [p2,dep]=match_bracket(str,2)
%      [p3,dep]=match_bracket(str,3)
%
% license:
%     BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details
%
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
%

if(nargin<3)
    brackets='[]';
end
count = str(startpos:end);
flag=cumsum(count==brackets(1))-cumsum(count==brackets(2))+1;
endpos = find(flag==0,1);
maxlevel=max(flag(1:endpos));
endpos = endpos + startpos-1;


function [ResultsAllCellLines] = performPPP(ResultsAllCellLines,mets,step_size,samples,step_num,direct)
% This function performs the a phase plane analysis. The analysis starts from zero and proceed `step_num*step_size` in the specified direction and for two exchanges.
% the results of the analysis will be saved into `ResultsAllCellLines`.
%
% USAGE:
%
%    [ResultsAllCellLines] = performPPP(ResultsAllCellLines, mets, step_size, samples, step_num, direct)
%
% INPUTS:
%    ResultsAllCellLines:
%    samples:                 Conditions
%    mets:                    Set of two metabolites to test e.g.  mets ={`EX_glc(e)`, `EX_gln(e)`; `EX_o2(e)`, `EX_o2(e)`}
%    step_size:               Step size for metabolites specified in mets e.g., `step_size` = 100
%    direct:                  Direction for metabolites specified in mets: uptake (-1) or secretion (1), e.g., direct = [-1,-1,-1,-1];
%    step_num:                Number of steps (1000/20 = 50), step_num = [5,5;5,5]
%
% OUTPUT:
%    ResultsAllCellLines:     The matrix of growth rates are added to the `ResultsAllCellLines` structure alond with the values or the bounds using the same of the manipulated exchanges
%
% .. Author: - Maike K. Aurich 08/07/15 (performed as in Jeff Orth et al. 2010, Supplemental tutorial.)

bound_size = max(max(step_num));
for k=1:length(samples)
    k
    model1 = eval(['ResultsAllCellLines.' samples{k} '.modelPruned']);

    for p=1:size(mets,1)
        bounds = zeros(bound_size,2); % allocate space to fill in bounds
        growthRates=zeros(step_num(p,1),step_num(p,2));
        model=model1;

        for i=1:step_num(p,1)
            if direct(p,1)==1
                bounds(i,1) = direct(p,1)*i*step_size(p,1)- step_size(p,1);
                model=changeRxnBounds(model,mets{p,1},bounds(i,1),'b');
            else
                bounds(i,1) = direct(p,1)*i*step_size(p,1)+ step_size(p,1);
                model=changeRxnBounds(model,mets{p,1},bounds(i,1),'b');
            end

            for j=1:step_num(p,2)
               if direct(p,2)==1
                bounds(j,2) = direct(p,2)*j*step_size(p,2)- step_size(p,2);
                model=changeRxnBounds(model,mets{p,2},bounds(j,2),'b');
               else
                   bounds(j,2) = direct(p,2)*j*step_size(p,2)+ step_size(p,2);
                model=changeRxnBounds(model,mets{p,2},bounds(j,2),'b');
               end
                FBAsolution=optimizeCbModel(model,'max');
                growthRates(i,j)=FBAsolution.f;
                clear FBAsolution
            end
        end
        if contains(mets{p,1},'[')
            name  = ['phasePlane_' strtok(mets{p,1}, '[') '_' strtok(mets{p,2}, '[')];
        else
            name  = ['phasePlane_' strtok(mets{p,1}, '(') '_' strtok(mets{p,2}, '(')];
        end

        ResultsAllCellLines.(samples{k}).(name).growthRates= growthRates;
        ResultsAllCellLines.(samples{k}).(name).bounds =  bounds;
        clear bounds model growthRates
    end

    clear model1
    save('PPP120', '-v7.3');
end
end


% caliper() - Measure a set of spatial components of a given data epoch relative to
%           a reference epoch and decomposition.
% Usage:
%   >> [amp,window]=caliper(newepoch,refepoch,weights,compnums,filtnums,times,'noplot');
%
% Inputs:
%     newepoch = (nchannels,ntimes) new data epoch
%     refepoch = a (nchannels,ntimes) reference data epoch
%     weights  = (nchannels,ncomponents) unmixing matrix (e.g., ICA weights*sphere)
%     compnums = vector of component numbers to return amplitudes for {def|0: all}
%     filtnums = [srate highpass lowpass] filter limits for refepoch {def|0: allpass}
%     times    = [start_ms end_ms] epoch latency limits, else latencies vector {def|0: 0:EEG.pnts-1}
%     'noplot' = produce no plots {default: plots windows for the first <=3 components}
%
% Outputs:
%     amps = (1,length(compnums)) vector of mean signed component rms amplitudes
%     windows = (length(compnums)),length(times)) matrix of tapering windows used
%
% Notes:
%   Function caliper() works as follows: First the reference epoch is decomposed using
%   the given weight matrix (may be ICA, PCA, or etc). Next, the time course of the
%   main lobe of the activation in the reference epoch (from max to 1st min, forward
%   and backward in time from abs max, optionally after bandpass filtering) is used
%   to window the new epoch. Then, the windowed new epoch is decomposed by the same
%   weight matrix, and signed rms amplitude (across the channels) is returned of the
%   projection of each of the specified component numbers integrated across the windowed
%   epoch. If not otherwise specified, plots the windows for the first <= 3 components listed.
%
% Example: Given a grand mean response epoch and weight matrix, it can be used
%   to measure amps of grand mean components in single-subject averages.
%
% Authors: Scott Makeig & Marissa Westerfield, SCCN/INC/UCSD, La Jolla, 11/2000

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

% Edit History:
% 12/05/00 -- added fig showing data, ref activation, and window vector -mw
% 12/19/00 -- adjusted new icaproj() args -sm
% 01-25-02 reformated help & license -ad

function [amps,windows] = caliper(newepoch,refepoch,weights,compnums,filtnums,times,noplot)

if nargin < 3
  help caliper
  return
end

if nargin<4
  compnums = 0;
end

nchans = size(newepoch,1);
ntimes = size(newepoch,2);

if compnums(1) == 0 | isempty(compnums(1))
   compnums = 1:nchans;
end

if min(compnums) < 1 | max(compnums) > size(weights,2)
   help caliper
   return
end

if nargin<5
  filtnums = [];
else
  if isempty(filtnums)
      filtnums = [];
  elseif length(filtnums)==1 & filtnums(1)==0
     filtnums = [];
  elseif length(filtnums) ~= 3
     fprintf('\ncaliper(): filter parameters (filtnums) must have length 3.\n')
     return
  end
end

if nargin< 6  | isempty(times) | (length(times)==1 & times(1)==0)
  times = 0:ntimes-1;
else
  if length(times) ~= ntimes
    if length(times) ~= 2
      fprintf('caliper(): times argument should be [startms endms] or vector.\n')
      return
    else
      times = times(1):(times(2)-times(1))/(ntimes-1):times(2);
      times = times(1:ntimes);
    end
  end
end

if nargin < 7
   noplot = 0;
else
   noplot = 1;
end

refact = weights(compnums,:)*refepoch; % size (length(compnums),ntimes)
newact = weights(compnums,:)*newepoch;

if length(filtnums) == 3
  if ~exist('eegfilt')
    fprintf('caliper(): function eegfilt() not found - not filtering refepoch.\n');
  else
   try
      refact = eegfilt(refact,filtnums(1),filtnums(2),filtnums(3));
   catch
      fprintf('\n%s',lasterr)
      return
   end
  end
end

if size(weights,1) == size(weights,2)
   winv = inv(weights);
else
   winv = pinv(weights);
end
winvrms = sqrt(mean(winv.*winv)); % map rms amplitudes

amps = [];
windows = [];
n = 1; % component index
for c=compnums
  if floor(c) ~= c
    help caliper
    fprintf('\ncaliper(): component numbers must be integers.\n')
    return
  end

  [lobemax i] = max(abs(refact(n,:)));
  f = i+1;
  oldact = lobemax;
  while f>0 & f<=ntimes & abs(refact(n,f)) < oldact
    oldact = abs(refact(n,f));
    f = f+1;
  end % f is now one past end of "main lobe"
  lobeend = f-1;

  f = i-1;
  oldact = lobemax;
  while f>0 & f<=ntimes & abs(refact(n,f)) < oldact
    oldact = abs(refact(n,f));
    f = f-1;
  end % f is now one past start of "main lobe"
  lobestart = f+1;

  refact(n,1:lobestart) = zeros(1,length(1:lobestart));
  refact(n,lobeend:end) = zeros(1,length(lobeend:ntimes));
  windows = [windows; refact(n,:)];

  refnorm = sum(refact(n,:));
  if abs(refnorm)<1e-25
    fprintf('caliper(): near-zero activation for component %d - returning NaN amp.\n',c)
    amps = [amps NaN];
  else
    refact(n,:) = refact(n,:)/refnorm; % make reference epoch window sum to 1
    amps = [amps winvrms(c)*sum(refact(n,:).*newact(n,:))];
  end
  n = n+1;
  if ~noplot & n <= 4  %%% only plot out at most the first 3 components
     refproj = icaproj(refepoch,weights,c);
     refproj = env(refproj);
     windproj = winv(:,c)*(refact(n-1,:)*refnorm);
     windproj = env(windproj);
     figure; plot(times,newepoch(2:nchans,:),'g');
     hold on;h=plot(times,newepoch(1,:),'g');
     hold on;h=plot(times,newepoch(1,:),'g',...
                    times,refproj(1,:),'b',...
                    times,windproj(1,:),'r','LineWidth',2);
     hold on;plot(times,refproj(2,:),'b',times,windproj(2,:),'r','LineWidth',2);
     set(h(1),'linewidth',1);
     legend(h,'new data','comp. act.','window');
     title(['Component ',int2str(c),';  rms amplitude = ',num2str(amps(n-1))],...
            'FontSize',14);
     ylabel('Potential (uV)');
  end;             %% endif
end % c


function [hE,hV]=wgPlot(adjMat,coord,varargin)
%function [hE,hV]=wgPlot(adjMat,coord,varargin)
%
% Weighted Graph Plot from adjacency matrix [adjMat] and vertices
% coordinate [coord].
%
% INPUT:
%    [adjMat] = N x N sparse square adjacency matrix.
%     [coord] = N x 2 matrix of vertex coordinates of the graph to be plotted.
%  [varargin] = are specified as parameter value pairs where the parameters are
%     'edgeColorMap' = m1 x 3 edge colormap for coloring edges by their
%                      weight, {default=cool}
%        'edgeWidth' = scalar specifying the width of the edges. {default=0.1}
%     'vertexMarker' = single char, can be {.ox+*sdv^<>ph} as in plot {default='.'}
%   'vertexColorMap' = m2 x 3 vertex color map for coloring vertices by their
%                      weight, {default=summer}
%     'vertexWeight' = N x 1 vector of vertex weight that overrides using the
%                      diagonal of [adjMat] for specifying vertex size.
%      'vertexScale' = scalar vertex scaling factor for specifying scaling
%                      the size of vertices. {default=100}
%   'vertexmetadata' = N x 1 vector of vertex meta data for coloring the verticies.
% OUTPUT:
%  [hE] = vector/scalar of handles to edges of the drawn graph (1 per color).
%  [hV] = scalar handles to vertices of the drawn graph.
%
% SEE ALSO: gplot, treeplot, spy, plot
%
% By: Michael Wu  --  michael.wu@lithium.com (May 2009)
%
%====================

% Set default parameter values
%--------------------
h=gca; prh; hold on; axis off;
axesArea(h,[6 7 5 5]);
plotParm={'markerSize',6,'lineWidth',0.1,'marker','.','MarkerEdgeColor',[1,0.5,0.2]};
siz=size(adjMat);
vrtxSiz=100;
edgeMap=cool;
vrtxMap=summer;

% Parse parameter value pairs
%--------------------
nVarArgin=length(varargin);
for kk=1:2:nVarArgin
	switch lower(varargin{kk})
    case 'edgecolormap'
      edgeMap=varargin{kk+1};
    case 'edgewidth'
      plotParm=[plotParm,{'lineWidth',varargin{kk+1}}];
    case 'vertexmarker'
      plotParm=[plotParm,{'marker',varargin{kk+1}}];
    case 'vertexcolormap'
      vrtxMap=varargin{kk+1};
    case 'vertexweight'
      vrtxWt=varargin{kk+1};
    case 'vertexmetadata'
      vrtxCol=varargin{kk+1};
    case 'vertexscale'
      vrtxSiz=varargin{kk+1};
    otherwise
      error(['wgPlot >< Unknown parameter ''',varargin{kk},'''.']) ;
  end
end

% Determine if diagonal is weighted.
%--------------------
if exist('vrtxWt','var')
  vWt=vrtxWt;
else
  vWt=diag(adjMat);
end
vWeighted=length(setdiff(unique(vWt),0))>1;

% Map edge weight to edge colormap
%--------------------
if ~all(vWt==0)
  adjMat(speye(siz)~=0)=0;
end  % if ~any

% Determine if edges are weighted
%--------------------
[ii,jj,eWt] = find(adjMat);
qq=unique([ii,jj]);
minEWt=min(eWt);
maxEWt=max(eWt);
eWtRange=maxEWt-minEWt;
eWeighted=eWtRange>0;

% Map edge weight to edge colormap
%--------------------
if eWeighted
  neColor=size(edgeMap,1);
  eWt=ceil((neColor-1)*(eWt-minEWt)/(maxEWt-minEWt)+1);
end  % if eWtRange

% Plot edges
%--------------------
if eWeighted
  hE=[];
  maxX=max(coord(qq,1));
  minX=min(coord(qq,1));
  maxY=max(coord(qq,2));
  minY=min(coord(qq,2));
  legLim=linspace(minX,maxX,neColor+1);
  yStep=(maxY-minY)/20;
  legY=minY-yStep;

  for kk=1:neColor
    p=find(eWt==kk);
    nSegment=length(p);
    x=[coord(ii(p),1),coord(jj(p),1),repmat(nan,nSegment,1)]';
    y=[coord(ii(p),2),coord(jj(p),2),repmat(nan,nSegment,1)]';
    hE=[hE,plot(x(:),y(:),'color',edgeMap(kk,:),plotParm{:})];
    % Draw legend bar
    line([legLim(kk),legLim(kk+1)],[legY,legY],'lineWidth',15,'color',edgeMap(kk,:));
  end  % for kk

  % Draw Legend Label
  text([legLim(1),legLim(end)],[legY-0.5*yStep,legY-0.5*yStep], ...
    {num2str(minEWt),num2str(maxEWt)},'HorizontalAlignment','center','color',[0.5,0.5,0.5]);
else
    nSegment=length(ii);
    x=[coord(ii,1),coord(jj,1),nan(nSegment,1)]';
    y=[coord(ii,2),coord(jj,2),nan(nSegment,1)]';
    hE=plot(x(:),y(:),plotParm{:});
end  % if eWeighted

% Plot vertices
%--------------------
if vWeighted
  % Map vertex weight to vertex size
  %--------------------
  minVwt=min(vWt);
  maxVwt=max(vWt);
  vWt=vrtxSiz*(vWt-minVwt)/(maxVwt-minVwt)+1;

  % Map vertex metadata to vertex colormap
  %--------------------
  if exist('vrtxCol','var')
    colormap(vrtxMap);
    hV=scatter(coord(qq,1),coord(qq,2),vWt,vrtxCol,'filled');
    colorbar;
  else
    hV=scatter(coord(qq,1),coord(qq,2),vWt,'filled','MarkerFaceColor',[1,0.5,0.2]);
  end

else
  %hV=plot(coord(:,1),coord(:,2),plotParm{:},'LineStyle','none');
  hV=plot(coord(qq,1),coord(qq,2),plotParm{:},'LineStyle','none');
end

% Set axes
%--------------------
axis tight;
ax=axis;
dxRange=(ax(2)-ax(1))/500;
dyRange=(ax(4)-ax(3))/500;
axis([ax(1)-dxRange,ax(2)+dxRange,ax(3)-dyRange,ax(4)+dyRange]);


clear all; close all; clc;
%% Info Generative Adversarial Network
%% Settings
args.maxepochs = 5; args.c_weight = 1; args.z_dim = 128;
args.batch_size = 16; args.image_size = [64,64,3];
args.lrD = 0.0002; args.lrG = 0.001; args.beta1 = 0.5;
args.beta2 = 0.999; args.cc_dim = 1; args.dc_dim = 10;
args.sample_size = 100;
%% Weights, Biases, Offsets and Scales
%% Generator
[paramsGen,stGen] = initializeGen(args);
%% Discriminator
[paramsDis,stDis] = initializeDis(args);
%% Train
out = false; epoch = 0; global_iter = 0; count = 1;
% average Gradient and average Gradient squared holders
avgG.Dis = []; avgGS.Dis = []; avgG.Gen = []; avgGS.Gen = [];

while ~out
    tic; epoch = epoch+1;
    shuffleid = randperm(100000);
    fprintf('Epoch %d\n',epoch)
    for i=1:floor(length(shuffleid)/args.batch_size)
        global_iter = global_iter+1;
        idx = (i-1)*args.batch_size+1:i*args.batch_size;
        XBatch=miniBatch(shuffleid(idx));

        [GradDis,GradGen,stDis,stGen] = ...
                dlfeval(@modelGradients,XBatch,genNoiseCDC(args),...
                paramsDis,paramsGen,args,stDis,stGen);

        % Update Discriminator network parameters
        [paramsDis,avgG.Dis,avgGS.Dis] = ...
            adamupdate(paramsDis, GradDis, ...
            avgG.Dis, avgGS.Dis, global_iter, ...
            args.lrD, args.beta1, args.beta2);

        % Update Generator network parameters
        [paramsGen,avgG.Gen,avgGS.Gen] = ...
            adamupdate(paramsGen, GradGen, ...
            avgG.Gen, avgGS.Gen, global_iter, ...
            args.lrG, args.beta1, args.beta2);

        if i==1 || rem(i,20) == 0
            % progress plot
            progressplot(args,paramsGen,stGen)
        end

        if rem(global_iter,count^2)==0 || rem(global_iter,500)==0
            h = gcf;
            % Capture the plot as an image
            frame = getframe(h);
            im = frame2im(frame);
            [imind,cm] = rgb2ind(im,256);
            % Write to the GIF File
            if count == 1
              imwrite(imind,cm,'InfoGANcelebA.gif','gif', 'Loopcount',inf);
            else
              imwrite(imind,cm,'InfoGANcelebA.gif','gif','WriteMode','append');
            end

            count = count+1;
        end

    end

    elapsedTime = toc;
    disp("Epoch "+epoch+". Time taken for epoch = "+elapsedTime + "s")

    if epoch == args.maxepochs
        out = true;
    end
end

%% Help Functions
%% miniBatch
function dlx = miniBatch(ids)
path = 'D:\44754\Documents\Data\celeba-dataset\img_align_celeba\img_align_celeba\';
filesA = dir([path '*.jpg']);
dlx = [];
for i = 1:length(ids)
    imj=imresize(imread([path filesA(ids(i)).name]),[64,64]);
    imj=preprocess(imj);
    dlx = cat(4,dlx,im2double(imj));
end
dlx = gpdl(dlx);
end
%% preprocess
function x = preprocess(x)
x = double(x)./255;
x = (x-.5)./.5;
x = reshape(x,64,64,3,[]);
end
%% Weight Initialization
function parameter = initializeGaussian(parameterSize)
parameter = randn(parameterSize, 'single') .* 0.01;
end
%% extract data
function x = gatext(x)
x = gather(extractdata(x));
end
%% gpu dl array wrapper
function dlx = gpdl(x,labels)
if nargin < 2
    labels='SSCB';
end
dlx = gpuArray(dlarray(single(x),labels));
end
%% Generator
function [dly,st] = Generator(dlx,params,st)
dly = dlx;
exstatbatch='[dly,st] = batchnormwrap(dly,params,st,%d);';
exstattran = 'dly = dltranspconv(dly,params.TCW%d,params.TCb%d,"Stride",%d,"Cropping",%d);';
exstatrelu = 'dly = relu(dly);';

for i = 1:5
    if i==1
        eval(sprintf(exstattran,i,i,1,0))
    elseif i==5
        eval(sprintf(exstattran,i,i,2,1))
        dly = tanh(dly);
    else
        eval(sprintf(exstattran,i,i,2,1))
        eval(sprintf(exstatbatch,i-1))
        eval(exstatrelu)
    end
end
end
%% Discriminator
function [dly,st] = Discriminator(dlx,params,args,st)
dly = dlx;
exstatconv ='dly = dlconv(dly,params.CNW%d,params.CNb%d,"Stride",%d,"Padding",%d);';
exstatleak = 'dly = leakyrelu(dly,.1);';
exstatbatch='[dly,st] = batchnormwrap(dly,params,st,%d);';

for i = 1:5
    if i == 1
        eval(sprintf(exstatconv,i,i,2,1))
        eval(exstatleak)
    elseif i == 5
        eval(sprintf(exstatconv,i,i,1,0))
    else
        eval(sprintf(exstatconv,i,i,2,1))
        eval(sprintf(exstatbatch,i-1))
        eval(exstatleak)
    end
end
dly = gpdl(reshape(dly,1+args.cc_dim+args.dc_dim,[]),'CB');
dly(1,:) = sigmoid(dly(1,:));
dly(args.cc_dim+2:end,:) = softmax(dly(args.cc_dim+2:end,:));

end
%% General Noise
function out = genNoiseCDC(args)
noi = randn([args.z_dim,args.batch_size]);
out = [noi;gen_cc([args.cc_dim,args.batch_size]);...
    gen_dc([args.dc_dim,args.batch_size])];
out = reshape(out,1,1,args.z_dim+args.cc_dim+args.dc_dim,[]);
out = gpuArray(dlarray(out,'SSCB'));
end
%% Generate Discrete Code
function out = gen_dc(shape)
out = zeros(shape);
random_cate = randi([1,shape(1)],shape(2),1);
for i = 1:length(random_cate)
    out(random_cate(i),i) = 1;
end
end
%% Generate Continuous Code
function out = gen_cc(shape)
out = randn(shape)*0.5;
end
%% Progress Plot
function progressplot(args,paramsGen,stGen)
fixednoise = zeros(args.z_dim,args.sample_size);
tmp = zeros(args.cc_dim,args.sample_size);
for i = 1:10
    tmp(1,(i-1)*10+1:i*10) = linspace(-2,2,10);
end
cc = tmp;

tmp = zeros(args.dc_dim,args.sample_size);
for i = 1:10
    tmp(i,(i-1)*10+1:i*10) = 1;
end
dc = tmp;

fake_data = gpdl(reshape(cat(1,fixednoise,cc,dc),1,1,...
    args.z_dim+args.cc_dim+args.dc_dim,[]));
fake_images = extractdata(Generator(fake_data,paramsGen,stGen));

fig = gcf;
if ~isempty(fig.Children)
    delete(fig.Children)
end

I = imtile(fake_images);
I = rescale(I);
imagesc(I)
title("Generated Images")

drawnow;

end
%% Report Progress
function [d_loss,g_loss] = reportprogress(x,z,paramsDis,...
    paramsGen,args,stDis,stGen)
fake_images = Generator(z,paramsGen,stGen);
d_output_real = Discriminator(x,paramsDis,args,stDis);
d_output_fake = Discriminator(fake_images,paramsDis,args,stDis);

% Loss due to true or not
d_loss_a = -mean(log(d_output_real(1,:))+log(1-d_output_fake(1,:)));
g_loss_a = -mean(log(d_output_fake(1,:)));

% cc loss
output_cc = d_output_fake(2,:);
d_loss_cc = mean((output_cc/0.5).^2);

% softmax classification loss
output_dc = d_output_fake(3:end,:);
d_loss_dc = -(mean(sum(z(args.z_dim+args.cc_dim+1:end,:).*output_dc,1))+...
    mean(sum(z(args.z_dim+args.cc_dim+1:end,:).*z(args.z_dim+args.cc_dim+1:end,:),1)));

% Discriminator Loss
d_loss = d_loss_a+args.c_weight*d_loss_cc+d_loss_dc;
% Generator Loss
g_loss = g_loss_a+args.c_weight*d_loss_cc+d_loss_dc;
end
%% Model Gradients
function [GradDis,GradGen,stDis,stGen] = modelGradients(x,z,paramsDis,...
    paramsGen,args,stDis,stGen)
[fake_images,stGen] = Generator(z,paramsGen,stGen);
d_output_real = Discriminator(x,paramsDis,args,stDis);
[d_output_fake,stDis] = Discriminator(fake_images,paramsDis,args,stDis);

% Loss due to true or not
d_loss_a = -mean(log(d_output_real(1,:))+log(1-d_output_fake(1,:)));
g_loss_a = -mean(log(d_output_fake(1,:)));

% cc loss
output_cc = d_output_fake(2,:);
d_loss_cc = mean((output_cc/0.5).^2);

% softmax classification loss
output_dc = d_output_fake(3:end,:);
z = gpdl(reshape(z,args.z_dim+args.cc_dim+args.dc_dim,[]),'CB');
d_loss_dc = -(mean(sum(z(args.z_dim+args.cc_dim+1:end,:).*output_dc,1))+...
    mean(sum(z(args.z_dim+args.cc_dim+1:end,:).*z(args.z_dim+args.cc_dim+1:end,:),1)));

% Discriminator Loss
d_loss = d_loss_a+args.c_weight*d_loss_cc+d_loss_dc;
% Generator Loss
g_loss = g_loss_a+args.c_weight*d_loss_cc+d_loss_dc;

% For each network, calculate the gradients with respect to the loss.
GradGen = dlgradient(g_loss,paramsGen,'RetainData',true);
GradDis = dlgradient(d_loss,paramsDis);

end
%% Initialize Generator params
function [paramsGen,stGen] = initializeGen(args)
paramsGen.TCW1 = dlarray(initializeGaussian([4,4,1024,...
    args.z_dim+args.cc_dim+args.dc_dim]));
paramsGen.TCb1 = dlarray(zeros(1024,1,'single'));
paramsGen.TCW2 = dlarray(initializeGaussian([4,4,512,1024]));
paramsGen.TCb2 = dlarray(zeros(512,1,'single'));
paramsGen.BNo1 = dlarray(zeros(512,1,'single'));
paramsGen.BNs1 = dlarray(ones(512,1,'single'));
paramsGen.TCW3 = dlarray(initializeGaussian([4,4,256,512]));
paramsGen.TCb3 = dlarray(zeros(256,1,'single'));
paramsGen.BNo2 = dlarray(zeros(256,1,'single'));
paramsGen.BNs2 = dlarray(ones(256,1,'single'));
paramsGen.TCW4 = dlarray(initializeGaussian([4,4,128,256]));
paramsGen.TCb4 = dlarray(zeros(128,1,'single'));
paramsGen.BNo3 = dlarray(zeros(128,1,'single'));
paramsGen.BNs3 = dlarray(ones(128,1,'single'));
paramsGen.TCW5 = dlarray(initializeGaussian([4,4,3,128]));
paramsGen.TCb5 = dlarray(zeros(3,1,'single'));

% States for Batch Norm
stGen.BN1 = []; stGen.BN2 = []; stGen.BN3 = [];
end
%% Initialize Discriminator params
function [paramsDis,stDis] = initializeDis(args)
paramsDis.CNW1 = dlarray(initializeGaussian([4,4,3,128]));
paramsDis.CNb1 = dlarray(zeros(128,1,'single'));
paramsDis.CNW2 = dlarray(initializeGaussian([4,4,128,256]));
paramsDis.CNb2 = dlarray(zeros(256,1,'single'));
paramsDis.BNo1 = dlarray(zeros(256,1,'single'));
paramsDis.BNs1 = dlarray(ones(256,1,'single'));
paramsDis.CNW3 = dlarray(initializeGaussian([4,4,256,512]));
paramsDis.CNb3 = dlarray(zeros(512,1,'single'));
paramsDis.BNo2 = dlarray(zeros(512,1,'single'));
paramsDis.BNs2 = dlarray(ones(512,1,'single'));
paramsDis.CNW4 = dlarray(initializeGaussian([4,4,512,1024]));
paramsDis.CNb4 = dlarray(zeros(1024,1,'single'));
paramsDis.BNo3 = dlarray(zeros(1024,1,'single'));
paramsDis.BNs3 = dlarray(ones(1024,1,'single'));
paramsDis.CNW5 = dlarray(initializeGaussian([4,4,1024,...
    1+args.cc_dim+args.dc_dim]));
paramsDis.CNb5 = dlarray(zeros(1+args.cc_dim+args.dc_dim,1,'single'));

% States for Batch Norm
stDis.BN1 = []; stDis.BN2 = []; stDis.BN3 = [];
end
%% batchnormwrap
function [dly,st] = batchnormwrap(dlx,params,st,num)
exstat1=sprintf('if isempty(st.BN%d),',num);
exstat2=sprintf('[dly,st.BN%d.mu,st.BN%d.sig]=batchnorm(dlx,params.BNo%d,params.BNs%d,"MeanDecay",0.8);else,',num*ones(1,4));
exstat3=sprintf('[dly,st.BN%d.mu,st.BN%d.sig]=batchnorm(dlx,params.BNo%d,params.BNs%d,st.BN%d.mu,st.BN%d.sig,"MeanDecay",0.8);end',num*ones(1,6));
eval(strcat(exstat1,exstat2,exstat3));
end


function fixed = p00_fixed_points ( test, m, fixed_num );

%*****************************************************************************80
%
%% P00_FIXED_POINTS returns the fixed points in a problem.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer TEST, the index of the test problem
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer FIXED_NUM, the number of fixed points.
%
%    Output, real FIXED(M,FIXED_NUM), the
%    coordinates of the fixed points.
%
  if ( test == 1 )
    fixed = p01_fixed_points ( m, fixed_num );
  elseif ( test == 2 )
    fixed = p02_fixed_points ( m, fixed_num );
  elseif ( test == 3 )
    fixed = p03_fixed_points ( m, fixed_num );
  elseif ( test == 4 )
    fixed = p04_fixed_points ( m, fixed_num );
  elseif ( test == 5 )
    fixed = p05_fixed_points ( m, fixed_num );
  elseif ( test == 6 )
    fixed = p06_fixed_points ( m, fixed_num );
  elseif ( test == 7 )
    fixed = p07_fixed_points ( m, fixed_num );
  elseif ( test == 8 )
    fixed = p08_fixed_points ( m, fixed_num );
  elseif ( test == 9 )
    fixed = p09_fixed_points ( m, fixed_num );
  elseif ( test == 10 )
    fixed = p10_fixed_points ( m, fixed_num );
  elseif ( test == 11 )
    fixed = p11_fixed_points ( m, fixed_num );
  elseif ( test == 12 )
    fixed = p12_fixed_points ( m, fixed_num );
  elseif ( test == 13 )
    fixed = p13_fixed_points ( m, fixed_num );
  elseif ( test == 14 )
    fixed = p14_fixed_points ( m, fixed_num );
  elseif ( test == 15 )
    fixed = p15_fixed_points ( m, fixed_num );
  else
    fprintf ( 1, '\n' );
    fprintf ( 1, 'P00_FIXED_POINTS - Fatal error!\n' );
    fprintf ( 1, '  Input value of TEST is out of range.\n' );
    error ( 'P00_FIXED_POINTS - Fatal error!' );
  end

  return
end


function rtk=udsol_sppins(rtk)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% The output is centered on the INS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
global glc

x=rtk.ins.x; P=rtk.ins.P;

[rr,Cen]=blh2xyz(x(7:9)); T=Dblh2Dxyz(x(7:9));
rtk.sol.pos=rr';
rtk.sol.vel=(Cen*x(4:6))';
rtk.sol.att=x(1:3)'/glc.D2R;

if rtk.sol.att(3)>=0
    rtk.sol.att(3)=360-rtk.sol.att(3);
else
    rtk.sol.att(3)=-rtk.sol.att(3);
end

posvar=P(7:9,7:9); posvar=T*posvar*T';        %blh_var to xyz_var
velvar=P(4:6,4:6); velvar=Cen*velvar*Cen';    %enu_var to xyz_var
attvar=P(1:3,1:3); attvar=attvar./glc.D2R^2;  %rad_var to deg_var

rtk.sol.posP(1)=posvar(1,1);
rtk.sol.posP(2)=posvar(2,2);
rtk.sol.posP(3)=posvar(3,3);
rtk.sol.posP(4)=posvar(1,2);
rtk.sol.posP(5)=posvar(2,3);
rtk.sol.posP(6)=posvar(1,3);

rtk.sol.velP(1)=velvar(1,1);
rtk.sol.velP(2)=velvar(2,2);
rtk.sol.velP(3)=velvar(3,3);
rtk.sol.velP(4)=velvar(1,2);
rtk.sol.velP(5)=velvar(2,3);
rtk.sol.velP(6)=velvar(1,3);

rtk.sol.attP(1)=attvar(1,1);
rtk.sol.attP(2)=attvar(2,2);
rtk.sol.attP(3)=attvar(3,3);
rtk.sol.attP(4)=attvar(1,2);
rtk.sol.attP(5)=attvar(2,3);
rtk.sol.attP(6)=attvar(1,3);

% update clk and isb
rtk.sol.dtr(1)=rtk.x(rtk.ic+1)/glc.CLIGHT;
rtk.sol.dtr(2)=rtk.x(rtk.ic+2)/glc.CLIGHT;
rtk.sol.dtr(3)=rtk.x(rtk.ic+3)/glc.CLIGHT;
rtk.sol.dtr(4)=rtk.x(rtk.ic+4)/glc.CLIGHT;
rtk.sol.dtr(5)=rtk.x(rtk.ic+5)/glc.CLIGHT;

return


function [F,M,Cq,Cp,QE,Qp] = spm_eeg_invert_EBoptimise(AY,UL,opttype,Qp,Qe,Qe0)
%% function [F,M,Cq,Cp,QE,Qp] = spm_eeg_invert_EBoptimise(AY,UL,opttype,Qp,Qe,Qe0)
%% Empirical Bayes optimization of priors Qp and Qe to fit data AY based on lead fields UL
% AY concatenated dimension reduced trials of M/EEG data
% UL dimension reduced lead field
% Qp source level priors- where Qp{i}.q holds an eigenmode. So source covariance
%                        component is Qp{i}.q*Qp{i}.q'.
%                         Alternately Qp{i} could be full source covariance component
% Qe sensor noise prior
% Qe0 floor of noise power to signal power (posteiror estimate of sensor noise will always be at
% least this big)
% opttype- how to optimize 'ARD','GS' or 'REML'

%% QE sensor noise posterior
%% Cp source level posterior (source by source variance)
%% F free energy
%% M MAP operator
%% Cq conditional variance
%% F free energy
%% Qp contains the posterior in same form as prior

% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging

% Gareth Barnes
% $Id: spm_eeg_invert_EBoptimise.m 6494 2015-07-06 10:23:04Z gareth $

if ~iscell(Qe),
    Qe={Qe};
end;

AYYA=AY*AY'; %% covariance over trials
Q0          = Qe0*trace(AYYA)*Qe{1}; %% fixed (min) level of sensor space variance
% Get source-level priors (using all subjects)
%--------------------------------------------------------------------------
j=1;
ploton=0;
if ploton,
    figure;
end;

[LQpL,Q,sumLQpL,QE,Cy,M,Cp,Cq,Lq]=spm_eeg_assemble_priors(UL,Qp,Qe,ploton);

sparseind=[];
for k=1:length(Qp), %% split up priors into those with sparse (eigenmode) and full matrix form
    if isfield(Qp{k},'q'),
        sparseind=[sparseind k];
    end;
end;
fullind=setxor([1:length(Qp)],sparseind);
Qp_sp=Qp(sparseind);
Qp_full=Qp(fullind);

if isfield(opttype{j},'GSopt'),
    % Greedy search over MSPs
    %% needs to work with sparse covariance matrices Qp{i}.q
    %------------------------------------------------------------------

    if isempty(AY),
        error('NEED AY for greedy search');
    end;

    if ~isempty(sparseind),
        Qp=Qp_sp;
        [LQpL,Q,sumLQpL,QE,Cy,M,Cp,Cq,Lq]=spm_eeg_assemble_priors(UL,Qp,Qe,ploton);

        MVB   = spm_mvb(AY,UL,[],Q,Qe,16);
        %%  THE VERSION BELOW IS MORE PEDESTRIAN BUT EASIER TO FOLLOW
        %  MVB_grb = spm_mvb_slow_grb( AY,UL,Q,QE,16,Q0 );

        Ne=length(Qe);
        QE=zeros(size(Qe{1}));
        for j=1:Ne,
            QE=QE+MVB.h(j)*Qe{j};
        end;

        Qcp           = Q*MVB.cp; %% mvb works with unity dipole moments so here they get scaled back up by priors

        qful=Qcp*Q';

        Qp=compact_form({qful});

        Qp=[Qp_full Qp]; %% keep full components too
        Qe={QE};
        F=max(MVB.F);

    else
        disp('Skipping GS as no eigenmode priors');
        F=-Inf;
    end;

end; %%GS

if  isfield(opttype{j},'ARDopt'),
    %% needs to work with sparse (svd decomposed) source covariance matrices
    Nn=size(AY,2); %% number of data samples used to make up covariance matrix
%    [LQpL,Q,sumLQpL,QE,Cy,M,Cp,Cq,Lq]=spm_eeg_assemble_priors(UL,Qp,Qe,ploton);
    if ~isempty(sparseind),
        Qp=Qp_sp;

        [LQpL,Q,sumLQpL,QE,Cy,M,Cp,Cq,Lq]=spm_eeg_assemble_priors(UL,Qp,Qe,ploton);

        ardthresh=opttype{j}.ARDopt; %%
        fprintf('ARD removing components less than 1/%3.2f max\n',ardthresh);

        %------------------------------------------------------------------

        %% SPM_SP_REML STARTS WITH EIGEN MODES Lq RATHER THAN FULL COV MATRICES
        fprintf('entering REML for ARD')

        %[Cy,h,Ph,F0] = spm_sp_reml(AYYA,[],[Qe Lq],Nn);
        [Cy,h,Ph,F0] = spm_sp_reml(AYYA,[],[Qe Lq],Nn);

        if isnan(F0),
            warning('NAN in ARD stage, dropping out');
            return;
        end;
        % Spatial priors (QP)
        %------------------------------------------------------------------
        % h provides the final weights of the hyperparameters
        Ne    = length(Qe);
        Np    = length(Qp);

        hp    = h(Ne + (1:Np));

        dropind=find(hp<max(hp)/ardthresh);
        fprintf('Removing %d of %d components\n',length(dropind),length(hp));
        hp(dropind)=0;
        keepind=find(hp>max(hp)/ardthresh);

        h=[h(1:Ne) hp(keepind)'];

        [LQpL,Q,sumLQpL,QE,Csensor,M,Cp,Cq,Lq]=spm_eeg_assemble_priors(UL,Qp(keepind),Qe,ploton,h);

        [Cy,h2,Ph,F] = spm_sp_reml(AYYA,[],[Qe Lq],Nn);
        [LQpL,Q,sumLQpL,QE,Csensor,M,Cp,Cq,Lq]=spm_eeg_assemble_priors(UL,Qp(keepind),Qe,ploton,h2);
        % Accumulate empirical priors (New set of patches for the second inversion)
        fprintf('ARD improvement %3.2f\n',F-F0);
        Qp=compact_form({Cp});
        Qp=[Qp_full Qp]; %% keep full components too
    else
        disp('Skipping ARD as no eigenmode priors');
        F=-Inf;
    end; % if LQ empty

end; % ARD

if  isfield(opttype{j},'REMLopt'),
    %  ReML: can work with both full and sparse source covariances
    %------------------------------------------------------------------
    Nn=size(AY,2); %% number of data samples used to make up covariance matrix

    Qp=[Qp_full Qp_sp];

    LQpL=[];

    if numel(Qp)>5,
        warning('Compressing %d priors into one full and one sparse for REML stage',length(Qp));
        count=0;
        Qp=[];
        if ~isempty(Qp_full),
            [dumLQpL,Qdum,sumLQpL,QE,Cy,M,Cp]=spm_eeg_assemble_priors(UL,Qp_full,Qe,ploton);
            count=count+1;
            LQpL{count}=sumLQpL;
            Qp{count}=Cp;
        end;
        if ~isempty(Qp_sp),
            [dumLQpL,Qdum,sumLQpL,QE,Cy,M,Cp]=spm_eeg_assemble_priors(UL,Qp_sp,Qe,ploton);
            count=count+1;
            LQpL{count}=sumLQpL;
            Qp{count}=Cp;
        end;
    else
        [LQpL,Q,sumLQpL,QE]=spm_eeg_assemble_priors(UL,Qp,Qe,ploton);
    end; % if

    %%% NOW OPTMIZE MIXTURE OF PRIOR COVARIANCE COMPS WITH REML

    [Cy,h,Ph,F] = spm_reml_sc(AYYA,[],[Qe LQpL],Nn,-4,16,Q0);

    %% Now convert the original priors to scaled versions of themselves

    [LCpL,Q,sumLCpL,QE,Cy,M,Cp,Cq]=spm_eeg_assemble_priors(UL,Qp,Qe,ploton,h);

    %% THIS NEXT LINE IS JUST A CHECK THAT THE POSTERIORS WORK AS PRIORS F2 should be greater or equal to F

    [Cy2,h2,Ph2,F2] = spm_reml_sc(AYYA,[],[{QE} {sumLCpL}],Nn,-4,16,Q0);

    if F2+1<F,
        F2-F
        error('something wrong here');
    end;

    Qp{1}=Cp;
    %Qp=compact_form({Cp});

end; %% REML opt

% re-do ReML (with informative hyperpriors)
%----------------------------------------------------------------------

function [Qp,Q]=compact_form(QP)

if isfield(QP{1},'q'),
    for j=1:length(QP),
        v=1;
        if isfield(QP{j},'v'),
            v=QP{j}.v;
        end;
        Q(:,j)=QP{j}.q*sqrt(v);
        Qp{j}.q=Q(:,j);
    end;
    disp('already sparse, returning');
    return;
end;

if length(QP)>1,
    error('only for single cells');
end;

[q,v] = spm_svd(QP{1});

if size(v,1)==size(QP{1},1),
    disp('Cannot sparsify returning full cov matrix');
    Qp=QP;
    return
end;

Q=q*sqrt(v); %% eigen vector

for i=1:size(Q,2),
    Qp{i}.q=Q(:,i);
end;
return;


function output = callcbc(interfacedata)

% Standard input interface
model = yalmip2cbc(interfacedata);

options = interfacedata.options;
model.opts = options.cbc;
model.opts.display = options.verbose;

if options.savedebug
    save cbcdebug model
end

showprogress('Calling CBC',options.showprogress);
solvertime = tic;
if nnz(model.H)==0
    [x,fval,exitflag,nodes,xc] = cbc([],model.f, model.A, model.rl, model.ru, model.lb, model.ub, model.xtype,model.sos,model.x0,model.opts);
else
    [x,fval,exitflag,nodes,xc] = cbc(model.H,model.f, model.A, model.rl, model.ru, model.lb, model.ub, model.xtype,model.sos,model.x0,model.opts);
end
solvertime = toc(solvertime);

% No duals
D_struc = [];
if isempty(x)
    x = zeros(length(c),1);
end

% Check, currently not exhaustive...
problem = 0;
switch exitflag
    case {0,2,6}
        problem = 0;
    case {1,8}
        problem = 1;
    case {3,4}
        problem = 3;
    case 5
        problem = 16;
    case 7
        problem = 2;
    otherwise
        problem = -1;
end

infostr = yalmiperror(problem,'CBC');

% Save all data sent to solver?
if options.savesolverinput
    solverinput.model = model;
else
    solverinput = [];
end

% Save all data from the solver?
if options.savesolveroutput
    solveroutput.x = x;
    solveroutput.fval = fval;
    solveroutput.exitflag = exitflag;
    solveroutput.nodes = nodes;
    solveroutput.xc = xc;
else
    solveroutput = [];
end

% Standard interface
output = createOutputStructure(x(:),[],[],problem,infostr,solverinput,solveroutput,solvertime);


function [Ds, D] = spm_eeg_inv_extract(D)
% Exports source activity using the MAP projector
% FORMAT [Ds] = spm_eeg_inv_extract(D)
% Requires:
%
%     D.inv{i}.source.XYZ   - (n x 3) matrix of MNI coordinates
%
% Optional:
%
%     D.inv{i}.source.rad   - radius (mm) of VOIs (default 5 mm)
%     D.inv{i}.source.label - label(s) for sources (cell array)
%     D.inv{i}.source.fname - output file name
%     D.inv{i}.source.type  - output type ('evoked'/'trials')
%__________________________________________________________________________
% Copyright (C) 2011 Wellcome Trust Centre for Neuroimaging

% Vladimir Litvak, Laurence Hunt, Karl Friston
% $Id: spm_eeg_inv_extract.m 7009 2017-02-07 18:14:16Z vladimir $

% SPM data structure
%==========================================================================
try
    inv = D.inv{D.val};
catch
    inv = D.inv{end};
    D.val = numel(D.inv);
end

Ds = [];

% defaults
%--------------------------------------------------------------------------
try, XYZ   = inv.source.XYZ;   catch,  return;                          end
try, rad   = inv.source.rad;   catch,  rad   = 5;                       end
try, label = inv.source.label; catch,  label = {};                      end
try
    fname  = inv.source.fname;
catch
    fname  = fullfile(D.path, ['i' D.fname]);
end
try
    type   =  inv.source.type;
catch
    if isequal(D.type, 'evoked')
        type = 'evoked';
    else
        type = 'trials';
    end
end

if numel(label)<size(XYZ, 1)
    for i = (numel(label)+1):size(XYZ, 1)
        label{i} = ['Source ' num2str(i)];
    end
end

% find relevant vertices
%==========================================================================
vert  = inv.mesh.tess_mni.vert(inv.inverse.Is, :);        % vertices
Ns    = size(XYZ, 1);                        % number of sources
svert = {};
for i = 1:Ns
    dist = sqrt(sum([vert(:,1) - XYZ(i,1), ...
                     vert(:,2) - XYZ(i,2), ...
                     vert(:,3) - XYZ(i,3)].^2, 2));
    if rad > 0
        svert{i} = find(dist < rad);
    else
        [junk,svert{i}] = min(dist);
        XYZ(i, :) = vert(svert{i}, :);
    end
end

% report
%--------------------------------------------------------------------------
Iy = find(cellfun('isempty', svert));
if ~isempty(Iy)
    disp(['No proximal vertices found for source(s) ' num2str(Iy)]);
    disp('These sources will be discarded');

    svert(Iy) = [];
    label(Iy) = [];
    Ns        = numel(label);

    if Ns == 0
        disp('No valid sources - Exiting');
        return;
    end
end

js      = spm_vec(svert);

% get info from inv
%--------------------------------------------------------------------------
scale   = inv.inverse.scale;
J       = inv.inverse.J;
U       = inv.inverse.U; % spatial projector (contains multiple cells if multimodal)
T       = inv.inverse.T; % S in Friston 2008 - temporal projector
TT      = T*T';
M       = inv.inverse.M(js, :);
Ic      = inv.inverse.Ic;
It      = inv.inverse.It;
Np      = length(It);

try
    trial = inv.inverse.trials;
catch
    trial = D.condlist;
end

% get source data
%==========================================================================
MYi    = 1;
switch(type)
    case 'evoked'
        Ne     = length(trial);
        MY     = zeros(size(M,1), Ne*Np);

        for i = 1:Ne
            MY(:, MYi:(MYi+Np-1)) = J{i}(js,:)*T';
            MYi                   = MYi + Np;
        end

        clabel = trial;
    case 'trials'
        Ne     = length(D.indtrial(trial, 'GOOD'));
        MY     = zeros(size(M,1), Ne*Np);
        clabel = {};

        for i = 1:numel(trial)

            c      = D.indtrial(trial{i}, 'GOOD');
            clabel = [clabel D.conditions(c)];

            % conditional expectation of contrast (J*W) and its energy
            %--------------------------------------------------------------
            Nt    = length(c);
            spm_progress_bar('Init',Nt,sprintf('extracting data condition %d',i),'trials');

            for j = 1:Nt

                if ~strcmp(D.modality(1,1), 'Multimodal')

                    % unimodal data
                    %------------------------------------------------------
                    Y     = D(Ic{1},It,c(j))*TT;
                    Y     = U{1}*Y*scale;

                else

                    % multimodal data
                    %------------------------------------------------------
                    for k = 1:length(U)
                        Y       = D(Ic{k},It,c(j))*TT;
                        UY{k,1} = U{k}*Y*scale(k);
                    end
                    Y = spm_cat(UY);
                end

                MY(:, MYi:(MYi+Np-1)) = M*Y;
                MYi                   = MYi+Np;

                spm_progress_bar('Set',j)
            end
            spm_progress_bar('Clear')
        end
end

% compute regional response in terms of first eigenvariate
%==========================================================================
iS    = [0 cumsum(cellfun('length', svert))];
Y     = zeros(Ns, size(MY, 2));

spm_progress_bar('Init', Ns, 'extracting eigenvariates', 'sources');

for i = 1:Ns
    y     = MY((iS(i)+1):iS(i+1),:)';

    [m,n]   = size(y);
    if n>1
        if m > n
            [v,s,v] = svd(y'*y);
            s       = diag(s);
            v       = v(:,1);
            u       = y*v/sqrt(s(1));
        elseif m>1
            [u,s,u] = svd(y*y');
            s       = diag(s);
            u       = u(:,1);
            v       = y'*u/sqrt(s(1));
        end
        d       = sign(sum(v));
        u       = u*d;
        v       = v*d;
        Y(i, :) = u'*sqrt(s(1)/n);
    else
        Y(i, :) = y';
    end

    spm_progress_bar('Set',i);
end

spm_progress_bar('Clear')

% create source dataset
%-----------------------------------------------------------------------
Ds = clone(D, fname, [Ns Np Ne], 3);
Ds = chanlabels(Ds, 1:Ns, label);
Ds = timeonset(Ds, D.time(It(1)));
Ds = chantype(Ds, 1:Ns, 'LFP');
Ds = conditions(Ds, 1:Ne, clabel);
Ds = sensors(Ds, 'MEG', []);
Ds = sensors(Ds, 'EEG', []);
Ds = fiducials(Ds, []);
Ds = rmfield(Ds, fieldnames(Ds));
Ds = condlist(Ds, trial);

spm_progress_bar('Init', Ne, 'writing out data', 'trials');
for i = 1:Ne
    Ds(:,:,i) = Y(:,((i - 1)*Np + 1):i*Np);
    spm_progress_bar('Set',i);
end
spm_progress_bar('Clear');

% store results in the original inv
%-----------------------------------------------------------------------
D.inv{D.val}.source.type  = type;
D.inv{D.val}.source.XYZ   = XYZ;
D.inv{D.val}.source.label = label;
D.inv{D.val}.source.rad   = rad;
D.inv{D.val}.source.fname = fname;

% save headers
%-----------------------------------------------------------------------
save(Ds);


% A real linear filter, usually lowpass, Abstract Method
%
% Copyright (c) 2018 Department of Computer Science,
%                    University of Toronto, Canada,
%                    Vector Institute, Canada
%
% License
% This file is under the LGPL license,  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. This file 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.
%
% This function is part of the Covarep project: http://covarep.github.io/covarep
%
% Author
%  Yingxue Wang <yingxue@cs.toronto.edu>
%  Sean Robertson <sdrobert@cs.toronto.edu>
%

classdef WindowFunction < handle
    methods (Abstract)
        window = get_impulse_response(obj, width)
    end
end


%______________________________________________________________________
function [y,C,R,c1]  = MissData(y,C,R,c1);
%______________________________________________________________________
% PROC missdata
% PURPOSE: eliminates the rows in y & matrices Z, G that correspond to
%          missing data (NaN) in y
% INPUT    y             vector of observations at time t  (n x 1 )
%          S             KF system matrices             (structure)
%                        must contain Z & G
% OUTPUT   y             vector of observations (reduced)   (# x 1)
%          Z G           KF system matrices     (reduced)   (# x ?)
%          L             To restore standard dimensions     (n x #)
%                        where # is the nr of available data in y
%______________________________________________________________________
  ix = ~isnan(y);
  e  = eye(size(y,1));
  L  = e(:,ix);

  y  =  y(ix);
  c1 =  c1(ix);
  C  =  C(ix,:);
  R  =  R(ix,ix);


function ens = comp_eff_node_sizes(ns, cnodes, ev, domain)

dnodes = mysetdiff(1:length(ns), cnodes);
odom = domain(~isemptycell(evidence(domain)));
cdom = myintersect(cnodes, domain);
ddom = myintersect(dnodes, domain);
cobs = myintersect(cdom, odom);
dobs = myintersect(ddom, odom);
ens = ns;
ens(cobs) = 0;
ens(dobs) = 1;


function [Jh,dJh] = calcJacobian(obj, x, dx)
    % calculate the holonomic constraints, Jacobian and its time
    % derivatives
    %
    % Parameters:
    % x: the states @type colvec
    % dx: the first order derivatives @type colvec
    %
    % Return values:
    %  Jh: the first-order Jacobian of the constraint @type matrix
    %  dJh: the time derivative of the Jacobian matrix @type matrix

    switch obj.Model.Type
        case 'FirstOrder'
            if obj.DerivativeOrder == 1
                Jh = feval(obj.Jh_name, x);
                dJh = [];
            else
                Jh = feval(obj.Jh_name, x);
                dJh = feval(obj.dJh_name, x);
            end
        case 'SecondOrder'
            Jh = feval(obj.Jh_name, x);
            dJh = feval(obj.dJh_name, x, dx);
    end

end


function res = bbIntersection(rect1, rect2)
res = zeros(1, 4);
res(1) = max(rect1(1), rect2(1));
res(2) = max(rect1(2), rect2(2));

res(3) = min(rect1(1) + rect1(3), rect2(1) + rect2(3)) - res(1);
res(4) = min(rect1(2) + rect1(4), rect2(2) + rect2(4)) - res(2);

end


function [ft] = au2ft(au)
% Convert length from astronomical units to feet.
% Chad A. Greene 2012
ft = au*490806662372;


 function y = reale(x, arg2)
%function y = reale(x)
%function y = reale(x, tol)
%function y = reale(x, 'warn')
%function y = reale(x, 'error')
%function y = reale(x, 'report')
%function y = reale(x, 'disp')
% return real part of complex data (with error checking).
% checks that imaginary part is negligible (or warning etc. if not)
% Copyright Jeff Fessler, The University of Michigan

com = 'error';
tol = 1e-13;
if nargin > 1
	if ischar(arg2)
		com = arg2;
	elseif isnumeric(arg2)
		tol = arg2;
	end
end

if streq(com, 'disp')
	;
elseif streq(com, 'warn')
	onlywarn = 1;
elseif streq(com, 'error')
	onlywarn = 0;
elseif streq(com, 'report')
	;
else
	error(sprintf('bad argument %s', com))
end

if max(abs(x(:))) == 0
	if any(imag(x(:)) ~= 0)
		error 'max real 0, but imaginary!'
	else
		y = real(x);
		return
end
end

frac = max(abs(imag(x(:)))) / max(abs(x(:)));
if streq(com, 'report')
	printf('imaginary part %g%%', frac * 100)
	return
end

if frac > tol
	t = sprintf('%s: imaginary fraction %g', mfilename, frac);
	if streq(com, 'disp')
		disp(t)
	elseif onlywarn
		disp(t)
	else
		error(t)
	end
end
y = real(x);


function result = glmnetPredict(object,s)

%--------------------------------------------------------------------------
% glmnetPredict.m: make predictions from a "glmnet" object.
%--------------------------------------------------------------------------
%
% DESCRIPTION:
%    Similar to other predict methods, this functions predicts fitted
%    values, logits, coefficients and more from a fitted "glmnet" object.
%
% USAGE:
%    glmnetPredict(object)
%    glmnetPredict(object, type)
%    glmnetPredict(object, type, newx)
%    glmnetPredict(object, type, newx, s)
%
% INPUT ARGUMENTS:
% fit         Fitted "glmnet" model object.
% type        Type of prediction required. Type "link" gives the linear
%             predictors for "binomial" or "multinomial" models; for
%             "gaussian" models it gives the fitted values. Type "response"
%             gives the fitted probabilities for "binomial" or
%             "multinomial"; for "gaussian" type "response" is equivalent
%             to type "link". Type "coefficients" computes the coefficients
%             at the requested values for s. Note that for "binomial"
%             models, results are returned only for the class corresponding
%             to the second level of the factor response. Type "class"
%             applies only to "binomial" or "multinomial" models, and
%             produces the class label corresponding to the maximum
%             probability. Type "nonzero" returns a list of the indices of
%             the nonzero coefficients for each value of s.
% newx        Matrix of new values for x at which predictions are to be
%             made. Must be a matrix; This argument is not used for
%             type=c("coefficients","nonzero")
% s           Value(s) of the penalty parameter lambda at which predictions
%             are required. Default is the entire sequence used to create
%             the model.
%
% DETAILS:
%    The shape of the objects returned are different for "multinomial"
%    objects. glmnetCoef(fit, ...) is equivalent to glmnetPredict(fit, "coefficients", ...)
%
% LICENSE: GPL-2
%
% DATE: 14 Jul 2009
%
% AUTHORS:
%    Algorithm was designed by Jerome Friedman, Trevor Hastie and Rob Tibshirani
%    Fortran code was written by Jerome Friedman
%    R wrapper (from which the MATLAB wrapper was adapted) was written by Trevor Hasite
%    MATLAB wrapper was written and maintained by Hui Jiang, jiangh@stanford.edu
%    Department of Statistics, Stanford University, Stanford, California, USA.
%
% REFERENCES:
%    Friedman, J., Hastie, T. and Tibshirani, R. (2009)
%    Regularization Paths for Generalized Linear Models via Coordinate Descent.
%    Journal of Statistical Software, 33(1), 2010
%
% SEE ALSO:
%    glmnet, glmnetSet, glmnetPrint, glmnetPlot and glmnetCoef methods.
%
% EXAMPLES:
%    x=randn(100,20);
%    y=randn(100,1);
%    g2=randsample(2,100,true);
%    g4=randsample(4,100,true);
%    fit1=glmnet(x,y);
%    glmnetPredict(fit1,'link',x(1:5,:),[0.01,0.005]') % make predictions
%    glmnetPredict(fit1,'coefficients')
%    fit2=glmnet(x,g2,'binomial');
%    glmnetPredict(fit2, 'response', x(2:5,:))
%    glmnetPredict(fit2, 'nonzero')
%    fit3=glmnet(x,g4,'multinomial');
%    glmnetPredict(fit3, 'response', x(1:3,:), 0.01)
%
% DEVELOPMENT:
%    14 Jul 2009: Original version of glmnet.m written.
%    20 Oct 2009: Fixed a bug in bionomial response, pointed out by Ramon
%                 Casanov from Wake Forest University.
%    26 Jan 2010: Fixed a bug in multinomial link and class, pointed out by
%                 Peter Rijnbeek from Erasmus University.
%    23 Jun 2010: Fixed a bug in multinomial with s, pointed out by
%                 Robert Jacobsen from Aalborg University.

% if nargin < 2
%     type = 'link';
% end
%
% if nargin < 3
%     newx = [];
% end
%
% if nargin < 4
%     s = object.lambda;
% end

% if strcmp(object.class, 'elnet')
a0=transpose(object.a0);
nbeta=[a0; object.beta];
% if nargin == 4
lambda=object.lambda;
lamlist=lambda_interp(lambda,s);
nbeta=nbeta(:,lamlist.left).*repmat(lamlist.frac',size(nbeta,1),1) +nbeta(:,lamlist.right).*(1-repmat(lamlist.frac',size(nbeta,1),1));
% end
% if strcmp(type, 'coefficients')
result = nbeta;
% elseif strcmp(type, 'link')
%     result = [ones(size(newx,1),1), newx] * nbeta;
% elseif strcmp(type, 'response')
%     result = [ones(size(newx,1),1), newx] * nbeta;
% elseif strcmp(type, 'nonzero')
%     result = nonzeroCoef(nbeta(2:size(nbeta,1),:), true);
% else
%     error('Unrecognized type');
% end
% elseif strcmp(object.class, 'lognet')
%
%     a0=transpose(object.a0);
%     nbeta=[object.a0; object.beta];
%     if nargin == 4
%         lambda=object.lambda;
%         lamlist=lambda_interp(lambda,s);
%         nbeta=nbeta(:,lamlist.left).*repmat(lamlist.frac',size(nbeta,1),1) +nbeta(:,lamlist.right).*(1-repmat(lamlist.frac',size(nbeta,1),1));
%     end
%     %%%   remember that although the fortran lognet makes predictions
%     %%%   for the first class, we make predictions for the second class
%     %%%   to avoid confusion with 0/1 responses.
%     %%%   glmnet flipped the signs of the coefficients
%     if strcmp(type,'coefficients')
%         result = nbeta;
%     elseif strcmp(type,'nonzero')
%         result = nonzeroCoef(nbeta(2:size(nbeta,1),:), true);
%     else
%         nfit = [ones(size(newx,1),1), newx] * nbeta;
%
%         if strcmp(type,'response')
%             pp=exp(-nfit);
%             result = 1./(1+pp);
%         elseif strcmp(type,'link')
%             result = nfit;
%         elseif strcmp(type,'class')
%             result = (nfit > 0) * 2 + (nfit <= 0) * 1;
%         else
%             error('Unrecognized type');
%         end
%     end
% elseif strcmp(object.class, 'multnet')
%     a0=object.a0;
%     nbeta=object.beta;
%     nclass=size(a0,1);
%     nlambda=length(s);
%     if nargin == 4
%         lambda=object.lambda;
%         lamlist=lambda_interp(lambda,s);
%         for i=1:nclass
%             kbeta=[a0(i,:); nbeta{i}];
% %            kbeta=kbeta(:,lamlist.left)*lamlist.frac +kbeta(:,lamlist.right)*(1-lamlist.frac);
%             kbeta=kbeta(:,lamlist.left).*repmat(lamlist.frac',size(kbeta,1),1)+kbeta(:,lamlist.right).*(1-repmat(lamlist.frac',size(kbeta,1),1));
%             nbeta{i}=kbeta;
%         end
%     else
%         for i=1:nclass
%             nbeta{i} = [a0(i,:);nbeta{i}];
%         end
%     end
%     if strcmp(type, 'coefficients')
%         result = nbeta;
%     elseif strcmp(type, 'nonzero')
%         for i=1:nclass
%             result{i}=nonzeroCoef(nbeta{i}(2:size(nbeta{i},1),:),true);
%         end
%     else
%         npred=size(newx,1);
%         dp = zeros(nclass,nlambda,npred);
%         for i=1:nclass
%             fitk = [ones(size(newx,1),1), newx] * nbeta{i};
%             dp(i,:,:)=dp(i,:,:)+reshape(transpose(fitk),1,nlambda,npred);
%         end
%         if strcmp(type, 'response')
%             pp=exp(dp);
%             psum=sum(pp,1);
%             result = permute(pp./repmat(psum,nclass,1),[3,1,2]);
%         elseif strcmp(type, 'link')
%             result=permute(dp,[3,1,2]);
%         elseif strcmp(type, 'class')
%             dp=permute(dp,[3,1,2]);
%             result = [];
%             for i=1:size(dp,3)
%                 result = [result, softmax(dp(:,:,i))];
%             end
%         else
%             error('Unrecognized type');
%         end
%     end
% else
%     error('Unrecognized class');
% end

%-------------------------------------------------------------
% End private function glmnetPredict
%-------------------------------------------------------------

function result = lambda_interp(lambda,s)
% lambda is the index sequence that is produced by the model
% s is the new vector at which evaluations are required.
% the value is a vector of left and right indices, and a vector of fractions.
% the new values are interpolated bewteen the two using the fraction
% Note: lambda decreases. you take:
% sfrac*left+(1-sfrac*right)

  if length(lambda)==1 % degenerate case of only one lambda
    nums=length(s);
    left=ones(nums,1);
    right=left;
    sfrac=ones(nums,1);
else
      s(s > max(lambda)) = max(lambda);
      s(s < min(lambda)) = min(lambda);
      k=length(lambda);
      sfrac =(lambda(1)-s)/(lambda(1) - lambda(k));
      lambda = (lambda(1) - lambda)/(lambda(1) - lambda(k));
      coord = interp1(lambda, 1:length(lambda), sfrac);
      left = floor(coord);
      right = ceil(coord);
      sfrac=(sfrac-lambda(right))./(lambda(left) - lambda(right));
      sfrac(left==right)=1;
  end
  result.left = left;
  result.right = right;
  result.frac = sfrac;

%-------------------------------------------------------------
% End private function lambda_interp
%-------------------------------------------------------------
%
% function result = softmax(x, gap)
% if nargin < 2
%     gap = false;
% end
% d = size(x);
% maxdist = x(:, 1);
% pclass = repmat(1, d(1), 1);
% for i =2:d(2)
%     l = x(:, i) > maxdist;
%     pclass(l) = i;
%     maxdist(l) = x(l, i);
% end
% if gap
%     x = abs(maxdist - x);
%     x(1:d(1), pclass) = x * repmat(1, d(2));
%     gaps = pmin(x);
% end
% if gap
%     result = {pclass, gaps};
% else
%     result = pclass;
% end

%-------------------------------------------------------------
% End private function softmax
%-------------------------------------------------------------


%==================================================================
%                        General Data File
% Title: TETREAHEDRA
% Units: SI
% Dimensions: 3D
% Type of problem: Plane_Stress
% Type of Phisics: ELASTIC
% Micro/Macro: MACRO
%
%==================================================================

%% Data

Data_prb = {
'TETRAHEDRA';
'SI';
'3D';
'Plane_Stress';
'ELASTIC';
'MACRO';
};

%% Coordinates
% Node                X                Y                Z

coord = [
1            2            0            1
2            2            0          0.5
3            2          0.5            1
4            2          0.5          0.5
5            2            0            0
6            2            1            1
7            1            0            1
8            1            0          0.5
9            1          0.5            1
10            2            1          0.5
11            2          0.5            0
12            1          0.5          0.5
13            2            1            0
14            1            0            0
15            1            1            1
16            1          0.5            0
17            1            1          0.5
18            1            1            0
19            0            0            1
20            0            0          0.5
21            0          0.5            1
22            0          0.5          0.5
23            0            1            1
24            0            0            0
25            0          0.5            0
26            0            1          0.5
27            0            1            0
];

%% Conectivities
% Element        Node(1)                Node(2)                Node(3)                Node(4)                Material

connec = [
1 10 17 12 6 0
2 6 10 4 12 0
3 15 9 12 6 0
4 6 3 9 12 0
5 6 15 17 12 0
6 3 4 12 6 0
7 11 16 12 13 0
8 13 11 4 12 0
9 18 17 12 13 0
10 13 10 17 12 0
11 13 18 16 12 0
12 10 4 12 13 0
13 9 21 23 12 0
14 12 9 15 23 0
15 22 26 23 12 0
16 12 17 26 23 0
17 12 22 21 23 0
18 17 15 23 12 0
19 17 26 27 12 0
20 12 17 18 27 0
21 22 25 27 12 0
22 12 16 25 27 0
23 12 22 26 27 0
24 16 18 27 12 0
25 3 9 12 1 0
26 1 3 4 12 0
27 7 8 12 1 0
28 1 2 8 12 0
29 1 7 9 12 0
30 2 4 12 1 0
31 2 8 12 5 0
32 5 2 4 12 0
33 14 16 12 5 0
34 5 11 16 12 0
35 5 14 8 12 0
36 11 4 12 5 0
37 8 20 19 12 0
38 12 8 7 19 0
39 22 21 19 12 0
40 12 9 21 19 0
41 12 22 20 19 0
42 9 7 19 12 0
43 16 25 24 12 0
44 12 16 14 24 0
45 22 20 24 12 0
46 12 8 20 24 0
47 12 22 25 24 0
48 8 14 24 12 0
];

%% Variable Prescribed
% Node            Dimension                Value

dirichlet_data = [
19 1 0
19 2 0
19 3 0
20 1 0
20 2 0
20 3 0
21 1 0
21 2 0
21 3 0
22 1 0
22 2 0
22 3 0
23 1 0
23 2 0
23 3 0
24 1 0
24 2 0
24 3 0
25 1 0
25 2 0
25 3 0
26 1 0
26 2 0
26 3 0
27 1 0
27 2 0
27 3 0
];

%% Force Prescribed
% Node                Dimension                Value

pointload_complete = [
4 1 0
4 2 -1
];

%% Volumetric Force
% Element        Dim                Force_Dim

Vol_force = [
];

%% Group Elements
% Element        Group_num

Group = [
];

%% Initial Holes
% Elements that are considered holes initially
% Element

Initial_holes = [
];

%% Boundary Elements
% Elements that can not be removed
% Element

Boundary_elements = [
];

%% Micro gauss post
%
% Element

Micro_gauss_post = [
];

%% Micro Slave-Master
% Nodes that are Slaves
% Nodes             Value (1-Slave,0-Master)

Micro_slave = [
];

%% Nodes solid
% Nodes that must remain
% Nodes

nodesolid = unique(pointload_complete(:,1));

%% External border Elements
% Detect the elements that define the edge of the domain
% Element               Node(1)           Node(2)

External_border_elements = [
];

%% External border Nodes
% Detect the nodes that define the edge of the domain
% Node

External_border_nodes = [
];

%% Materials
% Materials that have been used
% Material_Num              Mat_density        Young_Modulus        Poisson

Materials = [
];


function test_issue2169

% WALLTIME 00:10:00
% MEM 2gb
% DEPENDENCY ft_apply_montage

%%

data0 = {};
data0.label = {
  '1'
  '2'
  '3'
  '4'
  '5'
  '6'
  '7'
  '8'
  '9'
  };
data0.trial{1} = [
  1 1 1 1 1 1 1 1 1 1
  2 2 2 2 2 2 2 2 2 2
  3 3 3 3 3 3 3 3 3 3
  4 4 4 4 4 4 4 4 4 4
  5 5 5 5 5 5 5 5 5 5
  6 6 6 6 6 6 6 6 6 6
  7 7 7 7 7 7 7 7 7 7
  8 8 8 8 8 8 8 8 8 8
  9 9 9 9 9 9 9 9 9 9
  ];
data0.time{1} = 1:10;

data1 = data0;
data1.trial{1}(1,10) = nan;

data2 = data0;
data2.trial{1}(2,10) = nan;

data3 = data0;
data3.trial{1}(3,10) = nan;

%%

cfg = [];
cfg.montage.labelold = {'1', '2', '3'};
cfg.montage.labelnew = {'1', '2', '1-2'};
cfg.montage.tra = [
  1  0 0
  0  1 0
  1 -1 0
  ];
reref0 = ft_preprocessing(cfg, data0);
reref1 = ft_preprocessing(cfg, data1);
reref2 = ft_preprocessing(cfg, data2);
reref3 = ft_preprocessing(cfg, data3);

% check that the nans don't spread

assert(~isnan(reref0.trial{1}(1,10)))
assert(~isnan(reref0.trial{1}(2,10)))
assert(~isnan(reref0.trial{1}(3,10)))

assert( isnan(reref1.trial{1}(1,10)))
assert(~isnan(reref1.trial{1}(2,10)))
assert( isnan(reref1.trial{1}(3,10)))

assert(~isnan(reref2.trial{1}(1,10)))
assert( isnan(reref2.trial{1}(2,10)))
assert( isnan(reref2.trial{1}(3,10)))

assert(~isnan(reref3.trial{1}(1,10)))
assert(~isnan(reref3.trial{1}(2,10)))
assert(~isnan(reref3.trial{1}(3,10)))

%%
% repeat the same thing as above, but now for single precision data

data0.trial{1} = single(data0.trial{1});
data1.trial{1} = single(data1.trial{1});
data2.trial{1} = single(data2.trial{1});
data3.trial{1} = single(data3.trial{1});

cfg = [];
cfg.montage.labelold = {'1', '2', '3'};
cfg.montage.labelnew = {'1', '2', '1-2'};
cfg.montage.tra = [
  1  0 0
  0  1 0
  1 -1 0
  ];
reref0 = ft_preprocessing(cfg, data0);
reref1 = ft_preprocessing(cfg, data1);
reref2 = ft_preprocessing(cfg, data2);
reref3 = ft_preprocessing(cfg, data3);

% check that the nans don't spread

assert(~isnan(reref0.trial{1}(1,10)))
assert(~isnan(reref0.trial{1}(2,10)))
assert(~isnan(reref0.trial{1}(3,10)))

assert( isnan(reref1.trial{1}(1,10)))
assert(~isnan(reref1.trial{1}(2,10)))
assert( isnan(reref1.trial{1}(3,10)))

assert(~isnan(reref2.trial{1}(1,10)))
assert( isnan(reref2.trial{1}(2,10)))
assert( isnan(reref2.trial{1}(3,10)))

assert(~isnan(reref3.trial{1}(1,10)))
assert(~isnan(reref3.trial{1}(2,10)))
assert(~isnan(reref3.trial{1}(3,10)))