function fmri_loc1_GLMcontrasts

% LO Localizer scans processing code
%
% USER IMPORTANT!!!: Before running this script, make sure that all loloc
% scans have the correct annotation fields and scan groups (are grouped
% correctly). Otherwise, fmri_FFA_checkDataTypesForGLM will fail.
%
% 1. Set GLM parameters for all scans
% 2. Check LO localizer experiments for:
%    a. Datatype and scan numbers
%    b. Record parfiles
%    c. Make sure scan groupings are correct
% 3. Run GLM for LO localizer experiments
% 4. Run contrasts for the LO localizer experiments
%
% Calls the functions:
% * fmri_loc1_setGLMparams (subfunction)
% * fmri_loc1_checkDataTypesForGLM
% * fmri_loc1_computeContrastsLocalizer
%
%
% DY 06/05/2008
% Modified 06/18/2008: there are calls to er_setParams and saveSessions all
% over the place, which results in the params for the MotionComp_RefScan1
% being changed for the worse. I'm not sure how to efficiently prevent this
% from happening, so instead, I let it happen, and just fix the ANNOTATION
% and PARFILE fields at the end, since accuracy here is important.
%
% Code taken from fmri_FFA_motionCompFix
% AL 11/08: Adapted for loc1 GLM

clear all

% Set directory and subject list
% Alternatively: subs = {'sess1','sess2','sess3',...};
if ispc
    fmriDir = 'W:\projects\Kids\fmri\localizer\';
else
    %fmriDir = '/biac1/kgs/projects/Kids/fmri/localizer/';
    fmriDir='/biac1/kgs/projects/Kids/fmri/code/Alina/Subject/';
end
cd(fmriDir); s=dir('*0*'); subs={s.name};

% Start a log text file to document successes and failures in preprocessing
dateAndTime=datestr(now); dateAndTime(12)='_'; dateAndTime(15)='h';dateAndTime(18)='m';
logDir=fullfile(fmriDir,'logs');
if ~isdir(logDir), mkdir(logDir), end;
logFile = fullfile(fmriDir,'logs',['LO1_Log_' dateAndTime '.txt']);
fid=fopen(logFile,'w');
[junk,logFileName]=fileparts(logFile)
scriptName = 'fmri_loc1_GLMcontrasts.m';
startTime = clock;

% 1. Set GLM parameters
params=fmri_loc1_setGLMparams(fid,logFileName,scriptName); % Subfunction within this script

for ii=1:length(subs)

    % Get rid of all mrVista globals in workspace. Put this at the top,
    % just in case we break from the rest of the loop.
    clear dataTYPES mrSESSION vANATOMYPATH HOMEDIR hI newDt newScan

    thisDir = fullfile(fmriDir,subs{ii}); cd(thisDir);
    fprintf(fid,'\n ------------------------------------------ \n');
    fprintf(fid,'Processing %s\n\n',thisDir);
    fprintf('Processing %s\n\n',thisDir);

    %% Check if the subject already has been processed by script (and thus
    %% should not be re-entered to this script). If they do, skip to the
    %% next subject by using CONTINUE.
    load mrSESSION.mat
    theglm=find(strcmp({dataTYPES.name},'GLMs'));
    if ~isempty(theglm)
        checkScans=length(dataTYPES(theglm).eventAnalysisParams);
        alreadyDone=[];
        for xx=1:checkScans
            tmp=(strfind(lower(dataTYPES(theglm).eventAnalysisParams(xx).annotation),'lo localizer run 1'));
            alreadyDone=[alreadyDone tmp];
        end
        if(~isempty(alreadyDone))
            fprintf(fid,'Error: Subject already processed (has GLM with ''LO localizer Run 1'' in annotation field), skipping... \n\n');
            fprintf('Error: Subject already processed (has GLM with ''LO localizer Run 1'' in annotation field), skipping... \n\n');
            continue
        end
    end

    %% 2a/b/c. Find datatype number for MotionComp_RefScan1, find scan
    %% numbers for lo localizer scans, record parfiles for these scans and
    %% make sure scan groupings are correct. If everything checks out,
    %% proceed with GLM. If not, SKIP THIS SUBJECT.
    [go,s1]=fmri_loc1_checkDataTypesForGLM(fid,dataTYPES);
    %clear dataTYPES mrSESSION vANATOMYPATH

    % If there was a problem in step 3, skip GLM and proceed to next
    % subject
    if go==0
        continue

    %% 3. Otherwise, run GLM (to debug: fid=1)
    elseif go==1
        try
            % Initialize a hidden view of the 'inplane' data (like invoking
            % mrVista without a GUI, dataTYPES/etc in workspace)
            hI = initHiddenInplane(s1.mc, s1.scan);
            params.parfiles={s1.parfile};
            er_setParams(hI, params, s1.scan, s1.mc); % write params as eventAnalysisParams fields
            tic; [hI, lo_scan] = applyGlm(hI,s1.mc,s1.scangroup,params);
            time=toc;
            fprintf(fid,'GLM COMPLETED -- dt %d, scan %d. Time: %d m %2.2f s \n\n',...
                hI.curDataType,lo_scan,floor(time/60),mod(time,60));
            fprintf('GLM COMPLETED -- dt %d, scan %d. Time: %d m %2.2f s \n\n',...
                hI.curDataType,lo_scan,floor(time/60),mod(time,60));
            glmOK=1;
        catch
            fprintf(fid,'FAILURE TO SUCCESSFULLY RUN GLM \n');
            fprintf('FAILURE TO SUCCESSFULLY RUN GLM \n');
            theerror=lasterror;
            fprintf(fid,'%s \n\n',theerror.message);
            fprintf('%s \n\n',theerror.message);
            glmOK=0;
        end

        %% 4. Compute contrast maps
        if glmOK

            try
                fmri_loc1_computeContrastsLocalizer(hI, lo_scan)
                fprintf(fid,'Computed contrasts using fmri_FFA_computeContrastsLocalizer \n');
                fprintf('Computed contrasts using fmri_FFA_computeContrastsLocalizer \n');
            catch
                fprintf(fid,'FAILURE TO SUCCESSFULLY COMPUTE CONTRASTS \n');
                fprintf('FAILURE TO SUCCESSFULLY COMPUTE CONTRASTS \n');
                theerror=lasterror;
                fprintf(fid,'%s \n\n',theerror.message);
                fprintf('%s \n\n',theerror.message);

            end
        end
    end

    % Fix the annotation and parfile fields for the MotionComp_RefScan
    % dataTYPE, since these are undesirably changed (collateral damage).
    dataTYPES(s1.mc).eventAnalysisParams(s1.scan).annotation='loloc_run1';

    par1=dataTYPES(s1.mc).scanParams(s1.scan).parfile;

    dataTYPES(s1.mc).eventAnalysisParams(s1.scan).parfiles=par1;
    save(fullfile(thisDir,'mrSESSION.mat'),'mrSESSION','dataTYPES', '-append');
    clear par1

end

totalTime=etime(clock,startTime);

fprintf(fid,'\n ------------------------------------------ \n');
fprintf(fid,'Total running time for script: %f minutes \n',totalTime/60);
fprintf('Total running time for script: %f minutes \n',totalTime/60);

fclose(fid); % close out the log file

return

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function params=fmri_loc1_setGLMparams(fid,logFileName,scriptName)

% Set GLM parameters: We set the PARAMS struct fields to the values on the
% wiki, which are further explained there. Also we print the values to the
% log. http://vpnl.stanford.edu/internal/wiki/index.php/ROIanalysis#GLMs

fprintf(fid,'\n ------------------------------------------ \n');
fprintf(fid,'\n GLM PARAMETERS \n');
fprintf(fid,' ------------------------------------------ \n');

params=er_defaultParams % Initialize param struct with defaults
p.al='params.alpha=0.0500'; eval(p.al); fprintf(fid,'%s \n',p.al);
p.at='params.ampType=''betas'''; eval(p.at); fprintf(fid,'%s \n',p.at);
p.an='params.annotation=''LO localizer Run 1'''; eval(p.an); fprintf(fid,'%s \n',p.an);
p.ap='params.assignParfiles=0'; eval(p.ap); fprintf(fid,'%s \n',p.ap);
p.bp='params.bslPeriod=[-6 -5 -4 -3 -2 -1 0]'; eval(p.bp); fprintf(fid,'%s \n',p.bp);
p.dt='params.detrend=1'; eval(p.dt); fprintf(fid,'%s \n',p.dt);
p.df='params.detrendFrames=20;'; eval(p.df); fprintf(fid,'%s \n',p.df);
p.ea='params.eventAnalysis=1'; eval(p.ea); fprintf(fid,'%s \n',p.ea);
p.eb='params.eventsPerBlock=6'; eval(p.eb); fprintf(fid,'%s \n',p.eb);
p.fp='params.framePeriod=2'; eval(p.fp); fprintf(fid,'%s \n',p.fp);
p.gt='params.glmHRF=3'; eval(p.gt); fprintf(fid,'%s \n',p.gt);
p.gp='params.glmHRF_params=[6 16 1 1 6 0 24]'; eval(p.gp); fprintf(fid,'%s \n',p.gp);
p.gw='params.glmWhiten=0'; eval(p.gw); fprintf(fid,'%s \n',p.gw); % temporal autocorrelation
p.ic='params.inhomoCorrect=1'; eval(p.ic); fprintf(fid,'%s \n',p.ic);
p.lp='params.lowPassFilter=0'; eval(p.lp); fprintf(fid,'%s \n',p.lp);
p.nb='params.normBsl=1'; eval(p.nb); fprintf(fid,'%s \n',p.nb);
p.od='params.onsetDelta=0'; eval(p.od); fprintf(fid,'%s \n',p.od);
p.pf='params.parfiles='''''; eval(p.pf); fprintf(fid,'%s \n',p.pf); % fill in after checkDataTypes...
p.pp='params.peakPeriod=[4 5 6 7 8 9 10 11 12 13 14]'; eval(p.pp); fprintf(fid,'%s \n',p.pp);
p.sh='params.setHRFParams=0'; eval(p.sh); fprintf(fid,'%s \n',p.sh);
p.sc='params.snrConds=1'; eval(p.sc); fprintf(fid,'%s \n',p.sc);
p.tn='params.temporalNormalization=0'; eval(p.tn); fprintf(fid,'%s \n',p.tn);
p.tw='params.timeWindow=[-6:1:24]'; eval(p.tw); fprintf(fid,'%s \n',p.tw);
p.log=['params.logFile=''' logFileName '''']; eval(p.log); fprintf(fid,'%s \n',p.log)
p.script=['params.scriptName=''' scriptName '''']; eval(p.script); fprintf(fid,'%s \n',p.script)

% params.framePeriod = dataTYPES(dt).scanParams(scan).framePeriod;


function  bz_ConcatenatedTimes(basepath,sortFiles)
%   bz_ConcatenatedTimes(basepath)
%   This function generates the events.mat file that saves all the merge
%   information. Useful if you dind't do this when you merged the dats.
%
%  USAGE
%
%    bz_ConcatenateDats(basepath,sortFiles)
%
%  INPUTS
%
%    basepath          computer path to session folder.  Defaults to
%                      current folder if no input given
%    sortFiles               - boolean denoting whether to sort files according
%                              to time of recording (1) or
%                              not (0) and thus sort them alphabetically
%                              Default = 1.
%
%  OUTPUT
%     Operates on files in specified folder.  No output variable
%
%   Antonio FR 10/2018

%% Handling inputs
if ~exist('basepath','var')
    basepath = cd;
end
basename = bz_BasenameFromBasepath(basepath);

if ~exist('sortFiles','var')
    sortFiles = 1;
end

%% If the dats are not merged quit
if ~exist(fullfile(basepath,[basename,'.dat']),'file')
    disp('no merged dat in directory, quitting')
    return
end

if exist(fullfile(basepath,[basename,'.MergePoints.events.mat']),'file')
    disp('MergedPoints already in directory')
    return
end

%% Find all .dat paths in subfolders

otherdattypes = {'analogin';'digitalin';'auxiliary';'time';'supply'};
bad_otherdattypes = [];
for odidx = 1:length(otherdattypes)
    %eval(['new' otherdattypes{odidx} 'path = fullfile(basepath,''' otherdattypes{odidx} '.dat'');'])
    newpaths.(otherdattypes{odidx}) = fullfile(basepath,[otherdattypes{odidx}, '.dat']);
end

d = dir(basepath);
datpaths = {};
datsizes.amplifier = [];
recordingnames = {};
rcount = 0; %Count of good subfolders
for a = 1:length(d)
    %look in each subfolder
    if d(a).isdir
        %Check for amplifier.dat or subfolderbaseName.dat
        if exist(fullfile(basepath,d(a).name,[d(a).name,'.dat']),'file')
            ampfile = fullfile(basepath,d(a).name,[d(a).name,'.dat']);
        else
            ampfile = fullfile(basepath,d(a).name,'amplifier.dat');
        end

        if exist(ampfile,'file')
            rcount = rcount+1;
            datpaths.amplifier{rcount} = ampfile;
            t = dir(ampfile);
            datsizes.amplifier(rcount) = t.bytes;
            recordingnames{rcount} = d(a).name;

            for odidx = 1:length(otherdattypes)%loop through other .dat types found here
               % eval([otherdattypes{odidx} 'datpaths{rcount} = fullfile(basepath,recordingnames{rcount},''' otherdattypes{odidx} '.dat'');'])
                datpaths.(otherdattypes{odidx}){rcount} = fullfile(basepath,recordingnames{rcount},[otherdattypes{odidx} '.dat']);
                %eval(['d2 = dir(' otherdattypes{odidx} 'datpaths.amplifier{rcount});'])
                d2 = dir(datpaths.(otherdattypes{odidx}){rcount});
                if isempty(d2)
                    bad_otherdattypes(odidx) = 1;
                else
                    %eval([otherdattypes{odidx} 'datsizes(rcount) = d2(1).bytes;'])
                    datsizes.(otherdattypes{odidx})(rcount) = d2(1).bytes;
                end
            end
        end
    end
