function cnn_imagenet(varargin)
%CNN_IMAGENET   Demonstrates training a CNN on ImageNet
%  This demo demonstrates training the AlexNet, VGG-F, VGG-S, VGG-M,
%  VGG-VD-16, and VGG-VD-19 architectures on ImageNet data.

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

opts.dataDir = fullfile('data','ILSVRC2012') ;
opts.modelType = 'alexnet' ;
opts.networkType = 'simplenn' ;
opts.batchNormalization = true ;
opts.weightInitMethod = 'gaussian' ;
[opts, varargin] = vl_argparse(opts, varargin) ;

sfx = opts.modelType ;
if opts.batchNormalization, sfx = [sfx '-bnorm'] ; end
sfx = [sfx '-' opts.networkType] ;
opts.expDir = fullfile('data', ['imagenet12-' sfx]) ;
[opts, varargin] = vl_argparse(opts, varargin) ;

opts.numFetchThreads = 12 ;
opts.lite = false ;
opts.imdbPath = fullfile(opts.expDir, 'imdb.mat');
opts.train = struct([]) ;
[opts, varargin] = vl_argparse(opts, varargin) ;

% -------------------------------------------------------------------------
%                                                             Prepare model
% -------------------------------------------------------------------------

net = cnn_imagenet_init('model', opts.modelType, ...
                        'batchNormalization', opts.batchNormalization, ...
                        'weightInitMethod', opts.weightInitMethod, ...
                        'networkType', opts.networkType) ;

% -------------------------------------------------------------------------
%                                                              Prepare data
% -------------------------------------------------------------------------

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

% Set the class names in the network
net.meta.classes.name = imdb.classes.name ;
net.meta.classes.description = imdb.classes.description ;

% Compute image statistics (mean, RGB covariances, etc.)
imageStatsPath = fullfile(opts.expDir, 'imageStats.mat') ;
if exist(imageStatsPath)
  load(imageStatsPath, 'averageImage', 'rgbMean', 'rgbCovariance') ;
else
  [averageImage, rgbMean, rgbCovariance] = getImageStats(opts, net.meta, imdb) ;
  save(imageStatsPath, 'averageImage', 'rgbMean', 'rgbCovariance') ;
end

% Set the image average (use either an image or a color)
%net.meta.normalization.averageImage = averageImage ;
net.meta.normalization.averageImage = rgbMean ;

% Set data augmentation statistics
[v,d] = eig(rgbCovariance) ;
net.meta.augmentation.rgbVariance = 0.1*sqrt(d)*v' ;
clear v d ;

% -------------------------------------------------------------------------
%                                                                     Learn
% -------------------------------------------------------------------------

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

[net, info] = trainFn(net, imdb, getBatchFn(opts, net.meta), ...
                      'expDir', opts.expDir, ...
                      net.meta.trainOpts, ...
                      opts.train) ;

% -------------------------------------------------------------------------
%                                                                    Deploy
% -------------------------------------------------------------------------

net = cnn_imagenet_deploy(net) ;
modelPath = fullfile(opts.expDir, 'net-deployed.mat')

switch opts.networkType
  case 'simplenn'
    save(modelPath, '-struct', 'net') ;
  case 'dagnn'
    net_ = net.saveobj() ;
    save(modelPath, '-struct', 'net_') ;
    clear net_ ;
end

% -------------------------------------------------------------------------
function fn = getBatchFn(opts, meta)
% -------------------------------------------------------------------------
useGpu = numel(opts.train.gpus) > 0 ;

bopts.numThreads = opts.numFetchThreads ;
bopts.imageSize = meta.normalization.imageSize ;
bopts.border = meta.normalization.border ;
bopts.averageImage = meta.normalization.averageImage ;
bopts.rgbVariance = meta.augmentation.rgbVariance ;
bopts.transformation = meta.augmentation.transformation ;

switch lower(opts.networkType)
  case 'simplenn'
    fn = @(x,y) getSimpleNNBatch(bopts,x,y) ;
  case 'dagnn'
    fn = @(x,y) getDagNNBatch(bopts,useGpu,x,y) ;
end

% -------------------------------------------------------------------------
function [im,labels] = getSimpleNNBatch(opts, imdb, batch)
% -------------------------------------------------------------------------
images = strcat([imdb.imageDir filesep], imdb.images.name(batch)) ;
isVal = ~isempty(batch) && imdb.images.set(batch(1)) ~= 1 ;

if ~isVal
  % training
  im = cnn_imagenet_get_batch(images, opts, ...
                              'prefetch', nargout == 0) ;
else
  % validation: disable data augmentation
  im = cnn_imagenet_get_batch(images, opts, ...
                              'prefetch', nargout == 0, ...
                              'transformation', 'none') ;
end

if nargout > 0
  labels = imdb.images.label(batch) ;
end

% -------------------------------------------------------------------------
function inputs = getDagNNBatch(opts, useGpu, imdb, batch)
% -------------------------------------------------------------------------
images = strcat([imdb.imageDir filesep], imdb.images.name(batch)) ;
isVal = ~isempty(batch) && imdb.images.set(batch(1)) ~= 1 ;

if ~isVal
  % training
  im = cnn_imagenet_get_batch(images, opts, ...
                              'prefetch', nargout == 0) ;
else
  % validation: disable data augmentation
  im = cnn_imagenet_get_batch(images, opts, ...
                              'prefetch', nargout == 0, ...
                              'transformation', 'none') ;
end

if nargout > 0
  if useGpu
    im = gpuArray(im) ;
  end
  labels = imdb.images.label(batch) ;
  inputs = {'input', im, 'label', imdb.images.label(batch)} ;
end

% -------------------------------------------------------------------------
function [averageImage, rgbMean, rgbCovariance] = getImageStats(opts, meta, imdb)
% -------------------------------------------------------------------------
train = find(imdb.images.set == 1) ;
train = train(1: 101: end);
bs = 256 ;
opts.networkType = 'simplenn' ;
fn = getBatchFn(opts, meta) ;

for t=1:bs:numel(train)
  batch_time = tic ;
  batch = train(t:min(t+bs-1, numel(train))) ;
  fprintf('collecting image stats: batch starting with image %d ...', batch(1)) ;
  temp = fn(imdb, batch) ;
  z = reshape(permute(temp,[3 1 2 4]),3,[]) ;
  n = size(z,2) ;
  avg{t} = mean(temp, 4) ;
  rgbm1{t} = sum(z,2)/n ;
  rgbm2{t} = z*z'/n ;
  batch_time = toc(batch_time) ;
  fprintf(' %.2f s (%.1f images/s)\n', batch_time, numel(batch)/ batch_time) ;
end
averageImage = mean(cat(4,avg{:}),4) ;
rgbm1 = mean(cat(2,rgbm1{:}),2) ;
rgbm2 = mean(cat(3,rgbm2{:}),3) ;
rgbMean = rgbm1 ;
rgbCovariance = rgbm2 - rgbm1*rgbm1' ;


function v = volume(sR,S2G)
% volume of a spherical region
%
%
% TODO: make this better!!
% formula: v = S - (n-2)*pi
% where S is the sum of the interior angles and n is the number of vertices

if nargin == 1, S2G = equispacedS2Grid(0.5*degree); end

v = nnz(sR.checkInside(S2G))/length(S2G);


function [Lc,Mc,Rc] = compressfactors(L,M,R)

Lc = {};
Rc = {};
Mc = {};
taken = zeros(1,length(M));
for i = 1:length(M)
    Lsameas = [];
    Rsameas = [];
    if ~taken(i)
        for j = i+1:length(M)
            if isequal(M{i},M{j})
                if isequal(L{i},L{j})
                    Lsameas = [Lsameas j];
                    taken(j) = 1;
                elseif isequal(R{i},R{j})
                    Rsameas = [Rsameas j];
                    taken(j) = 1;
                end
            end
        end
        if isempty(Rsameas) & ~isempty(Lsameas)
            Lc{end+1} = L{i};
            Mc{end+1} = M{i};
            Rc{end+1} = R{i};
            for j = 1:length(Lsameas)
                Rc{end} = Rc{end} + R{Lsameas(j)};
            end
        elseif isempty(Lsameas) & ~isempty(Rsameas)
            Lc{end+1} = L{i};
            Mc{end+1} = M{i};
            Rc{end+1} = R{i};
            for j = 1:length(Rsameas)
                Lc{end} = Lc{end} + L{Rsameas(j)};
            end
        elseif ~taken(i)
            Lc{end+1} = L{i};
            Mc{end+1} = M{i};
            Rc{end+1} = R{i};
        end
    end
end


