function Nodes = traverseGrid(Nodes, Edges, verbose)
%% Traverse the color grid graph to find the neighbors of each Node

%% License
% ACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY
% Copyright (c) 2018 Bingyao Huang
% All rights reserved.

% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:

% The above copyright notice and this permission notice shall be included in all
% copies or substantial portions of the Software.

% If you publish results obtained using this software, please cite our paper.

% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
% SOFTWARE.

%%

if(nargin < 3)
    verbose = 0;
end

%% create the ajacency matrix and graph from Edges and Nodes
numNodes = numel(Nodes);
numEdges = numel(Edges);

A = zeros(numNodes, numNodes); % for both horizontal and vertical
% hA = zeros(numNodes, numNodes); % for horizontal only

for i = 1:numEdges
    curEdge = Edges(i);

    if (numel(curEdge.nodes) == 2)% ignore end point and end edge
        edgeLength = numel(curEdge.PixelIdxList);
        A(curEdge.nodes(1), curEdge.nodes(2)) = edgeLength;
        A(curEdge.nodes(2), curEdge.nodes(1)) = edgeLength;
%         if(curEdge.isH)
%             hA(curEdge.nodes(1), curEdge.nodes(2)) = edgeLength;
%             hA(curEdge.nodes(2), curEdge.nodes(1)) = edgeLength;
%         end
    end
end

% vA = A - hA; % for vertical only

% create a graph object of ajacency matrix
% then we can use all the functions in http://www.mathworks.com/help/matlab/ref/graph-object.html
G = graph(A);

%% Traverse
[Nodes.neighbor] = deal([]);
[Nodes.N] = deal([-1]);
[Nodes.S] = deal([-1]);
[Nodes.W] = deal([-1]);
[Nodes.E] = deal([-1]);
[Nodes.error] = deal([]);

for i =1:numNodes
    myRow = Nodes(i).Centroid(2);
    myCol = Nodes(i).Centroid(1);
    neighborNodes = neighbors(G, i);
    Nodes(i).neighbor = neighborNodes;

    numNeighbors = numel(neighborNodes);
    count = 0;
    for j = 1:numNeighbors
        curNode = neighborNodes(j);
        row = Nodes(curNode).Centroid(2);
        col = Nodes(curNode).Centroid(1);

        rowDiff = abs(row - myRow);
        colDiff = abs(col - myCol);
        flag = rowDiff >= colDiff;

        if(myRow >= row && flag)
            if(Nodes(i).N < 0)
                Nodes(i).N = curNode;
                count= count+1;
            end
        elseif(myRow <= row && flag)
            if(Nodes(i).S < 0)
                Nodes(i).S = curNode;
                count= count+1;
            end
        elseif(myCol <= col)
            if(Nodes(i).E < 0)
                Nodes(i).E = curNode;
                count= count+1;
            end
        elseif(myCol >= col)
            if(Nodes(i).W < 0)
                Nodes(i).W = curNode;
                count= count+1;
            end
        end
    end

    if(count ~= numNeighbors)
        Nodes(i).error = 1;
    end
end

%% double check if we have unmatched neighbors
for i =1:numNodes
    N = Nodes(i).N;
    S = Nodes(i).S;
    W = Nodes(i).W;
    E = Nodes(i).E;

    if(N > 0)
        if(Nodes(N).S ~= i)
            Nodes(N).error = i;
            Nodes(i).error = N;
        end
    end

    if(S > 0)
        if(Nodes(S).N ~= i)
            Nodes(S).error = i;
            Nodes(i).error = S;
        end
    end

    if(W > 0)
        if(Nodes(W).E ~= i)
            Nodes(W).error = i;
            Nodes(i).error = W;
        end
    end

    if(E > 0)
        if(Nodes(E).W ~= i)
            Nodes(E).error = i;
            Nodes(i).error = E;
        end
    end
end

errorNodes = [Nodes.error];
if(verbose)
    disp(['Get ', num2str(nnz(errorNodes)), ' error nodes during traverse'])
end
end


%% lighten underlay volume - for white background
function Z = lighten_underlay_edges(Z, maxpercent)

Zi = Z(:);

mindat = min(Zi);
maxdat = max(Zi);

Z(Z == mindat) = maxdat;

% higher ending values of k will be more 'softening'; lower =
% more dark edges

myprctiles = prctile(Zi, [0:1:maxpercent]); % speed up!!

for k = 1:maxpercent % for each of the darkest/lowest-value percentiles

    w = 1 - k/100; % weights, for wtd average of orig and inverted, 1 is all inverted
    % (bilinear weighting)

    %isdark = Zi < prctile(Zi, k) & Zi >= prctile(Zi, k - 1);
    isdark = Zi < myprctiles(k + 1) & Zi >= myprctiles(k);

    Z(isdark) = maxdat;

    %Z(isdark) = w .* (maxdat) + (1 - w) .* Z(isdark);

end % the weight value loop

end


% EEG_MATCHCHANS  - find closest channels in a larger EEGLAB chanlocs structure
%                     to channels in a smaller chanlocs structure
% Usage:
%        >> [selchans,distances,selocs] = eeg_matchchans(BIGlocs,smalllocs,'noplot');
% Inputs:
%        BIGlocs    - larger (or equal-sized) EEG.chanlocs structure array
%        smalllocs  - smaller (or equal-sized) EEG.chanlocs structure array
% Optional inputs:
%        'noplot'   - [optional string 'noplot'] -> do not produce plots {default:
%                     produce illustrative plots of the BIG and small locations}
% Outputs:
%        selchans   - indices of BIGlocs channels closest to the smalllocs channels
%        distances  - vector of distances between the selected BIGlocs and smalllocs chans
%        selocs     - EEG.chanlocs structure array containing nearest BIGlocs channels
%                     to each smalllocs channel: 1, 2, 3,... n. This structure has
%                     two extra fields:
%                                    bigchan  - original channel index in BIGlocs
%                                    bigdist  - distance between bigchan and smalllocs chan
%                     ==> bigdist assumes both input locs have sph_radius 1.
%
% Author: Scott Makeig, SCCN/INC/UCSD, April 9, 2004

% Copyright (C) 2004 Scott Makeig, SCCN/INC/UCSD, smakeig@ucsd.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

% History: began Jan 27, 2004 as selectchans.m(?) -sm

function [selchans,dists,selocs] = eeg_matchchans(bglocs,ltlocs,noplot)

if nargin < 2
  help eeg_matchchans
  return
end
no_plot = 0; % yes|no flag
if nargin > 2 && strcmp(lower(noplot),'noplot')
  no_plot = 1;
end

if ~isstruct(bglocs) || ~isstruct(ltlocs)
   help eeg_matchchans
end

ltchans = length(ltlocs);
bgchans = length(bglocs);
if ltchans > bgchans
  fprintf('BIGlocs chans (%d) < smalllocs chans (%d)\n',bgchans,ltchans);
  return
end
selchans = zeros(ltchans,1);
dists    = zeros(ltchans,1);
bd       = zeros(bgchans,1);
%
%%%%%%%%%%%%%%%%% Compute the distances %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
fprintf('BIG  ltl  Dist\n');
for c=1:ltchans
   for C=1:bgchans
      if ~isempty(ltlocs(c).X) && ~isempty(bglocs(C).X)
        bd(C) = sqrt((ltlocs(c).X/ltlocs(c).sph_radius - bglocs(C).X/bglocs(C).sph_radius)^2 + ...
                    (ltlocs(c).Y/ltlocs(c).sph_radius - bglocs(C).Y/bglocs(C).sph_radius)^2 + ...
                    (ltlocs(c).Z/ltlocs(c).sph_radius - bglocs(C).Z/bglocs(C).sph_radius)^2);
      end
   end
   %
   %%%%%%%%%%%%%%%%% Find the nearest BIGlocs channel %%%%%%%%%%%%%%%%%%%%%%%
   %
   [bd ix] = sort(bd); % find smallest distance c <-> C
   bglocs(1).bigchan = [];
   k=1;
   while ~isempty(bglocs(ix(k)).bigchan) & k<=bgchans % avoid empty channels
     k=k+1;
   end
   if k>bgchans
     fprintf('No match found for smalllocs channel %d - error!?\n',c);
     return % give up - should not reach here!
   end
   while k<length(ix)
     if c>1 && sum(ismember(ix(k),selchans(1:c-1)))>0 % avoid chans already chosen
        k = k+1;
     else
        break
     end
   end
   if k==length(ix)
      fprintf('NO available nearby channel for littlechan %d - using %d\n',...
                  c,ix(k));
   end
   selchans(c) = ix(k); % note the nearest BIGlocs channel
   dists(c)    = bd(k); % note its distance
   bglocs(ix(k)).bigchan = selchans(c); % add this info to the output
   bglocs(ix(k)).bigdist = dists(c);
   fprintf('.bigchan %4d, c %4d, k %d, .bigdist  %3.2f\n',...
        bglocs(ix(k)).bigchan,c,k,bglocs(ix(k)).bigdist); % commandline printout
end; % c
selocs = bglocs(selchans); % return the selected BIGlocs struct array subset
%
%%%%%%%%%%%%%%%%% Plot the results %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
if ~no_plot
    figure;
    titlestring = sprintf('%d-channel subset closest to %d channel locations',ltchans,bgchans);
    tl=textsc(titlestring,'title');
    set(tl,'fontweight','bold');
    set(tl,'fontsize',15);
    sbplot(7,2,[3 13]);
    hist(dists,length(dists));
    title('Distances between corresponding channels');
    xlabel('Euclidian distance (sph. rad. 1)');
    ylabel('Number of channels');

    sbplot(7,5,[8,35]);
    topoplot(dists,selocs,'electrodes','numbers','style','both');
    title('Distances');
    clen = size(colormap,1);
    sbnull = sbplot(7,2,[10 12])
    cb=cbar;
    cbar(cb,[clen/2+1:clen]);
    set(sbnull,'visible','off')

    axcopy; % turn on axcopy
end


function moveSensor(speed, rot_punkt, tot_rot, theta, patch)

    n_patch = length(patch);

    % Loop through all sensors
    for i = 1:n_patch

        Points = get(patch(i),'Vertices');
        r = ones(size(Points));
        r = [speed*cos(tot_rot)*r(:,1), speed*sin(tot_rot)*r(:,2)] + Points(:,1:2);
        set(patch(i), 'XData', r(:,1), 'YData', r(:,2));
        rotate(patch(i),[0,0,1], theta*180/pi, [rot_punkt,0]);
    end

end


function [label,depth] = RenderPCcameraMatlab(XYZ,RGB,XYZedges,RGBedges,K, Rt,width, height)

% XYZ should be 3*N double
% RGB should be 3*N uint8

%mex WarpMesh.cpp -lGLU -lOSMesa
%load debug.mat

if ~isempty(XYZ)
    XYZ = double(XYZ);
    XYZ = transformPointCloud(XYZ,Rt);
    XYZ(1,:) = -XYZ(1,:);
end

if ~isempty(XYZedges)
    XYZedges = double(XYZedges);
    XYZedges = transformPointCloud(XYZedges,Rt);
    XYZedges(1,:) = -XYZedges(1,:);
end

%{
figure(5); clf;
plot3(X(1,:),X(2,:),X(3,:),'.');
axis equal;
grid on;
xlabel('x');
ylabel('y');
zlabel('z');
set(gca,'ZDir','reverse');
set(gca,'YDir','reverse');
%}
P = [K [0;0;0]];
[label,depth]=RenderPCcamera(P,width,height,XYZ,RGB,XYZedges,RGBedges);

