clear Models, clear MM

% User-Specified Parameters
% ===============================================================

% Conditions and stimuli
% ---------------------------------------------------------------
GA.conditions = [1 2 3 4 5 6];
	% a vector of integers 1:# of event-related conditions (e.g., [1 2 3 4])
	% to add "rest" intervals, add an extra condition and set its contrast weight
	% to zero in all contrasts.
	% e.g., condition 3 in this design could be passive rest.

GA.freqConditions = [1 1 1 1 1 1] ./ 6;
	% vector of frequencies of each trial type; should sum to 1

GA.scanLength = 36;
	% how long your run is, in seconds.
    % This and the ISI determine how many stimuli are in each design vector

GA.ISI = 1;
	% how long between stimulus presentations? (you can also include "rest" presentations)
	% also the time resolution of stimulus condition function (list of stimuli)
	% designs will be constructed in time units of this resolution

GA.TR = 1;
    % the TR (sampling resolution) of your experiment; time for volume acquisition

GA.doepochs = 0;        % build epochs instead of events
	% use this if you have epochs instead of events; alpha version.  use with caution.
	% if you use this, use the GA function optimizeGA_epochs.m
	% also, the contrast matrix will be different, with 3 periods per trial explicitly modeled
	% this wasn't intended to be a general solution, but a specific optimization for a certain design.

% Hox optimization parameters
% A hox gene is a master gene.  These numbers control the stimulus
% parameters, which can be optimized within the GA rather than
% pre-specified.
% Hox elements in this GA go in the stimlist as the first several elements.
% hox sequence currently codes, in number order:
% ISI TR cuelen cuerest stimlen stimrest resplen resprest (in s)
% the last 6 parameters are for use with doepochs.
% They code epoch lengths for 6 periods within each trial.
% TR does not work right now
% use zeros to use default rather than variable hox parameters
% ---------------------------------------------------------------
GA.numhox = 0;
GA.hoxrange = [];
    % rows are each hox gene's allowable range, cols index hox elements
	% use this if you want to determine the ISI, etc. using the GA
	% also may require significant user input/program modification at this stage.

% Genetic algorithm parameters
% ---------------------------------------------------------------
nmodels = 1;
	% how many runs do you want to optimize?
	% GA runs one separate optimization for each model.

GA.cbalColinPowerWeights = [1 0 0 1];	% 1 = cbal, 2 = eff, 3 = hrf shape, 4 = freq
	% first element: counterbalancing of stimuli
	% second: contrast detection efficiency
	% third: hrf shape estimation efficiency
	% maintenance of input frequencies for each trial type
	% fitness scores for each measure are multiplied by these values
	% before collapsing to a single, final fitness measure for each design.
	% does not have to sum to 1.

GA.numGenerations = 30;
	% how many iterations of the GA to run.
GA.sizeGenerations = 500;
	% how many designs to test  for each generation?  Population size.
GA.maxTime = 30;
	% max time to run in s, or Inf for infinite time
	% The GA stops when either numGenerations or maxTime is reached.

GA.alph = 2.1;
	% "selection pressure": higher is more extreme selection; always pick the best 50% of designs
	%1 is no selection pressure at all, or random selection of designs for recombination
	% selection pressure is like in evolution; refers to whether the best designs are selected to
	% continue on to the next generation.
	% an intermediate value is best, to keep the population heterogeneity high.

GA.plotFlag = 0;
	% plot results after each run.
	% Recommended to leave this off if nmodels > 1, and then plot your final results later.

% Filtering, counterbalancing, and design tolerance
% ---------------------------------------------------------------
% Empty brackets indicate the option is not to be used.

GA.lowerLimit = [];
GA.HPlength = [];
	% high-pass filter length, in s, for analysis; [] for no HP filter
	% Used to filter out noise at lower frequencies than design during data analysis
	% The cutoff you should use depends on how much power in your design is below the cutoff -
	% you want all the power in your design to be above the cutoff.

GA.LPsmooth = [];
	% low-pass filter type for analysis; [] for no LP filter
	% choices are 'hrf' or []

GA.maxOrder = 1;
    % order of counterbalancing to use
    % 1 = each trial type follows each other with equal probabilities, adjusted for base frequencies
    % 2 = one-back and two-back counterbalancing.  3 = 1+2+3 back, etc.

% Hard constraints
% ---------------------------------------------------------------
% Here you can specify tolerances for designs
% If designs do not meet these criteria, they will receive -infinity fitness scores
% Empty brackets indicate the option is not to be used.

GA.NumStimthresh = [];      % maximum number of repeats of any one event type in a row
GA.maxCbalDevthresh = []; 	% maximum acceptable counterbalancing deviation (actual freq - expected freq)
GA.maxFreqDevthresh = .2;   % maximum acceptable deviation from input frequencies (GA.freqConditions)

% Contrast setup
% ---------------------------------------------------------------
% Here you specify contrasts across conditions, for use with the contrast estimation fitness measure
% Each contrasts should be a row in the matrix GA.contrasts
%
GA.contrasts = [1 0 0 0 0 0];
    % there should be one column per condition in your design, not including the intercept.
    %if trans2switch or trans2block = 1, double the number of columns.
    % when using epoch design, three elements per condition for epochs (3 epochs)!

GA.contrastweights = [1];
    % Weighting function for contrasts (rows of GA.contrasts)
    % Contrast efficiencies will be multiplied by these weights before computing overall design fitness
    % If no contrasts are specified, this vector can specify weights for predictors (columns)

% Autocorrelation and special options
% ---------------------------------------------------------------
AutocorrelationFileName = 'myscannerxc';
    % This is the name of a mat file without the .mat extension
    % In the mat file, there should be a variable called myscannerxc
    % which is a row vector containing the autocorrelation fucntion you wish to use.
    % This function is used as the intrinsic noise autocorrelation estimate.
    % Included with the GA scripts are these functions:
    % myscannerxc   (U of M 3T, 7 subjects)
    % hiautocorr    (1/f)
    % hiautocorr3   (another 1/f)
    % noautocorr    (identity; no autocorrelation)

GA.restlength = [];
    % if inserting probe or instruction periods, modeled with periodic rests in the simulation,
    % this is the length of the rest/probe/instr periods to insert, in units of the ISI
GA.restevery = [];
    % This is how many regular events you want to have (in ISIs) between rests.
    % Leave restlength and restevery blank to avoid using these options.
GA.trans2switch = 0;
    % 1 or 0.  This option works if the conditions field is 2 elements long.
    % This option creates new conditions 3 and 4 that occur whenever 1 is followed by 2 or 2 by 1
    % So this option creates trial history-dependent predictors.  1 and 2 are repeats, 3 and 4 are switches
    % Useful when studying habituation, switching between items, etc.
GA.trans2block = 0;
    % 1 or 0.  This option doubles the input length of conditions - so [1 2] is transformed to [1 2 3 4]
    % This option creates alternating ABAB blocks of your input event types (e.g., 1 2) with the new
    % event types (e.g., 3 4).  This is useful when simulating mixed block/event related designs.
    % Trial types 1-2, for example, can be two events within block A, and 3-4 can be the same (or different)
    % events within block B.  The alternation frequency (in ISIs) is specified by GA.restevery.
    % If you use this option, the contrasts field must contain twice as many columns as you have input conditions.
    % for example, if conditions = [1 2 3 4], contrasts = [1 1 1 1 -1 -1 -1 -1] specifies block A vs block B.
    % contrasts = [1 1 1 1 -1 -1 -1 -1; 1 1 -1 -1 1 1 -1 -1] specifies A vs B and events [1 2 5 6] - [3 4 7 8].
GA.dofirst = 0;
    % 1 or 0.  This creates a separate trial type for the first trial following rests in GA.restlength.
    % It only works if you're using trans2switch and trans2block together; unreliable under other circumstances.
GA.nonlinthreshold = [];
    % If the value here is x, predictor heights are clipped (thresholded) at x times the unit HRF height.
    % If empty, no thresholding is performed.
    % This is useful for modeling nonlinearities in the BOLD signal, which is important if your design uses
    % short ISIs (generally, 2 s or less).  The clipping acts as a 'saturation' factor.
    % I like to use 2, because data in our lab suggests the the nonlinearities in the HRF can be
    % roughly approximated by a clipping function with this parameter value.

% ---------------------------------------------------------------
%
% * E N D   U S E R   I N P U T
%
% ---------------------------------------------------------------
eval(['load ' AutocorrelationFileName]);
GA.xc = myscannerxc;

% =============================================
% * vary by parameter - set this in this script
% * if running multiple models, nmodels > 1
% ---------------------------------------------

varyparam = 0;
fieldname = 'alph';		% or 'freqConditions(end), etc.
incrementby = 0.3;
incrementevery = 5;		% every n models
contrastsofinterest = 1;% contrasts or predictors, if no cons specified

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

if varyparam
	eval(['paramvalue = GA.' fieldname ';'])
	disp(' ');disp('* *********************************************************************')
	disp('*  You have selected to vary a parameter across models in ga_gui_script')
	disp(['*  GA.' fieldname ' starting at ' num2str(paramvalue)])
	disp('* *********************************************************************')
end

for nm = 1:nmodels

   eval(['diary model' num2str(nm) '.log'])
   disp(['Starting Model ' num2str(nm)])
    % freqConditions

   M = optimizeGA(GA);

   Models(:,nm) = M.stimlist;
   MM{nm} = M;
   save GAworkspace

   if varyparam
   	if isfield(M,'consebeta'),
		Fit(1,nm) = mean(M.consebeta(contrastsofinterest));
	else
		Fit(1,nm) = mean(M.sebeta(contrastsofinterest));
	end
   	eval(['Fit(2,nm) = GA.' fieldname ';'])
   	FC(nm,:) = GA.freqConditions;
   	ALPH(nm,:) = GA.alph;
	str = ['if mod(nm,' num2str(incrementevery) ') == 0,GA.' fieldname ' = GA.' fieldname '+' num2str(incrementby) ';,end']
   	eval(str);
	eval(['paramvalue = GA.' fieldname ';'])
	disp('* *********************************************************************')
	disp('*  Varying parameter option on.')
	disp(['*  GA.' fieldname ' is now ' num2str(paramvalue)])
	disp('* *********************************************************************')
   end

   eval(['save model' num2str(nm) '_' M.date ' M'])
   save GAworkspace
   diary off
   fprintf('\n')
end


function V = VBA_spm_vol_nifti(P,n)
% Get header information for a NIFTI-1 image
% FORMAT V = spm_vol_nifti(P,n)
% P   - filename or NIfTI object
% n   - volume id (a 1x2 array, e.g. [3,1])
%
% V   - a structure containing the image volume information
%__________________________________________________________________________
% Copyright (C) 2005-2014 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: spm_vol_nifti.m 6079 2014-06-30 18:25:37Z spm $

if nargin<2,  n = [1 1];      end
if ischar(n), n = str2num(n); end

if ischar(P)
    N = nifti(P);
else
    N = P;
end
n  = [n 1 1];
n  = n(1:2);
dm = [N.dat.dim 1 1 1 1];
if any(n>dm(4:5)), V = struct([]); return; end

dt = struct(N.dat);
dt = double([dt.dtype dt.be]);

if isfield(N.extras,'mat') && ...
        size(N.extras.mat,3) >= n(1) && ...
        sum(sum(N.extras.mat(:,:,n(1)))) ~= 0
    mat = N.extras.mat(:,:,n(1));
else
    mat = N.mat;
end

off = (n(1)-1+dm(4)*(n(2)-1))*ceil(spm_type(dt(1),'bits')*dm(1)*dm(2)/8)*dm(3) + ...
    N.dat.offset;

V   = struct('fname',   N.dat.fname,...
             'dim',     dm(1:3),...
             'dt',      dt,...
             'pinfo',   [N.dat.scl_slope N.dat.scl_inter off]',...
             'mat',     mat,...
             'n',       n,...
             'descrip', N.descrip,...
             'private', N);


function engine = ff_inf_engine(bnet)
% FF_INF_ENGINE Factored frontier inference engine for DBNs
% engine = ff_inf_engine(bnet)
%
% The model must be topologically isomorphic to an HMM.
% In addition, each hidden node is assumed to have at most one observed child,
% and each observed child is assumed to have exactly one hidden parent.
%
% For details of this algorithm, see
%  "The Factored Frontier Algorithm for Approximate Inference in DBNs",
%   Kevin Murphy and Yair Weiss, UAI 2001.
%
% THIS IS HIGHLY EXPERIMENTAL CODE!

ss = length(bnet.intra);
onodes = bnet.observed;
hnodes = mysetdiff(1:ss, onodes);

[persistent_nodes, transient_nodes] = partition_dbn_nodes(bnet.intra, bnet.inter);
assert(isequal(onodes, transient_nodes));
assert(isequal(hnodes, persistent_nodes));

engine.onodes = onodes;
engine.hnodes = hnodes;
engine.marginals = [];
engine.fwd = [];
engine.back = [];
engine.CPDpot = [];
engine.filter = [];