%SETFEATSIZE Set the feature size of a dataset
%
%   A = SETFEATSIZE(A,FEATSIZE)
%
% INPUT
%   A         Dataset
%   FEATSIZE  Feature size vector
%
% OUTPUT
%   A         Dataset
%
% DESCRIPTION
% By default the feature size of a dataset is its number of features, i.e.
% the number of columns in the DATA field of A. If the features are samples
% of a multi-dimensional data item, e.g. the pixels of an image, the
% original size of this data item may be stored in FEATSIZE. The product of
% all elements in FEATSIZE has to be equal to the number of columns in the
% DATA field of A.


function [ data ] = readOffsetRep( ndata, labelset )
%READOFFSETREP read the offset representations and  recover the boxes with
%absolute positions
%
% INPUT: ndata - the ndata is a struct with
%                 "kids" (hierarchy)
%                 "leafreps" (layer+label of boxes)
%                 "relposreps" (relative positions between child
%                 and parent)
%        labelset - the category list for this dataset
%
% OUTPUT: data - the data is a struct with
%                 "kids" (hierarchy) the same with input
%                 "obblist" (boxes with absolute positions)
%                 "labellist" (labels of the boxes)
%                 "layers" (layers of the boxes)

kids = ndata.kids;
leafreps = ndata.leafreps;
relposreps = ndata.relposreps;
leafnum = size(leafreps,2);
nodenum = length(kids);

%% extract the labels
classnum = length(labelset);
labelvec = leafreps(end-classnum+1:end,:);
labellist = {};
for i = 1:leafnum
    label = labelvec(:,i);
    [~,I] = max(label);
    label = labelset{I};
    labellist{i} = label;
end

%% extract the layers
if(size(leafreps,1)-classnum>0)
    layers = leafreps(1,:);
end

%% compute the absolute positions of the boxes
obblist = zeros(12,nodenum);
% obblist(:,end) = [0.0322;0;-0.0885;1;0;0;0;1;0;0.49;0;1.0670]; % the root box
obblist(:,end) = [0;0;0;1;0;0;0;1;0;1;0;1];
% [ psize ] = getRootSize( ndata );
% obblist(10:12,end) = psize;
lastmergerep = relposreps{end};
rootrp = lastmergerep(:,1);
obblist(10,end) = rootrp(2);
obblist(12,end) = rootrp(3);
for i = nodenum:-1:1
    pobb = obblist(:,i);
    k = kids{i};
    rplist = relposreps{i};
    if(length(k)>1)
        for j = 2:length(k)
            rp = rplist(:,j-1);
            cobb = genOBBfrom2dOffset( pobb, rp );
            obblist(:,k(j)) = cobb;
        end
    end
end

% form the data
data.kids = kids;
data.labellist = labellist;
data.obblist = obblist;%(:,1:leafnum);
if(exist('layers','var'))
    data.layers = layers;
end

end


%-------------------------------------------------------------------------------------------------------------------%
%
% IB2d is an Immersed Boundary Code (IB) for solving fully coupled non-linear
% 	fluid-structure interaction models. This version of the code is based off of
%	Peskin's Immersed Boundary Method Paper in Acta Numerica, 2002.
%
% Author: Nicholas A. Battista
% Email:  nick.battista@unc.edu
% Date Created: May 27th, 2015
% Institution: UNC-CH
%
% This code is capable of creating Lagrangian Structures using:
% 	1. Springs
% 	2. Beams (*torsional springs)
% 	3. Target Points
%	4. Muscle-Model (combined Force-Length-Velocity model, "Hill+(Length-Tension)")
%
% One is able to update those Lagrangian Structure parameters, e.g., spring constants, resting lengths, etc
%
% There are a number of built in Examples, mostly used for teaching purposes.
%
% If you would like us to add a specific muscle model, please let Nick (nick.battista@unc.edu) know.
%
%--------------------------------------------------------------------------------------------------------------------%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: updates the spring attributes!
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function springs_info = update_Springs(dt,current_time,xLag,yLag,springs_info)

%springs_info: col 1: starting spring pt (by lag. discretization)
%              col 2: ending spring pt. (by lag. discretization)
%              col 3: spring stiffness
%              col 4: spring resting lengths

t = current_time;   %CURRENT TIME IN SIM.
ds1 = 3.906250e-03; %PHASE 1 Lag. Spacing
ds2 = 3.342919e-03; %PHASE 2 Lag. Spacing

Nbody = 106;                    %Number of springs before bell connections
RL = give_Resting_Lengths();    %Resting Lengths for Phase 1 (col 1) and Phase 2 (col 2)

% CHANGE RESTING LENGTH BTWN SIDES OF JELLYFISH BELL
for i=1:length( springs_info(:,4) )

    if i <= Nbody
        springs_info(i,4) = ds1 + 5*t*(ds2-ds1);
    else
        ii = i-Nbody;
        springs_info(i,4) = RL(ii,1) + 5*t*( RL(ii,2) - RL(ii,1) );
        %springs_info(107+(i-1),4) = distVec(i)*abs( cos(4*pi*current_time) );
        %springs_info(107+(i-1),4) = distVec(i) * ( 1 - 0.75*( sin(4*pi*current_time) ) );
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: give Resting Lengths (hardcoded!)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function RL = give_Resting_Lengths()

RL = [0.150000000000000   0.075000000000000
   0.149926741000240   0.074973170433545
   0.149706855857594   0.074892624017213
   0.149340020675537   0.074758187724185
   0.148825697410294   0.074569727429823
   0.148163136564709   0.074326763924451
   0.147351380996092   0.074028781527991
   0.146388643571571   0.073675421427274
   0.145274017365354   0.073265752667258
   0.144005152820154   0.072798927606369
   0.142580953464829   0.072274183901744
   0.140998544348621   0.071690309088121
   0.139255611062067   0.071045912762170
   0.137348541189626   0.070339929225114
   0.135274492318472   0.069570469632096
   0.133030516962324   0.068735403317456
   0.130612168717920   0.067832977122889
   0.128014600466564   0.066860709378195
   0.125234180745507   0.065816586316769
   0.122265614832230   0.064697078425658
   0.119103315657513   0.063499067862592
   0.115741451424401   0.062218444447808
   0.112173999448214   0.060850772863983
   0.108392818785359   0.059391311235482
   0.104393528844001   0.057835033327000
   0.100165653754868   0.056174749467196
   0.095702659718569   0.054402747848968
   0.090998237021989   0.052510837712120
   0.086041701055792   0.050487212358191
   0.080827140474999   0.048320369497431
   0.075349280754860   0.045994841644143
   0.069598549422225   0.043493120994599
   0.063573706279126   0.040793235757662
   0.057274941348722   0.037865974506005
   0.050704050274530   0.034676918247010
   0.043870119404512   0.031179908592683
   0.036787309077097   0.027316537892343
   0.029477909226729   0.023009349350403
   0.021975429586313   0.018167707789027
   0.014318966133393   0.012694598507574
   0.006558552552061   0.006558010776142];


