function [Bj1p,PSp] = FBASE( B,a)
config;
fS = nnconfig.FilterSize;
s=fS*fS-1;
size = nnconfig.ImageSize ;

if nargin == 1
    for j = 1:s
        Bj = reshape(B(:,j),fS,fS);
        Bj1(:,:,j) = rot90(Bj,2);
        PS(:,:,j) = psf2otf(Bj1(:,:,j), size);
    end
    PSp =gpuArray(PS);
    Bj1p = gpuArray(Bj1);
end
if nargin == 2
    for j = 1:s
        Bj = reshape(B(:,j),fS,fS);
        Bj1(:,:,j) = rot90(Bj,2);
    end
    Bj1p = gpuArray(Bj1)  ;
end
end


function [scores model binVals bins] = loglossboostLearnRandomFeatures(...
  data,labels,numIters,initWt,binVals,bins,params,obj,str)

if nargin<8,
  obj = [];
end

if nargin<9,
  str = '';
end

numEx = size(data,1);
wt = initWt;
model = struct('dim',{},'error',{},'dir',{},'tr',{},'alpha',{});

% Initialize with dummy models.
dummywk = struct('dim',1,'error',0.5','dir',1,'tr',0,'alpha',0);
for ndx = 1:numIters
  model(ndx) = dummywk;
end
scores = zeros(numEx,1);

clk = tic;
etimehist = [];
etimehistlength = 25;
nittoutput = 3;
origbins = bins; origdata = data; origbinVals = binVals;

numFeatures = size(origbins,1);
if numFeatures<10000,
  featureSetRatio = 1.1;
  refreshRatio = 100000; % never refresh
elseif numFeatures < 20000
  featureSetRatio = 0.7;
  refreshRatio = 1/10;
else
  featureSetRatio = 0.4;
  refreshRatio = 1/20;
end

% params.numSample = min(params.numSample,round(numEx/2));
for itt = 1:numIters
  if (ceil(itt/refreshRatio/numIters)-ceil( (itt-1)/refreshRatio/numIters) > 0.5)
    % every 1/20th iterations select features to train on.
    selFeatures = rand(1,size(origbins,1))>featureSetRatio;
    feature_map = find(~selFeatures);
    % MAYANK NOV 4 2015. copying and deleting as below is slow
%     bins = origbins;
%     data = origdata;
%     binVals = origbinVals;
%     bins(selFeatures,:) = [];
%     data(:,selFeatures) = [];
%     binVals(:,selFeatures) = [];
    bins = origbins(~selFeatures,:);
    data = origdata(:,~selFeatures);
    binVals = origbinVals(:,~selFeatures);
  end
  count = 0;
  while(count<1)
    [wkRule,wksel] = findWeakRuleSamples(data,labels,wt,binVals,bins,params);
    sel = false(size(labels));
    sel(wksel) = true;
    wkRule.dim = feature_map(wkRule.dim);
    tr = wkRule.tr;
    dir = wkRule.dir;
    dim = wkRule.dim;
    if dir>0,
      tt = ((origdata(:,dim)> tr)-0.5)*2;
    else
      tt = ((origdata(:,dim)<= tr)-0.5)*2;
    end
    curError = sum( (tt.*labels(:)).*wt(:));
    if curError>0,
      break;
    else
      curError = - curError;
      wkRule.dir = -wkRule.dir;
    end
    count = count + 1;
  end
%   if count == 11,
%     fprintf('Too much training\n');
%     break;
%   end

  wkRule.error = 0.5-curError/2;
  wkRule.alpha = 1-2*wkRule.error;
  model(itt) = wkRule;
  scores = myBoostClassify(origdata,model(1:itt));
  tt = scores.*labels;
  wt = initWt./(1+exp(tt));
  wt = wt./sum(wt);

  if( nargin>7 && mod(itt,nittoutput)==0)
    etime = toc(clk);
    etimehist(end+1) = etime;
    if numel(etimehist) > etimehistlength,
      etimehist = etimehist(end-etimehistlength+1:end);
    end
    if ~isempty(obj)
      obj.SetStatus('%s %d%% training done. Time Remaining:%ds ',str,...
        round(itt/numIters*100),round((numIters-itt)/nittoutput*mean(etimehist)));
      drawnow();
    end
    clk = tic;
  end

end
dump = toc(clk);
end


function [ patches, pdm, clmParams ] = Load_CLM_general()
%LOAD_CLM_WILD Summary of this function goes here
%   Detailed explanation goes here
    clmParams = struct;

    clmParams.window_size = [25,25; 23,23; 21,21;];
    clmParams.numPatchIters = size(clmParams.window_size,1);

    [patches] = Load_Patch_Experts( '../models/wild/', 'svr_patches_*_wild.mat', [], [], clmParams);

    % the default PDM to use
    pdmLoc = ['../models/pdm/pdm_68_aligned_wild.mat'];
    load(pdmLoc);

    pdm = struct;
    pdm.M = double(M);
    pdm.E = double(E);
    pdm.V = double(V);

    % the default model parameters to use
    clmParams.regFactor = [35, 27, 20, 5];
    clmParams.sigmaMeanShift = [1.25, 1.375, 1.5, 1.75];
    clmParams.tikhonov_factor = [2.5, 5, 7.5, 12.5];

    clmParams.startScale = 1;
    clmParams.num_RLMS_iter = 10;
    clmParams.fTol = 0.01;
    clmParams.useMultiScale = true;
    clmParams.use_multi_modal = 1;
    clmParams.multi_modal_types  = patches(1).multi_modal_types;

end


function options = gpsimMapInitParam(y, yvar, options);

% GPSIMMAPINITPARAM Creates a set of options for a GPSIMMAP model as the initial parameters.
% FORMAT
% DESC returns a default initialisation for a GPSIMMAP model.
% ARG y :  the values of each gene at the different time points.
% ARG yvar :  the variances of each gene at the different time points.
% ARG options : the values of each gene at the different time points.
% RETURN options : the options structure.
%
% SEEALSO : gpsimMapCreate
%
% COPYRIGHT : Pei Gao, Neil D. Lawrence and Magnus Rattary, 2008

% GPSIM

numGenes = length(options.S);
options.S = ones(1, numGenes);
initOptions = options;
mu = mean(y, 1);
optionDset = [0.01 0.1 0.4 1];
rand('seed',1);

for j = 1:numGenes
  initOptions.S = options.S(j);
  initOptions.gParam = options.gParam(j);
  %    figure(j);
  %    plot(options.times, y(:,j), 'rx');
  %    hold on;
  for di = 1:length(optionDset)
    initOptions.D = optionDset(di);
    initOptions.B = initOptions.D*mu(j);

    model.gene{j}.init{di} = gpsimMapCreate(1, 1, options.times, y(:,j), ...
                                            yvar(:,j), initOptions);
    if strcmp(options.kern, 'mlp')
      model.gene{j}.init{di}.kern.weightVariance = 30;
      model.gene{j}.init{di}.kern.biasVariance = 20;
      % This forces kernel recompute.
      params = gpsimMapExtractParam(model.gene{j}.init{di});
      model.gene{j}.init{di} = ...
          gpsimMapExpandParam(model.gene{j}.init{di}, params);
    elseif strcmp(options.kern, 'rbf')
      model.gene{j}.init{di}.kern.inverseWidth = 0.001;
      params = gpsimMapExtractParam(model.gene{j}.init{di});
      model.gene{j}.init{di} = ...
          gpsimMapExpandParam(model.gene{j}.init{di}, params);
    end

    updateFoptions = defaultOptions;
    model.gene{j}.init{di} = gpsimMapUpdateF(model.gene{j}.init{di}, ...
                                             updateFoptions);
    %       fmean =  mean(model.gene{j}.init{di}.f);
    %       fsd = sqrt(var(model.gene{j}.init{di}.f));
    %       model.gene{j}.init{di}.f = model.gene{j}.init{di}.f - fmean;
    %       model.gene{j}.init{di}.f = model.gene{j}.init{di}.f/fsd;
    %       model.gene{j}.init{di}.S = model.gene{j}.init{di}.S/exp(fmean);
    %       model.gene{j}.init{di}.gParam = model.gene{j}.init{di}.gParam/exp(fmean);
    ypredMean = mean(model.gene{j}.init{di}.ypred);
    ypredScale = sqrt(var(model.gene{j}.init{di}.ypred(model.gene{j}.init{di}.times_index)));
    model.gene{j}.init{di}.B = (model.gene{j}.init{di}.B - initOptions.D* ...
                                (ypredMean - ypredScale*mean(model.gene{j}.init{di}.y)))/ ...
        ypredScale;
    %       if isfield(model.gene{j}.init{di}, 'alpha')
    %         model.gene{j}.init{di}.alpha = model.gene{j}.init{di}.alpha/ypredScale;
    %       end
    if model.gene{j}.init{di}.B < 0 && isfield(model.gene{j}.init{di}, ...
                                               'alpha')
      model.gene{j}.init{di}.alpha = model.gene{j}.init{di}.alpha/ypredScale;
      model.gene{j}.init{di}.alpha = model.gene{j}.init{di}.alpha + ...
          model.gene{j}.init{di}.B;
      model.gene{j}.init{di}.B = 1e-6;
    end
    model.gene{j}.init{di}.S = model.gene{j}.init{di}.S/ypredScale;
    params = gpsimMapExtractParam(model.gene{j}.init{di});
    model.gene{j}.init{di} = gpsimMapExpandParam(model.gene{j}.init{di}, ...
                                                 params);
    f = gpsimMapFunctionalExtractParam(model.gene{j}.init{di});
    model.gene{j}.init{di} = gpsimMapFunctionalExpandParam(model.gene{j}.init{di}, f);
    model.gene{j}.ll(di) = ...
        gpsimMapLogLikelihood(model.gene{j}.init{di});
    %      plot(model.gene{j}.init{di}.mapt, model.gene{j}.init{di}.ypred);
  end
  [value, index] = max(model.gene{j}.ll);
  %    plot(model.gene{j}.init{index}.mapt, model.gene{j}.init{index}.ypred, 'm');

  options.D(j) = optionDset(index);
  options.S(j) = model.gene{j}.init{index}.S;
  %     if model.gene{j}.init{index}.B < 0
  %       if isfield(model.gene{j}.init{index},'alpha')
  %         options.alpha(j) = model.gene{j}.init{index}.alpha + ...
  %             model.gene{j}.init{di}.B;
  %       end
  %       options.B(j) = 1e-6;
  %     else
  if isfield(model.gene{j}.init{index},'alpha')
    options.alpha(j) = model.gene{j}.init{index}.alpha;
  end
  %     end
  options.B(j) = model.gene{j}.init{index}.B;
  options.gParam(j) = model.gene{j}.init{index}.gParam;
end
options.S = rand(1,numGenes);
options.B = options.D.*mu;


classdef DISOpticalFlow < handle
    %DISOPTICALFLOW  DIS optical flow algorithm
    %
    % This class implements the Dense Inverse Search (DIS) optical flow
    % algorithm. More details about the algorithm can be found at
    % [Kroeger2016]. Includes three presets with preselected parameters to
    % provide reasonable trade-off between speed and quality. However, even
    % the slowest preset is still relatively fast, use cv.calcOpticalFlowDF
    % if you need better quality and don't care about speed.
    %
    % This implementation includes several additional features compared to the
    % algorithm described in the paper, including spatial propagation of flow
    % vectors (cv.DISOpticalFlow.UseSpatialPropagation), as well as an option
    % to utilize an initial flow approximation passed to cv.DISOpticalFlow.calc
    % (which is, essentially, temporal propagation, if the previous frame's
    % flow field is passed).
    %
    % ## References
    % [Kroeger2016]:
    % > Till Kroeger, Radu Timofte, Dengxin Dai, and Luc Van Gool.
    % > "Fast optical flow using dense inverse search". In Proceedings of the
    % > European Conference on Computer Vision (ECCV), 2016.
    %
    % See also: cv.DISOpticalFlow.calc
    %

    properties (SetAccess = private)
        % Object ID
        id
    end

    properties (Dependent)
        % Finest level of the Gaussian pyramid on which the flow is computed
        % (zero level corresponds to the original image resolution). The final
        % flow is obtained by bilinear upscaling.
        FinestScale
        % Size of an image patch for matching (in pixels). Normally, default
        % 8x8 patches work well enough in most cases.
        PatchSize
        % Stride between neighbor patches. Must be less than patch size. Lower
        % values correspond to higher flow quality.
        PatchStride
        % Maximum number of gradient descent iterations in the patch inverse
        % search stage. Higher values may improve quality in some cases.
        GradientDescentIterations
        % Number of fixed point iterations of variational refinement per scale.
        % Set to zero to disable variational refinement completely. Higher
        % values will typically result in more smooth and high-quality flow.
        VariationalRefinementIterations
        % Weight of the smoothness term.
        VariationalRefinementAlpha
        % Weight of the color constancy term.
        VariationalRefinementDelta
        % Weight of the gradient constancy term.
        VariationalRefinementGamma
        % Whether to use mean-normalization of patches when computing patch
        % distance. It is turned on by default as it typically provides a
        % noticeable quality boost because of increased robustness to
        % illumination variations. Turn it off if you are certain that your
        % sequence doesn't contain any changes in illumination.
        UseMeanNormalization
        % Whether to use spatial propagation of good optical flow vectors.
        % This option is turned on by default, as it tends to work better on
        % average and can sometimes help recover from major errors introduced
        % by the coarse-to-fine scheme employed by the DIS optical flow
        % algorithm. Turning this option off can make the output flow field a
        % bit smoother, however.
        UseSpatialPropagation
    end

    %% Constructor/destructor
    methods
        function this = DISOpticalFlow(varargin)
            %DISOPTICALFLOW  Creates an instance of DISOpticalFlow
            %
            %     obj = cv.DISOpticalFlow()
            %     obj = cv.DISOpticalFlow('OptionName',optionValue, ...)
            %
            % ## Options
            % * __Preset__ preset one of:
            %   * __UltraFast__
            %   * __Fast__ (default)
            %   * __Medium__
            %
            % See also: cv.DISOpticalFlow.calc
            %
            this.id = DISOpticalFlow_(0, 'new', varargin{:});
        end

        function delete(this)
            %DELETE  Destructor
            %
            %     obj.delete()
            %
            % See also: cv.DISOpticalFlow
            %
            if isempty(this.id), return; end
            DISOpticalFlow_(this.id, 'delete');
        end
    end

    %% DenseOpticalFlow
    methods
        function flow = calc(this, I0, I1, varargin)
            %CALC  Calculates an optical flow
            %
            %     flow = obj.calc(I0, I1)
            %     flow = obj.calc(I0, I1, 'OptionName',optionValue, ...)
            %
            % ## Input
            % * __I0__ first 8-bit single-channel input image.
            % * __I1__ second input image of the same size and the same type
            %   as `I0`.
            %
            % ## Output
            % * __flow__ computed flow image that has the same size as `I0`
            %   and type `single` (2-channels).
            %
            % ## Options
            % * __InitialFlow__ specify the initial flow. Not set by default.
            %
            % See also: cv.DISOpticalFlow
            %
            flow = DISOpticalFlow_(this.id, 'calc', I0, I1, varargin{:});
        end

        function collectGarbage(this)
            %COLLECTGARBAGE  Releases all inner buffers
            %
            %     obj.collectGarbage()
            %
            DISOpticalFlow_(this.id, 'collectGarbage');
        end
    end

    %% Algorithm
    methods (Hidden)
        function clear(this)
            %CLEAR  Clears the algorithm state
            %
            %     obj.clear()
            %
            % See also: cv.DISOpticalFlow.empty
            %
            DISOpticalFlow_(this.id, 'clear');
        end

        function b = empty(this)
            %EMPTY  Returns true if the algorithm is empty
            %
            %     b = obj.empty()
            %
            % ## Output
            % * __b__ Returns true if the algorithm is empty (e.g. in the very
            %   beginning or after unsuccessful read).
            %
            % See also: cv.DISOpticalFlow.clear
            %
            b = DISOpticalFlow_(this.id, 'empty');
        end

        function name = getDefaultName(this)
            %GETDEFAULTNAME  Returns the algorithm string identifier
            %
            %     name = obj.getDefaultName()
            %
            % ## Output
            % * __name__ This string is used as top level XML/YML node tag
            %   when the object is saved to a file or string.
            %
            % See also: cv.DISOpticalFlow.save, cv.DISOpticalFlow.load
            %
            name = DISOpticalFlow_(this.id, 'getDefaultName');
        end

        function save(this, filename)
            %SAVE  Saves the algorithm to a file
            %
            %     obj.save(filename)
            %
            % ## Input
            % * __filename__ Name of the file to save to.
            %
            % This method stores the algorithm parameters in a file storage.
            %
            % See also: cv.DISOpticalFlow.load
            %
            DISOpticalFlow_(this.id, 'save', filename);
        end

        function load(this, fname_or_str, varargin)
            %LOAD  Loads algorithm from a file or a string
            %
            %     obj.load(fname)
            %     obj.load(str, 'FromString',true)
            %     obj.load(..., 'OptionName',optionValue, ...)
            %
            % ## Input
            % * __fname__ Name of the file to read.
            % * __str__ String containing the serialized model you want to
            %   load.
            %
            % ## Options
            % * __ObjName__ The optional name of the node to read (if empty,
            %   the first top-level node will be used). default empty
            % * __FromString__ Logical flag to indicate whether the input is a
            %   filename or a string containing the serialized model.
            %   default false
            %
            % This method reads algorithm parameters from a file storage.
            % The previous model state is discarded.
            %
            % See also: cv.DISOpticalFlow.save
            %
            DISOpticalFlow_(this.id, 'load', fname_or_str, varargin{:});
        end
    end

    %% Getters/Setters
    methods
        function value = get.FinestScale(this)
            value = DISOpticalFlow_(this.id, 'get', 'FinestScale');
        end
        function set.FinestScale(this, value)
            DISOpticalFlow_(this.id, 'set', 'FinestScale', value);
        end

        function value = get.PatchSize(this)
            value = DISOpticalFlow_(this.id, 'get', 'PatchSize');
        end
        function set.PatchSize(this, value)
            DISOpticalFlow_(this.id, 'set', 'PatchSize', value);
        end

        function value = get.PatchStride(this)
            value = DISOpticalFlow_(this.id, 'get', 'PatchStride');
        end
        function set.PatchStride(this, value)
            DISOpticalFlow_(this.id, 'set', 'PatchStride', value);
        end

        function value = get.GradientDescentIterations(this)
            value = DISOpticalFlow_(this.id, 'get', 'GradientDescentIterations');
        end
        function set.GradientDescentIterations(this, value)
            DISOpticalFlow_(this.id, 'set', 'GradientDescentIterations', value);
        end

        function value = get.VariationalRefinementIterations(this)
            value = DISOpticalFlow_(this.id, 'get', 'VariationalRefinementIterations');
        end
        function set.VariationalRefinementIterations(this, value)
            DISOpticalFlow_(this.id, 'set', 'VariationalRefinementIterations', value);
        end

        function value = get.VariationalRefinementAlpha(this)
            value = DISOpticalFlow_(this.id, 'get', 'VariationalRefinementAlpha');
        end
        function set.VariationalRefinementAlpha(this, value)
            DISOpticalFlow_(this.id, 'set', 'VariationalRefinementAlpha', value);
        end

        function value = get.VariationalRefinementDelta(this)
            value = DISOpticalFlow_(this.id, 'get', 'VariationalRefinementDelta');
        end
        function set.VariationalRefinementDelta(this, value)
            DISOpticalFlow_(this.id, 'set', 'VariationalRefinementDelta', value);
        end

        function value = get.VariationalRefinementGamma(this)
            value = DISOpticalFlow_(this.id, 'get', 'VariationalRefinementGamma');
        end
        function set.VariationalRefinementGamma(this, value)
            DISOpticalFlow_(this.id, 'set', 'VariationalRefinementGamma', value);
        end

        function value = get.UseMeanNormalization(this)
            value = DISOpticalFlow_(this.id, 'get', 'UseMeanNormalization');
        end
        function set.UseMeanNormalization(this, value)
            DISOpticalFlow_(this.id, 'set', 'UseMeanNormalization', value);
        end

        function value = get.UseSpatialPropagation(this)
            value = DISOpticalFlow_(this.id, 'get', 'UseSpatialPropagation');
        end
        function set.UseSpatialPropagation(this, value)
            DISOpticalFlow_(this.id, 'set', 'UseSpatialPropagation', value);
        end
    end

end


function  matcaffe_init(use_gpu, model_def_file, model_file)
% matcaffe_init(model_def_file, model_file, use_gpu)
% Initilize matcaffe wrapper

if nargin < 1
  % By default use CPU
  use_gpu = 0;
end
if nargin < 2 || isempty(model_def_file)
  % By default use imagenet_deploy
  model_def_file = '../../examples/imagenet/imagenet_deploy.prototxt';
end
if nargin < 3 || isempty(model_file)
  % By default use caffe reference model
  model_file = '../../examples/imagenet/caffe_reference_imagenet_model';
end

if caffe('is_initialized') == 0
  if exist(model_file, 'file') == 0
    % NOTE: you'll have to get the pre-trained ILSVRC network
    error('You need a network model file');
  end
  if ~exist(model_def_file,'file')
    % NOTE: you'll have to get network definition
    error('You need the network prototxt definition');
  end
  caffe('init', model_def_file, model_file)
end
fprintf('Done with init\n');

% set to use GPU or CPU
if use_gpu
  fprintf('Using GPU Mode\n');
  caffe('set_mode_gpu');
else
  fprintf('Using CPU Mode\n');
  caffe('set_mode_cpu');
end
fprintf('Done with set_mode\n');

% put into test mode
caffe('set_phase_test');
fprintf('Done with set_phase_test\n');


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

%% Specify Crystal and Specimen Symmetries

% crystal symmetry
CS = {crystal symmetry};

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

%% Specify File Names

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

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

%% Import the Data

% create a Tensor variable containing the data
tensor = tensor.load(fname,CS,'interface',{interface},{options});


function [f,J,D] = tapas_ceode_fx_cmc(x, u, P, M, xtau)
% [f,J,D] = tapas_ceode_fx_cmc(x, u, P, M, xtau)
%
% Computation of the dynamical (state) equation for a neural mass model
% (canonical microcircuit). Compatibile with continuous extension for ODE
% methods. Adapted from spm_fx_cmc.m (original function license below).
% Function output signature kept the same to ensure compatibility.
%
%
% INPUT
%   x           mat             vector of current state activity
%   u           mat             vector of current driving input
%   P           struct          parameter structure
%   M           struct          model specification
%   xtau        mat             vector of delayed state activity
%
% OUTPUT
%   f           mat             matrix of dx/dt
%   J           mat             Jacobian of the system df/dx. Fixed to 0
%                               since irrelevant for this integration
%                               scheme.
%   D           mat             matrix of delays. Empty since irrelevant
%                               for this integration scheme.

% -------------------------------------------------------------------------
%
% Author: Dario Schöbi
% Created: 2020-08-10
% Copyright (C) 2020 TNU, Institute for Biomedical Engineering, University of Zurich and ETH Zurich.
%
% This file is part of the TAPAS ceode Toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------
%
% ORIGINAL FUNCTION LICENSE
%
% Copyright (C) 2005 Wellcome Trust Centre for Neuroimaging
%
% Karl Friston
% $Id: spm_fx_cmc.m 6720 2016-02-15 21:06:55Z karl $
%--------------------------------------------------------------------------

% get dimensions and configure state variables
%--------------------------------------------------------------------------
if nargin < 5
    xtau = x;
end

% get dimensions and configure state variables
%--------------------------------------------------------------------------
x  = spm_unvec(x,M.x);            % neuronal states
xtau = spm_unvec(xtau, M.x);
n  = size(x,1);                   % number of sources

% [default] fixed parameters
%--------------------------------------------------------------------------
E  = [1 1/2 1 1/2]*200;           % extrinsic (forward and backward)
G  = [4 4 8 4 4 2 4 4 2 1]*200;   % intrinsic connections
T  = [2 2 16 28];                 % synaptic time constants
R  = 2/3;                         % slope of sigmoid activation function
B = 0;                            % bias or background (sigmoid)

% [specified] fixed parameters
%--------------------------------------------------------------------------
if isfield(M,'pF')
    try, E = M.pF.E; end
    try, G = M.pF.G; end
    try, T = M.pF.T; end
    try, R = M.pF.R; end
end

% Extrinsic connections
%--------------------------------------------------------------------------
% ss = spiny stellate
% sp = superficial pyramidal
% dp = deep pyramidal
% ii = inhibitory interneurons
%--------------------------------------------------------------------------
if n > 1
    A{1} = exp(P.A{1})*E(1);      % forward  connections (sp -> ss)
    A{2} = exp(P.A{2})*E(2);      % forward  connections (sp -> dp)
    A{3} = exp(P.A{3})*E(3);      % backward connections (dp -> sp)
    A{4} = exp(P.A{4})*E(4);      % backward connections (dp -> ii)
else
    A    = {0,0,0,0};
end

% detect and reduce the strength of reciprocal (lateral) connections
%--------------------------------------------------------------------------
for i = 1:length(A)
    L    = (A{i} > exp(-8)) & (A{i}' > exp(-8));
    A{i} = A{i}./(1 + 4*L);
end

% input connections
%--------------------------------------------------------------------------
C    = exp(P.C);

% pre-synaptic inputs: s(V)
%--------------------------------------------------------------------------
R    = R.*exp(P.S);              % gain of activation function
F    = 1./(1 + exp(-R*xtau + B));   % firing rate
S    = F - 1/(1 + exp(B));       % deviation from baseline firing

% input
%==========================================================================
if isfield(M,'u')

    % endogenous input
    %----------------------------------------------------------------------
    U = u(:)*512;

else
    % exogenous input
    %----------------------------------------------------------------------
    U = C*u(:)*32;

end

% time constants and intrinsic connections
%==========================================================================
T    = ones(n,1)*T/1000;
G    = ones(n,1)*G;

% extrinsic connections
%--------------------------------------------------------------------------
% forward  (i)   2  sp -> ss (+ve)
% forward  (ii)  1  sp -> dp (+ve)
% backward (i)   2  dp -> sp (-ve)
% backward (ii)  1  dp -> ii (-ve)
%--------------------------------------------------------------------------
% free parameters on time constants and intrinsic connections
%--------------------------------------------------------------------------
% G(:,1)  ss -> ss (-ve self)  4
% G(:,2)  sp -> ss (-ve rec )  4
% G(:,3)  ii -> ss (-ve rec )  4
% G(:,4)  ii -> ii (-ve self)  4
% G(:,5)  ss -> ii (+ve rec )  4
% G(:,6)  dp -> ii (+ve rec )  2
% G(:,7)  sp -> sp (-ve self)  4
% G(:,8)  ss -> sp (+ve rec )  4
% G(:,9)  ii -> dp (-ve rec )  2
% G(:,10) dp -> dp (-ve self)  1
%--------------------------------------------------------------------------
% Neuronal states (deviations from baseline firing)
%--------------------------------------------------------------------------
%   S(:,1) - voltage     (spiny stellate cells)
%   S(:,2) - conductance (spiny stellate cells)
%   S(:,3) - voltage     (superficial pyramidal cells)
%   S(:,4) - conductance (superficial pyramidal cells)
%   S(:,5) - current     (inhibitory interneurons)
%   S(:,6) - conductance (inhibitory interneurons)
%   S(:,7) - voltage     (deep pyramidal cells)
%   S(:,8) - conductance (deep pyramidal cells)
%--------------------------------------------------------------------------
j     = [1 2 3 4];
for i = 1:size(P.T,2)
    T(:,j(i)) = T(:,j(i)).*exp(P.T(:,i));
end
j     = [7 2 3 4];
for i = 1:size(P.G,2)
    G(:,j(i)) = G(:,j(i)).*exp(P.G(:,i));
end

% Modulatory effects of dp depolarisation on intrinsic connection j(1)
%--------------------------------------------------------------------------
if isfield(P,'M')
    G(:,j(1)) = G(:,j(1)).*exp(-P.M*32*S(:,7));
end

% Motion of states: f(x)
%--------------------------------------------------------------------------

% Conductance
%==========================================================================

% Granular layer (excitatory interneurons): spiny stellate: Hidden causes
%--------------------------------------------------------------------------
u      =   A{1}*S(:,3) + U;
u      = - G(:,1).*S(:,1) - G(:,3).*S(:,5) - G(:,2).*S(:,3) + u;
f(:,2) =  (u - 2*x(:,2) - x(:,1)./T(:,1))./T(:,1);

% Supra-granular layer (superficial pyramidal cells): Hidden causes - error
%--------------------------------------------------------------------------
u      = - A{3}*S(:,7);
u      =   G(:,8).*S(:,1) - G(:,7).*S(:,3) + u;
f(:,4) =  (u - 2*x(:,4) - x(:,3)./T(:,2))./T(:,2);

% Supra-granular layer (inhibitory interneurons): Hidden states - error
%--------------------------------------------------------------------------
u      = - A{4}*S(:,7);
u      =   G(:,5).*S(:,1) + G(:,6).*S(:,7) - G(:,4).*S(:,5) + u;
f(:,6) =  (u - 2*x(:,6) - x(:,5)./T(:,3))./T(:,3);

% Infra-granular layer (deep pyramidal cells): Hidden states
%--------------------------------------------------------------------------
u      =   A{2}*S(:,3);
u      = - G(:,10).*S(:,7) - G(:,9).*S(:,5) + u;
f(:,8) =  (u - 2*x(:,8) - x(:,7)./T(:,4))./T(:,4);

% Voltage
%==========================================================================
f(:,1) = x(:,2);
f(:,3) = x(:,4);
f(:,5) = x(:,6);
f(:,7) = x(:,8);

if nargout < 2; return, end

% Jacobian and delay matrix (will be properly computed in
% tnudcm_compute_xtau)
%==========================================================================
J  = 0;
D  = [];


%% REW_campussquare
% %{
imfolder = 'images\REW_campussquare';
im_n = 2;
imfile = cell(im_n,1);
imfile{1} = [imfolder '\' 'campussquare_01.jpg'];
imfile{2} = [imfolder '\' 'campussquare_02.jpg'];

im = cell(im_n,1);
for ii = 1:im_n
    im{ii} = imread(imfile{ii});
end

edge_list = [1,2];

% imsize = zeros(im_n,3);
%
% for ii = 1:im_n
%     imsize(ii,:) = size(im{ii});
%     if imsize(ii,1) > 720
%         scale = 720/size(im{ii}, 1);
%         im{ii} = imresize(im{ii}, scale);
%
%         imsize(ii,:) = size(im{ii});
%     end
% end

mosaic = REW_mosaic( im, edge_list, 1, 'persp', 0, imfolder );
%}


classdef prtClassAdaBoostFastAuc < prtClassAdaBoost
    %prtClassAdaBoostFastAuc AdaBoost classifier (fast training)
    %
    %   prtClassAdaBoostFastAuc is a version of prtClassAdaBoost that can
    %   be trained significantly more quickly than prtClassAdaBoost.
    %   prtClassAdaBoostFastAuc acheives this by assuming a linear
    %   classifier when picking the feature to be used in the weak learner.
    %   Unlike regular adaBoost, where the weak learner is trained and
    %   evaluated on each feature, in prtClassAdaBoostFastAuc, the feature
    %   is selected using simple ROC metrics, and this feature is used to
    %   train the weak learner for the current iteration.  This can be
    %   significantly faster than prtClassAdaBoost when the base learner is
    %   slow, or there are a very large number of features.
    %
    %   a = prtClassAdaBoostFastAuc;
    %   a = a.train(prtDataGenBimodal);
    %   plot(a)
    %
    %    See also: prtClassAdaBoost

    methods
        % Constructor
        function self = prtClassAdaBoostFastAuc(varargin)
            self = prtUtilAssignStringValuePairs(self,varargin{:});
        end
    end

    methods (Access = protected, Hidden = true)

        function self = trainAction(self,dataSet)

            d = ones(dataSet.nObservations,1)./dataSet.nObservations;

            classifier = self.baseClassifier + prtDecisionBinaryMinPe;
            classifier.verboseStorage = false;
            %classifier.verboseFeatureNames = false;

            y = double(dataSet.getTargetsAsBinaryMatrix);
            y = y(:,2);
            y(y == 0) = -1;

            globalX = dataSet.getX;
            globalY = dataSet.getY;
            rocFlip = ones(1,dataSet.nFeatures);

            for t = 1:self.maxIters
                if t == 1
                    dataSetBootstrap = dataSet;
                    if self.downSampleBootstrap
                        dataSetBootstrap = dataSetBootstrap.bootstrap(self.downSampleBootstrap);
                    end
                else
                    dataSetBootstrap = dataSet.bootstrap(dataSet.nObservations,d);
                    if self.downSampleBootstrap
                        dataSetBootstrap = dataSetBootstrap.bootstrapByClass(self.downSampleBootstrap);
                    end
                end

                localX = dataSetBootstrap.getX;
                localY = dataSetBootstrap.getY;
                if length(unique(localY)) < 2
                    %d told us not to re-sample
                    return;
                end

                pe = nan(1,size(localX,2));
                 if self.verbose
                    fprintf('\nIter: %d ',t);
                end
                for feature = 1:dataSet.nFeatures
                    if ~mod(feature,1000) & self.verbose
                        %disp(feature./dataSet.nFeatures);
                        if feature == 1000
                            fprintf('\n');
                        end
                        fprintf('.');
                    end

                    %Evaluate the ROC curve for a feature:
                    [pf,pd,tau,auc] = prtClassAdaBoost.fastRoc(localX(:,feature)*rocFlip(feature),localY);
                    if auc < .5
                        rocFlip(feature) = -1*rocFlip(feature);
                        %try again, flip the ROC
                        [pf,pd,tau] = prtClassAdaBoost.fastRoc(localX(:,feature)*rocFlip(feature),localY);
                    end

                    %Figure out the optimal expected threshold:
                    tempPe = prtUtilPfPd2Pe(pf,pd);
                    [~,ind] = min(tempPe);
                    threshold = tau(ind);

                    %Use the threshold to estimate pe(feature) from all the
                    %data
                    decisions = globalX(:,feature)*rocFlip(feature) >= threshold;
                    correctLogical = decisions == (globalY == 1);
                    pe(feature) = sum(double(~correctLogical).*d);
                end
                [minDeltaPe,minInd] = max(abs(pe-.5));

                if minDeltaPe < self.deltaPeThreshold
                    return;
                else

                    baseClass = self.baseClassifier;
                    baseClass.verboseStorage = false;
                    algo = prtFeatSelStatic('selectedFeatures',minInd) + baseClass + prtDecisionBinaryMinPe;
                    algo.verboseStorage = false;
                    %algo.verboseFeatureNames = false;

                    if t == 1
                        self.classifierArray = train(algo,dataSetBootstrap);
                    else
                        self.classifierArray(t) = train(algo,dataSetBootstrap);
                    end

                    yOut = run(self.classifierArray(t),dataSet);
                    wrong = yOut.getX ~= yOut.getY;
                    eps_t = sum(d.*wrong);

                    if eps_t == 0 %nothing wrong!
                        self.alpha(t) = 10;
                    else
                        self.alpha(t) = 1/2*log((1-eps_t)/eps_t);
                    end

                    h = double(yOut.getObservations);
                    h(h == 0) = -1;

                    d = d.*exp(-self.alpha(t).*y.*h);

                    if sum(d) == 0
                        return;
                    end

                    d = d./sum(d);

                end

            end
        end

    end
end


function ensureCompatibleSymmetries(SO3VF,varargin)
% For calculating with @SO3VectorFields (+, -, .*, ./, ...) we have to verify
% that the symmetries are suitable.
%
% Syntax
%   ensureCompatibleSymmetries(SO3F1,SO3F2)
%   ensureCompatibleSymmetries(SO3F1,sF)
%   ensureCompatibleSymmetries(SO3F1,ori)
%   ensureCompatibleSymmetries(SO3F1,SO3F2,'conv')
%   ensureCompatibleSymmetries(SO3F1,'antipodal')
%
% Input
%  SO3F1, SO3F2 - @SO3VectorField, @SO3Fun
%  sF - @S2FunHarmonicSym
%  ori - @orientation
%
% Output
%  msg - yields a error message if the symmetry do not match
%
% Options
%  conv - be shure switched symmetries match
%

if isa(SO3VF,'SO3VectorField')
  SO3VF = SO3FunHarmonic(0,SO3VF.SRight,SO3VF.SLeft);
end
if nargin>1 && isa(varargin{1},'SO3VectorField')
  varargin{1} = SO3FunHarmonic(0,varargin{1}.SRight,varargin{1}.SLeft);
end

ensureCompatibleSymmetries(SO3VF,varargin{:},'SO3VectorField')

end


function [influenceM] = getInfluenceM(IM, structNum)
%"getInfluenceM"
%   Get the influence matrix (dose(:) = influenceM * weights(:)),
%   for a single structure.  The output influenceM is sparse, and has
%   a row for every calculated dose point in the structure.  If a
%   the sampleRate is 1, this is the number of points in the structure,
%   otherwise it is the number of points in the downsampled structure.
%
%   Uses the global influence matrix.  This is not the most efficent
%   system, should be changed later.
%
%   JRA 4/1/04
%
%Usage:
%   function [influenceM] = getInfluenceM(IM, structNum)
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

%Get global influence for all points in plan.
gInfluenceM = getGlobalInfluenceM(IM, structNum);

%Get the structure mask, downsampled if necessary.
mask3M = getUniformStr(structNum);

%get indices of structures stored under beamlets
beamlets = IM.beams(1).beamlets;
structIndV = getAssociatedStr({beamlets(:,1).strUID});
structInd = find(ismember(structIndV,structNum));
sampleRate = beamlets(structInd(1),1).sampleRate;
%sampleRate = IM.beamlets(structNum,1).sampleRate;

mask3M = getDown3Mask(mask3M, sampleRate, 1) & mask3M;

%Find relevant indices into the gInfluenceM.
indV = find(mask3M);

%Extract the influence matrix for this structure.
influenceM = gInfluenceM(indV, :);


%==========================================================================
% This is the testing code of a special case of SRMD (scale factor = 1) for real image <denoising & deblurring>.
% There are two models, "SRMDx1_gray.mat" for grayscale image, "SRMDx1_color.mat"
% for color image. The models can do:
%   1. Deblurring. (The kernel is assumed to be Gaussian-like!!! For other kernels, you should re-train the model!)
%      there are two types of kernels,
%      including isotropic Gaussian (width range: [0.1, 3]),
%      anisotropic Gaussian ([0.5, 8]).
%   2. Denoising. the noise level range is [0, 75].
%      For denoising only, set "kerneltype = 1; kernelwidth = 0.1." (i.e., delta kernel)
%
%==========================================================================
% The basic idea of SRMD is to learn a CNN to infer the MAP of general SISR (with special case of sf=1), i.e.,
% solve x^ = arg min_x 1/(2 sigma^2) ||kx - y||^2 + lamda \Phi(x)
% via x^ = CNN(y,k,sigma;\Theta) or x^ = CNN(y,kernel,noiselevel;\Theta).
%
% There involves two important factors, i.e., blur kernel (k; kernel) and noise
% level (sigma; nlevel).
%
% For more information, please refer to the following paper.
%    @article{zhang2017learningsrmd,
%    title={Learning a Single Convolutional Super-Resolution Network for Multiple Degradations},
%    author={Kai, Zhang and Wangmeng, Zuo and Lei, Zhang},
%    year={2017},
%    }
%
% If you have any question, please feel free to contact with <Kai Zhang (cskaizhang@gmail.com)>.
%
% This code is for research purpose only.
%
% by Kai Zhang (Nov, 2017)
%==========================================================================

% clear; clc;
format compact;

addpath('utilities');
imageSets    = {'Hilbert','Set5','Set14','BSD68','BSD100','Urban100'}; % testing dataset

%%======= ======= ======= degradation parameter settings ======= ======= =======

% For real image 'Hilbert', some examples of degradation setting are given as follows.
% sf = 1; nlevel =  8; kerneltype = 1; kernelwidth = 0.2; % denoising only
% sf = 1; nlevel = 10; kerneltype = 1; kernelwidth = 0.5; % denoising and sharpening(deblurring)

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

%% select testing dataset, use GPU or not, ...
setTest      = imageSets([1]); %
showResult   = 1; % 1, show results; 2, save restored images
pauseTime    = 1;
useGPU       = 1; % 1 or 0, true or false
method       = 'SRMD';
folderTest   = 'testsets';
folderResult = 'results';
if ~exist(folderResult,'file')
    mkdir(folderResult);
end

%% scale factor (it is fixed to 1)

sf          = 1; %{1}

%% load model with scale factor sf
folderModel = 'models';
load(fullfile(folderModel,['SRMDx',int2str(sf),'_gray.mat']));
%net.layers = net.layers(1:end-1);
net = vl_simplenn_tidy(net);
if useGPU
    net = vl_simplenn_move(net, 'gpu') ;
end

%% degradation parameter (noise level and kernel) setting
%############################# noise level ################################
% noise level, from a range of [0, 75]

nlevel     = 10;  % [0, 75]

kerneltype = 1;  % {1}

%############################### kernel ###################################
% there are tree types of kernels, including isotropic Gaussian,
% anisotropic Gaussian, and estimated kernel k_b for isotropic Gaussian k_d
% under direct downsampler (x2 and x3 only).

if kerneltype == 1
    % type 1, isotropic Gaussian---although it is a special case of anisotropic Gaussian.
    kernelwidth = 0.5; % from a range of [0.1, 3]. set kernelwidth from (0.001, 0.2) to generate delta kernel (no blur)
    kernel = fspecial('gaussian',15, kernelwidth); % Note: the kernel size is fixed to 15X15.
    tag    = ['_',method,'_x',num2str(sf),'_itrG_',int2str(kernelwidth*10),'_nlevel_',int2str(nlevel)];

elseif kerneltype == 2
    % type 2, anisotropic Gaussian
    nk     = 1;%randi(size(net.meta.AtrpGaussianKernel,4)); % randomly select one
    kernel = net.meta.AtrpGaussianKernel(:,:,:,nk);
    tag    = ['_',method,'_x',num2str(sf),'_atrG_',int2str(nk),'_nlevel_',int2str(nlevel)];

end

%##########################################################################

surf(kernel) % show kernel
view(45,55);
title('Assumed kernel');
xlim([1 15]);
ylim([1 15]);
pause(2)
close;

%% for degradation maps
global degpar;
degpar = single([net.meta.P*kernel(:); nlevel(:)/255]);

for n_set = 1 : numel(setTest)

    %% search images
    setTestCur = cell2mat(setTest(n_set));
    disp('--------------------------------------------');
    disp(['    ----',setTestCur,'-----Super-Resolution-----']);
    disp('--------------------------------------------');
    folderTestCur = fullfile(folderTest,setTestCur);
    ext                 =  {'*.jpg','*.png','*.bmp'};
    filepaths           =  [];
    for i = 1 : length(ext)
        filepaths = cat(1,filepaths,dir(fullfile(folderTestCur, ext{i})));
    end

    %% prepare results
    folderResultCur = fullfile(folderResult, [setTestCur,tag]);
    if ~exist(folderResultCur,'file')
        mkdir(folderResultCur);
    end

    %% perform denoising or/and deblurring (only support Gaussian-like kernel)
    for i = 1 : length(filepaths)

        input  = imread(fullfile(folderTestCur,filepaths(i).name));
        %label  = modcrop(label, 2);
        [h,w,C]   = size(input);
        input     = im_pad(input);
        if C == 3
            input = rgb2gray(input); % input = rgb2ycbcr(input); input = input(:,:,1); % another option
        end

        [~,imageName,ext] = fileparts(filepaths(i).name);
        input1 = im2single(input);
        %tic
        if useGPU
            input1 = gpuArray(input1);
        end
        res = vl_srmd(net, input1,[],[],'conserveMemory',true,'mode','test','cudnn',true);
        %res = vl_srmd_concise(net, input1); % a concise version of "vl_srmd".
        %res = vl_srmd_matlab(net, input1); % You should also set "useGPU = 0;" and comment "net = vl_simplenn_tidy(net);"

        output = im2uint8(gather(res(end).x));

        %toc;
        output = im_crop(output,h,w);
        input  = im_crop(input,h,w);
        %output2 = 0.8*output + 0.2*input; % add noise and structure back to make the output more visually plausible. or GAN?

        disp([setTestCur,'    ',int2str(i),'    ',filepaths(i).name]);
        if showResult
            imshow(cat(2,input,output));
            drawnow;
            title(['Denoising and deblurring     ',filepaths(i).name],'FontSize',12)
            pause(pauseTime)
            imwrite(output,fullfile(folderResultCur,[imageName,'_x',int2str(sf),'.png']));% save results

        end
    end
end


function g = multimodelLogLikeGradients(model)

% MULTIMODELLOGLIKEGRADIENTS Gradient of MULTIMODEL model log likelihood with respect to parameters.
% FORMAT
% DESC computes the gradient of the multi-task learning wrapper
% model's log likelihood with respect to the parameters.
% ARG model : model structure for which gradients are being
% computed.
% RETURN g : the returned gradients.
%
% SEEALSO multimodelCreate, multimodelLogLikelihood, modelLogLikeGradients
%
% COPYRIGHT : Neil D. Lawrence, 2007, 2008
%
% MODIFICATIONS : Mauricio Alvarez, 2009

% MLTOOLS

  g = zeros(1, model.numParams);
  if numel(model.outputDim) == 1
  endShared = model.numParams - model.numModels*model.numSep;
  endVal = endShared;
  for i = 1:length(model.comp)
    gModel = modelLogLikeGradients(model.comp{i});
    g(1:endShared) = g(1:endShared) + gModel(model.sharedIndices);
    if ~isempty(model.separateIndices)
      startVal = endVal + 1;
      endVal = endVal + model.numSep;
      %g(startVal:endVal) = g(model.separateIndices);
      g(startVal:endVal) = gModel(model.separateIndices);
    end
  end
  else
      startVal = 1;
      endVal = 0;
      for i = 1:length(model.comp)
          endVal = endVal + model.comp{i}.nParams;
          if (i==6) || (i ==14)
              a =1;
          end
          g(startVal:endVal) = modelLogLikeGradients(model.comp{i});
          startVal = endVal + 1;
      end
  end
end


function A = old_get_gain(fid,ndx)
% GET_GAIN: Get a set of source foward fields from a .bin gain matrix file.
%
% USAGE:  A = old_get_gain(fid,ndx);
%
% INPUT:
%    - fid : a file identifier following a fopen call on a valid binary gain matrix file
%    - ndx : vector array of source indices for which the forward fields are requested
% OUTPUT:
%    - A   : array of requested forward fields
%
% NOTES:
%    - The user is responsible for opening the file in the proper machine format.
%    - For head model matrices, this routine should only be accessed from read_gain,
%      so that a consistent machine format is used to read the file.
%
% SEE ALSO: READ_GAIN, LOAD_RAW, SAVE_RAW

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Sylvain Baillet, October 2002

frewind(fid);

rows = fread(fid,1,'uint32');

if nargin == 2
   cols = length(ndx);

   A = zeros(rows,cols);

   for i = 1:cols,
      % 4 bytes per element, find starting point
      offset = 4 + (ndx(i)-1)*rows*4;
      status = fseek(fid,offset,'bof');
      if(status == -1),
         error('Error reading file at column %.0f',i);
      end

      A(:,i) = fread(fid,[rows,1],'float32');

   end

   return

else % ndx is not specified: read the whole matrix

   offset = 4;
   fseek(fid,offset,'bof');
   fbegin = ftell(fid);
   fseek(fid,0,'eof');
   fend = ftell(fid);

   frewind(fid);
   offset = 4;
   fseek(fid,offset,'bof');

   cols = (fend - fbegin + 1) / (4* rows); % Number of sources / columns

   A = fread(fid,[rows, cols],'float32');

end


function [result] = VBA_susceptibility(posterior,out,ind)
% scores the susceptibility of u->y relationships w.r.t. model parameters
% [result] = VBA_susceptibility(posterior,out,ind)
% IN:
%   - out/posterior: the output structures of the VBA inversion
%   - ind: a structure containing the following fields:
%       .u  : indices of inputs of interests
%       .phi: indices of observation parameters, whose importance in the
%       u->y relationship one wants to score
%       .theta: idem, for evolution parameters.
%       .y : indices of observations of interest
% OUT:
%   - susceptibility: nuXnphi and nuxntheta relative susceptibility
%   matrices (w.r.t. observation/evolution parameters), where nu and
%   nphi/ntehta are the number of considered inputs and parameters, respectively.
%   - susceptibility: nuXntphi qnd nuxntheta relative susceptibility matrices
%   (w.r.t. observation/evolution  parameters).

% ========================================================================================
% check parameters
% ========================================================================================

dim = out.dim;

% ________________________________________________________________________________________
% check if models has inputs

if dim.u == 0
    disp('*** Susceptibility analysis: the system does not receive any input!')
    result.susceptibility = struct('phi',[],'theta',[]);
    result.specificity    = struct('phi',[],'theta',[]);
    return
end

% ________________________________________________________________________________________
% set default parameters of interest

if ~exist('ind'), ind = struct; end

% check if is DCM
try, isDCM=out.options.inF.fullDCM; catch, isDCM=0; end

% complete option strucutre
if isDCM
    % keep only DCM connections
   idxConnect = 1:(out.options.inF.indself-1);
   % idxConnect = setdiff(idxConnect,out.options.inF.indC); % trivial effects (or maybe not)
   if isfield(out.options.inF,'indhself')
      % behaviour DCM
      idxResp = [out.options.sources(2:end).out] ;
   else
      % normal DCM
      idxResp = 1:dim.p;
   end
   ind = VBA_check_struct(ind,        ...
        'u'     , 1:dim.u       , ...
        'phi'   , []            , ...
        'theta' , idxConnect    , ...
        'y'     , idxResp         ...
    );
else
    % all params
    ind = VBA_check_struct(ind,       ...
        'u'     , 1:dim.u       , ...
        'phi'   , 1:dim.n_phi   , ...
        'theta' , 1:dim.n_theta , ...
        'y'     , 1:dim.p         ...
    );
end

% get rid of fixed parameters
fixedTheta = find(diag(out.options.priors.SigmaTheta)==0);
ind.theta = setdiff(ind.theta,fixedTheta);
fixedPhi = find(diag(out.options.priors.SigmaPhi)==0);
ind.phi = setdiff(ind.phi,fixedPhi);

% get rid of session param
if isfield(out.options, 'multisession')
    ind.u = setdiff(ind.u,dim.u);
end
% ========================================================================================
% shortcuts
% ========================================================================================

%options = out.options;
%f_fname = options.f_fname;
%g_fname = options.g_fname;
%y = out.y;

% ========================================================================================
% initialization
% ========================================================================================

% ========================================================================================
% Mutilating the models and deriving the output distortion
% ========================================================================================

% ________________________________________________________________________________________
% 1 - switching off inputs
vu = zeros(length(ind.u),1);
parfor iu=1:length(ind.u)
    mutilated_input_idx = ind.u(iu);
    vu(iu) = mutilation_score(posterior,out,ind,'u',mutilated_input_idx);
end

% dealing with parameters
for paramType = {'phi','theta'}
    paramType = paramType{1} ;

    if ~isempty(ind.(paramType)) > 0

        % compute mutilation score
        vparam  = zeros(1,numel(ind.(paramType)));
        % ________________________________________________________________________________
        % 2 - switching off system parameters
        parfor ip=1:length(ind.(paramType))
            mutilated_param_idx = ind.(paramType)(ip);
            vparam(ip) = mutilation_score(posterior,out,ind,paramType,mutilated_param_idx);
        end

        % _______________________________________________________________________________
        % 3 - bilateral mutilations
        vuparam = zeros(numel(ind.u),numel(ind.(paramType)));
        for iu=1:length(ind.u)
           parfor ip=1:length(ind.(paramType))
               mutilated_param_idx = ind.(paramType)(ip);
               mutilated_input_idx = ind.u(iu);
               vuparam_iu(ip) = mutilation_score(posterior,out,ind, ...
               paramType,mutilated_param_idx,'u',mutilated_input_idx);
           end
           vuparam(iu,:) = vuparam_iu ;
        end

        % ________________________________________________________________________________
        % compute susceptibility and specificity
        dvuparam = vuparam;
        dvu      = repmat(vu,1,length(ind.(paramType)));
        dvparam  = repmat(vparam,length(ind.u),1);

        % relative susceptibility
        susceptibility.raw.(paramType)  = 1 + (dvparam - dvuparam)      ;
        susceptibility.norm.(paramType) = 1 + (dvparam - dvuparam)./dvu ;
       % relative specificity
        specificity.raw.(paramType)  = 1 + (dvu - dvuparam)      ;
        specificity.norm.(paramType) = 1 + (dvu - dvuparam)./dvparam ;

        % interaction scores
        inter =  ((dvparam+dvu)-dvuparam) ;
        interaction.(paramType) = inter;
        interaction_norm.(paramType)  =  inter./min(dvu,dvparam);
        interaction_normU.(paramType) =  inter./dvu;
        interaction_normP.(paramType) =  inter./dvparam ;
        ii = max(inter,0) ;
        interaction_normC.(paramType) =  ii./ repmat(sum(ii),size(ii,1),1) ;

    else
        susceptibility.(paramType) = [];
        specificity.(paramType) = [];
        interaction.(paramType) = [];
        interaction_norm.(paramType) = [];
        interaction_normP.(paramType) = [];
        interaction_normU.(paramType) = [];
        interaction_normC.(paramType) = [];
    end

end

result.ind = ind ;
result.susceptibility = susceptibility;
result.specificity    = specificity;
result.interaction.raw     = interaction;
result.interaction.norm    = interaction_norm;
result.interaction.normP   = interaction_normP;
result.interaction.normU   = interaction_normU;
result.interaction.normC   = interaction_normC;

end

% ========================================================================================
% Additional functions
% ========================================================================================

% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
% compute the loss of explained variance of a mutilated model
function v = mutilation_score(posterior,out,ind,varargin)

    % default is no mutilation
    mutilation = VBA_check_struct(struct,'u',0,'phi',0,'theta',0);

    % set mutilation from args
    for iArg = 1:2:numel(varargin)
        mutilation.(varargin{iArg}) = varargin{iArg+1} ;
    end

    % compute mutilated model trajectory
    [muy] = laplace_mutilated(posterior,out,mutilation);

    % compute score
    y = out.y ;
    vfull = score(y,out.suffStat.gx,out.options,ind) ;
    v = vfull - score(y,muy,out.options,ind) ;
end

% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
% compute the loss of explained variance of a trajectory
function v = score(y,muy,options,ind)

    % select observation of interest
    y      =   y(ind.y,:);
    muy    = muy(ind.y,:);
    isYout = options.isYout(ind.y,:);

    % get rid of unused data
    y(isYout==1)   = [] ;
    muy(isYout==1) = [] ;

    % compute explained variance % ### TODO: multiline data
    dy = VBA_vec(y) - VBA_vec(muy);
    v =  1 - mean(dy.^2)./var(y) ;
end

% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
% compute the trajectory moments for a mutilated model
function [muy] = laplace_mutilated(posterior,out,mutilation)

    mutilation = VBA_check_struct(mutilation,'u',0,'phi',0,'theta',0);

    mutilation_ratio = 0;
    % define input
    u = out.u;
    if all(mutilation.u > 0)
        u(mutilation.u,:) = mutilation_ratio*u(mutilation.u,:);
    end

    % define parameters
    opt = out.options;
    opt.priors = posterior;

    if mutilation.theta > 0
        opt.priors.muTheta(mutilation.theta)      = mutilation_ratio*opt.priors.muTheta(mutilation.theta);
        opt.priors.SigmaTheta(mutilation.theta,:) = 0;
        opt.priors.SigmaTheta(:,mutilation.theta) = 0;
    end

    if mutilation.phi > 0
        opt.priors.muPhi(mutilation.phi)      = mutilation_ratio*opt.priors.muPhi(mutilation.phi);
        opt.priors.SigmaPhi(mutilation.phi,:) = 0;
        opt.priors.SigmaPhi(:,mutilation.phi) = 0;
    end

   % compute trajectory moments
   [muy] = VBA_getLaplace(u,out.options.f_fname,out.options.g_fname,out.dim,opt,0,'skip');
   muy = reshape(muy,size(out.y));
end


function net = updatemodel(tr_x, tr_y, Params, net)

    [N,V]=size(tr_x);
    batchsize=V;
    run=8000;
    index=round(1+rand(1,run*batchsize)*(N-1));
    for j=1:run
        x=tr_x(index((j-1)*batchsize+1:j*batchsize),:);
        y=tr_y(index((j-1)*batchsize+1:j*batchsize),:);
        net=trainNet(x, y, Params, net);
    end
end


function con = spm_dcm_connectivity_ui(DCM,D,title_text,defaults,enabled)
% GUI for manually specifying connection values in a DCM
% FORMAT [con] = spm_dcm_connectivity_ui(DCM,D,title_text,defaults,enabled)
%
% DCM        - DCM structure
% D          - 'A','B' or 'C' i.e. connectivity matrix of interest
% title_text - Text to display above the matrix, e.g. 'Enter contrast for '
% defaults   - (optional) structure of default values containing
%              defaults.A, defaults.B and defaults.C
% enabled    - (optional) structure of inputs to enable with binary
%              matrices enabled.A, enabled.B and enabled.C
%
% Returns:
% con        - structure with con.A, con.B and con.C of user-entered values
%__________________________________________________________________________
% Copyright (C) 2014-2016 Wellcome Trust Centre for Neuroimaging

% Will Penny & Peter Zeidman
% $Id: spm_dcm_connectivity_ui.m 6808 2016-06-13 16:48:30Z guillaume $

% Set-up data
%--------------------------------------------------------------------------
n       = DCM.n;              % number of regions
m       = length(DCM.U.name); % number of inputs

region_names = DCM.Y.name;
input_names  = DCM.U.name;

try, A = defaults.A; catch, A = zeros(n,n); end
try, B = defaults.B; catch, B = zeros(n,n,m); end
try, C = defaults.C; catch, C = zeros(n,m); end

if nargin < 5
    enabled = struct('A',ones(size(A)),'B',ones(size(B)),'C',ones(size(C)));
end

% Set-up GUI
%--------------------------------------------------------------------------
Finter  = spm_figure('GetWin','Interactive');
header  = get(Finter,'Name');
set(Finter,'Name','Dynamic Causal Modelling')
WS      = spm('WinScale');

% prompt for contrast if necessary
%--------------------------------------------------------------------------
if (nargin < 2) || isempty(D)
    str = 'contrast for';
    D   = spm_input(str,1,'b',{'A','B','C'});
end

% set object sizes
%--------------------------------------------------------------------------
dx    = 35;
wx    = 30;
wy    = 20;
uic   = uicontrol(Finter,'String','done','Position',[300 50 060 020].*WS,...
        'Callback', 'uiresume(gcbf)');

% Define left edge dialogue
% itext_left = 080;
% inum_left  = 180;
%--------------------------------------------------------------------------
BackgroundColor = get(get(uic,'Parent'),'Color');
itext_left  = 030;
inum_left   = 80;
name_length = 8; % number of characters in short names
for i=1:n
    if length(region_names{i}) > name_length
        short_name(i).str = region_names{i}(1:name_length);
    else
        short_name(i).str = region_names{i};
    end
end
text_top = 336;

switch D

    % Get contrast weights
    %======================================================================
    case 'A' % intrinsic

        str   = sprintf('%s A: ',title_text);
        spm_input(str,1,'d');

        % Warn if no matrix elements enabled
        any_enabled = any(enabled.A(:));
        if any_enabled
            h0 = [];
        else
            h0 = add_none_enabled_warning();
        end

        % Print names and numbers of regions
        %------------------------------------------------------------------
        for i = 1:n
            str    = sprintf('%s   %i',short_name(i).str,i);

            h1(i) = add_text([itext_left text_top-dx*i 080 020].*WS,...
                        str, any_enabled, 'right');

            h2(i) = add_text([inum_left+dx*i text_top 020 020].*WS,...
                        sprintf('%i',i), any_enabled);
        end

        % Set contrast values and display
        %------------------------------------------------------------------
        for i = 1:n
            for j = 1:n
                cc=ceil([inum_left+dx*j text_top+4-dx*i wx wy].*WS);
                h3(i,j) = add_matrix_input(cc, num2str(A(i,j)), enabled.A(i,j)==1);
            end
        end
        drawnow

        % wait for 'done'
        %------------------------------------------------------------------
        uiwait(Finter);
        for i = 1:n
            for j = 1:n
                A(i,j) = get_matrix_input(h3(i,j));
            end
        end

        % clean up
        %------------------------------------------------------------------
        delete([h0; h1(:); h2(:); h3(:)]);
        spm_input(' ',1,'d');

    case 'B' % modulatory
        %------------------------------------------------------------------
        for k = 1:m,
            str   = sprintf(...
                '%s B: effects of input  %-12s',...
                title_text, input_names{k});
            spm_input(str,1,'d')

            % Warn if no matrix elements enabled
            any_enabled = any(any(enabled.B(:,:,k)));
            if any_enabled
                h0 = [];
            else
                h0 = add_none_enabled_warning();
            end

            % Print names and numbers of regions
            %--------------------------------------------------------------
            for i = 1:n
                str    = sprintf('%s   %i',short_name(i).str,i);

                h1(i) = add_text([itext_left text_top-dx*i 080 020].*WS,...
                        str, any_enabled);

                h2(i) = add_text([inum_left+dx*i text_top 020 020].*WS,...
                        sprintf('%i',i), any_enabled);
            end

            % Set contrast values and display
            %--------------------------------------------------------------
            for i = 1:n
                for j = 1:n
                    cc=ceil([inum_left+dx*j text_top+4-dx*i wx wy].*WS);
                    h3(i,j) = add_matrix_input(cc, num2str(B(i,j,k)), enabled.B(i,j,k)==1);
                end
            end
            drawnow

            % wait for 'done'
            %--------------------------------------------------------------
            set(gcf,'CurrentObject',h3(1));
            uiwait(Finter);
            for i = 1:n
                for j = 1:n
                    B(i,j,k) = get_matrix_input(h3(i,j));
                end
            end

            % clean up
            %--------------------------------------------------------------
            delete([h0; h1(:); h2(:); h3(:)]);
            spm_input(' ',1,'d');

        end

    case 'C' % input
        %------------------------------------------------------------------
        for k = 1:m
            str   = sprintf(...
                '%s C: Effects of input %-12s',...
                title_text, input_names{k});
            spm_input(str,1,'d');

            % Warn if no matrix elements enabled
            any_enabled = any(enabled.C(:,k));
            if any_enabled
                h0 = [];
            else
                h0 = add_none_enabled_warning();
            end

            % Print names and numbers of regions
            %--------------------------------------------------------------
            for i = 1:n
                str    = sprintf('%s   %i',short_name(i).str,i);

                h1(i) = add_text([itext_left text_top-dx*i 080 020].*WS,...
                        str, any_enabled);

                cc = [inum_left+dx text_top+4-dx*i wx wy].*WS;
                h2(i) = add_matrix_input(cc, num2str(C(i,k)), enabled.C(i,k)==1);

            end
            drawnow

            % wait for 'done'
            %--------------------------------------------------------------
            set(gcf,'CurrentObject',h2(1))
            uiwait(Finter);

            for i = 1:n
                C(i,k)   = get_matrix_input(h2(i));
            end

            % clean up
            %--------------------------------------------------------------
            delete([h0; h1(:); h2(:)]);
            spm_input(' ',1,'d');
        end
    otherwise
        disp('Error in spm_dcm_connectivity_ui: matrix must be A, B or C');
        close
        return
end

% Bundle outputs
%--------------------------------------------------------------------------
con = struct('A',A,'B',B,'C',C);

delete(uic);

%--------------------------------------------------------------------------
function h = add_matrix_input(position, default_txt, enabled)
    % Adds an editor for a single element of a matrix
    if enabled == 1
        isvisible = 'On';
    else
        isvisible = 'Off';
    end

    h = uicontrol(Finter,...
        'Position',position,...
        'BackgroundColor',BackgroundColor,...
        'Style','edit',...
        'Visible',isvisible,...
        'String',default_txt);
end
%--------------------------------------------------------------------------
function num = get_matrix_input(h)
    % Reads a number from a single element of a matrix
    entry=get(h,'string');
    entry=strtrim(entry);

    if isempty(entry)
        entry = '0';
    end

    try
        num = str2double(entry);
    catch
        error('Could not read matrix input');
    end
end
%--------------------------------------------------------------------------
function h = add_text(position, default_txt, visible, horizontalAlignment)
    % Adds a text label to the GUI
    if nargin < 3
        visible = 1;
    end
    if nargin < 4
        horizontalAlignment = 'left';
    end

    if visible
        visible = 'On';
    else
        visible = 'Off';
    end

    h  = uicontrol(Finter,'String',default_txt,...
        'Style','text',...
        'HorizontalAlignment',horizontalAlignment,...
        'BackgroundColor',BackgroundColor,...
        'Position',position,...
        'Visible',visible);
end
%--------------------------------------------------------------------------
function h = add_none_enabled_warning()
    % Adds a warning for when there are no enabled matrix entries
    position = [itext_left text_top-dx*1 250 020].*WS;
    nonestring = 'Nothing to enter - press done to continue';
    h = add_text(position, nonestring);
end

end