obschild = zeros(1,ss);
for i=engine.hnodes(:)'
  %ocs = myintersect(children(bnet.dag, i), onodes);
  ocs = children(bnet.intra, i);
  assert(length(ocs) <= 1);
  if length(ocs)==1
    obschild(i) = ocs(1);
  end
end
engine.obschild = obschild;

engine = class(engine, 'ff_inf_engine', inf_engine(bnet));


function r = mtimes(p,q)
%TIMES this function multiplies the x, y, and z values of the structures that I use in
% the FVtool.
% reassign the scalar to new variable a and the struct to new variable b
%
% SYNOPSIS:
%
%
% PARAMETERS:
%
%
% RETURNS:
%
%
% EXAMPLE:
%
% SEE ALSO:
%

% Copyright (c) 2012-2016 Ali Akbar Eftekhari
% See the license file

if (isa(p, 'FaceVariable')&&isa(q, 'FaceVariable'))
    error('FVMtool: Wrong use of mtimes for a face variable. Try using .* instead.');
elseif isa(p, 'FaceVariable')
    r=p;
    r.xvalue = p.xvalue*q;
    r.yvalue = p.yvalue*q;
    r.zvalue = p.zvalue*q;
else
    r=q;
    r.xvalue = p*q.xvalue;
    r.yvalue = p*q.yvalue;
    r.zvalue = p*q.zvalue;
end


function train_model = runTrainNRSFM(data,class)

% Run and cache NRSFM. Load cached NRSFM model if available
globals;
params = get_params();

% Path to cached NRSFM model
shapeModelNRSFMFile = fullfile(cachedir,class,'shapeModelNRSFM.mat');

fprintf('\n%%%%%%%%%%%% NRSFM %%%%%%%%%%%%\n');

% Run NRSFM if cached model not found
if(exist(shapeModelNRSFMFile,'file'))
    fprintf('Loading cached NRSFM model from \n%s\n',shapeModelNRSFMFile);
    load(shapeModelNRSFMFile,'train_model');
else
    % Setup training data struct (filter instances and normalize keypoints)
    [train,~] = prep_data(data.train,1,params.nrsfm.flip);

    % Train model
    fprintf('Train Non Rigid SFM model \n');
    train_model = train_nrsfm(params.class,train);

    % Caching trained NRSFM model
    fprintf('Caching NRSFM model in \n%s\n',shapeModelNRSFMFile);
    save(shapeModelNRSFMFile,'train_model');
end

end


function [matlabbatch, indValidContrasts] = tapas_physio_check_prepare_job_contrasts(fileSPM, ...
    model, SPM, indReportPhysContrasts, namesPhysContrasts)
% adapts contrast generator for physiogical regressors to actual SPM-file
% (directory & design matrix columns)
%
%
% IN
%   fileSpm
%   model
%   SPM
%   indReportPhysContrasts  [1, nContrasts] vector of phys contrast ids to be
%                           reported, in their default order
%   indValidContrasts       contrasts ids that could be queried with existing
%                           physIO model
%   namesPhysContrasts      if contrasts shall be named differently,
%                           entered here
% Author: Lars Kasper
% Created: 2014-01-21
% Copyright (C) 2014 TNU, Institute for Biomedical Engineering, University of Zurich and ETH Zurich.
%
% This file is part of the PhysIO 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/>.

if nargin < 6
    namesPhysContrasts = tapas_physio_get_contrast_names_default();
end

if ~exist('SPM', 'var'), load(fileSPM); end

[colPhys, colCard, colResp, colMult, colHRV, colRVT, colRois, colMove, colAll] = ...
    tapas_physio_check_get_regressor_columns(SPM, model);
con{1} = colPhys;
con{2} = colCard;
con{3} = colResp;
con{4} = colMult;
con{5} = colHRV;
con{6} = colRVT;
con{7} = colRois;
con{8} = colMove;
con{9} = colAll;

pathCodePhysIO = fileparts(mfilename('fullpath'));
load(fullfile(pathCodePhysIO,'tapas_physio_check_job_contrasts.mat'));
matlabbatch{1}.spm.stats.con.spmmat{1} = fileSPM;

% execute computation only for non-empty contrasts;
indValidContrasts = intersect(indReportPhysContrasts, ...
    find(~cellfun(@isempty, con)));
nContrasts = numel(indValidContrasts);
for c = 1:nContrasts
    iC = indValidContrasts(c);
    F{c} = zeros(max(con{iC}));
    F{c}(sub2ind(size(F{c}),con{iC}, con{iC})) = 1;
    matlabbatch{1}.spm.stats.con.consess{c}.fcon.convec{1} = F{c};

    matlabbatch{1}.spm.stats.con.consess{c}.fcon.name = ...
            namesPhysContrasts{indValidContrasts(c)};
end

% remove additional contrasts in matlabbatch
matlabbatch{1}.spm.stats.con.consess(nContrasts+1:end) = [];


function [fl re]=lines(im_texto)
% Divide text in lines
% im_texto->input image; fl->first line; re->remain line
% Example:
% im_texto=imread('TEST_3.jpg');
% [fl re]=lines(im_texto);
% subplot(3,1,1);imshow(im_texto);title('INPUT IMAGE')
% subplot(3,1,2);imshow(fl);title('FIRST LINE')
% subplot(3,1,3);imshow(re);title('REMAIN LINES')
im_texto=clip(im_texto);
num_filas=size(im_texto,1);
for s=1:num_filas
    if sum(im_texto(s,:))==0
        nm=im_texto(1:s-1, :); % First line matrix
        rm=im_texto(s:end, :);% Remain line matrix
        fl = clip(nm);
        re=clip(rm);
        %*-*-*Uncomment lines below to see the result*-*-*-*-
        %         subplot(2,1,1);imshow(fl);
        %         subplot(2,1,2);imshow(re);
        break
    else
        fl=im_texto;%Only one line.
        re=[ ];
    end
end

function img_out=clip(img_in)
[f c]=find(img_in);
img_out=img_in(min(f):max(f),min(c):max(c));%Crops image


classdef NodeCoordinatesComputerTester < Tester

    properties (Access = private)
        data
    end

    properties (Access = public)
        testName
        corrValues
        calcValues
    end

    methods (Access = public)

        function obj = NodeCoordinatesComputerTester(cParams)
            obj.data = cParams;
            obj.testName = 'NodeCoordinatesComputer';
            obj.loadCorrectValues();
            obj.obtainCalculatedData();
        end

    end

    methods (Access = protected)

        function loadCorrectValues(obj)
            switch obj.data.nvert
                case 4
                    vC = load('vertCoordQuad.mat');
                    bC = load('boundCoordQuad.mat');
                    tC = load('totalCoordQuad.mat');
                case 6
                    vC = load('vertCoordHex.mat');
                    bC = load('boundCoordHex.mat');
                    tC = load('totalCoordHex.mat');
            end
            obj.corrValues(1).Matrix = vC.vertCoord;
            obj.corrValues(2).Matrix = bC.boundary;
            obj.corrValues(3).Matrix = tC.coord;
        end

        function obtainCalculatedData(obj)
            solution = NodeCoordinatesComputer(obj.data);
            solution.computeCoordinates();
            obj.calcValues(1).Matrix = solution.vertCoord;
            obj.calcValues(2).Matrix = solution.boundCoord;
            obj.calcValues(3).Matrix = solution.totalCoord;
        end

    end

end


%%%%%%%%%%% author: Szymon Leja 2008-01-11
function [y]=dec2q15(x,form)

option = {'mode' , 'roundmode', 'overflowmode', 'format'};
value   = {'fixed', 'ceil'     , 'saturate'    ,  [16 15]};
q = quantizer( option, value ) ;

if form=='bin'
    y=num2bin(q,x);
end;

if form=='hex'
    y=num2hex(q,x);
end;

end


function sqexpKernDisplay(kern, spacing)

% SQEXPKERNDISPLAY Display parameters of the SQEXP kernel.
% FORMAT
% DESC displays the parameters of the pre-built compound squared exponential
% kernel and the kernel type to the console.
% ARG kern : the kernel to display.
%
% FORMAT does the same as above, but indents the display according
% to the amount specified.
% ARG kern : the kernel to display.
% ARG spacing : how many spaces to indent the display of the kernel by.
%
% SEEALSO : sqexpKernParamInit, modelDisplay, kernDisplay
%
% COPYRIGHT : Neil D. Lawrence, 2004

% KERN

if nargin > 1
  spacing = repmat(32, 1, spacing);
else
  spacing = [];
end
spacing = char(spacing);
fprintf(spacing);
fprintf('RBF Variance: %2.4f\n', kern.rbfVariance)
fprintf(spacing);
fprintf('RBF inverse width: %2.4f\n', kern.inverseWidth)
fprintf(spacing);
fprintf('White noise Variance: %2.4f\n', kern.whiteVariance)
fprintf(spacing);
fprintf('Bias Kernel Variance: %2.4f\n', kern.biasVariance)


function h = plotOrbit(color, sma, ecc, inc, raan, arg, minTru, maxTru, gmu, varargin)
%plotOrbit Summary of this function goes here
%   Detailed explanation goes here
    if(minTru >= maxTru)
        h=plotOrbit(color, sma, ecc, inc, raan, arg, minTru, 2*pi, gmu, varargin{:});
        plotOrbit(color, sma, ecc, inc, raan, arg, 0, maxTru, gmu, varargin{:});
        return;
    end

    if(~isempty(varargin) && ~isempty(varargin{1}))
        axisPlotTo = varargin{1};
    else
        axisPlotTo = gca;
    end

    try
        if(~isempty(varargin) && length(varargin)>=2)
            if(length(varargin{2}) == 3)
                rOffset = reshape(varargin{2},3,1);
            else
                rOffset = [0;0;0];
            end
        else
            rOffset = [0;0;0];
        end
    catch
        rOffset = [0;0;0];
    end

    try
        if(~isempty(varargin) && length(varargin)>=3 && length(varargin{3}) == 1)
            lineWidth = varargin{3};
        else
            lineWidth = 1.5;
        end
    catch
        lineWidth = 1.5;
    end

    if(~isempty(varargin) && length(varargin)>=4)
        lineStyle = varargin{4};
    else
        lineStyle = '-';
    end

    tru = linspace(minTru,maxTru,250);
    zeroArr = zeros(size(tru));
    sma = zeroArr + sma;
    ecc = zeroArr + ecc;
    inc = zeroArr + inc;
    raan = zeroArr + raan;
    arg = zeroArr + arg;

    [rVect,~] = vect_getStatefromKepler(sma, ecc, inc, raan, arg, tru, gmu, false);
    x = rVect(1,:) + rOffset(1);
    y = rVect(2,:) + rOffset(2);
    z = rVect(3,:) + rOffset(3);

    hold(axisPlotTo,'on');
    if(ischar(color))
        colorNew = color;
        try
            h = plot3(axisPlotTo, x,y,z, 'Color', colorNew, 'LineWidth', lineWidth, 'LineStyle', lineStyle);
        catch
            h = plot3(axisPlotTo, x,y,z, 'Color', color, 'LineWidth', lineWidth, 'LineStyle', lineStyle);
        end
    else
        h = plot3(axisPlotTo, x,y,z, lineStyle, 'Color', color, 'LineWidth', lineWidth);
    end

    hold(axisPlotTo,'off');
end


% initialize VAR (once)
clear all;close all;clc
% clearvars -except 'CellResp' 'const'; clc

data_dir = GetCurrentDataDir();
save_dir = GetCurrentDataDir();
i_fish = 1;

%% load data
disp(['load fish ' num2str(i_fish)]);

filename = ['Data_F' num2str(i_fish) '.mat'];
load(fullfile(data_dir,filename),'data');
% [CellResp,data,dimCR] = LoadFileFromParts(data_dir,filename,'CellResp');

names = fieldnames(data); % cell of strings
for i = 1:length(names),
    eval([names{i} '= data.',names{i} ';']);
end

%% Initialize VAR
VAR = [];
%%
i_ClusGroup = 1;
VAR(i_fish).ClusGroupName{i_ClusGroup} = 'selection';

i_Cluster = 1;
cIX_abs = data.absIX(1:10:end);
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).name = '1/10 of validated cells';
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).cIX_abs = cIX_abs;
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).gIX = ones(length(cIX_abs),1);
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).numK = 1;

%
i_ClusGroup = 2;
VAR(i_fish).ClusGroupName{i_ClusGroup} = 'init';

i_Cluster = 1;
cIX_abs = (1:data.numcell_full)';
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).name = 'all raw cells (ROI''s)';
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).cIX_abs = cIX_abs;
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).gIX = ones(length(cIX_abs),1);
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).numK = 1;

i_Cluster = 2;
cIX_abs = data.absIX;
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).name = 'validated cells';
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).cIX_abs = cIX_abs;
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).gIX = ones(length(cIX_abs),1);
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).numK = 1;