classdef GraphTrainLog
    properties
        nCost = 1;
        cost;
        cost_cv;
        cost_cv_hour;

        costMinibatch;
        costBlock;

        nHourSeen = 0;
        actual_LR = [];
    end

    methods
        function obj = GraphTrainLog(sigGraph)
            obj.nCost = length(sigGraph.costWeight);
            obj.cost = GraphCost(obj.nCost, 0);
            obj.cost_cv = GraphCost(obj.nCost, 0);
            obj.cost_cv_hour = GraphCost(obj.nCost, 0);
            obj.costMinibatch = GraphCost(obj.nCost, 0);
            obj.costBlock = GraphCost(obj.nCost, 0);
        end

        function obj = initialize(obj)
            obj.actual_LR = [];
        end

        function obj = initializeBlockCost(obj)
            obj.costBlock = GraphCost(obj.nCost, 0);
        end

        function obj = initializeMiniBatchCost(obj,nCost, nBatch, useGPU)
            obj.costMinibatch = GraphCost(nCost, nBatch);
        end

        function obj = accumulateMiniBatchCost(obj, batch_i, cost_func)
            obj.costMinibatch = cost_func.copyCost(obj.costMinibatch, batch_i);
        end

        function obj = accumulateBlockCost(obj)
            obj.costBlock = obj.costMinibatch.appendCost(obj.costBlock);
        end

        function obj = accumulateItrCost(obj)
            obj.cost = obj.costBlock.appendMeanCost(obj.cost);
        end

        function obj = accumulateTrainDataAmount(obj, minibatch, data)
            for i=1:length(minibatch)
                [D,D2,T,N] = size(minibatch{i});
                if data.streams(i).frameRate==0
                    frameRate = 1;  % frameRate=0 means one data point per sequence. assume the sequence is 1s long.
                else
                    frameRate = data.streams(i).frameRate;
                end
                duration(i) = T*N/frameRate;
            end
            obj.nHourSeen = obj.nHourSeen + max(duration) / 3600;
        end

        function SaveModel(obj, itr, para, sigGraph)
            if mod(itr,para.saveModelEveryXIter)==0
                modelfile = [para.output sprintf('.itr%d.LR%s', itr, FormatFloat4Name(learning_rate))];
                if obj.cost_pure_cv(end)>0.1
                    modelfile = sprintf('%s.CV%2.3f.mat', modelfile, cost_pure_cv(end));
                else
                    modelfile = sprintf('%s.CV%s.mat', modelfile, FormatFloat4Name(cost_pure_cv(end)));
                end
                LOG = obj;
                SaveDNN(sigGraph, para, LOG, modelfile);
            end
        end

        function DisplayCostMinibatch(obj, itr, blk_i, nBlock, batch_i, nMiniBatch, displayInterval, displayTag)
            if itr<=0
                ItrStr = 'CV cost';
            else
                ItrStr = sprintf('Cost at itr %i', itr);
            end

            if mod(batch_i,displayInterval)==0 || (batch_i==nMiniBatch && displayInterval>batch_i)
                costMB = obj.costMinibatch;
                meanTotalCost = mean(costMB.totalCost(max(1,batch_i-displayInterval+1) : batch_i));
                if isnan(meanTotalCost)
                    pause(0.1);
                end
                fprintf('%s, blk %d/%d, MB %d/%d = %.4g / %.4g', ...
                    ItrStr, blk_i, nBlock, batch_i, nMiniBatch, ...
                    meanTotalCost, ...
                    mean(costMB.taskCost(max(1,batch_i-displayInterval+1) : batch_i)));
                if obj.nCost>1
                    fprintf(' - Subcosts: ');
                    for i = 1:obj.nCost
                        fprintf('%d) %f; ', i, mean(costMB.subCost(i,max(1,batch_i-displayInterval+1) : batch_i)));
                    end
                end
                fprintf(' - %s - %s\n', datestr(now), displayTag);
                pause(0.01);
            end
        end

        function DisplayCostIteration(obj, itr)
            if itr<=0
                ItrStr = 'CV cost';
            else
                ItrStr = sprintf('Cost at itr %i', itr);
            end

            fprintf('%s = %f / %f\t - %s\n', ...
                ItrStr, obj.cost.totalCost(end), sum(obj.cost.taskCost(:,end)), datestr(now));
            if length(obj.cost.subCost(:,end))>1
                fprintf('        ----subcosts = %f\n', obj.cost.subCost(:,end));
            end
            if sum(obj.cost.subAcc(:,end)>=0)
                fprintf('    ----(Sub)task accuracy = %2.2f%%\n', 100*obj.cost.subCost(:,end));
            end
        end
    end

    methods

    end

end


% dicomNumSlices
%
% Usage: numSlices = dicomNumSlices;
%
% By Davie
% 2008/02/19
%
% From Bob:
% Most dicom-to-nifti functions (including my niftiFromDicom, which calls
% my dicomLoadAllSeries) guess the number of slices by loading all of the
% files and then counting the slices. For 4d sequences like DTI and fMRI,
% where you have a set of volumes acquired many times, you also need to
% look at the DICOM SliceLocation field, which tells you the slice's
% position in the volume (in physical space units). The number of unique
% slice locations is the 'official' DICOM indication of the number of
% slices.
%
% Why a new function?:
% Number of slices can be computed by dicomLoadAllSeries, but I couldn't
% get it to work for some reason. So here is a simple (but less general)
% hack.
%
% This will take a long time to run (which is why I added printing status)

function numSlices = dicomNumSlices

d = dir('*.dcm*');

sliceLocations = zeros(length(d));

for ii=1:length(d)
    curFile=d(ii).name;
    info=dicominfo(curFile);
    sliceLocations(ii)=info.SliceLocation;
    fprintf('\n Loaded slice %d',ii);
    clear info
end

numSlices = unique(sliceLocations);
numSlices = length(numSlices)-1; % subtract 1, b/c there is a 0 location


function g = tensorKernGradient(kern, x, varargin)

% TENSORKERNGRADIENT Gradient of TENSOR kernel's parameters.
% FORMAT
% DESC computes the gradient of functions with respect to the
% tensor product
% kernel's parameters. As well as the kernel structure and the
% input positions, the user provides a matrix PARTIAL which gives
% the partial derivatives of the function with respect to the
% relevant elements of the kernel matrix.
% ARG kern : the kernel structure for which the gradients are being
% computed.
% ARG x : the input locations for which the gradients are being
% computed.
% ARG partial : matrix of partial derivatives of the function of
% interest with respect to the kernel matrix. The argument takes
% the form of a square matrix of dimension  numData, where numData is
% the number of rows in X.
% RETURN g : gradients of the function of interest with respect to
% the kernel parameters. The ordering of the vector should match
% that provided by the function kernExtractParam.
%
% FORMAT
% DESC computes the derivatives as above, but input locations are
% now provided in two matrices associated with rows and columns of
% the kernel matrix.
% ARG kern : the kernel structure for which the gradients are being
% computed.
% ARG x1 : the input locations associated with the rows of the
% kernel matrix.
% ARG x2 : the input locations associated with the columns of the
% kernel matrix.
% ARG partial : matrix of partial derivatives of the function of
% interest with respect to the kernel matrix. The matrix should
% have the same number of rows as X1 and the same number of columns
% as X2 has rows.
% RETURN g : gradients of the function of interest with respect to
% the kernel parameters.
%
% SEEALSO tensorKernParamInit, kernGradient, tensorKernDiagGradient, kernGradX
%
% COPYRIGHT : Neil D. Lawrence, 2006

% KERN

% Last of varargin is covGrad.
  g = zeros(1, kern.nParams);
  startVal = 1;
  endVal = 0;
  twoXin = 0;
  if length(varargin) > 1
    twoXin = 1;
    x2 = varargin{1};
    covGrad = varargin{end};
  else
    covGrad = varargin{end};
  end

  for i = 1:length(kern.comp)
    tempKern = tensorKernSlash(kern, i);
    if twoXin
      tempCovGrad = covGrad.*kernCompute(tempKern, x, x2);
    else
      tempCovGrad = covGrad.*kernCompute(tempKern, x);
  end
  endVal = endVal + kern.comp{i}.nParams;
  if ~isempty(kern.comp{i}.index)
    % only part of the data is involved in the kernel.
    if ~twoXin
      g(1, startVal:endVal)  = kernGradient(kern.comp{i}, ...
                                            x(:, kern.comp{i}.index), ...
                                            tempCovGrad);
    else
      g(1, startVal:endVal) = kernGradient(kern.comp{i}, ...
                                           x(:, kern.comp{i}.index), ...
                                           x2(:, kern.comp{i}.index), ...
                                           tempCovGrad);
    end
  else
    if ~twoXin
      % all the data is involved with the kernel.
      g(1, startVal:endVal)  = kernGradient(kern.comp{i}, x, ...
                                            tempCovGrad);
    else
      g(1, startVal:endVal) = kernGradient(kern.comp{i}, x, x2, ...
                                           tempCovGrad);
    end
  end
  startVal = endVal + 1;
end
g = g*kern.paramGroups;


% THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION IS RELEASED "AS IS."  THE U.S. GOVERNMENT MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, CONCERNING THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT WILL THE U.S. GOVERNMENT BE LIABLE FOR ANY DAMAGES, INCLUDING ANY LOST PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE, OR INABILITY TO USE, THIS SOFTWARE OR ANY ACCOMPANYING DOCUMENTATION, EVEN IF INFORMED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
%
% file: test_prop_diff_ci.m
%
% use: run "test_prop_diff_ci" and then examine "test_prop_diff_ci_results.csv" in the work folder and
%      compare it to the "test_prop_diff_ci_results_reference.csv" distributed with the code.
%      Failure to run or significant differences in results may indicate installation problems.
%
% change log:
%   030114 tdr created from test_prop_ci.m

function test_prop_diff_ci

methods = [1 3 4 5 6];
alphas = [1e-4 1e-2 0.9];
ns = [1 30 1e5];

fid = fopen('test_prop_diff_ci_results.csv','w');
fprintf(fid,'%s\n','delta_p_hat, Lower CI Bound, Upper CI Bound, x1, n1, x2, n2, Desired alpha, Method, Length, Lower Tail, Upper Tail, Actual alpha, Delta alpha, Run Time');