%{

% to deal with camera coodinate system
%XYZcamera(:,:,1) = -XYZcamera(:,:,1);
%P = K * Rt;
%P = P * [-1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1];

%P = Rt;

XYZcamera(:,:,2) = -XYZcamera(:,:,2);
XYZcamera(:,:,3) = -XYZcamera(:,:,3);

F = [1 0 0 ; 0 -1 0; 0 0 -1];

P = [ F*Rt(:,1:3)*inv(F) F*Rt(:,4)];
%P = Rt; % * [1 0 0 0; 0 -1 0 0; 0 0 -1 0; 0 0 0 1];

%{
XYZcamera(:,:,2) = -XYZcamera(:,:,2);
XYZcamera(:,:,3) = -XYZcamera(:,:,3);
P = [1 0 0 0; 0 -1 0 0; 0 0 -1 0; 0 0 0 1] * [Rt; 0 0 0 1] * [1 0 0 0; 0 -1 0 0; 0 0 -1 0; 0 0 0 1];
P = P(1:3,:);
%}

good = XYZcamera(:,:,4)~=0;
good = good(:);

X = reshape(XYZcamera,[],4)';
X = X(1:3,good);

figure(5); clf;
plot3(X(1,:),X(2,:),X(3,:),'.');
axis equal;
grid on;
xlabel('x');
ylabel('y');
zlabel('z');
set(gca,'ZDir','reverse');
set(gca,'YDir','reverse');

X = transformPointCloud(X,P);

figure(3);clf;
plot3(X(1,:),X(2,:),X(3,:),'.');
axis equal;
grid on;
xlabel('x');
ylabel('y');
zlabel('z');
set(gca,'ZDir','reverse');
set(gca,'YDir','reverse');

figure(4);clf;
x= K*X;
x = [x(1,:)./x(3,:); x(2,:)./x(3,:)];
plot(x(1,:),x(2,:),'.')
axis equal
set(gca,'YDir','reverse');
hold on;
plot([1 640 640 1 1],[1 1 480 480 1],'-r');

P = K * P;

%{
XYZcamera(:,:,2) = -XYZcamera(:,:,2);
XYZcamera(:,:,3) = -XYZcamera(:,:,3);
%P = P * [1 0 0 0; 0 -1 0 0; 0 0 -1 0; 0 0 0 1];
Rt(2,4) = -Rt(2,4);
Rt(3,4) = -Rt(3,4);
P = K * Rt;
%}

[label,depth]=WarpMesh(P,640,480,XYZcamera);

%}

label = label';
label = label(:,end:-1:1);
%figure
%imagesc(label)

label = double(label);

B = mod(label,256);
G = mod(floor(label/256),256);
R = floor(label/(256*256));

clear label;
label(:,:,1) = R;
label(:,:,2) = G;
label(:,:,3) = B;
label = uint8(label);

depth = depth';
depth = depth(end:-1:1,end:-1:1);

if ~any(label(:))
    depth = single(zeros(size(depth)));
    return
end

z_near = 0.3;
z_far_ratio = 1.2;
depth = z_near./(1-single(depth)/2^32);
maxDepth = max(depth(abs(depth) < 100));

cropmask = (depth < z_near) | (depth > z_far_ratio * maxDepth);
depth(cropmask) = 0; %NaN;%z_far_ratio * maxDepth;

%figure
%imagesc(depth)


function g = scd_display_qspacedata3D(data,scheme,fibredir,Marker,Linestyle,color,noise)
% scd_display_qspacedata(data,scheme,fibredir)
% data: vector OR NxM matrix. N: number of measurement (=size(scheme,1)). M: number of
%      observation (for error bars).
% EXAMPLE:
%       SCD_DISPLAY_QSPACEDATA(Smodel,Ax.scheme)
%       SCD_DISPLAY_QSPACEDATA(Smodel,Ax.scheme,0,'x','-')

if ~exist('Marker','var'), Marker='x'; end
if ~exist('Linestyle','var'), Linestyle='none'; end

Gparr=scheme(:,1:3)*fibredir(:);
absc = Gparr;
[absc,II] = sort(absc); scheme = scheme(II,:); data = data(II);
bval = scd_scheme_bvalue(scheme);

if size(scheme,2)<9
    % Find different shells
    list_G=unique(round(scheme(:,[4 5 6 7])*1e8)/1e8,'rows');
    nnn = size(list_G,1);
    for j = 1 : nnn
        for i = 1 : size(scheme,1)
            if  round(scheme(i,[4 5 6 7])*1e8)/1e8 == list_G(j,:)
                scheme(i,9) = j;
            end
        end
    end
end

seq=unique(scheme(:,9)); ND=length(seq);
if ~exist('color','var')
    color=jet(ND);
end

for iD=1:ND
    seqiD=find(scheme(:,9)==seq(iD));

    datavoxel=mean(squeeze(data),2);

    g(iD)=plot(absc(seqiD,:),datavoxel(seqiD),'LineStyle',Linestyle, 'Marker',Marker,'Color',color(min(iD,end),:),'LineWidth',2);

    if ~moxunit_util_platform_is_octave
        hold on
        set(g(iD),'DisplayName',['bvalue=' num2str(max(bval(seqiD))*1e3,'%.0f') 's/mm^2 G=' num2str(max(scheme(seqiD,4))*1e6,'%.0f') 'mT/m \Delta=' num2str(mean(scheme(seqiD,5)),'%.0f') 'ms \delta=' num2str(mean(scheme(seqiD,6)),'%.0f') 'ms TE=' num2str(mean(scheme(seqiD,7)),'%.0f') 'ms']);
    end

    if exist('noise','var')==1

        h(iD)=errorbar(absc(seqiD),datavoxel(seqiD),noise(seqiD), 'xr', 'Color', color);
    elseif size(data,2)>1
        data_stdvoxel=std(data,0,2);
        h(iD)=errorbar(absc(seqiD),datavoxel(seqiD),data_stdvoxel(seqiD), 'xr', 'Color', color);
        %         figure(3)
        %         d(iD)=plot(q(seqiD),data_stdvoxel(seqiD),'LineStyle','none', 'Marker','x','Color',color,'LineWidth',2);
        %         hold on
    end
    if exist('h','var')==1
        % don't display data legend
        if ~moxunit_util_platform_is_octave
            hAnnotation = get(h(iD),'Annotation');
            hLegendEntry = get(hAnnotation','LegendInformation');
            set(hLegendEntry,'IconDisplayStyle','off');
        end
    end
end

if ~moxunit_util_platform_is_octave
    xlabel('G_{//}/|G|','FontSize',15);
    ylabel('Signal','FontSize',15);
    legend('show','Location','Best')
    set(gca,'FontSize',15)
    %ylim([0 1.2])
    grid on, box off
    hold off
end

% Add legend about linestyle
switch Linestyle
    case 'none'
        switch Marker
            case 'o'
                txt = [Marker ' = simulated data'];
                pos = [0.25, 0.97];
            case 'x'
                txt = [Marker ' = noisy simulated data'];
                pos = [0.5, 0.97];
        end
    otherwise
        txt = [Linestyle ' = fit'];
        pos = [0.75, 0.97];
end
t = text(pos(1),pos(2),txt,'Units','normalized');

if ~moxunit_util_platform_is_octave
    set(t,'FontSize',10);
    set(t,'BackgroundColor',[0.9  0.9 0.9]);
end

end


function hypercube_integrals_test ( )

%*****************************************************************************80
%
%% HYPERCUBE_INTEGRALS_TEST tests the HYPERCUBE_INTEGRALS library.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 January 2014
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'HYPERCUBE_INTEGRALS_TEST\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Test the HYPERCUBE_INTEGRALS library.\n' );

  hypercube_integrals_test01 ( );
  hypercube_integrals_test02 ( );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'HYPERCUBE_INTEGRALS_TEST\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end


function display(SO3F,varargin)
% called by standard output

if ~check_option(varargin,'skipHeader')
  displayClass(SO3F,inputname(1),[],'moreInfo',symChar(SO3F),varargin{:});
  if SO3F.antipodal, disp('  antipodal: true'); end
  disp(' ');
end

if SO3F.c0 ~= 0
  disp('  uniform component');
  disp(['  weight: ',xnum2str(SO3F.c0)]);

  disp(' ');
end

if ~isempty(SO3F.center)

  if length(SO3F.center)==1
    disp('  unimodal component');
  else
    disp('  multimodal components');
  end
  disp(['  kernel: ',char(SO3F.psi)]);
  if isa(SO3F.center,'SO3Grid')
    disp(['  center: ',char(SO3F.center)]);
    disp(['  weight: ',xnum2str(sum(SO3F.weights(:)))]);
    disp(' ');
  else
    disp(['  center: ',num2str(length(SO3F.center)), ' orientations']);
    s.weight = SO3F.weights(:);

    if length(SO3F.center) < 20 && ~isempty(SO3F.center)
       Euler(SO3F.center,s)
    elseif ~getMTEXpref('generatingHelpMode')
      disp(' ')
      s = setappdata(0,'data2beDisplayed',SO3F.center);
      setappdata(0,'data2beDisplayedWeights',s);
      disp(['  show centers of the components and corresponding weights'])
      disp(' ')
    end

  end
end

end


function level = thresh_tool(im,cmap)
%THRESH_TOOL - GUI tool for selecting threshold level
%
%  Example 1 - nonblocking behavior:
%    x=imread('rice.png');
%    thresh_tool(x) %no return value, so MATLAB keeps running
%
%  Example 2 - blocking behavior:
%    x=imread('rice.png');
%    lev=thresh_tool(x) %MATLAB waits for GUI tool to finish first

% Copyright 2004-2010 The MathWorks, Inc.

max_colors=1000;    %practical limit

%calculate bins centers
color_range = double(limits(im));
if isinteger(im)
  %try direct indices first
  num_colors=diff(color_range)+1;
  if num_colors<max_colors %okay
    di=1;                               %inherent bins
  else %too many levels
    num_colors=max_colors;                  %practical limit
    di=diff(color_range)/(num_colors-1);
  end
else %noninteger
  %try infering discrete resolution first (intensities often quantized)
  di=min(diff(sort(unique(im(:)))));
  num_colors=diff(color_range)/di+1;
  if num_colors>max_colors %too many levels
    num_colors=max_colors;                  %practical limit
    di=diff(color_range)/(num_colors-1);
  end
end
bin_ctrs = [color_range(1):di:color_range(2)];
FmtSpec=['%.' num2str(ceil(-log10(di))) 'f'];

%new figure - interactive GUI tool for level segmenting
h_fig=figure;
if nargin>1 & isstr(cmap) & strmatch(lower(cmap),'gray')
  full_map=gray(num_colors);
else
  full_map=jet(num_colors);
end
setappdata(h_fig,'im',im)
setappdata(h_fig,'FmtSpec',FmtSpec)

%top left - input image
h_ax1=axes('unit','norm','pos',[0.05 0.35 0.4 0.60]);
subimage(im,full_map)
axis off, title('Input Image')

%top right - segmented (eventually)
h_ax2=axes('unit','norm','pos',[0.55 0.35 0.4 0.60]);
axis off
setappdata(h_fig,'h_ax2',h_ax2)

%next to bottom - intensity distribution
h_hist=axes('unit','norm','pos',[0.05 0.1 0.9 0.2]);

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% bin_ctrs=[0:double(max(im(:)))];
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

n=hist(double(im(:)),bin_ctrs);
bar(bin_ctrs,n)
axis([color_range limits(n(2:end))])
set(h_hist,'xtick',[],'ytick',[])
title('Intensity Distribution')

%very bottom - colorbar
h_cbar=axes('unit','norm','pos',[0.05 0.05 0.9 0.05],'tag','thresh_tool_cbar');
subimage(color_range,[0.5 1.5],1:num_colors,full_map)
set(h_cbar,'ytick',[],'xlim',color_range)
axis normal

%colorbar tick locations
set(h_cbar,'xtick',color_range)

%threshold level - initial guess (graythresh)
lo=double(color_range(1));
hi=double(color_range(2));
norm_im=(double(im)-lo)/(hi-lo);
norm_level=graythresh(norm_im);     %GRAYTHRESH assumes DOUBLE range [0,1]
my_level=norm_level*(hi-lo)+lo;

%display level as vertical line
axes(h_hist)
h_lev=vline(my_level,'-');
set(h_lev,'LineWidth',2,'color',0.5*[1 1 1],'UserData',my_level)
setappdata(h_fig,'h_lev',h_lev)

%attach draggable behavior for user to change level
move_vline(h_lev,@update_plot);

axes(h_cbar)
y_lim = get(h_cbar,'ylim');

% PLACE TEXT LOCATION ON COLORBAR (Laurens)
%h_text = text(my_level,mean(y_lim),num2str(round(my_level)));
h_text = text(my_level,mean(y_lim),'dummy','HorizontalAlignment','Center');
if nargin<2
  text_color=0.5*[1 1 1];
else
  text_color='m';
end
set(h_text,'FontWeight','Bold','color',text_color,'Tag','cbar_text')
movex_text(h_text,my_level)
%%%%%%%%%%%%%%%%%%%%%%%%

%segmented image
bw=(im>my_level);
axes(h_ax2)
hold on
subimage(bw), axis off, axis ij
hold off
title('Segmented')

update_plot

%add reset button (resort to initial guess)
h_reset = uicontrol('unit','norm','pos',[0.0 0.95 .1 .05]);
set(h_reset,'string','Reset','callback',@ResetOriginalLevel)

