function varargout=spm_figure(varargin)
% Setup and callback functions for Graphics window
% FORMAT varargout=spm_figure(varargin)
%       - An embedded callback, multi-function function
%       - For detailed programmers comments, see format specifications
%         in main body of code
%_______________________________________________________________________
%
% spm_figure creates and manages the 'Graphics' window. This window and
% these facilities may be used independently of SPM, and any number of
% Graphics windows my be used within the same MATLAB session. (Though
% only one SPM 'Graphics' 'Tag'ed window is permitted.
%
% The Graphics window is provided with a menu bar at the top that
% facilitates editing and printing of the current graphic display,
% enabling interactive editing of graphic output prior to printing
% (e.g. selection of color maps, deleting, moving and editing graphics
% objects or adding text). (This menu is also provided as a figure
% background "ContextMenu" - right-clicking on the figure background
% should bring up the menu.)
%
% Print: Graphics windows with multi-page axes are printed page by page.
%
% Clear: Clears the Graphics window. If in SPM usage (figure 'Tag'ed as
% 'Graphics') then all SPM windows are cleared and reset.
%
% Colormap options:
% * gray, hot, pink: Sets the colormap to its default values and loads
%                 either a grayscale, 'hot metal' or color map.
% * gray-hot, etc: Creates a 'split' colormap {128 x 3 matrix}.
%          The lower half is a gray scale and the upper half
%          is 'hot metal' or 'pink'.  This color map is used for
%      viewing 'rendered' SPMs on a PET, MRI or other background images
%
% Colormap effects:
% * Invert: Inverts (flips) the current color map.
% * Brighten and Darken: Brighten and Darken the current colourmap
%      using the MATLAB BRIGHTEN command, with  beta's of +0.2 and -0.2
%      respectively.
%
% Editing: Right button ('alt' button) cancels operations
% * Cut  : Deletes the graphics object next selected (if deletable)
%          Select with middle mouse button to delete blocks of text,
%          or to delete individual elements from a plot.
% * Move : To re-position a text, uicontrol or axis object using a
%          'drag and drop' implementation (i.e. depress - move - release)
%          Using the middle 'extend' mouse button on a text object moves
%          the axes containing the text - i.e. blocks of text.
% * Size : Re-sizes the text, uicontrol or axis object next selected
%          {left button - decrease, middle button  - increase} by a factor
%          of 1.24 (or increase/decrease FontSize by 2 dpi)
% * Text : Creates an editable text widget that produces a text object as
%          its CallBack.
%          The text object is provided with a ContextMenu, obtained by
%          right-clicking ('alt') on the text, allowing text attributes
%          to be changed. Alternatively, the edit facilities on the window
%          menu bar or ContextMenu can be used.
% * Edit : To edit text, select a text object with the circle cursor,
%          and edit the text in the editable text widget that appears.
%          A middle 'extend' mouse click places a context menu on the text
%          object, facilitating easy modification of text atributes.
%
% For SPM usage, the figure should be 'Tag'ed as 'Graphics'.
%
% For SPM power users, and programmers, spm_figure provides utility
% routines for using the SPM graphics interface. Of particular use are
% the GetWin, FindWin and Clear functions See the embedded callback
% reference in the main body of spm_figure, below the help text.
%
% See also: spm_print, spm_clf
%
%_______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Andrew Holmes
% $Id$

%=======================================================================
% - FORMAT specifications for embedded CallBack functions
%=======================================================================
%( This is a multi function function, the first argument is an action  )
%( string, specifying the particular action function to take. Recall   )
%( MATLAB's command-function duality: `spm_figure Create` is           )
%( equivalent to `spm_figure('Create')`.                               )
%
% FORMAT F = spm_figure
% [ShortCut] Defaults to Action 'Create'
%
% FORMAT F = spm_figure(F) - numeric F
% [ShortCut] Defaults to spm_figure('CreateBar',F)
%
% FORMAT F = spm_figure('Create',Tag,Name,Visible)
% Create a full length WhiteBg figure 'Tag'ed Tag (if specified),
% with a ToolBar and background context menu.
% Equivalent to spm_figure('CreateWin','Tag') and spm_figure('CreateBar')
% Tag     - 'Tag' string for figure.
% Name    - Name for window
% Visible - 'on' or 'off'
% F   - Figure used
%
% FORMAT F = spm_figure('FindWin',F)
% Finds window with 'Tag' or figure numnber F - returns empty F if not found
% F - (Input)  Figure to use [Optional] - 'Tag' string or figure number.
%   - Defaults to 'Graphics'
% F - (Output) Figure number (if found) or empty (if not).
%
% FORMAT F = spm_figure('GetWin',Tag)
% Like spm_figure('FindWin',Tag), except that if no such 'Tag'ged figure
% is found and 'Tag' is recognized, one is created. Further, the "got"
% window is made current.
% Tag   - Figure 'Tag' to get, defaults to 'Graphics'
% F - Figure number (if found/created) or empty (if not).
%
% FORMAT F = spm_figure('ParentFig',h)
% Finds window containing the object whose handle is specified
% h - Handle of object whose parent figure is required
%   - If a vector, then first object handle is used
% F - Number or parent figure
%
% FORMAT spm_figure('Clear',F,Tags)
% Clears figure, leaving ToolBar (& other objects with invisible handles)
% Optional third argument specifies 'Tag's of objects to delete.
% If figure F is 'Tag'ged 'Interactive' (SPM usage), then the window
% name and pointer are reset.
% F - 'Tag' string or figure number of figure to clear, defaults to gcf
% Tags  - 'Tag's (string matrix or cell array of strings) of objects to delete
%         *regardless* of 'HandleVisibility'. Only these objects are deleted.
%         '!all' denotes all objects
%
%
% FORMAT spm_figure('Print',F)
% F - [Optional] Figure to print. ('Tag' or figure number)
%     Defaults to figure 'Tag'ed as 'Graphics'.
%     If none found, uses CurrentFigure if avaliable.
% If objects 'Tag'ed 'NextPage' and 'PrevPage' are found, then the
% pages are shown and printed in order. In breif, pages are held as
% separate axes, with ony one 'Visible' at any one time. The handles of
% the "page" axes are stored in the 'UserData' of the 'NextPage'
% object, while the 'PrevPage' object holds the current page number.
% See spm_help('!Disp') for details on setting up paging axes.
%
% FORMAT [hNextPage, hPrevPage, hPageNo] = spm_figure('NewPage',hPage)
% SPM pagination function: Makes objects with handles hPage paginated
% Creates pagination buttons if necessary.
% hPage                         - Handles of objects to stick to this page
% hNextPage, hPrevPage, hPageNo - Handles of pagination controls
%
% FORMAT spm_figure('TurnPage',move,F)
% SPM pagination function: Turn to specified page
%
% FORMAT spm_figure('DeletePageControls',F)
% SPM pagination function: Deletes page controls
% F - [Optional] Figure in which to attempt to turn the page
%         Defaults to 'Graphics' 'Tag'ged window
%
% FORMAT n = spm_figure('#page')
% Returns the current number of pages.
%
% FORMAT n = spm_figure('CurrentPage');
% Return the current page number.
%
% FORMAT spm_figure('WaterMark',F,str,Tag,Angle,Perm)
% Adds watermark to figure windows.
% F - Figure for watermark. Defaults to gcf
% str   - Watermark string. Defaults (missing or empty) to SPM
% Tag   - Tag for watermark axes. Defaults to ''
% Angle - Angle for watermark. Defaults to -45
% Perm  - If specified, then watermark is permanent (HandleVisibility 'off')
%
% FORMAT F = spm_figure('CreateWin',Tag,Name,Visible)
% Creates a full length WhiteBg figure 'Tag'ged Tag (if specified).
% F   - Figure created
% Tag     - Tag for window
% Name    - Name for window
% Visible - 'on' or 'off'
%
% FORMAT WS = spm_figure('GetWinScale')
% Returns ratios of current display dimensions to that of a 1152 x 900
% Sun display. WS=[Xratio,Yratio,Xratio,Yratio]. Used for scaling other
% GUI elements.
% (Function duplicated in spm.m, repeated to reduce inter-dependencies.)
%
% FORMAT FS = spm_figure('FontSizes',FS)
% Returns fontsizes FS scaled for the current display.
% FS     - (vector of) Font sizes to scale
%          [default [08,09,11,13,14,6:36]]
%
% FORMAT spm_figure('CreateBar',F)
% Creates toolbar in figure F (defaults to gcf). F can be a 'Tag'
% If the figure is 'Tag'ed as 'Graphics' (SPM usage), then the Print button
% callback is set to attempt to clear an 'Interactive' figure too.
%
% FORMAT spm_figure('ColorMap')
% Callback for "ColorMap" buttons
%
% FORMAT h = spm_figure('GraphicsHandle',F)
% GUI choose object for handle identification. LeftMouse 'normal' returns
% handle, MiddleMouse 'extend' returns parents handle, RightMouse 'alt' cancels.
% F - figure to do a GUI "handle ID" in [Default gcbf]
%_______________________________________________________________________

%-Condition arguments
%-----------------------------------------------------------------------
if (nargin==0), Action = 'Create'; else Action = varargin{1}; end

switch lower(Action), case 'create'
%=======================================================================
% F = spm_figure('Create',Tag,Name,Visible)
%-Condition arguments
if nargin<4, Visible='on'; else Visible=varargin{4}; end
if nargin<3, Name=''; else, Name=varargin{3}; end
if nargin<2, Tag=''; else Tag=varargin{2}; end

F = spm_figure('CreateWin',Tag,Name,Visible);
spm_figure('CreateBar',F);
spm_figure('FigContextMenu',F);
varargout = {F};

case 'findwin'
%=======================================================================
% F=spm_figure('FindWin',F)
% F=spm_figure('FindWin',Tag)
%-Find window: Find window with FigureNumber# / 'Tag' attribute
%-Returns empty if window cannot be found - deletes multiple tagged figs.

if nargin<2, F='Graphics'; else F=varargin{2}; end

shh = get(0,'showhiddenhandles');
set(0,'showhiddenhandles','on');

if isempty(F)
    % Leave F empty
elseif ischar(F)
    % Finds Graphics window with 'Tag' string - delete multiples
    Tag=F;
    F = findobj(get(0,'Children'),'Flat','Tag',Tag);
    if length(F) > 1
        % Multiple Graphics windows - close all but most recent
        close(F(2:end))
        F = F(1);
    end
else
    % F is supposed to be a figure number - check it
    if ~any(F==get(0,'Children')), F=[]; end
end
set(0,'showhiddenhandles',shh);
varargout = {F};

case 'getwin'
%=======================================================================
% F=spm_figure('GetWin',Tag)

if nargin<2, Tag='Graphics'; else Tag=varargin{2}; end
F = spm_figure('FindWin',Tag);

if isempty(F)
    if ischar(Tag)
        switch Tag

            case 'Graphics'
                F = spm_figure('Create','Graphics','Graphics');
            case 'DEM'
                F = spm_figure('Create','DEM','Dynamic Expectation Maximisation');
            case 'DFP'
                F = spm_figure('Create','DFP','Variational filtering');
            case 'FMIN'
                F = spm_figure('Create','FMIN','Function minimisation');
            case 'MFM'
                F = spm_figure('Create','MFM','Mean-field and neural mass models');
            case 'MVB'
                F = spm_figure('Create','MVB','Multivariate Bayes');
            case 'SI'
                F = spm_figure('Create','SI','System Identification');
            case 'PPI'
                F = spm_figure('Create','PPI','Physio/Psycho-Physiologic Interaction');
            case 'Interactive'
                F = spm('CreateIntWin');
            otherwise
                F = spm_figure('Create',Tag,Tag);
        end
    end
else
    set(0,'CurrentFigure',F);
    figure(F);
end
varargout = {F};

case 'parentfig'
%=======================================================================
% F=spm_figure('ParentFig',h)
if nargin<2, error('No object specified'), else h=varargin{2}; end
F = get(h(1),'Parent');
while ~strcmp(get(F,'Type'),'figure'), F=get(F,'Parent'); end
varargout = {F};

case 'clear'
%=======================================================================
% spm_figure('Clear',F,Tags)

%-Sort out arguments
%-----------------------------------------------------------------------
if nargin<3, Tags=[]; else Tags=varargin{3}; end
if nargin<2, F=get(0,'CurrentFigure'); else F=varargin{2}; end
F = spm_figure('FindWin',F);
if isempty(F), return, end

%-Clear figure
%-----------------------------------------------------------------------
if isempty(Tags)
    %-Clear figure of objects with 'HandleVisibility' 'on'
    pos = get(F,'Position');
    delete(findobj(get(F,'Children'),'flat','HandleVisibility','on'));
    drawnow
    set(F,'Position',pos);

    %-Reset figures callback functions
    zoom(F,'off');
    rotate3d(F,'off');
    set(F,'KeyPressFcn','',...
        'WindowButtonDownFcn','',...
        'WindowButtonMotionFcn','',...
        'WindowButtonUpFcn','')
    %-If this is the 'Interactive' window, reset name & UserData
    if strcmp(get(F,'Tag'),'Interactive')
        set(F,'Name','','UserData',[]), end
else
    %-Clear specified objects from figure
    cSHH = get(0,'ShowHiddenHandles');
    set(0,'ShowHiddenHandles','on')
    if ischar(Tags); Tags=cellstr(Tags); end
    if any(strcmp(Tags(:),'!all'))
        delete(get(F,'Children'))
    else
        for tag = Tags(:)'
        delete(findobj(get(F,'Children'),'flat','Tag',tag{:}));
        end
    end
    set(0,'ShowHiddenHandles',cSHH)
end
set(F,'Pointer','Arrow')
movegui(F);

case 'print'
%=======================================================================
% spm_figure('Print',F,fname)

%-Arguments & defaults
if nargin<3, fname=''; else fname=varargin{3};end
if nargin<2, F='Graphics'; else F=varargin{2}; end

%-Find window to print, default to gcf if specified figure not found
% Return if no figures
if ~isempty(F), F = spm_figure('FindWin',F); end
if  isempty(F), F = get(0,'CurrentFigure'); end
if  isempty(F), return, end

%-Note current figure, & switch to figure to print
cF = get(0,'CurrentFigure');
set(0,'CurrentFigure',F)

%-See if window has paging controls
hNextPage = findobj(F,'Tag','NextPage');
hPrevPage = findobj(F,'Tag','PrevPage');
hPageNo   = findobj(F,'Tag','PageNo');
iPaged    = ~isempty(hNextPage);

%-Construct print command
%-----------------------------------------------------------------------

%-Temporarily change all units to normalized prior to printing
% (Fixes bizzarre problem with stuff jumping around!)
%-----------------------------------------------------------------------
H  = findobj(get(F,'Children'),'flat','Type','axes');
if ~isempty(H),
    un = cellstr(get(H,'Units'));
    set(H,'Units','normalized')
end;

%-Print
%-----------------------------------------------------------------------
if ~iPaged
    spm_print(fname)
else
    hPg       = get(hNextPage,'UserData');
    Cpage     = get(hPageNo,  'UserData');
    nPages    = size(hPg,1);

    set([hNextPage,hPrevPage,hPageNo],'Visible','off')
    if Cpage~=1
        set(hPg{Cpage,1},'Visible','off'), end
    for p = 1:nPages
        set(hPg{p,1},'Visible','on');
        spm_print(fname);
        set(hPg{p,1},'Visible','off')
    end
    set(hPg{Cpage,1},'Visible','on')
    set([hNextPage,hPrevPage,hPageNo],'Visible','on')
end
if ~isempty(H), set(H,{'Units'},un); end;
set(0,'CurrentFigure',cF)

case 'printto'
%=======================================================================
%spm_figure('PrintTo',F)

%-Arguments & defaults
if nargin<2, F='Graphics'; else F=varargin{2}; end

%-Find window to print, default to gcf if specified figure not found
% Return if no figures
F=spm_figure('FindWin',F);
if isempty(F), F = get(0,'CurrentFigure'); end
if isempty(F), return, end

[fn pn] = uiputfile('*.ps', 'Print to File');
if fn == 0
    return;
end;

psname = fullfile(pn, fn);
spm_figure('Print',F,psname);

case 'newpage'
%=======================================================================
% [hNextPage, hPrevPage, hPageNo] = spm_figure('NewPage',h)
if nargin<2 || isempty(varargin{2}) error('No handles to paginate')
else h=varargin{2}(:)'; end

%-Work out which figure we're in
F = spm_figure('ParentFig',h(1));

hNextPage = findobj(F,'Tag','NextPage');
hPrevPage = findobj(F,'Tag','PrevPage');
hPageNo   = findobj(F,'Tag','PageNo');

%-Create pagination widgets if required
%-----------------------------------------------------------------------
if isempty(hNextPage)
    WS = spm('WinScale');
    FS = spm('FontSizes');
    SatFig = findobj('Tag','Satellite');
    if ~isempty(SatFig)
        SatFigPos    = get(SatFig,'Position');
        hNextPagePos = [SatFigPos(3)-25 15 15 15];
        hPrevPagePos = [SatFigPos(3)-40 15 15 15];
        hPageNo      = [SatFigPos(3)-40  5 30 10];
    else
        hNextPagePos = [580 022 015 015].*WS;
        hPrevPagePos = [565 022 015 015].*WS;
        hPageNo      = [550 005 060 015].*WS;
    end

    hNextPage = uicontrol(F,'Style','Pushbutton',...
        'HandleVisibility','on',...
        'String','>','FontSize',FS(10),...
        'ToolTipString','next page',...
        'Callback','spm_figure(''TurnPage'',''+1'',gcbf)',...
        'Position',hNextPagePos,...
        'ForegroundColor',[0 0 0],...
        'Tag','NextPage','UserData',[]);
    hPrevPage = uicontrol(F,'Style','Pushbutton',...
        'HandleVisibility','on',...
        'String','<','FontSize',FS(10),...
        'ToolTipString','previous page',...
        'Callback','spm_figure(''TurnPage'',''-1'',gcbf)',...
        'Position',hPrevPagePos,...
        'Visible','on',...
        'Enable','off',...
        'Tag','PrevPage');
    hPageNo = uicontrol(F,'Style','Text',...
        'HandleVisibility','on',...
        'String','1',...
        'FontSize',FS(6),...
        'HorizontalAlignment','center',...
        'BackgroundColor','w',...
        'Position',hPageNo,...
        'Visible','on',...
        'UserData',1,...
        'Tag','PageNo','UserData',1);
end

%-Add handles for this page to UserData of hNextPage
%-Make handles for this page invisible if PageNo>1
%-----------------------------------------------------------------------
mVis    = strcmp('on',get(h,'Visible'));
mHit    = strcmp('on',get(h,'HitTest'));
hPg     = get(hNextPage,'UserData');
if isempty(hPg)
    hPg = {h(mVis), h(~mVis), h(mHit), h(~mHit)};
else
    hPg = [hPg; {h(mVis), h(~mVis), h(mHit), h(~mHit)}];
    set(h(mVis),'Visible','off');
        set(h(mHit),'HitTest','off');
end
set(hNextPage,'UserData',hPg)

%-Return handles to pagination controls if requested
if nargout>0, varargout = {[hNextPage, hPrevPage, hPageNo]}; end

case 'turnpage'
%=======================================================================
% spm_figure('TurnPage',move,F)
if nargin<3, F='Graphics'; else F=varargin{3}; end
if nargin<2, move=1; else move=varargin{2}; end
F = spm_figure('FindWin',F);
if isempty(F), error('No Graphics window'), end

hNextPage = findobj(F,'Tag','NextPage');
hPrevPage = findobj(F,'Tag','PrevPage');
hPageNo   = findobj(F,'Tag','PageNo');
if isempty(hNextPage), return, end
hPg       = get(hNextPage,'UserData');
Cpage     = get(hPageNo,  'UserData');
nPages    = size(hPg,1);

%-Sort out new page number
if ischar(move), Npage = Cpage+eval(move); else Npage = move; end
Npage = max(min(Npage,nPages),1);

%-Make current page invisible, new page visible, set page number string
set(hPg{Cpage,1},'Visible','off');
set(hPg{Cpage,3},'HitTest','off');
set(hPg{Npage,1},'Visible','on');
set(hPg{Npage,3},'HitTest','on');
set(hPageNo,'UserData',Npage,'String',sprintf('%d / %d',Npage,nPages))

for k = 1:length(hPg{Npage,1}) % VG
    if strcmp(get(hPg{Npage,1}(k),'Type'),'axes')
        axes(hPg{Npage,1}(k));
    end;
end;

%-Disable appropriate page turning control if on first/last page (for neatness)
if Npage==1, set(hPrevPage,'Enable','off')
else set(hPrevPage,'Enable','on'), end
if Npage==nPages, set(hNextPage,'Enable','off')
else set(hNextPage,'Enable','on'), end

case 'deletepagecontrols'
%=======================================================================
% spm_figure('DeletePageControls',F)
if nargin<2, F='Graphics'; else F=varargin{2}; end
F = spm_figure('FindWin',F);
if isempty(F), error('No Graphics window'), end

hNextPage = findobj(F,'Tag','NextPage');
hPrevPage = findobj(F,'Tag','PrevPage');
hPageNo   = findobj(F,'Tag','PageNo');

delete([hNextPage hPrevPage hPageNo])

case '#page'
%=======================================================================
% n = spm_figure('#Page',F)
if nargin<2, F='Graphics'; else F=varargin{2}; end
F = spm_figure('FindWin',F);
if isempty(F), error('No Graphics window'), end

hNextPage = findobj(F,'Tag','NextPage');
if isempty(hNextPage)
    n = 1;
else
    n = size(get(hNextPage,'UserData'),1)+1;
end
varargout = {n};

case 'currentpage'
%=======================================================================
% n = spm_figure('CurrentPage', F)
if nargin<2, F='Graphics'; else F=varargin{2}; end
F = spm_figure('FindWin',F);
if isempty(F), error('No Graphics window'), end

hPageNo   = findobj(F,'Tag','PageNo');
Cpage     = get(hPageNo,  'UserData');

varargout = {Cpage};

case 'watermark'
%=======================================================================
% spm_figure('WaterMark',F,str,Tag,Angle,Perm)
if nargin<6, HVis='on'; else HVis='off'; end
if nargin<5, Angle=-45; else Angle=varargin{5}; end
if nargin<4 || isempty(varargin{4}), Tag = 'WaterMark'; else Tag=varargin{4}; end
if nargin<3 || isempty(varargin{3}), str = 'SPM';       else str=varargin{3}; end
if nargin<2, if any(get(0,'Children')), F=gcf; else F=''; end
else F=varargin{2}; end
F = spm_figure('FindWin',F);
if isempty(F), return, end

%-Specify watermark color from background colour
%-----------------------------------------------------------------------
Colour = get(F,'Color');
%-Only mess with grayscale backgrounds
if ~all(Colour==Colour(1)), return, end
%-Work out colour - lighter unless grey value > 0.9
Colour = Colour+(2*(Colour(1)<0.9)-1)*0.02;

cF = get(0,'CurrentFigure');
set(0,'CurrentFigure',F)
Units=get(F,'Units');
set(F,'Units','normalized');
h = axes('Position',[0.45,0.5,0.1,0.1],...
    'Units','normalized',...
    'Visible','off',...
    'Tag',Tag);
set(F,'Units',Units)
text(0.5,0.5,str,...
    'FontSize',spm('FontSize',80),...
    'FontWeight','Bold',...
    'FontName',spm_platform('Font','times'),...
    'Rotation',Angle,...
    'HorizontalAlignment','Center',...
    'VerticalAlignment','middle',...
    'EraseMode','normal',...
    'Color',Colour,...
    'ButtonDownFcn',[...
        'if strcmp(get(gcbf,''SelectionType''),''open''),',...
            'delete(get(gcbo,''Parent'')),',...
        'end'])
set(h,'HandleVisibility',HVis)
set(0,'CurrentFigure',cF)

case 'createwin'
%=======================================================================
% F=spm_figure('CreateWin',Tag,Name,Visible)

%-Condition arguments
%-----------------------------------------------------------------------
if nargin<4 || isempty(varargin{4}), Visible='on'; else Visible=varargin{4}; end
if nargin<3, Name=''; else Name = varargin{3}; end
if nargin<2, Tag='';  else Tag  = varargin{2}; end

WS   = spm('WinScale');           %-Window scaling factors
FS   = spm('FontSizes');          %-Scaled font sizes
PF   = spm_platform('fonts');     %-Font names (for this platform)
Rect = spm('WinSize','Graphics'); %-Graphics window rectangle
S0   = spm('WinSize','0',1);      %-Screen size (of the current monitor)

F    = figure(...
    'Tag',Tag,...
    'Position',[S0(1) S0(2) 0 0] + Rect,...
    'Resize','off',...
    'Color','w',...
    'ColorMap',gray(64),...
    'DefaultTextColor','k',...
    'DefaultTextInterpreter','none',...
    'DefaultTextFontName',PF.helvetica,...
    'DefaultTextFontSize',FS(10),...
    'DefaultAxesColor','w',...
    'DefaultAxesXColor','k',...
    'DefaultAxesYColor','k',...
    'DefaultAxesZColor','k',...
    'DefaultAxesFontName',PF.helvetica,...
    'DefaultPatchFaceColor','k',...
    'DefaultPatchEdgeColor','k',...
    'DefaultSurfaceEdgeColor','k',...
    'DefaultLineColor','k',...
    'DefaultUicontrolFontName',PF.helvetica,...
    'DefaultUicontrolFontSize',FS(10),...
    'DefaultUicontrolInterruptible','on',...
    'PaperType','A4',...
    'PaperUnits','normalized',...
    'PaperPosition',[.0726 .0644 .854 .870],...
    'InvertHardcopy','off',...
    'Renderer',spm_get_defaults('renderer'),...
    'Visible','off',...
    'Toolbar','none');
if ~isempty(Name)
    set(F,'Name',sprintf('%s%s: %s',spm('ver'),...
        spm('GetUser',' (%s)'),Name),'NumberTitle','off')
end
set(F,'Visible',Visible)
varargout = {F};

case 'getwinscale'
%=======================================================================
% WS = spm_figure('GetWinScale')
warning('spm_figure(''GetWinScale''... is Grandfathered: use spm(''WinScale''')
varargout = {spm('WinScale')};

case 'fontsizes'
%=======================================================================
% FS = spm_figure('FontSizes',FS)
warning('spm_figure(''FontSizes''... is Grandfathered: use spm(''FontSizes''')
if nargin<2, FS=[08,09,11,13,14,6:36]; else FS=varargin{2}; end
varargout = {round(FS*min(spm('WinScale')))};

%=======================================================================
 case 'createbar'
%=======================================================================
% spm_figure('CreateBar',F)
if nargin<2, if any(get(0,'Children')), F=gcf; else F=''; end
else F=varargin{2}; end
F = spm_figure('FindWin',F);
if isempty(F), return, end

cSHH = get(0,'ShowHiddenHandles');
set(0,'ShowHiddenHandles','on')

t0 = findobj(get(F,'Children'),'Flat','Label','&Help');
if isempty(t0), t0 = uimenu( F,'Label','&Help'); end;

set(findobj(t0,'Position',1),'Separator','on');
uimenu(t0,'Position',1,...
    'Label','SPM web',...
    'CallBack','web(''http://www.fil.ion.ucl.ac.uk/spm/'');');
uimenu(t0,'Position',1,...
    'Label','SPM help','ForegroundColor',[0 1 0],...
    'CallBack','spm_help');

t0=uimenu( F,'Label','Colours','HandleVisibility','off');
t1=uimenu(t0,'Label','ColorMap');
uimenu(t1,'Label','Gray',     'CallBack','spm_figure(''ColorMap'',''gray'')');
uimenu(t1,'Label','Hot',      'CallBack','spm_figure(''ColorMap'',''hot'')');
uimenu(t1,'Label','Pink',     'CallBack','spm_figure(''ColorMap'',''pink'')');
uimenu(t1,'Label','Jet','CallBack','spm_figure(''ColorMap'',''jet'')');
uimenu(t1,'Label','Gray-Hot', 'CallBack','spm_figure(''ColorMap'',''gray-hot'')');
uimenu(t1,'Label','Gray-Cool','CallBack','spm_figure(''ColorMap'',''gray-cool'')');
uimenu(t1,'Label','Gray-Pink','CallBack','spm_figure(''ColorMap'',''gray-pink'')');
uimenu(t1,'Label','Gray-Jet', 'CallBack','spm_figure(''ColorMap'',''gray-jet'')');
t1=uimenu(t0,'Label','Effects');
uimenu(t1,'Label','Invert','CallBack','spm_figure(''ColorMap'',''invert'')');
uimenu(t1,'Label','Brighten','CallBack','spm_figure(''ColorMap'',''brighten'')');
uimenu(t1,'Label','Darken','CallBack','spm_figure(''ColorMap'',''darken'')');
uimenu( F,'Label','Clear','HandleVisibility','off','CallBack','spm_figure(''Clear'',gcbf)');
t0=uimenu( F,'Label','SPM-Print','HandleVisibility','off');
%uimenu( F,'Label','SPM-Print','HandleVisibility','off','CallBack','spm_figure(''Print'',gcbf)');
t1=uimenu(t0,'Label','default print file','HandleVisibility','off','CallBack','spm_figure(''Print'',gcbf)');
t1=uimenu(t0,'Label','other print file','HandleVisibility','off','CallBack','spm_figure(''PrintTo'',spm_figure(''FindWin'',''Graphics''))');

% ### CODE FOR SATELLITE FIGURE ###
% Code checks if there is a satellite window and if results are currently displayed
% It assumes that if hReg is invalid then there are no results currently displayed
% Modified by DRG to display a satellite figure 02/14/01.
cb = ['global SatWindow,',...
        'try,',...
        'tmp = get(hReg);,',...
        'ResFlag = 1;',...
        'catch,',...
        'ResFlag = 0;',...
        'end,',...
        'if SatWindow,',...
        'figure(SatWindow),',...
        'else,',...
        'if ResFlag,',...
        'spm_setup_satfig,',...
        'end,',...
        'end'];
uimenu( F,'Label','Results-Fig','HandleVisibility','off','Callback',cb);
% ### END NEW CODE ###

set(0,'ShowHiddenHandles',cSHH)
try
    spm_jobman('pulldown');
end

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

case 'figcontextmenu'
%=======================================================================
% h = spm_figure('FigContextMenu',F)
if nargin<2
    F = get(0,'CurrentFigure');
    if isempty(F), error('no figure'), end
else
    F = spm_figure('FindWin',varargin{2});
    if isempty(F), error('no such figure'), end
end
h       = uicontextmenu('Parent',F,'HandleVisibility','CallBack');
cSHH = get(0,'ShowHiddenHandles');
set(0,'ShowHiddenHandles','on')
copy_menu(F,h);
set(0,'ShowHiddenHandles',cSHH)
set(F,'UIContextMenu',h)
varargout = {h};

case 'colormap'
%=======================================================================
% spm_figure('ColorMap',ColAction,h)
if nargin<3, h=[]; else h=varargin{3}; end
if nargin<2, ColAction='gray'; else ColAction=varargin{2}; end

switch lower(ColAction), case 'gray'
    colormap(gray(64))
case 'hot'
    colormap(hot(64))
case 'pink'
    colormap(pink(64))
case 'jet'
    colormap(jet(64))
case 'gray-hot'
    tmp = hot(64 + 16);  tmp = tmp((1:64) + 16,:);
    colormap([gray(64); tmp]);
case 'gray-cool'
    cool = [zeros(10,1) zeros(10,1) linspace(0.5,1,10)';
            zeros(31,1) linspace(0,1,31)' ones(31,1);
            linspace(0,1,23)' ones(23,1) ones(23,1) ];
    colormap([gray(64); cool]);
case 'gray-pink'
    tmp = pink(64 + 16); tmp = tmp((1:64) + 16,:);
    colormap([gray(64); tmp]);
case 'gray-jet'
    colormap([gray(64); jet(64)]);
case 'invert'
    colormap(flipud(colormap));
case 'brighten'
    colormap(brighten(colormap, 0.2));
case 'darken'
    colormap(brighten(colormap, -0.2));
otherwise
    error('Illegal ColAction specification');
end

case 'graphicshandle'
%=======================================================================
% h = spm_figure('GraphicsHandle',F)
if nargin<2, F=gcbf; else F=spm_figure('FindWin',varargin{2}); end
if isempty(F), return, end

tmp = get(F,'Name');
set(F,'Name',...
    'Handle: Select item to identify, MiddleMouse=parent, RightMouse=cancel...');
set(F,'Pointer','CrossHair')
waitforbuttonpress;
h        = gco(F);
hType    = get(h,'Type');
SelnType = get(gcf,'SelectionType');
set(F,'Pointer','Arrow','Name',tmp)

if ~strcmp(SelnType,'alt') && ~isempty(h) && gcf==F
    str = sprintf('Selected (%s) object',get(h,'Type'));
    if strcmp(SelnType,'normal')
        str = sprintf('%s: handle',str);
    else
        h = get(h,'Parent');
        str = sprintf('%s: handle of parent (%s) object',str,get(h,'Type'));
    end
    if nargout==0
        assignin('base','ans',h)
        fprintf('\n%s: \n',str)
        ans = h
    else
        varargout={h};
    end
else
    varargout={[]};
end

otherwise
%=======================================================================
warning(['Illegal Action string: ',Action])
end
return;
%=======================================================================

%=======================================================================
function copy_menu(F,G)
%=======================================================================
handles = findobj(get(F,'Children'),'Flat','Type','uimenu','Visible','on');
if isempty(handles), return; end;
for F1=handles',
    if ~strcmp(get(F1,'Label'),'&Window'),
        G1 = uimenu(G,'Label',get(F1,'Label'),...
            'CallBack',get(F1,'CallBack'),...
            'Position',get(F1,'Position'),...
            'Separator',get(F1,'Separator'));
        copy_menu(F1,G1);
    end;
end;
return;
%=======================================================================


classdef StiffnessDescriptor < FieldNameDescriptor

    methods (Access = protected)

        function loadFieldVariable(obj)
            obj.fieldName = 'stiffness';
        end

    end

end


function assocScansV = getDoseAssociatedScan(dosesV, planC)
% "getDoseAssociatedScan"
%   Returns a vector with the corresponding associated scan for each
%   dose number passed in structsV.
%
%   If planC is not specified, the global planC is used.
%
% DK 07/19/2006
%
%Usage:
%   [assocScansV, relStructNum] = getDoseAssociatedScan(dosesV, planC)
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with CERR.  If not, see <http://www.gnu.org/licenses/>.

if ~exist('planC')
    global planC
end
indexS = planC{end};

assocScansV = [];

for i = 1:length(dosesV)
    assocScanTmp = getAssociatedScan(planC{indexS.dose}(dosesV(i)).assocScanUID, planC);
    if ~isempty(assocScanTmp)
        assocScansV(i) = assocScanTmp;
    end
end


function setglobal(var)

% SETGLOBAL assigns global variables from a structure
%
% Use as
%   var = getglobal;
%   setglobal(var);
%
% See also GETGLOBAL

% Copyright (C) 2012, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

if isempty(var)
  return
end

list = fieldnames(var);

for i=1:length(list)
  eval(sprintf('global %s', list{i}));
  eval(sprintf('%s = var.%s;', list{i}, list{i}));
end


function fig = scopegui()
% SCOPEGUI is GUI-part for oscilloscope SCOPE.M function
% This is the machine-generated representation of a Handle Graphics object
% and its children.  Note that handle values may change when these objects
% are re-created. This may cause problems with any callbacks written to
% depend on the value of the handle at the time the object was saved.
%
% To reopen this object, just type the name of the M-file at the MATLAB
% prompt. The M-file and its associated MAT-file must be on your path.

load scopegui

h0 = figure('Units','points', ...
	'BackingStore','off', ...
	'Color',[0.8 0.8 0.8], ...
	'Colormap',mat0, ...
	'DeleteFcn','scope h_Close;', ...
	'MenuBar','none', ...
	'Name','DAPScope', ...
	'NumberTitle','off', ...
	'PointerShapeCData',mat1, ...
	'Position',[87 137.25 546.75 324], ...
	'RendererMode','manual', ...
	'Tag','scope', ...
	'WindowButtonDownFcn','zoom xdown', ...
	'WindowButtonUpFcn','ones;');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'Callback','scope(''h_Start'');', ...
	'ListboxTop',0, ...
	'Position',[468.375 69.75 63.75 24.75], ...
	'String','Start', ...
	'Tag','h_Start');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'Callback','scope(''h_Stop'');', ...
	'Enable','off', ...
	'ListboxTop',0, ...
	'Position',[468.375 43.5 63.75 24], ...
	'String','Stop', ...
	'Tag','h_Stop');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'Callback','scope h_Close;', ...
	'ListboxTop',0, ...
	'Position',[468.375 17.25 63.75 24], ...
	'String','Close', ...
	'Tag','h_Close');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0 0.5 0.5], ...
	'Enable','inactive', ...
	'FontWeight','demi', ...
	'ForegroundColor',[1 1 1], ...
	'ListboxTop',0, ...
	'Position',[468 132 64.5 16.5], ...
	'String','360mks/cnt', ...
	'Style','edit', ...
	'Tag','h_Dwell');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0 0.5 0.5], ...
	'Enable','inactive', ...
	'FontWeight','demi', ...
	'ForegroundColor',[1 1 1], ...
	'ListboxTop',0, ...
	'Position',[466.875 246.75 66.75 15], ...
	'String','0', ...
	'Style','edit', ...
	'Tag','h_SpNum');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'Callback','scope(''h_DwTime'');', ...
	'ListboxTop',0, ...
	'Max',333, ...
	'Min',20, ...
	'Position',[470.25 114 60 14.25], ...
	'String','DwTime', ...
	'Style','slider', ...
	'Tag','h_DwTime', ...
	'Value',100);
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0 0 1], ...
	'Enable','inactive', ...
	'FontWeight','demi', ...
	'ForegroundColor',[1 1 0], ...
	'ListboxTop',0, ...
	'Position',[459 289.5 82.5 15.75], ...
	'String','LanscView 1.0', ...
	'Style','edit', ...
	'Tag','Label1Text');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'FontWeight','bold', ...
	'ListboxTop',0, ...
	'Position',[467.625 264 65.25 15.75], ...
	'String','Trace Num', ...
	'Style','text', ...
	'Tag','Label2Text');