warning off;

for method = methods
   for alpha = alphas
      for n1 = ns
         if n1 < 5
            x1s = [0];
         else
            x1s = [0 1 round(n1/3)];
         end;
         for n2 = ns
            if n2 < 5
                x2s = [n2];
            else
                x2s = [0 1 round(n2/2) n2];
            end;
            for x1 = x1s
                for x2 = x2s
                    ci = prop_diff_ci(x1,n1,x2,n2,alpha,method,1);
                    fprintf(fid,'%8.6g, %8.6g, %8.6g, %d, %d, %d, %d, %8.6g, %d, %8.6g, %8.6g, %8.6g, %8.6g, %8.6g, %8.2g\n',ci);
                end;
			end;
		 end;
     end;
   end;
end;

warning on;
fclose(fid);


classdef ImageTakerFor3DShape < handle

    properties (Access = private)
        uMesh
        outDir
    end

    methods (Access = public)

        function obj = ImageTakerFor3DShape(cParams)
            obj.init(cParams)
        end

        function takeImages(obj)
            obj.plotUnfittedMesh();
            obj.takeIsoFrontImage();
            obj.takeBackImage();
            obj.takeFrontImage();
            obj.takeIsoBackImage();
        end

    end

    methods (Access = private)

        function init(obj,cParams)
            obj.uMesh  = cParams.unfittedMesh;
            obj.outDir = cParams.outDir;
        end

        function takeIsoFrontImage(obj)
            fName = 'IsoFrontImage';
            az = 120;
            el = 30;
            fName = [obj.outDir,fName];
            view(az,el)
            obj.takeImage(fName)
        end

        function takeIsoBackImage(obj)
            fName = 'IsoBackImage';
            az = 240;
            el = 30;
            fName = [obj.outDir,fName];
            view(az,el)
            obj.takeImage(fName)
        end

        function takeFrontImage(obj)
            fName = 'YZfrontImage';
            az = 90;
            el = 0;
            fName = [obj.outDir,fName];
            view(az,el)
            obj.takeImage(fName)
        end

        function takeBackImage(obj)
            fName = 'YZbackImage';
            az = 90;
            el = 180;
            fName = [obj.outDir,fName];
            view(az,el)
            obj.takeImage(fName)
        end

        function plotUnfittedMesh(obj)
            f = figure();
            f.WindowState = 'maximized';
            obj.uMesh.plot();
        end

    end

    methods (Access = private, Static)

        function takeImage(name)
            print(name,'-dpng')
        end

    end

end


% sim_press_shaped.m
% Robin Simpson and Jamie Near, 2014.
%
% USAGE:
% out = sim_press_shaped(n,sw,Bfield,linewidth,sys,tau1,tau2,RF,tp,dx,dy,Gx,Gy,flipAngle,centreFreq)
%
% DESCRIPTION:
% This function simulates the PRESS experiment.  The excitation is
% simulated as an instantaneous rotation, and the refocusing pulses are
% simulated as shaped rotations.
%
% It employs coherence selection to only include desired coherence orders
% of the spin system being simulated. For the PRESS experiment, the desired
% coherence after the excitation pulse is -1, +1 after the first refocusing
% pulse and -1 after the final refocusing pulse.
%
% Finally, this code simulates the spectrum at a given point in space (x,y),
% given the values of the slice selection gradients (Gx, and Gy).  The pulse
% waveform is assumed to be the same for both refocusing pulses.  In order
% to fully simulate the MEGA-PRESS experiment, you have to run this
% simulation many times at various points in space (x,y), and then add
% together the resulting spectra.
%
% INPUTS:
% n         = number of points in fid/spectrum
% sw        = desired spectral width in [Hz]
% Bfield    = main magnetic field strength in [T]
% linewidth = linewidth in [Hz]
% sys       = spin system definition structure
% tau1      = echo time 1 in [ms].
% tau2      = echo time 2 in [ms].
% RF        = RF pulse definition structure for refoc pulses (obtain using 'io_loadRFwaveform.m')
% tp        = RF pulse duration in [ms]
% dx        = position offset in x-direction (corresponding to first refocusing pulse) [cm]
% dy        = position offset in y-direction (corresponding to second refocusing pulse) [cm]
% Gx        = gradient strength for first selective refocusing pulse [G/cm]
% Gy        = gradient strength for second selective refocusing pulse [G/cm]
% flipAngle = flip angle of refocusing pulses [degrees] (Optional.  Default = 180 deg)
% centreFreq= centre frequency of the spectrum in [ppm] (Optional.  Default = 2.3)
%
% OUTPUTS:
% out       = simulated spectrum, in FID-A structure format, using PRESS
%             sequence.

function out = sim_press_shaped(n,sw,Bfield,linewidth,sys,tau1,tau2,RF,tp,dx,dy,Gx,Gy,flipAngle,centreFreq)

if nargin<15
    centreFreq=2.3;
    if nargin<14
        flipAngle=180;
    end
end

if tau1<tp/1000
    error('ERROR:  Echo-time 1 cannot be less than duration of refocusing pulse! ABORTING!!');
end
if tau2<tp/1000
    error('ERROR:  Echo-time 2 cannot be less than duration of refocusing pulse! ABORTING!!');
end

%Set water to centre
for k=1:length(sys)
    sys(k).shifts=sys(k).shifts-centreFreq;
end

%Calculate Hamiltonian matrices and starting density matrix.
[H,d]=sim_Hamiltonian(sys,Bfield);

%Calculate new delays by subtracting the pulse duration from tau1 and tau2;
delays=zeros(2);
delays(1)=tau1-tp;
delays(2)=tau2-tp;
if sum(delays<0)
    error(['ERROR! The following taus are too short: ' num2str(find(delays<0)) '.']);
end

%BEGIN PULSE SEQUENCE************
d=sim_excite(d,H,'x');                                    %EXCITE
d=sim_COF(H,d,-1);                       %Keep only -1 coherences
d=sim_evolve(d,H,delays(1)/2000);                         %Evolve by delays(1)/2
d=sim_shapedRF(d,H,RF,tp,flipAngle,90,dx,Gx);             %1st shaped 180 degree refocusing pulse
d=sim_COF(H,d,1);                        %Keep only +1 coherences
d=sim_evolve(d,H,(delays(1)+delays(2))/2000);             %Evolve by (delays(1)+delays(2))/2
d=sim_shapedRF(d,H,RF,tp,flipAngle,90,dy,Gy);             %2nd shaped 180 degree refocusing pulse
d=sim_COF(H,d,-1);                       %Keep only -1 coherences
d=sim_evolve(d,H,delays(2)/2000);                         %Evolve by delays(2)/2
[out,dout]=sim_readout(d,H,n,sw,linewidth,90);            %Readout along y (90 degree phase);
%END PULSE SEQUENCE**************

%Correct the ppm scale:
out.ppm=out.ppm-(4.65-centreFreq);

%Fill in structure header fields:
out.seq='press';
out.te=tau1+tau2;
out.sim='shaped';

%Additional fields for compatibility with FID-A processing tools.
out.sz=size(out.specs);
out.date=date;
out.dims.t=1;
out.dims.coils=0;
out.dims.averages=0;
out.dims.subSpecs=0;
out.dims.extras=0;
out.averages=1;
out.rawAverages=1;
out.subspecs=1;
out.rawSubspecs=1;
out.flags.writtentostruct=1;
out.flags.gotparams=1;
out.flags.leftshifted=0;
out.flags.filtered=0;
out.flags.zeropadded=0;
out.flags.freqcorrected=0;
out.flags.phasecorrected=0;
out.flags.averaged=1;
out.flags.addedrcvrs=1;
out.flags.subtracted=1;
out.flags.writtentotext=0;
out.flags.downsampled=0;
out.flags.isFourSteps=0;


function model = rmGridFit_twoGaussiansDoGbetafixed(model,prediction,data,params,t)
% rmGridFit_twoGaussiansDoG - core of DoG fit
%
% model = rmGridFit_twoGaussiansDoG(model,prediction,data,params);
%
% Second gaussian can go negative only.
%
% 2008/01 SOD: split of from rmGridFit.

% input check
if nargin < 4,
    error('Not enough arguments');
end

% some variables we need
rssinf         = inf(size(data(1,:)),'single');
trends         = t.trends;
t_id           = t.dcid+1;

% stimulus sequence is needed because make second pRF on the fly
allstimimages = rmDecimate(params.analysis.allstimimages,...
    params.analysis.coarseDecimate);