end
otherdattypes(find(bad_otherdattypes)) = [];%if there weren't analogin or digitalin in some recording
if isempty(datpaths.amplifier)
    disp('No .dats found in subfolders.  Exiting bz_ConcatenateDats.')
    return
end

%% Get the XML
try
    %Look for xml/sessionInfo in topfolder
    sessionInfo = bz_getSessionInfo(basepath,'noPrompts',true);
catch
    %If none exists, look for xml in any of the subpaths
    disp('No .xml or .sessionInfo in top folder, trying subfolders')
    for ff = 1:length(recordingnames)
        try
            sessionInfo = LoadParameters(fullfile(basepath,recordingnames{ff}));
            xmlfilename = fullfile(sessionInfo.session.path,[sessionInfo.session.name,'.xml']);
            [SUCCESS,MESSAGE,MESSAGEID] = copyfile(...
                xmlfilename,...
                fullfile(basepath,[basename,'.xml']),'f');
            display(['Copied xml from ',recordingnames{ff}])
            break
        catch
        end
    end
end

%% Sort files according to time of recording

if sortFiles

    try
        names2sort = cellfun(@(X) str2num(X(end-5:end)),recordingnames,'UniformOutput',false);
        names2sort = cell2mat(names2sort);
        %disp('Assuming the last 6 digits reflect recording time.')
        %disp('Don''t like it? Write in some new options for sorting.')
    catch
        disp('Last 6 digits not numeric... sorting alphabetically')
    end

    [~,I] = sort(names2sort);
    recordingnames = recordingnames(I);
    datpaths.amplifier = datpaths.amplifier(I);
    datsizes.amplifier = datsizes.amplifier(I);
    for odidx = 1:length(otherdattypes)
        datpaths.(otherdattypes{odidx}) = datpaths.(otherdattypes{odidx})(I);
        datsizes.(otherdattypes{odidx}) = datsizes.(otherdattypes{odidx})(I);
    end
else
    disp('not implemented for non temporally sorted concatenation')
end

%% Check that size of resultant .dat is equal to the sum of the components
newdatpath = fullfile(basepath,[basename,'.dat']);
t = dir(newdatpath);
if t.bytes ~= sum(datsizes.amplifier)
    error('New .dat size not right.  Exiting')
    return
else
    sizecheck.amplifier = true;
    disp('Primary .dats concatenated and size checked')
end

%% Get time points from the time.dat
%Use the timestamps from time.dat to get the sort order
%Number of samples in time.dat. First timepoint, last timepoint
%Convert from number of samples to recording time of start/ends
for ff = 1:length(datpaths.time)

	f = fopen(datpaths.time{ff},'r');
    % Determine total number of samples in file
    fileStart = ftell(f);

    %Read the first time point
    firsttimepoint = fread(f,1,'int32');
    status = fseek(f,-4,'eof'); %int32 = 4 bytes
    lasttimepoint = fread(f,1,'int32');
    fileStop = ftell(f);

    firstlasttimepoints(ff,:) = [firsttimepoint lasttimepoint];
    numsamples(ff) = fileStop./4;
    if ff==1
        transitiontimes_samp = firstlasttimepoints(ff,:);
    else
        transitiontimes_samp(ff,:) = firstlasttimepoints(ff,:)+transitiontimes_samp(ff-1,2)+1;
    end
end

disp(['Calculating merge times based on wideband samplingRate of ',num2str(sessionInfo.rates.wideband),'Hz.'])
transitiontimes_sec = transitiontimes_samp./sessionInfo.rates.wideband; %convert to seconds

%% Make the events.mat file that saves all the merge information
% filesT.int == MergePoint.timestamps

eventsfilename = fullfile(basepath,[basename,'.MergePoints.events.mat']);

MergePoints.timestamps = transitiontimes_sec;
MergePoints.timestamps_samples = transitiontimes_samp;
MergePoints.firstlasttimpoints_samples = firstlasttimepoints;
MergePoints.foldernames = recordingnames;
MergePoints.filesmerged = datpaths;
MergePoints.filesizes = datsizes;
MergePoints.sizecheck = sizecheck;
MergePoints.detectorinfo.detectorname = 'bz_ConcatenateDats';
MergePoints.detectorinfo.detectiondate = datestr(now,'yyyy-mm-dd');

save(eventsfilename,'MergePoints');

end


function s=mergestruct(s1,s2)
%
% s=mergestruct(s1,s2)
%
% merge two struct objects into one
%
% authors:Qianqian Fang (q.fang <at> neu.edu)
% date: 2012/12/22
%
% input:
%      s1,s2: a struct object, s1 and s2 can not be arrays
%
% output:
%      s: the merged struct object. fields in s1 and s2 will be combined in s.
%
% license:
%     BSD License, see LICENSE_BSD.txt files for details
%
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
%

if(~isstruct(s1) || ~isstruct(s2))
    error('input parameters contain non-struct');
end
if(length(s1)>1 || length(s2)>1)
    error('can not merge struct arrays');
end
fn=fieldnames(s2);
s=s1;
for i=1:length(fn)
    s=setfield(s,fn{i},getfield(s2,fn{i}));
end


function spm_eeg_inv_vbecd_disp(action,varargin)
% Display the dipoles as obtained from VB-ECD
%
% FORMAT spm_eeg_inv_vbecd_disp('Init',D)
% Display the latest VB-ECD solution saved in the .inv{} field of the
% data structure D.
%
% FORMAT spm_eeg_inv_vbecd_disp('Init',D, ind)
% Display the ind^th .inv{} cell element, if it is actually a VB-ECD
% solution.
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Christophe Phillips
% $Id$

% Note:
% unfortunately I cannot see how to ensure that when zooming in the image
% the dipole location stays in place...

global st

Fig     = spm_figure('GetWin','Graphics');
colors  = {'y','b','g','r','c','m'};              % 6 possible colors
marker  = {'o','x','+','*','s','d','v','p','h'};  % 9 possible markers
Ncolors = length(colors);
Nmarker = length(marker);

if nargin == 0, action = 'Init'; end;

switch lower(action),

%==========================================================================
case 'init'
%==========================================================================
% FORMAT spm_eeg_inv_vbecd_disp('init',D,ind)
% Initialise the variables with GUI
%--------------------------------------------------------------------------

if nargin<2
    D = spm_eeg_load;
else
    D = varargin{1};
end
if nargin<3
    % find the latest inverse produced with vbecd
    Ninv = length(D.inv);
    lind = [];
    for ii=1:Ninv
        if isfield(D.inv{ii},'method') && ...
                strcmp(D.inv{ii}.method,'vbecd')
            lind = [lind ii];
        end
    end
    ind = max(lind);
    if ~ind,
        spm('alert*','No VB-ECD solution found with this data file!',...
                'VB-ECD display')
        return
    end
else
    ind = varargin{3};
end

% Stash dipole(s) information in sdip structure
sdip = D.inv{ind}.inverse;

% if the exit flag is not in the structure, assume everything went ok.
if ~isfield(sdip,'exitflag')
    sdip.exitflag = ones(1,sdip.n_seeds);
end

try
    Pimg = spm_vol(D.inv{ind}.mesh.sMRI);
catch
    Pimg = spm_vol(fullfile(spm('dir'), 'canonical', 'single_subj_T1.nii'));
end

spm_orthviews('Reset');
spm_orthviews('Image', Pimg, [0.0 0.45 1 0.55]);
spm_orthviews('MaxBB');
spm_orthviews('AddContext')
st.callback = 'spm_image(''shopos'');';
% remove clicking in image
for ii=1:3,
    set(st.vols{1}.ax{ii}.ax,'ButtonDownFcn',';');
end
WS = spm('WinScale');

% Build GUI
%==========================================================================
% Location:
%--------------------------------------------------------------------------
uicontrol(Fig,'Style','Frame','Position',[60 25 200 325].*WS, ...
    'DeleteFcn','spm_image(''reset'');');
uicontrol(Fig,'Style','Frame','Position',[70 250 180 90].*WS);
uicontrol(Fig,'Style','Text', 'Position',[75 320 170 016].*WS, ...
    'String','Current Position');
uicontrol(Fig,'Style','Text', 'Position',[75 295 35 020].*WS,'String','mm:');
uicontrol(Fig,'Style','Text', 'Position',[75 275 35 020].*WS,'String','vx:');
uicontrol(Fig,'Style','Text', 'Position',[75 255 75 020].*WS,'String','Img Intens.:');

st.mp = uicontrol(Fig,'Style','Text', 'Position',[110 295 135 020].*WS,'String','');
st.vp = uicontrol(Fig,'Style','Text', 'Position',[110 275 135 020].*WS,'String','');
st.in = uicontrol(Fig,'Style','Text', 'Position',[150 255  85 020].*WS,'String','');

c = 'if get(gco,''Value'')==1, spm_orthviews(''Xhairs'',''off''), else, spm_orthviews(''Xhairs'',''on''); end;';
uicontrol(Fig,'Style','togglebutton','Position',[95 220 125 20].*WS,...
    'String','Hide Crosshairs','Callback',c,'ToolTipString','show/hide crosshairs');

% Dipoles/seeds selection:
%--------------------------------------------------------------------------
uicontrol(Fig,'Style','Frame','Position',[300 25 180 325].*WS);
sdip.hdl.hcl = uicontrol(Fig,'Style','pushbutton','Position',[310 320 100 20].*WS, ...
        'String','Clear all','CallBack','spm_eeg_inv_vbecd_disp(''ClearAll'')');

sdip.hdl.hseed=zeros(sdip.n_seeds,1);
for ii=1:sdip.n_seeds
    if sdip.exitflag(ii)==1
        sdip.hdl.hseed(ii) = uicontrol(Fig,'Style','togglebutton','String',num2str(ii),...
            'Position',[310+rem(ii-1,8)*20 295-fix((ii-1)/8)*20 20 20].*WS,...
            'CallBack','spm_eeg_inv_vbecd_disp(''ChgSeed'')');
    else
        sdip.hdl.hseed(ii) = uicontrol(Fig,'Style','Text','String',num2str(ii), ...
            'Position',[310+rem(ii-1,8)*20 293-fix((ii-1)/8)*20 20 20].*WS) ;
    end
end

uicontrol(Fig,'Style','text','String','Select dipole # :', ...
        'Position',[310 255-fix((sdip.n_seeds-1)/8)*20 110 20].*WS);

txt_box = cell(sdip.n_dip,1);
for ii=1:sdip.n_dip, txt_box{ii} = num2str(ii); end
txt_box{sdip.n_dip+1} = 'all';
sdip.hdl.hdip = uicontrol(Fig,'Style','popup','String',txt_box, ...
        'Position',[420 258-fix((sdip.n_seeds-1)/8)*20 40 20].*WS, ...
        'Callback','spm_eeg_inv_vbecd_disp(''ChgDip'')');

% Dipoles orientation and strength:
%--------------------------------------------------------------------------
uicontrol(Fig,'Style','Frame','Position',[70 120 180 90].*WS);
uicontrol(Fig,'Style','Text', 'Position',[75 190 170 016].*WS, ...
                'String','Dipole orientation & strength');
uicontrol(Fig,'Style','Text', 'Position',[75 165 65 020].*WS, ...
                'String','x-y-z or.:');
uicontrol(Fig,'Style','Text', 'Position',[75 145 75 020].*WS, ...
                'String','theta-phi or.:');
uicontrol(Fig,'Style','Text', 'Position',[75 125 75 020].*WS, ...
                'String','Dip. intens.:');

sdip.hdl.hor1 = uicontrol(Fig,'Style','Text', 'Position', ...
                            [140 165  105 020].*WS,'String','a');
sdip.hdl.hor2 = uicontrol(Fig,'Style','Text', 'Position', ...
                            [150 145  85 020].*WS,'String','b');
sdip.hdl.int  = uicontrol(Fig,'Style','Text', 'Position', ...
                            [150 125  85 020].*WS,'String','c');

st.vols{1}.sdip = sdip;

% First plot = all the seeds that converged !
l_conv = find(sdip.exitflag==1);
if isempty(l_conv)
    error('No seed converged towards a stable solution, nothing to be displayed !')
else
    spm_eeg_inv_vbecd_disp('DrawDip',l_conv,1)
    set(sdip.hdl.hseed(l_conv),'Value',1); % toggle all buttons
end

%==========================================================================
case 'drawdip'
%==========================================================================
% FORMAT spm_eeg_inv_vbecd_disp('DrawDip',i_seed,i_dip,sdip)
% e.g. spm_eeg_inv_vbecd_disp('DrawDip',1,1,sdip)
% e.g. spm_eeg_inv_vbecd_disp('DrawDip',[1:5],1,sdip)
%--------------------------------------------------------------------------

if nargin < 2
    i_seed = 1;
else
    i_seed = varargin{1};
end
if nargin<3
    i_dip = 1;