h1 = axes('Parent',h0, ...
	'Units','points', ...
	'Box','on', ...
	'CameraUpVector',[0 1 0], ...
	'CameraUpVectorMode','manual', ...
	'Color',[0 0 0], ...
	'ColorOrder',mat2, ...
	'DrawMode','fast', ...
	'FontSize',8, ...
	'FontWeight','demi', ...
	'NextPlot','replacechildren', ...
	'Position',[142.5 27 312.75 268.5], ...
	'Tag','h_Axes', ...
	'XColor',[0 0 0], ...
	'XLim',mat3, ...
	'XLimMode','manual', ...
	'YColor',[0 0 0], ...
	'YLim',[-5000 5000], ...
	'YLimMode','manual', ...
	'ZColor',[0 0 0]);
h2 = text('Parent',h1, ...
	'Color',[0 0 0], ...
	'FontSize',8, ...
	'FontWeight','demi', ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','center', ...
	'Position',[235.2568512568512 5140.056022408962 17.32050807568877], ...
	'String','Signal', ...
	'Tag','h_AxesText4', ...
	'VerticalAlignment','bottom');
set(get(h2,'Parent'),'Title',h2);
h2 = text('Parent',h1, ...
	'Color',[0 0 0], ...
	'FontSize',8, ...
	'FontWeight','demi', ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','center', ...
	'Position',[235.2568512568512 -5560.224089635854 17.32050807568877], ...
	'String','count', ...
	'Tag','h_AxesText2', ...
	'VerticalAlignment','cap');