%-----------------------------------
%--- fit different receptive fields profiles
%--- another loop --- and a slow one too
%-----------------------------------
tic; progress = 0;
for n=1:numel(params.analysis.x0),
    %-----------------------------------
    % progress monitor (10 dots) and time indicator
    %-----------------------------------
    if floor(n./numel(params.analysis.x0).*10)>progress,
        if progress==0,
            % print out estimated time left
            esttime = toc.*10;
            if floor(esttime./3600)>0,
                fprintf(1,'[%s]:Estimated processing time: %d hours.\t(%s)\n',...
                    mfilename, ceil(esttime./3600), datestr(now));
            else
                fprintf(1, '[%s]:Estimated processing time: %d minutes.\t(%s)\n',...
                    mfilename, ceil(esttime./60), datestr(now));
            end;
            fprintf(1,'[%s]:Grid (x,y,sigma) fit:',mfilename);drawnow;
        end;
        % progress monitor
        fprintf(1,'.');drawnow;
        progress = progress + 1;
    end;

    %-----------------------------------
    %--- first make all second rf profiles
    %-----------------------------------
    sigmaNew = params.analysis.sigmaRatio.*params.analysis.sigmaMajor(n);
    % limit to sigmaRatioMaxVal
    sigmaNew = sigmaNew(sigmaNew<=params.analysis.sigmaRatioMaxVal);
    % add sigmaRatioInfVal which essentially is on/off
    sigmaNew = [sigmaNew; params.analysis.sigmaRatioInfVal]; %#ok<AGROW>
    %betaratio = params.analysis.betaRatioAlpha.*(params.analysis.sigmaMajor(n).^2./sigmaNew.^2);
    betaratio = (params.analysis.sigmaMajor(n)./sigmaNew).^params.analysis.betaRatioAlpha;

    % Now we make it: slightly different call for speed reasons.
    z = zeros(size(sigmaNew));
    tmprf   = rfGaussian2d(params.analysis.X - params.analysis.x0(n),...
        params.analysis.Y - params.analysis.y0(n),...
        sigmaNew,sigmaNew, ...
        false, z, z);
    prediction2 = allstimimages*tmprf;

    %-----------------------------------
    %--- try two rf profiles, yet another loop
    %-----------------------------------
    for sr = 1:numel(sigmaNew),
        %-----------------------------------
        % Now apply GLM, see *_oneGaussian for logic.
        % New rules for this one:
        % 1. first Gaussian has to be positive
        % 2. there should be a positive response in the
        % center at all times. This
        % assumes Gaussians are unscaled (see rfGaussian2d).
        %-----------------------------------
        predictionNew = prediction(:,n) - betaratio(sr,:).*prediction2(:,sr);
        X     = [predictionNew trends];
        b     = pinv(X)*data;
        rss   = rssinf;
        keep  = b(1,:)>0;
        rss(keep) = sum((data(:,keep)-X*b(:,keep)).^2);

        %-----------------------------------
        %--- store data with lower rss
        %-----------------------------------
        minRssIndex = rss < model.rss;

        % now update
        model.x0(minRssIndex)       = params.analysis.x0(n);
        model.y0(minRssIndex)       = params.analysis.y0(n);
        model.s(minRssIndex)        = params.analysis.sigmaMajor(n);
        model.s_major(minRssIndex)        = params.analysis.sigmaMajor(n);
        model.s_minor(minRssIndex)        = params.analysis.sigmaMajor(n);
        model.s_theta(minRssIndex)        = params.analysis.theta(n);
        model.rss(minRssIndex)      = rss(minRssIndex);
        model.b([1 t_id],minRssIndex)    = b(:,minRssIndex);
        model.s2(minRssIndex)       = sigmaNew(sr);
    end;
end;

% end time monitor
et  = toc;
if floor(esttime/3600)>0,
    fprintf(1,'Done[%d hours].\t(%s)\n', ceil(et/3600), datestr(now));
else
    fprintf(1,'Done[%d minutes].\t(%s)\n', ceil(et/60), datestr(now));
end;
drawnow;
return;


jobIDs = [2130597 2130598 2130599 2130600 2130601 2130602];
taskIDs = 1:4;

infNames = {'SM+zDD AnnealLIN', 'SM+zDD', 'SM+cDD'};
initNames = {'one', 'seq'};

nn=1;
for aa = 1:length(initNames)
for jj = 1:length(infNames)
    jobNames{nn} = [infNames{jj} ' ' initNames{aa}];
    nn=nn+1;
end
end

plotLogPrVsTime( jobIDs(1:3), taskIDs, jobNames(1:3) );
set(gcf, 'name', 'OneInit' );
ylim( [-6.45 -6.25]*1e5 );

plotLogPrVsTime( jobIDs(4:6), taskIDs, jobNames(4:6) );
set(gcf, 'name', 'SeqInit' );
ylim( [-6.45 -6.25]*1e5 );


classdef prtRvUniform < prtRv
    % prtRvUniform  Uniform random variable
    %
    %   RV = prtRvUniform creates a prtRvUniform object with empty
    %   upperBounds and lowerBounds. The upperBounds and lowerBounds must
    %   be set either directly, or by calling the MLE method. upperBounds
    %   and lowerBounds specify the range of the uniform variable.
    %
    %   RV = prtRvUniform(PROPERTY1, VALUE1,...) creates a prtRvUniform
    %   object RV with properties as specified by PROPERTY/VALUE pairs.
    %
    %   A prtRvUniform object inherits all properties from the prtRv class.
    %   In addition, it has the following properties:
    %
    %   upperBounds - 1 x nDims double vector specifying the upper bound of
    %                 the region with uniform density
    %   lowerBounds - 1 x nDims double vector specifying the lower bound of
    %                 the region with uniform density
    %
    %  A prtRvUniform object inherits all methods from the prtRv class.
    %  The MLE  method can be used to estimate the distribution parameters
    %  from data.
    %
    %  Example:
    %
    %  dataSet = prtDataGenUnimodal;        % Load a dataset consisting of
    %                                       % 2 features
    %  dataSet = retainFeatures(dataSet,1); % Retain only the first feature
    %
    %  RV = prtRvUniform;                   % Create a prtRvUniform object
    %  RV = RV.mle(dataSet);                % Compute the bounds
    %                                       % form the data
    %  RV.plotPdf                           % Plot the pdf
    %
    %   See also: prtRv, prtRvMvn, prtRvGmm, prtRvMultinomial,
    %   prtRvVq, prtRvKde

    properties (SetAccess = private)
        name = 'Uniform Random Variable'
        nameAbbreviation = 'RVUnif';
    end

    properties (SetAccess = protected)
        isSupervised = false;
        isCrossValidateValid = true;
    end

    properties
        upperBounds  % The lower bounds of the random variable
        lowerBounds  % The upper bounds of the random variable
    end

    properties (Hidden = true, Dependent = true)
        nDimensions
    end

    methods
        % The Constructor
        function R = prtRvUniform(varargin)
            R = constructorInputParse(R,varargin{:});
        end

        function R = mle(R,X)
            X = R.dataInputParse(X); % Basic error checking etc
            R.upperBounds = max(X,[],1);
            R.lowerBounds = min(X,[],1);
        end

        function vals = pdf(R,X)

            [isValid, reasonStr] = R.isValid;
            assert(isValid,'PDF cannot yet be evaluated. This RV is not yet valid %s.',reasonStr);

            X = R.dataInputParse(X); % Basic error checking etc
            assert(size(X,2) == R.nDimensions,'Data, RV dimensionality missmatch. Input data, X, has dimensionality %d and this RV has dimensionality %d.', size(X,2), R.nDimensions)

            isIn = true(size(X,1),1);
            for iDim = 1:size(X,2)
                isIn = isIn & X(:,iDim) >= R.lowerBounds(iDim) & X(:,iDim) <= R.upperBounds(iDim);
            end

            vals = zeros(size(X,1),1);
            vals(isIn) = 1/R.area();
        end

        function vals = logPdf(R,X)
            [isValid, reasonStr] = R.isValid;
            assert(isValid,'LOGPDF cannot yet be evaluated. This RV is not yet valid %s.',reasonStr);

            vals = log(pdf(R,X));
        end

        function vals = cdf(R,X)
            X = R.dataInputParse(X); % Basic error checking etc
            assert(size(X,2) == R.nDimensions,'Data, RV dimensionality missmatch. Input data, X, has dimensionality %d and this RV has dimensionality %d.', size(X,2), R.nDimensions)
            vals = prod(max(bsxfun(@minus,bsxfun(@min,X,R.upperBounds),R.lowerBounds),0),2)./R.area();
        end

        function a = area(R)
            a = prod(R.upperBounds - R.lowerBounds);
        end

        function vals = draw(R,N)
            if nargin < 2
                N = 1;
            end

            assert(numel(N)==1 && N==floor(N) && N > 0,'N must be a positive integer scalar.')

            [isValid, reasonStr] = R.isValid;
            assert(isValid,'DRAW cannot yet be evaluated. This RV is not yet valid %s.',reasonStr);

            vals = bsxfun(@plus,bsxfun(@times,rand(N,R.nDimensions),R.upperBounds - R.lowerBounds),R.lowerBounds);
        end

        function val = get.nDimensions(R)
            val = length(R.upperBounds);
        end
    end

    methods (Hidden = true)
        function [val, reasonStr] = isValid(R)
            if numel(R) > 1
                val = false(size(R));
                for iR = 1:numel(R)
                    [val(iR), reasonStr] = isValid(R(iR));
                end
                return
            end

            badOrder = ~all(R.upperBounds>R.lowerBounds);

            val = ~isempty(R.upperBounds) && ~isempty(R.lowerBounds) && ~badOrder;

            if val
                reasonStr = '';
            else
                badUpper = isempty(R.upperBounds);
                badLower = isempty(R.lowerBounds);

                if badUpper && ~badLower
                    reasonStr = 'because upperBounds has not been set';
                elseif ~badUpper && badLower
                    reasonStr = 'because lowerBounds has not been set';
                elseif badUpper && badLower
                    reasonStr = 'because upperBounds and lowerBounds have not been set';
                elseif badOrder
                    reasonStr = 'because at least one entry of lowerBounds is greater than the corresponding entry of upperBounds';
                else
                    reasonStr = 'because of an unknown reason';
                end
            end
        end

        function val = plotLimits(R)
            [isValid, reasonStr] = R.isValid;
            if isValid

                range = R.upperBounds-R.lowerBounds;

                val = zeros(2*R.nDimensions,1);
                val(1:2:end) = R.lowerBounds-range/10;
                val(2:2:end) = R.upperBounds+range/10;

            else
                error('prtRvUniform:plotLimits','Plotting limits can not be determined for this RV. It is not yet valid %s.',reasonStr)
            end
        end
    end