%%
i_fish = 2;
i_ClusGroup = 1;
i_Cluster = 1;
cIX_abs = (1:data.numcell_full)';
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).name = 'all raw cells (ROI''s)';
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).cIX_abs = cIX_abs;
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).gIX = ones(length(cIX_abs),1);
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).numK = 1;

i_ClusGroup = 1;
i_Cluster = 2;
cIX_abs = data.absIX;
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).name = 'validated cells';
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).cIX_abs = cIX_abs;
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).gIX = ones(length(cIX_abs),1);
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).numK = 1;

i_ClusGroup = 2;
i_Cluster = 1;
cIX_abs = data.absIX(1:10:end);
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).name = '1/10 of validated cells';
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).cIX_abs = cIX_abs;
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).gIX = ones(length(cIX_abs),1);
VAR(i_fish).ClusGroup{i_ClusGroup}(i_Cluster).numK = 1;

%%
save(fullfile(data_dir,'VAR_current.mat'),'VAR');

%%

% varience/std for reps for each cell
% if i_fish==2 || i_fish==3 || i_fish==6,
%     period_real = period/2;
% else
%     period_real = period;
% end
% nrep_real = floor((size(CR,2)-shift)/period_real);
% while period_real*nrep_real+shift>size(CR,2),
%     nrep_real = nrep_real-1;
% end
% CRZ_3D = reshape(CRZ(:,1+shift:period_real*nrep_real+shift),nCells,period_real,[]);
%% updated method, weighing both std between each rep and (summed with) std of 1st half & 2nd half of experiment - 1/8/15
% CRZ = CONST.M_array.CellResp;
% if i_fish==2 || i_fish==3 || i_fish==6,
%     period_real = CONST.M_array.period/2;
% else
%     period_real = CONST.M_array.period;
% end
% CRZ_3D = reshape(CRZ,size(CRZ,1),period_real,[]);
% divide = round(size(CRZ_3D,3)/2);
% CRZ_std1 = std(CRZ_3D(:,:,1:divide),0,3);
% CRZ_std2 = std(CRZ_3D(:,:,divide+1:end),0,3);
% temp1 = mean(CRZ_std1,2);
% temp2 = mean(CRZ_std2,2);
%
% temp12 = horzcat(temp1,temp2);
% temp = mean(temp12,2)+std(temp12,0,2);
% [~,I] = sort(temp);
% M = temp(I);
% figure;plot(M)
%
% figure;imagesc(CRZ(I,:))
%
% nCells = size(CRZ,1);

%% find low variance / stimulus-locked cells
CRZ_std = std(CRZ_3D,0,3);
temp = mean(CRZ_std,2);

% find mean-std thres: 0.5
[~,I] = sort(temp);
M = temp(I);
figure;plot(M)
%%
i_last = length(VAR(i_fish).Class);
M_perc = [0.025,0.1,0.3];
for j = 1:length(M_perc);
    thres = M(round(nCells*M_perc(j)));
    cIX = find(temp<thres);
    i = j+i_last;
    VAR(i_fish).Class(i).round = 0;
    VAR(i_fish).Class(i).name = ['perc < ' num2str(M_perc(j)*100) '%'];
    %     VAR(i_fish).Class(i).notes = ['perc < ' num2str(M_perc(j)*100) '%'];
    VAR(i_fish).Class(i).cIX = cIX;
    VAR(i_fish).Class(i).gIX = ones(length(cIX),1);
    VAR(i_fish).Class(i).numel = length(cIX);
    VAR(i_fish).Class(i).numK = 1;
    VAR(i_fish).Class(i).datatype = 'std';
end