set(get(h2,'Parent'),'XLabel',h2);
h2 = text('Parent',h1, ...
	'Color',[0 0 0], ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','right', ...
	'Position',[-9.666225666225643 6036.414565826328 17.32050807568877], ...
	'Tag','h_AxesText1', ...
	'UserData',[0 1024 -5000 5000], ...
	'Visible','off');
set(get(h2,'Parent'),'ZLabel',h2);
h2 = line('Parent',h1, ...
	'Color',[1 1 0], ...
	'EraseMode','background', ...
	'LineWidth',0.2, ...
	'Tag','h_AxesLine2', ...
	'XData',mat4, ...
	'YData',mat5);
h2 = line('Parent',h1, ...
	'Color',[0 1 0], ...
	'EraseMode','background', ...
	'LineWidth',0.2, ...
	'Tag','h_AxesLine1', ...
	'XData',mat6, ...
	'YData',mat7);
h2 = text('Parent',h1, ...
	'Color',[0 0 0], ...
	'HandleVisibility','off', ...
	'HorizontalAlignment','center', ...
	'Position',[83.25685125685125 -42.01680672269049 17.32050807568877], ...
	'Rotation',90, ...
	'Tag','h_AxesText3', ...
	'VerticalAlignment','baseline');
set(get(h2,'Parent'),'YLabel',h2);
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'Callback','scope h_Mode;', ...
	'ListboxTop',0, ...
	'Position',[468.375 185.25 63.75 15.75], ...
	'String','Switch View', ...
	'Tag','h_Mode');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0 0.5 0.5], ...
	'Enable','inactive', ...
	'FontWeight','demi', ...
	'ForegroundColor',[1 1 1], ...
	'ListboxTop',0, ...
	'Position',[16.5 250 60 15.5], ...
	'String','0', ...
	'Style','edit', ...
	'Tag','h_Inp1_ed');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'Callback','scope h_Inp1_sl;', ...
	'ListboxTop',0, ...
	'Max',100, ...
	'Position',[80.25 251.25 14.25 30.75], ...
	'String','Shift, mV', ...
	'Style','slider', ...
	'Tag','h_Inp1_sl');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.501960784313725 0.501960784313725 0.501960784313725], ...
	'FontWeight','bold', ...
	'ForegroundColor',[0 1 0], ...
	'ListboxTop',0, ...
	'Position',[16.5 285.25 75 15.75], ...
	'String','Channel 1', ...
	'Style','text', ...
	'Tag','Label2Text');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'FontWeight','bold', ...
	'ListboxTop',0, ...
	'Position',[15.75 267.75 60 15.75], ...
	'String','Input', ...
	'Style','text', ...
	'Tag','h_Inp1_lb');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'Enable','inactive', ...
	'FontWeight','bold', ...
	'ListboxTop',0, ...
	'Position',[16.5 232.25 60 15.75], ...
	'String','Scale', ...
	'Style','text', ...
	'Tag','h_Scale1_lb');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'Callback','scope h_Scale1_sl;', ...
	'ListboxTop',0, ...
	'Max',101, ...
	'Min',1, ...
	'Position',[79.5 215.25 14.25 30.75], ...
	'String','Shift, mV', ...
	'Style','slider', ...
	'Tag','h_Scale1_sl', ...
	'Value',1);
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0 0.5 0.5], ...
	'Enable','inactive', ...
	'FontWeight','demi', ...
	'ForegroundColor',[1 1 1], ...
	'ListboxTop',0, ...
	'Position',[16.5 214.75 60 15.5], ...
	'String','1', ...
	'Style','edit', ...
	'Tag','h_Scale1_ed');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'FontWeight','bold', ...
	'ListboxTop',0, ...
	'Position',[466.875 150.75 66.75 15.75], ...
	'String','Dwell Time', ...
	'Style','text', ...
	'Tag','Label2Text');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0 0.5 0.5], ...
	'Enable','inactive', ...
	'FontWeight','demi', ...
	'ForegroundColor',[1 1 1], ...
	'ListboxTop',0, ...
	'Position',[16.5 179.25 60 15.75], ...
	'String','0', ...
	'Style','edit', ...
	'Tag','h_Shift1_ed');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'Callback','scope h_Shift1_sl;', ...
	'ListboxTop',0, ...
	'Max',5000, ...
	'Min',-5000, ...
	'Position',[79.5 179.25 14.25 30.75], ...
	'String','Shift, mV', ...
	'Style','slider', ...
	'Tag','h_Shift1_sl');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'Enable','inactive', ...
	'FontWeight','bold', ...
	'ListboxTop',0, ...
	'Position',[16.5 197 60 15.75], ...
	'String','Shift, mV', ...
	'Style','text', ...
	'Tag','h_Shift1_lb');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'FontWeight','bold', ...
	'ListboxTop',0, ...
	'Position',[16.5 52.75 60 15.75], ...
	'String','Shift, mV', ...
	'Style','text', ...
	'Tag','h_Shift2_lb');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'Callback','scope h_Shift2_sl;', ...
	'ListboxTop',0, ...
	'Max',5000, ...
	'Min',-5000, ...
	'Position',[79.5 35.25 14.25 30.75], ...
	'String','Shift, mV', ...
	'Style','slider', ...
	'Tag','h_Shift2_sl');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0 0.5 0.5], ...
	'FontWeight','demi', ...
	'ForegroundColor',[1 1 1], ...
	'ListboxTop',0, ...
	'Position',[16.5 35.25 60 15.5], ...
	'String','0', ...
	'Style','edit', ...
	'Tag','h_Shift2_ed');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0 0.5 0.5], ...
	'FontWeight','demi', ...
	'ForegroundColor',[1 1 1], ...
	'ListboxTop',0, ...
	'Position',[16.5 70.5 60 15.75], ...
	'String','1', ...
	'Style','edit', ...
	'Tag','h_Scale2_ed');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'Callback','scope h_Scale2_sl;', ...
	'ListboxTop',0, ...
	'Max',101, ...
	'Min',1, ...
	'Position',[79.5 70.5 14.25 30.75], ...
	'String','Shift, mV', ...
	'Style','slider', ...
	'Tag','h_Scale2_sl', ...
	'Value',1);
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'FontWeight','bold', ...
	'ListboxTop',0, ...
	'Position',[16.5 88.25 60 15.75], ...
	'String','Scale', ...
	'Style','text', ...
	'Tag','h_Scale2_lb');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'FontWeight','bold', ...
	'ListboxTop',0, ...
	'Position',[16.5 123.75 60 15.75], ...
	'String','Input', ...
	'Style','text', ...
	'Tag','h_Inp2_lb');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.501960784313725 0.501960784313725 0.501960784313725], ...
	'FontWeight','bold', ...
	'ForegroundColor',[1 1 0], ...
	'ListboxTop',0, ...
	'Position',[16.5 141.5 75 15.75], ...
	'String','Channel 2', ...
	'Style','text', ...
	'Tag','Label2Text');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'Callback','scope h_Inp2_sl;', ...
	'ListboxTop',0, ...
	'Max',100, ...
	'Position',[79.5 107.25 14.25 30.75], ...
	'String','Shift, mV', ...
	'Style','slider', ...
	'Tag','h_Inp2_sl');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0 0.5 0.5], ...
	'FontWeight','demi', ...
	'ForegroundColor',[1 1 1], ...
	'ListboxTop',0, ...
	'Position',[17.25 106 60 15.75], ...
	'String','0', ...
	'Style','edit', ...
	'Tag','h_Inp2_ed');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ...
	'FontWeight','bold', ...
	'ListboxTop',0, ...
	'Position',[467.625 221.25 65.25 15.75], ...
	'String','View Mode', ...
	'Style','text', ...
	'Tag','Label2Text');