end


classdef GeneralizedHoughBallard < handle
    %GENERALIZEDHOUGHBALLARD  Generalized Hough transform
    %
    % Finds arbitrary template in the grayscale image using
    % Generalized Hough Transform.
    %
    % Detects position only without translation and rotation.
    %
    % ## References
    % > Ballard, D.H. (1981). Generalizing the Hough transform to detect
    % > arbitrary shapes. Pattern Recognition 13 (2): 111-122.
    %
    % See also: cv.GeneralizedHoughGuil
    %

    properties (SetAccess = private)
        % Object ID
        id
    end

    properties (Dependent)
        % Canny low threshold. default 50
        CannyLowThresh
        % Canny high threshold. default 100
        CannyHighThresh
        % Minimum distance between the centers of the detected objects.
        % default 1.0
        MinDist
        % Inverse ratio of the accumulator resolution to the image resolution.
        % default 1.0
        Dp
        % Maximal size of inner buffers. default 1000
        MaxBufferSize

        % R-Table levels. default 360
        Levels
        % The accumulator threshold for the template centers at the detection
        % stage. The smaller it is, the more false positions may be detected.
        % default 100
        VotesThreshold
    end

    %% GeneralizedHoughBallard
    methods
        function this = GeneralizedHoughBallard()
            %GENERALIZEDHOUGHBALLARD  Constructor
            %
            %     obj = cv.GeneralizedHoughBallard()
            %
            % See also: cv.GeneralizedHoughBallard.detect
            %
            this.id = GeneralizedHoughBallard_(0, 'new');
        end

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

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

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

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

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

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

    %% GeneralizedHough
    methods
        function [positions,votes] = detect(this, varargin)
            %DETECT  Find template on image
            %
            %     [positions,votes] = hough.detect(image)
            %     [positions,votes] = hough.detect(edges, dx, dy)
            %
            % ## Input
            % * __image__ input image, 8-bit 1-channel image
            % * __edges__ image edges
            % * __dx__ image x-derivative of the same size as `edges` and
            %   single-precision floating type.
            % * __dy__ image y-derivate of the same size and type as `dx`.
            %
            % ## Output
            % * __positions__ Cell array of 4-element vectors, each of the
            %   form: `[posx, posy, scale, angle]`
            % * __votes__ Cell array of 3-element vectors, of the same length
            %   as `positions`.
            %
            [positions,votes] = GeneralizedHoughBallard_(this.id, 'detect', varargin{:});
        end

        function setTemplate(this, varargin)
            %SETTEMPLATE  Set template to search
            %
            %     hough.setTemplate(templ)
            %     hough.setTemplate(edges, dx, dy)
            %     hough.setTemplate(..., 'OptionName', optionValue, ...)
            %
            % ## Input
            % * __templ__ template, 8-bit 1-channel image
            % * __edges__ template edges
            % * __dx__ template x-derivative of the same size as `edges` and
            %   single-precision floating type.
            % * __dy__ template y-derivate of the same size and type as `dx`.
            %
            % ## Options
            % * __Center__ Template center `[x,y]`. The default `[-1,-1]`
            %   will use `[size(templ,2) size(templ,1)]./2` as center.
            %
            % In the first variant of the function (with the `templ` input),
            % the `edges` are internally calculated using the cv.Canny filter,
            % and the derivatives `dx` and `dy` using cv.Sobel operator.
            %
            GeneralizedHoughBallard_(this.id, 'setTemplate', varargin{:});
        end
    end

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

        function value = get.CannyLowThresh(this)
            value = GeneralizedHoughBallard_(this.id, 'get', 'CannyLowThresh');
        end
        function set.CannyLowThresh(this, value)
            GeneralizedHoughBallard_(this.id, 'set', 'CannyLowThresh', value);
        end

        function value = get.Dp(this)
            value = GeneralizedHoughBallard_(this.id, 'get', 'Dp');
        end
        function set.Dp(this, value)
            GeneralizedHoughBallard_(this.id, 'set', 'Dp', value);
        end

        function value = get.MaxBufferSize(this)
            value = GeneralizedHoughBallard_(this.id, 'get', 'MaxBufferSize');
        end
        function set.MaxBufferSize(this, value)
            GeneralizedHoughBallard_(this.id, 'set', 'MaxBufferSize', value);
        end

        function value = get.MinDist(this)
            value = GeneralizedHoughBallard_(this.id, 'get', 'MinDist');
        end
        function set.MinDist(this, value)
            GeneralizedHoughBallard_(this.id, 'set', 'MinDist', value);
        end

        function value = get.Levels(this)
            value = GeneralizedHoughBallard_(this.id, 'get', 'Levels');
        end
        function set.Levels(this, value)
            GeneralizedHoughBallard_(this.id, 'set', 'Levels', value);
        end

        function value = get.VotesThreshold(this)
            value = GeneralizedHoughBallard_(this.id, 'get', 'VotesThreshold');
        end
        function set.VotesThreshold(this, value)
            GeneralizedHoughBallard_(this.id, 'set', 'VotesThreshold', value);
        end
    end

end


function opt_checkTypes(opt, optDefaults, structname)
%OPT_CHECKTYPE - Check types of the values in property/value struct
%
%Synopsis:
%  opt_checkTypes(OPT, PROPSPEC)
%
%Arguments:
%  PROPSPEC: PROPSPECLIST - Property specification list with type definition,
%      i.e., CELL of size [N 3], with the first column all being strings
%      (property names), the second column holding the default values (not
%      used in this function), and the third column specifying the expected
%      type of the values. If a third column does not exist, this function
%      just exists.
%
%Returns:
%  nothing (just throws errors)
%
%Description:
%  This function ensures that the values in the property/value struct OPT
%  comply with the types that are specified in the property specification
%  PROCSPEC. For a list of possible specifications, see misc_checkType.
%
%See also misc_checkType, opt_setDefaults.
%
%Examples:
%  props= {'LineColor', 'k', 'CHAR[1]|DOUBLE[3]';
%          'LineWidth', 0.7, 'DOUBLE';
%          'Colormap', copper(51), 'DOUBLE[- 3]';
%          'Transform', eye(2,2), 'DOUBLE[2 2]'};
%
%  opt= struct('Colormap', hot(5));
%  opt_checkTypes(opt, props)
%
%  opt= struct('LineColor', [1 0 0.5 0.5]);
%  % Should throw an error
%  opt_checkTypes(opt, props)
%
%  opt= struct('LineWidth', 'Very Thick');
%  % Should throw an error
%  opt_checkTypes(opt, props)
%
%  opt= struct('Transform', randn(2,2));
%  opt_checkTypes(opt, props)