else
    i_dip = varargin{2};
end

if nargin<4
    if isfield(st.vols{1},'sdip')
        sdip = st.vols{1}.sdip;
    else
        error('I can''t find sdip structure');
    end
else
    sdip = varargin{3};
    st.vols{1}.sdip = sdip;
end

if any(i_seed>sdip.n_seeds) || i_dip>(sdip.n_dip+1)
    error('Wrong i_seed or i_dip index in spm_eeg_inv_vbecd_disp');
end

% Note if i_dip==(sdip.n_dip+1) all dipoles are displayed simultaneously,
% The 3D cut will then be at the mean location of all sources !!!
if i_dip == (sdip.n_dip+1)
    i_dip = 1:sdip.n_dip;
end

% if seed indexes passed is wrong (no convergence) remove the wrong ones
i_seed(sdip.exitflag(i_seed)~=1) = [];
if isempty(i_seed)
    error('You passed the wrong seed indexes...')
end
if size(i_seed,2)==1, i_seed=i_seed'; end

% Display business
%--------------------------------------------------------------------------
loc_mm = sdip.loc{i_seed(1)}(:,i_dip);
if length(i_seed)>1
%     unit = ones(1,sdip.n_dip);
    for ii = i_seed(2:end)
        loc_mm = loc_mm + sdip.loc{ii}(:,i_dip);
    end
    loc_mm = loc_mm/length(i_seed);
end
if length(i_dip)>1
    loc_mm = mean(loc_mm,2);
end

% Place the underlying image at right cuts
spm_orthviews('Reposition',loc_mm);

