 function xs = wls_pscd(x, G, yi, dqi, wi, dj, niter)
% Runs one iteration of coordinate descent in the style suitable
% for the inner part of paraboloidal surrogates coordinate descent updates
% cost function: J(x) = ?
% Output
%	x [np,1]	updated image
%
% This is for TESTING ONLY.
% IT IS NOT USEFUL because it is unregularized and slow
%
% Copyright Aug 2000, Jeff Fessler, The University of Michigan

NOT DONE!

if nargin < 3, ir_usage, end

if ~isvar('wi') || isempty(wi)
	wi = ones(size(yi));
end
if ~isvar('niter') || isempty(niter)
	niter = 1;
end

% backproject curvatures for denominator
if ~isvar('dj') || isempty(dj)
	dj = wi(:)' * G.^2;
end

%
% now we are minimizing the quadratic function:
% J(x) = \sum_k q_i([Gx]_i)
%	where q_i(l) = doth' (l-l0) - 1/2 (l-l0)' D(n) (l-l0)
% ?
% d/dli P(l;l0) = dothi - ni (li-l0i)
% Q(x) == doth' G (x-x0) - 1/2 (x-x0)' G' D(n) G (x-x0)
% ??? d/dx_j Q(x) = \sumi \gij \dothi - \sumi \gij \ni [G(x-x0)]_i
% d/dx_j Q(x) = \sumi \gij [d/dli P(l;l0)]
% -d^2/dx_j^2 Q(x) = \sumi \gij^2 \ni
%
dqi = doth(:);	% initial surrogate derivatives

xs = zeros(length(x), nsubiter);
xs(:,1) = x;