h1 = uicontrol('Parent',h0, ...
	'Units','points', ...
	'BackgroundColor',[0 0.5 0.5], ...
	'Enable','inactive', ...
	'FontWeight','demi', ...
	'ForegroundColor',[1 1 1], ...
	'ListboxTop',0, ...
	'Position',[466.875 204 66.75 15], ...
	'String','X-T', ...
	'Style','edit', ...
	'Tag','h_View_ed');
if nargout > 0, fig = h0; end


function versionnumber = SFS_version()
%SFS_VERSION Return the version number of the SFS Toolbox
%
%   Usage: versionnumber = SFS_version;
%
%   SFS_VERSION returns the version number of the used Sound Field Synthesis
%   Toolbox.
%
%   See also: SFS_start, SFS_config

%*****************************************************************************
% The MIT License (MIT)                                                      *
%                                                                            *
% Copyright (c) 2010-2019 SFS Toolbox Developers                             *
%                                                                            *
% Permission is hereby granted,  free of charge,  to any person  obtaining a *
% copy of this software and associated documentation files (the "Software"), *
% to deal in the Software without  restriction, including without limitation *
% the rights  to use, copy, modify, merge,  publish, distribute, sublicense, *
% and/or  sell copies of  the Software,  and to permit  persons to whom  the *
% Software is furnished to do so, subject to the following conditions:       *
%                                                                            *
% The above copyright notice and this permission notice shall be included in *
% all copies or substantial portions of the Software.                        *
%                                                                            *
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
% IMPLIED, INCLUDING BUT  NOT LIMITED TO THE  WARRANTIES OF MERCHANTABILITY, *
% FITNESS  FOR A PARTICULAR  PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL *
% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
% LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT  OR OTHERWISE, ARISING *
% FROM,  OUT OF  OR IN  CONNECTION  WITH THE  SOFTWARE OR  THE USE  OR OTHER *
% DEALINGS IN THE SOFTWARE.                                                  *
%                                                                            *
% The SFS Toolbox  allows to simulate and  investigate sound field synthesis *
% methods like wave field synthesis or higher order ambisonics.              *
%                                                                            *
% https://sfs.readthedocs.io                            sfstoolbox@gmail.com *
%*****************************************************************************