% 06-2012 Benjamin Blankertz

if size(optDefaults, 2) < 3,
  % No types specified
  return
end

for k= 1:size(optDefaults, 1),
  fld= optDefaults{k,1};
  if isfield(opt, fld),
    fielddisplayname= [structname '.' fld];
    for n= 1:length(opt),
      [ok, msg]= misc_checkType(opt(n).(fld), optDefaults{k,3}, fielddisplayname);
      if ~ok,
        error(msg);
      end
    end
  end
end


function marginal = marginal_nodes(engine, b, nodes, t, add_ev, is_fam)
% function marginal = marginal_nodes(engine, b, nodes, t, add_ev, is_fam) (jtree_2TBN)

if nargin < 6, is_fam = 0; end
ss = engine.slice_size;

if ~is_fam & (t > 1) & all(nodes<=ss)
  nodes = nodes + ss;
end

if t==1
  c = clq_containing_nodes(engine.jtree_engine1, nodes, is_fam);
else
  c = clq_containing_nodes(engine.jtree_engine, nodes, is_fam);
end
if c == -1
  error(['no clique contains ' nodes])
end
bigpot = b.clpot{c};
pot = marginalize_pot(bigpot, nodes, engine.maximize);
marginal = pot_to_marginal(pot);

% we convert the domain to the unrolled numbering system
% so that add_ev_to_dmarginal (maybe called in update_ess) extracts the right evidence.
if t > 1
  marginal.domain = nodes+(t-2)*engine.slice_size;
end
assert(~add_ev);


function RunningOneMicrostructureVademecum

%dSmooth = obtainSettings('SquareMesh4b','Rectangle');
dSmooth = obtainSettings('SmallCircleQ2','SmoothRectangle');

vc = VademecumCellVariablesCalculator(dSmooth);
vc.computeVademecumData()

end

function d = obtainSettings(prefix,freeFemFile)
d = SettingsVademecumCellVariablesCalculator();
d.freeFemFileName = freeFemFile;
d.fileName   = prefix;
d.mxMin = 0.1;
d.mxMax = 0.1;
d.myMin = 0.1;
d.myMax = 0.1;
d.nMx   = 1;
d.nMy   = 1;
d.outPutPath = [];
d.print = true;

%i = 4;
%d.freeFemSettings.hMax  = 10^(-1)/(2^(i - 1));%0.0025;

d.freeFemSettings.hMax  = 0.02;%0.0025;

%d.smoothingExponentSettings.type = 'Optimal';

d.smoothingExponentSettings.type = 'Given';
d.smoothingExponentSettings.q = 2;

end


function ELF(option, up)
%ELF eliminates very low frequencies from resampled respiratory
% signals.
%	            ELF(option, up)
%
%	Inputs:
%		option          the option which has led to this function being used
%       up              universal parameters structure
%

fprintf('\n--- Eliminating VLFs ');
wave_type = option(1:3);