%
% loop over subiterations of paraboloid
%
for it=1:niter

	%
	% loop over pixels
	%
	for jj=1:numel(x)
		g = G(:,jj);
		x0j = x(jj);
		x(jj) = x0j + (dqi' * g) / dj(jj);
		x(jj) = max(x(jj),0);
		dqi = dqi - wi .* (g * (x(jj) - x0j));

	end
	xs(:,it) = x;
end


% OverlayRegCheck: shell for mrAlign3 to compare inplanes for a session
%                  with interpolated inplanes, given the bestrotvol.
%                   This is intended as an update for regCheckRotAll.
%
%
%
% (regCheckRotAll)- Script that interpolates the inplanes corresponding
%                to the estimated rotation (rot) and translation (trans)
%                and displays slice by slice the original inplanes, the
%                interpolated inplanes and a mosaic of both.
%
%  Oscar Nestares - 5/99
%  Rory Sayres - 8/04, updated to use the overlayVol interface.

% Size of the original inplanes
[NyI NxI NzI] = size(INPLANE.anat);
inp = INPLANE.anat;

% interpolating the inplanes
hmsgbox = msgbox('Wait while interpolating the inplanes...'); drawnow
inpMf = regInplanes(reshape(volume,[sagSize, numSlices]),...
                    NxI, NyI, NzI, scaleFac, rot, trans);

% Correct intensity (selecting 'No' doesn't do anything useful)
fprintf('Correcting intensity...\n');
Limit = 4;
IntFunc = 'regEstFilIntGrad'; PbyPflag = 0;
inp = regCorrMeanInt(inp);
% intensity estimation
[Int Noise] = feval(IntFunc, inp, PbyPflag);
% intensity normalization
inp = regCorrIntGradWiener(inp, Int, Noise);
% robust mean and contrast normalization
inp = regCorrContrast(inp,Limit);
% intensity estimation
[IntM NoiseM] = feval(IntFunc, inpMf, PbyPflag);
% intensity normalization
inpMf = regCorrIntGradWiener(inpMf, IntM, NoiseM);
% robust mean and contrast normalization
[inpMf, pM] = regCorrContrast(inpMf,Limit);

close(hmsgbox);

% ensure inplanes and interp inplanes are same size
if size(inp) ~= size(inpMf)
    for i = 1:size(inp,3)
        tmp(:,:,i) = imresize(inp(:,:,i),size(inpMf(:,:,i)));
    end
    inp = tmp;
end

% call external overlay interface
FF = overlayVolumes(inp,inpMf);

% % checking the alignment
% FF = figure;
% SS = get(0,'ScreenSize');
% set(FF,'Position', [1 -40 SS(3)/3  SS(4)-80])
% for k=1:size(inpMf,3)
%    figure(FF)
%    subplot(3,1,1)
%    imagesc(inp(:,:,k));
%    axis('image'); colormap('gray'); axis('off');
%    subplot(3,1,2)
%    imagesc(regMosaic(regNormal(inpMf(:,:,k),0,1),...
%                      regNormal(inp(:,:,k),0,1)));
%    axis('image'); colormap('gray'); axis('off');
%    subplot(3,1,3)
%    imagesc(inpMf(:,:,k));
%    axis('image'); colormap('gray'); axis('off');
%    disp('Press a key to continue...')
%    pause
% end
%
% close(FF)

return


% RunMCMCSimForBPHMM
%  Generic harness for running many iterations of MCMC,
%   allows sensible reporting/saving of samples and diagnostics
%USAGE
%  Usually called from more "user-friendly" function "runBPHMM"
%  but if specific data and initial configuration Psi are available,
%  >> RunMCMCForBPHMM( data, Psi, algP, outP )
%INPUT
%  data : SeqData object, defining a collection of sequences to fit model
%  Psi  : initial model state
%           usually generated by a function in the "init" folder
%  algParams : specifies MCMC behavior (# iterations, proposal distribs)
%           see defaults/defaultMCMCParams_BPHMM.m for details
%  outParams : specifies MCMC output behavior
%           how often to save samples, write to disk, etc.
%           see defaults/defaultOutputParams_BPHMM.m for details
%OUTPUT
%  Markov Chain state variables saved at preset frequency to hard drive
%     at filepath location specified in outParams.saveDir

function [ChainHist] = RunTimedMCMCSimForBPHMM( data, Psi, algParams, outParams, model )
tic;

if isfield( Psi, 'F' )
    % Stating chain from scratch
    n = 0;
    logPr = calcJointLogPr_BPHMMState( Psi, data );
    ChainHist = recordMCMCHistory_BPHMM( 0, outParams, [], Psi, logPr  );

    fprintf( 'Initial Config: \n' );
    printTimedMCMCSummary_BPHMM( 0, Psi, logPr, algParams);
else
    ChainHist = Psi;
    Psi = unpackBPHMMState(  ChainHist.Psi(end), data, model );
    logPr = calcJointLogPr_BPHMMState( Psi, data );
    n = ChainHist.iters.Psi(end );
    fprintf( 'Resumed Config: \n' );
    printTimedMCMCSummary_BPHMM( 0, Psi, logPr, algParams);
end

fprintf( 'Running MCMC Sampler %d : %d ... \n', outParams.jobID, outParams.taskID );

while toc < algParams.TimeLimit
    n = n + 1;
    Psi.iter = n;

    % Perform 1 iteration of MCMC, moving to next Markov state!
    [Psi, Stats] = BPHMMsample( Psi, data, algParams );

    % Diagnose convergence by calculating joint log pr. of all sampled vars
    if n == 1 || rem(n, outParams.logPrEvery)==0
        % NB: not passing "data" as arg means Psi stores all X suff stats
        logPr = calcJointLogPr_BPHMMState( Psi );
    end

    %Record current sampler state
    %  NB: internally only records at preset frequency
    ChainHist = recordMCMCHistory_BPHMM( n, outParams, ChainHist, Psi, logPr, Stats );

    doSaveToDisk = n==1 || rem(n, outParams.saveEvery)==0 || toc > algParams.TimeLimit;
    if doSaveToDisk
        filename = fullfile( outParams.saveDir,  'SamplerOutput.mat' );
        save(filename, '-struct', 'ChainHist');
    end

    if n == 1 || rem(n, outParams.printEvery)==0
       printTimedMCMCSummary_BPHMM( n, Psi, logPr, algParams);
    end

end % loop over sampler iterations

fprintf( '<<<<< --------------------------------------------------- \n');

end % main function


function add_header_to_bin(bin_filename, fc_requested, fc_programmed, fs_requested, fs_programmed)

[fc_requested_exist, fc_programmed_exist, fs_requested_exist, fs_programmed_exist] = read_header_from_bin(bin_filename);
if fc_requested_exist ~= inf
    disp('There is already a header! Just return.');
    disp(['fc_requested ' num2str(fc_requested_exist) ' fc_programmed ' num2str(fc_programmed_exist)  ' fs_requested ' num2str(fs_requested_exist)  ' fs_programmed ' num2str(fs_programmed_exist) ]);
    return;
end

fid = fopen(bin_filename, 'r');

if fid==-1
    disp('add_header_to_bin: Can not open file for read!');
    return;
end

tmp_store = fread(fid, inf, 'uint8');
fclose(fid);

fc_requested_magic = 73492.215;
fc_programmed_magic = -0.7923597;
fs_requested_magic = -189978508;
fs_programmed_magic = 93.126712;

reserve1_magic = -53243.129;
reserve2_magic = 0.0008123898;
reserve3_magic = -6.0098321;
reserve4_magic = 237.09983;

fid = fopen(bin_filename, 'w');

if fid==-1
    disp('add_header_to_bin: Can not open file for write!');
    return;
end

fwrite(fid, fc_requested_magic, 'double');
fwrite(fid, fc_requested, 'uint64');

fwrite(fid, fc_programmed_magic, 'double');
fwrite(fid, fc_programmed, 'uint64');

fwrite(fid, fs_requested_magic, 'double');
fwrite(fid, fs_requested, 'uint64');

fwrite(fid, fs_programmed_magic, 'double');
fwrite(fid, fs_programmed, 'uint64');

fwrite(fid, reserve1_magic, 'double');
fwrite(fid, 0, 'uint64');

fwrite(fid, reserve2_magic, 'double');
fwrite(fid, 0, 'uint64');

fwrite(fid, reserve3_magic, 'double');
fwrite(fid, 0, 'uint64');

fwrite(fid, reserve4_magic, 'double');
fwrite(fid, 0, 'uint64');

fwrite(fid, tmp_store, 'uint8');

fclose(fid);


% function calvinNNDetection()
%
% Copyright by Holger Caesar, 2016

% Global variables
global glDatasetFolder glFeaturesFolder;
assert(~isempty(glDatasetFolder) && ~isempty(glFeaturesFolder));

%%% Settings
% Dataset
vocYear = 2010;
trainName = 'train';
testName  = 'val';

% Specify paths
vocName = sprintf('VOC%d', vocYear);
datasetDir = [fullfile(glDatasetFolder, vocName), '/'];
outputFolder = fullfile(glFeaturesFolder, 'CNN-Models', 'FRCN', vocName, sprintf('%s-testRelease', vocName));
netPath = fullfile(glFeaturesFolder, 'CNN-Models', 'matconvnet', 'imagenet-vgg-verydeep-16.mat');
logFilePath = fullfile(outputFolder, 'log.txt');

% Fix randomness
randSeed = 42;
rng(randSeed);

% Setup dataset specific options and check validity
setupDataOpts(vocYear, testName, datasetDir);
global DATAopts;
assert(~isempty(DATAopts), 'Error: Dataset not initialized properly!');

% Task-specific
nnOpts.testFn = @testDetection;
nnOpts.misc.overlapNms = 0.3;
nnOpts.derOutputs = {'objective', 1, 'regressObjective', 1};

% General
nnOpts.batchSize = 2;
nnOpts.numSubBatches = nnOpts.batchSize; % 1 image per sub-batch
nnOpts.weightDecay = 5e-4;
nnOpts.momentum = 0.9;
nnOpts.numEpochs = 16;
nnOpts.learningRate = [repmat(1e-3, 12, 1); repmat(1e-4, 4, 1)];
nnOpts.misc.netPath = netPath;
nnOpts.expDir = outputFolder;
nnOpts.gpus = 1; % for automatic selection use: SelectIdleGpu();

% Create outputFolder
if ~exist(outputFolder, 'dir')
    mkdir(outputFolder);
end

% Start logging
diary(logFilePath);

%%% Setup
% Start from pretrained network
net = load(nnOpts.misc.netPath);

% Setup imdb
imdb = setupImdbDetection(trainName, testName, net);

% Create calvinNN CNN class
% By default, network is transformed into fast-rcnn with bbox regression
calvinn = CalvinNN(net, imdb, nnOpts);

%%% Train
calvinn.train();

%%% Test
stats = calvinn.test();

%%% Eval
evalDetection(testName, imdb, stats, nnOpts);


function vw = computeResStdMap(vw, scanList, forceSave)
%
% vw = computeResStdMap(vw, [scanList], [forceSave])
%
% Cycles through tSeries, computing the residual std of the
% functional images.  Puts them together into a parameter map and
% calls setParameterMap to set vw.map = stdMap.
% Residual time series have the harmonics of freq removed
%
% scanList:
%   0 - do all scans
%   number or list of numbers - do only those scans
%   default - prompt user via selectScans dialog
%
% forceSave: 1 = true (overwrite without dialog)
%            0 = false (query before overwriting)
%           -1 = do not save
%
%
% If you change this function make parallel changes in:
%    computeCorAnal, computeStdMap, computeMeanMap
%
% rmk, 05/05/99
% djh 2/2001, mrLoadRet-3.0

if notDefined('forceSave'),   forceSave = 0;   end

nScans = viewGet(vw,'numScans');

if strcmp(vw.mapName,'resStdMap')
    % If exists, initialize to existing map
    map=vw.map;
else
    % Otherwise, initialize empty cell array
    map = cell(1,nScans);
end

% (Re-)set scanList
if ~exist('scanList','var')
    scanList = selectScans(vw);
elseif scanList == 0
    scanList = 1:nScans;
end
if isempty(scanList)
  error('Analysis aborted');
end

% Compute it
waitHandle = mrvWaitbar(0,'Computing res std images from the tSeries.  Please wait...');
ncScans = length(scanList);
for iScan = 1:ncScans
    scan    = scanList(iScan);
    dims    = viewGet(vw, 'sliceDims', scanNum);
    nCycles = viewGet(vw, 'numcycles', scanNum);
    datasz  = viewGet(vw, 'dataSize',  scanNum);

    map{scan} = NaN*ones(datasz);
    for slice = sliceList(vw,scan)
        resStd = computeTSResStd(vw,scan,slice,nCycles);
        map{scan}(:,:,slice) = reshape(resStd,dims);
    end
    mrvWaitbar(scan/ncScans)
end
close(waitHandle);

% Set parameter map
vw = setParameterMap(vw,map,'resStdMap');

% Save file
if forceSave >= 0, saveParameterMap(vw, [], forceSave); end


function [y,swp]=mvk2(a,x,eps,nswp,z,rmax,varargin)
%Two-sided DMRG fast matrix-by-vector product
%   [Y,SWP]=MVK2(A,X,EPS,[NSWP],[Y],[RMAX],[OPTIONS]) Two-sided DMRG (mvk
%   is one-sided). Matrix-by-vector product of a TT-matrix A
%   by a TT-tensor X with accuracy EPS. Also, one can specify the number of
%   sweeps NSWP, initial approximation Z and the maximal TT-rank RMAX (if
%   they become too large)
%
%
% TT-Toolbox 2.2, 2009-2012
%
%This is TT Toolbox, written by Ivan Oseledets et al.
%Institute of Numerical Mathematics, Moscow, Russia
%webpage: http://spring.inm.ras.ru/osel
%
%For all questions, bugs and suggestions please mail
%ivan.oseledets@gmail.com
%---------------------------
n=a.n;
m=a.m;
att=a.tt;
corea=att.core;
psa=att.ps;
ra=att.r;
d=att.d;
%start_val='fast_mv';
start_val='rough_mv';
%start_val='random';
rmax_loc=8; %For the "rough" matrix-by-vector product
if ( nargin <= 5 || isempty(rmax) )
   rmax=1000;
end
if ( nargin <= 4 || isempty(z) )

    if ( strcmp(start_val,'random') )
    rz1=rank(a,1)*rank(x,1);
    rzd=rank(a,d+1)*rank(x,d+1);
    kf=5;
    rz=[rz1;kf*ones(d-1,1);rzd];
    z=tt_rand(n,ndims(x),rz);
    elseif (strcmp(start_val,'rough_mv'))
        rmax_loc=8; %
        xloc=round(x,0,rmax_loc);
        aloc=round(a,0,rmax_loc);
        z=round(aloc*xloc,eps);
        %z=aloc*xloc;
    elseif (strcmp(start_val,'fast_mv') )
         rz1=rank(a,1)*rank(x,1);
      rzd=rank(a,d+1)*rank(x,d+1);
      kf=5;
      rz=[rz1;kf*ones(d-1,1);rzd];
      z=tt_rand(n,ndims(x),rz);
       z=mvk2(a,x,max(eps,1e-2),10,z,rmax); %First, do it with bad accuracy
    end
end
if ( nargin <= 3 || isempty(nswp) )
  nswp = 40;
end
y=z;

%Parameters section
kick_rank=6;
verb=false;

%Warmup is to orthogonalize Y from right-to-left and compute psi-matrices
%for Ax
psi=cell(d+1,1); %Psi-matrices
%psi{d+1}=1; psi{1}=1;
psi{d+1}=eye(rank(y,d+1));
psi{1}=eye(rank(y,1));
%Here we will add convergence test
%Warmup: right-to-left QR + computation of psi matrices

corex=x.core;
psx=x.ps;
rx=x.r;

swp=1;
converged=false;
while (swp <= nswp && ~converged)
psy=y.ps;
  ry=y.r;
  corey=y.core;
     pos1=psy(d+1);
cr1=corey(psy(d):psy(d+1)-1);

for i=d:-1:2
   cr2=corey(psy(i-1):psy(i)-1);
   cr1=reshape(cr1,[ry(i),n(i)*ry(i+1)]);
   cr2=reshape(cr2,[ry(i-1)*n(i-1),ry(i)]);
   cr1=cr1.';
   [q,rm]=qr(cr1,0); rn=size(q,2); rm=rm.';
   q=q.';
   ry(i)=rn;
   corey(pos1-ry(i+1)*n(i)*ry(i):pos1-1)=q(:);
   %Convolution is now performed for psi(i) using psi(i+1) and corea, and
   %(new) core q
   cra=corea(psa(i):psa(i+1)-1); cra=reshape(cra,[ra(i),n(i),m(i),ra(i+1)]);
   cry=reshape(conj(q),[ry(i),n(i),ry(i+1)]);
   crx=corex(psx(i):psx(i+1)-1); crx=reshape(crx,[rx(i),m(i),rx(i+1)]);
   pscur=psi{i+1}; pscur=reshape(pscur,[ra(i+1),rx(i+1),ry(i+1)]); %ra,rx,ry
   %First, convolve over rx(i+1)
   crx=reshape(crx,[rx(i)*m(i),rx(i+1)]);
   pscur=permute(pscur,[2,1,3]); pscur=reshape(pscur,[rx(i+1),ra(i+1)*ry(i+1)]);
   pscur=crx*pscur; %pscur is now rx(i)*m(i)*ra(i+1)*ry(i+1)
   %Convolve over m(i),ra(i+1),n(i),ry(i+1)
    pscur=reshape(pscur,[rx(i),m(i)*ra(i+1),ry(i+1)]);
    pscur=permute(pscur,[1,3,2]);
    pscur=reshape(pscur,[rx(i)*ry(i+1),m(i)*ra(i+1)]);
    cra=reshape(cra,[ra(i)*n(i),m(i)*ra(i+1)]); cra=cra.';
    pscur=pscur*cra;
    %pscur is now rx(i)*ry(i+1)*ra(i)*n(i), it is left to convolve over
    %n(i)*ry(i+1)
    pscur=reshape(pscur,[rx(i),ry(i+1),ra(i),n(i)]);
    pscur=permute(pscur,[3,1,4,2]);
    pscur=reshape(pscur,[rx(i)*ra(i),n(i)*ry(i+1)]);
    cry=reshape(cry,[ry(i),n(i)*ry(i+1)]); cry=cry.';
    pscur=pscur*cry;
    psi{i}=pscur;
   %End of psi-block
   pos1=pos1-ry(i+1)*n(i)*ry(i);
   cr1=cr2*rm;

end
corey(pos1-ry(2)*n(1)*ry(1):pos1-1)=cr1(:);
pos1=pos1-ry(2)*n(1)*ry(1);
corey=corey(pos1:numel(corey)); %Truncate unused elements

  %left-to-right dmrg sweep
  pos1=1;
  cry_old=corey;
  psy=cumsum([1;n.*ry(1:d).*ry(2:d+1)]);
  converged=true;
  ermax=0;
  for i=1:d-1
     %We care for two cores, with number i & number i+1, and use
     %psi(i) and psi(i+2) as a basis; also we will need to recompute
     %psi(i+1)
     ps1=psi{i}; ps2=psi{i+2};
     cra1=corea(psa(i):psa(i+1)-1); cra2=corea(psa(i+1):psa(i+2)-1);
     crx1=corex(psx(i):psx(i+1)-1); crx2=corex(psx(i+1):psx(i+2)-1);
     %our convolution is
     %ps1(ra(i),rx(i),ry(i))*cra1(ra(i),n(i),m(i),ra(i+1))*
     %cra2(ra(i+1),n(i+1),m(i+1),ra(i+2))*
     %*ps2(ra(i+2),rx(i+2),ry(i+2))
     %*crx1(rx(i),m(i),rx(i+1))*cr2x(rx(i+1)*m(i+1)*rx(i+2))
     %Scheme ps1*crx1 over rx(i)

     ps1=reshape(ps1,[ra(i),rx(i),ry(i)]);
     ps1=permute(ps1,[1,3,2]); ps1=reshape(ps1,[ra(i)*ry(i),rx(i)]);
     crx1=reshape(crx1,[rx(i),m(i)*rx(i+1)]);
     ps1=ps1*crx1; %ps1 is now ra(i)*ry(i)*m(i)*rx(i+1)
     %Now convolve with matrix A over ra(i)*m(i)
     ps1=reshape(ps1,[ra(i),ry(i),m(i),rx(i+1)]);
     ps1=permute(ps1,[2,4,1,3]);
     ps1=reshape(ps1,[ry(i)*rx(i+1),ra(i)*m(i)]);
     cra1=reshape(cra1,[ra(i),n(i),m(i),ra(i+1)]);
     cra1=permute(cra1,[1,3,2,4]);
     cra1=reshape(cra1,[ra(i)*m(i),n(i)*ra(i+1)]);
     ps1=ps1*cra1; %ps1 is now ry(i)*rx(i+1)*n(i)*ra(i+1)
     %Then the ``same'' convolution is carried over for second pair of
     %cores
     ps2=reshape(ps2,[ra(i+2),rx(i+2),ry(i+2)]);
     ps2=permute(ps2,[2,1,3]);
     ps2=reshape(ps2,[rx(i+2),ra(i+2)*ry(i+2)]);
     crx2=reshape(crx2,[rx(i+1)*m(i+1),rx(i+2)]);
     ps2=crx2*ps2; %ps2 is now rx*(i+1)*m(i+1)*ra(i+2)*ry(i+2)
     %Convolve over m(i+1)*ra(i+2)
     ps2=reshape(ps2,[rx(i+1),m(i+1)*ra(i+2),ry(i+2)]);
     ps2=permute(ps2,[2,1,3]);
     ps2=reshape(ps2,[m(i+1)*ra(i+2),rx(i+1)*ry(i+2)]);
     cra2=reshape(cra2,[ra(i+1)*n(i+1),m(i+1)*ra(i+2)]);
     ps2=cra2*ps2;
     %ps2 is now ra(i+1)*n(i+1)*rx(i+1)*ry(i+2)
     %Now form superblock by contraction ps1 & ps2
     %over ra(i+1)*rx(i+1)
     ps0=reshape(ps1,[ry(i),rx(i+1),n(i),ra(i+1)]);
     ps0=permute(ps0,[1,3,2,4]);
     ps0=reshape(ps0,[ry(i)*n(i),rx(i+1)*ra(i+1)]);
     ps2=reshape(ps2,[ra(i+1),n(i+1),rx(i+1),ry(i+2)]);
     ps2=permute(ps2,[3,1,2,4]);
     ps2=reshape(ps2,[rx(i+1)*ra(i+1),n(i+1)*ry(i+2)]);
     super_core=ps0*ps2; %super_core is ry(i)*n(i)*n(i+1)*ry(i+2)
    if ( i > 1 )
     %Compute previous supercore
        cr1=corey(pos1:pos1+ry(i)*n(i)*ry(i+1)-1);
        cr2=cry_old(psy(i+1):psy(i+2)-1);
        cr1=reshape(cr1,[ry(i)*n(i),ry(i+1)]);
        cr2=reshape(cr2,[ry(i+1),n(i+1)*ry(i+2)]);
         super_core_old=cr1*cr2;
         er=norm(super_core_old(:)-super_core(:))/norm(super_core(:));

        if ( er > eps )
            converged=false;
        end
        ermax=max(er,ermax);
     %if ( verb )
     %  fprintf('i=%d er=%3.2e \n',i,er);
     %end
     end
     [u,s,v]=svd(super_core,'econ');
     s=diag(s);
     r=my_chop2(s,eps/sqrt(d-1)*norm(s)); r=min(r,rmax);
     u=u(:,1:r); s=s(1:r); v=v(:,1:r); v=v*diag(s);

     %Kick rank

     ur=randn(size(u,1),kick_rank);
     %Orthogonalize ur to u by Golub-Kahan reorth
     u=reort(u,ur);
     radd=size(u,2)-r;
     if ( radd > 0 )
        vr=zeros(size(v,1),radd);
        v=[v,vr];
     end
     r=size(u,2);

     ry(i+1)=r;
     %u is ry(i)*n(i)*ry(i+1)
     %core_new(pos1:pos1+ry(i)*n(i)*ry(i+1)-1)=u(:);
     corey(pos1:pos1+ry(i)*n(i)*ry(i+1)-1)=u(:);

     u=reshape(u,[ry(i),n(i),ry(i+1)]);

     %Compute new psi
     %ps1 is ry(i)*rx(i+1)*n(i)*ra(i+1) with u over ry(i)*n(i)
     u=conj(u);
     ps1=reshape(ps1,[ry(i),rx(i+1),n(i),ra(i+1)]);
     ps1=permute(ps1,[4,2,1,3]);
     ps1=reshape(ps1,[ra(i+1)*rx(i+1),ry(i)*n(i)]);
     u=reshape(u,[ry(i)*n(i),ry(i+1)]);
     ps1=ps1*u;
     psi{i+1}=ps1;
     %Compute (?) new v
     pos1=pos1+ry(i)*n(i)*ry(i+1);
     v=v';
     %v=reshape(v,[ry(i+1),n(i+1),ry(i+2)]);
     corey(pos1:pos1+ry(i+1)*n(i+1)*ry(i+2)-1)=v(:);
  end
  psy=cumsum([1;n.*ry(1:d).*ry(2:d+1)]);
y.core=corey;
y.r=ry;
y.ps=psy;
swp=swp+1;
if ( verb )
fprintf('swp=%d er=%3.2e trunk=%3.2e \n',swp,ermax,eps/sqrt(d-1));
end
end
if ( swp == nswp )
  fprintf('mvk2 warning: error is not fixed for maximal number of sweeps %d\n', swp);
end%end
%p1=tt_mvdot(core(a),core(x),y0);
%p2=dot(y,tt_tensor(y0));
%abs(p1-p2)/abs(p1)
%keyboard;


function [res] = mne_ex_evoked_grad_amp(inname,bmin,bmax,outname)
%
%   function [res] = mne_ex_evoked_grad_amp(inname,bmin,bmax,outname)
%
%   Compute the magnitude of the tangential gradient at each
%   sensor location using the planar gradiometer data and
%   optionally output the result to a fif file.
%
%   inname      The input file name. All average data sets are
%               read and processed
%   bmin,bmax   Baseline limits in seconds
%   outname     Optional output file name
%
%
%   Function returns the data which was or would have been written
%   to the file
%

%
%   Author : Matti Hamalainen, MGH Martinos Center
%   License : BSD 3-clause
%

me='MNE:mne_ex_evoked_grad_amp';

global FIFF;
if isempty(FIFF)
    FIFF = fiff_define_constants();
end

if nargin == 1
    do_baseline = false;
elseif (nargin == 3 || nargin == 4)
    do_baseline = true;
else
    error(me,'Wrong number of arguments');
end
%
%   Read the data
%
data = fiff_read_evoked_all(inname);
%
%   Figure out the planar gradiometer pairs
%
pairs = zeros(data.info.nchan,2);
npair = 0;
k = 1;
while k < data.info.nchan
    %
    %   First check the coil types
    %
    coil1 = data.info.chs(k).coil_type;
    coil2 = data.info.chs(k+1).coil_type;
    if (coil1 == coil2 && ...
            (coil1 == 2 || coil1 == 3012 || coil1 == 3013))
        one = data.info.ch_names{k};
        two = data.info.ch_names{k+1};
        lastone = one(length(one));
        lasttwo = two(length(two));
        %
        %   Then the channel names
        %
        if (strcmp(one(1:3),'MEG') && strcmp(one(1:3),'MEG'))
            if (strcmp(one(1:(length(one)-1)),two(1:(length(two)-1))) && ...
                    ((lastone == '2' && lasttwo == '3') || ...
                    (lastone == '3' && lasttwo == '2')))
                npair = npair + 1;
                pairs(npair,1) = k;
                pairs(npair,2) = k+1;
                k = k + 1;
            end
        end
    end
    k = k + 1;
end

if npair == 0
    error(me,'No planar gradiometers in these data');
end
%
%   Compute the amplitudes
%
fprintf(1,'Computing the amplitudes');
if do_baseline
    fprintf(1,' (Baseline = %7.1f ... %7.1f ms)',1000*bmin,1000*bmax);
end
fprintf(1,'...');
for k = 1:length(data.evoked)
    epochs = data.evoked(k).epochs;
    %
    %  Setup baseline limits
    %
    if do_baseline
        b1 = double(data.info.sfreq*bmin - data.evoked(k).first);
        b2 = double(data.info.sfreq*bmax - data.evoked(k).first);
        if b1 < 1
            b1 = 1;
        end
        if b2 > size(epochs,2)
            b2 = size(epochs,2)
        end
    else
        b1 = 1;
        b2 = 1;
    end
    %
    %   Go through all pairs
    %
    for p = 1:npair
        one = pairs(p,1);
        two = pairs(p,2);
        if b2 > b1
            base1 = sum(epochs(one,b1:b2))/(b2-b1);
            base2 = sum(epochs(two,b1:b2))/(b2-b1);
            epochs(one,:) = sqrt((epochs(one,:)-base1).*(epochs(one, ...
                :)-base1)+(epochs(two,:)-base2).*(epochs(two,:)-base2));
        else
            epochs(one,:) = sqrt(epochs(one,:).*epochs(one, ...
                :)+epochs(two,:).*epochs(two,:));
        end
    end
    data.evoked(k).epochs = epochs;
    fprintf(1,'.');
end
fprintf(1,'[done]\n');
%
%   Compose the selection name list
%
pairs = pairs(1:npair,:);
for k = 1:npair
    ch_sel_names{k} = data.info.ch_names{pairs(k,1)};
end
%
%   Omit MEG channels but include others
%
for p = 1:data.info.nchan
    if (data.info.chs(p).kind ~= FIFF.FIFFV_MEG_CH)
        k = k + 1;
        ch_sel_names{k} = data.info.ch_names{p};
    end
end
%
%   Modify the bad channel list
%
if ~isempty(data.info.bads)
    nbad = length(data.info.bads);
    for k = 1:npair
        one = data.info.ch_names{pairs(k,1)};
        two = data.info.ch_names{pairs(k,2)};
        %
        %   If one channel of the planar gradiometer is marked bad,
        %   add the other to the bad channel list
        %
        if (~isempty(strmatch(one,data.info.bads)) && ...
                isempty(strmatch(two,data.info.bads)))
            nbad = nbad + 1;
            data.info.bads{nbad} = two;
        elseif (isempty(strmatch(one,data.info.bads)) && ...
                ~isempty(strmatch(two,data.info.bads)))
            nbad = nbad + 1;
            data.info.bads{nbad} = one;
        end
    end
end
%
%   Do the picking
%
res = fiff_pick_channels_evoked(data,ch_sel_names);
%
%   Optionally write an output file
%
if nargin == 4
    fiff_write_evoked(outname,res);
    fprintf(1,'Wrote %s\n',outname);
end


function [rgb,ucs,status,RGB,UCS] = maxdistcolor_view(N,fun,varargin)
% Create a figure for interactive generation and display of MAXDISTCOLOR colors.
%
% (c) 2017-2020 Stephen Cobeldick
%
% This function has exactly the same inputs and outputs as MAXDISTCOLOR.
% See MAXDISTCOLOR for descriptions of the required and optional arguments.
%
% See also MAXDISTCOLOR MAXDISTCOLOR_DEMO SRGB_TO_CAM02UCS SRGB_TO_CIELAB
% SRGB_TO_OSAUCS COLORNAMES COLORMAP RGBPLOT AXES SET LINES PLOT

%% New Figure %%
%
figH = figure('Units','pixels', 'ToolBar','figure', 'NumberTitle','off',...
	'HandleVisibility','off', 'Name',mfilename(), 'Visible','on');
figP = get(figH, 'Position');
figY = get(figH, 'Pointer');
set(figH, 'Pointer','watch')
%
iniH = uicontrol(figH, 'Units','pixels', 'Style','text', 'HitTest','off',...
	'Visible','on',	'String','Initializing the figure... please wait.');
iniX = get(iniH,'Extent');
set(iniH,'Position',[figP(3:4)/2-iniX(3:4)/2,iniX(3:4)])
%
drawnow()
%
% First call to check input arguments and define all output arguments:
[bgr,ucs,status,RGB,UCS] = maxdistcolor(N,fun,varargin{:});
%
opts = status.options;
%
inw = true;
ohm = pow2([opts.bitR,opts.bitG,opts.bitB])-1;
%
if isempty(opts.exc)
	opts.exc = nan(0,3);
end
if isempty(opts.inc)
	opts.inc = nan(0,3);
end
%
delete(iniH)
%
%% Parameters %%
%
gap = 7;
% UI colors:
[R,G,B] = ndgrid(0:1/8:1);
smp = [R(:),G(:),B(:)];
clear R G B
txc = [0.7,0.3,0.2];
bgd = [];
fgd = [];
fBackFore(false)
% Slider steps:
bStp = [1,2]; % bits
cStp = [0.005,0.1]; % chroma
lStp = [0.005,0.1]; % lightness
% Number properties:
nRng = [1,64];
nStp = [1,5];
nFun = @(n) max(nRng(1),min(nRng(2),n));
% Table properties:
tTxt = {'exc'; 'inc'};
% Menu properties:
mTxt = {'plot'; 'sort'; 'path'; 'disp'};
mSrt = {{'none','farthest','hue','zip','lightness','a','b'},{'maxmin','minmax','longest','shortest'}};
mStr = {''; [mSrt{:}]; {'open','closed'}; {'off','time','summary','verbose'}};
% Slider properties:
sTxt = {'Cmax'; 'Cmin'; 'Lmax'; 'Lmin'; 'bitR'; 'bitG'; 'bitB'; 'start'};
sInt = [ false;  false;  false;  false;   true;   true;   true;   false];
sRng = [   0,1;    0,1;    0,1;    0,1;    1,8;    1,8;    1,8;   0,360];
sStp = [  cStp;   cStp;   lStp;   lStp;   bStp;   bStp;   bStp;    1,10];
sTwo = [    +1;     -1;     +2;     -2;      0;      0;      0;       0];
sFun = @(n,k) max(sRng(k,1),min(sRng(k,2),n));
sStr = @(x) sprintf('%.4g',round(1000*x)/1000);
% Colorspace axes:
f2s = upper(regexp(func2str(fun),'(?<=_to_)\w+','match','once'));
tmp = struct('CAM02UCS',{'J''','a''','b'''}, 'CIELAB',{'L*','a*','b*'},...
	'DIN99',{'L_{99}','a_{99}','b_{99}'}, 'OSAUCS',{'L','j','g'});
if isfield(tmp,f2s)
	zyx = {tmp.(f2s)};
else
	zyx = {'L?','a?','b?'};
	f2s = '???';
end
% Maximum chroma:
tmp = fun(smp);
mxc = max(max(abs(tmp(:,2:3))));
%
%% 3D Axes %%
%
az = [];
el = [];
%
%% Interactive Graphics Objects %%
%
% Get text width:
cnc = {'Red','Green','Blue'};
tmp = uicontrol(figH, 'Style','text', 'Units','pixels', 'String',cnc);
txw = get(tmp,'Extent');
txh = txw(4)/numel(cnc);
txw = num2cell(ones(1,3)*(7+txw(3)));
delete(tmp)
% Add drop-down menus:
mTxN = numel(mTxt);
mAxH = axes('Parent',figH, 'Units','pixels', 'Visible','off', 'View',[0,90],...
	'HitTest','off', 'Xlim',[0,1], 'Ylim',[0,2*mTxN]);
mTxH = text(zeros(1,mTxN),2*mTxN-1:-2:1, mTxt, 'parent',mAxH, 'Color',txc,...
	'VerticalAlignment','bottom','HorizontalAlignment','left');
set(mTxH(1),'Color',txc([3,2,1]));
for k = mTxN:-1:1
	if k>1
		idm = find(strcmpi(opts.(mTxt{k}),mStr{k}));
	else
		idm = 1;
	end
	mUiH(k) = uicontrol(figH, 'Style','popupmenu', 'Units','pixels',...
		'String',mStr{k}, 'Callback',{@fOptMenu,k}, 'Value',idm);
end
% Add horizontal sliders:
sTxN = numel(sTxt);
for k = sTxN:-1:1
	val = opts.(sTxt{k});
	sTxH(k) = uicontrol(figH, 'Units','pixels', 'Style','text',...
		'String',sTxt{k}, 'HorizontalAlignment','left', 'ForegroundColor',txc);
	sVaH(k) = uicontrol(figH, 'Units','pixels', 'Style','edit',...
		'String',sStr(val), 'HorizontalAlignment','left', 'Callback',{@fOptEdit,k});
	sUiH(k) = uicontrol(figH, 'Units','pixels', 'Style','slider', 'Value',1,...
		'Min',sRng(k,1), 'Max',sRng(k,2), 'Value',sFun(val,k),...
		'SliderStep',sStp(k,:)./diff(sRng(k,:)), 'Callback',@fUpDtMap);
	addlistener(sUiH(k), 'Value', 'PostSet',@(o,e)fOptSlide(o,e,k));
end
% Add tables:
tTxN = numel(tTxt);
for k = tTxN:-1:1
	tmp = opts.(tTxt{k});
	tmp(end+1:N,:) = NaN;
	tUiH(k) = uitable(figH, 'Units','pixels', 'Data',tmp, 'ColumnWidth',txw,...
		'ColumnName',cnc, 'ColumnEditable',true, 'CellEditCallback',{@fCellEdit,k});
	tTxH(k) = uicontrol(figH, 'Style','text', 'Units','pixels','ForegroundColor',txc,...
		'String',tTxt{k}, 'HorizontalAlignment','left');
	tCbH(k) = uicontrol(figH, 'Style','checkbox', 'Units','pixels','String','X',...
		'Callback',{@fCheckBox,k});
end
% Add colorbar:
bAxH = axes('Parent',figH, 'Units','pixels', 'Visible','off',...
	'HitTest','off', 'Xlim',[0.5,1.4], 'Ylim',[0,N]+0.5, 'View',[0,90],...
	'YDir','normal', 'XTick',[], 'YTick',1:N, 'Box','off');
bImH = image('CData',permute(bgr,[1,3,2]), 'Parent',bAxH);
% Add number slider:
nVaH = uicontrol(figH, 'Units','pixels', 'Style','edit', 'String',sprintf('%d',N),...
	'HorizontalAlignment','center', 'Callback',@fNumEdit);
nUiH = uicontrol(figH, 'Units','pixels', 'Style','slider', 'Value',nFun(N),...
	'Min',nRng(1), 'Max',nRng(2), 'SliderStep',nStp./diff(nRng), 'Callback',@fUpDtMap);
addlistener(nUiH, 'Value', 'PostSet',@fNumSlide);
% Add EVAL button:
eUiH = uicontrol(figH, 'Units','pixels', 'Style','pushbutton',...
	'String','pause', 'ForegroundColor',txc([3,2,1]), 'Callback',@fEvalFun);
eUiX = true;
eUiC = get(eUiH,'BackgroundColor');
%
%% Main Plot Objects %%
%
ndx = 'Colormap Index';
eds = sprintf('Euclidean Distance (%s)',f2s);
%
axp = {'Units','normalized', 'NextPlot','replacechildren', 'Clipping','off',...
	'Color','none', 'XColor',fgd, 'YColor',fgd, 'ZColor',fgd, 'UserData'};
pnp = {figH, 'Units','pixels', 'BorderType','none', 'Title','', 'BackgroundColor',bgd};
%
pAxH(10) = axes('Parent',uipanel(pnp{:}), axp{:},4);
pAxS(10) = struct('title','RGB Gamut (alphashape) [slow]',...
	'X',zyx{3}, 'Y',zyx{2}, 'Z',zyx{1}, 'fun',@fAlphaTry);
%
pAxH(9) = axes('Parent',uipanel(pnp{:}), axp{:},3);
pAxS(9) = struct('title','RGB Gamut (point cloud) [fast]',...
	'X',zyx{3}, 'Y',zyx{2}, 'Z',zyx{1}, 'fun',@fPointCloud);
%
pAxH(8) = axes('Parent',uipanel(pnp{:}), axp{:},3);
pAxS(8) = struct('title','Colors with RGB Cube',...
	'X',zyx{3}, 'Y',zyx{2}, 'Z',zyx{1}, 'fun',@fCubeRGB);
%
pAxH(7) = axes('Parent',uipanel(pnp{:}), axp{:},3);
pAxS(7) = struct('title','Colors with Sort Path',...
	'X',zyx{3}, 'Y',zyx{2}, 'Z',zyx{1}, 'fun',@fSortPath);
%
pAxH(6) = axes('Parent',uipanel(pnp{:}), axp{:},2, 'Visible','off');
pAxS(6) = struct('title','Matrix Scatter Plot',...
	'X','', 'Y','', 'Z','', 'fun',@fScatterMat);
%
pAxH(5) = axes('Parent',uipanel(pnp{:}), axp{:},2);
pAxS(5) = struct('title','Adjacent Color Matrix',...
	'X',ndx, 'Y',ndx, 'Z','', 'fun',@fAdjaNode);
%
pAxH(4) = axes('Parent',uipanel(pnp{:}), axp{:},2, 'XTick',[]);
pAxS(4) = struct('title','Bands with RGB Values',...
	'X','', 'Y',ndx, 'Z','', 'fun',@fRgbValues);
%
pAxH(3) = axes('Parent',uipanel(pnp{:}), axp{:},2, 'XTick',[]);
pAxS(3) = struct('title','Bands with Color Names',...
	'X','', 'Y',ndx, 'Z','', 'fun',@fBandName);
%
pAxH(2) = axes('Parent',uipanel(pnp{:}), axp{:},3);
pAxS(2) = struct('title','Euclidean Distance (3D Plot)',...
	'X',ndx, 'Y',ndx, 'Z',eds, 'fun',@fEuclDist);
%
pAxH(1) = axes('Parent',uipanel(pnp{:}), axp{:},2);
pAxS(1) = struct('title','Euclidean Distance (2D Plot)',...
	'X',ndx, 'Y',eds, 'Z','', 'fun',@fEuclDist);
%
pPnH = get(pAxH,'Parent');
pPnH = [pPnH{:}];
pScH = [];
%
for k = 1:numel(pAxH)
	xlabel(pAxH(k), pAxS(k).X, 'Color',fgd)
	ylabel(pAxH(k), pAxS(k).Y, 'Color',fgd)
	zlabel(pAxH(k), pAxS(k).Z, 'Color',fgd)
	title( pAxH(k), pAxS(k).title, 'Color',fgd, 'Visible','on')
	if get(pAxH(k), 'UserData')>2
		% Axes 3D view:
		view(pAxH(k),3)
		% Zlabel orientation for short strings:
		if numel(pAxS(k).Z)<7
			set(get(pAxH(k), 'ZLabel'), 'Rotation',0, 'HorizontalAlignment','right')
		end
	end
end
%
% Optional linking of 3D axes:
xud = cellfun(@(m)isequal(m,zyx{3}),{pAxS.X});
linkprop(pAxH(xud), 'View');
%
%% Initialize GUI %%
%
rgb2str = @(f,d,m)cellfun(@(v)sprintf(f,v),reshape(num2cell(round(m*d)/d,2),1,[]),'uni',0);
arrayfun(@(s,a) s.fun(a), pAxS, pAxH)
set(pPnH(:), 'Visible','off', 'HitTest','off')
set(pPnH(1), 'Visible','on', 'HitTest','on')
set(mUiH(1), 'String',{pAxS.title})
set(figH, 'Pointer',figY, 'ResizeFcn',@fSizeObj)
fNumTick()
fSizeObj()
%
%% Main Plot Functions %%
%
	function fOrient3D(axh,az,el)
		axis(axh,'equal')
		grid(axh,'on')
		view(axh,az,el)
		mat = fun([0,0,0;1,1,1]);
		set(axh, 'XGrid','on', 'YGrid','on', 'ZGrid','on',...
			'XLim',[-mxc,mxc], 'YLim',[-mxc,mxc], 'ZLim',[mat(1),mat(2)])
	end
%
	function fAlphaTry(~) % ALPHASHAPE is slow, run only on demand.
		plv = get(mUiH(strcmpi('plot',mTxt)), 'Value');
		if eUiX && inw && 4==get(pAxH(plv), 'UserData')
			set(figH, 'Pointer','watch')
			drawnow()
			fAlphaRGB(pAxH(plv))
			set(figH, 'Pointer',figY)
			inw = false;
		end
	end
	function fAlphaRGB(axh) % Show the RGB gamut using alphashape.
		delete(get(axh, 'Children'))
		[az,el] = view(axh);
		% Get gamut boundary:
		nrw = size(UCS,1);
		mxn = 1e4; % max elements for ALPHASHAPE: more elements -> slower runtime.
		stp = ceil(nrw/mxn);
		vec = [];
		for idk = 1:stp
			idu = idk:stp:nrw;
			try
				bnd = fGetBound(idu);
			catch %#ok<CTCH>
				text(0.5, 0.5, 0.5,...
					{'ALPHASHAPE not found','(requires R2014b or later)'},...
					'Parent',axh, 'HorizontalAlignment','center',...
					'FontWeight','bold', 'Color',fgd)
				return
			end
			vec = union(vec,idu(bnd(:)));
		end
		bnd = fGetBound(vec);
		% Show RGB gamut:
		patch('Faces',bnd, 'Vertices',UCS(vec,[3,2,1]), 'Parent',axh,...
			'EdgeColor','none', 'FaceColor','interp', 'FaceVertexCData',RGB(vec,:));
		% Show color nodes:
		hold(axh,'on')
		scatter3(ucs(:,3),ucs(:,2),ucs(:,1), 13, fgd, 'filled', 'Parent',axh)
		% Orient axes:
		fOrient3D(axh,az,el)
	end
	function bnd = fGetBound(idu) % Get boundary of the node cloud.
		shp = alphaShape(UCS(idu,[3,2,1]),Inf); % requires R2014b or later.
		shp.Alpha = shp.criticalAlpha('all-points');
		bnd = shp.boundaryFacets();
	end
%
	function fPointCloud(axh) % Show the RGB gamut using a point cloud.
		delete(get(axh, 'Children'))
		[az,el] = view(axh);
		% Plot point cloud:
		npt = 1e4;
		I = unique(round(linspace(1,size(UCS,1),npt)));
		scatter3(UCS(I,3),UCS(I,2),UCS(I,1), 3, RGB(I,:), 'filled', 'Parent', axh)
		hold(axh,'on')
		scatter3(ucs(:,3),ucs(:,2),ucs(:,1), 13, fgd, 'filled', 'Parent',axh)
		% Orient axes:
		fOrient3D(axh,az,el)
	end
%
	function fSortPath(axh) % Colors shown in UCS space, with path.
		delete(get(axh, 'Children'))
		[az,el] = view(axh);
		% Show color nodes:
		n2s = cellstr(strjust(num2str((1:N).'),'left'));
		scatter3(ucs(:,3),ucs(:,2),ucs(:,1), 256, bgr, 'filled', 'Parent',axh)
		text(ucs(:,3),ucs(:,2),ucs(:,1), n2s, 'Parent',axh,...
			'Color',fgd, 'HorizontalAlignment','center')
		hold(axh,'on')
		% Show path:
		ipc = strcmpi(opts.path,'closed');
		mat = ucs([1:N,1:+ipc],:);
		plot3(mat(:,3),mat(:,2),mat(:,1),'-', 'Parent',axh, 'Color',fgd)
		% Show distances:
		vec = sqrt(sum(diff(mat,1,1).^2,2));
		[mxv,mxi] = max(vec);
		[mnv,mni] = min(vec);
		mxp = mean(mat(mxi:mxi+1,:),1);
		mnp = mean(mat(mni:mni+1,:),1);
		text(mxp(3),mxp(2),mxp(1), sprintf('max:%.5g',mxv), 'Parent',axh, 'Color',fgd)
		text(mnp(3),mnp(2),mnp(1), sprintf('min:%.5g',mnv), 'Parent',axh, 'Color',fgd)
		% Orient axes:
% 		axis(axh,'equal')
% 		view(axh,az,el)
		fOrient3D(axh,az,el)
	end
%
	function fCubeRGB(axh) % Colors shown in UCS space, with RGB cube.
		delete(get(axh, 'Children'))
		[az,el] = view(axh);
		% Show color nodes:
		n2s = cellstr(strjust(num2str((1:N).'),'left'));
		scatter3(ucs(:,3),ucs(:,2),ucs(:,1), 256, bgr, 'filled', 'Parent',axh)
		text(ucs(:,3),ucs(:,2),ucs(:,1), n2s, 'Parent',axh,...
			'Color',fgd, 'HorizontalAlignment','center')
		% Show excluded nodes:
		if isinteger(opts.exc)
			exc = bsxfun(@rdivide,double(opts.exc),ohm);
		else
			exc = opts.exc;
		end
		cxe = fun(exc);
		hold(axh,'on')
		scatter3(cxe(:,3),cxe(:,2),cxe(:,1), 256, exc, 'filled', 'Parent',axh)
		text(cxe(:,3),cxe(:,2),cxe(:,1), 'X', 'Parent',axh,...
			'Color',fgd, 'HorizontalAlignment','center')
		% Show outline of RGB cube:
		M = 23;
		[X,Y,Z] = ndgrid(linspace(0,1,M),0:1,0:1);
		mat = fun([X(:),Y(:),Z(:);Y(:),Z(:),X(:);Z(:),X(:),Y(:)]);
		X = reshape(mat(:,3),M,[]);
		Y = reshape(mat(:,2),M,[]);
		Z = reshape(mat(:,1),M,[]);
		line(X,Y,Z, 'Color',fgd, 'Parent',axh)
		% Orient axes:
% 		axis(axh,'equal')
% 		view(axh,az,el)
		fOrient3D(axh,az,el)
	end
%
	function fScatterMat(axh) % Matrix scatter plot.
		uih = get(axh, 'Parent');
		ise = isempty(pScH);
		for rr = 3:-1:1
			for cc = 3:-1:1
				if ise
					pos = [rr-1,(3-cc)*0.93,1,0.93]./3;
					pScH(rr,cc) = axes('Parent',uih, 'Visible','on',...
						'Units','normalized', 'OuterPosition',pos,...
						'NextPlot','replacechildren',...
						'Color','none', 'XColor',fgd, 'YColor',fgd); %#ok<LAXES>
				else
					delete(get(pScH(rr,cc), 'Children'))
				end
				if rr==cc
					text(0.5,0.5, zyx{rr}, 'Parent',pScH(rr,cc),...
						'FontWeight','bold', 'Color',fgd)
				else
					scatter(pScH(rr,cc), ucs(:,rr),ucs(:,cc), 32, bgr, 'filled');%, 'Parent',axh)
				end
			end
		end
		%set(pScH, 'XLimMode','auto', 'YLimMode','auto')
		set(pScH([1,5,9]), 'XLim',0:1, 'YLim',0:1, 'Visible','off')
		set(pScH, 'XColor',fgd, 'YColor',fgd, 'ZColor',fgd)
	end
%
	function fAdjaNode(axh) % Show matrix with all colors adjacent.
		delete(get(axh, 'Children'))
		[idr,idc] = ndgrid(0:N);
		F = (1:N*(N+1)).';
		F(N+1:N+1:end) = [];
		image('Parent',axh, 'CData',repmat(permute(bgr,[1,3,2]),[1,N,1]));
		patch('Parent',axh, 'Faces',[F,F+N+1,F+N+2], 'Vertices',0.5+[idr(:),idc(:)],...
			'FaceColor','flat', 'FaceVertexCData',bgr(mod(F,N+1),:), 'EdgeColor','none');
	end
%
	function fBandName(axh) % Show bands with colornames (if COLORNAMES is available).
		delete(get(axh, 'Children'))
		image(permute(bgr,[1,3,2]), 'Parent',axh)
		try
			cnm = colornames('CSS',bgr);
		catch %#ok<CTCH>
			cnm = repmat({'COLORNAMES not found: download FEX #48155'},1,N);
		end
		text(ones(1,N), 1:N, cnm, 'Parent',axh, 'Color',fgd,...
			'BackgroundColor',bgd, 'HorizontalAlignment','center')
	end
%
	function fRgbValues(axh) % Show bands with RGB values (floating point and integer).
		delete(get(axh, 'Children'))
		image(permute(bgr,[1,3,2]), 'Parent',axh)
		% Integer:
		cnm = rgb2str('[%d,%d,%d] =',1,bsxfun(@times,bgr,ohm));
		text(ones(1,N), 1:N, cnm, 'Parent',axh, 'Color',fgd,...
			'BackgroundColor',bgd, 'HorizontalAlignment','right')
		% Normalized:
		cnm = rgb2str(' [%.5g,%.5g,%.5g]',1e5,bgr);
		text(ones(1,N), 1:N, cnm, 'Parent',axh, 'Color',fgd,...
			'BackgroundColor',bgd, 'HorizontalAlignment','left')
	end
%
	function fEuclDist(axh) % Show Euclidean distances (2D or 3D).
		delete(get(axh, 'Children'))
		aud = get(axh, 'UserData');
		sgc = {'Parent',axh, 'LineWidth',2.8, 'Marker','o'};
		for idk = 1:N
			dst = sqrt(sum(bsxfun(@minus,ucs,ucs(idk,:)).^2,2));
			switch aud
				case 2
					scatter(1:N, dst, 123, bgr,...
						sgc{:}, 'MarkerFaceColor',bgr(idk,:), 'Parent',axh);
				case 3
					scatter3(idk*ones(1,N), 1:N, dst, 123, bgr,...
						sgc{:}, 'MarkerFaceColor',bgr(idk,:), 'Parent',axh);
				otherwise
					error('SC:maxdistcolor_view:TooManyDimensions',...
						'Sorry, I don''t know how to plot %d dimensions.',aud)
			end
			hold(axh,'on')
		end
		%
		if aud==2
			dst = status.minDistOutput;
			text(N+0.5,dst,sprintf(' %#.5g',dst), 'Parent',axh,...
				'Color',fgd, 'BackgroundColor','none')
		end
	end
%
%% Callback Functions %%
%
	function fEvalFun(obj,~) % Turn evaluation on and off.
		eUiX = ~eUiX;
		if eUiX % eval
			set(obj,'String','pause', 'BackgroundColor',eUiC)
		else % paused
			set(obj,'String','eval', 'BackgroundColor',[1,1,0])
		end
		fUpDtMap()
	end
	function fUpDtMap(~,~) % Update colormap using options structure.
		if eUiX
			% Generate colormap:
			set(figH, 'Pointer','watch')
			drawnow()
			[bgr,ucs,status,RGB,UCS] = maxdistcolor(N,fun,opts);
			set(figH, 'Pointer',figY)
			inw = true;
			ohm = pow2([opts.bitR,opts.bitG,opts.bitB])-1;
			% Update colorbar:
			set(bImH, 'CData',permute(bgr,[1,3,2]))
			% Update main plots:
			arrayfun(@(s,h) s.fun(h), pAxS, pAxH)
		end
	end
%
	function fNumEdit(obj,~) % Number edit box callback.
		str = get(obj, 'String');
		if all(isstrprop(str,'digit')) && sscanf(str,'%d')
			N = sscanf(str,'%d');
			set(nUiH, 'Value',nFun(N))
			fNumTick()
			fUpDtMap()
		else
			set(obj,'String',sprintf('%d',N))
		end
	end
	function fNumSlide(~,evt) % Number slider listener callback.
		try
			N = round(get(evt,'NewValue'));
		catch %#ok<CTCH>
			N = round(evt.AffectedObject.Value);
		end
		set(nVaH, 'String',sprintf('%d',N))
		fNumTick()
	end
	function fNumTick() % Number adjust limits and tickmarks.
		fPermSort()
		% Colorbar limits:
		set(bAxH, 'Ylim',[0,N]+0.5, 'YTick',1:N)
		% Table sizes:
		for idk = 1:tTxN
			new = get(tUiH(idk), 'Data');
			new(end+1:N,:) = NaN;
			new(N+1:end,:) = [];
			set(tUiH(idk), 'Data',new)
		end
		% Main plot axes limits:
		for idk = 1:numel(pAxH)
			for idc = 'XYZ'
				if strcmpi(pAxS(idk).(idc),ndx)
					set(pAxH(idk), [idc,'Lim'],[0,N]+0.5, [idc,'Tick'],1:N);
				end
			end
		end
	end
%
	function fOptEdit(obj,~,idk) % Options edit box callback.
		str = get(obj, 'String');
		new = str2double(str);
		if ~isreal(new) || (sInt(idk) && fix(new)~=new) || new<sRng(idk,1) || new>sRng(idk,2)
			new = NaN;
		end
		if isnan(new)
			set(obj, 'String',sStr(opts.(sTxt{idk})))
		else
			opts.(sTxt{idk}) = new;
			set(sUiH(idk), 'Value',new)
			fUpDtMap()
		end
	end
	function fOptSlide(~,evt,idk) % Options slider listener callback.
		try
			new = get(evt,'NewValue');
		catch %#ok<CTCH>
			new = evt.AffectedObject.Value;
		end
		if sInt(idk)
			new = round(new);
			set(sUiH(idk), 'Value',new)
		end
		opts.(sTxt{idk}) = new;
		set(sVaH(idk), 'String',sStr(new))
		% Move paired slider:
		if sTwo(idk)
			idt = setdiff(find(abs(sTwo)==abs(sTwo(idk))),idk);
			old = get(sUiH(idt), 'Value');
			if ((new-old) * diff(sign(sTwo([idt,idk])))) < 0
				set(sUiH(idt), 'Value',new)
			end
		end
	end
%
	function fOptMenu(obj,~,idk) % Options menu callback.
		idv = get(obj,'Value');
		if idk>1
			opts.(mTxt{idk}) = mStr{idk}{idv};
			fUpDtMap()
		else
			set(pPnH,     'Visible','off', 'HitTest','off')
			set(pPnH(idv),'Visible','on',  'HitTest','on')
		end
		fAlphaTry()
	end
%
	function fCellEdit(obj,~,idk) % Options table cell callback.
		new = get(obj,'Data');
		isn = sum(isnan(new),2);
		idz = isn==0;
		if all(idz|(isn==3))
			new = new(idz,:);
			if get(tCbH(idk),'Value') % uint
				pwr = pow2(max(3,ceil(log2(max(log2(ohm+1))))));
				new = cast(new,sprintf('uint%d',pwr));
			end
			opts.(tTxt{idk}) = new;
			fBackFore(true)
			fUpDtMap()
		end
	end
	function fCheckBox(obj,~,idk) % Options table checkbox callback.
		old = get(tUiH(idk),'Data');
		if get(obj,'Value')
			% float->uint
			new = round(bsxfun(@times,old,ohm));
		else
			% uint->float
			new = bsxfun(@rdivide,old,ohm);
		end
		set(tUiH(idk),'Data',new);
	end
%
	function fPermSort() % No permutation sorting if N>9.
		ids = strcmpi('sort',mTxt);
		idn = get(mUiH(ids), 'Value');
		if N>9
			if idn > numel(mSrt{1})
				idn = 1;
			end
			opts.sort = mSrt{1}{idn};
			set(mUiH(ids), 'String',mSrt{1}, 'Value',idn)
		else
			set(mUiH(ids), 'String',mStr{ids})
		end
	end
%
	function fBackFore(chg) % Background and Foreground colors.
		if isempty(opts.exc)
			bgd = [1,1,1];
			fgd = [0,0,0];
		else
			new = opts.exc(1,:);
			if isfloat(new)
				bgd = double(new);
			else
				bgd = double(new) ./ ohm;
			end
			% Define forground as farthest color from background:
			[~,idf] = max(sum(bsxfun(@minus,fun(bgd),fun(smp)).^2,2));
			fgd = smp(idf,:);
		end
		if chg
			uih = get(pAxH, 'Parent');
			set([uih{:}], 'BackgroundColor',bgd)
			uih = get(pAxH, 'Title');
			set([uih{:}], 'Color',fgd)
			set(pAxH, 'XColor',fgd, 'YColor',fgd, 'ZColor',fgd)
		end
	end
%
	function fSizeObj(~,~) % Resize the figure contents.
		drawnow()
		try
			figP = get(figH, 'Position');
		catch %#ok<CTCH>
			return
		end
		% Ensure minimum virtual figure size:
		adj = max(figP(3:4),[425,254]);
		pFg = [figP(1:2)+min(0,figP(3:4)-adj),adj];
		% Get object sizes:
		mUiX = cell2mat(get(mUiH, 'Extent'));
		sTxX = cell2mat(get(sTxH, 'Extent'));
		tCbX = cell2mat(get(tCbH, 'Extent'));
		tUiX = cell2mat(get(tUiH, 'Extent'));
		tTxX = cell2mat(get(tTxH, 'Extent'));
		% Group widths and heights:
		tWd = max(tUiX(:,3))+21; % table width
		bWd = 36; % colorbar axes width
		aWd = pFg(3)-tWd-bWd-gap*4; % main axes width
		mHt = max(mUiX(:,4)); % menu height
		% Menu UI positions:
		mUiP = mUiX;
		mUiP(:,1) = aWd+bWd+3*gap;
		mUiP(:,2) = gap+2*mHt*(mTxN-1:-1:0)+3;
		mUiP(:,3) = tWd;
		mUiP(:,4) = mHt;
		set(mUiH,{'Position'},num2cell(mUiP,2))
		% Menu text positions:
		mAxP = mUiP(end,:);
		mAxP(:,4) = 2*mTxN*mHt;
		set(mAxH,'Position',mAxP)
		% Horizontal slider text positions:
		sHt = (2*mTxN*mHt)/sTxN;
		sTxP = sTxX;
		sTxP(:,1) = gap;
		sTxP(:,2) = gap+sHt*(sTxN-1:-1:0);
		sTxP(:,3) = max(sTxX(:,3));
		sTxP(:,4) = sHt;
		set(sTxH,{'Position'},num2cell(sTxP,2))
		% Horizontal slider value positions:
		sVaP = sTxP;
		sVaP(:,1) = sum(sTxP(:,[1,3]),2);
		set(sVaH,{'Position'},num2cell(sVaP,2))
		% Horizontal slider UI positions:
		sUiP = sVaP;
		sUiP(:,1) = sum(sVaP(:,[1,3]),2);
		sUiP(:,3) = aWd-sTxP(:,3)-sVaP(:,3);
		set(sUiH,{'Position'},num2cell(sUiP,2))
		% Table UI positions:
		bHt = pFg(4)-2*mTxN*mHt-3*gap;
		tUiP = tUiX;
		tUiP(:,1) = aWd+bWd+3*gap;
		tUiP(:,2) = 2*mTxN*mHt+2*gap+[bHt/2;0];
		tUiP(:,3) = tWd;
		tUiP(:,4) = bHt/2;
		set(tUiH,{'Position'},num2cell(tUiP,2))
		% Table text positions:
		tTxP = tTxX;
		tTxP(:,1) = tUiP(:,1)+3;
		tTxP(:,2) = tUiP(:,2)+bHt/2-tTxX(:,4);
		tTxP(:,4) = tTxX(:,4)-3;
		set(tTxH,{'Position'},num2cell(tTxP,2))
		% Table checkbox UI positions:
		tCbP = tCbX(:,[1,2,4,4]);
		tCbP(:,1) = tUiP(:,1)+tUiP(:,3)-21;
		tCbP(:,2) = tUiP(:,2)+tUiP(:,4)-21;
		set(tCbH,{'Position'},num2cell(tCbP,2))
		% Colorbar axes position:
		bAxP = tUiP(end,:);
		bAxP(1) = aWd+gap*2;
		bAxP(3) = bWd;
		bAxP(4) = bHt;
		set(bAxH,'Position',bAxP)
		% Number slider UI position:
		nUiP = bAxP;
		nUiP(2) = gap;
		nUiP(4) = 2*mTxN*mHt-txh-gap-mHt;
		set(nUiH,'Position',nUiP)
		% Number slider value position:
		nVaP = nUiP;
		nVaP(2) = gap+nUiP(4);
		nVaP(4) = txh;
		set(nVaH,'Position',nVaP)
		% Eval button UI position:
		eUiP = nVaP;
		eUiP(2) = 2*mTxN*mHt-mHt+gap;
		eUiP(4) = mHt;
		set(eUiH,'Position',eUiP)
		% Main plots uipanel position:
		pPnP = bAxP;
		pPnP(1) = gap;
		pPnP(3) = aWd;
		set(pPnH,'Position',pPnP)
	end
%
if nargout
	waitfor(figH)
	rgb = bgr;
end
%
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%maxdistcolor_view


function rinds = APPspInds2RegionInds(map, sinds)
% rinds = APPspInds2RegionInds(map, sinds)
% Gets the sp in each region
%
% Copyright(C) Derek Hoiem, Carnegie Mellon University, 2005
% Permission granted to non-commercial enterprises for
% modification/redistribution under GNU GPL.
% Current Version: 1.0  09/30/2005

nr = max(map);
rinds = cell(nr, 1);
for r = 1:nr
    count = 0;
    rs = find(map==r);
    for k = 1:length(rs)
        count = count + length(sinds{rs(k)});
    end
    rinds{r} = zeros(count, 1);

    count = 0;
    for k = 1:length(rs)
        rinds{r}(count+1:count+length(sinds{rs(k)})) = sinds{rs(k)};
        count = count + length(sinds{rs(k)});
    end
end


function plotPredictionResults_VASARI(pathResults,nameOutcome,fSetNames,metric,maxOrder,pathFig)
% -------------------------------------------------------------------------
% function plotPredictionResults_VASARI(pathResults,nameOutcome,fSetNames,metrics,maxOrder)
% -------------------------------------------------------------------------
% DESCRIPTION:
% This function plots prediction performance estimation results for all the
% different feature set types entered as inputs in the LGG study.
% -------------------------------------------------------------------------
% INPUTS:
% 1. pathResults: Full path to the 'RESULTS' folder where prediction results
%                 are saved.
%                 --> Ex: '/myProject/WORKSPACE/VASARI/RESULTS'
% 2. nameOutcome: String specifying the name of the outcome being displayed
%                 --> Ex: 'progression'
% 3. fSetNames: Cell of strings specifying the name of the type of feature
%               set analyzed.
%               --> Ex: {'VASARI'}
% 4. metric: String specifying the metric to display.
%            --> 'AUC632'
% 5. maxOrder: Integer specifying the maximal multivariable model order.
%              --> Ex: 10
% 6. pathFig: (optional).  Full path to where figure is saved without
%             displaying it. Put '' for displaying the figure and not
%             saving it to 'pathFig' (default).
%             --> Ex: ''
% -------------------------------------------------------------------------
% AUTHOR(S): Martin Vallieres <mart.vallieres@gmail.com>
% -------------------------------------------------------------------------
% HISTORY:
% - Creation: January 2017
%--------------------------------------------------------------------------
% STATEMENT:
% This file is part of <https://github.com/mvallieres/radiomics/>,
% a package providing MATLAB programming tools for radiomics analysis.
% --> Copyright (C) 2015-2017  Martin Vallieres
%
%    This package is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    This package is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with this package.  If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------

if nargin < 6
    pathFig = '';
end

startpath = pwd;
cd(pathResults)

signs = {'-r',':b','--g','-.y'};
nFSET = numel(fSetNames);

maxOrderChosen = maxOrder;

if isempty(pathFig)
    figure
else
    h = figure('visible','off');
end
for i = 1:nFSET
    fSET = fSetNames{i};
    results = load(['RESULTS_',fSET,'_',nameOutcome]); results = struct2cell(results); results = results{1};
    nOrders = numel(fieldnames(results));
    if nOrders < maxOrderChosen
        maxOrder = nOrders;
    else
        maxOrder = maxOrderChosen;
    end
    val = zeros(maxOrder,1);
    val_SE = zeros(maxOrder,1);
    for j = 1:maxOrder
        orderName = ['Order',num2str(j)];
        val(j,1) = results.(orderName).(metric);
        val_SE(j,1) = results.(orderName).(['SE_',metric]);
    end
    errorbar(1:maxOrder,val(:,1),val_SE(:,1),signs{i},'LineWidth',3,'MarkerFaceColor',signs{i}(end),'MarkerSize',6)
    hold on
end
set(gca,'FontSize',20)
xlabel('Model Order','FontSize',24)
ylabel('Prediction performance','FontSize',24)
ind = strfind(metric,'632');
if ~isempty(ind)
    metric = [metric,'+'];
end
metric = [metric(1:ind-1),'_{',metric(ind:end),'}'];
ind = strfind(nameOutcome,'Death');
if ~isempty(ind)
    nameOutcome(ind:ind+4) = [];
    nameOutcome = ['Survival',nameOutcome];
end
titleName = [nameOutcome,'(VASARI) -- ',metric];
title(titleName,'FontSize',30,'FontWeight','bold')
legend(fSetNames,'Location','SouthEast')
axis([0 maxOrderChosen+1 0.5 1])
set(gca,'XTick',[1 2 3 4 5 6 7 8 9 10])

if ~isempty(pathFig)
    cd(pathFig)
    saveas(h,titleName,'fig')
end

cd(startpath)
end


% Read all images and extract point coordinates.
%
% All information needed are stored and retrieved
% from the function CONFIGDATA

% $Author: svoboda $
% $Revision: 2.6 $
% $Id: im2points.m,v 2.6 2005/05/23 16:26:03 svoboda Exp $
% $State: Exp $

clear all;

% add path to config data
addpath ../../CommonCfgAndIO
% add path for graphical output if needed
addpath ../OutputFunctions

SHOWFIG	  = 0; % show images during point extraction
STEP4STAT = 1; % step for computing average and std images, if 1 then all images taken

% Read configuration from whatever is specified on command-line (via --config=FILENAME)
config = read_configuration();

im.dir = config.paths.img;
im.ext = config.files.imgext;

NoCams = size(config.files.idxcams,2);	% number of cameras

% load image names
for i=1:NoCams,
  seq(i).camId = config.files.idxcams(i);
  if seq(i).camId > -1
	if strfind(config.expname,'oscar')
	  seq(i).data = dir([sprintf(im.dir,seq(i).camId),config.files.imnames,'*.',im.ext]);
	else
	  seq(i).data = dir([sprintf(im.dir,seq(i).camId),sprintf(config.files.imnames,seq(i).camId),im.ext]);
	end
  else
	seq(i).data = dir([im.dir,sprintf(config.files.imnames),im.ext]);
  end
  seq(i).size = size(seq(i).data,1);
  if seq(i).size<4
	error('Not enough images found. Wrong image path or name pattern?');
  end
end

% create an occupancy matrix for image frames
occmat=1; try config.files.maxid; catch occmat=0; end
if occmat,
	NoPoints = config.files.maxid;
	FrameMat = zeros(config.files.maxid,NoCams);
	for i=1:NoCams,
		seq(i).imgidx = zeros(size(1:NoPoints));
		for j=1:size(seq(i).data,1)
			FrameMat(str2num(seq(i).data(j).name(config.files.posid)),i)=j;
		end
	end
else
	NoPoints = min([seq.size]);
	FrameMat = zeros(NoPoints,NoCams);
	for i=1:NoCams,
		FrameMat(:,i) = [1:NoPoints]';
	end
end

% In fact, some frames might be without any calibration point

% Becouse of non-consistent stopping of capturing, the sequences might
% have different number of images, select the minimal value as the right one

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% beginning of the findings

t = cputime;
for i=1:NoCams,
  if ~exist(sprintf(config.files.avIM,seq(i).camId)),
	disp(sprintf('The average image of the camera %d is being computed',seq(i).camId));
	avIM = zeros(size(imread([sprintf(im.dir,seq(i).camId),seq(i).data(1).name])));
	pointIdx = 1:STEP4STAT:seq(i).size;
	for j=pointIdx,
	  IM = imread([sprintf(im.dir,seq(i).camId),seq(i).data(j).name]);
	  avIM = avIM + double(IM);
	end
	avIM = uint8(round(avIM./size(pointIdx,2)));
	imwrite(avIM,sprintf(config.files.avIM,seq(i).camId));
  else	disp('Average file already exists');
  end
end
disp(sprintf('Elapsed time for computation of average images: %4.2f [sec]',cputime-t))
% compute the standard deviations images that will be used for finding LEDs
% if not already computed
t = cputime;
for i=1:NoCams,
  if ~exist(sprintf(config.files.stdIM,seq(i).camId)),
	avIM = double(imread(sprintf(config.files.avIM,seq(i).camId)));
	disp(sprintf('The image of standard deviations of the camera %d is being computed',seq(i).camId));
	stdIM = zeros(size(imread([sprintf(im.dir,seq(i).camId),seq(i).data(1).name])));
	pointIdx = 1:STEP4STAT:seq(i).size;
	for j=pointIdx,
	  IM = imread([sprintf(im.dir,seq(i).camId),seq(i).data(j).name]);
	  stdIM = stdIM + (double(IM)-avIM).^2;
	end
	stdIM = uint8(round(sqrt(stdIM./(size(pointIdx,2)-1))));
	imwrite(stdIM,sprintf(config.files.stdIM,seq(i).camId));
  else
	disp('Image of standard deviations already exists')
  end
end

disp(sprintf('Elapsed time for computation of variance images: %4.2f [sec]',cputime-t))

% find points in the images
Ws    = [];	  % joint image matrix
Res	  = [];	  % resolution of cameras
% UsableFramesIdx = find(sum(FrameMat')>2);
IdMat = ones(NoCams,NoPoints);
% IdMat is very important for Martinec&Pajdla filling [ECCV2002]
% it is a NoCams x NoPoints matrix,
% IdMat(i,j) = 0 -> no j-th point in i-th
% IdMat(i,j) = 1 -> point successfully detected

disp('*********************************************')
disp('Finding points (laser projections) in cameras')
disp(sprintf('Totally %d cameras, %d images for each cam', NoCams, NoPoints'))
disp('*********************************************')
for i=1:NoCams,
  t1 = cputime;
  disp(sprintf('Finding points in camera No: %0.2d',config.files.idxcams(i)))
  Points = [];
  avIM  = imread(sprintf(config.files.avIM,seq(i).camId));
  stdIM	= imread(sprintf(config.files.stdIM,seq(i).camId));
  for j=1:NoPoints,
	  fprintf(1,'\b\b\b\b\b\b %5d',j);
	  idx2data = FrameMat(j,i);
	  if idx2data
		  [pos,err] = getpoint([sprintf(im.dir,seq(i).camId),seq(i).data(idx2data).name], SHOWFIG, config.imgs, avIM, stdIM);
	  else
		  err = 1;
	  end
	if err
	  IdMat(i,j) = 0;
	  Points = [Points, [NaN; NaN; NaN]];
	else
	  Points = [Points, [pos; 1]];
	end
  end
  Ws = [Ws; Points];
  Res= [Res; size(avIM,2), size(avIM,1)];
  t2 = cputime;
  disp(sprintf('\nElapsed time for finding points in one camera: %d minutes %d seconds',floor((t2-t1)/60), round(mod((t2-t1),60))))
  disp(sprintf('%4d points found in camera No: %0.2d',sum(Points(3,:)>0),config.files.idxcams(i)));
end

%%% End of the findings
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if strfind(config.expname,'oscar')
  % needs special care for handling projector data
  ProjPoints = load(config.files.projdata,'-ASCII');
  Ws = [Ws; ProjPoints(:,end-1:end)'; ones(size(ProjPoints(:,1)'))];
  IdMat = [IdMat; ones(size(ProjPoints(:,1)'))];
  Res	= [Res; config.imgs.projres];
end

save(config.files.points, 'Ws','-ASCII')
save(config.files.Res, 'Res', '-ASCII')
save(config.files.IdMat, 'IdMat', '-ASCII')

% display the overall statistics
disp('Overall statistics from im2points:  ************************  ')
disp(sprintf('Total number of frames (possible 3D points): %d',NoPoints))
disp(sprintf('Total number of cameras %d', NoCams))
disp('More important statistics: *********************************  ')
disp(sprintf('Detected 3D points:                    %d', sum(sum(IdMat)>0)))
disp(sprintf('Detected 3D points in at least 3 cams: %d', sum(sum(IdMat)>2)))
disp(sprintf('Detected 3D points in ALL cameras:     %d', sum(sum(IdMat)==NoCams)))


function vw = nifti2ROI(vw, mappth)
%   Convert a nifti label file into a mrVista format ROI
%
% vw = nifti2ROI([vw], [mappth])
%
% vw:       mrVista view structure (must be gray view)
%               [default = current Gray view]
% mappth:   path to nifti file with map to convert;
%               [default = dialog]
%
% Notes: the nifti format map is a 3D matrix. The mrVista parameter map is
% a vector, indexed to the gray coords. The main steps of the routine are:
%   1) Convert the nifti format 3D map to a vector and 3xN coordinate
%           matrix
%   2) Transform the coordinates to the space of the t1-weighted anatomy
%       (using header information in the two files)
%   3) Transform the coordinates to mrAnat conventions
%
% Example:  Convert a class file into ROIs
% vw = nifti2ROI(vw, viewGet(vw, 'class file', 'right'))
%
%   JW, 4/27/2015
%

mrGlobals;

% Variable check
if notDefined('vw'), vw = getSelectedGray; end

if ~exist('mappth', 'var') || ~exist(mappth, 'file')
    mappth = getPathStrDialog(dataDir(vw),'Choose nifti parameter map','*.nii.gz');
end

% read a nifti file with map to be converted to ROIs
ni = niftiRead(mappth);

% apply our canonical transform to ensure orientation is matched to t1;
ni   = niftiApplyCannonicalXform(ni);

% This is the map data
data = niftiGet(ni, 'data');
data = nifti2mrVistaAnat(data);
data = round(data);
% ensure data are integers
assert(isequal(data, round(data)));

% define ROIs
labels = setdiff(unique(data(:)),0);

fprintf('[%s]: Creating %d ROIs from file %s\n', mfilename, length(labels), mappth);

for ii = 1:length(labels)
   [x, y, z] = ind2sub(size(data), find(data == labels(ii)));
   coords = [x y z]';
   comments = sprintf('ROI defined by label %d in map %s', labels(ii), mappth);
   name = sprintf('ROI_%03d', labels(ii));
   fprintf('.');drawnow();
   vw = newROI(vw,name,1,'k',coords, comments);
end

return


function flag=istfraff(method);
% flag=istfr2(method) returns true is method is an affine
% time frequency representation.
%	See also istfr1, istfr2.

%	F. Auger, may 98
%	Copyright (c) CNRS - France 1998.
%
%  This program is free software; you can redistribute it and/or modify
%  it under the terms of the GNU General Public License as published by
%  the Free Software Foundation; either version 2 of the License, or
%  (at your option) any later version.
%
%  This program is distributed in the hope that it will be useful,
%  but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%  GNU General Public License for more details.
%
%  You should have received a copy of the GNU General Public License
%  along with this program; if not, write to the Free Software
%  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

method=upper(method);
if strcmp(method,'TFRASPW' ) | strcmp(method,'TFRSCALO') | ...
   strcmp(method,'TFRDFLA' ) | strcmp(method,'TFRSPAW' ) | ...
   strcmp(method,'TFRUNTER') | strcmp(method,'TFRBERT' ) | ...
   strcmp(method,'TFRSPBK' ),
 flag=1;
else
 flag=0;
end;


function [y,fs,bits]=wavread(fn,n)
%WAVREAD  Legacy MATLAB function to read .WAV file [Y,FS,BITS]=(FILENAME,NMAX)
% wavread supports multichannel data, with up to 32 bits per sample, and supports reading 24- and 32-bit .wav files.
%
% Usage:
% y = wavread('filename')               loads a WAVE file specified by the string filename, returning
%                                       the sampled data in y. The .wav extension is appended if no
%                                       extension is given. Amplitude values are in the range [-1,+1].
% [y,Fs,bits] = wavread('filename')     returns the sample rate (Fs) in Hertz and the number of bits
%                                       per sample (bits) used to encode the data in the file.
% [...] = wavread('filename',N)         returns only the first N samples from each channel in the file.
% [...] = wavread('filename',[N1 N2])   returns only samples N1 through N2 from each channel in the file.
% siz = wavread('filename','size')      returns the size of the audio data contained in the file in place
%                                       of the actual audio data, returning the vector siz = [samples channels].

%	   Copyright (C) Mike Brookes 2018
%      Version: $Id: wavread.m 10865 2018-09-21 17:22:45Z dmb $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if nargin<2
    [y,fs,wm,fx]=v_readwav(fn);
elseif ischar(n)
    if strcmp(n,'size')
        [y,fs,wm,fx]=v_readwav(fn,'',0);
        y=fx(4:5); % number of samples and channels
    else
        error('%s is invalid option',n);
    end
elseif length(n)<2
    [y,fs,wm,fx]=v_readwav(fn,'',n);
else
    [y,fs,wm,fx]=v_readwav(fn,'',n(2)-n(1)+1,n(1)-1);
end
bits=fx(7); % bits precision


function []=anim8_DIC3DPP_faceMeasureDirection(DIC3DPPresults,faceMeasureString,RBMlogic,varargin)
%% function for plotting 3D-DIC results of face measures as color + direction as arrows in STEP4.
% plotting 3D surfaces from camera pairs, animation changing
% with time, and the faces colored according to faceMeasureString
% this function is called in plotMultiDICPairResults
%
% Options:
% anim8_DIC3DPP_faceMeasureDirection(DIC_3Dallpairs_results,faceMeasureString)
% anim8_DIC3DPP_faceMeasureDirection(DIC_3Dallpairs_results,faceMeasureString,optStruct)
%
% Inputs:
% * DIC3DAllPairsResults
% * faceMeasureString: can be any of the following:
%   'Epc1','Epc2','epc1','epc2','Lamda1','Lamda2', or a combination of two  in a cell array to plot side by side
% * optStruct: optional structure for plotting options which may include any of the following fields:
%   - smoothLogic: logical variable for smoothing (true)/not smoothing (false) the face measure
%   - FaceAlpha: transparacy of the faces (scalar between 0 and 1, where zero is transparent and 1 is opaque)
%   - colorBarLimits: a 2x1 scalar vector for the colobar limits. if not set, it's automatic
%   - dataLimits: a 2x1 scalar vector for the data limits of the face measure. if a face measure is outside these limits, it is set to NaN. if not set no face is set to NaN
%   - colorMap
%   - zDirection: 1 for z up and -1 for z down
%   - lineColor: line color for the mesh. can be for example 'b','k','none',etc...
%   - supTitleString=faceMeasureString;

%% Assign plot options
Narg=numel(varargin);
switch Narg
    case 1
        optStruct=varargin{1};
    case 0
        optStruct=struct;
    otherwise
        ('wrong number of input arguments');
end

% complete the struct fields
if ~isfield(optStruct,'smoothLogic')
    optStruct.smoothLogic=0;
end
if ~isfield(optStruct,'FaceAlpha')
    optStruct.FaceAlpha=1;
end
if ~isfield(optStruct,'dataLimits')
    optStruct.dataLimits=[-inf inf];
end
if ~isfield(optStruct,'zDirection') % 1 or -1
    optStruct.zDirection=1;
end
if ~isfield(optStruct,'lineColor') % 'none' or 'k'
    optStruct.lineColor='none';
end
if ~isfield(optStruct,'maxCorrCoeff')
    optStruct.maxCorrCoeff=[];
end
if ~isfield(optStruct,'quiverScaleFactor')
    optStruct.quiverScaleFactor=20;
end
%%
nFrames=numel(DIC3DPPresults.Points3D);

[xl,yl,zl]=axesLimits(DIC3DPPresults.Points3D);
meanEdgeLength=nanmean(patchEdgeLengths(DIC3DPPresults.Faces,DIC3DPPresults.Points3D{1}));

%% Assign the right face measure into FC

if iscell(faceMeasureString)
    faceMeasureCell=faceMeasureString;
    nStrains=numel(faceMeasureString);
    switch nStrains
        case 1
            FC=cell(nFrames,nStrains);
            D=cell(nFrames,nStrains);
            Ds=cell(nFrames,nStrains);
            Vc=cell(nFrames,nStrains);
        case 2
            FC=cell(nFrames,nStrains);
            D=cell(nFrames,nStrains);
            Ds=cell(nFrames,nStrains);
            Vc=cell(nFrames,nStrains);
        otherwise
            error('wrong number of cells in faceMeasureString cell array (must be 1 or 2)');
    end
elseif ischar(faceMeasureString)
    nStrains=1;
    faceMeasureCell=cell(1);
    faceMeasureCell{1}=faceMeasureString;
    FC=cell(nFrames,1);
    D=cell(nFrames,1);
    Ds=cell(nFrames,1);
    Vc=cell(nFrames,1);
else
    error('wrong face measure (second input variable)');
end

directionStringCell=cell(nStrains,1);
for is=1:nStrains
    switch faceMeasureCell{is}
        case 'Epc1'
            directionStringCell{is}='Epc1vecCur';
            optStruct.supTitleString{is}='1st principal Lagrangian strain';
        case 'Epc2'
            directionStringCell{is}='Epc2vecCur';
            optStruct.supTitleString{is}='2nd principal Lagrangian strain';
        case 'epc1'
            directionStringCell{is}='epc1vec';
            optStruct.supTitleString{is}='1st principal Eulerian strain';
        case 'epc2'
            directionStringCell{is}='epc2vec';
            optStruct.supTitleString{is}='2nd principal Eulerian strain';
        case 'Lamda1'
            directionStringCell{is}='Epc1vecCur';
            optStruct.supTitleString{is}='1st principal stretch';
        case 'Lamda2'
            directionStringCell{is}='Epc2vecCur';
            optStruct.supTitleString{is}='2nd principal stretch';
        otherwise
            error('unexpected face measure string. plots not created');
    end
    for it=1:nFrames
        if RBMlogic
            FC{it,is}=DIC3DPPresults.Deform_ARBM.(faceMeasureCell{is}){it}; % face color (strain)
            D{it,is}=DIC3DPPresults.Deform_ARBM.(directionStringCell{is}){it}; % direction (unit vector)

            switch faceMeasureCell{is}
                case {'Epc1','Epc2','epc1','epc2'}
                    Ds{it,is}=optStruct.quiverScaleFactor*FC{it,is}.*D{it,is}; % direction with magnitude (scaled vector)
                    DsLengths=sqrt((sum(Ds{it,is}.^2,2)));
                    LogicTooLong=DsLengths>meanEdgeLength;
                    Ds{it,is}(LogicTooLong,:)=meanEdgeLength*Ds{it,is}(LogicTooLong,:)./DsLengths(LogicTooLong);
                case {'Lamda1','Lamda2'}
                    Ds{it,is}=optStruct.quiverScaleFactor*(FC{it,is}-1).*D{it,is}; % direction with magnitude (scaled vector)
                    DsLengths=sqrt((sum(Ds{it,is}.^2,2)));
                    LogicTooLong=DsLengths>meanEdgeLength;
                    Ds{it,is}(LogicTooLong,:)=meanEdgeLength*Ds{it,is}(LogicTooLong,:)./DsLengths(LogicTooLong);
            end
            Vc{it,is}=DIC3DPPresults.FaceCentroids_ARBM{it}-.5*Ds{it,is};
        else
            FC{it,is}=DIC3DPPresults.Deform.(faceMeasureCell{is}){it}; % face color (strain)
            D{it,is}=DIC3DPPresults.Deform.(directionStringCell{is}){it}; % direction (unit vector)

            switch faceMeasureCell{is}
                case {'Epc1','Epc2','epc1','epc2'}
                    Ds{it,is}=optStruct.quiverScaleFactor*FC{it,is}.*D{it,is}; % direction with magnitude (scaled vector)
                    DsLengths=sqrt((sum(Ds{it,is}.^2,2)));
                    LogicTooLong=DsLengths>meanEdgeLength;
                    Ds{it,is}(LogicTooLong,:)=meanEdgeLength*Ds{it,is}(LogicTooLong,:)./DsLengths(LogicTooLong);
                case {'Lamda1','Lamda2'}
                    Ds{it,is}=optStruct.quiverScaleFactor*(FC{it,is}-1).*D{it,is}; % direction with magnitude (scaled vector)
                    DsLengths=sqrt((sum(Ds{it,is}.^2,2)));
                    LogicTooLong=DsLengths>meanEdgeLength;
                    Ds{it,is}(LogicTooLong,:)=meanEdgeLength*Ds{it,is}(LogicTooLong,:)./DsLengths(LogicTooLong);
            end
            Vc{it,is}=DIC3DPPresults.FaceCentroids{it}-.5*Ds{it,is};
        end

        if ~isempty(optStruct.maxCorrCoeff)
            corrNow=DIC3DPPresults.FaceCorrComb{it};
            FC{it,is}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
            D{it,is}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
            Vc{it,is}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
        end

    end
end
FCmat = cell2mat(FC);
if ~isfield(optStruct,'colorBarLimits')
    switch faceMeasureCell{is}
        case {'Epc1','Epc2','epc1','epc2'}
            Emax=max(abs(FCmat(:)));
            optStruct.colorBarLimits=[-Emax Emax];
        case {'Lamda1','Lamda2'}
            Lmax=max(abs(FCmat(:)-1));
            if Lmax>1
                optStruct.colorBarLimits=[0 2];
            else
                optStruct.colorBarLimits=[1-prctile(abs(FCmat(:)-1),100) 1+prctile(abs(FCmat(:)-1),100)];
            end
    end
end
colorBarLogic=1;
if ~isfield(optStruct,'colorMap')
    optStruct.colorMap=.8*coldwarm;
end

%% Plot

animStruct=struct;

hf=cFigure;
hf.Units='normalized'; hf.OuterPosition=[.05 .05 .9 .9]; hf.Units='pixels';

for is=1:nStrains
    subplot(1,nStrains,is);

    axisGeom;
    ax=gca;
    ax.CameraUpVector=[0 0 optStruct.zDirection];
    colormap(optStruct.colorMap);
    if colorBarLogic
        colorbar;
        caxis(optStruct.colorBarLimits);
    end

    title(optStruct.supTitleString{is});
%     axis off
    % camlight headlight

    it=1;
    Fnow=DIC3DPPresults.Faces;
    if RBMlogic
        Pnow=DIC3DPPresults.Points3D_ARBM{it};
    else
        Pnow=DIC3DPPresults.Points3D{it};
    end

    Vnow=Vc{it,is};
    FCnow=FC{it,is};
    Dnow=Ds{it,is};
    if optStruct.smoothLogic
        smoothPar.lambda=0.5;
        smoothPar.n=2;
        [FCnow]=patchSmoothFaceMeasure(Fnow,Pnow,FCnow,smoothPar);
    end
    FCnow(FCnow<optStruct.dataLimits(1))=NaN;
    FCnow(FCnow>optStruct.dataLimits(2))=NaN;

    hp(is)=gpatch(Fnow,Pnow,FCnow,optStruct.lineColor,optStruct.FaceAlpha); hold on
    hq(is)=quiver3(Vnow(:,1),Vnow(:,2),Vnow(:,3),Dnow(:,1),Dnow(:,2),Dnow(:,3),0,'Color',.2*[1 1 1],'ShowArrowHead','off','AutoScale','off'); hold on;
%
    h_ax=gca;
    h_ax.XLim = xl; h_ax.YLim = yl; h_ax.ZLim = zl;

end

%% fill in the animstruct

animStruct.Time=1:nFrames;
animStruct.Handles=cell(1,nFrames);
animStruct.Props=cell(1,nFrames);
animStruct.Set=cell(1,nFrames);

for it=1:nFrames
    animStruct.Handles{it}=[];
    animStruct.Props{it}=cell(1,8*nStrains);
    animStruct.Set{it}=cell(1,8*nStrains);

    for is=1:nStrains
        if RBMlogic
            Pnow=DIC3DPPresults.Points3D_ARBM{it};
        else
            Pnow=DIC3DPPresults.Points3D{it};
        end
        Fnow=DIC3DPPresults.Faces;
        FCnow=FC{it,is};
        if optStruct.smoothLogic
            [FCnow]=patchSmoothFaceMeasure(Fnow,Pnow,FCnow,smoothPar);
        end
        FCnow(FCnow<optStruct.dataLimits(1))=NaN;
        FCnow(FCnow>optStruct.dataLimits(2))=NaN;

        Vnow=Vc{it,is};
        Dnow=Ds{it,is};

        animStruct.Handles{it}=[animStruct.Handles{it} hp(is) hp(is) hq(is) hq(is) hq(is) hq(is) hq(is) hq(is)]; %Handles of objects to animate (add one every pair)

        animStruct.Props{it}{1+8*(is-1)}='CData';
        animStruct.Props{it}{2+8*(is-1)}='Vertices'; %Properties of objects to animate
        animStruct.Props{it}{3+8*(is-1)}='XData'; %Properties of objects to animate
        animStruct.Props{it}{4+8*(is-1)}='YData'; %Properties of objects to animate
        animStruct.Props{it}{5+8*(is-1)}='ZData'; %Properties of objects to animate
        animStruct.Props{it}{6+8*(is-1)}='UData'; %Properties of objects to animate
        animStruct.Props{it}{7+8*(is-1)}='VData'; %Properties of objects to animate
        animStruct.Props{it}{8+8*(is-1)}='WData'; %Properties of objects to animate

        animStruct.Set{it}{1+8*(is-1)}=FCnow;
        animStruct.Set{it}{2+8*(is-1)}=Pnow; %Property values for to set in order to animate
        animStruct.Set{it}{3+8*(is-1)}=Vnow(:,1); %Property values for to set in order to animate
        animStruct.Set{it}{4+8*(is-1)}=Vnow(:,2); %Property values for to set in order to animate
        animStruct.Set{it}{5+8*(is-1)}=Vnow(:,3); %Property values for to set in order to animate
        animStruct.Set{it}{6+8*(is-1)}=Dnow(:,1); %Property values for to set in order to animate
        animStruct.Set{it}{7+8*(is-1)}=Dnow(:,2); %Property values for to set in order to animate
        animStruct.Set{it}{8+8*(is-1)}=Dnow(:,3); %Property values for to set in order to animate

        h_ax.XLim = xl; h_ax.YLim = yl; h_ax.ZLim = zl;

    end
end

anim8(hf,animStruct);

addColorbarLimitsButton(hf);
addColormapButton(hf);
addEdgeColorButton(hf);
addFaceAlphaButton(hf);
addLightButton(hf);
addAmbientStrengthButton(hf);
addDiffuseStrengthButton(hf);
addSpecularStrengthButton(hf);
addQuiverFactorButton(hf);
addFaceLightingButton(hf);

end

%%
% MultiDIC: a MATLAB Toolbox for Multi-View 3D Digital Image Correlation
%
% License: <https://github.com/MultiDIC/MultiDIC/blob/master/LICENSE.txt>
%
% Copyright (C) 2018  Dana Solav
% %
% If you use the toolbox/function for your research, please cite our paper:
% <https://engrxiv.org/fv47e>


function bnet = mk_dbn(intra, inter, node_sizes, varargin)
% MK_DBN Make a Dynamic Bayesian Network.
%
% BNET = MK_DBN(INTRA, INTER, NODE_SIZES, ...) makes a DBN with arcs
% from i in slice t to j in slice t iff intra(i,j) = 1, and
% from i in slice t to j in slice t+1 iff inter(i,j) = 1,
% for i,j in {1, 2, ..., n}, where n = num. nodes per slice, and t >= 1.
% node_sizes(i) is the number of values node i can take on.
% The nodes are assumed to be in topological order. Use TOPOLOGICAL_SORT if necessary.
% See also mk_bnet.
%
% Optional arguments [default in brackets]
% 'discrete' - list of discrete nodes [1:n]
% 'observed' - the list of nodes which will definitely be observed in every slice of every case [ [] ]
% 'eclass1' - equiv class for slice 1 [1:n]
% 'eclass2' - equiv class for slice 2 [tie nodes with equivalent parents to slice 1]
%    equiv_class1(i) = j means node i in slice 1 gets its parameters from bnet.CPD{j},
%    i.e., nodes i and j have tied parameters.
% 'intra1' - topology of first slice, if different from others
% 'names' - a cell array of strings to be associated with nodes 1:n [{}]
%    This creates an associative array, so you write e.g.
%     'evidence(bnet.names{'bar'}) = 42' instead of  'evidence(2} = 42'
%     assuming names = { 'foo', 'bar', ...}.
%
% For backwards compatibility with BNT2, arguments can also be specified as follows
%   bnet = mk_dbn(intra, inter, node_sizes, dnodes, eclass1, eclass2, intra1)
%
% After calling this function, you must specify the parameters (conditional probability
% distributions) using bnet.CPD{i} = gaussian_CPD(...) or tabular_CPD(...) etc.

n = length(intra);
ss = n;
bnet.nnodes_per_slice = ss;
bnet.intra = intra;
bnet.inter = inter;
bnet.intra1 = intra;
dag = zeros(2*n);
dag(1:n,1:n) = bnet.intra1;
dag(1:n,(1:n)+n) = bnet.inter;
dag((1:n)+n,(1:n)+n) = bnet.intra;
bnet.dag = dag;
bnet.names = {};

directed = 1;
if ~acyclic(dag,directed)
  error('graph must be acyclic')
end

bnet.eclass1 = 1:n;
%bnet.eclass2 = (1:n)+n;
bnet.eclass2 = bnet.eclass1;
for i=1:ss
  if isequal(parents(dag, i+ss), parents(dag, i)+ss)
    %fprintf('%d has isomorphic parents, eclass %d\n', i, bnet.eclass2(i))
  else
    bnet.eclass2(i) = max(bnet.eclass2) + 1;
    %fprintf('%d has non isomorphic parents, eclass %d\n', i, bnet.eclass2(i))
  end
end

dnodes = 1:n;
bnet.observed = [];

if nargin >= 4
  args = varargin;
  nargs = length(args);
  if ~isstr(args{1})
    if nargs >= 1, dnodes = args{1}; end
    if nargs >= 2, bnet.eclass1 = args{2}; end
    if nargs >= 3, bnet.eclass2 = args{3}; end
    if nargs >= 4, bnet.intra1 = args{4}; end
  else
    for i=1:2:nargs
      switch args{i},
       case 'discrete', dnodes = args{i+1};
       case 'observed', bnet.observed = args{i+1};
       case 'eclass1',  bnet.eclass1 = args{i+1};
       case 'eclass2',  bnet.eclass2 = args{i+1};
       case 'intra1',  bnet.intra1 = args{i+1};
       %case 'ar_hmm',  bnet.ar_hmm = args{i+1};  % should check topology
       case 'names',  bnet.names = assocarray(args{i+1}, num2cell(1:n));
       otherwise,
	error(['invalid argument name ' args{i}]);
      end
    end
  end
end

bnet.observed = sort(bnet.observed); % for comparing sets
ns = node_sizes;
bnet.node_sizes_slice = ns(:)';
bnet.node_sizes = [ns(:) ns(:)];

cnodes = mysetdiff(1:n, dnodes);
bnet.dnodes_slice = dnodes;
bnet.cnodes_slice = cnodes;
bnet.dnodes = [dnodes dnodes+n];
bnet.cnodes = [cnodes cnodes+n];

bnet.equiv_class = [bnet.eclass1(:) bnet.eclass2(:)];
bnet.CPD = cell(1,max(bnet.equiv_class(:)));
eclass = bnet.equiv_class(:);
E = max(eclass);
bnet.rep_of_eclass = zeros(1,E);
for e=1:E
  mems = find(eclass==e);
  bnet.rep_of_eclass(e) = mems(1);
end

ss = n;
onodes = bnet.observed;
hnodes = mysetdiff(1:ss, onodes);
bnet.hidden_bitv = zeros(1,2*ss);
bnet.hidden_bitv(hnodes) = 1;
bnet.hidden_bitv(hnodes+ss) = 1;

bnet.parents = cell(1, 2*ss);
for i=1:ss
  bnet.parents{i} = parents(bnet.dag, i);
  bnet.parents{i+ss} = parents(bnet.dag, i+ss);
end

bnet.auto_regressive = zeros(1,ss);
% ar(i)=1 means (observed) node i depends on i in the  previous slice
for o=bnet.observed(:)'
  if any(bnet.parents{o+ss} <= ss)
    bnet.auto_regressive(o) = 1;
  end
end


% EASY3	  Read RINEX navigation file, version 3.03, and reformat
%             into a Matlab Eph matrix. Open a RINEX observation file,
%             version 3.03, analyse the header and identify observation
%             types. The call fgetl finds the information for the epoch time.
%             Next we read observations line  by line. Finally recpo_ls
%             estimates the  (stand alone) receiver position.

% Kai Borre 31-10-2001
% Copyright (c) by Kai Borre
% $Revision: 1.0 $  $Date: 2001/10/31  $
% Total revision 2.0, February 13, 2016

% RINEX version 3.03

% Read RINEX ephemerides file and convert to internal Matlab format
rinexe('log_24h.15n','eph.dat');
% rinexe('D:\Work\Laboratory\Trana\rec\r302_long\Bas_log_2016_05_07_12.00.00.16N','eph.dat');
Eph = get_eph('eph.dat');

% Open the observation file
ofile2 = 'log_r.15o'; % log_24h.15o
% ofile2 = 'D:\Work\Laboratory\Trana\rec\r302_long\Bas_log_2016_05_07_12.00.00.16o';
fid2 = fopen(ofile2,'rt');

% The selection of observation type is set
ss = 'C1W'%;
linjer = 0;

while 1			   % Gobbling the header
    linjer = linjer +1;
    line = fgetl(fid2);
    answer = strfind(line,'END OF HEADER');
    if  ~isempty(answer), break; end;
    if (line == -1), eof = 1; break; end;
    answer = strfind(line,'ANT # / TYPE');
    if ~isempty(answer)
        delta = textscan(fid2,'%6.4f','Delimiter','\n');
        delt = delta{1};
        delx = delt(1,1);
        dely = delt(2,1);
        delz = delt(3,1);
    end

    answer = strfind(line,'SYS / # / OBS TYPES');
    if ~isempty(answer)
        tline1 = strsplit(line);
        line = fgetl(fid2);
        tline2 = strsplit(line);
        tt = horzcat(tline1,tline2);
        i = strcmp(tt,ss); % if tt equals ss, i =1, else 0
        ii = find(i == 1) ;
        ii = ii-2;
        if ii > 15,  ii = ii-7; end;
        % the cell array of strings tline1 originally contains two strings
        % which describe the system and number of observation types.
        % Both tline1 and tline2 terminates with six additional strings.
        % An extra string appears at  the start of tline2; it originates
        % from concatenation of  the two lines. The indexing does not
        % change, even if you empty the cells. They remain empty
        % cells and keep a place
        obs_col = ii%;
    end;
    answer = strfind(line,'INTERVAL');
    if ~isempty(answer)
        interval = strtok(line);
        int = str2double(interval);
    end;
end % end reading header

% the string arrays for the tline1 and tline2 contain an integer after the
% carrier phase observation. We account for this by the following
% correctional table
if         strcmp(ss(2:3), '1C'), obs_col = obs_col +1;
elseif   strcmp(ss(2:3), '1W'), obs_col = obs_col+2;
elseif  strcmp(ss(2:3), '2X'), obs_col = obs_col +3;
else    strcmp(ss(2:3), '2W'), obs_col = obs_col +4;
end

Pos = [];
epoch = 0;
dt = [];
Tline = [];

while ~feof(fid2)
    epoch = epoch +1;
    %time = 0;
    sats = [];
    sats0 = [];

    % We read the first line in every  epoch and get sow and
    % number of SVs.
    [time,post] = textscan(fid2,'%s %d8','Delimiter','\n');
    tid = time{1}{1};
    year = str2double(tid(3:6));
    month = str2double(tid(8:9));
    day = str2double(tid(11:12));
    hour = str2double(tid(14:15));
    minute = str2double(tid(17:18));
    second = str2double(tid(20:29));
    static = str2double(tid(31:32));
    NoSvs = str2double(tid(34:36));
    dte  = str2double(tid(38:56));
    dt = [dt dte];
    h = hour+minute/60+second/3600;
    jd = julday(year, month, day, h);
    [~, sec_of_week] = gps_time(jd);
    time = sec_of_week; % sow

    Obs = zeros(NoSvs,length(obs_col));
    for i = 1:NoSvs
        obs = textscan(fid2,'%s %d8','Delimiter','\n');
        obsy = obs{1}{1};
        obs = strsplit(obsy);
        sat = obs{1};
        sats(i,:) = str2double(sat(2:3));
        Obs(i,1) = str2double(obs(obs_col));
    end

    % Next we test if all observed sats have an ephemeris.
    % sats contains the SVs as read in the observation lines.
    % The intersect command delivers Sats in sorted order!
    % Therefore we must be careful in the follwing manipulations
    Sats = intersect(sats,Eph(1,:));

    %The command ismember does not change the sequence of entries in sats
    lia = ismember(sats,Sats);
    % A 0 (zero) in lia indicates that a SV has been deleted. We delete the
    % corresponding row in the observations
    sats(lia==0) = [];
    Obs(lia==0) = [];
    % All book-keeping has prepared the data so that we can nake the call
    % for a  final position computation
    pos = recpo_ls(Obs,sats,time,Eph);
    Pos = [Pos pos];
end % while
fclose(fid2);

me = mean(Pos,2);
fprintf('\n\nMean Position as Computed From %d Epochs:', epoch)
fprintf('\n\nX: %12.3f  Y: %12.3f  Z: %12.3f\n\n', me(1,1), me(2,1), me(3,1))

figure(1);
plot(1:epoch,(Pos(1,:)-Pos(1,1)*ones(1,epoch))','-',...
    1:epoch,(Pos(2,:)-Pos(2,1)*ones(1,epoch))','-.',...
    1:epoch,(Pos(3,:)-Pos(3,1)*ones(1,epoch))','--','linewidth',.25)
title('Positions over time','fontsize',16)
legend('X','Y','Z')
xlabel('Epochs [1 s interval]','fontsize',16)
ylabel('Changes in {\itX}, {\itY}, {\itZ} since the first epoch [m]','fontsize',16)
set(gca,'fontsize',16)
legend
print -dpdf easy31

figure(2);
plot(1:epoch,dt*10^6')
ylabel('Receiver clock off-set in {\mu}s','fontsize',16),
xlabel('Epochs [1 s interval]','fontsize',16)
print -dpdf  easy32

% transformation from (X, Y, Z) to geographical coordinates
[phi, lambda, h] = cart2geo(me(1,1), me(2,1), me(3,1), 5)
%%%%%%%%%%%%%%%%%%%%% end easy3.m %%%%%%%%%%%%%%%


% This make.m is for MATLAB and OCTAVE under Windows, Mac, and Unix
function make(opt)
fprintf('=> Building liblinear.\n');
if nargin < 1
    try
        % This part is for OCTAVE
        if(exist('OCTAVE_VERSION', 'builtin'))
            % Use -std=c++11 for newer versions of Octave
            if ispc
                setenv('CFLAGS','-std=gnu99 -O3')
                setenv('CC','gcc')
            else
                setenv('CFLAGS','-O3 -fstack-protector-strong -Wformat -Werror=format-security')
            end
            %mex libsvmread.c
            %mex libsvmwrite.c
            mex -I.. -O3 svmtrain.cpp linear_model_matlab.cpp ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
            mex -I.. -O3 svmpredict.cpp linear_model_matlab.cpp ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
            delete *.o
            % This part is for MATLAB
            % Add -largeArrayDims on 64-bit machines of MATLAB
        else
            if ispc
                %mex COMPFLAGS="\$COMPFLAGS -std=c99 -O3" -largeArrayDims libsvmread.c
                %mex COMPFLAGS="\$COMPFLAGS -std=c99 -O3" -largeArrayDims libsvmwrite.c
                mex COMPFLAGS="\$COMPFLAGS -O3" -I.. -largeArrayDims svmtrain.cpp linear_model_matlab.cpp ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
                mex COMPFLAGS="\$COMPFLAGS -O3" -I.. -largeArrayDims svmpredict.cpp linear_model_matlab.cpp ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
            else
                %mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmread.c
                %mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmwrite.c
                mex CFLAGS="\$CFLAGS" -I.. -largeArrayDims svmtrain.cpp linear_model_matlab.cpp ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
                mex CFLAGS="\$CFLAGS" -I.. -largeArrayDims svmpredict.cpp linear_model_matlab.cpp ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
            end
        end
    catch err
        fprintf('Error: %s failed (line %d)\n', err.stack(1).file, err.stack(1).line);
        disp(err.message);
        fprintf('=> Please check README for detailed instructions.\n');
    end
elseif nargin == 1
    switch lower(opt)
        case 'clean'
            delete *.o
        case 'cleanall'
            delete *.o
            delete *.mexa64
        otherwise
            error('make option "%s" not recognized', opt)
    end
end


% This file is part of the project NILM-Eval (https://github.com/beckel/nilm-eval).
% Licence: GPL 2.0 (http://www.gnu.org/licenses/gpl-2.0.html)
% Copyright: ETH Zurich, 2014
% Author: Romano Cicchetti

% Returns a threshold that defines whether
% the specified appliance is in state 'on' or 'off'
function [threshold] = getThresholdDiffOnOff(applianceID)

threshold_vector = [
        15;  % fridge
        15;  % freezer
        500; % microwave
        500; % dishwasher
        15;  % entertainment
        500; % kettle
        500; % stove
        15;  % coffee machine
        500; % washing machine
        300; % dryer
        15;  % lamp
        15;  % PC
        15;  % laptop
        15;  % TV
        15;  % Stereo
        5;   % Tablet
        5;   % Router
        5;   % Illuminated fountain
    ]; % stereo

     threshold = threshold_vector(applianceID,1);
end


function [uOutput] = import_harvard(nFunction, sFilename)
% [uOutput] = harvardcmt_imp(nFunction, sFilename);
% ----------------------------------------------------------
% Imports Harvard CMT data of a selfmade ASCII-file.
% Use 'getharvardcatalog' in the importfilters/harvard directory.
% See import_harvard_doc.html for more information.
%
% D. Schorlemmer; schorlemmer@sed.ethz.ch
%
% 17.05.2005

% Filter function switchyard
if nFunction == FilterOp.getDescription
  uOutput = 'Harvard CMT catalog';
elseif nFunction == FilterOp.getWebpage
  uOutput = 'import_harvard_doc.html';
elseif nFunction == FilterOp.importCatalog
  % Read formated data
  mData = textread(sFilename, '%s', 'delimiter', '\n', 'whitespace', '');
  % Create empty catalog
  uOutput = zeros(length(mData), 10);
  % Loop thru all lines of catalog and convert them
  for i = 1:length(mData)
    if rem(i,100) == 0 ; disp([ num2str(i) ' of ' num2str(length(mData)) ' events processed']); end
    try
      uOutput(i,1) = str2num(mData{i}(28:34));      % Longitude (PDE)
      uOutput(i,2) = str2num(mData{i}(21:25));      % Latitude  (PDE)
      uOutput(i,3) = str2num(mData{i}(1:2));        % Year
      if uOutput(i,3) < 76
        uOutput(i,3) = uOutput(i,3)+2000;
      else
        uOutput(i,3) = uOutput(i,3)+1900;
      end
      uOutput(i,4) = str2num(mData{i}(4:5));        % Month
      uOutput(i,5) = str2num(mData{i}(7:8));        % Day
      uOutput(i,6) = str2num(mData{i}(82:85));      % Magnitude Mw
      uOutput(i,7) = str2num(mData{i}(36:40));      % Depth (PDE)
      uOutput(i,8) = str2num(mData{i}(10:11));      % Hour
      uOutput(i,9) = str2num(mData{i}(13:14));      % Minute
      uOutput(i,10) = str2num(mData{i}(16:19));     % Second
      uOutput(i,11) = nan;                          % Reserved for cross-section values

      uOutput(i,12) = str2num(mData{i}(87:89));     % Strike (Plane 1)
      uOutput(i,13) = uOutput(i,12) + 90;           % Dip direction (Plane 1)
      uOutput(i,13) = mod(uOutput(i,13) + 360, 360);
      uOutput(i,14) = str2num(mData{i}(91:92));     % Dip (Plane 1)
      uOutput(i,15) = str2num(mData{i}(94:97));     % Rake (Plane 1)

      uOutput(i,16) = str2num(mData{i}(99:101));    % Strike (Plane 2)
      uOutput(i,17) = uOutput(i,16) + 90;           % Dip direction (Plane 2)
      uOutput(i,17) = mod(uOutput(i,17) + 360, 360);
      uOutput(i,18) = str2num(mData{i}(103:104));   % Dip (Plane 2)
      uOutput(i,19) = str2num(mData{i}(106:109));   % Rake (Plane 2)

      uOutput(i,20) = str2num(mData{i}(42:44));     % Magnitude mb
      uOutput(i,21) = str2num(mData{i}(46:48));     % Magnitude Ms
      uOutput(i,22) = str2num(mData{i}(50:55));     % Latitude (HAV)
      uOutput(i,23) = str2num(mData{i}(57:63));     % Longitude (HAV)
      uOutput(i,24) = str2num(mData{i}(65:69));     % Depth (HAV)
      uOutput(i,25) = str2num(mData{i}(72:75));     % Cen_time
      uOutput(i,26) = str2num(mData{i}(77:80));     % Half Duration
      % Create decimal year
      uOutput(i,3) = decyear([uOutput(i,3) uOutput(i,4) uOutput(i,5) uOutput(i,8) uOutput(i,9) uOutput(i,16)]);
    catch
      msg.dbfprintf('Import: Problem in line %d of %s. Line ignored.\n',i, sFilename);
    end
  end
end