if length(i_dip)>1
    tabl_seed_dip = [kron(ones(length(i_dip),1),i_seed') ...
                        kron(i_dip',ones(length(i_seed),1))];
else
    tabl_seed_dip = [i_seed' ones(length(i_seed),1)*i_dip];
end

% Scaling, according to all dipoles in the selected seed sets.
% The time displayed is the one corresponding to the maximum EEG power !
Mn_j = -1;
l3 = -2:0;
for ii = 1:length(i_seed)
    for jj = 1:sdip.n_dip
        Mn_j = max([Mn_j sqrt(sum(sdip.j{ii}(jj*3+l3,sdip.Mtb).^2))]);
    end
end
st.vols{1}.sdip.tabl_seed_dip = tabl_seed_dip;

% Display all dipoles, the 1st one + the ones close enough.
% Run through the 6 colors and 9 markers to differentiate the dipoles.
% NOTA: 2 dipoles coming from the same set will have same colour/marker
ind = 1 ;
dip_h = zeros(9,size(tabl_seed_dip,1),1);
    % each dipole displayed has 9 handles:
    %   3 per view (2*3): for the line, for the circle & for the error
js_m = zeros(3,1);

% Deal with case of multiple i_seed and i_dip displayed.
% make sure dipole from same i_seed have same colour but different marker.

pi_dip = find(diff(tabl_seed_dip(:,2)));
if isempty(pi_dip)
    % i.e. only one dip displayed per seed, use old fashion
    for ii=1:size(tabl_seed_dip,1)
        if ii>1
            if tabl_seed_dip(ii,1)~=tabl_seed_dip(ii-1,1)
                ind = ind+1;
            end
        end
        ic = mod(ind-1,Ncolors)+1;
        im = fix(ind/Ncolors)+1;

        loc_pl = sdip.loc{tabl_seed_dip(ii,1)}(:,tabl_seed_dip(ii,2));
        js = sdip.j{tabl_seed_dip(ii,1)}(tabl_seed_dip(ii,2)*3+l3,sdip.Mtb);
        vloc = sdip.cov_loc{tabl_seed_dip(ii,1)}(tabl_seed_dip(ii,2)*3+l3,tabl_seed_dip(ii,2)*3+l3);
        dip_h(:,ii) = add1dip(loc_pl,js/Mn_j*20,vloc, ...
                            marker{im},colors{ic},st.vols{1}.ax,Fig,st.bb);
        js_m = js_m+js;
    end
else
    for ii=1:pi_dip(1)
        if ii>1
            if tabl_seed_dip(ii,1)~=tabl_seed_dip(ii-1,1)
                ind = ind+1;
            end
        end
        ic = mod(ind-1,Ncolors)+1;
        for jj=1:sdip.n_dip
            im = mod(jj-1,Nmarker)+1;

            loc_pl = sdip.loc{tabl_seed_dip(ii,1)}(:,jj);
            js = sdip.j{tabl_seed_dip(ii,1)}(jj*3+l3,sdip.Mtb);
            vloc = sdip.cov_loc{tabl_seed_dip(ii,1)}(jj*3+l3,jj*3+l3);
            js_m = js_m+js;
            dip_h(:,ii+(jj-1)*pi_dip(1)) = ...
                add1dip(loc_pl,js/Mn_j*20,vloc, ...
                        marker{im},colors{ic},st.vols{1}.ax,Fig,st.bb);
        end
    end
end
st.vols{1}.sdip.ax = dip_h;

% Display dipoles orientation and strength
js_m = js_m/size(tabl_seed_dip,1);
[th,phi,Ijs_m] = cart2sph(js_m(1),js_m(2),js_m(3));
Njs_m = round(js_m'/Ijs_m*100)/100;
Angle = round([th phi]*1800/pi)/10;

set(sdip.hdl.hor1,'String',[num2str(Njs_m(1)),' ',num2str(Njs_m(2)), ...
        ' ',num2str(Njs_m(3))]);
set(sdip.hdl.hor2,'String',[num2str(Angle(1)),'� ',num2str(Angle(2)),'�']);
set(sdip.hdl.int,'String',Ijs_m);

% Change the colour of toggle button of dipoles actually displayed
for ii=tabl_seed_dip(:,1)
    set(sdip.hdl.hseed(ii),'BackgroundColor',[.7 1 .7]);
end

%==========================================================================
case 'clearall'
%==========================================================================
% Clears all dipoles, and reset the toggle buttons
%--------------------------------------------------------------------------

if isfield(st.vols{1},'sdip')
    sdip = st.vols{1}.sdip;
else
    error('I can''t find sdip structure');
end

disp('Clears all dipoles')
spm_eeg_inv_vbecd_disp('ClearDip');
for ii=1:st.vols{1}.sdip.n_seeds
    if sdip.exitflag(ii)==1
        set(st.vols{1}.sdip.hdl.hseed(ii),'Value',0);
    end
end
set(st.vols{1}.sdip.hdl.hdip,'Value',1);

%==========================================================================
case 'chgseed'
%==========================================================================
% Changes the seeds displayed
%--------------------------------------------------------------------------

% disp('Change seed')

sdip = st.vols{1}.sdip;
if isfield(sdip,'tabl_seed_dip')
    prev_seeds = p_seed(sdip.tabl_seed_dip);
else
    prev_seeds = [];
end

l_seed = zeros(sdip.n_seeds,1);
for ii=1:sdip.n_seeds
    if sdip.exitflag(ii)==1
        l_seed(ii) = get(sdip.hdl.hseed(ii),'Value');
    end
end
l_seed = find(l_seed);

% Modify the list of seeds displayed
if isempty(l_seed)
    % Nothing left displayed
    i_seed=[];
elseif isempty(prev_seeds)
    % Just one dipole added, nothing before
    i_seed=l_seed;
elseif length(prev_seeds)>length(l_seed)
    % One seed removed
    i_seed = prev_seeds;
    for ii=1:length(l_seed)
        p = find(prev_seeds==l_seed(ii));
        if ~isempty(p)
            prev_seeds(p) = [];
        end % prev_seeds is left with the index of the one removed
    end
    i_seed(i_seed==prev_seeds) = [];
    % Remove the dipole & change the button colour
    spm_eeg_inv_vbecd_disp('ClearDip',prev_seeds);
    set(sdip.hdl.hseed(prev_seeds),'BackgroundColor',[.7 .7 .7]);
else
    % One dipole added
    i_seed = prev_seeds;
    for ii=1:length(prev_seeds)
        p = find(prev_seeds(ii)==l_seed);
        if ~isempty(p)
            l_seed(p) = [];
        end % l_seed is left with the index of the one added
    end
    i_seed = [i_seed ; l_seed];
end

i_dip = get(sdip.hdl.hdip,'Value');
spm_eeg_inv_vbecd_disp('ClearDip');
if ~isempty(i_seed)
    spm_eeg_inv_vbecd_disp('DrawDip',i_seed,i_dip);
end

%==========================================================================
case 'chgdip'
%==========================================================================
% Changes the dipole index for the first seed displayed
%--------------------------------------------------------------------------

disp('Change dipole')
sdip = st.vols{1}.sdip;

i_dip = get(sdip.hdl.hdip,'Value');
if isfield(sdip,'tabl_seed_dip')
    i_seed = p_seed(sdip.tabl_seed_dip);
else
    i_seed = [];
end

if ~isempty(i_seed)
    spm_eeg_inv_vbecd_disp('ClearDip')
    spm_eeg_inv_vbecd_disp('DrawDip',i_seed,i_dip);
end

%==========================================================================
case 'cleardip'
%==========================================================================
% FORMAT spm_eeg_inv_vbecd_disp('ClearDip',seed_i)
% e.g. spm_eeg_inv_vbecd_disp('ClearDip')
%       clears all displayed dipoles
% e.g. spm_eeg_inv_vbecd_disp('ClearDip',1)
%       clears the first dipole displayed
%--------------------------------------------------------------------------

if nargin>2
    seed_i = varargin{1};
else
    seed_i = 0;
end
if isfield(st.vols{1},'sdip')
        sdip = st.vols{1}.sdip;
    else
        return; % I don't do anything, as I can't find sdip strucure
end

if isfield(sdip,'ax')
    Nax = size(sdip.ax,2);
    else
        return; % I don't do anything, as I can't find axes info
end

if seed_i==0 % removes everything
    for ii=1:Nax
        for jj=1:9
            delete(sdip.ax(jj,ii));
        end
    end
    for ii=sdip.tabl_seed_dip(:,1)
        set(sdip.hdl.hseed(ii),'BackgroundColor',[.7 .7 .7]);
    end
    sdip = rmfield(sdip,'tabl_seed_dip');
    sdip = rmfield(sdip,'ax');
elseif seed_i<=Nax % remove one seed only
    l_seed = find(sdip.tabl_seed_dip(:,1)==seed_i);
    for ii=l_seed
        for jj=1:9
            delete(sdip.ax(jj,ii));
        end
    end
    sdip.ax(:,l_seed) = [];
    sdip.tabl_seed_dip(l_seed,:) = [];
else
    error('Trying to clear unspecified dipole');
end
st.vols{1}.sdip = sdip;

%==========================================================================
case 'redrawdip'
%==========================================================================
% spm_eeg_inv_vbecd_disp('RedrawDip')
% redraw everything, useful when zooming into image
%--------------------------------------------------------------------------

% spm_eeg_inv_vbecd_disp('ClearDip')
% spm_eeg_inv_vbecd_disp('ChgDip')

% disp('Change dipole')
sdip = st.vols{1}.sdip;

i_dip = get(sdip.hdl.hdip,'Value');
if isfield(sdip,'tabl_seed_dip')
    i_seed = p_seed(sdip.tabl_seed_dip);
else
    i_seed = [];
end

if ~isempty(i_seed)
    spm_eeg_inv_vbecd_disp('ClearDip')
    spm_eeg_inv_vbecd_disp('DrawDip',i_seed,i_dip);
end

%==========================================================================
otherwise
%==========================================================================
    warning('Unknown action string');
end
% warning(sw);
return

%==========================================================================
% dh = add1dip(loc,js,vloc,mark,col,ax,Fig,bb)
%==========================================================================
function dh = add1dip(loc,js,vloc,mark,col,ax,Fig,bb)
% Plots the dipoles on the 3 views, with an error ellipse for location
% Then returns the handle to the plots

global st
is = inv(st.Space);
loc = is(1:3,1:3)*loc(:) + is(1:3,4);
% taking into account the zooming/scaling only for the location
% NOT for the dipole's amplitude.
% Amplitude plotting is quite arbitrary anyway and up to some scaling
% defined for better viewing...

loc(1,:) = loc(1,:) - bb(1,1)+1;
loc(2,:) = loc(2,:) - bb(1,2)+1;
loc(3,:) = loc(3,:) - bb(1,3)+1;
% +1 added to be like John's orthview code

% prepare error ellipse
vloc = is(1:3,1:3)*vloc*is(1:3,1:3);
[V,E] = eig(vloc);
VE = V*diag(sqrt(diag(E))); % use std
% VE = V*E;   % or use variance ???

dh = zeros(9,1);
figure(Fig)
% Transverse slice, # 1
%----------------------
set(Fig,'CurrentAxes',ax{1}.ax)
set(ax{1}.ax,'NextPlot','add')
dh(1) = plot(loc(1),loc(2),[mark,col],'LineWidth',1);
dh(2) = plot(loc(1)+[0 js(1)],loc(2)+[0 js(2)],col,'LineWidth',2);
% add error ellipse
[uu,ss,vv] = svd(VE([1 2],:));
[phi] = cart2pol(uu(1,1),uu(2,1));
e = diag(ss);
t = (-1:.02:1)*pi;
x = e(1)*cos(t)*cos(phi)-e(2)*sin(t)*sin(phi)+loc(1);
y = e(2)*sin(t)*cos(phi)+e(1)*cos(t)*sin(phi)+loc(2);
dh(3) = plot(x,y,[':',col],'LineWidth',.5);
set(ax{1}.ax,'NextPlot','replace')

% Coronal slice, # 2
%----------------------
set(Fig,'CurrentAxes',ax{2}.ax)
set(ax{2}.ax,'NextPlot','add')
dh(4) = plot(loc(1),loc(3),[mark,col],'LineWidth',1);
dh(5) = plot(loc(1)+[0 js(1)],loc(3)+[0 js(3)],col,'LineWidth',2);
% add error ellipse
[uu,ss,vv] = svd(VE([1 3],:));
[phi] = cart2pol(uu(1,1),uu(2,1));
e = diag(ss);
t = (-1:.02:1)*pi;
x = e(1)*cos(t)*cos(phi)-e(2)*sin(t)*sin(phi)+loc(1);
y = e(2)*sin(t)*cos(phi)+e(1)*cos(t)*sin(phi)+loc(3);
dh(6) = plot(x,y,[':',col],'LineWidth',.5);
set(ax{2}.ax,'NextPlot','replace')

% Sagital slice, # 3
%----------------------
set(Fig,'CurrentAxes',ax{3}.ax)
set(ax{3}.ax,'NextPlot','add')
% dh(5) = plot(dim(2)-loc(2),loc(3),[mark,col],'LineWidth',2);
% dh(6) = plot(dim(2)-loc(2)+[0 -js(2)],loc(3)+[0 js(3)],col,'LineWidth',2);
dh(7) = plot(bb(2,2)-bb(1,2)-loc(2),loc(3),[mark,col],'LineWidth',1);
dh(8) = plot(bb(2,2)-bb(1,2)-loc(2)+[0 -js(2)],loc(3)+[0 js(3)],col,'LineWidth',2);
% add error ellipse
[uu,ss,vv] = svd(VE([2 3],:));
[phi] = cart2pol(uu(1,1),uu(2,1));
e = diag(ss);
t = (-1:.02:1)*pi;
x = -(e(1)*cos(t)*cos(phi)-e(2)*sin(t)*sin(phi))+bb(2,2)-bb(1,2)-loc(2);
y = e(2)*sin(t)*cos(phi)+e(1)*cos(t)*sin(phi)+loc(3);
dh(9) = plot(x,y,[':',col],'LineWidth',.5);
set(ax{3}.ax,'NextPlot','replace')

return

%==========================================================================
% pr_seed = p_seed(tabl_seed_dip)
%==========================================================================
function pr_seed = p_seed(tabl_seed_dip)
% Gets the list of seeds used in the previous display

ls = sort(tabl_seed_dip(:,1));
if length(ls)==1
    pr_seed = ls;
else
    pr_seed = ls([find(diff(ls)) ; length(ls)]);
end

%

% OLD STUFF

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Use it with arguments or not:
% - spm_eeg_inv_vbecd_disp('Init')
%        The routine asks for the dipoles file and image to display
% - spm_eeg_inv_vbecd_disp('Init',sdip)
%        The routine will use the avg152T1 canonical image
% - spm_eeg_inv_vbecd_disp('Init',sdip,P)
%        The routines dispays the dipoles on image P.
%
% If multiple seeds have been used, you can select the seeds to display
% by pressing their index.
% Given that the sources could have different locations, the slices
% displayed will be the 3D view at the *average* or *mean* locations of
% selected sources.
% If more than 1 dipole was fitted at a time, then selection of source 1
% to N is possible through the pull-down selector.
%
% The location of the source/cut is displayed in mm and voxel, as well as
% the underlying image intensity at that location.
% The cross hair position can be hidden by clicking on its button.
%
% Nota_1: If the cross hair is manually moved by clicking in the image or
%       changing its coordinates, the dipole displayed will NOT be at
%       the right displayed location. That's something that needs to be improved...
%
% Nota_2: Some seeds may have not converged within the limits fixed,
%       these dipoles are not displayed...
%
% Fields needed in sdip structure to plot on an image:
%       + n_seeds: nr of seeds set used, i.e. nr of solutions calculated
%       + n_dip: nr of fitted dipoles on the EEG time series
%       + loc: location of fitted dipoles, cell{1,n_seeds}(3 x n_dip)
%               remember that loc is fixed over the time window.
%       + j: sources amplitude over the time window,
%            cell{1,n_seeds}(3*n_dip x Ntimebins)
%       + Mtb: index of maximum power in EEG time series used

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% % First point to consider
% loc_mm = sdip.loc{i_seed(1)}(:,i_dip);
%
% % PLace the underlying image at right cuts
% spm_orthviews('Reposition',loc_mm);
% % spm_orthviews('Reposition',loc_vx);
% % spm_orthviews('Xhairs','off')
%
% % if i_seed = set, Are there other dipoles close enough ?
% tabl_seed_dip=[i_seed(1) i_dip]; % table summarising which set & dip to use.
% if length(i_seed)>1
%   unit = ones(1,sdip.n_dip);
%   for ii = i_seed(2:end)'
%         d2 = sqrt(sum((sdip.loc{ii}-loc_mm*unit).^2));
%         l_cl = find(d2<=lim_cl);
%         if ~isempty(l_cl)
%             for jj=l_cl
%                 tabl_seed_dip = [tabl_seed_dip ; [ii jj]];
%             end
%         end
%   end
% end
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% get(sdip.hdl.hseed(1),'Value')
% for ii=1:sdip.n_seeds, delete(hseed(ii)); end
% h1 = uicontrol(Fig,'Style','togglebutton','Position',[600 25 10 10].*WS)
% h2 = uicontrol(Fig,'Style','togglebutton','Position',[620 100 20 20].*WS,'String','1')
% h2 = uicontrol(Fig,'Style','checkbox','Position',[600 100 10 10].*WS)
% h3 = uicontrol(Fig,'Style','radiobutton','Position',[600 150 20 20].*WS)
% h4 = uicontrol(Fig,'Style','radiobutton','Position',[700 150 20 20].*WS)
% delete(h2),delete(h3),delete(h4),
% delete(hdip)


function transformed_slice_figure = transformed_sliceBrowser(transformed_slice_figure, save_location, f, highlight_point, relevant_slice, min_dist, ...
                                                clickX, clickY, point_ind, add)

% go through histology at the same time

transformed_images_folder = fullfile(save_location, ['transformations' filesep]);
transformed_images = dir([transformed_images_folder filesep '*.tif']);

try
    ud_transformed_slice.transformed_image_names = natsortfiles({transformed_images.name});
    browse_transformed_slices = true;
catch
    disp('no transformed images found.'); ud_transformed_slice.transformed_image_names = {};
    browse_transformed_slices = false;
end

if browse_transformed_slices

    try
        figure(transformed_slice_figure);
    catch
        transformed_slice_figure = figure('Name','Transformed Slice & Probe Point Viewer');
    end
    clf(transformed_slice_figure)

    ud_transformed_slice.current_plot_handles = [];
    ud_transformed_slice.save_location = save_location;

    ud = get(f, 'UserData');

    ud_transformed_slice.transformed_images = transformed_images;
    ud_transformed_slice.transformed_images_folder = transformed_images_folder;
    ud_transformed_slice.sliceAx = axes('Position', [0.05 0.05 0.9 0.9]);
    hold(ud_transformed_slice.sliceAx, 'on');
    set(ud_transformed_slice.sliceAx, 'HitTest', 'off');
    title('Probe on Slice Viewer');

    ud_transformed_slice.im = plotTVslice(zeros(ud.ref_size, 'uint8'));

    % for probe view mode
    if highlight_point
        ud_transformed_slice.all_slices_slice_num = relevant_slice;
        if min_dist < 10
            x_plot = ud.pointList{ud.currentProbe,1}(point_ind,1);
            y_plot = ud.ref_size(1)-ud.pointList{ud.currentProbe,1}(point_ind,2);
        else
            x_plot = clickX;
            y_plot = ud.ref_size(1) - clickY;
        end
            figure(transformed_slice_figure)
            ud_transformed_slice.quiver_plot{1} = scatter(ud_transformed_slice.sliceAx, x_plot, y_plot, 200, 'ro', ...
            'MarkerFaceColor',[1 1 1],'MarkerEdgeColor', [.3 .3 .3], ...
            'MarkerFaceAlpha',.5, 'MarkerFaceAlpha',.1);

        ud_transformed_slice.quiver_plot{2} = quiver( x_plot - 30 - 10, y_plot + 30 + 10, 30, -30, 1, 'color', 'white', 'linewidth',1,'MaxHeadSize',10);
    else
        ud_transformed_slice.all_slices_slice_num = ud.slice_at_shift_start+ud.slice_shift+add;
        ud_transformed_slice.quiver_plot = [];
    end

    processed_images = dir([ud_transformed_slice.save_location filesep '*.tif']);
    processed_image_names = natsortfiles({processed_images.name});
    ud_transformed_slice.total_num_files = length(processed_image_names);

    ud_transformed_slice.slice_num =  find(strcmp([processed_image_names{ud_transformed_slice.all_slices_slice_num}(1:end-4)  '_transformed.tif'],ud_transformed_slice.transformed_image_names));

    % show image
    if size(ud_transformed_slice.slice_num,2)
        processed_image_name = ud_transformed_slice.transformed_image_names{ud_transformed_slice.slice_num};
        current_slice_image = flip(imread([transformed_images_folder processed_image_name]),1);
        ud_transformed_slice.extra_text = ' (transformed)';
    else
        processed_image_name = processed_image_names{ud_transformed_slice.all_slices_slice_num};
        current_slice_image = flip(imread(fullfile(save_location, processed_image_name)),1);
        ud_transformed_slice.extra_text = ' (not transformed)';
    end

    set(ud_transformed_slice.im, 'CData', current_slice_image);
    title(['Probe on Slice Viewer ' num2str(ud_transformed_slice.all_slices_slice_num) '/' num2str(ud_transformed_slice.total_num_files) ud_transformed_slice.extra_text])

    set(transformed_slice_figure, 'KeyPressFcn', @(slice_figure, keydata)SliceAtlasHotkeyFcn(transformed_slice_figure, keydata, f, transformed_images_folder));
    set(transformed_slice_figure, 'UserData', ud_transformed_slice)
end

% ------------------------
% react to keyboard press
% ------------------------
function SliceAtlasHotkeyFcn(fig, keydata, f, transformed_images_folder)

ud = get(fig, 'UserData');
ud_atlas_viewer = get(f, 'UserData');

processed_images = dir([ud.save_location filesep '*.tif']);
processed_image_names = natsortfiles({processed_images.name});

transformed_images = dir([transformed_images_folder filesep '*.tif']);
try
    ud.transformed_image_names = natsortfiles({transformed_images.name});
catch
    ud.transformed_image_names = {};
end

ud.transformed_images = transformed_images;

if strcmp(keydata.Key,'leftarrow')
    if ud.all_slices_slice_num > 1
        ud.all_slices_slice_num = ud.all_slices_slice_num - 1;

        ud.slice_num =  find(strcmp([processed_image_names{ud.all_slices_slice_num}(1:end-4)  '_transformed.tif'],ud.transformed_image_names));

        % show next image
        if size(ud.slice_num,2)
            processed_image_name = ud.transformed_image_names{ud.slice_num};
            current_slice_image = flip(imread(fullfile(ud.transformed_images_folder, processed_image_name)),1);
            ud.extra_text = ' (transformed)';
        else
            processed_image_name = processed_image_names{ud.all_slices_slice_num};
            current_slice_image = flip(imread(fullfile(ud.save_location, processed_image_name)),1);
            ud.extra_text = ' (not transformed)';
        end
        % reduce to 3 channels at most
        color_channels = min( 3, size(image,3));
        current_slice_image = current_slice_image(:,:,1:color_channels);
        set(ud.im, 'CData', current_slice_image);

    end
elseif strcmp(keydata.Key,'rightarrow') % break
    if ud.all_slices_slice_num < ud.total_num_files
       ud.all_slices_slice_num = ud.all_slices_slice_num + 1;

        ud.slice_num =  find(strcmp([processed_image_names{ud.all_slices_slice_num}(1:end-4)  '_transformed.tif'],ud.transformed_image_names));

        % show next image
        if size(ud.slice_num,2)
            processed_image_name = ud.transformed_image_names{ud.slice_num};
            current_slice_image = flip(imread(fullfile(ud.transformed_images_folder, processed_image_name)),1);
            ud.extra_text = ' (transformed)';
        else
            processed_image_name = processed_image_names{ud.all_slices_slice_num};
            current_slice_image = flip(imread(fullfile(ud.save_location, processed_image_name)),1);
            ud.extra_text = ' (not transformed)';
        end
        % reduce to 3 channels at most
        color_channels = min( 3, size(image,3));
        current_slice_image = current_slice_image(:,:,1:color_channels);
        set(ud.im, 'CData', current_slice_image);
    end
else
% otherwise -- call function to atlas browser
    fcn = get(f, 'KeyPressFcn');
    fcn(f, keydata);
end
        title(['Probe on Slice Viewer -- Slice ' num2str(ud.all_slices_slice_num) '/' num2str(ud.total_num_files) ud.extra_text ])
        % plot probe points for that slice
        set(ud.current_plot_handles(:), 'Visible', 'off'); ud.current_plot_handles = [];

        for probe = 1:size(ud_atlas_viewer.pointList,1)
            for point = 1:size(ud_atlas_viewer.pointList{probe,1},1)
                if ud.all_slices_slice_num == ud_atlas_viewer.pointList{probe,2}(point)
                    ud.current_plot_handles(end+1) = scatter(ud.sliceAx, ud_atlas_viewer.pointList{probe,1}(point,1), ...
                        ud_atlas_viewer.ref_size(1)-ud_atlas_viewer.pointList{probe,1}(point,2), 20, 'ro', 'MarkerFaceColor',[ .1 .1 .1],...
                    'MarkerEdgeColor', ud_atlas_viewer.ProbeColors(probe, :), 'MarkerFaceAlpha',.4,'LineWidth',1.5);
                end
            end
        end

set(fig, 'UserData', ud);


function status = testYamlConversion
% test the functions for yaml import/export see if the conversion process
% changes the model content
%
% Usage: status = testYamlConversion
%

% Get model path
[ST, I]=dbstack('-completenames');
modelPath=fileparts(fileparts(fileparts(ST(I).file)));

% Import yaml model
ymlFile=fullfile(modelPath,'model','Human-GEM.yml');
model = importYaml(ymlFile, true);

% make sure there is no intermediate Yaml file under the current folder
warning('off', 'MATLAB:DELETE:FileNotFound')
if exist('testYamlConversion.yml','file')
    delete testYamlConversion.yml;
end

% export to yml and then import back
exportYaml(model,'testYamlConversion.yml');
importedHumanGEM = importYaml('testYamlConversion.yml', true);

% remove intermediate Yaml file
delete testYamlConversion.yml;

% compare the imported model from yaml with the original one
if isequal(model, importedHumanGEM)
    % model conversion between Matlab and Yaml files is successful
    disp('The conversion was successful.')
    status = 1;
else
    error('There are problems during the conversion between Matlab and Yaml files');
end


% The COBRAToolbox: testSimilarity.m
%
% Purpose:
%     - testSimilarity tests the functionality of similarity in the
%       rBioNet extension
%
% Authors:
%     - Stefania Magnusdottir April 2017
%

% save the current path
currentDir = pwd;

% initialize the test
fileDir = fileparts(which('testSimilarity'));
cd(fileDir);

% load rBioNet reaction database
load([fileDir, filesep 'rxn.mat'])

% find similar reactions, only checks metabolites
reactions = similarity('2pg[c] <=> h2o[c] + 2 pep[c]', rxn(:, 3), 0);

% test that similar reactions are found
assert(~isempty(reactions))

% try to find reacitons similar to made-up reaction
reactions = similarity('2pg[c] <=> ac[c] + 2 met-L[c]', rxn(:, 3), 0);

% test that similar reactions are found
assert(isempty(reactions))

% change the directory
cd(currentDir)


classdef(Abstract) AbstractLaunchVehicleElectricalPowerSrcSnk < matlab.mixin.SetGet & matlab.mixin.Heterogeneous
    %AbstractLaunchVehicleElectricalPowerSrc Summary of this class goes here
    %   Detailed explanation goes here

    properties(Abstract)
        id
    end

    properties(Dependent)
        lvdData
    end

    methods
        name = getName(obj);

        stage = getAttachedStage(obj);

        pwrRate = getElectricalPwrRate(obj, elemSet, steeringModel, hasSunLoS, body2InertDcm, elemSetSun);

        newState = createDefaultInitialState(obj, stageState)

        useTF = openEditDialog(obj);

        tf = isInUse(obj);

        newObj = copy(obj);

        summStr = getSummaryStr(obj);

        function lvdData = get.lvdData(obj)
            lvdData = obj.getAttachedStage().launchVehicle.lvdData;
        end
    end

    methods(Sealed)
        function tf = eq(a,b)
            tf = [a.id] == [b.id];
        end
    end
end


function [hFig, iDS, iFig] = view_channels(ChannelFile, Modality, isMarkers, isLabels, hFig, is3DElectrodes, selChannels)
% VIEW_CHANNELS: Display a channel file in all the associated 3DViz figure.
%
% USAGE: view_channels(ChannelFile, Modality, isMarker=1, isLabels=1, hFig=[], is3DElectrodes=0, selChannels=[])
%        view_channels(ChannelFile, Modality)
% OUTPUT:
%     - hFig : Matlab handle to the 3DViz figure that was created or updated
%     - iDS  : DataSet index in the GlobalData variable
%     - iFig : Indice of returned figure in the GlobalData(iDS).Figure array

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

global GlobalData;
% Parse inputs
if (nargin < 7) || isempty(selChannels)
    selChannels = [];
end
if (nargin < 6) || isempty(is3DElectrodes)
    is3DElectrodes = 0;
end
if (nargin < 5) || isempty(hFig)
    hFig = [];
end
if (nargin < 4) || isempty(isLabels) || isempty(isMarkers)
    isMarkers = 1;
    isLabels  = 1;
end
iDS  = [];
iFig = [];
% Get short path to this file
ChannelFile = file_short(ChannelFile);

% ===== GET/CREATE DATASET =====
if isempty(hFig)
    % Get Study that holds this ChannelFile
    sStudy = bst_get('ChannelFile', ChannelFile);
    % If this surface does not belong to any subject
    if isempty(sStudy)
        StudyFile = '';
        SubjectFile = '';
        %warning('This surface does not belong to any database subject.');
        % Check that the SurfaceFile really exist as an absolute file path
        if ~file_exist(ChannelFile)
            bst_error(['File not found : "', ChannelFile, '"'], 'Display surface');
            return
        end
    else
        StudyFile   = sStudy.FileName;
        SubjectFile = sStudy.BrainStormSubject;
        iDS = [];
        % Get GlobalData DataSet associated with channel file
        iDSChannel = bst_memory('GetDataSetChannel', ChannelFile);
        if ~isempty(iDSChannel) && ~isempty([GlobalData.DataSet(iDSChannel).Figure])
            iDS = iDSChannel;
        end
        iDSStudy   = [];
        iDSSubject = [];
        % ChannelFile not found in DataSets (or DataSet has no figure), try StudyFile
        if isempty(iDS)
            iDSStudy = bst_memory('GetDataSetStudy', StudyFile);
            if ~isempty(iDSStudy) && ~isempty([GlobalData.DataSet(iDSStudy).Figure])
                iDS = iDSStudy;
            end
        end
        % StudyFile not found in DataSets, try SubjectFile
        if isempty(iDS)
            iDSSubject = bst_memory('GetDataSetSubject', SubjectFile, 0);
            % Do not accept DataSet if an other ChannelFile is already attributed to the DataSet
            iDSSubject = iDSSubject(cellfun(@(c)isempty(c), {GlobalData.DataSet(iDSSubject).ChannelFile}));
            % Check if Datasets are acceptable
            if ~isempty(iDSSubject) && ~isempty([GlobalData.DataSet(iDSSubject).Figure])
                iDS = iDSSubject(1);
            end
        end
        % If no dataset with figure was selected, get the first dataset without figures
        if isempty(iDS)
            iDS = [iDSChannel iDSStudy iDSSubject];
            if ~isempty(iDS)
                iDS = iDS(1);
            end
        end
    end
    % If no existing dataset is found : create a new one
    if isempty(iDS)
       iDS = bst_memory('GetDataSetEmpty');
    end
    iDS = iDS(1);
    GlobalData.DataSet(iDS).SubjectFile = SubjectFile;
    GlobalData.DataSet(iDS).StudyFile   = StudyFile;

% ===== RE-USE EXISTING FIGURE =====
else
    % Get figure definition
    [hFig, iFig, iDS] = bst_figures('GetFigure', hFig);
end

% ===== LOAD CHANNEL FILE IF NOT DONE =====
% Also check if we are processing the same channel file, which can be
% different when doing real-time head position alignment (2 helmets from
% different datasets in the same figure).
if isempty(GlobalData.DataSet(iDS).ChannelFile) || ~strcmpi(GlobalData.DataSet(iDS).ChannelFile, ChannelFile) || ...
   (~GlobalData.DataSet(iDS).isChannelModified && isempty(GlobalData.DataSet(iDS).Channel))
    % Check if this channel file is already loaded and modified in another DataSet
    iDSother = setdiff(1:length(GlobalData.DataSet), iDS);
    if ~isempty(iDSother) && any([GlobalData.DataSet(iDSother).isChannelModified])
        % Ask user
        isSave = java_dialog('confirm', ...
            ['This channel file is being edited in another window.' 10 ...
             'Save the modifications so the new figure can show updated positions?'], 'Save modifications');
        % Force saving of the modifications
        if isSave
            bst_memory('SaveChannelFile', iDSother(1));
        end
    end
    % Load channel file
    ChannelMat = in_bst_channel(ChannelFile);
    % Copy information in memory
    GlobalData.DataSet(iDS).ChannelFile     = ChannelFile;
    GlobalData.DataSet(iDS).Channel         = ChannelMat.Channel;
    GlobalData.DataSet(iDS).MegRefCoef      = ChannelMat.MegRefCoef;
    GlobalData.DataSet(iDS).Projector       = ChannelMat.Projector;
    GlobalData.DataSet(iDS).Clusters        = ChannelMat.Clusters;
    GlobalData.DataSet(iDS).IntraElectrodes = ChannelMat.IntraElectrodes;
    GlobalData.DataSet(iDS).HeadPoints      = ChannelMat.HeadPoints;
end

% ===== CREATE 3DVIZ FIGURE =====
% Progress bar
isProgress = ~bst_progress('isVisible');
if isProgress
    bst_progress('start', 'View sensors', 'Loading data...');
end
if isempty(hFig)
    % Prepare FigureId structure
    FigureId = db_template('FigureId');
    FigureId.Type     = '3DViz';
    FigureId.SubType  = '';
    FigureId.Modality = Modality;
    % Create figure
    [hFig, iFig, isNewFig] = bst_figures('CreateFigure', iDS, FigureId);
    % If figure was not created: Display an error message and return
    if isempty(hFig)
        bst_error('Cannot create figure', '3D figure creation...', 0);
        return;
    end
    setappdata(hFig, 'StudyFile',    StudyFile);
    setappdata(hFig, 'SubjectFile',  SubjectFile);
else
    isNewFig = 0;
    % Get existing list of selected channels
    if ~isempty(GlobalData.DataSet(iDS).Figure(iFig).SelectedChannels)
        selChannels = GlobalData.DataSet(iDS).Figure(iFig).SelectedChannels;
    end
end
% Make sure that the Modality is saved
GlobalData.DataSet(iDS).Figure(iFig).Id.Modality = Modality;
% Set application data
setappdata(hFig, 'DataFile', '');
setappdata(hFig, 'isSensorsOnly', 1);

% ===== DISPLAY SENSORS =====
% Update figure selection
bst_figures('SetCurrentFigure', hFig, '3D');
% Get default selected channels for this modality
if isempty(selChannels)
    % Get selected channels
    selChannels = good_channel(GlobalData.DataSet(iDS).Channel, [], Modality);
    % Remove the channels with empty positions
    iNoLoc = find(cellfun(@isempty, {GlobalData.DataSet(iDS).Channel.Loc}));
    if ~isempty(iNoLoc)
        selChannels = setdiff(selChannels, iNoLoc);
    end
    if isempty(selChannels) && ~isempty(iNoLoc)
        error('None of the channels have positions defined.');
    end
end
% Set figure selected sensors
GlobalData.DataSet(iDS).Figure(iFig).SelectedChannels = selChannels;
% Display sensors
if is3DElectrodes
    figure_3d('PlotSensors3D', iDS, iFig);
    if isLabels
        figure_3d('ViewSensors', hFig, 1, 1, 0, Modality);
    end
    % Open iEEG tab
    if ismember(Modality, {'SEEG', 'ECOG', 'ECOG+SEEG'})
        gui_brainstorm('ShowToolTab', 'iEEG');
    end
elseif ismember(lower(Modality), {'ctf', 'vectorview306', '4d', 'kit', 'kriss', 'babymeg', 'ricoh'})
    figure_3d('PlotCoils', hFig, Modality, isMarkers);
elseif ismember(lower(Modality), {'nirs','nirs-brs'})
    figure_3d('PlotNirsCap', hFig, isMarkers);
else
    isMesh = ~isequal(Modality, 'SEEG');
    figure_3d('ViewSensors', hFig, isMarkers, isLabels, isMesh, Modality);
end
% Open Cluster tab
if ~isempty(GlobalData.DataSet(iDS).Clusters)
    gui_brainstorm('ShowToolTab', 'Cluster');
end
% Update lights
camlight(findobj(hFig, 'Tag', 'FrontLight'), 'headlight');
% Update figure name
bst_figures('UpdateFigureName', hFig);
% Camera basic orientation
if isNewFig
    figure_3d('SetStandardView', hFig, 'top');
end
% Show figure
set(hFig, 'Visible', 'on');
% Close progress bar
if isProgress
    bst_progress('stop');
end


function data_list = read_off_list(data_path, classes, train_or_test, debug)
% read raw off filenames

% data_path: off data folder
% classes: a cell array of class names
% train_or_test: select training data or testing data('train', 'test')
% debug: true for debug.

if nargin < 4 ; debug = 0; end

if debug
    maxNum = 20;
else
    maxNum = 10000;
end

num_classes = length(classes);
data_list = cell(num_classes,1);
for c = 1 : num_classes
    fprintf('reading the %s category\n', classes{c});
    category_path = [data_path '/' classes{c}  '/off/' train_or_test];
    files = dir(category_path);

    cat_ind = 0;
    data_list{c} = [];
    for i = 1 : min(length(files), maxNum)
        if strcmp(files(i).name, '.') || strcmp(files(i).name, '..') || files(i).isdir == 1 || ~strcmp(files(i).name(end-2:end), 'off')
            continue;
        end
        filename = [category_path '/' files(i).name];

        cat_ind = cat_ind + 1;
        data_list{c}(cat_ind,1).filename = filename;
        data_list{c}(cat_ind,1).label = c;

        if cat_ind == maxNum; break; end
    end
end


function bool= str_matchesHead(head, str)
%STR_MATCHESHEAD - Is one string the head of another string?
%
%Synopsis:
% TF= str_matchesHead(HEAD, STR)
%
%Arguments:
%  HEAD:  CHAR - Short string
%  STR :  CHAR - String that is presumably shorter
%
%Description:
%  This function decides whether the string HEAD is the head, i.e.,
%  the first part of the second string STR.
%
%Returns:
%  TF : BOOL - Truth value of HEAD being the head of STR

% 06-2012 Some Genius

bool= strncmp(head, str, length(head));


% ir_mex_build
%
% Some of the functions in this toolbox use calls to mex files.
% The source code for *some*, but not all, of those mex files
% is included with the toolbox, and this script generates the corresponding mex files.

% The full MIRT toolbox with complete mex files can be found at:
% http://web.eecs.umich.edu/~fessler/code/index.html

% This script and the scripts it calls have been tested
% for compiling on Mac, PC, and Linux.

ir_mex_build_mri
ir_mex_build_table

% todo: ir_mex_build_penal


function res = badchannels(this, varargin)
% Method for getting/setting bad channels
% FORMAT res = badchannels(this)
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Stefan Kiebel
% $Id: badchannels.m 4329 2011-05-19 20:54:36Z christophe $

if length(varargin) == 2 && ~isempty(varargin{1})
    % make sure that the two inputs for set are the same length
    if ~(length(varargin{2}) == 1 | (length(varargin{1}) == length(varargin{2})))
        error('Use either same vector length or scalar for value');
    end
end

if numel(varargin) >= 1  && ~isempty(varargin{1})
    if ~(all(varargin{1} >= 1) && all(varargin{1} <= nchannels(this)))
        error('Channel number out of range.');
    end
end

if numel(varargin) >= 2
    ubad = unique(varargin{2});
    if isempty(ubad) | ~all(ismember(ubad, [0 1]))
        error('Illegal bad flags (should be 0 or 1)');
    end
end

res = getset(this, 'channels', 'bad', varargin{:});

if isempty(varargin)
    if iscell(res)
        res = [res{:}];
    end

    res = find(res);
end


%gohome   positions the command prompt at top level directory
%   IFISS scriptfile: DJS; 24 May 2006.
% Copyright (c) 2005 D.J. Silvester, H.C. Elman, A. Ramage (see readme.m)
%
cd ( '/panfs/panasas1/users/jburkardt/public_html/m_src/ifiss3.3' );


function hsvargplvmClassVisualise(call)

% LVMCLASSVISUALISE Callback function for visualising data.
% FORMAT
% DESC contains the callback functions for visualizing points from the
% latent space in the higher dimension space.
% ARG call : either 'click', 'move', 'toggleDynamics',
% 'dynamicsSliderChange'
%
% COPYRIGHT : Neil D. Lawrence, 2003, 2009
%
% SEEALSO : lvmResultsDynamic

% MLTOOLS

global visualiseInfo

% In which output modality do we predict? If there is only one modality,
% this should be set to either "-1" or 1:model.layer{1}.M
visIndex = visualiseInfo.model.vis.index;
% From which input layer do we predict all the way until the leaves?
visLayer = visualiseInfo.model.vis.layer;

switch call
 case 'click'
  [x, y]  = localCheckPointPosition(visualiseInfo);
  if ~isempty(x)
    visualiseInfo.latentPos(visualiseInfo.dim1) = x;
    visualiseInfo.latentPos(visualiseInfo.dim2) = y;
  end
  visualiseInfo.clicked = ~visualiseInfo.clicked;
  if isfield(visualiseInfo.model, 'dynamics') & ~isempty(visualiseInfo.model.dynamics)
    if visualiseInfo.runDynamics
      visualiseInfo.dynamicsRunning = 1;
      fhandle = str2func([visualiseInfo.model.type 'DynamicsRun']);
      feval(fhandle);
      visualiseInfo.dynamicsRunning = 0;
    end
  else
    visualiseInfo.dynamicsRunning = 0;
  end
 case 'move'
  if visualiseInfo.clicked & ~visualiseInfo.runDynamics
    [x, y]  = localCheckPointPosition(visualiseInfo);
    if ~isempty(x)
      % This should be changed to a model specific visualisation.
      visualiseInfo.latentPos(visualiseInfo.dim1) = x;
      visualiseInfo.latentPos(visualiseInfo.dim2) = y;
      set(visualiseInfo.latentHandle, 'xdata', x, 'ydata', y);
      fhandle = str2func([visualiseInfo.model.type 'PosteriorMeanVar']);
      % In contrast to the other posteriorMeanVar functions, this one
      % has outputs that act as inputs in the next layer. In the current implementation, only
      % one output can be visualised. This has to be instructed in a
      % special field "vis" of the complete model.
      visIndex = visualiseInfo.model.vis.index;
      visLayer = visualiseInfo.model.vis.layer;
      if visualiseInfo.showVariance
        [mu, varsigma] = fhandle(visualiseInfo.model, visualiseInfo.latentPos, [], visLayer, 1, visIndex);
      else
          mu = fhandle(visualiseInfo.model, visualiseInfo.latentPos, [], visLayer, 1, visIndex);
          varsigma = zeros(size(mu));
      end
      if isfield(visualiseInfo.model, 'noise')
        Y = noiseOut(visualiseInfo.model.noise, mu, varsigma);
      else
        Y = mu;
      end
       % Some skeletons need to have their data remapped
      if isfield(visualiseInfo.model, 'Ytochannels') && visualiseInfo.model.Ytochannels
        Y = Ytochannels(Y);
      end
      visualiseInfo.visualiseModify(visualiseInfo.visHandle, ...
                                    Y, visualiseInfo.varargin{:});
    end
  end
 case 'toggleDynamics'
  visualiseInfo.runDynamics = ~visualiseInfo.runDynamics;
  set(visualiseInfo.dynamicsRadio, 'value', visualiseInfo.runDynamics);

 case 'dynamicsSliderChange'
  X = modelOut(visualiseInfo.model.dynamics, get(visualiseInfo.dynamicsSlider, 'value'));
  x = X(1);
  y = X(2);
  visualiseInfo.latentPos(visualiseInfo.dim1) = x;
  visualiseInfo.latentPos(visualiseInfo.dim2) = y;
  set(visualiseInfo.latentHandle, 'xdata', x, 'ydata', y);
  fhandle = str2func([visualiseInfo.model.type 'PosteriorMeanVar']);
  [mu, varsigma] = fhandle(visualiseInfo.model, visualiseInfo.latentPos, [], visLayer, 1, visIndex);
  if isfield(visualiseInfo.model, 'noise')
    Y = noiseOut(visualiseInfo.model.noise, mu, varsigma);
  else
    Y = mu;
  end
  % Some skeletons need to have their data remapped
  if isfield(visualiseInfo.model, 'Ytochannels') && visualiseInfo.model.Ytochannels
      Y = Ytochannels(Y);
  end
  visualiseInfo.visualiseModify(visualiseInfo.visHandle, ...
                                Y, visualiseInfo.varargin{:});

 case 'latentSliderChange'
  counter = 0;
  for i = size(visualiseInfo.latentPos, 2):-1:1
    % Go through setting latent positions to slider positions.
    if i ~= visualiseInfo.dim1 && i ~= visualiseInfo.dim2
      counter = counter + 1;
      visualiseInfo.latentPos(i) = get(visualiseInfo.latentSlider(counter), 'value');
      set(visualiseInfo.sliderTextVal(counter), 'string', num2str(visualiseInfo.latentPos(i)));
    end
  end
  if visualiseInfo.showVariance
    lvmSetPlot;
  else
      lvmSetPlotNoVar('hsvargplvmClassVisualise');
  end
  fhandle = str2func([visualiseInfo.model.type 'PosteriorMeanVar']);
  if visualiseInfo.showVariance
    [mu, varsigma] = fhandle(visualiseInfo.model, visualiseInfo.latentPos, [], visLayer, 1, visIndex);
  else
      mu = fhandle(visualiseInfo.model, visualiseInfo.latentPos, [], visLayer, 1, visIndex);
      varsigma = zeros(size(mu));
  end
  if isfield(visualiseInfo.model, 'noise')
    Y = noiseOut(visualiseInfo.model.noise, mu, varsigma);
  else
    Y = mu;
  end
  % Some skeletons need to have their data remapped
  if isfield(visualiseInfo.model, 'Ytochannels') && visualiseInfo.model.Ytochannels
      Y = Ytochannels(Y);
  end
  visualiseInfo.visualiseModify(visualiseInfo.visHandle, ...
                                    Y, visualiseInfo.varargin{:});

  visualiseInfo.latentHandle = line(visualiseInfo.latentPos(visualiseInfo.dim1), ...
                                    visualiseInfo.latentPos(visualiseInfo.dim2), ...
                                    'markersize', 20, 'color', [0.5 0.5 0.5], ...
                                    'marker', '.', 'visible', 'on', ...
                                    'erasemode', 'xor');

 case 'updateLatentRepresentation'
  visualiseInfo.dim1 = get(visualiseInfo.xDimension, 'value');
  visualiseInfo.dim2 = get(visualiseInfo.yDimension, 'value');
  if visualiseInfo.showVariance
    lvmSetPlot;
  else
     lvmSetPlotNoVar('hsvargplvmClassVisualise');
  end

  visualiseInfo.latentHandle = line(visualiseInfo.latentPos(visualiseInfo.dim1), ...
                                    visualiseInfo.latentPos(visualiseInfo.dim2), ...
                                    'markersize', 20, 'color', [0.5 0.5 0.5], ...
                                    'marker', '.', 'visible', 'on', ...
                                    'erasemode', 'xor');

end

function point = localGetNormCursorPoint(figHandle)

point = get(figHandle, 'currentPoint');
figPos = get(figHandle, 'Position');
% Normalise the point of the curstor
point(1) = point(1)/figPos(3);
point(2) = point(2)/figPos(4);

function [x, y] = localGetNormAxesPoint(point, axesHandle)

position = get(axesHandle, 'Position');
x = (point(1) - position(1))/position(3);
y = (point(2) - position(2))/position(4);
lim = get(axesHandle, 'XLim');
x = x*(lim(2) - lim(1));
x = x + lim(1);
lim = get(axesHandle, 'YLim');
y = y*(lim(2) - lim(1));
y = y + lim(1);

function [x, y] = localCheckPointPosition(visualiseInfo)

% Get the point of the cursor
point = localGetNormCursorPoint(gcf);

% get the position of the axes
position = get(visualiseInfo.plotAxes, 'Position');

% Check if the pointer is in the axes
if point(1) > position(1) ...
      & point(1) < position(1) + position(3) ...
      & point(2) > position(2) ...
      & point(2) < position(2) + position(4);

  % Rescale the point according to the axes
  [x y] = localGetNormAxesPoint(point, visualiseInfo.plotAxes);

  % Find the nearest point
else
  % Return nothing
  x = [];
  y = [];
end


function msfun_odometry(block)

% Copyright (C) 2013, Georgia Tech Research Corporation
% see the LICENSE file included with this software

%%
%% The setup method is used to set up the basic attributes of the
%% S-function such as ports, parameters, etc. Do not add any other
%% calls to the main body of the function.
%%
myPrevTicks = struct('right', 0, 'left', 0);

setup(block);

%endfunction

%% Function: setup ===================================================
%% Abstract:
%%   Set up the basic characteristics of the S-function block such as:
%%   - Input ports
%%   - Output ports
%%   - Dialog parameters
%%   - Options
%%
%%   Required         : Yes
%%   C-Mex counterpart: mdlInitializeSizes
%%
    function setup(block)

        % Register number of ports
        block.NumInputPorts  = 4;
        block.NumOutputPorts = 3;

        % Setup port properties to be inherited or dynamic
        % block.SetPreCompInpPortInfoToDynamic;
        % block.SetPreCompOutPortInfoToDynamic;
        block.SetPreCompPortInfoToDefaults;

        % Override input port properties
        for i=1:3
            block.InputPort(i).Dimensions        = 1;
            block.InputPort(i).DatatypeID  = 0;  % double
            block.InputPort(i).Complexity  = 'Real';
            block.InputPort(i).DirectFeedthrough = true;
        end

        block.InputPort(4).Dimensions        = 2;
        block.InputPort(4).DatatypeID  = 0;  % double
        block.InputPort(4).Complexity  = 'Real';
        block.InputPort(4).DirectFeedthrough = true;

        block.InputPort(1).SamplingMode = 0;
        block.InputPort(2).SamplingMode = 0;
        block.InputPort(3).SamplingMode = 0;
        block.InputPort(4).SamplingMode = 0;

        % Override output port properties
        block.OutputPort(1).Dimensions       = 1;
        block.OutputPort(1).DatatypeID  = 0; % double
        block.OutputPort(1).Complexity  = 'Real';

        block.OutputPort(2).Dimensions       = 1;
        block.OutputPort(2).DatatypeID  = 0; % double
        block.OutputPort(2).Complexity  = 'Real';

        block.OutputPort(2).Dimensions       = 1;
        block.OutputPort(2).DatatypeID  = 0; % double
        block.OutputPort(2).Complexity  = 'Real';

        % Set up the states
        block.NumContStates = 0;
        block.NumDworks = 0;

        % Register parameters
        block.NumDialogPrms     = 3;
        block.DialogPrmsTunable = {'NonTunable', 'NonTunable', 'NonTunable'};

        % Register sample times
        %  [0 offset]            : Continuous sample time
        %  [positive_num offset] : Discrete sample time
        %
        %  [-1, 0]               : Inherited sample time
        %  [-2, 0]               : Variable sample time
        block.SampleTimes = [0.033 0];

        % Specify the block simStateCompliance. The allowed values are:
        %    'UnknownSimState', < The default setting; warn and assume DefaultSimState
        %    'DefaultSimState', < Same sim state as a built-in block
        %    'HasNoSimState',   < No sim state
        %    'CustomSimState',  < Has GetSimState and SetSimState methods
        %    'DisallowSimState' < Error out when saving or restoring the model sim state
        block.SetAccelRunOnTLC(false); % run block in interpreted mode even w/ Acceleration
        block.SimStateCompliance = 'DefaultSimState';

        %% -----------------------------------------------------------------
        %% The MATLAB S-function uses an internal registry for all
        %% block methods. You should register all relevant methods
        %% (optional and required) as illustrated below. You may choose
        %% any suitable name for the methods and implement these methods
        %% as local functions within the same file. See comments
        %% provided for each function for more information.
        %% -----------------------------------------------------------------

        block.RegBlockMethod('PostPropagationSetup',    @DoPostPropSetup);
        block.RegBlockMethod('InitializeConditions', @InitializeConditions);
        block.RegBlockMethod('Start', @Start);
        block.RegBlockMethod('Outputs', @Outputs);     % Required
        block.RegBlockMethod('Update', @Update);
        block.RegBlockMethod('Terminate', @Terminate); % Required

    end %setup

%%
%% PostPropagationSetup:
%%   Functionality    : Setup work areas and state variables. Can
%%                      also register run-time methods here
%%   Required         : No
%%   C-Mex counterpart: mdlSetWorkWidths
%%
    function DoPostPropSetup(block)

    end

%%
%% InitializeConditions:
%%   Functionality    : Called at the start of simulation and if it is
%%                      present in an enabled subsystem configured to reset
%%                      states, it will be called when the enabled subsystem
%%                      restarts execution to reset the states.
%%   Required         : No
%%   C-MEX counterpart: mdlInitializeConditions
%%
    function InitializeConditions(block)

        myPrevTicks = struct('right', 0, 'left', 0);

    end

%%
%% Start:
%%   Functionality    : Called once at start of model execution. If you
%%                      have states that should be initialized once, this
%%                      is the place to do it.
%%   Required         : No
%%   C-MEX counterpart: mdlStart
%%
    function Start(block)

    end %endfunction

%%
%% Outputs:
%%   Functionality    : Called to generate block outputs in
%%                      simulation step
%%   Required         : Yes
%%   C-MEX counterpart: mdlOutputs
%%
    function Outputs(block)

        % Get wheel encoder ticks from the robot
        right_ticks = block.InputPort(4).Data(1);
        left_ticks = block.InputPort(4).Data(2);

        % Recal the previous wheel encoder ticks
        prev_right_ticks = myPrevTicks.right;
        prev_left_ticks = myPrevTicks.left;

        % Previous estimate
        x = block.InputPort(1).Data;
        y = block.InputPort(2).Data;
        theta = block.InputPort(3).Data;

        % Compute odometry here
        R = block.DialogPrm(1).Data;
        L = block.DialogPrm(2).Data;
        ticks_per_rev = block.DialogPrm(3).Data;
        m_per_tick = (2*pi*R)/ticks_per_rev;

        d_right = (right_ticks-prev_right_ticks)*m_per_tick;
        d_left = (left_ticks-prev_left_ticks)*m_per_tick;
        d_center = (d_right + d_left)/2;

        x_dt = d_center*cos(theta);
        y_dt = d_center*sin(theta);
        theta_dt = (d_right - d_left)/L;

        theta_new = theta + theta_dt;
        x_new = x + x_dt;
        y_new = y + y_dt;
        %             fprintf('Estimated pose (x,y,theta): (%0.3g,%0.3g,%0.3g)\n', x_new, y_new, theta_new);

        % Save the wheel encoder ticks for the next estimate
        myPrevTicks.right = right_ticks;
        myPrevTicks.left = left_ticks;

        % Update your estimate of (x,y,theta)
        block.OutputPort(1).Data = x_new;
        block.OutputPort(2).Data = y_new;
        block.OutputPort(3).Data = theta_new;

    end %end Outputs

%%
%% Update:
%%   Functionality    : Called to update discrete states
%%                      during simulation step
%%   Required         : No
%%   C-MEX counterpart: mdlUpdate
%%
    function Update(block)

    end %end Update

%%
%% Terminate:
%%   Functionality    : Called at the end of simulation for cleanup
%%   Required         : Yes
%%   C-MEX counterpart: mdlTerminate
%%
    function Terminate(block)

    end %end Terminate

end


function err = hdf5write_safe(fname, name, val, options)

    err = -1;
    if isempty(val)
        return;
    end
    if ~exist('options','var')
        options = '';
    end

    force_scalar = false;
    force_array = false;
    if any(strcmp(options, 'array'))
       force_array = true;
    elseif any(strcmp(options, 'scalar'))
        force_scalar = true;
    end
    % Identify type of val and use SNIRF v1.1-compliant write function

    if exist(fname,'file')
        fid = H5F.open(fname, 'H5F_ACC_RDWR', 'H5P_DEFAULT');
    else
        fid = H5F.create(fname, 'H5F_ACC_TRUNC', 'H5P_DEFAULT', 'H5P_DEFAULT');
    end
    if fid < 0
        err = -1;
        return;
    end

    % Create group where dataset is located
    group = filesepStandard(fileparts(name), 'nameonly');
    gid = HDF5_CreateGroup(fid, group);
    if gid < 0
        err = -1;
        return;
    end

    if iscell(val) || isstring(val)
        if length(val) > 1 && ~force_scalar || force_array  % Returns true for single strings, believe it or not
            write_string_array(fid, fname, name, val);
        else
            write_string(fid, fname, name, val);
        end
        return
    elseif ischar(val)
        write_string(fid, fname, name, val);
        return
    elseif isfloat(val)
        if length(val) > 1 && ~force_scalar || force_array
            write_numeric_array(fname, name, val);
        else
            write_numeric(fid, fname, name, val);
        end
        return
    elseif isinteger(val)
        if length(val) > 1 && ~force_scalar || force_array
            write_numeric_array(fid, fname, name, val);  % As of now, no integer arrays exist
        else
            write_integer(fid, fname, name, val);
        end
        return
    else
        warning(['An unrecognized variable was saved to ', name, ' in ', fname])
    end

    H5F.close(fid);

end

function err = write_string(fid, fname, name, val)
    sid = H5S.create('H5S_SCALAR');
    tid = H5T.copy('H5T_C_S1');
    H5T.set_size(tid, 'H5T_VARIABLE');
    did = H5D.create(fid, name, tid, sid, 'H5P_DEFAULT');
    H5D.write(did, tid, 'H5S_ALL', 'H5S_ALL', 'H5P_DEFAULT', {val});
    err = 0;
end

function err = write_string_array(fid, fname, name, val)
    val = HDF5_Transpose(val);
    sid = H5S.create_simple(1, numel(val), H5ML.get_constant_value('H5S_UNLIMITED'));
    tid = H5T.copy('H5T_C_S1');
    H5T.set_size(tid, 'H5T_VARIABLE');
    pid = H5P.create('H5P_DATASET_CREATE');
    H5P.set_chunk(pid, 2);
    did = H5D.create(fid, name, tid, sid, pid);
    H5D.write(did, tid, 'H5S_ALL', 'H5S_ALL', 'H5P_DEFAULT', val);
    err = 0;
end

function err = write_numeric(fid, fname, name, val)
    fid = H5F.open(fname, 'H5F_ACC_RDWR', 'H5P_DEFAULT');
    tid = H5T.copy('H5T_NATIVE_DOUBLE');
    sid = H5S.create('H5S_SCALAR');
    H5D.create(fid, name, tid, sid, 'H5P_DEFAULT');
    h5write(fname, name, val);
    err = 0;
end

function err = write_numeric_array(fname, name, val)
    val = HDF5_Transpose(val);
    sizeval = size(val);
    if sizeval(1) == 1 || sizeval(2) == 1
        n = length(val);
    else
        n = sizeval;
    end
    h5create(fname, name, n, 'Datatype', 'double');
    h5write(fname, name, val);
    err = 0;
end

function err = write_integer(fid, fname, name, val)
    warning off;  % Suppress the int truncation warning
    tid = H5T.copy('H5T_NATIVE_INT');
    sid = H5S.create('H5S_SCALAR');
    H5D.create(fid, name, tid, sid, 'H5P_DEFAULT');
    h5write(fname, name, val);
    err = 0;
    warning on;
end


function jv = toJava(v,collection)
%toJava       Convert to Java representation.
% toJava(v) returns a Java object representing the matlab value v.
% toJava(v,1) requires the result to be a collection, not a simple object
% such as java.lang.Double.
%
% Conversions:
% scalar           -> java.lang.Double
% numeric array    -> javaArray of Double
% character array  -> java.lang.String or array of same
% empty array      -> java.util.Vector
% cell array       -> javaArray of Objects
% empty cell array -> java.util.BitSet
% structure        -> java.util.HashTable
% class            -> struct with '_class' property
%
% See also fromJava.

% Written by Tom Minka
% (c) Microsoft Corporation. All rights reserved.

if nargin < 2
  collection = 0;
end
% in case v already is a Java object
jv = v;
if isnumeric(v)
  if isempty(v)
    jv = java.util.Vector;
  elseif length(v) == 1
    if collection
      jv = javaArray('java.lang.Double',1);
      jv(1) = java.lang.Double(v);
    else
      jv = java.lang.Double(v);
    end
  else
    sz = size(v);
    jv = javaArray('java.lang.Double',sz);
    v = v(:);
    for i = 1:prod(sz)
      index = substruct('()',num2cell(ind2subv(sz,i)));
      subsasgn(jv,index,toJava(v(i)));
    end
  end
  return
end
if ischar(v)
  n = rows(v);
  if n == 1 & ~collection
    jv = java.lang.String(v);
  else
    jv = javaArray('java.lang.String',n);
    for i = 1:n
      jv(i) = java.lang.String(deblank(v(i,:)));
    end
  end
end
if iscell(v)
  if isempty(v)
    jv = java.util.BitSet;
  else
    sz = size(v);
    jv = javaArray('java.lang.Object',sz);
    v = v(:);
    for i = 1:prod(sz)
      index = substruct('()',num2cell(ind2subv(sz,i)));
      subsasgn(jv,index,toJava(v{i}));
    end
  end
  return
end
if isobject(v) | isstruct(v)
  jv = java.util.Hashtable;
  if isobject(v)
    jv.put('_class',class(v));
    v = struct(v);
  end
  % record the order of the fieldnames
  fields = java.util.Vector;
  for f = fieldnames(v)'
    fields.addElement(char(f));
    jv.put(char(f),toJava(getfield(v,char(f))));
  end
  jv.put('_fields',fields);
  return
end


%gohome   positions the command prompt at top level directory
%   IFISS scriptfile: DJS; 24 May 2006.
% Copyright (c) 2005 D.J. Silvester, H.C. Elman, A. Ramage (see readme.m)
%
cd ( '/panfs/panasas1/users/jburkardt/public_html/m_src/toms866' );


function net = vl_simplenn_move(net, destination)
%VL_SIMPLENN_MOVE  Move a SimpleNN network between CPU and GPU.
%   NET = VL_SIMPLENN_MOVE(NET, 'gpu') moves the network to the
%   current GPU device. NET = VL_SIMPLENN_MOVE(NET, 'cpu') moves the
%   network to the CPU.
%
%   See also: VL_SIMPLENN().

% Copyright (C) 2014-15 Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

switch destination
  case 'gpu', moveop = @(x) gpuArray(x) ;
  case 'cpu', moveop = @(x) gather(x) ;
  otherwise, error('Unknown destination ''%s''.', destination) ;
end
for l=1:numel(net.layers)
  switch net.layers{l}.type
    case {'conv', 'convt', 'bnorm'}
      for f = {'filters', 'biases', 'filtersMomentum', 'biasesMomentum'}
        f = char(f) ;
        if isfield(net.layers{l}, f)
          net.layers{l}.(f) = moveop(net.layers{l}.(f)) ;
        end
      end
      for f = {'weights', 'momentum'}
        f = char(f) ;
        if isfield(net.layers{l}, f)
          for j=1:numel(net.layers{l}.(f))
            net.layers{l}.(f){j} = moveop(net.layers{l}.(f){j}) ;
          end
        end
      end
    otherwise
      % nothing to do ?
  end
end


classdef (Abstract) MimModelCollection  < MimModel

    methods
        function addItem(obj, itemId)
            [currentCollection, ~] = obj.getOrRun();
            if ~ismember(itemId, currentCollection)
                currentCollection{end + 1} = itemId;
                obj.setValue(currentCollection);
            end
        end

        function removeItem(obj, itemId)
            [currentCollection, ~] = obj.getOrRun();
            if ismember(itemId, currentCollection)
                currentCollection = setdiff(currentCollection, itemId);
                obj.setValue(currentCollection);
            end
        end
    end
end


classdef MimTimer < CoreBaseClass
    % MimTimer. Part of the internal framework of the TD MIM Toolkit.
    %
    %     You should not use this class within your own code. It is intended to
    %     be used internally within the framework of the TD MIM Toolkit.
    %
    %     MimTimer is used to time plugin execution
    %
    %     Licence
    %     -------
    %     Part of the TD MIM Toolkit. https://github.com/tomdoel
    %     Author: Tom Doel, Copyright Tom Doel 2014.  www.tomdoel.com
    %     Distributed under the MIT licence. Please see website for details.
    %

    properties (Access = private)
        StartTicId       % ID from the tic function called at Start()
        PauseTicId       % ID from the tic function called at Resume()
        Reporting        % error/progress reporting
    end

    properties (SetAccess = private)
        SelfTime         % After Stop() is called, contains elapsed time in seconds, excluding when the timer was paused
        TotalElapsedTime % After Stop() is called, contains elapsed time in seconds, ignoring any Pause() calls
    end

    methods
        function obj = MimTimer(reporting)
            obj.Reporting = reporting;
        end

        function Start(obj)
            if ~isempty(obj.StartTicId)
                reporting.Error('MimTimer:TimerAlreadyStarted', 'The Start() method was called but the clock has already been started.');
            end
            obj.StartTicId = tic;
            obj.PauseTicId = obj.StartTicId;
        end

        function Stop(obj)
            if isempty(obj.StartTicId)
                reporting.Error('MimTimer:TimerNotStarted', 'The Stop() method was called but the clock has not been started.');
            end
            if ~isempty(obj.TotalElapsedTime)
                reporting.Error('MimTimer:ClockAlreadyStopped', 'The Stop() method was called but the clock has already been stopped.');
            end
            obj.TotalElapsedTime = toc(obj.StartTicId);
            elapsed_time_since_resume = toc(obj.PauseTicId);
            if isempty(obj.SelfTime)
                obj.SelfTime = elapsed_time_since_resume;
            else
                obj.SelfTime = obj.SelfTime + elapsed_time_since_resume;
            end
        end

        function Pause(obj)
            if isempty(obj.StartTicId)
                reporting.Error('MimTimer:TimerNotStarted', 'The Pause() method was called but the clock has not been started.');
            end
            if isempty(obj.PauseTicId)
                reporting.Error('MimTimer:TimerNotStarted', 'The Pause() method was called but the clock is already paused.');
            end
            if ~isempty(obj.TotalElapsedTime)
                reporting.Error('MimTimer:ClockAlreadyStopped', 'The Pause() method was called but the clock has already been stopped.');
            end
            elapsed_time_since_resume = toc(obj.PauseTicId);
            if isempty(obj.SelfTime)
                obj.SelfTime = elapsed_time_since_resume;
            else
                obj.SelfTime = obj.SelfTime + elapsed_time_since_resume;
            end
            obj.PauseTicId = [];
        end

        function Resume(obj)
            if isempty(obj.StartTicId)
                obj.Reporting.Error('MimTimer:TimerNotStarted', 'The Resume() method was called but the clock has not been started.');
            end
            if ~isempty(obj.TotalElapsedTime)
                obj.Reporting.Error('MimTimer:ClockAlreadyStopped', 'The Resume() method was called but the clock has already been stopped.');
            end
            if ~isempty(obj.PauseTicId)
                obj.Reporting.Error('MimTimer:NotPaused', 'The Resume() method was called but the clock has not been paused.');
            end
            obj.PauseTicId = tic;
        end
    end
end


%% SAUSAGEPLOT
function sausageplot(obj, numBinsToUse, varargin)
    %sausageplot
    %    Under development, this function attempts to replicate the
    %    capabilities of sausageplot.xpy written by Glenn Thompson
    %    at AVO.
    p = inputParser;
    p.addRequired('numBinsToUse', @isnumeric);
    p.addOptional('numPoints', 1, @isnumeric);
    p.addOptional('radii', [], @isnumeric);
    p.parse(numBinsToUse, varargin{:});
    numBinsToUse = p.Results.numBinsToUse;
    numPoints = p.Results.numPoints;
    radii = p.Results.radii;
%             % Page size, dots-per-inch and scale settings
%             fh = figure()
%             if numBinsToUse > NUMPOINTS
%                 dpi = 6*(numBinsToUse+1);
%                 axes_width = 0.8 * (NUMPOINTS + 1) / (numBinsToUse + 1);
%                 axes_height = 0.8;
%             else
%                 dpi = 6*(NUMPOINTS+1);
%                 axes_width = 0.8;
%                 axes_height = 0.8 * (numBinsToUse + 1) / (NUMPOINTS + 1);
%             end
%             fh.set_dpi(dpi)
%             fh.set_size_inches((10.0,10.0),forward=True)
%             fig2ax1 = fig2.add_axes([0.1, 0.85-axes_height, axes_width, axes_height]);
%             print_pixels(fig2, fig2ax1, numBinsToUse, NUMPOINTS);
%             colormapname = 'hot_r';
    MAXMAGCOLORBAR = 5.0;
    MINMAGCOLORBAR = 1.0;
    % Marker size configuration
%             SCALEFACTOR = 84.0 / dpi;
%             MAXMARKERSIZE = 43.0 * SCALEFACTOR;
%             MINMARKERSIZE = 4.0 * SCALEFACTOR;
    PTHRESHOLD = 50;
    for c = 1:length(obj)
        % set up weekending list for yticklabels
        binendstr = {};
        for bin_index=numel(obj.time)-numBinsToUse+1: numel(obj.time)

            dstr = datestr(obj.time(bin_index))
            binendstr{bin_index} = dstr;
        end
        pointlabels = {};
        for i=1:length(numPoints)
            % filter here based on points and radii
            j = 1:length(obj(c).counts); % replace this
            counts = obj(c).counts(j);
            cummag = obj(c).cum_mag(j);
            prcntile = percentiles(obj(c).counts);
            %pointlabels{i} = sprintf('%s(%d)', point_label{i}, counts(-1));
            pointlabels{i}='';
            for bin_index=numel(obj.time)-numBinsToUse+1: numel(obj.time)%-numBinsToUse-1: 1: 0
                y = obj(c).counts(bin_index);
                magnitude = obj(c).cum_mag(bin_index);
                p = y2percentile(y,prcntile);
                if y>0
                    colorVal = scalarMap.to_rgba(magnitude)
                    msize = MINMARKERSIZE + (p-PTHRESHOLD) * (MAXMARKERSIZE - MINMARKERSIZE) / (100-PTHRESHOLD);
                    if msize<MINMARKERSIZE
                        msize=MINMARKERSIZE;
                    end
%                             fig2ax1.plot(i+0.5, w, 's', color=colorVal, markersize=msize, linewidth=0 );
                    scatter(i+0.5, bin_index, msize, y, 's', 'filled')
                    if msize > MAXMARKERSIZE * 0.3
                        text(i+0.5, bin_index, num2str(y))
%                                fig2ax1.text(i+0.5, w, '%d', y, horizontalalignment='center', verticalalignment='center', fontsize = 8 * SCALEFACTOR)
                    end
                end
            end
        end

        % Adding xticks, yticks, labels, grid
%                 fig2ax1.set_axisbelow(True) % I think this puts grid and tickmarks below actual data plotted

        % x-axis
%                 fig2ax1.set_xticks(np.arange(.5,NUMVOLCANOES+.5,1))
        set(gca, 'XTick', 0.5:1:numPoints+0.5);
%                 fig2ax1.set_xlim([-0.5, NUMVOLCANOES+0.5])
        set(gca, 'XLim', [-0.5 numPoints+0.5])
%                 fig2ax1.xaxis.grid(True, linestyle='-', color='gray')
        grid on;
        set(gca, 'XTickLabel', pointlabels)
%                 fig2ax1.xaxis.set_ticks_position('top')
%                 fig2ax1.xaxis.set_label_position('top')
        %plt.setp( fig2ax1.get_xticklabels(), rotation=45, horizontalalignment='left', fontsize=10*SCALEFACTOR )

        % y-axis
%                 fig2ax1.set_yticks(np.arange(-number_of_weeks_to_plot-0.5, 0, 1))
        set(gca, 'YTick', -numBinsToUse-0.5: 1: 0)
%                 fig2ax1.set_yticklabels(weekending)
        set(gca, 'YTickLabel', binendstr)
%                 fig2ax1.set_ylim([-number_of_weeks_to_plot - 0.5, -0.5])
        set(gca, 'YLim', -numBinsToUse -0.5 : 1 : -0.5)
%                 plt.setp( fig2ax1.get_yticklabels(), fontsize=10*SCALEFACTOR )
    end
end

function pvalue(obj)
    logt = log10(obj.time-obj.time(1));
    logc = log10(obj.counts);
    plot(logt, logc);
    p = logt \ logc'
%     p = polyfit(logt, logc, 1)
%     hold on
%     logt1 = min(logt);
%     logc1 = polyval(p, logt1);
%     logt2 = max(logt);
%     logc2 = polyval(p, logt2);
%     line([logt1 logt2], [logc1 logc2]);
end

%% PERCENTILES
function p=percentiles(vals)
    lenVals = length(vals);
    for i=1:100
        p(i) = vals(floor(i/100 * (lenVals-1))+1);
    end
end

%% PLOT_PERCENTILES
function plot_percentiles(p)
    figure(get(gcf,'Number')+1, 'Color', [1 1 1])
    plot(1:100, p);
end


function ma_playMovieTimerCallback(timer, evt, hPlayBtn, hFig, mAxes, maData, frameRate, celBodyData, handles)

    userData = get(timer,'UserData');
    stateLogTime = userData(1);
    prevBody = userData(2);
    orbitToPlot = userData(3);

    stateLog = maData.stateLog;

    if(isnan(stateLogTime))
        stateLogTime = get(handles.movieFrameSlider,'Value');
    end

    if(get(hPlayBtn,'Value')==0 && ~isempty(evt))
        stop(timer); drawnow;

        return;
    end

    timeWarpMultiplier = get(handles.warpRateCombo,'UserData');
    [curBody] = ma_plotFrame(hFig, mAxes, maData, stateLog, stateLogTime, prevBody, orbitToPlot, celBodyData, handles);
    curStateLogTime = ma_getStateLogTimeToPlot(stateLogTime, frameRate, timeWarpMultiplier);

    if(prevBody~=curBody)
        orbitToPlot = orbitToPlot + 1;
    end
    prevBody = curBody;

    ma_setAnimatorSliderBounds(handles, stateLog);
    if(curStateLogTime > max(stateLog(:,1)) && stateLogTime < max(stateLog(:,1)))
        curStateLogTime = max(stateLog(:,1));
    end

    if(curStateLogTime > max(stateLog(:,1)))
        stop(timer);
        set(hPlayBtn,'Value',0);
        set(handles.movieFrameSlider,'Value',max(stateLog(:,1)));

        writeVideo();

        ma_handlePlayButton(handles, frameRate);
        set(handles.movieFrameSlider,'Value',get(handles.movieFrameSlider,'Min'));
        cb = get(handles.movieFrameSlider,'Callback');
        cb(handles.movieFrameSlider,[]);
        return;
    else
        set(handles.movieFrameSlider,'Value',curStateLogTime);
        set(handles.sliderUTText,'String',fullAccNum2Str(curStateLogTime));
    end
    stateLogTime = curStateLogTime;
    set(timer,'UserData',[stateLogTime, prevBody, orbitToPlot]);
end

function writeVideo()
    global GLOBAL_VideoWriter GLOBAL_isRecording;

    if(GLOBAL_isRecording)
        close(GLOBAL_VideoWriter);

        helpMsg = sprintf('Your recording has completed and is available at the following location:\n\n%s',GLOBAL_VideoWriter.Filename);
        h = msgbox(helpMsg,'Recording Complete','help','modal');
        uiwait(h);

        GLOBAL_isRecording = false;
        GLOBAL_VideoWriter = [];
    end
end


function [s, t, tobj] = cs_must_compile (srcdir, f, suffix, obj, hfile, force)
%CS_MUST_COMPILE return 1 if source code f must be compiled, 0 otherwise
%   Used by cs_make, and MATLAB/Test/cs_test_make.m.
%
%   Example:
%        none, not meant for end users.
%   See also: CS_MAKE.

%   Copyright 2006-2007, Timothy A. Davis.
%   http://www.cise.ufl.edu/research/sparse

dobj = dir ([f obj]) ;
if (force | isempty (dobj))                                                 %#ok
    s = 1 ;
    t = Inf ;
    tobj = -1 ;
    return
end
dsrc = dir ([srcdir f suffix '.c']) ;
dh = dir (hfile) ;
t = max (datenum (dsrc.date), datenum (dh.date)) ;
tobj = datenum (dobj.date) ;
s = (tobj < t) ;


function [weight]=best_expert(data, weight_o)
% expert function for the market function
% Input
%     data    -- market historical prices
%     weight_o -- portfolio weight for last trading day
%
% Output
%     weight  -- weight column vector
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file is part of OLPS: http://OLPS.stevenhoi.org/
% Original authors: Bin LI, Steven C.H. Hoi
% Contributors:
% Change log:
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

end