if nargout>0
  h_done=uicontrol('unit','norm','pos',[0.9 0.95 0.1 0.05]);
  set(h_done,'string','Done','callback',@DeleteDoneButton)
  set(h_fig,'WindowStyle','modal')
  waitfor(h_done)
  if ishandle(h_fig)
    h_lev=getappdata(gcf,'h_lev');
    level=mean(get(h_lev,'xdata'));
    delete(h_fig)
  else
    warning('User aborted; no return value.')
    level=[];
  end
end

function DeleteDoneButton(hObject,varargin)
delete(hObject)

function ResetOriginalLevel(hObject,varargin)
h_lev = getappdata(gcf,'h_lev');
init_level = get(h_lev,'UserData');
set(h_lev,'XData',init_level*[1 1])
text_obj = findobj('Type','Text','Tag','cbar_text');
movex_text(text_obj,init_level)
update_plot

function update_plot
im=getappdata(gcf,'im');
h_lev=getappdata(gcf,'h_lev');
my_level=mean(get(h_lev,'xdata'));
h_ax2=getappdata(gcf,'h_ax2');
h_im2=findobj(h_ax2,'type','image');
%segmented image
bw=(im>my_level);
rgb_version=repmat(double(bw),[1 1 3]);
set(h_im2,'cdata',rgb_version)


function k = kernCompute(kern, x, x2)

% KERNCOMPUTE Compute the kernel given the parameters and X.
% FORMAT
% DESC computes a kernel matrix for the given kernel type given an
% input data matrix.
% ARG kern : kernel structure to be computed.
% ARG X : input data matrix (rows are data points) to the kernel computation.
% RETURN K : computed elements of the kernel structure.
%
% FORMAT
% DESC computes a kernel matrix for the given kernel type given
% two input data matrices, one for the rows and one for the columns.
% ARG kern : kernel structure to be computed.
% ARG X : first input matrix to the kernel computation (forms the rows of the kernel).
% ARG X2 : second input matrix to the kernel computation (forms the columns of the kernel).
% RETURN K : computed elements of the kernel structure.
%
% SEEALSO : kernCreate, kernDiagCompute
%
% COPYRIGHT : Neil D. Lawrence, 2004, 2005, 2006

% KERN

fhandle = str2func([kern.type 'KernCompute']);
if nargin < 3
  k = fhandle(kern, x);
else
  k = fhandle(kern, x, x2);
end


function d=wtcenter(x);

%  WTCENTER Calculates the delay of filters for alignment.
%
%           WTCENTER (X) calculates the integer aproximation
%           of delay for filter X using the method set with
%           the WTMETHOD function, for alignment operations
%           in Wavelet transforms.
%
%           For a non integer value, use the CENTER function.
%
%           See also: WTMETHOD, CENTER, WT
%

%--------------------------------------------------------
% Copyright (C) 1994, 1995, 1996, by Universidad de Vigo
%
%
% Uvi_Wave is free software; you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% Free Software Foundation; either version 2, or (at your option) any
% later version.
%
% Uvi_Wave 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 Uvi_Wave; see the file COPYING.  If not, write to the Free
% Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
%
%       Author: Sergio J. Garcia Galan
%       e-mail: Uvi_Wave@tsc.uvigo.es
%--------------------------------------------------------

global WTCENTERMETHOD

if size(WTCENTERMETHOD)==[0,0]
	WTCENTERMETHOD=0;
end

if WTCENTERMETHOD>3 | WTCENTERMETHOD<0
	WTCENTERMETHOD=0
end

d=floor(center(x,WTCENTERMETHOD));

% (Another long function !!!)


function [features] = collect(conf, imgs, scale, filters, verbose)

if nargin < 5
    verbose = 0;
end

num_of_imgs = numel(imgs);
feature_cell = cell(num_of_imgs, 1); % contains images' features
num_of_features = 0;

if verbose
    fprintf('Collecting features from %d image(s) ', num_of_imgs)
end
feature_size = [];

h = [];
for i = 1:num_of_imgs
    h = progress(h, i / num_of_imgs, verbose);
    sz = size(imgs{i});
    if verbose
        fprintf(' [%d x %d]', sz(1), sz(2));
    end

    F = extract(conf, imgs{i}, scale, filters);
    num_of_features = num_of_features + size(F, 2);
    feature_cell{i} = F;

    assert(isempty(feature_size) || feature_size == size(F, 1), ...
        'Inconsistent feature size!')
    feature_size = size(F, 1);
end
if verbose
    fprintf('\nExtracted %d features (size: %d)\n', num_of_features, feature_size);
end
clear imgs % to save memory
features = zeros([feature_size num_of_features], 'single');
offset = 0;
for i = 1:num_of_imgs
    F = feature_cell{i};
    N = size(F, 2); % number of features in current cell
    features(:, (1:N) + offset) = F;
    offset = offset + N;
end


%
% Usage:  [Z [A,B]]=mexArchetypalAnalysis(X,param);
% Usage:  [Z [A,B]]=mexArchetypalAnalysis(X,Z,param);
%
% Name: mexArchetypalAnalysis
%
% Description: documentation to appear soon
%
% Inputs: X:  double m x n matrix   (input signals)
%               m is the signal size
%               n is the number of signals to decompose
% Output: Z: double %
%
% Author: Yuansi Chen and Julien Mairal, 2014


figure
subplot(2,2,1)
hold on
plot(vTime,100 * vAggregateTFP_full,'linewidth',1.5,'linestyle','-','color',[.03,.24,.8])
plot(vTime,100 * vAggregateTFP_reduced,'linewidth',1.5,'linestyle','--','color',[.8,.24,.03])
set(gcf,'color','w')
xlim([vTime(1) vTime(end)])
grid on
title('TFP','interpreter','latex','fontsize',14)
ylabel('$\%$ deviation from s.s.','interpreter','latex')
legend('Full model','Reduced model','location','northeast')
hold off

subplot(2,2,2)
hold on
plot(vTime,100 * vAggregateOutput_full,'linewidth',1.5,'linestyle','-','color',[.03,.24,.8])
plot(vTime,100 * vAggregateOutput_reduced,'linewidth',1.5,'linestyle','--','color',[.8,.24,.03])
set(gcf,'color','w')
xlim([vTime(1) vTime(end)])
grid on
title('Output','interpreter','latex','fontsize',14)
hold off

subplot(2,2,3)
hold on
plot(vTime,100 * vAggregateConsumption_full,'linewidth',1.5,'linestyle','-','color',[.03,.24,.8])
plot(vTime,100 * vAggregateConsumption_reduced,'linewidth',1.5,'linestyle','--','color',[.8,.24,.03])
set(gcf,'color','w')
xlim([vTime(1) vTime(end)])
grid on
title('Consumption','interpreter','latex','fontsize',14)
ylabel('$\%$ deviation from s.s.','interpreter','latex')
xlabel('Quarters','interpreter','latex')
hold off

subplot(2,2,4)
hold on
plot(vTime,100 * vAggregateInvestment_full,'linewidth',1.5,'linestyle','-','color',[.03,.24,.8])
plot(vTime,100 * vAggregateInvestment_reduced,'linewidth',1.5,'linestyle','--','color',[.8,.24,.03])
set(gcf,'color','w')
xlim([vTime(1) vTime(end)])
grid on
title('Investment','interpreter','latex','fontsize',14)
xlabel('Quarters','interpreter','latex')
hold off


% labels01 = (labelsPM+1)/2; % maps -1->0, +1->1
% labelsPM = (2*labels01)-1; % maps 0,1 -> -1,1


function calpak_test69 ( )

%*****************************************************************************80
%
%% CALPAK_TEST69 tests YMDF_DIF_COMMON.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 April 2013
%
%  Author:
%
%    John Burkardt
%
  dhi = 1;
  dlo = 1;
  fhi = 0.0;
  flo = 0.0;
  mhi = 1;
  mlo = 1;
  seed = 123456789;
  yhi = 1960;
  ylo = 1970;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'CALPAK_TEST69\n' );
  fprintf ( 1, '  YMDF_DIF_COMMON gets the day difference \n' );
  fprintf ( 1, '  between YMDF dates.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  YMDF1        YMDF2        (YMDF2 - YMDF1)\n' );
  fprintf ( 1, '\n' );

  for i = 1 : 10

    [ y1, m1, d1, f1, seed ] = ymdf_uniform_common ( ylo, mlo, dlo, flo, ...
      yhi, mhi, dhi, fhi, seed );

    s1 = ymdf_to_s_common ( y1, m1, d1, f1 );

    [ y2, m2, d2, f2, seed ] = ymdf_uniform_common ( ylo, mlo, dlo, flo, ...
      yhi, mhi, dhi, fhi, seed );

    s2 = ymdf_to_s_common ( y2, m2, d2, f2 );

    [ days, ierror ] = ymdf_dif_common ( y1, m1, d1, f1, y2, m2, d2, f2 );

    fprintf ( 1, '  %10s  %10s  %11.2f\n', s1, s2, days );

  end

  return
end


classdef TestGeneralizedHoughGuil
    %TestGeneralizedHoughGuil

    methods (Static)
        function test_1
            hough = cv.GeneralizedHoughGuil();
            [img, tmpl] = sample_data();
            hough.setTemplate(tmpl);
            [pos,votes] = hough.detect(img);
            assert(iscell(pos) && iscell(votes));
            assert(isequal(numel(pos), numel(votes)));
            if ~isempty(pos)
                assert(all(cellfun(@numel,pos) == 4));
                assert(all(cellfun(@numel,votes) == 3));
            end
        end

        function test_2
            hough = cv.GeneralizedHoughGuil();
            [img, tmpl] = sample_data();
            [edges, dx, dy] = calcEdges(tmpl);
            hough.setTemplate(edges, dx, dy);
            [pos,votes] = hough.detect(img);
        end

        function test_3
            hough = cv.GeneralizedHoughGuil();
            [img, tmpl] = sample_data();
            hough.setTemplate(tmpl);
            [edges, dx, dy] = calcEdges(img);
            [pos,votes] = hough.detect(edges, dx, dy);
        end
    end

end

function [img, tmpl] = sample_data()
    img = zeros(200,200,'uint8');
    img(20:50,20:50) = 255;
    img(120:150,120:150) = 255;

    tmpl = zeros(50,50,'uint8');
    tmpl(10:40,10:40) = 255;
end

function [edges, dx, dy] = calcEdges(img)
    edges = cv.Canny(img, [50 100]);
    dx = cv.Sobel(img, 'DDepth','single', 'XOrder',1, 'YOrder',0);
    dy = cv.Sobel(img, 'DDepth','single', 'XOrder',0, 'YOrder',1);
end


function spm_dcm_Granger_demo
% Demo routine for induced responses
%==========================================================================
%
% This routine illustrates the relationship between Geweke Granger
% causality (GC) in frequency space and modulation transfer functions
% (MTF).  We first compare and contrast analytic results for GC with
% estimates based on a simulated time series. These synthetic data are
% chosen to show that (analytic) GC can, in principle, detect sparsity
% structure in terms of missing causal connections (however, GC estimates
% are not so efficient). We then demonstrate the behaviour of (analytic)
% GC by varying the strength of forward connections, backward connections
% and intrinsic gain.  There is reasonable behaviour under these
% manipulations. However, when we introduce realistic levels of (power law)
% measurement noise, GC fails. The simulations conclude by showing that DCM
% recovery of the underlying model parameters can furnish  (analytic) GC
% among sources (in the absence of measurement noise). [delete the 'return'
% below to see these simulations].
%
% See also:
%  spm_ccf2csd.m, spm_ccf2mar, spm_csd2ccf.m, spm_csd2mar.m, spm_mar2csd.m,
%  spm_csd2coh.m, spm_ccf2gew, spm_dcm_mtf.m, spm_Q.m, spm_mar.m and
%  spm_mar_spectral.m
%
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_dcm_Granger_demo.m 6059 2014-06-19 11:57:31Z vladimir $

% Model specification
%==========================================================================
rng('default')

% number of regions
%--------------------------------------------------------------------------
Nc    = 2;                                       % number of channels
Ns    = 2;                                       % number of sources
ns    = 2*128;                                   % sampling frequency
dt    = 1/ns;                                    % time bins
Hz    = 1:128;                                   % frequency
p     = 16;                                      % autoregression order
options.spatial  = 'LFP';
options.model    = 'CMC';
options.analysis = 'CSD';
M.dipfit.model = options.model;
M.dipfit.type  = options.spatial;
M.dipfit.Nc    = Nc;
M.dipfit.Ns    = Ns;
M.pF.D         = [1 4];

% extrinsic connections (forward an backward)
%--------------------------------------------------------------------------
A{1} = [0 0; 0 0];
A{2} = [0 0; 0 0];
A{3} = [0 0; 0 0];
B    = {};
C    = sparse(2,0);