%% shift CR?
% shift = 161;
% nrep=floor(size(CR,2)/period)-1;
%
% skiplist=[];
% IX_rep=setdiff(1:nrep, skiplist);
% IX=zeros(period*length(IX_rep),1);
%
% for i=1:length(IX_rep)
%     IX(period*(i-1)+1:period*i)=period*(IX_rep(i)-1)+1+shift:period*(IX_rep(i))+shift;
% end
%
% % cell_resp=cell_resp(:,1:nrep*period);
% CRA=mean(reshape(CR(:,IX),[nCells,period,length(IX_rep)]),3);
% CRAZ = zscore(CRA')';


function [lgraph,hyperParams,numsNetParams,FLOPs] = importDarknetWeights(cfgfile,weightsfile,cutoffModule)
% IMPORTDARKNETWEIGHTS 功能：指定导入部分module的darknet模型
% 输入：cfgfile, 指定的cfg后缀的模型描述文件
%       weighfile, 指定的.weights后缀的二进制文件
%       cutoffModule,(可选项)1*1的正整数，(可选项)1*1的正整数，指定导出darknet前cutoffModule个module。以cfg文件中第一个非[net]开始的module为0开始的计数，没有该项则导出整个网络
% 输出：lgraph， matlab深度学习模型计算图
%      hyperParams,结构体，超参配置文件
%      numsReadParams,权重参数个数
%      FLOPs， 模型计算力
% 注意：1、适合2019b版本及以上
%       2、leaky阈值darknet为0.1
%       3、如果某个module中有bn层，则conv的bias为0，因为darknet是这种存储形式
%      4、darknet weights保存顺序依次为BN层offset,scale,mean,variance,Conv层的bias,weights
%      特征图输出output Size = (Input Size – ((Filter Size – 1)*Dilation Factor + 1) + 2*Padding)/Stride + 1
% 参考：1、官方文档，Specify Layers of Convolutional Neural Network
%      2、https://www.zhihu.com/question/65305385
%       3、https://github.com/ultralytics/yolov3/blob/master/models.py
% cuixingxing150@gmail.com
% 2019.8.19
% 2019.9.4修改，由原来的darknet中[net]为0开始的索引改为以cfg文件中第一个非[net]开始的module为0开始的计数的索引
% 2020.4.25修改函数默认输入参数
%
arguments
    cfgfile (1,:) char
    weightsfile (1,:) char
    cutoffModule {mustBeNonnegative} = 0 % 默认导入所有的层
end

[lgraph,hyperParams,numsNetParams,FLOPs,...
    moduleTypeList,moduleInfoList,layerToModuleIndex] = importDarkNetLayers(cfgfile);% only weights需要cutoff,layer都导入
assert(length(moduleTypeList)==length(moduleInfoList));

%% 读取权重参数文件
fid_w = fopen(weightsfile,'rb');
if fid_w == -1
  error('Author:Function:OpenFile', 'Cannot open file: %s', weightsfile);
end
header = fread(fid_w, 3, '*int32');
if header(2) > 1
    header2 = fread(fid_w, 1, '*int64'); % int64占用8个字节
else
    header2 = fread(fid_w, 1, '*int32'); % int32占用4个字节
end
fprintf('Major :%d, Minor :%d,Revision :%d,number of images during training:%d,reading params...\n',...
    header(1),header(2),header(3),header2);
weights = fread(fid_w,'*single');
fclose(fid_w);

% numsWeightsParams = numel(weights);
readSize = 1;
numsModule = length(moduleTypeList);
if cutoffModule>0
    numsModule = cutoffModule+1;% [net] plus 1
end

for i = 1:numsModule
    currentModuleType = moduleTypeList{i};
    currentModuleInfo = moduleInfoList{i};
    if strcmp(currentModuleType,'[convolutional]')
        currentModule = lgraph.Layers(i==layerToModuleIndex);
        filterSize = str2double(currentModuleInfo.size);
        numFilters = str2double(currentModuleInfo.filters);
        channels_in = moduleInfoList{i-1}.channels;

        if isfield(currentModuleInfo,'batch_normalize')
            % bn bias
            bn_bias = weights(readSize:readSize+numFilters-1);
            bn_bias = reshape(bn_bias,[1,1,numFilters]);
            currentModule(2).Offset = bn_bias;
            readSize = readSize+numFilters;
            % bn weight
            bn_weight = weights(readSize:readSize+numFilters-1);
            bn_weight = reshape(bn_weight,[1,1,numFilters]);
            currentModule(2).Scale = bn_weight;
            readSize = readSize+numFilters;
             % bn trainedMean
            bn_mean = weights(readSize:readSize+numFilters-1);
            bn_mean = reshape(bn_mean,[1,1,numFilters]);
            currentModule(2).TrainedMean = bn_mean;
            readSize = readSize+numFilters;
             % bn trainedVariance
            bn_var = weights(readSize:readSize+numFilters-1);
            bn_var = reshape(bn_var,[1,1,numFilters]);
            if any(bn_var<-0.01)
                error("方差应该大于0！");
            end
            currentModule(2).TrainedVariance = abs(bn_var); % 防止接近于0的数是负数
            readSize = readSize+numFilters;
            % conv bias 为0
            if isfield(currentModuleInfo,'groups')
                numGroups = str2double(currentModuleInfo.groups);
                numFiltersPerGroup_out = numFilters/numGroups;
                currentModule(1).Bias = zeros(1,1,numFiltersPerGroup_out,numGroups,'single');
            else
                currentModule(1).Bias = zeros(1,1,numFilters,'single');
            end
        else
            % load conv bias
            conv_bias = weights(readSize:readSize+numFilters-1);
            if isfield(currentModuleInfo,'groups')
                numGroups = str2double(currentModuleInfo.groups);
                numFiltersPerGroup_out = numFilters/numGroups;
                conv_bias = reshape(conv_bias,1,1,numFiltersPerGroup_out,numGroups);
            else
                conv_bias = reshape(conv_bias,1,1,numFilters);
            end
            currentModule(1).Bias = conv_bias;
            readSize = readSize+numFilters;
        end % end of is bn
        % load conv weights
        if isfield(currentModuleInfo,'groups')
            numGroups = str2double(currentModuleInfo.groups);
            numFiltersPerGroup_out = numFilters/numGroups;
            nums_conv_w = filterSize*filterSize*channels_in/numGroups*numFiltersPerGroup_out*numGroups;
            conv_weights = weights(readSize:readSize+nums_conv_w-1);
            conv_weights = reshape(conv_weights,filterSize,filterSize,channels_in/numGroups,numFiltersPerGroup_out,numGroups);
            conv_weights = permute(conv_weights,[2,1,3,4,5]);
            currentModule(1).Weights = conv_weights;
            readSize = readSize+nums_conv_w;
        else
            nums_conv_w = filterSize*filterSize*channels_in*numFilters;% weights
            conv_weights = weights(readSize:readSize+nums_conv_w-1);
            conv_weights = reshape(conv_weights,filterSize,filterSize,channels_in,numFilters);
            conv_weights = permute(conv_weights,[2,1,3,4]);
            currentModule(1).Weights = conv_weights;
            readSize = readSize+nums_conv_w;
        end % end of load conv weights
        % 更新参数
        % lgraph.Layers(i==layerToModuleIndex) = currentModule;
        for replaceInd = 1:length(currentModule)
            layerName = currentModule(replaceInd).Name;
            lgraph = replaceLayer(lgraph,layerName,currentModule(replaceInd));
        end
    end % end of module '[convolutional]'

    % fullyConnectedLayer
    if  strcmp(currentModuleType,'[connected]')
        currentModule = lgraph.Layers(i==layerToModuleIndex);
        numFilters = str2double(currentModuleInfo.output);
        % load fc bias
        numBias = numFilters;
        fl_bias = weights(readSize:readSize+numBias-1);
        fl_bias = reshape(fl_bias,numBias,1);
        currentModule(1).Bias = fl_bias;
        readSize = readSize+numBias;
         % load fc weights
        input_all_neurons = prod(moduleInfoList{i-1}.mapSize)*moduleInfoList{i-1}.channels;
        numWeights = numFilters*input_all_neurons; % help fullyConnectedLayer weights
        fl_weights = weights(readSize:readSize+numWeights-1);
        fl_weights = reshape(fl_weights,input_all_neurons,numFilters);
        fl_weights = permute(fl_weights,[2,1]);% fc不需要permute?
        currentModule(1).Weights = fl_weights;
        readSize = readSize+numWeights;
        % 更新参数
        for replaceInd = 1:length(currentModule)
            layerName = currentModule(replaceInd).Name;
            lgraph = replaceLayer(lgraph,layerName,currentModule(replaceInd));
        end
    end % end of module '[connected]'
end % end of nums of module

if isa(lgraph.Layers(end),'nnet.cnn.layer.SoftmaxLayer')
    lastLayerName = lgraph.Layers(end).Name;
    classifyLayer = classificationLayer('Name','classify');
    lgraph = addLayers(lgraph,classifyLayer);
    lgraph = connectLayers(lgraph,lastLayerName,'classify');
end

fprintf('Load parameters succfully!\n')


function [MDP] = spm_MDP_VB_sleep(MDP,BMR)
% Bayesian model reduction (sleep) for MDP models
% FORMAT [MDP] = spm_MDP_VB_sleep(MDP,BMR)
%
% MDP  - (inverted) MDP structure
%
% BMR.g - modality [default: 1]
% BMR.o - outcomes - that induce REM [default: {}]
% BMR.x - increase in concentration parameters for BMR [default: 8]
% BMR.f - hearing factors to sum over [default: 0]
% BMR.T - log Bayes factor threshold [default: 1/4]
% BMR.m - indicator function to enable BMR [@(i,i1,i2,i3,i4)1]
%
%
% MDP  - (reduced) model structure: with reduced MDP.a
%
% This routine optimises the hyperparameters of a NDP model (i.e.,
% concentration parameters encoding probabilities. It uses Bayesian model
% reduction to evaluate the evidence for models with and without a
% particular parameter in the columns of MDP.a (c.f., SWS)
%
% If specified, the scheme will then recompute posterior beliefs about the
% model parameters based upon (fictive) outcomes generated under its
% (reduced) generative model.(c.f., REM sleep)
%
% See also: spm_MDP_log_evidence.m, spm_MDP_VB and spm_MDP_VB_X.m
%__________________________________________________________________________
% Copyright (C) 2005 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_MDP_VB_sleep.m 7679 2019-10-24 15:54:07Z spm $

% deal with a sequence of trials
%==========================================================================

% BMR options
%--------------------------------------------------------------------------
try, g   = BMR.g; catch, g = 1;   end
try, o   = BMR.o; catch, o = {};  end
try, x   = BMR.x; catch, x = 8;   end
try, f   = BMR.f; catch, f = 0;   end
try, T   = BMR.T; catch, T = 1/4; end

% model selection function
%--------------------------------------------------------------------------
if isfield(BMR,'m')
    m = BMR.m;
else
    m = @(i,i1,i2,i3,i4)1;
end

% Baysian model reduction - parameters
%--------------------------------------------------------------------------
if isfield(MDP,'a')
    [sa,ra] = spm_MDP_VB_prune(MDP(end).a{g},MDP(1).a0{g},f,x,T,m);
end

% reiterate expectation maximisation (or rapid eye movement sleep)
%--------------------------------------------------------------------------
N  = numel(o);
if N

    % remove previous experience
    %----------------------------------------------------------------------
    REM  = MDP;
    try, REM = rmfield(REM,'s'); end
    try, REM = rmfield(REM,'o'); end
    try, REM = rmfield(REM,'u'); end

    % and install a generative process and reset priors
    %----------------------------------------------------------------------
    REM.a{g}  = ra;
    REM.a0{g} = ra;
    REM.o = o{1};
    for i = 1:N
        REM(i)   = REM(1);
        REM(i).o = o{i};
    end

    % Bayesian updating and updated parameters
    %----------------------------------------------------------------------
    REM    = spm_MDP_VB_X(REM);
    MDP.a  = REM(N).a;
    MDP.a0 = REM(N).a0;

else

    % otherwise, use reduced posteriors and priors
    %----------------------------------------------------------------------
    MDP.a{g}  = sa;
    MDP.a0{g} = ra;

end

function [sA,nA] = spm_MDP_VB_prune(qA,pA,f,x,T,m)
% FORMAT [sA,nA] = spm_MDP_VB_prune(qA,pA,f,x,T,m)
% qA - posterior expectations
% pA - prior expectations
% f  - hidden factor to integrate over [defult: 0]
% x  - prior counts [default: 8]
% T  - threshold for Bayesian model reduction [default: three]
%
% sA - reduced posterior expectations
% rA - reduced prior expectations
%__________________________________________________________________________

% defaults
%--------------------------------------------------------------------------
if nargin < 4, T = 3; end
if nargin < 3, x = 8; end

% identify noninformative subspaces
%--------------------------------------------------------------------------
ndim  = ndims(pA);
for i = 1:ndim
    d    = 1:ndim;
    d(i) = [];
    s    = pA < 4 & pA > 0;
    for j = 1:(ndim - 1)
        s = sum(s,d(j));
    end
    ind{i} = find(s(:));
end

% motifs of salient (low free free energy) abilities
%--------------------------------------------------------------------------
mot{1} = [1 0 0;0 1 0;0 0 1];
mot{2} = [1 0 0;0 0 1;0 1 0];
mot{3} = [0 1 0;1 0 0;0 0 1];
mot{4} = [0 1 0;0 0 1;1 0 0];
mot{5} = [0 0 1;1 0 0;0 1 0];
mot{6} = [0 0 1;0 1 0;1 0 0];

% model space: additional concentration parameters (i.e., precision)
%--------------------------------------------------------------------------
nmot  = numel(mot);
for i = 1:nmot*nmot;
    rA{i} = spm_zeros(pA);
end

for m1 = 1:numel(mot)
    [i1,i2] = find(mot{m1});
    for m2 = 1:numel(mot)
        i  = nmot*(m1 - 1) + m2;
        for j = 1:numel(i1)
            dA    = spm_zeros(pA);
            dA(1:3,i1(j),:,i2(j),4) = mot{m2};
            rA{i} = rA{i} + dA*x;
        end
    end
end

% score models using Bayesian model reduction
%--------------------------------------------------------------------------
for i = 1:numel(rA);
    G    = spm_MDP_log_evidence(qA,pA,pA + rA{i});
    F(i) = sum(G(isfinite(G)));
end

% find any model that has greater evidence than the parent model
%--------------------------------------------------------------------------
[F,j] = min(F);
if (F + T) < 0
    rA = rA{j};
else
    rA = spm_zeros(pA);
end

% reduced posterior and prior
%--------------------------------------------------------------------------
sA     = qA;
nA     = pA;
for i1 = 1:size(qA,2)
    for i2 = 1:size(qA,3)
        for i3 = 1:size(qA,4)
            for i4 = 1:size(qA,5)

                % get posteriors, priors and reduced priors
                %----------------------------------------------------------
                p  = pA(:,i1,i2,i3,i4);
                q  = qA(:,i1,i2,i3,i4);
                r  = rA(:,i1,i2,i3,i4);
                j  = find(p);
                p  = p(j);
                q  = q(j);
                r  = j(find(r(j)));

                % redistribute concentration parameters if indicated
                %----------------------------------------------------------
                if numel(r);
                    sA(:,i1,i2,i3,i4) = 0;
                    nA(:,i1,i2,i3,i4) = 0;
                    sA(r,i1,i2,i3,i4) = sum(q);
                    nA(r,i1,i2,i3,i4) = sum(p);
                else
                    sA(j,i1,i2,i3,i4) = q;
                    nA(j,i1,i2,i3,i4) = p;
                end
            end
        end
    end
end

return

% alternative formulation with specified indicator functions
%==========================================================================

% defaults
%--------------------------------------------------------------------------
if nargin < 5, m = @(i,i1,i2,i3,i4)1; end
if nargin < 4, T = 3; end
if nargin < 3, x = 8; end
if nargin < 2, f = 0; end

% column-wise model comparison
%--------------------------------------------------------------------------
for i1 = 1:size(qA,2)
    for i2 = 1:size(qA,3)
        for i3 = 1:size(qA,4)
            for i4 = 1:size(qA,5)

                % get posteriors, priors and cycle over reduced priors
                %----------------------------------------------------------
                p  = pA(:,i1,i2,i3,i4);
                q  = qA(:,i1,i2,i3,i4);
                j  = find(p);
                p  = p(j);
                q  = q(j);

                % informative state?
                %----------------------------------------------------------
                F  = 0;
                if length(j) > 1
                    for i = 1:length(j);
                        if m(i,i1,i2,i3,i4)
                            r    = p;
                            r(i) = r(i) + x;
                            F(i) = spm_MDP_log_evidence(q,p,r);
                        else
                            F(i) = 16;
                        end
                    end
                end

                % eliminate parameter
                %----------------------------------------------------------
                [F,i] = min(F);
                mF(i1,i2,i3,i4) = F;
                iF(i1,i2,i3,i4) = j(i);
            end
        end
    end
end

% pool over s{f}
%---------------------------------------------------------------------
if f, sF = sum(mF,f); end

% column-wise reduction
%--------------------------------------------------------------------------
sA     = qA;
rA     = pA;
for i1 = 1:size(qA,2)
    for i2 = 1:size(qA,3)
        for i3 = 1:size(qA,4)
            for i4 = 1:size(qA,5)

                % get posteriors, priors and cycle over reduced priors
                %----------------------------------------------------------
                p  = pA(:,i1,i2,i3,i4);
                q  = qA(:,i1,i2,i3,i4);
                i  = iF(i1,i2,i3,i4);
                j  = find(p);
                p  = p(j);
                q  = q(j);

                % BMC
                %----------------------------------------------------------
                if f == 0
                    F = mF(i1,i2,i3,i4);
                elseif f == 1
                    F = sF( 1,i2,i3,i4);
                elseif f == 2
                    F = sF(i1, 1,i3,i4);
                elseif f == 3
                    F = sF(i1,i2, 1,i4);
                elseif f == 4
                    F = sF(i1,i2,i3, 1);
                end

                % eliminate parameter
                %----------------------------------------------------------
                if F < - T;
                    sA(:,i1,i2,i3,i4) = 0;
                    rA(:,i1,i2,i3,i4) = 0;
                    sA(i,i1,i2,i3,i4) = sum(q);
                    rA(i,i1,i2,i3,i4) = sum(p);
                else
                    sA(j,i1,i2,i3,i4) = q;
                    rA(j,i1,i2,i3,i4) = p;
                end

            end
        end
    end
end


function events = sta_lta(wave,varargin)

%STA_LTA: Short-Time-Average/Long-Time-Average event detector.
%
%USAGE: events = sta_lta(wave,prop_name_1,prop_val_1,...)
%
%DIAGRAM:
%                       /\      /\/\        /\
%              /\  /\/\/  \/\  /    \/\    /  \/\
%                \/          \/        \/\/      \
%                                           |-STA-| -->
%         --> |-----------------LTA---------------| -->
%
%INPUTS: wave     - A waveform object containing events (maybe)
%        varargin - User-defined parameter name/value pairs (below)
%
%VALID PROP_NAME:
%
%  'edp'      - Event Detection Parameters (Detailed in 'VALID PROP_VAL')
%  'lta_mode' - LTA window behavior following a 'trigger on' flag
%  'skip'     - Times for STA/LTA to skip over (if known), examples are
%               data gaps, calibration pulses, periods of excessive noise
%  'eot'      - Event output type (Detailed in 'VALID PROP_VAL')
%  'fix'      - Output event length fixed or variable?
%  'pad'      - Pad output events by a fixed amount of time before start
%               time (trigger on) and after stop time (trigger off).
%
%VALID PROP_VAL:
%
%  'edp'(1x6 numeric) ... default: [1 8 2 1.6 0 3]
%     --> [l_sta l_lta th_on th_off min_sep min_dur]
%        --> l_sta    - STA window length (s)
%        --> l_lta    - LTA window length (s)
%        --> th_on    - STA/LTA trigger on threshold
%        --> th_off   - STA/LTA trigger off threshold
%        --> min_sep  - Minimum seperation between trigger off time of an
%                       event and trigger on time of the next event (s)
%        --> min_dur  - Minimum event duration to be recorded(s)
%
%	'lta_mode' (string) ... default: 'continuous'
%     --> 'frozen' - LTA window fixed in place after trigger is turned on
%                    while STA window continues forward.
%     --> 'continuous' - LTA window continues w/ STA window after trigger
%                        is turned on (Same behavior as before trigger)
%     --> 'grow' - LTA left edge fixed, right edges continues w/ STA right
%                  edge after trigger on, thus size of LTA window is
%                  growing until trigger off, at which point LTA window
%                  returns to original size.
%
%	'skip' (nx2 numeric) ... default: [] (don't skip anything)
%     --> skip_val - List of start/stop times to skip
%
%	'eot' (string) ... default: 'sst'
%     --> 'st'  - Return event start times (nx1 numeric)
%                 (a.k.a. trigger on times)
%     --> 'sst' - Return event start/stop times (nx2 numeric)
%                 (a.k.a. trigger on/off times)
%     --> 'ssd' - Return event start/stop datapoints (nx2 integer)
%                 (referenced from first datapoint in 'wave')
%     --> 'wfa' - Return event waveform array (1xn waveform)
%
%   'fix' (1x1 numeric) ... default: 0
%     --> 'fix_val' - If 0, output events will be variable length
%                     (trigger on time to trigger off time)
%                     If a positive numeric value N, output events will be
%                     fixed length (trigger on time to fixed length N)
%                     Units of N is seconds if non-zero
%
%   'pad' (1x2 numeric) ... default: [0 0] (i.e. no padding)
%     --> 'pad_val' - If [0 0] events will have no time padding
%                     [1 2] - pad by 1s before, 2s after event
%                     this will pad events regarless of the value of fix:
%                     i.e. fix = 7, pad = [1 2], returned events are 10s
%
%OUTPUTS: events - events in format specified by 'return'

% Author: Dane Ketner, Alaska Volcano Observatory
% $Date$
% $Revision$

%% Check waveform variable
if isa(wave,'waveform')
   Fs = get(wave,'freq');         % Sampling frequency
   l_v = get(wave,'data_length'); % Length of time series
   tv = get(wave, 'timevector');  % Time vector of waveform
   if isempty(wave)
       disp('Input waveform empty, no events detected')
       events = [];
       return
   end
else
   error('STA_LTA: First Argument must be a waveform object')
end

%% Set all default parameters
l_sta = 1*Fs;     % STA window length
l_lta = 8*Fs;     % LTA window length
th_on = 2;        % Trigger on when sta_to_lta exceeds this theshold
th_off = 1.6;     % Trigger off when sta_to_lta drops below threshold
min_sep = 0*Fs;   % Skip ahead after end of event
min_dur = 3*Fs;   % Any triggers shorter than min_dur are discarded

lta_mode = 'continuous'; % Post trigger-on LTA behavior
skip = [];               % List of start/stop times to skip
eot = 'sst';             % Event output type
fix = 0*Fs;              % Fix event length
pad = [0 0]*Fs;          % Pad event start/stop times

%% Check varargin size
nv = numel(varargin);
if ~rem(nv,2) == 0
   error(['STA_LTA: Arguments after wave must appear in ',...
          'property_name/property_value pairs'])
end

%% User-defined parameters (varargin)
if nv > 0
    for p = 1:2:nv-1
        v1 = varargin{p};
        v2 = varargin{p+1};
        switch lower(v1)
            case 'edp'
                if isnumeric(v2) && numel(v2) == 6
                    l_sta = v2(1)*Fs;    % STA window length
                    l_lta = v2(2)*Fs;    % LTA window length
                    th_on = v2(3);       % Trigger on theshold
                    th_off = v2(4);      % Trigger off threshold
                    min_sep = v2(5)*Fs;  % Skip ahead after end of event
                    min_dur = v2(6)*Fs;  % Minimum event duration
                else
                    error('STA_LTA: Wrong format for input ''edp''')
                end
            case 'lta_mode'
                switch lower(v2)
                    case {'freeze','frozen'}
                        lta_mode = 'frozen';
                    case {'continue','continuous'}
                        lta_mode = 'continuous';
                    case {'grow','growing'}
                        lta_mode = 'grow';
                    otherwise
                      error('STA_LTA: Wrong format for input ''lta_mode''')
                end

            case 'skip'
                if isnumeric(v2) && size(v2,2) == 2
                    skip = v2;
                else
                    error('STA_LTA: Wrong format for input ''skip''')
                end
            case 'eot'
                switch lower(v2)
                    case 'st'
                        eot = v2;
                    case 'sst'
                        eot = v2;
                    case 'ssd'
                        eot = v2;
                    case 'wfa'
                        eot = v2;
                    otherwise
                        error('STA_LTA: Wrong format for input ''eot''')
                end
            case 'fix'
                if isnumeric(v2) && numel(v2) == 1
                    fix = v2*Fs;
                else
                    error('STA_LTA: Wrong format for input ''fix''')
                end
            case 'pad'
                if isnumeric(v2) && size(v2,1) == 1 && size(v2,2) == 2
                    pad = v2*Fs;
                else
                    error('STA_LTA: Wrong format for input ''pad''')
                end
            otherwise
                error(['STA_LTA: ''edp'', ''lta_mode'', ''skip'' ',...
                    '''eot'', ''fix'', and ''pad'' are the only ',...
                    'property names recognized'])
        end
    end
end

%% Initialize waveform data
wave = set2val(wave,skip,NaN);   % NaN skip times
wave = zero2nan(wave,10);        % NaN any data gaps
v = get(wave,'data');            % Waveform data
abs_v = abs(v);                  % Absolute value of time series

%% Initialize flags and other variables
lta_calc_flag = false;       % has the full LTA window been calculated?
ntrig = 0;               % number of triggers
trig_array = zeros(1,2); % array of trigger times: [on,off;on,off;...]

%% Loops over data
% i is the primary reference point (right end of STA/LTA window)
i = l_lta+1;
while i <= l_v % START STA_LTA MAIN LOOP

%% Skip data gaps (NaN values in LTA window)?
   if any(isnan(abs_v(i-l_lta:i)))
      gap = true;
      lta_calc_flag = false; % Force full claculations after gap
      while (gap) && (i < l_v)
         i = i+1;
         if ~any(isnan(abs_v(i-l_lta:i)))
            gap = false;
         end
      end
   end

%% Calculate STA & LTA Sum (Do Full Calculation?)
   if ~lta_calc_flag
      lta_sum = 0;
      sta_sum = 0;
      for j = i-l_lta:i-1              % Loop to compute LTA & STA
         lta_sum = lta_sum + abs_v(j); % Sum LTA window
         if (i - j) <= l_sta           % Sum STA window (right side of LTA)
            sta_sum = sta_sum + abs_v(j);
         end
      end
      lta_calc_flag = true;
   else

%% Calculate STA & LTA Sum (Single new data point if not Full)
      lta_sum = lta_sum - abs_v(i-l_lta-1) + abs_v(i-1);
      sta_sum = sta_sum - abs_v(i-l_sta-1) + abs_v(i-1);
   end

%% Calculate STA & LTA
   lta = lta_sum/l_lta;
   sta = sta_sum/l_sta;

%% Calculate STA/LTA Ratio
   sta_to_lta = sta/lta;

%% Trigger on? (Y/N)
   if (sta_to_lta > th_on)
      j = i;   % Set secondary reference point = primary
      g = 0;   % l_lta growth, only used if LTA growing
      while (sta_to_lta > th_off)
         j = j+1;
         if j < l_v
            sta_sum = sta_sum - abs_v(j-l_sta-1) + abs_v(j-1);
            switch lta_mode
               case 'frozen'
                  % LTA is good just the way it is
               case 'continuous'
                  % Add new data point, remove oldest data point
                  lta_sum = lta_sum - abs_v(j-l_lta-1) + abs_v(j-1);
               case 'grow'
                  % Add new data point, increase
                  lta_sum = lta_sum + abs_v(j-1);
                  l_lta = l_lta + 1;
                  g = g+1;
            end
            sta = sta_sum/l_sta;
            lta = lta_sum/l_lta;
            sta_to_lta = sta/lta;
            if any(isnan(abs_v(j-l_sta:j))) % NaN gaps to skip?
               sta_to_lta = 0; % Force trigger off (data gap in STA window)
            end
         else
            sta_to_lta = 0; % Force trigger off (end of data)
         end
      end
      duration = (j-i); % span from trigger on to trigger off
      l_lta = l_lta-g;

%% Triggered period long enough? (Y/N)
      if duration > min_dur % If duration < min_dur then skip it
         trig_t = i-l_sta;  % Beginning of STA window during trigger on
         end_t  = j;        % End of STA window during trigger off
         ntrig = ntrig + 1; % Event counter
         trig_array(ntrig,:) = [trig_t, end_t];
      end
      i = j + min_sep;   % Skip ahead by minimum event seperation
      lta_calc_flag = false; % Reset LTA calc flag to force new computation
   end
   i = i + 1;
end % END STA_LTA MAIN LOOP

%% Return events
if (trig_array(1,1)==0)&&(trig_array(1,2)==0)
    disp('No events detected')
    events = [];
    return
end
if fix>0
    trig_array(:,2) = trig_array(:,1) + fix;
end
trig_array(:,1) = trig_array(:,1) - pad(1);
trig_array(:,2) = trig_array(:,2) + pad(2);
% If events are padded, make sure the first and last events are not out of
% range (beginning before or ending after the span of input 'wave')
trig_array(trig_array<1) = 1;      % Set to first datapoint
trig_array(trig_array>l_v) = l_v;  % Set to last datapoint
switch lower(eot)
    case {'st'}
        events = tv(trig_array(:,1));
    case {'sst'}
        events = tv(trig_array);
    case {'ssd'}
        events = trig_array;
    case {'wfa'}
        events = [];
        for n = 1:size(trig_array,1)
            events = [events; extract(wave,'INDEX',trig_array(n,1),...
                                                   trig_array(n,2))];
        end
end


%%test network
cam1_size=size(test_data_cam1);
cam2_size=size(test_data_cam2);
cam1_feature1=[];
test_batch_data=zeros(224,224,3,param.test_batch_size,'single');
for m=0:floor(cam1_size(1)/param.test_batch_size)-1
    for n=1:param.test_batch_size
        im_data=imresize((reshape(single(test_data_cam1(m*param.test_batch_size+n,:)),128,64,3)),[224 224]);
        im_data=im_data(:,:,[3,2,1]);
        im_data=permute(im_data,[2,1,3]);
        test_batch_data(:,:,:,n)=im_data;
        test_batch_data(:,:,1,n)=test_batch_data(:,:,1,n)-104;
        test_batch_data(:,:,2,n)=test_batch_data(:,:,2,n)-117;
        test_batch_data(:,:,3,n)=test_batch_data(:,:,3,n)-123;
    end
    net.blobs('data').set_data(test_batch_data);
    net.forward_prefilled;
    cam1_feature1=[cam1_feature1;(squeeze(net.blobs('pool5/7x7_s1').get_data))'];
end
test_batch_data=zeros(224,224,3,param.test_batch_size,'single');
for m=(floor(cam1_size(1)/param.test_batch_size))*param.test_batch_size+1:cam1_size(1)
        count=m-(floor(cam1_size(1)/param.test_batch_size))*param.test_batch_size;
        im_data=imresize((reshape(single(test_data_cam1(m,:)),128,64,3)),[224 224]);
        im_data=im_data(:,:,[3,2,1]);
        im_data=permute(im_data,[2,1,3]);
        test_batch_data(:,:,:,count)=im_data;
        test_batch_data(:,:,1,count)=test_batch_data(:,:,1,count)-104;
        test_batch_data(:,:,2,count)=test_batch_data(:,:,2,count)-117;
        test_batch_data(:,:,3,count)=test_batch_data(:,:,3,count)-123;
end
net.blobs('data').set_data(test_batch_data);
net.forward_prefilled;
index=cam1_size(1)-(floor(cam1_size(1)/param.test_batch_size))*param.test_batch_size;
result1=(squeeze(net.blobs('pool5/7x7_s1').get_data))';
cam1_feature1=[cam1_feature1;result1(1:index,:)];
prob_feature=[];
name_cam1={};
for m=1:param.train_person_num
    test_label_index=find(label_test_cam1==(m+param.train_person_num));
    a=sum(cam1_feature1(test_label_index,:))/size(test_label_index,1);
    prob_feature=[prob_feature;a];
    name_cam1=[name_cam1,test_image_name_cam1{test_label_index(1)}];
end
%extract feature cam2
cam2_feature1=[];
test_batch_data=zeros(224,224,3,param.test_batch_size,'single');
for m=0:floor(cam2_size(1)/param.test_batch_size)-1
    for n=1:param.test_batch_size
        im_data=imresize((reshape(single(test_data_cam2(m*param.test_batch_size+n,:)),128,64,3)),[224 224]);
        im_data=im_data(:,:,[3,2,1]);
        im_data=permute(im_data,[2,1,3]);
        test_batch_data(:,:,:,n)=im_data;
        test_batch_data(:,:,1,n)=test_batch_data(:,:,1,n)-104;
        test_batch_data(:,:,2,n)=test_batch_data(:,:,2,n)-117;
        test_batch_data(:,:,3,n)=test_batch_data(:,:,3,n)-123;
    end
    net.blobs('data').set_data(test_batch_data);
    net.forward_prefilled;
    cam2_feature1=[cam2_feature1;(squeeze(net.blobs('pool5/7x7_s1').get_data))'];
end
test_batch_data=zeros(224,224,3,param.test_batch_size,'single');
for m=(floor(cam2_size(1)/param.test_batch_size))*param.test_batch_size+1:cam2_size(1)
        count=m-(floor(cam2_size(1)/param.test_batch_size))*param.test_batch_size;
        im_data=imresize((reshape(single(test_data_cam2(m,:)),128,64,3)),[224 224]);
        im_data=im_data(:,:,[3,2,1]);
        im_data=permute(im_data,[2,1,3]);
        test_batch_data(:,:,:,count)=im_data;
        test_batch_data(:,:,1,count)=test_batch_data(:,:,1,count)-104;
        test_batch_data(:,:,2,count)=test_batch_data(:,:,2,count)-117;
        test_batch_data(:,:,3,count)=test_batch_data(:,:,3,count)-123;
end
net.blobs('data').set_data(test_batch_data);
net.forward_prefilled;
index=cam2_size(1)-(floor(cam2_size(1)/param.test_batch_size))*param.test_batch_size;
result1=(squeeze(net.blobs('pool5/7x7_s1').get_data))';
cam2_feature1=[cam2_feature1;result1(1:index,:)];
gallery_feature=[];
%%
name_cam2={};
for m=1:param.train_person_num
    test_label_index=find(label_test_cam2==(m+param.train_person_num));
    a=sum(cam2_feature1(test_label_index,:))/size(test_label_index,1);
    gallery_feature=[gallery_feature;a];
    name_cam2=[name_cam2,train_image_name_cam2{test_label_index(1)}];
end
% cal cmc
prob_norm=bsxfun(@rdivide,prob_feature,sum(abs(prob_feature).^2,2).^(1/2));
gallery_norm=bsxfun(@rdivide,gallery_feature,sum(abs(gallery_feature).^2,2).^(1/2));
% [~,it]=sort(prob_norm*gallery_norm',2,'descend');
score_matrix=prob_norm*gallery_norm';
rank1_hit=0;
rank5_hit=0;
rank10_hit=0;
rank20_hit=0;
problen=size(prob_feature,1);
for m=1:problen
    [~,location]=sort(score_matrix(m,:),2,'descend');
    if find(location(1)==m)
        rank1_hit=rank1_hit+1;
    end
    if find(location(1:5)==m)
        rank5_hit=rank5_hit+1;
    end
    if find(location(1:10)==m)
        rank10_hit=rank10_hit+1;
    end
    if find(location(1:20)==m)
        rank20_hit=rank20_hit+1;
    end
end
rank_acc=[rank1_hit/problen,rank5_hit/problen,rank10_hit/problen,rank20_hit/problen];
fin=fopen(param.result_save_file,'a');
fprintf(fin,'split_index:%d,iter:%d, rank1:%f,rank5:%f,rank10:%f,rank20:%f\n',split_index,iter,rank_acc(1),rank_acc(2),rank_acc(3),rank_acc(4));
fprintf('split_index:%d,iter:%d, rank1:%f,rank5:%f,rank10:%f,rank20:%f\n',split_index,iter,rank_acc(1),rank_acc(2),rank_acc(3),rank_acc(4));
fclose(fin);


function res = killer(n,p)

persistent plist rd
plist = [plist p];

switch n
    case 1
        res = 'cooperate';
        plist = p;
        rd = 0;
    case 20
        res = 'defect';
    otherwise
        if any( (plist(n-1:n)==1) + (plist(n-1:n)==5) ) && rd<5
            res = 'defect';
            rd = rd+1;
        else
            res = 'cooperate';
            if ~rd<5, rd=0; end
        end
end


function C = mtimes(A,B)
%MTIMES Multiplies two tenmat objects.
%
%  C = MTIMES(A,B) computes the product of A and B. The result is a
%  TENMAT object and can be transformed into a tensor.
%
%  C = MTIMES(A,B) is called for the syntax 'A * B' when A or B is a
%  TENMAT object.
%
%   See also TENMAT.
%
%MATLAB Tensor Toolbox.
%Copyright 2015, Sandia Corporation.

% This is the MATLAB Tensor Toolbox by T. Kolda, B. Bader, and others.
% http://www.sandia.gov/~tgkolda/TensorToolbox.
% Copyright (2015) Sandia Corporation. Under the terms of Contract
% DE-AC04-94AL85000, there is a non-exclusive license for use of this
% work by or on behalf of the U.S. Government. Export of this data may
% require a license from the United States Government.
% The full license terms can be found in the file LICENSE.txt

% Handle scalar input
if ~isa(B,'tenmat') && numel(B) == 1
    C = A;
    C.data = C.data * B;
    return;
end
if ~isa(A,'tenmat') && numel(A) == 1
    C = B;
    C.data = C.data * A;
    return;
end

% Handle matrix input
if ~isa(A,'tenmat')
    A = tenmat(A,1);
end

if ~isa(B,'tenmat')
    B = tenmat(B,1);
end

% Error check
if size(A,2) ~= size(B,1)
    error(['Size mismatch: Number of columns in A is not equal to' ...
	   ' the number of rows in B']);
end

tsiz = [A.tsize(A.rindices) B.tsize(B.cindices)];

if ~isempty(tsiz)
    C = tenmat;
    C.tsize = tsiz;
    C.rindices = 1:length(A.rindices);
    C.cindices = (1:length(B.cindices)) + length(A.rindices);
    C.data = A.data * B.data;
else
    C = A.data * B.data;
end


% Copyright (C) 1993-2017, by Peter I. Corke
%
% This file is part of The Machine Vision Toolbox for Matlab (MVTB).
%
% MVTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% MVTB is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with MVTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com
function showcam(c, T, P)

    if nargin < 2
        T = c.T;
    end

    T = SE3(T);

    clf
    axis([-3, 3, -3, 3, -3 3])
    daspect([1 1 1])
    hold on
    grid
    [x,y,z] = sphere(20);

    hg = hgtransform;
    surf(x,y,z, 'FaceColor', [0.8 0.8 1], 'EdgeColor', 0.5*[0.8 0.8 1], ...
        'EdgeLighting', 'gouraud', 'Parent', hg)
    light
    lighting gouraud
    set(hg, 'Matrix', T.T);

    trplot(T, 'length', 1.6, 'arrow')

    axis
    limits = reshape(axis, 2, []);
    maxdim = max(diff(limits));

    o = T.t;

    if nargin > 2
        for i=1:numcols(P)
            plot3([o(1) P(1,i)], [o(2) P(2,i)], [o(3) P(3,i)], 'r');
            plot_sphere(P(:,i), maxdim*0.02, 'r');
        end
    end
    hold off
    xlabel('x'); ylabel('y'); zlabel('z');


classdef Camera_Rotatory < Camera_Abstract

    properties (Access = protected)
        currentView = [90 30]
    end

    properties (Access = private)
        period = 200
        speed
    end

    methods (Access = public)

        function obj = Camera_Rotatory(axes)
            obj@Camera_Abstract(axes);
        end

        function updateView(obj)
            obj.applyAngularMotion();
            obj.checkView();
            obj.refresh();
        end

    end

    methods (Access = private)

        function applyAngularMotion(obj)
            obj.currentView  = obj.currentView + [obj.speed 0];
        end

        function checkView(obj)
            az = obj.currentView(1);
            el = obj.currentView(2);

            az = obj.keepInRange(az,0,360);
            el = obj.keepInRange(el,-90,90);

            obj.currentView(1) = az;
            obj.currentView(2) = el;

        end

    end

    methods (Access = private, Static)

        function x = keepInRange(x,xMin,xMax)
            X = abs(xMin-xMax);
            while x > xMax
                x = x - X;
            end

            while x < xMin
                x = x + X;
            end
        end

    end

    methods

        function w = get.speed(obj)
            w = 360/obj.period;
        end

    end

end


function [H, xx, xw]= plot_barWithAntenna(y, y_sem, varargin)
%PLOT_BARWITHANTENNA - Bar plot with antennas, e.g., to show the SEM.
%
%Synopsis:
% [H, X]= plot_barWithAntenna(Y, Y_SEM, <OPT>)
%
%Input:
% Y:     Heights of the bars, DOUBLE [MxN]
% Y_SEM: Length of the antenna, DOUBLE [MxN]
% OPT:   Structure or property/value list of optional properties:
%  .Clf          - Clear figure before plotting, BOOL (default 1)
%  .ColOrder     - Colormap of N colors, default blue to white, DOUBLE [Nx3]
%                  (generated by cmap_bluewhite(N, 'min_val',0.15)
%  .AntennaType  - Specifies how anntennas are drawn, options are 'o','oo',
%                  'T','I', CHAR (default 'o')
%  .AntennaColor - Color of antennas, with 'auto' meaning same colors as
%                  bars, DOUBLE [Nx3] or 'auto' (default)
%  .AntennaSpec  - Line specifications for antennas
%
%Output:
% H: handles to graphic objects
% X: horizonal position of the middle of the bars
%
%Description:
% This function makes a bar plot in which a (symmetric) interval around
% each value is visualized by antennas. The typically application is
% that the values itself are the means of some observed variable and
% the intervals around each mean are given as the standard deviation
% (STD) or the standard error of the mean (SEM).
%
%Examples:
% Y= diag([5 6 2])*rand(3,6)+1;
% Y_SEM= rand(3,6)+0.2;
% H= bar_with_antenna(Y, Y_SEM);
% set(gca, 'XTickLabel','Group 1|Group 2|Group 3');
% legend(H.bar, str_cprintf('bar %d',1:6));
%
% [H, xx]= bar_with_antenna(Y(1,:), Y_SEM(1,:), 'ColOrder',cmap_rainbow(6), 'AntennaColor',[0 0 0]);
% set(gca, 'XTick',xx, 'XTickLabel',1:6);
% H= bar_with_antenna(Y, Y_SEM, 'AntennaType','oo');
%
% H= bar_with_antenna(Y(1,:), Y_SEM(1,:), 'AntennaType','I', 'AntennaColor','auto', 'DrawMarker',1);
% delete(H.bar);

% Benjamin Blankertz
% Modified Laura Acqualagna 04.15: Adjusted for handling new graphcs of Matlab versions later than 8.4

[nGroups, nCol]= size(y);
cmap_default= cmap_bluewhite(nCol, 'MinVal',0.15);

props = {'Clf',             1,              '!BOOL';
         'ColOrder',        cmap_default,   '!DOUBLE[- 3]';
         'AntennaType',     'o',            '!CHAR(o oo T TT I none)';
         'AntennaColor',    'auto',         '!CHAR(auto)|DOUBLE[- 3]';
         'AntennaSpec',     {},             'CELL';
         'AntennaWidth',    .5,             'DOUBLE[1]';
         'DrawMarker',      0,              '!BOOL';
         'MarkerSpec',      {},             'CELL';
         };

if nargin==0,
  H= props; return
end

misc_checkType(y,'!DOUBLE[- -]');
misc_checkType(y_sem,'!DOUBLE[- -]');
opt= opt_proplistToStruct(varargin{:});
[opt, isdefault]= opt_setDefaults(opt, props);
opt_checkProplist(opt, props);

if nargin<2 || isempty(y_sem),
  opt.AntennaType= 'none';
end

if ismember(opt.AntennaType, {'oo','TT','I'},'legacy'),
  [opt, isdefault]= opt_overrideIfDefault(opt, isdefault, ...
                                          'AntennaColor',0.5*[1 1 1]);
end
if isequal(opt.AntennaColor, 'auto'),
  opt.AntennaColor= opt.ColOrder;
end

if opt.Clf,
  clf;
end

if nGroups==1,  %% work-around for case nGroups=1
  H.bar= bar([y; y]);
else
  H.bar= bar(y);
end

hold on;
for c= 1:nCol,
 if verLessThan('matlab', '8.4') % old Matlab versions before 2014b
 xdata= get(get(H.bar(c),'Children'),'XData');
 xw= xdata(3,1)-xdata(1,1);
 xtmp= mean(xdata);
 else
 set(H.bar(c), 'FaceColor',opt.ColOrder(c,:));
 xtmp =  H.bar(c).XData + [H.bar(c).XOffset];
 xw=H.bar(c).BarWidth/(length(H.bar)*2-1); % BarWidth refers to the overall width of the group.
 %To get width of single bar, divide BarWidth for number of bars + number of spaces between bars.
 end
 if nGroups==1,  %% work-around for case nGroups=1
   xtmp= xtmp(1);
 end
 xx(c,:)= xtmp;
 xtw= xw*opt.AntennaWidth/2;
 switch(opt.AntennaType),
  case 'o',
   h1= line([xx(c,:); xx(c,:)], ...
            [y(:,c), y(:,c)+y_sem(:,c)]');
   h2= line([xx(c,:); xx(c,:)], ...
            [y(:,c)+y_sem(:,c), y(:,c)+y_sem(:,c)]');
   H.antenna(:,c)= [h1; h2];
  case 'T',
   h1= line([xx(c,:); xx(c,:)], ...
            [y(:,c), y(:,c)+y_sem(:,c)]');
   h2= line([xx(c,:)-xtw; xx(c,:)+xtw], ...
            [y(:,c)+y_sem(:,c), y(:,c)+y_sem(:,c)]');
   H.antenna(:,c)= [h1; h2];
  case 'oo',
   H.antenna(:,c)= line([xx(c,:); xx(c,:)], ...
                        [y(:,c)-y_sem(:,c), y(:,c)+y_sem(:,c)]');
  case {'I','TT'},
   h1= line([xx(c,:); xx(c,:)], ...
            [y(:,c)-y_sem(:,c), y(:,c)+y_sem(:,c)]');
   h2= line([xx(c,:)-xtw; xx(c,:)+xtw], ...
            [y(:,c)+y_sem(:,c), y(:,c)+y_sem(:,c)]');
   h3= line([xx(c,:)-xtw; xx(c,:)+xtw], ...
            [y(:,c)-y_sem(:,c), y(:,c)-y_sem(:,c)]');
   H.antenna(:,c)= [h1; h2; h3];
  case 'none',
   H.antenna(:,c)= NaN;
 end
 if verLessThan('matlab', '8.4')
     if ~any(isnan(H.antenna(:,c))),
       ci= 1+mod(c-1, size(opt.AntennaColor,1));
       set(H.antenna(:,c), 'Color',opt.AntennaColor(ci,:));
     end
 else %in the new version the previous check cannot be done in one line, if condition has been removed
       ci= 1+mod(c-1, size(opt.AntennaColor,1));
       set(H.antenna(:,c), 'Color',opt.AntennaColor(ci,:));
 end
end

switch(opt.AntennaType),
 case 'o',
  ii= nGroups+[1:nGroups];
  set(H.antenna(ii,:), 'Marker','o', 'MarkerSize',8, 'MarkerFaceColor','w');
 case 'oo',
  set(H.antenna, 'Marker','o', 'MarkerSize',8, 'MarkerFaceColor','w');
end
 if verLessThan('matlab', '8.4')
     if ~any(isnan(H.antenna(:,c))),
      set(H.antenna, 'LineWidth',4, opt.AntennaSpec{:});
     end
 else
     set(H.antenna, 'LineWidth',4, opt.AntennaSpec{:});
 end
set(gca, 'YGrid','on', 'TickLength',[0 0]);

if opt.DrawMarker,
  for c= 1:nCol,
    H.marker(:,c)= plot(xx(c,:)', y(:,c), 'd');
    ci= 1+mod(c-1, size(opt.AntennaColor,1));
    set(H.marker(:,c), 'Color',opt.AntennaColor(ci,:));
  end
  set(H.marker, 'MarkerSize',12, 'LineWidth',4, 'MarkerFaceColor','w', ...
                opt.AntennaSpec{:}, opt.MarkerSpec{:});
end

% Adjust XLim such that there is one bar-width space at the borders,
set(gca, 'XLim',reshape(xx([1 end]),[1 2])+[-1 1]*xw*1.5);
hold off;


function Op=operatornew(otype,varargin)
%OPERATORNEW  Construct a new operator
%   Usage: F=operatornew(otype,...);
%
%   `Op=operatornew(otype,...)` constructs a new operator object *Op* of type
%   *otype*. Arguments following *otype* are specific to the type of operator
%   chosen.
%
%   Frame multipliers
%   -----------------
%
%   `operatornew('framemul',Fa,Fs,s)` constructs a frame multiplier with
%   analysis frame *Fa*, synthesis frame *Fs* and symbol *s*. See the help on
%   |framemul|.
%
%   Spreading operators
%   -------------------
%
%   `operatornew('spread',s)` constructs a spreading operator with symbol
%   *s*. See the help on |spreadop|.
%
%   See also: operator, ioperator

if nargin<2
  error('%s: Too few input parameters.',upper(mfilename));
end;

if ~ischar(otype)
  error(['%s: First agument must be a string denoting the type of ' ...
         'frame.'],upper(mfilename));
end;

otype=lower(otype);

switch(otype)
  case 'framemul'
    Op.Fa=varargin{1};
    Op.Fs=varargin{2};
    Op.s =varargin{3};
    Op.L =framelengthcoef(Op.Fs,size(Op.s,1));
  case 'spread'
    Op.s =varargin{1};
    Op.L =length(Op.s);
  otherwise
    error('%s: Unknows operator type: %s',upper(mfilename),otype);
end;

Op.type=otype;


function [p ener a enerFF aFF max_doseV doseV_wt] = optSourceModel_depth6cm_blurring(planC, energy, numBin, extraBin, depth, dose, ...
    depth1, x1, profile1,  depth2, x2, profile2, depth3, x3, profile3, depth4, x4, profile4, LB, UB);
% JC Dec 09,2005
% Optimize photon spectrum, using (Fatigue-life)*Fermi distribution
% Usage:
% energy = energy of the photon beam
% numBin = number of bins to divide the energy range [0 energy]
% depth is a row vector as the depth
% dose is the corresponding dose at each depth
%
% 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/>.

% Underline assumptions:
% The calculated dose sets are the same size as the uniformizedCTscan.
% 1. Interpolation the calculated dose on to the respectively dose profiles
% coordinates may cause problem: Since the individual dose profile
% measurements do not necessarily have the same coordinates/# of points,
%

% 2. The input depth/x coordinates are in cm
%    The depth dose (PDD) is normalized. dmax = 1
%    The lateral dose profiles at various depth are also normalized. Each
%       has a maximal value as 1. It will be scaled according to PDD.

% 3. The phantom is at least 25cm in the depth direction. Otherwise, the
% interpolation of PDD will have out-flow, meaning the non-meaningful
% values, N/A. An error will be thrown out.
%   Also, the input PDD's depth may not start from zero, this may generate
%   N/A if the yVals starts from zero. So chop yVals according to PDD's
%   depth.

% 4. All input measured data are in a nx1 vector, i.e. a column vector

% 5 Add more input parameters: adjustable to different machines
% LB=[0.6  -0.1 1.2   100  1  0.1  0.005    0.005];
% UB=[1.5  0.1   10  1000  4   0.25  0.05  0.05];

% Input parameters descriptions:
% LB, UB. Upper and lower bound for the parameters.
% p, the optimazied parameters.
% p(1:4) The parameters for "Fagitue-Fermi" function, to model the primary photon
% spectrum.
% p(5) The parameter to "shrink" the primary photon spectrum
% to get the spectrum for the extra-focal (FF) components.
% p(6) The parameter to "scale" the extra-focal (FF) components,
% to determine the relative fluence contribution of the extra-focal (FF)
% to the primary photon.
% p(7) used to determine "the slope of the horn", not used anymor i.e. It is how many "pixels"/"grid".
% The dimension of the ICsigma in (cm) should be p(9)*e.
% p(8) the electron contamination (fluence relative to the primary photon.
% p(9) the "ICsigma", to convolve the MC dose, to model the spearing of the dose by IC chamber.
% If the resolution of the dose calc. grid changes, i.e.
% The dimension of the sigma is p(9)*dx, where "dx" is the grid spacing for
% dose calc.

% 6. Add another parameter for the optimization, sigma. A gaussian filter
% to blur the penumbra.

% Sept 21, 2006
% Add electron contamination components.
% For PDD, includes depth < 5cm

% Nov 27, 2006
% correct
% doseP2_arrayFF(:,i) = dose3D(find(yVals == yDepth3),[xIndexStart:xIndexEnd],int16(s));
% doseP2_arrayFF(:,i) = dose3D(find(yVals == yDepth2),[xIndexStart:xIndexEnd],int16(s));

% Get the isocenter coordinate
bf = planC{7}.FractionGroupSequence.Item_1.ReferencedBeamSequence.Item_1;
bs = planC{7}.BeamSequence.Item_1;
iC = bs.ControlPointSequence.Item_1.IsocenterPosition;

position = {planC{7}.PatientSetupSequence.(['Item_' num2str(1)]).PatientPosition};

if strcmpi(position, 'HFP')
    isocenter.x = iC(1)/10;
    isocenter.y = iC(2)/10;
    isocenter.z = -iC(3)/10;
else
    isocenter.x = iC(1)/10;
    isocenter.y = -iC(2)/10;
    isocenter.z = -iC(3)/10;
end
% So iC is the isocenter. Need to find indices from the (x, y, z) values.

[xVals, yVals, zVals] = getUniformScanXYZVals(planC{3});
% Need to confirm that iC(2), i.e. the y value is right on the skin
% surface. Thus, the depth for dose along the center ray can be determined.
j = find(strcmpi({planC{4}.structureName}, 'Skin'));

if isempty(j)
    j = find(strcmpi({planC{4}.structureName}, 'Body'));
end

if isempty(j)
    error('Skin structure must be defined to input to DPM.');
else
    j = j(1);
end

skinMask=getUniformStr(j,planC);

%confirm that the isocenter.y is right on the skin surface
bbox=boundingBox(skinMask)
%[r,c,s] = xyztom(isocenter.x,isocenter.y,isocenter.z, planC)
[r,c,s] = xyztom(isocenter.x,isocenter.y,isocenter.z, 1, planC)

%Get the indices of where yVals==depth(end)/10 ; Failed???
%[r,c,s] = xyztom(isocenter.x,yVals(find(yVals==isocenter.y-min(isocenter.y-yVals))),isocenter.z, planC)

% Get the objective dose from input(Golden Beam Data), not from planC.

% get the yVals for different depth, to pick out the appropriate lateral dose profiles in the calcualted dose sets.
dy = yVals(2)-yVals(1);  % dy is < 0, because of y increases as row number decreases
yDepth0 = yVals(bbox(1));
yDepth1 = yVals(bbox(1)+int16(-depth1/dy));
yDepth2 = yVals(bbox(1)+int16(-depth2/dy));
yDepth3 = yVals(bbox(1)+int16(-depth3/dy));
yDepth4 = yVals(bbox(1)+int16(-depth4/dy));
yDepth25cm = yVals(bbox(1)+int16(-25/dy));

%depthTPS can't start from 0, which will cause intepolated data N/A.
depthTPS = [ceil(min(depth)/(-dy))*(-dy) : -dy: yVals(bbox(1))-yDepth25cm];
PDD = interp1(depth, dose, depthTPS);
doseV_obj = PDD';
doseV_array = zeros(length(PDD),numBin+extraBin);
max_doseV = zeros(numBin+extraBin,1);

% GET the start and end indices objective for dose profile at depth 5cm
xStart = max(min([x1 x2 x3 x4]));
xEnd = min(max([x1 x2 x3 x4]));
% use margin 1 to make sure the results xTPS is within the measured region.
xIndexStart = find(abs(xStart - xVals) == min(abs(xStart - xVals))) + 1;
xIndexEnd = find(abs(xEnd - xVals) == min(abs(xEnd - xVals))) - 1 ;

% Should correct xTPS for isocenter.x? Does, then xTPS maybe outside of the
% valid region.
 xTPS = [xVals(xIndexStart)-isocenter.x : (xVals(2)-xVals(1)): xVals(xIndexEnd)-isocenter.x];
% Currently, do not correct.
% xTPS = [xVals(xIndexStart): (xVals(2)-xVals(1)): xVals(xIndexEnd)];

doseProfile1 = interp1(x1, profile1, xTPS);
% Since the input measured data is the asdfScale it to be consistent with PDD
% Needed for Golden Beam data. Not for Murty's measurement.
doseProfile1_obj = doseProfile1' * PDD(find(abs(depth1-depthTPS) == min(abs(depth1-depthTPS))));
% Creat array to hold the dose profiles for the different energy bins.
doseP1_array = zeros(length(doseProfile1_obj), numBin+extraBin);

doseProfile2 = interp1(x2, profile2, xTPS);
% Scale it to be consistent with PDD
doseProfile2_obj = doseProfile2' * PDD(find(abs(depth2-depthTPS) == min(abs(depth2-depthTPS))));
doseP2_array = zeros(length(doseProfile2_obj), numBin+extraBin);

% GET the objective for dose profile at depth 10cm
doseProfile3 = interp1(x3, profile3, xTPS);
% Scale it to be consistent with PDD
doseProfile3_obj = doseProfile3' * PDD(find(abs(depth3-depthTPS) == min(abs(depth3-depthTPS))));
doseP3_array = zeros(length(doseProfile3_obj), numBin+extraBin);

% GET the objective for dose profile at depth 20cm
doseProfile4 = interp1(x4, profile4, xTPS);
% Scale it to be consistent with PDD
doseProfile4_obj = doseProfile4' * PDD(find(abs(depth4-depthTPS) == min(abs(depth4-depthTPS))));
doseP4_array = zeros(length(doseProfile4_obj), numBin+extraBin);

figure; plot(depthTPS, PDD);
% There's shift of doseProfile2_obj, x as half voxel size. 0.1875/2 =
% 0.094cm
hold on; plot(xTPS, doseProfile1, 'c', xTPS, doseProfile2, 'b', xTPS, doseProfile3, 'r', xTPS, doseProfile4, 'g');
legend('PDD', num2str(depth1), num2str(depth2), num2str(depth3), num2str(depth4));

% Read in the dose from the DPM calculation.
for i = 1:(numBin+extraBin),
    filename = ['dose3D_', num2str(i*energy/numBin),'MV.mat'];
    load (filename, 'dose3D');
    doseV_array(:,i) = dose3D([(bbox(1)+ceil(min(depth)/(-dy))):find(yVals == yDepth25cm)],int16(c),int16(s));
    doseP1_array(:,i) = dose3D(find(yVals == yDepth1),[xIndexStart:xIndexEnd],int16(s));
    doseP2_array(:,i) = dose3D(find(yVals == yDepth2),[xIndexStart:xIndexEnd],int16(s));
    doseP3_array(:,i) = dose3D(find(yVals == yDepth3),(xIndexStart:xIndexEnd),int16(s));
    doseP4_array(:,i) = dose3D(find(yVals == yDepth4),(xIndexStart:xIndexEnd),int16(s));

  end

% currentDir = pwd;
% cd ./FlatFilter
%NOW, for the flattenning filter part, need to do the exactly same thing,
%i.e. get PDD and doseP5cm, doseP10cm, doseP20cm....
numBinFF = ceil((numBin+extraBin)/2); %15
% JC. Use all energy bins.
numBinFF = numBin+extraBin; %15
doseV_arrayFF = zeros(length(PDD),numBinFF);
doseP1_arrayFF = zeros(length(doseProfile1), numBinFF);
doseP2_arrayFF = zeros(length(doseProfile2), numBinFF);
doseP3_arrayFF = zeros(length(doseProfile3), numBinFF);
doseP4_arrayFF = zeros(length(doseProfile4), numBinFF);
% Read in the dose from the DPM calculation, for the secondary source, i.e. Flattening Filter,FF.
for i = 1 : numBinFF,
    filename = ['dose3D_FF_', num2str((double(i*energy)/double(numBin))),'MV.mat'];
    load (filename, 'dose3D');
    doseV_arrayFF(:,i) = dose3D([(bbox(1)+ceil(min(depth)/(-dy))):find(yVals == yDepth25cm)],int16(c),int16(s));
    doseP1_arrayFF(:,i) = dose3D(find(yVals == yDepth1),[xIndexStart:xIndexEnd],int16(s));
    doseP2_arrayFF(:,i) = dose3D(find(yVals == yDepth2),[xIndexStart:xIndexEnd],int16(s));
    doseP3_arrayFF(:,i) = dose3D(find(yVals == yDepth3),(xIndexStart:xIndexEnd),int16(s));
    doseP4_arrayFF(:,i) = dose3D(find(yVals == yDepth4),(xIndexStart:xIndexEnd),int16(s));
end
% cd(currentDir);

% Read the dose of the electron contamination.
load dose3D_elec.mat dose3D
doseV_e = dose3D([(bbox(1)+ceil(min(depth)/(-dy))):find(yVals == yDepth25cm)],int16(c),int16(s));
% Need doseP5cm_e etc. is a collumn vector.
doseP1_e = dose3D(find(yVals == yDepth1),[xIndexStart:xIndexEnd],int16(s))';
doseP2_e = dose3D(find(yVals == yDepth2),[xIndexStart:xIndexEnd],int16(s))';
doseP3_e = dose3D(find(yVals == yDepth3),(xIndexStart:xIndexEnd),int16(s))';
doseP4_e = dose3D(find(yVals == yDepth4),(xIndexStart:xIndexEnd),int16(s))';

%%Need to pick the indices for dose profile at 5cm, 10cm, 20cm. And shift
%%the middle as x_coordinate = 0, as in the golden beam data.
%% Also need to scale the maximum dose at this depth according to the PDD
%% at this depth, because the profile dose is relative (max = 100).
%% Now only account the dose profile at depth 5cm.

%options = optimset('DISPLAY', 'notify', 'TolX', 1.e-12);
%%%% Using Ant Colony Opt. (api.m)
%%% O.K. parameters. JC

% Parameters: p(1) till p(4), the four parameters to determine the primary
% photon spectrum, sum(a) is the weight.
% p(5) "shrink" for the Flattening filter.
% p(6) is the weight of FF photon, aFF = aFF * p(6)
% p(7) is the Horn effect weight, respective to sum(a)
% p(8) is the electron contamination weight, respective to sum(a)

FUN='PDD_Profile_res';
% "working" LB, UB settings
% Add one more bounds for the penumbra
%LB=[0.6  -0.1 1.2   100  2  0.1  0.01    0.005 0.01];
%UB=[1.5  0.1   10  1000  4   0.2  0.05  0.04 5];

% expand the LB and UB by the suggesstions from JOD. On Oct 09, 2006
% LB=[0.6  -0.1 1.2   100  1  0.1  0.005    0.001];
% UB=[1.5  0.1   10  1000  4   0.25  0.05  0.05];

NumAnts=25;Nmoves=20;LocalMoves=30;
NONLNCON=[];rpmax=[]; RES=1e-8;
p=api(FUN,LB,UB,NumAnts,Nmoves,LocalMoves,NONLNCON,rpmax,RES, ...
    doseV_obj, doseV_array, doseV_arrayFF, doseV_e, ...
    doseProfile1_obj, doseP1_array, doseP1_arrayFF, doseP1_e, ...
    doseProfile2_obj, doseP2_array, doseP2_arrayFF, doseP2_e, ...
    doseProfile3_obj, doseP3_array, doseP3_arrayFF, doseP3_e, ...
    doseProfile4_obj, doseP4_array, doseP4_arrayFF, doseP4_e, ...
    energy, numBin, extraBin, numBinFF)

% Output results
ener = energy/numBin: energy/numBin:energy*(1+extraBin/numBin);
a = Fatigue(p(1:4), ener);
a(find(isnan(a))) = 0;

cutoff = 0.85;
Ef = energy*cutoff;
kt = energy*0.15;  % change kt
f = 1./(1+exp((ener-Ef)/kt));
a = a.*f;

doseV_wt = (doseV_array)  * real(a)';
doseProfile1_wt = (doseP1_array) * real(a)';
doseProfile2_wt = (doseP2_array) * real(a)';
doseProfile3_wt = (doseP3_array)  * real(a)';
doseProfile4_wt = (doseP4_array) * real(a)';

% Get the weights/spectrum for the flattening filter
enerFF = energy/numBin : energy/numBin : numBinFF*energy/numBin;
aFF = Fatigue(p(1:4), p(5)*enerFF);
aFF(find(isnan(aFF))) = 0;

% Get modified Flattening filter spectrum/weights
f = 1./(1+exp((p(5)*enerFF-Ef)/kt));
aFF = aFF.* f;
aFF = aFF * (sum(a)/sum(aFF)*p(6)) ;  % scale FF weight respect to sum(a)

doseV_wtFF = doseV_arrayFF * real(aFF)';
doseProfile1_wtFF = doseP1_arrayFF * real(aFF)';
doseProfile2_wtFF = doseP2_arrayFF * real(aFF)';
doseProfile3_wtFF = doseP3_arrayFF * real(aFF)';
doseProfile4_wtFF = doseP4_arrayFF * real(aFF)';

filterSize = 7;
filterWindow = [-3 -2 -1 0 1 2 3];
G1 = gauss(filterWindow, p(9));  %p(9) is sigma
G1 = G1/sum(G1);   % normalize, to make sum(G1)==1;

doseV_DPM = doseV_wt + doseV_wtFF + p(8) * sum(a)* doseV_e;
doseProfile1_DPM = doseProfile1_wt + doseProfile1_wtFF + p(8) * sum(a)* doseP1_e;
doseProfile1_DPM = conv(G1, doseProfile1_DPM);
doseProfile2_DPM = doseProfile2_wt + doseProfile2_wtFF + p(8) * sum(a)* doseP2_e;
doseProfile2_DPM = conv(G1, doseProfile2_DPM);
doseProfile3_DPM = doseProfile3_wt + doseProfile3_wtFF + p(8) * sum(a)* doseP3_e;
doseProfile3_DPM = conv(G1, doseProfile3_DPM);
doseProfile4_DPM = doseProfile4_wt + doseProfile4_wtFF + p(8) * sum(a)* doseP4_e;
doseProfile4_DPM = conv(G1, doseProfile4_DPM);

figure;
subplot(2,1,1); plot(depth,dose, '.');
hold on;
plot(depthTPS,doseV_DPM, 'r');
legend('measured', 'DPM wt');
axis([0 25 0 1.1])
subplot(2,1,2); plot([0 ener], [0 a], '+-b')
hold on;  plot([0 enerFF], [0 aFF], '+-r')

% Note: There's shift in the measured dose. Now fix the display
figure;
plot(xTPS, doseProfile1_obj, 'b', xTPS, doseProfile1_DPM(4:end-3), '-.r')
hold on; plot(xTPS, doseProfile3_obj, 'c', xTPS, doseProfile3_DPM(4:end-3), '-.m')
legend('measured', ['DPM ', num2str(depth1)], 'measured', ['DPM ', num2str(depth3)]);

figure; plot(xTPS, doseProfile2_obj, 'b', xTPS, doseProfile2_DPM(4:end-3), '-.r')
hold on; plot(xTPS, doseProfile4_obj, 'c', xTPS, doseProfile4_DPM(4:end-3), '-.m');
legend('measured', ['DPM ', num2str(depth2)], 'measured', ['DPM ', num2str(depth4)]);

filename = 'modelParameters';
save(filename, 'p', 'ener', 'a', 'enerFF', 'aFF', 'max_doseV', 'doseV_wt');
disp('ok');


function [gmn, gm, dgm] = spm_eeg_inv_vbecd_getLF(s, sens, vol, step)
% Estimation of the leadfield matrix and its spatial derivative if required
% for a set of dipoles used in the VB-ECD solution
%% scales non-eeg data up by a fixed factor (1e8) for compatibility of
%% units
%
% FORMAT [gmn, gm, dgm] = spm_eeg_inv_vbecd_getLF(s, sens, vol, step)
%
% s      - location vector
% sens   - sensor locations (MNI [mm])
% vol    - volume structure needed by fieldtrip
% step   - stepsize to compute numerical derivatives
%
% gmn    - leadfields (three vectors for each dipole)
% gm     - vectorized leadfields
% dgm    - vectorized partials wrt locations
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Christophe Phillips & Stefan Kiebel
% $Id: spm_eeg_inv_vbecd_getLF.m 3833 2010-04-22 14:49:48Z vladimir $

%%% now does rank reduction (to 2) for non eeg data

MEGRANK=2;
MEGSCALE=1e10;  %% should be the same as in spm_eeg_inv_vbecd.m

if nargin<4
     step = 0;
end

gm = [];
for i = 1:length(s)/3

    % mean correction of LF, only for EEG data.
    if ft_senstype(sens, 'eeg')
       [tmp] = ft_compute_leadfield(s(1+(i-1)*3:i*3)', sens, vol);
        tmp = tmp - repmat(mean(tmp), size(tmp,1), 1);
    else %% reduce rank of leadfield for MEG- assume one direction (radial) is silent
       [tmp] = ft_compute_leadfield(s(1+(i-1)*3:i*3)', sens, vol,'reducerank',MEGRANK);
        tmp=tmp.*MEGSCALE;
    end
    gm = [gm tmp];
end

gmn = gm; % leadfield

[Nc, Np] = size(gmn);
if nargout >= 2
    gm = gmn(:); % vectorized leadfield
end

if all(step > 0) && nargout == 3,
%     if isempty(step),
%         step=randn(size(s));
%     end; % if isempty
    dgm = [];
    for j = 1:length(s)
        ds = s;
        ds(j) = s(j) + step(j);
        dtmp = [];
        for i = 1:length(s)/3
            if ceil(j/3) == i

                % mean correction of LF, only for EEG data.
                if ft_senstype(sens, 'eeg')
                    [tmp] = ft_compute_leadfield(ds(1+(i-1)*3:i*3)', sens, vol);
                    tmp = tmp - repmat(mean(tmp), size(tmp,1), 1);
                else  % MEG
                   [tmp] = ft_compute_leadfield(ds(1+(i-1)*3:i*3)', sens, vol,'reducerank',MEGRANK);
                    tmp=tmp.*MEGSCALE;
                end
                dtmp = [dtmp tmp];
            else
                dtmp = [dtmp gmn(:, 1+(i-1)*3:i*3)];
            end
        end
        dtmp = dtmp(:);
        dgm = [dgm (-gm + dtmp)./step(j)];
    end

    % correct order
    ind = reshape(1:Np^2 , Np, Np)';

    dgm = reshape(dgm, size(gmn, 1), Np^2);
    dgm = dgm(:, ind(:));
    dgm = reshape(dgm, Np*Nc, Np);
end


%Saving data into ASPAR type 5 format

report_this_filefun(mfilename('fullpath'));
ZG = ZmapGlobal.Data;
if ~exist('tlen', 'var'); tlen = 30 ; end
str = [];
newmatfile = 't1.sum';
newpath = [hodi '/aspar/'];

do = [ ' cd ' newpath ];
eval(do)

% lets addev the mainshock as the fisrt and largest event...

l = ZG.newt2.Date > ZG.maepi.Date(1) & ZG.newt2.Date < mati + days(tlen);
newt3 =  ZG.newt2(l,1:9);
newt3 = [ZG.maepi(1:1:9) ; newt3 ];

lam = (newt3(:,2)-floor(newt3(:,2)))*100*6/10;
lom = (newt3(:,1)-floor(newt3(:,1)))*100*6/10;

s = [floor(newt3(:,3:5))  newt3(:,8:9) floor(newt3(:,2)) lam  floor(abs((newt3(:,1))))  lom  newt3(:,7) newt3(:,6)];
fid = fopen([newpath newmatfile],'w') ;

fprintf(fid,'%7.3f  %7.3f %7f3\n',[min(newt3(:,6)) tmin1 tlen]);

fprintf(fid,'%5.0f %5.0f %5.0f %5.0f %5.0f %5.0f %7.3f %5.0f %7.3f %7.3f %7.3f\n',s');
fclose(fid);
clear s
return