for subj = up.paramSet.subj_list
    %% Skip if this processing has been done previously
    log_int_respSig = 0;             % Has value 1 unless this is a final respiratory signal
    iden_resp_sig_file_ending
    savepath = [up.paths.data_save_folder, num2str(subj), ending];
    log_int_respSig = 1;             % Has value 1 unless this is a final respiratory signal
    iden_resp_sig_file_ending
    initloadpath = [up.paths.data_save_folder, num2str(subj), ending];
    filecontents = whos('-file', initloadpath);
    var_names = extractfield(filecontents, 'name');
    rel_log = zeros(size(var_names));
    for s = 1 : length(var_names)
        if strfind(var_names{s}, [option(1:3), up.paths.filenames.resampler])
            rel_log(s) = 1;
        end
    end
    rel_var_names = var_names(logical(rel_log));
    for rel_var_name_no = 1 : length(rel_var_names)
        eval(['save_name = ''' option(1:3), up.paths.filenames.elim_vlf2, rel_var_names{rel_var_name_no}(4:end) ''';']);
        exist_log = check_exists(savepath, save_name);
        if exist_log
            continue
        end

        %% Load relevant data
        rel_name = rel_var_names{rel_var_name_no};
        loadpath = [up.paths.data_save_folder, num2str(subj), up.paths.filenames.int_respSigs];
        load(loadpath, rel_name);
        eval(['old_data = ' rel_name ';']);

        %% Eliminate VLFs
        data.hpfilt.t = old_data.t;
        try
            data.hpfilt.v = elim_vlfs(old_data, up);
        catch
            % if there aren't enough points to use the filter, simply carry forward the previous data
            data.hpfilt.v = old_data.v;
        end
        data.hpfilt.fs = old_data.fs;
        eval([save_name ' = data.hpfilt;']);

        %% Save processed data
        save_or_append_data
    end
end

end


function [grad, roiCoords, view] = checkSpatialGradMap(view, scan, roi, preserveCoords);
%
% [grad, roiCoords, view] = checkSpatialGradMap(view, [scan=1], [roi], [preserveCoords=0]);
%
% Get a spatial gradient map for detrending purposes, loading and/or
% computing in the view as needed. Returns a gradient matrix (size
% is dataSize(view)) for the selected scan.
%
% If an ROI is specified (see tc_roiStruct for the ways to specify), will
% also return a 3xN set of coordinates into the gradient map corresponding
% to the ROI, appropriate for the current view. The roiCoords are intended
% for use with er_preporcessTSeries.
%
% ras, 02/2007
if notDefined('view'),      view = getCurView;          end
if notDefined('scan'),      scan = view.curScan;        end
if notDefined('preserveCoords'), preserveCoords = 0;    end

grad = [];
roiCoords = [];

if ~isfield(view, 'spatialGrad') | isempty(view.spatialGrad)
    % load and/or compute
    mapPath = fullfile(dataDir(view), 'spatialGrad.mat');
    if ~exist(mapPath, 'file')  % offer to compute it
        q = ['The inomogeity correction flag is set to use the spatial ' ...
             'gradient map (inhomoCorrect=3). This map is not found. ' ...
             'Compute it now? '];
        resp = questdlg(q);
        if ~isequal(resp, 'Yes')
            error('Aborted--no spatial gradient map.')
        end
        view = computeSpatialGradient(view);
    end

    view = loadSpatialGradient(view);

    % ensure the loaded spatial grad map propagates back
    % to the base workspace (global variable):
    updateGlobal(view);
end

grad = view.spatialGrad{scan};

if exist('roi', 'var') & ~isempty(roi)
    % get map coordinates for the ROI
    roi = tc_roiStruct(view, roi);

    if preserveCoords==0
       subCoords = roiSubCoords(view, roi.coords);
    else
       subCoords = roi.coords;
    end
    [indices roiCoords] = roiIndices(view, subCoords, preserveCoords);

    % for volume/gray views, we want the indices and not coords
    % for the map (which is size 1 x nIndices). Mock up a 3xN
    % coords array, in which the columns reflec the indices into the map:
    if ismember(view.viewType, {'Volume' 'Gray'})
        roiCoords = ones(3, size(indices,2));
        roiCoords(2,:) = indices;
    end
end

return


function [TorF, vstr, rdate] = have_feature_sdp_pf()
%HAVE_FEATURE_SDP_PF  Detect availability/version info for SDP_PF
%
%   Feature detection function implementing 'sdp_pf' tag for HAVE_FEATURE
%   to detect availability/version of SDP_PF, a MATPOWER extension for
%   applications of semi-definite programming relaxations of power flow
%   equations (https://github.com/MATPOWER/mx-sdp_pf/).
%
%   See also HAVE_FEATURE.

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

TorF = have_feature('yalmip') && exist('mpoption_info_sdp_pf', 'file') == 2;
if TorF
    v = sdp_pf_ver('all');
    vstr = v.Version;
    rdate = v.Date;
else
    vstr = '';
    rdate = '';
end


% --------------------------------------------------------
% ObjectNet3D
% Copyright (c) 2016 CVGL Stanford University
% Licensed under The MIT License [see LICENSE for details]
% Written by Yu Xiang
% --------------------------------------------------------
% display CAD model and anchor points
% example: draw_cad('car', 1)
function draw_cad(cls, index)

opt = globals();

% load mat file
filename = fullfile(opt.root, sprintf('CAD/mat/%s.mat', cls));
object = load(filename);
cads = object.(cls);
cad = cads(index);

% display mesh
trimesh(cad.faces, cad.vertices(:,1), cad.vertices(:,2), cad.vertices(:,3), 'EdgeColor', 'b');
axis equal;
hold on;

% display anchor points
pnames = cad.pnames;
for i = 1:numel(pnames)
    X = cad.(pnames{i});
    if isempty(X) == 0
        plot3(X(1), X(2), X(3), 'ro', 'LineWidth', 5);
    end
end


function varargout = mldivide(N, rhs, varargin)
%\    MLDIVIDE   Solve CHEBOP BVP or IVP system.
%
% MLDIVIDE is a convenient wrapper for CHEBOP/SOLVEBVP and CHEBOP/SOLVEIVP. It
% calls the appropriate method, depending on whether the problem being solved is
% a boundary-value problem, or an initial/final-value problem. Problems,
% specified by a CHEBOP N are determined to be a boundary-value or
% initial/final-value problems as follows:
%   * If N.LBC is non-empty, but both N.RBC and N.BC are empty, it's considered
%     to be an initial-value problem. In this case, CHEBOP/SOLVEIVP is called.
%   * If N.RBC is non-empty, but both N.LBC and N.BC are empty, it's considered
%     to be a final-value problem. In this case, CHEBOP/SOLVEIVP is called.
%   * Otherwise, the problem is considered to be a boundary-value problem. In
%     this case, CHEBOP/SOLVEBVP is called.
%
% See the documentation of the corresponding methods for further details.
%
% See also CHEBOP/SOLVEBVP, CHEBOP/SOLVEIVP.

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

% Are we dealing with an initial or a final value problem. In that case, either
% we have
%   - N.LBC is nonempty, but both N.RBC and N.BC are empty. Here, we are dealing
%     with an initial value problem, where all conditions are imposed via N.LBC.
%   - N.RBC is nonempty, but both N.LBC and N.BC are empty. Here, we are dealing
%     with a final value problem, where all conditions are imposed via N.RBC.
isIVP =  ( ~isempty(N.lbc) && isempty(N.rbc) && isempty(N.bc) ) || ...
     ( isempty(N.lbc) && ~isempty(N.rbc) && isempty(N.bc) );

% If we did not get preferences passed in, we need to create a cheboppref so
% that we know wheter we want to solve the IVP via time-stepping or globally:
if ( nargin < 3 )
    pref = cheboppref();
else
    pref = varargin{1};
end

% Look at what solver we're using for IVPs:
ivpSolver = func2str(pref.ivpSolver);

% If we are solving an IVP, and we've specified one of the MATLAB solvers
% (ode113, ode15s, ode45) as our choice, call the solveivp method. Otherwise,
% solve problems globally:
if ( isIVP && ~isempty(strfind(ivpSolver, 'chebfun.ode')) )
    % Pass PREF here, as we'd have to start by constructing a CHEBOPPREF anyway
    % that start of solveivp otherwise.
    [varargout{1:nargout}] = solveivp(N, rhs, pref, varargin{:});
else
    % We have conditions in other fields, or we want to solve IVPs globablly,
    % call CHEBOP/SOLVEBVP. However, here, we don't want to pass PREF if it
    % wasn't included in VARARGIN, as that'd mean we couldn't to an automatic
    % switch to Fourier methods in the periodic case (i.e. change the
    % discretization to TRIGTECH).
    [varargout{1:nargout}] = solvebvp(N, rhs, varargin{:});
end

end


function main_cartpole_closedloop
close all;

T = 3;
N = 60;

solver = ocl.acados.Solver( ...
  T, ...
  'vars', @ocl.examples.cartpole.vars, ...
  'dae', @ocl.examples.cartpole.dae, ...
  'pathcosts', @ocl.examples.cartpole.pathcosts, ...
  'terminalcost', @ocl.examples.cartpole.terminalcost, ...
  'N', N, 'verbose', false);

solver.setInitialState('p', 0);
solver.setInitialState('v', 0);
solver.setInitialState('theta', 0);
solver.setInitialState('omega', 0);

solver.initialize('theta', [0 1], [0 0]);

solver.solve();

x0 = [0;0;0;0];

sim = ocl.Simulator(@ocl.examples.cartpole.vars, @ocl.examples.cartpole.dae);
sim.reset(x0);

draw_handles = ocl.examples.cartpole.draw_prepare(x0(1), x0(2), 0.8, 6);

% log window
log_fig = figure('menubar', 'none');
log_window = uicontrol(log_fig, 'Style', 'listbox', ...
  'Units',    'normalized', ...
  'Position', [0,0,1,1]);

data = struct;
data.T = T;
data.dt = T/N;
data.draw_handles = draw_handles;
data.t = 0;
data.current_state = x0;
data.force = {};

% control loop
control_timer = timer('TimerFcn', @(t,d) controller(t, d, solver, sim, log_window), ...
  'ExecutionMode', 'fixedRate', 'Period', data.dt, 'UserData', data);

start(control_timer);
cli(control_timer);
stop(control_timer);

end

function controller(t, ~, solver, sim, log_window)

dt = t.UserData.dt;
draw_handles = t.UserData.draw_handles;
time = t.UserData.t;
current_state = t.UserData.current_state;

solver.setInitialState('p', current_state(1));
solver.setInitialState('theta', current_state(2));
solver.setInitialState('v', current_state(3));
solver.setInitialState('omega', current_state(4));

[sol,~] = solver.solve();

u = sol.controls.F.value;

sim.current_state = current_state;

force = 0;
if ~isempty(t.UserData.force)
  force = t.UserData.force{end};
  t.UserData.force(end) = [];
end

x = sim.step(u(1) + force, dt);
x = x.value;

if abs(x(1)) > 6
  sim.current_state = [0;0;0;0];
  solver.initialize('p', [0 1], [0 0]);
  solver.initialize('theta', [0 1], [0 0]);
  solver.initialize('v', [0 1], [0 0]);
  solver.initialize('omega', [0 1], [0 0]);
  solver.initialize('F', [0 1], [0 0]);
end

% draw
ocl.examples.cartpole.draw(draw_handles, time, x, 0.8);

lines = splitlines(solver.stats());
set(log_window, 'String', lines);
drawnow

t.UserData.sol = sol;
t.UserData.t = time + dt;
t.UserData.current_state = sim.current_state;

end

function cli(t)

  cli_info = [newline, 'You are now in the command line interface. ', newline, ...
    'You can make use of ', ...
    'the following commands:', newline, newline, ...
    'q: quits the program', newline, ...
    'f: applies a force of 30N', newline, ...
    '<number>:  applies a force of <number> Newton', newline];

  disp(cli_info);

  terminated = false;
  while ~terminated
    m = input('  cli >>', 's');

    if strcmp(m, 'q') || strcmp(m, 'x') || strcmp(m, 'c')
      disp('exiting...')
      stop(t);
      terminated = true;
    elseif strcmp(m, 'f')
      disp('force!!')
      t.UserData.force{end+1} = 30*sign(rand-0.5);
    elseif ~isnan(str2double(m))
      F = str2double(m);
      disp(['force ', m, '!!!']);
      t.UserData.force{end+1} = F*sign(rand-0.5);
    else
      disp('Command not recognized!')
      disp(cli_info);
    end
  end

end


classdef AbstractHomogenizedTensorPrinter < CompositeResultsPrinter

    properties (Access = protected)
        nstre
    end

    methods (Access = protected)

        function storeFieldsToPrint(obj,d)
            obj.storeMicroProblemsFields(d);
          %  obj.storeRegularizedDensity(d);
        end

        function createPrinters(obj,d)
            obj.printers        = obj.createMicroProblemsPrinters(d);
          %  obj.printers{end+1} = obj.createRegularizedDensityPrinter(d);
        end

        function computeNstre(obj,ndim)
            if ndim == 2
                obj.nstre = 3;
            elseif ndim == 3
                obj.nstre = 6;
            end
        end

    end

    methods (Access = private)

        function p = createMicroProblemsPrinters(obj,d)
            for istre = 1:obj.nstre
                p{istre} = ResultsPrinter.create('ElasticityMicro',d);
                obj.printers{istre} = p;
            end
        end

        function p = createRegularizedDensityPrinter(obj,d)
            p = ResultsPrinter.create('DensityGauss',d);
        end

        function storeRegularizedDensity(obj,d)
            d.fields = d.regDensity;
            obj.printers{obj.nstre+1}.storeFieldsToPrint(d);
        end

    end

    methods (Access = protected, Abstract)
       storeMicroProblemsFields(obj)
    end

end


function res = isFeasible(route,model)
    len = length(route);
    if route(1)>model.city||route(len)>model.city
        res = 0; return
    end

    for i = 2:len
        if route(i)>model.city && route(i-1)>model.city  % not use all vehicles
            res = 0; return
        end
    end

    res = 1;
end