% get priors
%--------------------------------------------------------------------------
pE    = spm_dcm_neural_priors(A,B,C,options.model);
pE    = spm_L_priors(M.dipfit,pE);
pE    = spm_ssr_priors(pE);
x     = spm_dcm_x_neural(pE,options.model);

% (log) connectivity parameters
%--------------------------------------------------------------------------
pE.A{1}(2,1) = 2;
pE.S         = 1/8;

% (log) amplitude of fluctations and noise
%--------------------------------------------------------------------------
pE.a(1,:) = -2;
pE.b(1,:) = -8;
pE.c(1,:) = -8;

% orders and model
%==========================================================================
nx    = length(spm_vec(x));

% create forward model
%--------------------------------------------------------------------------
M.f   = 'spm_fx_cmc';
M.g   = 'spm_gx_erp';
M.x   = x;
M.n   = nx;
M.pE  = pE;
M.m   = Ns;
M.l   = Nc;
M.Hz  = Hz;
M.Rft = 4;

% specify M.u - endogenous input (fluctuations) and intial states
%--------------------------------------------------------------------------
M.u   = sparse(Ns,1);

% solve for steady state
%--------------------------------------------------------------------------
M.x   = spm_dcm_neural_x(pE,M);

% Analytic spectral chararacterisation
%==========================================================================
spm_figure('GetWin','Figure 1'); clf

[csd,Hz,mtf] = spm_csd_mtf(pE,M);
csd          = csd{1};
mtf          = mtf{1};
ccf          = spm_csd2ccf(csd,Hz,dt);
mar          = spm_ccf2mar(ccf,p);
mar          = spm_mar_spectra(mar,Hz,ns);

spm_figure('GetWin','Figure 1'); clf
spm_spectral_plot(Hz,csd,  'b', 'frequency','density')
spm_spectral_plot(Hz,mar.P,'r', 'frequency','density')

legend('cross spectral density',...
       'autoregressive model')

%  comparison of expected results
%==========================================================================
spm_figure('GetWin','Figure 2'); clf

dtf  = mar.dtf;
gew  = mar.gew;
new  = spm_csd2gew(csd,Hz);

spm_spectral_plot(Hz,mtf,'b', 'frequency','density')
spm_spectral_plot(Hz,dtf,'g', 'frequency','density')
spm_spectral_plot(Hz,gew,'r', 'frequency','density')
spm_spectral_plot(Hz,new,'r:','frequency','density')

subplot(2,2,3), a = axis; subplot(2,2,2), axis(a);

legend('modulation transfer function',...
       'directed transfer function',...
       'Granger causality (parametric)',...
       'Granger causality (non-parametric)')

% effects of changing various model parameters
%==========================================================================

% (log) scaling, and parameters
%--------------------------------------------------------------------------
logs  = [ ((1:4)/1 - 2);
          ((1:4)/1 - 2);
          ((1:4)/6 + 0);
          ((1:4)/1 - 6)];

param = {'A{1}(2,1)','A{3}(1,2)','S','c(1,2)'};
str   = {     'forward connectivity',
              'backward connectivity',
              'intrinsic gain',
              'amplitude of noise'};

% expected transfer function and Gramger causality
%--------------------------------------------------------------------------
spm_figure('GetWin','Figure 3'); clf
a     = [0 Hz(end) 0 .35];
ca    = 0;
for i = 1:size(logs,1)
    for j = 1:size(logs,2)

        P     = pE;
        eval(sprintf('P.%s = %i;',param{i},logs(i,j)));

        % create forward model and solve for steady state
        %------------------------------------------------------------------
        M.x   = spm_dcm_neural_x(P,M);

        % Analytic spectral chararacterisation
        %==================================================================
        [csd,Hz,mtf,qew] = spm_csd_mtf(P,M);

        ccf   = spm_csd2ccf(csd{1},Hz,dt);
        mar   = spm_ccf2mar(ccf,p);
        mar   = spm_mar_spectra(mar,Hz,ns);

        % plot forwards and backwards functions
        %------------------------------------------------------------------
        subplot(4,2,ca + 1)
        plot(Hz,abs(mar.gew(:,2,1)),Hz,abs(qew{1}(:,2,1)))
        xlabel('frequency')
        ylabel('absolute value')
        title(sprintf('%s',str{i}),'FontSize',16)
        axis square, hold on, set(gca,'XLim',[0 Hz(end)])
        axis(a);

        subplot(4,2,ca + 2)
        plot(Hz,abs(mar.gew(:,1,2)),Hz,abs(qew{1}(:,1,2)))
        xlabel('frequency')
        ylabel('absolute value')
        title(sprintf('backward'),'FontSize',16)
        axis square, hold on, set(gca,'XLim',[0 Hz(end)])
        axis(a);

    end
    ca  = ca + 2;

end

% Lyapunov functions
%==========================================================================

% (log) scaling, and parameters
%--------------------------------------------------------------------------
param = {'A{1}(2,1)','A{3}(1,2)','S','D(1,1)'};
str   = {     'forward connectivity',
              'backward connectivity',
              'intrinsic gain',
              'intrinsic delays'};

% changing parameters and Lyapunov functions
%--------------------------------------------------------------------------
spm_figure('GetWin','Figure 4'); clf
k     = linspace(0,1,32);
for i = 1:length(param)
    for j = 1:length(k)

        P     = pE;
        eval(sprintf('P.%s = %i;',param{i},k(j)));

        % create forward model and solve for steady state
        %------------------------------------------------------------------
        M.x   = spm_dcm_neural_x(P,M);

        % Analytic spectral chararacterisation
        %==================================================================
        [f,dfdx,D] = feval(M.f,M.x,M.u,P,M);
        dfdx       = D*dfdx;
        S(i,j)     = max(real(eig(full(dfdx),'nobalance')));

        % recursive check on MAR approximation
        %------------------------------------------------------------------
        csd        = spm_csd_mtf(P,M);
        ccf        = spm_csd2ccf(csd{1},Hz);
        [mar,c]    = spm_ccf2mar(ccf,p);
        pcond(i,j) = c;

    end
end

% plot
%--------------------------------------------------------------------------
subplot(2,2,1)
plot(k,S),hold on
xlabel('parameter (log) scaling')
ylabel('principal eigenvalue')
title('Lyapunov exponents','FontSize',16)
axis square; spm_axis tight
plot(k,k*0,'k:',k,k*0 - 1/(dt*p),'k-.'),hold off

subplot(2,2,2)
semilogy(k,pcond),hold on
xlabel('parameter (log) scaling')
ylabel('condition number')
title('condition of cross covariance','FontSize',16)
axis square;
legend(str)

plot(k,k*0 + 1e4,'k:'),hold off

% MAR approximation
%==========================================================================
param = {'S'};
for i = 1:length(param)
    for j = 1:length(k)

        P     = pE;
        eval(sprintf('P.%s = %i;',param{i},k(j)));

        % create forward model and solve for steady state
        %------------------------------------------------------------------
        M.x   = spm_dcm_neural_x(P,M);

        % check on MAR approximation
        %------------------------------------------------------------------
        csd   = spm_csd_mtf(P,M);
        mar   = spm_csd2mar(csd{1},Hz,p);
        mar   = spm_mar_spectra(mar,Hz);

        CSD(:,j) = csd{1}(:,2,2);
        PSD(:,j) = mar.P(:,2,2);

    end
end

subplot(2,2,3)
imagesc(k,Hz,log(abs(CSD)))
xlabel('parameter (log) scaling')
ylabel('frequency')
title('(log) spectral density','FontSize',16)
axis square

subplot(2,2,4)
imagesc(k,Hz,abs(PSD - CSD).^(1/4))
xlabel('parameter (log) scaling')
ylabel('frequency')
title('MAR approximation error','FontSize',16)
axis square