%% ===== Configuration ===================================================
% Version number
versionnumber = '2.5.0';


function varargout = doseManagementGui(command, varargin)
%"doseManagementGui" GUI
%   Create a GUI to manage doses.
%
%   JRA 2/27/04
%
%Usage:
%   doseManagementGui()
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with CERR.  If not, see <http://www.gnu.org/licenses/>.

%The cursed globals. Need em.
global planC stateS
indexS = planC{end};

%Use a static window size, by pixels.  Do not allow resizing.
screenSize = get(0,'ScreenSize');
y = 380;
x = 640;
units = 'normalized';

%Height of a single row of text.
rowHeight = .06;

%If no command given, default to init.
if ~exist('command','var') || isempty(command)
    command = 'init';
end

%Find handle of the gui figure.
%h = findobj('tag', 'doseManagementGui');
h = [];
if isfield(stateS.handle,'doseManagementFig') && ishandle(stateS.handle.doseManagementFig)
    h = stateS.handle.doseManagementFig;
end

%Set framecolor for uicontrols and pseudoframes.
frameColor = [0.8314 0.8157 0.7843];

switch upper(command)
    case 'INIT'
        %If gui doesnt exist, create it, else refresh it.
        if isempty(h)
            %Set up a new GUI window.
            h = figure('units', 'pixels', 'position',[(screenSize(3)-x)/2 (screenSize(4)-y)/2 x y], 'MenuBar', 'none', 'NumberTitle', 'off', 'resize', 'off', 'Tag', 'doseManagementGui', 'Color', [.75 .75 .75], 'WindowButtonUpFcn', 'doseManagementGui(''FIGUREBUTTONUP'')');
            stateS.handle.doseManagementFig = h;
            set(h, 'Name','Dose Management');

            %Create pseudo frames.
            axes('Position', [.02 .05 + (rowHeight + .02) .96 .87 - (rowHeight + .02)/2], 'color', frameColor, 'ytick',[],'xtick',[], 'box', 'on');
            line([.5 .5], [0 1], 'color', 'black');
            axes('Position', [.02 .03 .96 rowHeight+.02], 'color', frameColor, 'ytick',[],'xtick',[], 'box', 'on');

            %Create controls for displaying the GUI status.
            ud.handles.status = uicontrol(h, 'units', units, 'string', 'Status:', 'Position', [.04 .03 .05 rowHeight], 'Style', 'text', 'BackgroundColor', frameColor);
            ud.handles.status = uicontrol(h, 'units', units, 'string', '', 'Position', [.1 .03 .8 rowHeight], 'Style', 'text', 'HorizontalAlignment', 'left', 'foregroundcolor', 'red', 'BackgroundColor', frameColor);
            ud.currentDose = 1;
            ud.doseBlock = 1;
            set(h, 'userdata', ud);
        end
        doseManagementGui('refresh', h);
        figure(h);

    case 'REFRESHFIELDS'
        %Refresh the field list for the current dose.
        ud = get(h, 'userdata');
        doseNum = ud.currentDose;
        set(ud.handles.name, 'string', planC{indexS.dose}(doseNum).fractionGroupID);
        set(ud.handles.units, 'string', planC{indexS.dose}(doseNum).doseUnits);
        [dA, isCompress, isRemote] = getDoseArray(doseNum, planC);
        if isCompress
            set(ud.handles.compbutton, 'string', 'Decompress');
            set(ud.handles.storageMethod, 'string', 'Memory, Compressed');
        else
            set(ud.handles.compbutton, 'string', 'Compress');
        end

        if isRemote
            set(ud.handles.remotebutton, 'string', 'Use Memory');
            set(ud.handles.storageMethod, 'string', 'On Disk');
        else
            set(ud.handles.remotebutton, 'string', 'Use Disk');
        end

        if ~isCompress & ~isRemote
            set(ud.handles.storageMethod, 'string', 'Memory');
        end
        set(ud.handles.maxdose, 'string', ud.maxDoses{doseNum});
        doseSize = getByteSize(planC{indexS.dose}(doseNum));
        set(ud.handles.dosesize, 'string', [num2str(doseSize/(1024*1024), '%6.2f') 'MB']);

    case 'REFRESH'
        %Recreate and redraw the entire doseManagementGui.
        if isempty(h)
            return;
        end

        %Save the current figure so focus can be returned.
        hOld = gcf;

        %Focus on doseManagementGui for the moment.
        set(0, 'CurrentFigure', h);
        ud = get(h, 'userdata');
        try
            %Scrap all old buttons and axes.
            delete(ud.handles.thumbaxis);
            delete(ud.handles.name);
            delete(ud.handles.dosesize);
            delete(ud.handles.storageMethod);
            delete(ud.handles.maxdose);
            delete(ud.handles.units);
            delete(ud.handles.compbutton);
            delete(ud.handles.copybutton);
            delete(ud.handles.delbutton);
            ud.handles.thumbaxis = [];
            ud.handles.name = [];
            ud.handles.dosesize = [];
            ud.handles.storageMethod = [];
            ud.handles.maxdose = [];
            ud.handles.units = [];
            ud.handles.compbutton = [];
            ud.handles.copybutton = [];
            ud.handles.delbutton = [];
        end

        i = 1;

        txtLeft = .05;
        textWidth = .13;
        fieldLeft = .35;
        fieldWidth = .13;

        %Make text to describe uicontrols.
        uicontrol(h, 'units',units,'Position',[txtLeft 1-.15 textWidth rowHeight],'String', 'Edit Dose name:', 'Style', 'text', 'horizontalAlignment', 'left', 'BackgroundColor', frameColor,'TooltipString','Change/Edit dose name string');
        uicontrol(h, 'units',units,'Position',[txtLeft 1-.21 textWidth rowHeight],'String', 'RAM Used:', 'Style', 'text', 'horizontalAlignment', 'left', 'BackgroundColor', frameColor,'TooltipString','Memory used');
        uicontrol(h, 'units',units,'Position',[txtLeft 1-.27 textWidth rowHeight],'String', 'Storage Method:', 'Style', 'text', 'horizontalAlignment', 'left', 'BackgroundColor', frameColor,'TooltipString','Tells if dose is stored on disk OR RAM');
        uicontrol(h, 'units',units,'Position',[txtLeft 1-.33 textWidth rowHeight],'String', 'Max Dose:', 'Style', 'text', 'horizontalAlignment', 'left', 'BackgroundColor', frameColor,'TooltipString','Maximum Dose Value');
        uicontrol(h, 'units',units,'Position',[txtLeft 1-.39 textWidth rowHeight],'String', 'Units:', 'Style', 'text', 'horizontalAlignment', 'left', 'BackgroundColor', frameColor,'TooltipString','Dose Units');
        uicontrol(h, 'units',units,'Position',[0.24 1-.39 textWidth rowHeight],'String', 'Scale by:', 'Style', 'text', 'horizontalAlignment', 'left', 'BackgroundColor', frameColor, 'TooltipString', 'Scale Factor');

        %Make uicontrols for managing the doses, and displaying info.
        ud.handles.name          = uicontrol(h, 'units',units,'Position',[fieldLeft-fieldWidth 1-.15+.02 fieldWidth*2 rowHeight-.01],'String','', 'Style', 'edit', 'callback', 'doseManagementGui(''NAMEFIELD'');', 'userdata', i, 'horizontalAlignment', 'right','TooltipString','Change/Edit dose name string');
        ud.handles.dosesize      = uicontrol(h, 'units',units,'Position',[fieldLeft 1-.21 fieldWidth rowHeight],'String', '',  'Style', 'text', 'horizontalAlignment', 'right', 'BackgroundColor', frameColor,'TooltipString','Memory used');
        ud.handles.storageMethod = uicontrol(h, 'units',units,'Position',[fieldLeft-.05 1-.27 fieldWidth+.05 rowHeight],'String', '',  'Style', 'text', 'horizontalAlignment', 'right', 'BackgroundColor', frameColor,'TooltipString','Tells if dose is stored on disk OR RAM');
        ud.handles.maxdose       = uicontrol(h, 'units',units,'Position',[fieldLeft 1-.33+.02 fieldWidth rowHeight-.01],'String', '', 'Style', 'edit', 'callback', 'doseManagementGui(''DOSESCALE'');', 'userdata', i, 'horizontalAlignment', 'right','TooltipString','Maximum Dose Value');
        %ud.handles.units         = uicontrol(h, 'units',units,'Position',[fieldLeft 1-.39 fieldWidth rowHeight],'String', '',  'Style', 'text', 'horizontalAlignment', 'right', 'BackgroundColor', frameColor);
        ud.handles.units         = uicontrol(h, 'units',units,'Position',[0.1 1-.39+0.02 fieldWidth-0.02 rowHeight-0.01],'String', '',  'Style', 'edit', 'callBack','doseManagementGui(''UNITFIELD'');','horizontalAlignment', 'left','TooltipString','Dose Units');
        ud.handles.scale         = uicontrol(h, 'units',units,'Position',[fieldLeft 1-.39+0.02 fieldWidth rowHeight-0.01],'String', '',  'Style', 'edit', 'callBack','doseManagementGui(''SCALEBYFACTOR'');', 'horizontalAlignment', 'left','TooltipString','Scale Factor');

        ud.handles.remotebutton  = uicontrol(h, 'units',units,'Position',[fieldLeft 1-.59 fieldWidth rowHeight],'String', 'Make Remote', 'Style', 'pushbutton', 'callback', 'doseManagementGui(''REMOTE'');', 'userdata', i,'TooltipString','Store Dose Remotely, save memory used');
        ud.handles.compbutton    = uicontrol(h, 'units',units,'Position',[fieldLeft 1-.67 fieldWidth rowHeight],'String', 'Compress', 'Style', 'pushbutton', 'callback', 'doseManagementGui(''COMPRESS'');', 'userdata', i,'TooltipString','Compress Remote Dose');