% a more careful examination of [in]stability on Granger causality
%==========================================================================
spm_figure('GetWin','Figure 5'); clf
k     = linspace(0,2/3,8);
for j = 1:length(k)

    % amplitude of observation noise
    %----------------------------------------------------------------------
    P        = pE;
    P.S      = k(j);

    % create forward model and solve for steady state
    %----------------------------------------------------------------------
    M.x      = spm_dcm_neural_x(P,M);

    % Analytic spectral chararacterisation (parametric)
    %======================================================================
    [csd,Hz,mtf,qew] = spm_csd_mtf(P,M);

    ccf      = spm_csd2ccf(csd{1},Hz,dt);
    mar      = spm_ccf2mar(ccf,p);
    mar      = spm_mar_spectra(mar,Hz,ns);

    % and non-parametric
    %======================================================================
    gew      = spm_csd2gew(csd{1},Hz);

    % save forwards and backwards functions
    %----------------------------------------------------------------------
    GCF(:,j) = abs(mar.gew(:,2,1));
    GCB(:,j) = abs(mar.gew(:,1,2));

    % plot forwards and backwards functions (parametric)
    %----------------------------------------------------------------------
    spm_figure('GetWin','Figure 5');

    subplot(3,2,1)
    plot(Hz,abs(mar.gew(:,2,1)),Hz,abs(qew{1}(:,2,1)))
    xlabel('frequency')
    ylabel('absolute value')
    title('forward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    a  = axis;

    subplot(3,2,2)
    plot(Hz,abs(mar.gew(:,1,2)),Hz,abs(qew{1}(:,1,2)))
    xlabel('frequency')
    ylabel('absolute value')
    title('backward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    axis(a);

    % plot forwards and backwards functions (nonparametric)
    %----------------------------------------------------------------------
    subplot(3,2,3)
    plot(Hz,abs(gew(:,2,1)),Hz,abs(qew{1}(:,2,1)))
    xlabel('frequency')
    ylabel('absolute value')
    title('forward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    axis(a);

    subplot(3,2,4)
    plot(Hz,abs(gew(:,1,2)),Hz,abs(qew{1}(:,1,2)))
    xlabel('frequency')
    ylabel('absolute value')
    title('backward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    axis(a);

end

a = .2;
subplot(3,2,5)
image(Hz,k,GCF'*64/a)
xlabel('frequency')
ylabel('log(exponent)')
title('forward','FontSize',16)
axis square

subplot(3,2,6)
image(Hz,k,GCB'*64/a)
xlabel('frequency')
ylabel('log(exponent)')
title('backward','FontSize',16)
axis square

% a more careful examination of measurement noise
%==========================================================================
spm_figure('GetWin','Figure 6' ); clf
spm_figure('GetWin','Figure 6a'); clf
k     = linspace(-8,-0,8);
for j = 1:length(k)

    % amplitude of observation noise
    %----------------------------------------------------------------------
    P        = pE;
    P.b(1)   = k(j);
    P.c(1,:) = k(j) + 1;

    % create forward model and solve for steady state
    %----------------------------------------------------------------------
    M.x      = spm_dcm_neural_x(P,M);

    % Analytic spectral chararacterisation (parametric)
    %======================================================================
    [csd,Hz,mtf,qew] = spm_csd_mtf(P,M);

    ccf      = spm_csd2ccf(csd{1},Hz,dt);
    mar      = spm_ccf2mar(ccf,p);
    mar      = spm_mar_spectra(mar,Hz,ns);

    % and non-parametric
    %======================================================================
    gew      = spm_csd2gew(csd{1},Hz);
    qew      = qew{1};

    % save forwards and backwards functions
    %----------------------------------------------------------------------
    GCF(:,j) = abs(gew(:,2,1));
    GCB(:,j) = abs(gew(:,1,2));

    % plot forwards and backwards functions  (parametric)
    %----------------------------------------------------------------------
    spm_figure('GetWin','Figure 6');

    subplot(3,2,1)
    plot(Hz,abs(mar.gew(:,2,1)),Hz,abs(qew(:,2,1)))
    xlabel('frequency')
    ylabel('absolute value')
    title('forward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    a  = axis;

    subplot(3,2,2)
    plot(Hz,abs(mar.gew(:,1,2)),Hz,abs(qew(:,1,2)))
    xlabel('frequency')
    ylabel('absolute value')
    title('backward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    axis(a);

    % plot forwards and backwards functions  (nonparametric)
    %----------------------------------------------------------------------
    subplot(3,2,3)
    plot(Hz,abs(gew(:,2,1)),Hz,abs(qew(:,2,1)))
    xlabel('frequency')
    ylabel('absolute value')
    title('forward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    axis(a);

    subplot(3,2,4)
    plot(Hz,abs(gew(:,1,2)),Hz,abs(qew(:,1,2)))
    xlabel('frequency')
    ylabel('absolute value')
    title('backward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    axis(a);

    % plot associated coherence
    %----------------------------------------------------------------------
    spm_figure('GetWin','Figure 6a' );

    if j > 4, str = ':'; else, str = '-'; end
    coh = spm_csd2coh(csd{1},Hz);
    spm_spectral_plot(Hz,coh,str,'frequency','coherence')

end

spm_figure('GetWin','Figure 6' );

subplot(3,2,5)
imagesc(Hz,k,GCF')
xlabel('frequency')
ylabel('log(exponent)')
title('forward','FontSize',16)
axis square

subplot(3,2,6)
imagesc(Hz,k,GCB')
xlabel('frequency')
ylabel('log(exponent)')
title('backward','FontSize',16)
axis square

% return if in demonstration mode
%--------------------------------------------------------------------------
DEMO = 1;
if DEMO, return, end

% DCM estimates of coupling
%==========================================================================
rng('default')

% get priors and generate data
%--------------------------------------------------------------------------
pE    = spm_dcm_neural_priors(A,B,C,options.model);
pE    = spm_L_priors(M.dipfit,pE);
pE    = spm_ssr_priors(pE);

% (log) connectivity parameters (forward connection only)
%--------------------------------------------------------------------------
pE.A{1}(2,1) = 2;
pE.S         = 1/8;

% (log) amplitude of fluctations and noise
%--------------------------------------------------------------------------
pE.a(1,:) = -2;
pE.b(1,:) = -8;
pE.c(1,:) = -8;

% expected cross spectral density
%--------------------------------------------------------------------------
csd       = spm_csd_mtf(pE,M);

% Get spectral profile of fluctuations and noise
%--------------------------------------------------------------------------
[Gu,Gs,Gn] = spm_csd_mtf_gu(pE,Hz);

% Integrate with power law process (simulate multiple trials)
%--------------------------------------------------------------------------
PSD   = 0;
CSD   = 0;
N     = 1024;
U.dt  = dt;
for t = 1:16

    % neuronal fluctuations
    %----------------------------------------------------------------------
    U.u      = spm_rand_power_law(Gu,Hz,dt,N);
    LFP      = spm_int_L(pE,M,U);

    % and measurement noise
    %----------------------------------------------------------------------
    En       = spm_rand_power_law(Gn,Hz,dt,N);
    Es       = spm_rand_power_law(Gs,Hz,dt,N);
    E        = Es + En*ones(1,Ns);

    % and estimate spectral features under a MAR model
    %----------------------------------------------------------------------
    MAR      = spm_mar(LFP + E,p);
    MAR      = spm_mar_spectra(MAR,Hz,ns);
    CSD      = CSD + MAR.P;

    % and using Welch's method
    %----------------------------------------------------------------------
    PSD      = PSD + spm_csd(LFP + E,Hz,ns);

    CCD(:,t) = abs(CSD(:,1,2)/t);
    PCD(:,t) = abs(CSD(:,1,1)/t);

    % plot
    %----------------------------------------------------------------------
    spm_figure('GetWin','Figure 7'); clf
    spm_spectral_plot(Hz,csd{1},'r',  'frequency','density')
    spm_spectral_plot(Hz,CSD/t, 'b',  'frequency','density')
    spm_spectral_plot(Hz,PSD/t, 'g',  'frequency','density')
    legend('real','estimated (AR)','estimated (CSD)')
    drawnow

end

%  show convergence of spectral estimators
%--------------------------------------------------------------------------
subplot(2,2,3), hold off
imagesc(Hz,1:t,log(PCD'))
xlabel('frequency')
ylabel('trial number')
title('log auto spectra','FontSize',16)
axis square

subplot(2,2,4), hold off
imagesc(Hz,1:t,log(CCD'))
xlabel('frequency')
ylabel('trial number')
title('log cross spectra','FontSize',16)
axis square

% DCM set up (allow for both forward and backward connections)
%==========================================================================

% (log) connectivity parameters (forward connection only)
%--------------------------------------------------------------------------
pE.A{1}(2,1) = 2;
pE.S         = 1/8;

% (log) amplitude of fluctations and noise
%--------------------------------------------------------------------------
pE.a(1,:) = -2;
pE.b(1,:) = -4;
pE.c(1,:) = -4;

% expected cross spectral density
%--------------------------------------------------------------------------
[csd,Hz,mtf] = spm_csd_mtf(pE,M);

DCM.options.model   = 'CMC';
DCM.options.spatial = 'LFP';
DCM.options.DATA    = 0;

DCM.M.dipfit.Nc  = Nc;
DCM.M.dipfit.Ns  = Ns;
DCM.M.Nmax = 32;
DCM.M.U    = eye(Nc,Nc);

DCM.A      = {[0 0; 1 0],[0 1; 0 0],[0 0; 0 0]};
DCM.B      = {};
DCM.C      = sparse(Ns,0);

% place in data structure
%--------------------------------------------------------------------------
DCM.xY.y  = csd;
DCM.xY.dt = dt;
DCM.xY.Hz = Hz;

% estimate
%--------------------------------------------------------------------------
DCM       = spm_dcm_csd(DCM);

% show results in terms of transfer functions and Granger causality
%==========================================================================
spm_figure('GetWin','Figure 8'); clf

% transfer functions in the absence of measurement noise
%--------------------------------------------------------------------------
Ep    = DCM.Ep;
Ep.b  = Ep.b - 32;              % and suppress non-specific and
Ep.c  = Ep.c - 32;              % specific channel noise

Gu           = spm_csd_mtf_gu(Ep,Hz);
[psd Hz dtf] = spm_csd_mtf(Ep,DCM.M);

mtf   = mtf{1};
csd   = csd{1};
dtf   = dtf{1};

% transfer functions and Granger causality among sources and channels
%--------------------------------------------------------------------------
gwe  = spm_dtf2gew(mtf,Gu);
qew  = spm_dtf2gew(dtf,Gu);
gew  = spm_csd2gew(csd,Hz);

spm_spectral_plot(Hz,mtf,'b:', 'frequency','density')
spm_spectral_plot(Hz,gwe,'b',  'frequency','density')
spm_spectral_plot(Hz,qew,'r',  'frequency','density')
spm_spectral_plot(Hz,gew,'g',  'frequency','density')
legend('modulation transfer function',...
       'Granger causality (true)',...
       'Granger causality (source)',...
       'Granger causality (channel)')

subplot(2,2,3), a = axis; subplot(2,2,2), axis(a);

return

% NOTES: a more careful examination of delays
%==========================================================================
spm_figure('GetWin','Figure 9'); clf

k     = linspace(8,11,8);
for j = 1:length(k)

    % keep total power of fluctuations constant
    %----------------------------------------------------------------------
    M.pF.D(2,1)  = k(j);

    % create forward model and solve for steady state
    %----------------------------------------------------------------------
    M.x          = spm_dcm_neural_x(pE,M);

    % Analytic spectral chararacterisation (parametric)
    %======================================================================
    [csd,Hz,mtf] = spm_csd_mtf(pE,M);
    ccf          = spm_csd2ccf(csd{1},Hz,dt);
    mar          = spm_ccf2mar(ccf,p);
    mar          = spm_mar_spectra(mar,Hz,ns);

    % and non-parametric)
    %======================================================================
    gew          = spm_csd2gew(csd{1},Hz);

    % plot forwards and backwards functions
    %----------------------------------------------------------------------
    subplot(3,2,1)
    plot(Hz,abs(mar.gew(:,2,1)),Hz,abs(mtf{1}(:,2,1)))
    xlabel('frequency')
    ylabel('absolute value')
    title('forward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    a  = axis;

    subplot(3,2,2)
    plot(Hz,abs(mar.gew(:,1,2)),Hz,abs(mtf{1}(:,1,2)))
    xlabel('frequency')
    ylabel('absolute value')
    title('backward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    axis(a);

    % plot forwards and backwards functions
    %----------------------------------------------------------------------
    subplot(3,2,3)
    plot(Hz,abs(gew(:,2,1)),Hz,abs(mtf{1}(:,2,1)))
    xlabel('frequency')
    ylabel('absolute value')
    title('forward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    axis(a);

    subplot(3,2,4)
    plot(Hz,abs(gew(:,1,2)),Hz,abs(mtf{1}(:,1,2)))
    xlabel('frequency')
    ylabel('absolute value')
    title('backward','FontSize',16)
    axis square, hold on, set(gca,'XLim',[0 Hz(end)])
    axis(a);

end


load hall1-200;
matlabpool open;
X = normalize(XO);
[P Q L] = onlineRPMF(X, 2, 1, 1, 1e-2, ones(size(X)));
% M = normalize(I0);
% [P2 Q2 L2] = onlineRPMF(M, 2, 1, 1, 1e-2, ones(size(M)));
%show(X, L, abs(X - L), [144 176]);
show(X, L, (X - L), [144 176]);
%show(M, L2, (M - L2), [vidHeight vidWidth]);
matlabpool close;


filename='Bridge_hexahedra_coarse';
 ptype = 'MACRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'full';
cost = {'compliance';'perimeter'};
weights = [1, 0.1];
constraint = {'volumeConstraint'};
optimizer = 'MMA'; incrementFactor = 1;
filterType = 'P1';

nsteps = 5;
Vfrac_final = 0.05;
Perimeter_target = 1;
optimality_final = 1e-3;
constr_final =1e-3;

Vfrac_initial = 1;
optimality_initial = 1e-2;
constr_initial = 1e-3;
TOL.rho_plus = 1;
TOL.rho_minus = 0;
TOL.E_plus = 1;
TOL.E_minus = 1e-3;
TOL.nu_plus = 1/3;
TOL.nu_minus = 1/3;


function [M] = spm_DEM_M(model,varargin)
% Create a [template] model structure
% FORMAT [M] = spm_DEM_M(model,l,n)
% FORMAT [M] = spm_DEM_M(model,X1,X2,...)
%
% model: 'General linear model','GLM'
%        'Factor analysis','FA'
%        'Independent component analysis','ICA'
%        'Sparse coding',"SC'
%        'convolution model'
%        'State space model','SSM',','Double Well'
%        'Lorenz'
%        'Ornstein_Uhlenbeck','OU'
%
% l(i) - number of outputs from level i
% n(i) - number of hidden states in level i
%
% Xi   - deisgn matrix for level i
%
%==========================================================================
% hierarchical generative model
%--------------------------------------------------------------------------
%   M(i).g  = y(t)  = g(x,v,P)    {inline function, string or m-file}
%   M(i).f  = dx/dt = f(x,v,P)    {inline function, string or m-file}
%
%   M(i).pE = prior expectation of p model-parameters
%   M(i).pC = prior covariances of p model-parameters
%   M(i).hE = prior expectation of h hyper-parameters (cause noise)
%   M(i).hC = prior covariances of h hyper-parameters (cause noise)
%   M(i).gE = prior expectation of g hyper-parameters (state noise)
%   M(i).gC = prior covariances of g hyper-parameters (state noise)
%   M(i).Q  = precision components (input noise)
%   M(i).R  = precision components (state noise)
%   M(i).V  = fixed precision (input noise)
%   M(i).W  = fixed precision (state noise)
%
%   M(i).m  = number of inputs v(i + 1);
%   M(i).n  = number of states x(i);
%   M(i).l  = number of output v(i);
%__________________________________________________________________________
% Copyright (C) 2007-2015 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_DEM_M.m 6416 2015-04-21 15:34:10Z guillaume $

switch lower(model)

    % hierarchical linear generative model - the basis for  static models
    % These subsume: Parametric emprical Bayes (PEB) models
    %                Mixed effects (MFX) models
    %======================================================================
    case{'hierarchical linear model','hlm','peb','mfx'}

        % Get design matrices for each level
        %------------------------------------------------------------------
        M(1).E.linear = 1;
        if ~isempty(varargin);
            pE   = varargin;
        else
            error('Please specify design matrices');

            global SPM_DATA;
            fig  = spm_data;
            set(fig,'Name','Please specify design matrices using ''next''')
            waitfor(fig)
            pE   = SPM_DATA;
        end

        for i = 1:length(pE)

            % level i
            %--------------------------------------------------------------
            M(i).m  = size(pE{i},2);
            M(i).l  = size(pE{i},1);
            M(i).g  = inline('P*v','x','v','P');
            M(i).pE = pE{i};
            M(i).hE = 0;
            M(i).hC = 16;

        end

        % non-hierarchical linear generative model (static)
        %==================================================================
    case{'general linear model','glm'}

        % Get design matrix
        %------------------------------------------------------------------
        if ~isempty(varargin);
            pE  = varargin{1};
        else
            global SPM_DATA
            fig = spm_data;
            set(fig,'Name','Please specify a design matrix')
            waitfor(fig)
            pE  = SPM_DATA;
        end

        % This is simply a one-level HLM with flat priors
        %------------------------------------------------------------------
        M       = spm_DEM_M('hlm',pE);

        % Factor analysis model (static) with unknown parameters
        %==================================================================
    case{'factor analysis','fa'}

        % Get orders (this routine will accommodate hierarchical FA)
        %------------------------------------------------------------------
        try
            l = varargin{1};
            l = l(~~l);
        catch
            errordlg('please specify number of inputs and ouputs')
        end

        % This is simply a HLM with unknown parameters
        %------------------------------------------------------------------
        g     = length(l) - 1;
        for i = 1:g
            pE{i} = sparse(l(i),l(i + 1));
            pC{i} = speye(l(i)*l(i + 1));
        end

        % create basic HLM and add prior uncertainty
        %------------------------------------------------------------------
        M     = spm_DEM_M('hlm',pE{:});
        for i = 1:g
            M(i).pC = pC{i};
        end

        % Principal component analysis (static - linear)
        % Equivalent to singular value decomposition (SVD)
        %==================================================================
    case{'principal component analysis','pca','svd'}

        % create basic FA
        %------------------------------------------------------------------
        try
            l    = varargin{1}(1);
        catch
            msgbox('please specify number of outputs')
            error(' ')
        end
        M        = spm_DEM_M('fa',[l l]);
        g        = length(M);

        % assume precisely small error at the first level
        %------------------------------------------------------------------
        M(1).hE  = 8;
        M(1).hC  = 1/32;

        % assume unit causes
        %------------------------------------------------------------------
        M(2).V   = speye(M(2).l,M(2).l);

        % Independent component analysis (static - nonlinear)
        %==================================================================
    case{'independent component analysis','ica'}

        % create basic FA
        %------------------------------------------------------------------
        M        = spm_DEM_M('pca',varargin{:});
        g        = length(M);

        % and add supra-ordinate [nonlinear] level
        %------------------------------------------------------------------
        M(g + 1) = M(g);
        M(g).m   = M(g + 1).l;
        M(g).g   = 'v-tanh(v)*P';
        M(g).pE  = 0;
        M(g).pC  = 0;
        M(g).V   = speye(M(2).l,M(2).l)*exp(8);

        % Sparse coding, pICA (static - nonlinear)
        %==================================================================
    case{'sparse coding','pica','sc'}

        % create basic ica
        %------------------------------------------------------------------
        M          = spm_DEM_M('ica',varargin{:});
        g          = length(M);

        % and add a noise component to the lower levels
        %------------------------------------------------------------------
        for i = 1:(g - 2)
            M(i).hE = 1;
            M(i).V  = sparse(M(i).l,M(i).l);
        end

        % Linear convolution (State-space model)
        %==================================================================
    case{'convolution model'}

        % time-step
        %------------------------------------------------------------------
        try
            dt = varargin{1};
        catch
            dt = 1;
        end

        % smoothness
        %------------------------------------------------------------------
        M(1).E.linear = 1;                          % linear model
        M(1).E.s      = 1/2;                          % smoothness

        % level 1
        %------------------------------------------------------------------
        pE.f    = [-1  4;                           % the Jacobian for the
                   -2 -1]/(4*dt);                   % hidden sates
        pE.g    = [spm_dctmtx(4,2)]/4;              % the mixing parameters
        pE.h    = [1 0]';                           % input parameter
        M(1).n  = 2;
        M(1).f  = inline('P.f*x + P.h*v','x','v','P');
        M(1).g  = inline('P.g*x','x','v','P');
        M(1).pE = pE;                               % prior expectation

        % level 2
        %------------------------------------------------------------------
        M(2).l  = 1;                                % inputs
        M(2).V  = 1;                                % with shrinkage priors

        % Nonlinear [Polynomial] factor analysis (static - nonlinear)
        %==================================================================
    case{'nonlinear model','nlfa'}

        % non-hierarchical nonlinear generative model (dynamic)
        %==================================================================
    case{'state space model','ssm','double well'}

        % temporal correlations
        %------------------------------------------------------------------
        M(1).E.s  = 1/2;

        % model specification - 1st level
        %------------------------------------------------------------------
        f      = '(16*x./(1 + x.^2) - x/2 + v*2)/8';
        g      = '(x.^2)/16';
        M(1).x = 1;
        M(1).f = inline(f,'x','v','P');
        M(1).g = inline(g,'x','v','P');
        M(1).V = exp(2);
        M(1).W = exp(16);

        % model specification - 2nd level
        %------------------------------------------------------------------
        M(2).v = 0;
        M(2).V = 1/8;

                % non-hierarchical nonlinear generative model (dynamic)
        %==================================================================
    case{'lorenz'}

        % correlations
        %--------------------------------------------------------------------------
        M(1).E.linear = 3;
        M(1).E.s      = 1/8;

        % level 1
        %--------------------------------------------------------------------------
        P       = [18.0; -4.0; 46.92];
        x       = [0.9; 0.8; 30];
        f       = '[-P(1) P(1) 0; (P(3)-x(3)) -1 -x(1); x(2) x(1) P(2)]*x/32;';
        M(1).f  = f;
        M(1).g  = inline('sum(x)','x','v','P');
        M(1).x  = x;
        M(1).pE = P;
        M(1).V  = exp(0);
        M(1).W  = exp(16);

        % level 2
        %--------------------------------------------------------------------------
        M(2).v  = 0;
        M(2).V  = exp(16);

        % Ornstein_Uhlenbeck linear generative model (dynamic)
        %==================================================================
    case{'Ornstein_Uhlenbeck','ou'}

        % temporal correlations
        %------------------------------------------------------------------
        M(1).E.linear = 1;                          % linear model
        M(1).E.s  = 1/2;

        % model specification - 1st level
        %------------------------------------------------------------------
        f      = '-1/16*x + v';
        g      = 'x';
        M(1).x = 0;
        M(1).f = inline(f,'x','v','P');
        M(1).g = inline(g,'x','v','P');
        M(1).V = exp(8);
        M(1).W = exp(32);

        % model specification - 2nd level
        %------------------------------------------------------------------
        M(2).v = 0;
        M(2).V = exp(-8);

    otherwise

        errordlg('unknown model; please add to spm_DEM_M')
        return

end

% check and conplete model specification
%---------------------------------------------------------------------------
M       = spm_DEM_M_set(M);


% This is material illustrating the methods from the book
% Financial Modelling  - Theory, Implementation and Practice with Matlab
% source
% Wiley Finance Series
% ISBN 978-0-470-74489-5
%
% Date: 02.05.2012
%
% Authors:  Joerg Kienitz
%           Daniel Wetterau
%
% Please send comments, suggestions, bugs, code etc. to
% kienitzwetterau_FinModelling@gmx.de
%
% (C) Joerg Kienitz, Daniel Wetterau
%
% Since this piece of code is distributed via the mathworks file-exchange
% it is covered by the BSD license
%
% This code is being provided solely for information and general
% illustrative purposes. The authors will not be responsible for the
% consequences of reliance upon using the code or for numbers produced
% from using the code.

% ADD2DATE Add a yearfraction quantity V to a Date D
%   R = ADD2DATE(D,V) will add a double valued quantity V to
%   a date string or serial date number D, and return the new date string R
%
%   INPUT PARAMETERS:
%   D:  string or serial number, defining the date value
%   V:  double scalar, defining the quantity to add to D
%
%   RETURN PARAMETERS:
%   R:  returning the new date number R

%   ASSUMPTIONS:
%       V is given in terms of yearfractions
%       1 year equals 12 month
%       1 month equals 30 days
%       yearfractions < 1/30 are rounded to plus infinity

function R = add2date(D,V)

if ischar(D)
    dateval = datenum(D);
else
    dateval = D;
end

nr_month = floor(V*12);
nr_days = ceil((V*12-nr_month)*30);

tmpVec = zeros(size(V));
for i = 1:length(V)
   tmpVec(i) = addtodate(dateval,nr_month(i),'month');
end
R = daysadd(tmpVec,nr_days);

end


function y = any(x)

% ALL    True if all elements of a vector are nonzero.
%    For vectors, ALL(V) returns logical 1 (TRUE) if none of the elements
%    of the vector are zero.  Otherwise it returns logical 0 (FALSE).  For
%    matrices, ALL(X) operates on the columns of X, returning a row vector
%    of logical 1's and 0's. For N-D arrays, ALL(X) operates on the first
%    non-singleton dimension.

if nargin>1
  error('this implementation is only supported with one input argument');
end

siz = size(x);
if numel(siz)>2
  error('this implementation is only supported with vector or matrix input');
end

if siz(1)==1 || siz(2)==1
  y = true;
  for i=1:prod(siz)
    if ~x(i)
      y = false;
      break
    end
  end

else
  y = true(1,siz(2));
  for j=1:siz(2)
    for i=1:siz(1)
      if ~x(i,j)
        y(1,j) = false;
        break
      end
    end
  end

end


function out = iszero(f)
%ISZERO   Check if a CHEBFUN3 is identically zero on its domain.
%   OUT = ISZERO(F) returns logical 1 if the CHEBFUN3 object F is exactly
%   the zero function, and logical 0 otherwise.
%
% See also CHEBFUN2/ISZERO.

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

% Get data:
[fCore, fCols, fRows, fTubes] = tucker(f);

% Trivial check: If all the pivots are zero, then the SEPARABLEAPPROX is zero:
if ( norm(fCore(:), inf) == 0 )
    out = 1;
    return
end

% Quick check: Evaluate on a grid. If the tensor is nonzero then the
% CHEBFUN3 is nonzero.
dom = f.domain;
x = linspace(dom(1), dom(2), 10);
y = linspace(dom(3), dom(4), 10);
z = linspace(dom(5), dom(6), 10);
vals = fevalt(f, x, y, z);

if ( norm(vals(:), inf) > 0 )
   out = 0;
   return
end

% Slower check: The core may be nonzero, but the columns, rows, or tubes
% may be zero:
[rk1, rk2, rk3] = rank(f);
out_cols = zeros(rk1, 1);
out_rows = zeros(rk2, 1);
out_tubes = zeros(rk3, 1);
for j = 1:rk1
    out_cols(j) = iszero(fCols(:, j));
end
for j = 1:rk2
    out_rows(j) = iszero(fRows(:, j));
end
for j = 1:rk3
    out_tubes(j) = iszero(fTubes(:, j));
end
out = ( all(out_cols) || all(out_rows) || all(out_tubes) );

end


function [sp, K, scores] = update_sp_indexing(sp, K, h, w, opts)
% After spagglom_sub.m has been run for a while (phase1, obtaining the
% refined superpixelation), The 'sp' variable contains lots of useless
% empty superpixels and the superpixels are made of multiple parts. If this
% information is not required (by default it's not), this function can be
% run to simplify the 'sp' variable and accordingly update neighbor
% variable 'K'.

cc = 1; % a counter
sp_old = sp;
sp = [];
key = [];

% Build each superpixel
for q = 1:length(sp_old)
    if size(sp_old{q}.pixels,1) > 0 % remove empty sp by ignoring them
        sp{cc} = sp_old{q}; % copy the old information
        sp{cc}.parts = [cc]; % each sp has one part, which is the same as its index
        key(end+1,1:2) = [q, cc]; % contruct mapping from old to new indexing
        cc = cc + 1;
    end
end

sp_amount = length(sp);

% Spply mapping to update sp labels
K = arrayfun(@(x)key(key(:,1) == x, 2), K); % changes each value of K by lookup using table matrix 'key'
for q = 1:length(sp)
    sp{q}.neighbors = arrayfun(@(x)key(key(:,1) == x, 2), sp{q}.neighbors); % same for neighbors
end

% List pixel coordinates in index format
for sus = 1:sp_amount
    sp{sus}.spind = sub2ind([h,w], double(sp{sus}.pixels(:,1)), double(sp{sus}.pixels(:,2)));
end

% Recalculate scores
scores = similarity_scores(sp, K, opts); % rows of this variable have been permutated. Instead of solving the permutation, we just recalculate the values.


function v1 = ctranspose(v1)
% transpose vector

v1.x = v1.x';
v1.y = v1.y';
v1.z = v1.z';


% *************************************************************************
% Code for setting the numerical values of nonlinear terms
% *************************************************************************
function p = updateonenonlinearbound(p,changed_var)
if ~isempty(p.bilinears)
    impactedVariables = find((p.bilinears(:,2) == changed_var) | (p.bilinears(:,3) == changed_var));
    x = p.bilinears(impactedVariables,2);
    y = p.bilinears(impactedVariables,3);
    z = p.bilinears(impactedVariables,1);
    x_lb = p.lb(x);
    x_ub = p.ub(x);
    y_lb = p.lb(y);
    y_ub = p.ub(y);
    bounds = [x_lb.*y_lb x_lb.*y_ub x_ub.*y_lb x_ub.*y_ub];
    p.lb(z) = max([p.lb(z) min(bounds,[],2)],[],2);
    p.ub(z) = min([p.ub(z) max(bounds,[],2)],[],2)';
    p.lb(impactedVariables(x==y)<0) = 0;
end


function tcourses_svm = classify_ConvertForSVM(tcourses, trials)

nConds = length(tcourses.labels);
[nVoxels nTimePoints] = size(tcourses.data.conditions(1).trials{1});
nEntries = nTimePoints*nVoxels;
nTrials = length(trials);
tcourses_svm.trials = trials;
tcourses_svm.labels = tcourses.labels;
tcourses_svm.label_vector = (1:(nConds*nTrials))';
tcourses_svm.instance_matrix = zeros(nConds,nEntries);

condIndex = 0;
for cond = 1:nConds
    for trial = trials;
        condIndex = condIndex + 1;
        tcourses_svm.label_vector(condIndex) = cond;
        tcourses_svm.instance_matrix(condIndex,:) = ...
            reshape(tcourses.data.conditions(cond).trials{trial}',[1 nEntries]);
    end
end


Z = W*X;cz = [Z(:,ind)];

if exist('ZV2')
    [ZV,ZV2{2}] = ZV_gen2(Z,cz,ind,ZV2{1});
else
    [ZV,ZV2] = ZV_gen(Z,cz,Y,ind);
end;

CalcG;

RegMat = GG(ind,:) + Ib*RegEpsilon;

alpha = (Hhat + lambda*RegMat)\hhat;
Is_tmp = IsCalc(Hhat,hhat,alpha);


% AVEREF - convert common-reference EEG data to average reference
%            Note that this old function is not being used in EEGLAB. The
%            function used by EEGLAB is REREF.
%
% Usage:
%   >> data = averef(data);
%   >> [data_out W_out S_out meandata] = averef(data,W);
%
% Inputs:
%   data - 2D data matrix (chans,frames*epochs)
%   W    - ICA weight matrix
%
% Outputs:
%   data_out - Input data converted to average reference.
%   W_out    - ICA weight matrix converted to average reference
%   S_out    - ICA sphere matrix converted to EYE
%   meandata - (1,dataframes) mean removed from each data frame (point)
%
% Note: If 2 args, also converts the weight matrix W to average reference:
%         If ica_act = W*data, then data = inv(W)*ica_act;
%         If R*data is the average-referenced data,
%         R*data=(R*inv(W))*ica_act and W_out = inv(R*inv(W));
%         The average-reference ICA maps are the columns of inv(W_out).
%
% Authors: Scott Makeig and Arnaud Delorme, SCCN/INC/UCSD, La Jolla, 1999
%
% See also: REREF

% Copyright (C) 1999 Scott Makeig, SCCN/INC/UCSD, scott@sccn.ucsd.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

% 12/16/99 Corrected denomiator on the suggestion of Ian Nimmo-Smith, Cambridge UK
% 01-25-02 reformated help & license -ad

function [data, W, S, meandata] = averef(data, W, S)

if nargin<1
  help averef
  return
end
chans = size(data,1);
if chans < 2
  help averef
  return
end

% avematrix = eye(chans)-ones(chans)*1/chans;
% data = avematrix*data; % implement as a matrix multiply
% else (faster?)

meandata = sum(data)/chans;
data = data - ones(chans,1)*meandata;

% treat optional ica parameters
if nargin == 2
	winv  = pinv(W);
    size1 = size(winv,1);
	avematrix = eye(size1)-ones(size1)*1/size1;
	W = pinv(avematrix*winv);
end
if nargin >= 3
	winv = pinv(W*S);
    size1 = size(winv,1);
	avematrix = eye(size1)-ones(size1)*1/size1;
	W = pinv(avematrix*winv);
	S = eye(chans);
end


function FOut = ReOrderVariables( FIn, NewVarOrder )

    %Check that new variable order is OK:
    [isMem MAP] = ismember( NewVarOrder, FIn.var );
    assert( length(FIn.var) == length(NewVarOrder), 'Different # variables!' );
    assert( all(isMem), 'Some of new variables not in factor!' );
    assert( length(NewVarOrder) == length(unique(NewVarOrder)), 'Some variables repeated!');

    %Set up variables and cardinality; preallocate
    FOut.var = NewVarOrder;
    FOut.card = FIn.card( MAP );
    FOut.val = ones(1,prod(FIn.card));

    for i=1:prod(FIn.card)
        %Loop through every value in FIn, and copy to FOut as approprate
        OldAssignment = IndexToAssignment(i, FIn.card);
        NewAssignment = OldAssignment( MAP );

        newIdx = AssignmentToIndex( NewAssignment, FOut.card );
        FOut.val( newIdx ) = FIn.val( i );
    end
end


function plaza = create_plaza(B, L)
global plazalength;
topgap = 5;
bottomgap = 1;
plaza = zeros(plazalength,B+2);
plaza(1:plazalength,[1,2+B]) = -888;
if mod(B-L,2)==0
    for col = 2:B/2 - L/2 + 1
        for row = 1:(plazalength-1)/2 - topgap * (col-1)
            plaza(row,[col, B+3-col]) = -888;
        end
        for row = (plazalength+3)/2 + bottomgap*(col-1):plazalength
            plaza(row,[col, B+3-col]) = -888;
        end
    end
else
    plaza(1:plazalength, B+3) = -888;
    for col = 2:(B+1)/2 - L/2 + 1
        for row = 1:(plazalength-1)/2 - topgap * (col-1)
            plaza(row, [col, B+4-col]) = -888;
        end
        for row = (plazalength+3)/2 + bottomgap*(col-1):plazalength
            plaza(row, [col, B+4-col]) = -888;
        end
    end
end


function com = calcCoM()
global uLINK

M  = TotalMass(1);
MC = calcMC(1);
com = MC / M;


function Index = SVM_AFdetection_withoutTrainingModel(test_feature,test_class)
%******************************************************
% $ This function is used for calculating the SVM-based AF detection
% indices using the trained 9-fold models from MIT AF database. The
% determination of the AF is based on the voting resuts from the 9-fold
% models
%
% $ Reference: Q. Li, C. Y. Liu, J. Oster and G. D. Clifford. Chapter:
% Signal processing and feature selection preprocessing for classification
% in noisy healthcare data. In book: Machine Learning for Healthcare
% Technologies, Edition: 1st, Publisher: IET, Editors: David A. Clifton,
% 2016.
%
% Roberta Collaca, Julian Oster, Clifford
%
% $ Variable declaration: Input:
%   test_feature: the feature metrix from AF detection, you need to run
%       AF_feature function first to obtain the AF features, each row is a
%       feature vector from an RR interval time series
%   test_class: the labels of AF for the tested RR ineterval time series,
%       N*1 metrix, 1 for AF and 0 for non-AF
% Output:
%   Index: AF detection indices output, with the defined order of indices
%   of TP FN FP TN Se Sp Acc PPV NPV J in turn.
%
%   LICENSE:
%       This software is offered freely and without warranty under
%       the GNU (v3 or later) public license. See license file for
%       more information

if nargin<2
    test_class = ones(length(test_feature),1);
end

% if strcmp(computer,'GLNXA64')
%     addpath('/home/adriana/libsvm-320/matlab');
% elseif strcmp(computer, 'MACI64')
%     addpath('/Users/adri/Documents/MATLAB/libsvm-3.20/libsvm-3.20/matlab/');
% end

model_all = load('models.mat');
meanx_all = load('means.mat');
stdx_all = load('stds.mat');

select=[2 3 4 5 6 7 12 14];
test_feature=test_feature(:,select);

predict_all=[];
for k = 1:9
    model=model_all.model_all{k};
    meanx=meanx_all.meanx_all{k};
    stdx=stdx_all.stdx_all{k};
    xtest=bsxfun(@minus, test_feature, meanx);
    xtest=bsxfun(@rdivide, xtest,stdx);
    [predict_all(:,k), accuracy_test, ytest_out] = svmpredict(test_class, xtest, model, '-b 1');
end

vote=sum(predict_all');
vote(find(vote<5))=0;
vote(find(vote>=5))=1;
vote=vote';

TP=length(find(test_class==1 & vote==1));
FP=length(find(test_class==0 & vote==1));
FN=length(find(test_class==1 & vote==0));
TN=length(find(test_class==0 & vote==0));
Se=TP/(TP+FN);
Sp=TN/(TN+FP);
Acc=(TP+TN)/length(test_class);
PPV=TP/(TP+FP);
NPV=TN/(TN+FN);
J=Se+Sp-1;
% Index=[TP FN FP TN Se Sp Acc PPV NPV J];

% Edited by Adriana N Vest
% Changed output Index to include only AF prediction, not accuracy
Index = [vote];
end


% op_addrcvrs.m
% Jamie Near, McGill University 2014.
%
% USAGE:
% [out,fids_presum,specs_presum,ph,sig]=op_addrcvrs(in,point,mode,coilcombos);
%
% DESCRIPTION:
% Perform weighted coil recombination for MRS data acquired with a reciever
% coil array.
%
% INPUTS:
% in            = input spectrum in matlab structure format.
% point         = point of fid to use for phase estimation (optional. Default = 1);
% mode          = Method for estimating the coil weights and phases (optional.  Default = 'w').
%                 -'w' performs amplitude weighting of channels based on the
%                 maximum signal of each coil channel.
%                 -'h' performs amplitude weighting of channels based on the
%                 maximum signal of each coil channel divided by the square of
%                 the noise in each coil channel (as described by Hall et al.
%                 Neuroimage 2014).
% coilcombos    = The predetermined coil weights and phases and amplitudes as
%                 generated by the op_getcoilcombos.m function.  If this
%                 argument is provided, the 'point', and 'mode', arguments
%                 will be ignored.  (optional.  Default = []).
%
% OUTPUTS:
% out           = Output dataset with coil channels combined.
% fids_presum   = Input data with coil channels in phase (time domain).
% specs_presum  = Input data with coil channels in phase (frequency domain).
% ph            = Vector of applied coil phases (in degrees).
% sig           = Vector of coil weights.

function [out,fids_presum,specs_presum,ph,sig]=op_addrcvrs(in,point,mode,coilcombos);

if in.flags.addedrcvrs || ~in.dims.coils
    disp('WARNING:  Only one receiver channel found!  Returning input without modification!');
    out=in;
    out.flags.addedrcvrs=1;
    fids_presum=in.fids;
    specs_presum=in.specs;
    ph=0;
    sig=1;
else

    %To get best possible SNR, add the averages together (if it hasn't already been done):
    if ~in.flags.averaged
        av=op_averaging(in);
    else
        av=in;
    end

    %also, for best results, we will combine all subspectra:
    if nargin<4
        if in.flags.isFourSteps
            av=op_fourStepCombine(av);
        end
        if in.dims.subSpecs>0
            av=op_combinesubspecs(av,'summ');
        end
        if nargin<3
            mode = 'w';
            if nargin<2
                point=1;
            end
        end
    end
    avfids=av.fids;
    avspecs=av.specs;

    %initialize phase matrix and the amplitude maxtrix that are the size of nPoints x Coils
    %ph=ones(in.sz(in.dims.t),in.sz(in.dims.coils));
    %sig=ones(in.sz(in.dims.t),in.sz(in.dims.coils));

    %now start finding the relative phases between the channels and populate
    %the ph matrix
    for n=1:in.sz(in.dims.coils)
        if nargin<4
            %ph(:,n)=phase(avfids(point,n,1,1))*ph(:,n);
            phs(n)=phase(avfids(point,n,1,1));
            switch mode
                case 'w'
                    %sig(:,n)=abs(avfids(point,n,1,1))*sig(:,n);
                    sigs(n)=abs(avfids(point,n,1,1));
                case 'h'
                    S=max(abs(avfids(:,n,1,1)));
                    N=std(avfids(end-100:end,n,1,1));
                    %sig(:,n)=(S/(N.^2))*sig(:,n);
                    sigs(n)=(S/(N.^2));
            end
        else
            %ph(:,n)=coilcombos.ph(n)*ph(:,n);
            phs(n)=coilcombos.ph(n);
            sigs(n)=coilcombos.sig(n);
        end
    end

    %now replicate the phase matrix to equal the size of the original matrix:
    % replicate=in.sz;
    % replicate(1)=1;
    % replicate(in.dims.coils)=1;
    % ph=repmat(ph,replicate);
    % sig=repmat(sig,replicate);
    sigs=sigs/norm(sigs(:));

    ph=ones(in.sz);
    sig=ones(in.sz);

    if in.dims.coils==1
        for n=1:in.sz(1)
            ph(n,:)=phs(n)*ph(n,:);
            sig(n,:)=sigs(n)*sig(n,:);
        end
    elseif in.dims.coils==2
        for n=1:in.sz(2)
            ph(:,n,:)=phs(n)*ph(:,n,:);
            sig(:,n,:)=sigs(n)*sig(:,n,:);
        end
    elseif in.dims.coils==3
        for n=1:in.sz(3)
            ph(:,:,n,:)=phs(n)*ph(:,:,n,:);
            sig(:,:,n,:)=sigs(n)*sig(:,:,n,:);
        end
    elseif in.dims.coils==4
        for n=1:in.sz(4)
            ph(:,:,:,n,:)=phs(n)*ph(:,:,:,n,:);
            sig(:,:,:,n,:)=sigs(n)*sig(:,:,:,n,:);
        end
    elseif in.dims.coils==5
        for n=1:in.sz(5)
            ph(:,:,:,:,n)=phs(n)*ph(:,:,:,:,n);
            sig(:,:,:,:,n)=sigs(n)*sig(:,:,:,:,n);
        end
    end

    %now apply the phases by multiplying the data by exp(-i*ph);
    fids=in.fids.*exp(-i*ph);
    fids_presum=fids;
    specs_presum=fftshift(ifft(fids,[],in.dims.t),in.dims.t);

    %Apply the amplitude factors by multiplying the data by amp;
    if mode=='w' || mode=='h'
        fids=fids.*sig;
    end

    %now sum along coils dimension
    fids=sum(fids,in.dims.coils);
    fids=squeeze(fids);

    %re-calculate Specs using fft
    specs=fftshift(ifft(fids,[],in.dims.t),in.dims.t);

    %change the dims variables
    if in.dims.t>in.dims.coils
        dims.t=in.dims.t-1;
    else
        dims.t=in.dims.t;
    end
    dims.coils=0;
    if in.dims.averages>in.dims.coils
        dims.averages=in.dims.averages-1;
    else
        dims.averages=in.dims.averages;
    end
    if in.dims.subSpecs>in.dims.coils
        dims.subSpecs=in.dims.subSpecs-1;
    else
        dims.subSpecs=in.dims.subSpecs;
    end
    if in.dims.extras>in.dims.coils
        dims.extras=in.dims.extras-1;
    else
        dims.extras=in.dims.extras;
    end

    %re-calculate the sz variable
    sz=size(fids);

    %FILLING IN DATA STRUCTURE
    out=in;
    out.fids=fids;
    out.specs=specs;
    out.sz=sz;
    out.dims=dims;

    %FILLING IN THE FLAGS
    out.flags=in.flags;
    out.flags.writtentostruct=1;
    out.flags.addedrcvrs=1;

end

end


function [ep,out] = VBA_groupBMC_btwConds(L,options,factors)
% group-level between-condition Bayesian model comparison
% function Ltilde = VBA_groupBMC_btwConds(L,options,factors)
% IN:
%   - L: nmXnsxnc array of log-model evidences (nm models; ns subjects; nc
%   conditions).
%   - options: a structure containing the following fields:
%       .DisplayWin: flag for display window
%       .verbose: flag for summary statistics display
%       .families: a cell array of size nf, which contains the indices of
%       the models that belong to each of the nf families.
%   - factors: n1Xn2X...Xnf factorial condition attribution matrix. Each
%   entry contains the index of the corresponding condition. This is used in
%   case of a factorial design, to gather conditions into orthogonal
%   factors.
% OUT:
%   - ep: a nfX1 vector containing the exceedance probability of no
%   difference in models along each of the nf dimensions of the factorial
%   design space (if design is not factorial, then nf=1).
%   - out: structure containing the following fields:
%       .dt: the algorithm execution time (in sec)
%       .date: date vector, in matlab format (see clock.m)
%       .families: a cell array of size 2Xnf, which contains the indices of
%       the models that belong to each of the tuples families 'equal' and
%       'not equal', for each dimension of the factorial design.
%       .options: this is useful when using default options
%       .C: ncXnt tuple label matrix (where the number of tuples is
%       nt=nm^nc). Each column identifies a nc-tuple by the index of models
%       in each of the  possible conditions.
%       .VBA: a nfX1 structure containing the output of VBA_groupBMC.m,
%       which has been called for each dimension of the factorial design.

options.tStart = tic;
[nm,ns,nc] = size(L);
try;options;catch;options=[];end
if nc==1
    disp('Error: only one condition detected!')
    ep = [];
    out = [];
    return
end
if ~isfield(options,'verbose')
    options.verbose = 1;
end
if ~isfield(options,'DisplayWin')
    options.DisplayWin = 1;
end
if ~isfield(options,'families')
    options.families = [];
end
if ~isempty(options.families)
    nfam = length(options.families);
    Cfam = zeros(nm,1);
    tmp = [];
    for i=1:nfam
        indf = options.families{i};
        if isempty(indf)
            disp(['Error: family #',num2str(i),' is empty!'])
            ep = [];
            out = [];
            return
        end
        Cfam(indf) = i;
        if ~isempty(intersect(tmp,indf))
            disp('Error: families are not mutually exclusive!')
            ep = [];
            out = [];
            return
        end
        tmp = [tmp; VBA_vec(indf)];
    end
    if ~isequal(VBA_vec(unique(tmp)),VBA_vec(1:nm))
        if numel(unique(tmp)) < nm
            disp('Error: families do not cover the entire set of models!')
        else
            disp('Error: families contain models that do not exist!')
        end
        ep = [];
        out = [];
        return
    end
else
    Cfam = VBA_vec(1:nm);
end

try;factors;catch;factors=VBA_vec(1:nc);end
sf = size(factors);
sf(sf<=1) = [];
nf = size(sf,2); % number of factors/dimensions across conditions
indf = cell(nf,1);
for f=1:nf
    nlevels = size(factors,f); % #levels in this dimension
    nconds = numel(factors)/nlevels; % #conditions per level
    indf{f} = zeros(nconds,nlevels);
    strpar = repmat([':,'],1,nf);
    strpar(end) = [];
    strpar(2*(f-1)+1) = 'k';
    for k=1:nlevels
        eval(['indf{f}(:,k) = VBA_vec(factors(',strpar,'));'])
    end
end
% form nc-tuples
[Ccon] = VBA_getNtuples(nm,nc,0);
nt = size(Ccon,2);
fam = cell(2,nf);
Lt = zeros(nt,ns);
if options.verbose
    fprintf(1,['Forming tuples families... ']);
    fprintf(1,'%6.2f %%',0)
end
for i=1:nt
    Ci = Ccon(:,i);
    for j=1:nc
        Lt(i,:) = Lt(i,:) + L(Ci(j),:,j);
    end
    % pool conditions across dimension
    for f=1:nf
        nconds = size(indf{f},1);
        flag = 1;
        for k=1:nconds
            flag = flag && isequal(length(unique(Cfam(Ci(indf{f}(k,:))))),1);
        end
        if flag
            fam{1,f} = [fam{1,f};i];
        else
            fam{2,f} = [fam{2,f};i];
        end
    end
    if options.verbose
        fprintf(1,repmat('\b',1,8))
        fprintf(1,'%6.2f %%',100*i/nt)
    end
end
if options.verbose
    fprintf(1,repmat('\b',1,8))
    fprintf(' OK.')
    fprintf('\n')
end

% perform per-condition BMS
for i=1:nc
    VBA_disp({'---',['[per-condition BMS: condition #',num2str(i),']']},options)
    [out.VBA.cond(i).posterior,out.VBA.cond(i).out] = VBA_groupBMC(L(:,:,i),options);
end

% perform btw-condition BMS
opt.verbose = 0;
opt.DisplayWin = options.DisplayWin;
ep = zeros(nf,1);
out.pep = zeros(nf,1);
for f=1:nf
    if nf >1
        VBA_disp({'---',['[factorial design: dimension #',num2str(f),' (',num2str(size(factors,f)),' levels)]'],'---'},options)
    else
        VBA_disp({'---',['[btw-condition stability assessment]'],'---'},options)
    end
    opt.families = fam(:,f);
    [out.VBA.btw(f).posterior,out.VBA.btw(f).out] = VBA_groupBMC(Lt,opt);

    %-- display summary statistics
    ep(f) = out.VBA.btw(f).out.families.ep(1);
    out.pep(f) = ep(f).*(1-out.VBA.btw(f).out.bor) + 0.5*out.VBA.btw(f).out.bor;

    if options.verbose
        if floor(out.VBA.btw(f).out.dt./60) == 0
            timeString = [num2str(floor(out.VBA.btw(f).out.dt)),' sec'];
        else
            timeString = [num2str(floor(out.VBA.btw(f).out.dt./60)),' min'];
        end
        n1 = length(opt.families{1});
        n2 = length(opt.families{2});
        fprintf(['VB converged in ',num2str(length(out.VBA.btw(f).out.F)),' iterations (took ~',timeString,').','\n'])
        fprintf(['Dimensions:','\n'])
        fprintf(['     - subjects: n=',num2str(ns),'\n'])
        fprintf(['     - conditions: c=',num2str(nc),'\n'])
        fprintf(['     - models: K=',num2str(nm),'\n'])
        fprintf(['     - ',num2str(nc),'-tuples: t=',num2str(nt),' (',num2str(n1),'+',num2str(n2),')','\n'])
        fprintf(['Posterior probabilities:','\n'])
        fprintf(['     - RFX: p(H1|y)= ','%4.3f','\n'],1-out.VBA.btw(f).out.bor)
        fprintf(['     - null: p(H0|y)= ','%4.3f','\n'],out.VBA.btw(f).out.bor)
        fprintf(['Assessment of model stability across conditions:','\n'])
        fprintf(['     - exc. prob.: ','%4.3f','\n'],ep(f))
        fprintf(['     - protected exc. prob.: ','%4.3f','\n'],out.pep(f))
        fprintf('\n')
    end
end

% wrap-up
out.dt = toc(options.tStart);
out.date = clock;
out.options = options;
out.families = fam;
out.factors = factors;
out.Ccon = Ccon;
out.L = L;

if options.DisplayWin
    VBA_displayGroupBMCbtw(ep,out)
end


function quality_test ( )

%*****************************************************************************80
%
%% QUALITY_TEST tests the QUALITY library.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 August 2005
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'QUALITY_TEST\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Test the QUALITY library.\n' );

  quality_test_cvt ( );
  quality_test_halton ( );
  quality_test_sphere ( );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'QUALITY_TEST\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end


function gradWeight = getGradWtFromClusters(viewClusters,i)
    thisCluster = find(cellfun(@(x)(sum(x==i)),viewClusters));
    meanElems = mean(cellfun(@length,viewClusters));
    gradWeight = meanElems/length(viewClusters{thisCluster});
end


%--- help for transform_parameters ---
%
%  transform the parameters under linear restrictions and or dirichlet priors
%
%  ::
%
%    [obj,x0,lb,ub,vcov]=transform_parameters(obj,x0,lb,ub)
%    [obj,x0,lb,ub,vcov]=transform_parameters(obj,x0,lb,ub,vcov)
%
%  Args:
%
%     obj (rise | dsge | rfvar | svar): model object
%
%     x0 (empty | n x 1 vector): initial conditions of estimation in a space that
%       the user understands
%
%     lb (n x 1 vector): lower bound of the search space
%
%     ub (n x 1 vector): upper bound of the search space
%
%     vcov (empty | n x n matrix): variance covariance of the parameters
%
%  Returns:
%     :
%
%     - **obj** [rise|dsge|rfvar|svar]: model object with all restrictions set
%       up
%
%     - **x0** [empty|m x 1 vector]: transform initial conditions with m<=n
%
%     - **lb** [m x 1 vector]: transformed lower bound of the search space with
%       m<=n
%
%     - **ub** [m x 1 vector]: transformed upper bound of the search space with
%       m<=n
%
%     - **vcov** [empty|m x m matrix]: transformed variance covariance of the
%       parameters with m<=n
%
%  Note:
%
%     - Some checks have to be made after transformation in order to insure
%       that no element in the transformed lower bound exceeds its upper bound
%       counterpart.
%
%  See also:
%     - untransform_parameters
%
%