%         ud.handles.copybutton    = uicontrol(h, 'units',units,'Position',[fieldLeft 1-.75 fieldWidth rowHeight],'String','Save', 'Style', 'pushbutton', 'callback', 'doseManagementGui(''SAVE'');', 'userdata', i);
        ud.handles.delbutton     = uicontrol(h, 'units',units,'Position',[fieldLeft 1-.83 fieldWidth rowHeight],'String','Delete', 'Style', 'pushbutton', 'callback', 'doseManagementGui(''DELETE'');', 'userdata', i,'TooltipString','Delete Dose Permantely/ Save Plan to take effect');

        ud.handles.previewAxis   = axes('position', [txtLeft 1-.83 .25 .25*x/y], 'parent', h, 'box', 'on', 'ytick', [], 'xtick', [], 'buttondownfcn', 'doseManagementGui(''PREVIEWBUTTONDOWN'')');
        ud.handles.previewSliceNum = uicontrol(h, 'units',units,'Position',[fieldLeft-0.03 1-.47 fieldWidth rowHeight],'String', '',  'Style', 'text', 'horizontalAlignment', 'left', 'BackgroundColor', frameColor);

        text(.5, .6, 'After selecting a dose, ', 'fontsize', 8, 'hittest', 'off', 'parent', ud.handles.previewAxis, 'horizontalAlignment', 'center');
        text(.5, .5, 'click and drag mouse up', 'fontsize', 8, 'hittest', 'off', 'parent', ud.handles.previewAxis, 'horizontalAlignment', 'center');
        text(.5, .4, 'and down here to preview.', 'fontsize', 8, 'hittest', 'off', 'parent', ud.handles.previewAxis, 'horizontalAlignment', 'center');

        % Create Prev and Next Buttons
        nDoses = length(planC{indexS.dose});
        if nDoses > 9
            ud.handles.prev = uicontrol(h, 'units',units,'Position',[fieldLeft+0.18 1-.86 0.1 rowHeight],'String','<--', 'Style', 'pushbutton', 'callback', 'doseManagementGui(''PREV_BLOCK'');', 'TooltipString','Show Previous Set of Doses','fontWeight','bold');
            ud.handles.next = uicontrol(h, 'units',units,'Position',[fieldLeft+0.5 1-.86 0.1 rowHeight],'String','-->', 'Style', 'pushbutton', 'callback', 'doseManagementGui(''NEXT_BLOCK'');', 'TooltipString','Show Next Set of Doses','fontWeight','bold');
            uicontrol(h, 'units',units,'Position',[fieldLeft+0.3 1-.86 0.18 rowHeight+0.01],'String','Use these buttons to view more doses', 'Style', 'text', 'fontSize',8,'fontWeight','normal', 'BackgroundColor', frameColor);
        end

        set(h, 'userdata', ud);
        set(0, 'CurrentFigure', hOld);

        doseManagementGui('REFRESH_THUMBS')

    case 'PREV_BLOCK'
        ud = get(h, 'userdata');
        if ud.doseBlock == 1
            return;
        end
        ud.doseBlock = ud.doseBlock - 1;
        set(h, 'userdata', ud);
        doseManagementGui('REFRESH_THUMBS')

    case 'NEXT_BLOCK'
        ud = get(h, 'userdata');
        nDoses = length(planC{indexS.dose});
        maxDoseBlocks = ceil(nDoses/9);
        if ud.doseBlock == maxDoseBlocks
            return;
        end
        ud.doseBlock = ud.doseBlock + 1;
        set(h, 'userdata', ud);
        doseManagementGui('REFRESH_THUMBS')

    case 'REFRESH_THUMBS'

        ud = get(h, 'userdata');
        if isfield(ud.handles,'thumbaxis')
            try %To handle double-clicks on next and previous buttons
                delete(ud.handles.thumbaxis);
            catch
                %return
            end
        end

        nDoses      = length(planC{indexS.dose});

        dosesToDisplayV = (ud.doseBlock-1)*9+1:min(nDoses,ud.doseBlock*9);
        nDoses = length(dosesToDisplayV);

        if ud.currentDose > max(dosesToDisplayV)
            ud.currentDose = max(dosesToDisplayV);
        elseif ud.currentDose < min(dosesToDisplayV)
            ud.currentDose = min(dosesToDisplayV);
        end

        %Downsample colormap, redraws much faster.
        cM = CERRColorMap(stateS.optS.doseColormap);
        n  = size(cM, 1);
        newSize = 32;
        interval = (n-1) / 32;
        b = interp1(1:n, cM(:,1), 1:interval:n);
        c = interp1(1:n, cM(:,2), 1:interval:n);
        d = interp1(1:n, cM(:,3), 1:interval:n);
        ud.cM = [b' c' d'];

        %Setup thumbnail pane, with NxN axes.
        dx = 1/x; %pixel width in x,
        dy = 1/y; %pixel width in y, for margins.
        %thumbRegion = [.52 .17 .44 .75];
        thumbRegion = [.52 .23 .44 .70];
        subPlotSize = max(1,ceil(sqrt(nDoses)));
        dh = thumbRegion(4)/subPlotSize;
        dw = thumbRegion(3)/subPlotSize;
        ud.handles.thumbaxis = [];
        for i =1:subPlotSize^2
            row = subPlotSize - ceil(i/subPlotSize) + 1;
            col = mod(i-1,subPlotSize)+1;
            ud.handles.thumbaxis(i) = axes('position', [thumbRegion(1) + dw*(col-1) thumbRegion(2) + dh*(row-1) dw-dx dh-dy], 'box', 'on');
            set(ud.handles.thumbaxis(i), 'ytick',[],'xtick',[], 'color', 'black');
            colormap(ud.handles.thumbaxis(i), ud.cM);
        end

        maxDose = [];
        for i=1:nDoses
            set(ud.handles.thumbaxis(i), 'ButtonDownFcn', ['doseManagementGui(''CHANGEDOSE'', ' num2str(dosesToDisplayV(i)) ');']);
            maxDose{dosesToDisplayV(i)} = num2str(drawThumb(ud.handles.thumbaxis(i), planC, dosesToDisplayV(i), h));
            ud.previewSlice(dosesToDisplayV(i)) = 1; %%%%%%%%%%%%%%%%%
        end

        ud.maxDoses = maxDose;

        try
            set(ud.handles.previewAxis,'nextPlot','add')
            set(ud.handles.thumbaxis,'nextPlot','add')
        end

        set(h,'userdata',ud)

        if ~isempty(maxDose)
            doseManagementGui('REFRESHFIELDS');
        end

    case 'PREVIEWBUTTONDOWN'
        %Button clicked in the preview window.
        ud = get(h, 'userdata');
        ud.previewDown = 1;
        set(h, 'WindowButtonMotionFcn', 'doseManagementGui(''PREVIEWMOTION'')');
        set(h, 'userdata', ud)

    case 'FIGUREBUTTONUP'
        %Mouse up, if in preview window disable motion fcn.
        ud = get(h, 'userdata');
        if ~isfield(ud, 'previewDown') || ud.previewDown == 1
            ud.previewDown = 0;
            set(h, 'WindowButtonMotionFcn', '');
            set(h, 'userdata', ud);
        end

    case 'PREVIEWMOTION'
        %Motion in the preview, with mouse down. Change preview slice.
        ud = get(h, 'userdata');
        cp = get(h, 'currentpoint');
        if isfield(ud, 'previewY')
            if ud.previewY > cp(2)
                ud.previewSlice(ud.currentDose) = ud.previewSlice(ud.currentDose)+1;%min(ud.previewSlice(ud.currentDose)+1, size(getDoseArray(ud.currentDose), 3));
                set(h, 'userdata', ud);
                doseManagementGui('refreshpreviewandfields');
            elseif ud.previewY < cp(2)
                ud.previewSlice(ud.currentDose) = ud.previewSlice(ud.currentDose)-1;%max(ud.previewSlice(ud.currentDose)-1,1);
                set(h, 'userdata', ud);
                doseManagementGui('refreshpreviewandfields');
            end
            ud = get(h, 'userdata');
            ud.previewY = cp(2);
        else
            ud.previewY = cp(2);
        end
        set(h, 'userdata', ud);

    case 'REFRESHPREVIEWANDFIELDS'
        %Refresh both the preview and the fields.  Not modular with RefreshFields
        %to ensure that only one call to getDoseArray is made.
        ud = get(h, 'userdata');
        try
            set(ud.handles.previewAxis,'nextPlot','replace')
            set(ud.handles.thumbaxis,'nextPlot','replace')
        end
        doseNum = ud.currentDose;
        bdf = get(ud.handles.previewAxis, 'buttondownfcn');
        [dA, isCompress, isRemote] = getDoseArray(doseNum, planC);
        minSlice = 1;
        maxSlice = size(dA, 3);
        previewSlice = clip(ud.previewSlice(doseNum), minSlice, maxSlice, 'limits');
        ud.previewSlice(doseNum) = previewSlice;
        set(ud.handles.previewSliceNum, 'string', num2str(previewSlice));
        maxDose = str2num(ud.maxDoses{doseNum});
        cLim =  [0 maxDose];
        if maxDose == 0;
            cLim = [0 1];
        end
        imagesc(dA(:,:,previewSlice), 'parent', ud.handles.previewAxis, 'hittest', 'off');
        set(ud.handles.previewAxis, 'buttondownfcn', bdf, 'box', 'on', 'ytick', [], 'xtick', [], 'CLim', cLim);
        set(h, 'userdata', ud);

        %Refresh fields as well.
        set(ud.handles.name, 'string', planC{indexS.dose}(doseNum).fractionGroupID);
        set(ud.handles.units, 'string', planC{indexS.dose}(doseNum).doseUnits);
        if isCompress
            set(ud.handles.compbutton, 'string', 'Decompress');
            set(ud.handles.storageMethod, 'string', 'Memory, Compressed');
        else
            set(ud.handles.compbutton, 'string', 'Compress');
        end

        if isRemote
            set(ud.handles.remotebutton, 'string', 'Use Memory');
            set(ud.handles.storageMethod, 'string', 'On Disk');
        else
            set(ud.handles.remotebutton, 'string', 'Use Disk');
        end

        if ~isCompress & ~isRemote
            set(ud.handles.storageMethod, 'string', 'Memory');
        end

        %Refresh borders.
        set(ud.handles.thumbaxis, 'xcolor', 'black', 'ycolor', 'black');
        set(ud.handles.thumbaxis(doseNum - (ud.doseBlock-1)*9), 'xcolor', 'yellow', 'ycolor', 'yellow');

        set(ud.handles.maxdose, 'string', ud.maxDoses{doseNum});
        doseSize = getByteSize(planC{indexS.dose}(doseNum));
        set(ud.handles.dosesize, 'string', [num2str(doseSize/(1024*1024), '%6.2f') 'MB']);

        set(ud.handles.previewAxis,'nextPlot','add')
        set(ud.handles.thumbaxis,'nextPlot','add')

    case 'CHANGEDOSE'
        %New dose has been clicked on.
        ud = get(h, 'userdata');
        oldDose = ud.currentDose;
        newDose = varargin{1};
        ud.currentDose = newDose;
        set(h, 'userdata', ud);
        doseManagementGui('refreshpreviewandfields');

    case 'NAMEFIELD'
        %Dose name has changed, update in planC.
        ud = get(h, 'userdata');
        doseNum = ud.currentDose;
        doseUID = planC{indexS.dose}(doseNum).doseUID;
        oldString = planC{indexS.dose}(doseNum).fractionGroupID;
        string = get(gcbo, 'string');

%       Check for duplicate or blank names.
        if (length(string) == 0)
            warndlg('The dose name cannot be blank. Please enter a name.', 'Warning','modal');
            return;
        end
        if ~strcmp(oldString, string)
            for i = 1:length(planC{indexS.dose})
                if ischar(planC{indexS.dose}(1,i).fractionGroupID)
                    idString = planC{indexS.dose}(1,i).fractionGroupID;
                else
                    idString = num2str(planC{indexS.dose}(1,i).fractionGroupID);
                end
                if strcmpi(idString, string) && ~strcmp(idString, oldString)
                    warndlg('That plan name is already in use. Please choose another name.', 'Warning','modal');
                    return;
                end
            end
            for i = 1:length(planC{indexS.DVH})
                if ischar(planC{indexS.DVH}(1,i).planIDOfOrigin)
                    idString = planC{indexS.DVH}(1,i).planIDOfOrigin;
                else
                    idString = num2str(planC{indexS.DVH}(1,i).planIDOfOrigin);
                end
                if strcmpi(idString, string) && ~strcmp(idString, oldString)
                    warndlg('That plan name is already in use. Please choose another name.', 'Warning','modal');
                    return;
                end
            end
        end

        planC{indexS.dose}(doseNum).fractionGroupID = string;
        statusString = ['Renamed dose number ' num2str(doseNum) ' from ''' oldString ''' to ''' string '''.'];
        doseManagementGui('status', statusString);

%       Write new fractionGroupID to beam geometry
        for i = 1:length(planC{indexS.beamGeometry})
            if ischar(planC{indexS.beamGeometry}(1,i).fractionGroupID)
                idString = planC{indexS.beamGeometry}(1,i).fractionGroupID;
            else
                idString = num2str(planC{indexS.beamGeometry}(1,i).fractionGroupID);
            end
            if strcmp(idString, oldString)
                planC{indexS.beamGeometry}(1,i).fractionGroupID = string;
            end
        end

%       Write new fractionGroupID to DVH as fractionIDOfOrigin
        for i = 1:length(planC{indexS.DVH})
            if ischar(planC{indexS.DVH}(1,i).fractionIDOfOrigin)
                idString = planC{indexS.DVH}(1,i).fractionIDOfOrigin;
            else
                idString = num2str(planC{indexS.DVH}(1,i).fractionIDOfOrigin);
            end
            if strcmp(idString, oldString)
                planC{indexS.DVH}(1,i).fractionIDOfOrigin = string;
            end

            try
                if strcmpi(planC{indexS.DVH}(1,i).assocDoseUID, doseUID) && ...
                        ~isempty(planC{indexS.DVH}(1,i).planIDOfOrigin)
                    planC{indexS.DVH}(1,i).planIDOfOrigin = string;
                end
            end
        end

    case 'UNITFIELD'
        %Dose units have changed, update in planC.
        ud = get(h, 'userdata');
        doseNum = ud.currentDose;
        oldString = planC{indexS.dose}(doseNum).doseUnits;
        string = get(gcbo, 'string');
        planC{indexS.dose}(doseNum).doseUnits = string;
        statusString = ['Renamed units of dose number ' num2str(doseNum) ' from ''' oldString ''' to ''' string '''.'];
        doseManagementGui('status', statusString);

    case 'STATUS'
        %Display passed string in status bar.
        statusString = varargin{1};
        ud = get(gcbf, 'userdata');
        h = ud.handles.status;
        set(h, 'string', statusString);
        drawnow

    case 'COMPRESS'
        %Compress/decompress selected dose.
        ud = get(h, 'userdata');
        doseNum = ud.currentDose;
        doseName = planC{indexS.dose}(doseNum).fractionGroupID;

        if ~isCompressed(planC{indexS.dose}(doseNum).doseArray)
            statusString = ['Compressing dose number ' num2str(doseNum) ', ''' doseName ''' please wait...'];
            doseManagementGui('status', statusString);
            planC{indexS.dose}(doseNum).doseArray = compress(getDoseArray(doseNum, planC));
            drawThumb(ud.handles.thumbaxis(doseNum), planC, doseNum, h);
            statusString = ['Compressed dose number ' num2str(doseNum)  ', ''' doseName '''.'];
            doseManagementGui('status', statusString);
            set(ud.handles.compbutton, 'string', 'Decompress');
        else
            statusString = ['Decompressing dose number ' num2str(doseNum) ', ''' doseName ''', please wait...'];
            doseManagementGui('status', statusString);
            %Use getDoseArray and not decompress to use the cached value.
            planC{indexS.dose}(doseNum).doseArray = getDoseArray(doseNum, planC);
            maxDose = drawThumb(ud.handles.thumbaxis(doseNum), planC, doseNum, h);
            %Update the maxDoses value, but be sure to get a fresh ud since
            %a user could have clicked during compression.
            ud = get(h, 'userdata');
            ud.maxDoses{doseNum} = num2str(maxDose);
            set(h, 'userdata', ud);
            statusString = ['Decompressed dose number ' num2str(doseNum)  ', ''' doseName '''.'];
            doseManagementGui('status', statusString);
            set(ud.handles.compbutton, 'string', 'Compress');
        end
        doseManagementGui('refreshpreviewandfields');

    case 'REMOTE'
        %Make/unmake selected dose remote.
        ud = get(h, 'userdata');
        doseNum = ud.currentDose;
        doseName = planC{indexS.dose}(doseNum).fractionGroupID;

        doseUID = planC{indexS.dose}(doseNum).doseUID;

        if isLocal(planC{indexS.dose}(doseNum).doseArray)
            statusString = ['Writing to disk dose number ' num2str(doseNum) ', ''' doseName ''' please wait...'];
            doseManagementGui('status', statusString);
            [fpath,fname] = fileparts(stateS.CERRFile);
            %planC{indexS.dose}(doseNum).doseArray = setRemoteVariable(getDoseArray(doseNum, planC), 'LOCAL',[fpath,'\',fname,'_store'],['doseArray_',doseName,'.mat']);
            planC{indexS.dose}(doseNum).doseArray = setRemoteVariable(getDoseArray(doseNum, planC), 'LOCAL',fullfile(fpath,[fname,'_store']),['doseArray_',doseUID,'.mat']);
            drawThumb(ud.handles.thumbaxis(doseNum), planC, doseNum, h);
            statusString = ['Wrote to disk dose number ' num2str(doseNum)  ', ''' doseName '''.'];
            doseManagementGui('status', statusString);
            set(ud.handles.remotebutton, 'string', 'Use Memory');
            uiwait(msgbox(['doseArray stored in folder ',fullfile(fpath,[fname,'_store']),'Note the Location','modal']))

        else
            statusString = ['Reading from disk dose number ' num2str(doseNum) ', ''' doseName ''', please wait...'];
            doseManagementGui('status', statusString);

            remotePath = planC{indexS.dose}(doseNum).doseArray.remotePath;
            filenam = planC{indexS.dose}(doseNum).doseArray.filename;
            %Use getDoseArray and not decompress to use the cached value.
            planC{indexS.dose}(doseNum).doseArray = getDoseArray(doseNum, planC);

            stateS.reqdRemoteFiles(strcmp(fullfile(remotePath,filenam),stateS.reqdRemoteFiles)) = [];
            delete(fullfile(remotePath,filenam))

            %remove remote storage directory if it is empty
            dirRemoteS = dir(remotePath);
            if ~any(~cellfun('isempty',strfind({dirRemoteS.name},'.mat')))
                rmdir(remotePath)
            end
            maxDose = drawThumb(ud.handles.thumbaxis(doseNum), planC, doseNum, h);
            statusString = ['Read from disk dose number ' num2str(doseNum)  ', ''' doseName '''.'];
            doseManagementGui('status', statusString);
            set(ud.handles.remotebutton, 'string', 'Use Disk');

            %Update the maxDoses value, but be sure to get a fresh ud since
            %a user could have clicked during remote writing to disk.
            ud = get(h, 'userdata');
            ud.maxDoses{doseNum} = num2str(maxDose);
            set(h, 'userdata', ud);
        end
        doseManagementGui('refreshpreviewandfields');

    case 'SAVE'
        %Open dialog to save dose array as .mat file.
        ud = get(h, 'userdata');
        doseNum = ud.currentDose;
        doseName = planC{indexS.dose}(doseNum).fractionGroupID;
        [filename, pathname] = uiputfile('*.mat', ['Save (uncompressed) dose array number ' num2str(doseNum) ' as:']);
        if filename==0
            return;
        end
        dose3D = getDoseArray(doseNum, planC);
        save(fullfile(pathname, filename), 'dose3D');
        statusString = ['Saved dose number ' num2str(doseNum) ', ''' doseName ''' to ' [filename '.mat'] '.'];
        doseManagementGui('status', statusString);

    case 'DELETE'
        %Delete selected dose.  If being displayed, verify deletion with user.
        ud = get(h, 'userdata');
        doseNum = ud.currentDose;
        doseName = planC{indexS.dose}(doseNum).fractionGroupID;

        refreshViewer = 0;
        axesV = checkDisplayedDoses(doseNum);
        if ~isempty(axesV)
            choice = questdlg('One or more CERR axes are currently displaying this dose.  If you delete it, these axes will be set to display no dose.  Proceed?', 'Continue?', 'Continue', 'Abort', 'Continue');
            if strcmpi(choice, 'Abort')
                statusString = ['Delete aborted.'];
                doseManagementGui('status', statusString);
                return;
            else
                %Set the axes dose value to null.
                setAxisDoseToNull(axesV);
            end
        end

        if stateS.doseSet == doseNum
            stateS.doseSet = [];
        end
        del = questdlg(['Are you sure you want to delete dose number' num2str(doseNum) ', ''' doseName '''?'], 'Continue?', 'Continue', 'Abort', 'Continue');
        if strcmpi(del, 'Continue')
            statusString = ['Deleted dose number ' num2str(doseNum) ', ''' doseName '''.'];
            doseManagementGui('status', statusString);
            planC{indexS.dose}(doseNum) = [];
            %If dose below displayed dose deleted, its number has changed.
            if doseNum < stateS.doseSet
                stateS.doseSet = stateS.doseSet - 1;
            end
            refreshViewer = 1;
            updateAxesForDeletedDose(doseNum);
            doseManagementGui;
        else
        end

        % Delete colorbar children if plan contains no dose
        if length(planC{indexS.dose}) == 0
            delete(get(stateS.handle.doseColorbar.trans, 'children'));
        end

        %Refresh CERR axes in the case of changed dose sets.
        if refreshViewer
            sliceCallBack('refresh');
        end

    case 'DOSESCALE'
        ud          = get(h, 'userdata');
        doseNum     = ud.currentDose;
        doseName    = planC{indexS.dose}(doseNum).fractionGroupID;
        newMaxDose  = str2num(get(gcbo, 'string'));

        %Get the dose array and its compression state.
        [dA, isCompress, isRemote] = getDoseArray(doseNum, planC);

        maxDose = max(dA(:));
        if maxDose == 0
            set(gcbo, 'string', '0')
            statusString = ['Unable to rescale all zero dose distribution.'];
            doseManagementGui('status', statusString);
            return;
        end

        doseManagementGui('status', 'Rescaling dose, please wait...');

        if isCompress | isRemote
            statusString = ['Rescaling compressed or remote dose can take a moment, please wait...'];
            doseManagementGui('status', statusString);
        end

        %Perform the rescale.
        dA = dA *  (1/maxDose * newMaxDose);

        oldDoseUID = planC{indexS.dose}(doseNum).doseUID;

        % set new dose UID
        planC{indexS.dose}(doseNum).doseUID = createUID('DOSE');

        % update doseArray in dose struct.
        planC = setDoseArray(doseNum, dA, planC);

        % remove old remote file if it exists
        if ~isLocal(planC{indexS.dose}(doseNum).doseArray)
            if ~ismember(fullfile(planC{indexS.dose}(doseNum).doseArray.remotePath,['doseArray_',oldDoseUID,'.mat']),stateS.reqdRemoteFiles)
                delete(fullfile(planC{indexS.dose}(doseNum).doseArray.remotePath,['doseArray_',oldDoseUID,'.mat']))
            end
        end

        statusString = ['Rescaled dose number ' num2str(doseNum) ', ''' doseName ''' from [0 ' num2str(maxDose) '] Gy to [0 ' num2str(newMaxDose) '] Gy.'];
        ud.maxDoses{doseNum} = num2str(newMaxDose);
        set(h, 'userdata', ud);

        % update dose UID's for CERR axes
        for i = 1:length(stateS.handle.CERRAxis)
            if getAxisInfo(stateS.handle.CERRAxis(i),'doseSets') == doseNum
                setAxisInfo(stateS.handle.CERRAxis(i),'doseSets',doseNum)
            end
        end

        stateS.doseSetChanged = 1;
        stateS.CTDisplayChanged = 1;
        CERRRefresh
        doseManagementGui('status', statusString);

    case 'SCALEBYFACTOR'
        ud          = get(h, 'userdata');
        doseNum     = ud.currentDose;
        doseName    = planC{indexS.dose}(doseNum).fractionGroupID;
        scale       = str2num(get(gcbo, 'string'));
        if isempty(scale) | ~isnumeric(scale)
            return
        end

        %Get the dose array and its compression state.
        [dA, isCompress, isRemote] = getDoseArray(doseNum, planC);

        doseManagementGui('status', 'Scaling dose, please wait...');

        if isCompress | isRemote
            statusString = ['Scaling compressed or remote dose can take a moment, please wait...'];
            doseManagementGui('status', statusString);
        end

        %Perform the rescale.
        dA = dA *  scale;
        set(ud.handles.maxdose,'string',num2str(max(dA(:))))

        statusString = ['Rescaled dose number ' num2str(doseNum) ', ''' doseName ''' by a factor of ' num2str(scale)];

        oldDoseUID = planC{indexS.dose}(doseNum).doseUID;

        % set new dose UID
        planC{indexS.dose}(doseNum).doseUID = createUID('DOSE');

        % update doseArray in dose struct.
        planC = setDoseArray(doseNum, dA, planC);

        % remove old remote file if it exists
        if ~isLocal(planC{indexS.dose}(doseNum).doseArray)
            if ~ismember(fullfile(planC{indexS.dose}(doseNum).doseArray.remotePath,['doseArray_',oldDoseUID,'.mat']),stateS.reqdRemoteFiles)
                delete(fullfile(planC{indexS.dose}(doseNum).doseArray.remotePath,['doseArray_',oldDoseUID,'.mat']))
            end
        end

        ud.maxDoses{doseNum} = num2str(str2num(ud.maxDoses{doseNum})*scale);
        set(h, 'userdata', ud);

        % update dose UID's for CERR axes
        for i = 1:length(stateS.handle.CERRAxis)
            if  getAxisInfo(stateS.handle.CERRAxis(i),'doseSets') == doseNum
                setAxisInfo(stateS.handle.CERRAxis(i),'doseSets',doseNum)
            end
        end

        stateS.doseSetChanged = 1;
        stateS.CTDisplayChanged = 1;
        CERRRefresh
        doseManagementGui('status', statusString);

    case 'QUIT'
        close;
end

return;

function nBytes = getByteSize(data)
%"getByteSize"
%Returns the number of bytes in the passed data
infoStruct = whos('data');
nBytes = infoStruct.bytes;
return;

function maxDose = drawThumb(hAxis, planC, index, hFigure)
%"drawThumb"
%In passed dose array, find slice with highest dose and draw in hAxis.
%Also denote the index in the corner.  If compressed show compressed.
set(hFigure, 'CurrentAxes', hAxis);
toDelete = get(hAxis, 'children');
delete(toDelete);

%Get the dose array and its compression state.
[dA, isCompress, isRemote] = getDoseArray(index, planC);

bdf = get(hAxis, 'buttondownfcn');

maxDose = arrayMax(dA);
maxLoc = find(dA == maxDose);
[r,c,s] = ind2sub(size(dA), maxLoc(1));
thumbImage = dA(:,:,s(1));
imagesc(thumbImage, 'hittest', 'off', 'parent', hAxis);
set(hAxis, 'ytick',[],'xtick',[]);
if isCompress && isRemote
    text(.1, .1, 'Compressed', 'units', 'normalized', 'fontsize', 8, 'color', 'black', 'horizontalAlignment', 'left', 'hittest', 'off', 'parent', hAxis);
    text(.1, .2, 'Remote', 'units', 'normalized', 'fontsize', 8, 'color', 'black', 'horizontalAlignment', 'left', 'hittest', 'off', 'parent', hAxis);
elseif isRemote
    text(.1, .1, 'Remote', 'units', 'normalized', 'fontsize', 8, 'color', 'black', 'horizontalAlignment', 'left', 'hittest', 'off', 'parent', hAxis);
elseif isCompress
    text(.1, .1, 'Compressed', 'units', 'normalized', 'fontsize', 8, 'color', 'black', 'horizontalAlignment', 'left', 'hittest', 'off', 'parent', hAxis);
end

xLim = get(hAxis, 'xlim');
yLim = get(hAxis, 'ylim');
x = (xLim(2) - xLim(1)) * .87 + xLim(1);
y = (yLim(2) - yLim(1)) * .15 + yLim(1);
text(x, y, num2str(index), 'fontsize', 8, 'color', 'white', 'hittest', 'off', 'parent', hAxis);
set(hAxis, 'buttondownfcn', bdf);
axis ij;
drawnow;
return;

function [nAxesV] = checkDisplayedDoses(doseNum)
%"checkDisplayedDoses"
%   Check to see if any CERR axes are displaying the requested dose num.
%   Returns the numbers of any axes that are.

global planC stateS

nAxesV = [];

%Iterate over axes.
for i=1:length(stateS.handle.CERRAxis)
    %Get axis info for this axis.
    %aI = get(stateS.handle.CERRAxis(i), 'userdata');
    aI = stateS.handle.aI(i);
    if ismember(doseNum, aI.doseSets)
        nAxesV = union(nAxesV, i);
    end
end
return;

function setAxisDoseToNull(nAxesV)
%"setAxisDoseToNull"
%   Sets the passed axis number's userdata doseUID fields to null if they
%   were using 'manual'.

global planC stateS

%Iterate over axes.
for i=1:length(nAxesV)
    %Get axis info for this axis.
    %aI = get(stateS.handle.CERRAxis(nAxesV(i)), 'userdata');
    aI = stateS.handle.aI(nAxesV(i));
    if strcmpi(aI.doseSelectMode, 'manual');
        aI.doseSets = [];
        stateS.handle.aI(nAxesV(i)) = aI;
    end
end
return;

function updateAxesForDeletedDose(delIndex)
%"updateAxesForDeletedDose"
%   Shifts all doseNums being displayed in CERR axes to account for deleted
%   dose distributions, given the number of the deleted dose.

global planC stateS
indexS = planC{end};

nAxesV = [];

%Iterate over axes.
for i=1:length(stateS.handle.CERRAxis)
    %Get axis info for this axis.
    %aI = get(stateS.handle.CERRAxis(i), 'userdata');
    aI = stateS.handle.aI(i);

    % DK
    aI.doseSets = aI.doseSets(aI.doseSets > delIndex) - 1;
%     doseSet = getAssociatedDose(aI.doseSets);
%     doseSet = doseSet(doseSet > delIndex)- 1;
%     if doseSet~=0
%         aI.doseSets = planC{indexS.dose}(doseSet).doseSets;
%     else
%         aI.doseSets = [];
%     end
    % DK

    stateS.handle.aI(i) = aI;
end
return;


%% Set path to iFEM
%
% Add all subdirectories under pathstr to search path.
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

addpath(genpath(pwd),'-begin');
savepath;


function caxisChange(inputLimits,varargin)
	% caxis wrapper to also change colorbar range to be correct automatically.
	% Biafra Ahanonu
	% started: 2019.10.08 [19:15:59]
	% inputs
		% inputLimits - [lowerLimit upperLimit] vector
	% outputs
		%

	ciapkg.view.caxisChange(inputLimits,'passArgs', varargin);
end


fprintf('Compiling mex functions\n');
mex -largeArrayDims maskmult.c
mex -largeArrayDims setsparseentries.c


function varargout = ge_html(varargin)
% GE_HTML M-file for ge_html.fig
%      GE_HTML, by itself, creates a new GE_HTML or raises the existing
%      singleton*.
%
%      H = GE_HTML returns the handle to a new GE_HTML or the handle to
%      the existing singleton*.
%
%      GE_HTML('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in GE_HTML.M with the given input arguments.
%
%      GE_HTML('Property','Value',...) creates a new GE_HTML or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before ge_html_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to ge_html_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help ge_html

% Last Modified by GUIDE v2.5 03-Aug-2011 16:39:30

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @ge_html_OpeningFcn, ...
                   'gui_OutputFcn',  @ge_html_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before ge_html is made visible.
function ge_html_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to ge_html (see VARARGIN)

% Open ActiveX-Control from Microsoft-Internet-Explorer
handles.ie = actxcontrol('Shell.Explorer.2',[2 2 996 700 ]);

% Choose default command line output for ge_html
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes ge_html wait for user response (see UIRESUME)
% uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = ge_html_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;

% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Navigate to the html;
% Navigate(handles.ie,'C:\Users\sk\Documents\MATLAB\ge_ma.html');

% locate to the ge_ma.html
[FileName,PathName,FilterIndex] = uigetfile('*.html','open GE-html ') ;
if isequal(FileName,0)
   disp('User selected Cancel')
else
   Navigate(handles.ie,[PathName, FileName]);
end;

% Wait for initialising
pause(4);   % if pause is too short so that Matlab produce error, take a little more time

% Get the Document
handles.myDoc = handles.ie.Document;

% Update handles structure
guidata(hObject, handles);

% --- Executes on button press in pushbutton2.
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% show/ hide borders
handles.myDoc.parentWindow.execScript('toggleBorders()', 'Jscript');

% --- Executes on button press in pushbutton3.
function pushbutton3_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.myDoc.parentWindow.execScript('toggleRotation()', 'Jscript');

% --- Executes on button press in pushbutton4.
function pushbutton4_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton4 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.myDoc.parentWindow.execScript('toggleNav()', 'Jscript');

% --- Executes on button press in pushbutton5.
function pushbutton5_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton5 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.myDoc.parentWindow.execScript('toggleRoads()', 'Jscript');

% --- Executes on button press in pushbutton6.
function pushbutton6_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton6 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.myDoc.parentWindow.execScript('showBuildings()', 'Jscript');

% --- Executes on button press in pushbutton7.
function pushbutton7_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton7 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.myDoc.parentWindow.execScript('hideBuildings()', 'Jscript');

function edit1_Callback(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit1 as text
%        str2double(get(hObject,'String')) returns contents of edit1 as a double

% --- Executes during object creation, after setting all properties.
function edit1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in pushbutton8.
function pushbutton8_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton8 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

searchStr = get(handles.edit1,'String');
handles.myDoc.parentWindow.execScript(['findmyaddress(''',searchStr ,''')' ], 'Jscript');


function [] = display_stop_reason(epoch, infos, options, disp_name, reason, max_reached_flag)
% Function to display stop reason
%
% This file is part of NMFLibrary.
%
% Created by H.Kasai on July 14, 2022
%

    if options.verbose > 0

        if options.verbose == 1 && ~max_reached_flag
            fprintf(' (incomplete)\n');
        end

        fprintf('# %s: %s', disp_name, reason);
    end

end


function  status = writeascii(filename, l)

% status = writeascii(filename, l)
% write each line of list l into an ASCII file filename

status = 0;
fid = fopen(filename, 'w');

if fid ~= -1
	for i=1:length(l)
		line = get(l,i);
		fprintf(fid, ['%s \n'], line);
	end
	fclose(fid);
else
	status = -1;
end