www.gusucode.com > mbcmodels 工具箱 matlab 源码程序 > mbcmodels/mv_DialUp.m

    function varargout= mv_DialUp(Action,varargin)
%MV_DIALUP Surface plot/table generator for viewing global models
%

%  Copyright 2000-2016 The MathWorks, Inc. and Ford Global Technologies, Inc.


switch lower(Action)
    case 'create'
        [varargout{1:2}]= i_Create(varargin{:});
    case 'close'
        % Make invisible for now, so default values can be retrieved
        % Figure is deleted when base model is changed or on Exit Main GR
        set(gcbf,'Visible','off');
    case 'table'
        % Produce UITable of Values
        i_DrawTable(gcbf);
    case 'checkvals'
        % check values entered in edit boxes
        i_CheckVals(varargin{:})
    case 'export'
        % Export Matrix to Workspace
        i_Export(varargin{:});
    case 'replay'
        % Replay Movie
        i_Replay;
    case 'exclusive'
        i_Exclusive(varargin{:});
        i_DisplayType(varargin{1})
    case {'display','modelselect','view','plot'}
        % display called from datum checkbox
        i_Display(varargin{:})
    case {'displaytype'}
        i_DisplayType(varargin{:})
    case 'pethreshold'
        i_PEthreshold(varargin{:});
    case 'print'
        i_Print(varargin{:});
    case 'updateranges'
        iUpdateRanges(varargin{:});
end

%-------------------------------------------------------------------
% SUBFUNCTION i_Create
%-------------------------------------------------------------------
function [Tool, mainPane] = i_Create(hParent,m,p,RememberSettings)
% creates a layout = mainPane with lots of bits inside
% returns mainPane unpacked and invisible

if nargin<3
    p= get(MBrowser,'currentnode');
end
if nargin<4
    RememberSettings = true;
end

Tool.Name= 'Response &Surface';
Tool.mfile= mfilename;
Tool.MultiSelect=0;
Tool.Icon = 'dialup.bmp';
Tool.model = m;
yi= yinfo(m);
Tool.RespName= yi.Name;
Tool.Renderer='zbuffer';
Tool.RememberSettings= RememberSettings;
Tool.PanelPos = [];

% only update ranges for localmulti models
Tool.DoUpdateRanges = isa(m,'localmulti');
labels= get(m,'symbol');
isTwoStage= isa(m,'xregtwostage');
nf= nfactors(m);

% title for listctrl
listCtrlTitle = uicontrol('Parent', hParent,...
    'Style','text',...
    'Visible','off',...
    'String','Input factors:',...
    'HorizontalAlignment','left');
% make a xreglistctrl object
hnd.listCtrl = xreglistctrl(hParent,...
    'cellborder',2,...
    'border',4,...
    'Visible','off',...
    'cellheight',22,...
    'userdata',[]);

% -------------------------------------
%      Factor Selectors
% -------------------------------------
hnd.factor(1)=uicontrol('Style','popupmenu',...
    'Parent',hParent,...
    'String',' ',...
    'BackgroundColor','w',...
    'Visible','off',...
    'Value',1,...
    'Tag','1');
hnd.text(1)=uicontrol('Style','text',...
    'Parent',hParent,...
    'String','X-axis factor:',...
    'Visible','off',...
    'UserData',{});
hnd.factor(2)=uicontrol('Style','popupmenu',...
    'Parent',hParent,...
    'String',' ',...
    'Value',min(2,nf),...
    'BackgroundColor','w',...
    'Visible','off',...
    'UserData',0,...
    'Tag','2');
hnd.text(2)=uicontrol('Style','text',...
    'Parent',hParent,...
    'String','Y-axis factor:',...
    'Visible','off',...
    'UserData',{});
hnd.factor(3)=uicontrol('Style','popupmenu',...
    'Parent',hParent,...
    'String',' ',...
    'Value',min(3,nf),...
    'BackgroundColor','w',...
    'Visible','off',...
    'Tag','3');
hnd.text(3)=uicontrol('Style','text',...
    'Parent',hParent,...
    'String','Time factor:',...
    'Visible','off',...
    'UserData',{});
% Deal with type 2 input factors
% userdata of factors holds ListCtrl indices
set(hnd.factor,'String',labels,...
    'UserData',1:length(labels));
set(hnd.factor(1),'Callback',@(s,e) mv_DialUp('exclusive',hParent,1))
if nf>=2
    set(hnd.factor(2),'Callback',@(s,e) mv_DialUp('exclusive',hParent,2));
end
if nf>=3
    set(hnd.factor(3),'Callback',@(s,e) mv_DialUp('exclusive',hParent,3));
end

% Check Box to user absolute value of local variable
if isTwoStage && get(m,'DatumType')
    hnd.AbsX=uicontrol('Parent',hParent,...
        'Visible','off',...
        'Style','checkbox',...
        'String',['Display using (',labels{1},' - datum)'],...
        'Callback',@(s,e) i_DisplayType(hParent),...
        'Value',0);
    PEenable='on';
else
    PEenable='on';
    hnd.AbsX=[];
end

hnd.Constraints=uicontrol('Parent',hParent,...
    'Visible','off',...
    'Style','checkbox',...
    'String','Display boundary constraint',...
    'Callback',@(s,e) i_DisplayType(hParent),...
    'Value',1);
if isempty(iGetBoundaryModel(m,p))
     set(hnd.Constraints,'Enable','off','Value',0);
end





% -------------------------------------
%      Plot type controls + buttons
% -------------------------------------

choiceFrame=mbcgui.container.layoutpanel(...
    'Tag','DialupChoicePanel',...
    'Parent', hParent,...
    'Visible','off',...
    'BorderType', 'etchedin', ...
    'Title','Display type');

% SEE WHICH PLOTS WILL BE POSSIBLE
n= nf;
%note: size includes text controls = none-value controls
if n<2
    DisplayTypes= {'Table','2-D Plot'};
    InitVal=2;
elseif n<3
    DisplayTypes= {'Table','2-D Plot','Multiline Plot','Contour Plot','Surface Plot'};
    InitVal=5;
else
    DisplayTypes= {'Table','2-D Plot','Multiline Plot','Contour Plot','Surface Plot','Movie'};
    InitVal=5;
end

hnd.dispType = uicontrol('Parent',choiceFrame,...
    'Style','listbox',...
    'String',DisplayTypes,...
    'BackgroundColor','w',....
    'Value',InitVal,...
    'Callback',@(s,e) i_DisplayType(hParent));

% -------------------------------------
%   Controls specific to each plot type
% -------------------------------------
% Check Box for surface PE colouring
hnd.PEcol=uicontrol('Parent',choiceFrame,...
    'Visible','off',...
    'Style','checkbox',...
    'String','Prediction Error shading',...
    'Callback',@(s,e) mv_DialUp('Display',hParent),...
    'Enable',PEenable,...
    'Value',0);
hnd.PEthresh=xregGui.labelcontrol('parent',choiceFrame,...
    'ControlSize',70,...
    'string','Prediction Error threshold:',...
    'visible','off',...
    'Control',uicontrol('Parent',choiceFrame,...
    'Visible','off',...
    'Style','edit',...
    'BackgroundColor','w',...
    'Callback',@(s,e) mv_DialUp('PEthreshold',hParent) ));

String  = {'Contours...','Replay'};
CallBack= {{@i_EditContours, hParent},{@i_Replay, hParent}};
for i=1:length(String);
    hnd.Btns(i)= uicontrol('Parent',choiceFrame,...
        'Visible','off',...
        'Style','push',...
        'String',String{i},...
        'Callback',CallBack{i});
end
% Contour properties
udv.V=[];
udv.labels=1;
udv.fill=0;
set(hnd.Btns(1),'UserData',udv,...
    'Callback',{@i_EditContours, hParent});

hnd.framePS=xregGui.labelcontrol('parent',choiceFrame,...
    'visible','off',...
    'ControlSize',50,...
    'string','Frames/second:',...
    'Control',mbcgui.widget.Spinner('Parent', choiceFrame,...
    'Visible','off',...
    'Min',1,...
    'Max',20,...
    'Value',2,...
    'ClickIncrement',1));


%  Create the Export section
exportFrame=mbcgui.container.layoutpanel(...
    'Tag','DialupExportPanel',...
    'Parent', hParent,...
    'Visible','off',...
    'BorderType', 'etchedin', ...
    'Title','Export model values');
hnd.exportRadios=xregGui.rbgroup(exportFrame,'nx',1,'ny',2,'value',[1; 0],...
    'string',{'Export to workspace';'Export to mat file...'});
export.text1=uicontrol('Style','text',...
    'String','Save input as:',...
    'HorizontalAlignment','left',...
    'Parent',exportFrame);
hnd.exportName1=uicontrol('Style','edit',...
    'BackgroundColor',[1 1 1],...
    'HorizontalAlignment','left',...
    'String','X',...
    'Parent',exportFrame);
export.text2=uicontrol('Style','text',...
    'String','Save result as:',...
    'HorizontalAlignment','left',...
    'Parent',exportFrame);
hnd.exportName2=uicontrol('Style','edit',...
    'BackgroundColor',[1 1 1],...
    'HorizontalAlignment','left',...
    'String','Y',...
    'Parent',exportFrame);
hnd.exportButton=uicontrol('Parent',exportFrame,...
    'Style','push',...
    'String','Export',...
    'Callback',{@i_Export,hParent});

% -------------------------------------
%     TABLE for viewing data
% -------------------------------------
Tool.TablePos= [1 1 100 100];

% only create table on first viewing
hnd.DispTable=[];
hnd.ColorBar= [];
% -------------------------------------
%     AXES for viewing data
% -------------------------------------
hnd.Axes=axes('Parent',hParent,...
    'Units','pixels',...
    'Box','on',...
    'Visible','off');
set(hnd.Axes,'BoxStyle','full')
hnd.axisPanel = mbcgui.widget.AxesPanel(...
    'AxesHandle', hnd.Axes, ...
    'Border', [65 40 50 20]);

ux= uicontextmenu('Parent',ancestor(hParent, 'figure'));
set(hnd.Axes,'UIContextMenu',ux);
xregdialupmenu('init',hnd.Axes);

% ============ set up layouts ====================
PEcard = xreggridbaglayout(choiceFrame,...
    'packstatus','off',...
    'dimension',[3 1],...
    'rowsizes',[-1 20 20],...
    'gapy',2,...
    'elements',{[],hnd.PEcol,hnd.PEthresh});
CONTcard = xreggridbaglayout(choiceFrame,...
    'dimension',[2 2],...
    'rowsizes',[-1 25],...
    'colsizes',[-1 65],...
    'elements',{[],[],[],hnd.Btns(1)});
MOVIEcard = xreggridbaglayout(choiceFrame,...
    'dimension',[4 2],...
    'colsizes',[-1 65],...
    'rowsizes',[-1 2 20 3],...
    'gapx',10,...
    'mergeblock',{[2 4],[2 2]},...
    'elements',{[],[],hnd.framePS,[],[],hnd.Btns(2),[],[]});
% card layout for PEcol, contour, replay
hnd.controlsCard = xregcardlayout(choiceFrame,...
    'numcards',5,...
    'currentcard',InitVal);
attach(hnd.controlsCard, PEcard, 3);
attach(hnd.controlsCard, CONTcard, 4);
attach(hnd.controlsCard, MOVIEcard, 5);

% listbox and cardLayout
hnd.insideChoice = xreggridbaglayout(choiceFrame,...
    'dimension',[2 1],...
    'rowsizes',[-1 47],...
    'border', [10 10 10 5], ...
    'elements',{hnd.dispType,hnd.controlsCard});
set(choiceFrame, 'LayoutComponent', {hnd.insideChoice});

% frame for export controls
exptop = xreggridbaglayout(exportFrame,...
    'dimension',[4 2],...
    'rowsizes',[35 -1 15 20],...
    'gapx',10,...
    'mergeblock',{[1 1],[1 2]},...
    'elements',{hnd.exportRadios,[],export.text1,hnd.exportName1,...
    [],[],export.text2,hnd.exportName2});
exp = xreggridbaglayout(exportFrame,...
    'dimension',[2 2],...
    'rowsizes',[-1 25],...
    'colsizes',[-1 65],...
    'gapy',10,...
    'border', [10 10 10 5], ...
    'mergeblock',{[1 1],[1 2]},...
    'elements',{exptop,[],[],hnd.exportButton});
set(exportFrame, 'LayoutComponent', {exp});

% the pane for graphs/tables
hnd.ColorBar = mbcwidgets.ColorBar('parent', hParent, ...
    'visible', 'off', ...
    'RangeEditable', false);
set(hnd.ColorBar,'UserData',...
    [mbcgui.hgclassesutil.proplistener(ancestor(hnd.Axes,'figure'),'ColorMap', 'PostSet', mbcutils.callback(@i_setcolormap, hnd.ColorBar));
    mbcgui.hgclassesutil.proplistener(hnd.Axes, 'CLim', 'PostSet', mbcutils.callback(@i_setcolorbarclim, hnd.ColorBar));
    mbcgui.hgclassesutil.proplistener(hnd.Axes, 'CLimMode', 'PostSet', mbcutils.callback(@i_setcolorbarclim, hnd.ColorBar))]);

hnd.ColorBarCard = xregcardlayout(hParent, ...
    'numcards', 2, ...
    'border', [0 20 0 20]);
attach(hnd.ColorBarCard, hnd.ColorBar, 2);

hnd.AxesLayout = xreggridlayout(hParent,...
    'visible','off',...
    'dimension',[1,2],...
    'correctalg','on',...
    'elements',{hnd.axisPanel,hnd.ColorBarCard},...
    'colsizes',[-1 0]);

hnd.displayPane = xregcardlayout(hParent,...
    'visible','off');
attach(hnd.displayPane, hnd.AxesLayout, 2);
rhspane= xreggridbaglayout(hParent,...
    'dimension',[5 5],...
    'rowsizes',[-1 15 15 2 22],...
    'colsizes',[-1 90 90 90 -1],...
    'gapx',20,...
    'mergeblock',{[1 1],[1 5]},...
    'elements',{hnd.displayPane,[],[],[],[],...
    [],[],hnd.text(1),[],hnd.factor(1),...
    [],[],hnd.text(2),[],hnd.factor(2),...
    [],[],hnd.text(3),[],hnd.factor(3)});

mainPane = xreggridbaglayout(hParent,...
    'visible','off',...
    'dimension',[8,2],...
    'gapy',2,...
    'gapx',20,...
    'rowsizes',[15, -1 20 20 5 -1 7 140],...
    'colratios',[.3 .7],...
    'mergeblock',{[1 8],[2 2]},...
    'border',[10 10 10 10],...
    'elements',{listCtrlTitle,hnd.listCtrl,...
    hnd.AbsX,hnd.Constraints,[],choiceFrame,[],exportFrame,rhspane});

Tool.Hand=hnd;
Tool.Movie=[];
Tool.helpmenus={'&Response Surface Help','xreg_modSel_surface'};

if Tool.DoUpdateRanges
    % sort out initial ranges
    iUpdateRanges(hParent,Tool,m,p,true)
else
    iInitType(hParent,Tool,m,p)
end

%-------------------------------------------------------------------
% SUBFUNCTION i_GetValues (not *check* vals!!)
%-------------------------------------------------------------------
function [x,XVar,YVar,TVar]=i_GetValues(Tool,Check)
% call with 2 args and Check=0 returns new factor values
% WITHOUT checking single valuedness
% x = input data
% XVar = number of factor (from listctrl) for x-coords

% the handles
h=Tool.Hand;

x= get(h.listCtrl,'Values');

[XVar,YVar,TVar] = i_GetFactors(Tool);
factors = [XVar,YVar,TVar];


% Check that non X,Y,T variables must be scalar
if nargin < 2 || Check
    Str= get(h.listCtrl,'Name');
    for i= 1:length(x)
        x{i}=x{i}(:);
        if ~any(i==factors) && length(x{i})>1 
            errordlg(['A single value is required for ',Str{i}],...
                'Plot Error','modal');
            XVar=[]; % signals error
            return
        end
    end
end

%-------------------------------------------------------------------
% SUBFUNCTION i_GetFactors (not *check* vals!!)
%-------------------------------------------------------------------
function [XVar,YVar,TVar] = i_GetFactors(Tool)
% for current factor selections, returns the relevant
% input control indices from the ListCtrl.

h=Tool.Hand;

XVals = get(h.factor(1),'UserData');
YVals = get(h.factor(2),'UserData');
TVals = get(h.factor(3),'UserData');

XVar = XVals(get(h.factor(1),'Value'));
YVar=[]; TVar=[];

nf = nfactors(Tool.model);
if nf>1
    YVar = YVals(get(h.factor(2),'Value'));
    if XVar==YVar
        YVar= find(~ismember( 1:nf, XVar) );
        YVar= YVar(1);
        set(h.factor(2),'Value',YVar)
    end

end
if nf>2
    TVar = TVals(get(h.factor(3),'Value'));

    if TVar==YVar || TVar==XVar
        TVar= find(~ismember( 1:nf, [XVar YVar]) );
        TVar= TVar(1);
        set(h.factor(3),'Value',TVar)
    end

end

switch get(h.dispType,'Value')
    case 1
        % table
        TVar=[];
        if size(h.listCtrl)<2
            YVar=[];
        end
    case 2
        % 2-D plot
        YVar=[];
        TVar=[];
    case {3,4,5}
        % multi-line, contour, surface
        TVar=[];
end



%-------------------------------------------------------------------
% SUBFUNCTION i_CheckVals
%-------------------------------------------------------------------
function i_CheckVals(~, evt, hParent )

Tool= i_GetTool( hParent );
num = evt.ListIndex;
h = Tool.Hand;

% Check for too many plot points
x = i_GetValues(Tool);

numPoints = prod(cellfun('length',x));
DispType= get(h.dispType,'Value');
switch DispType
    case '1' % table
        if numPoints > 10000
            errordlg('Too many plot points requested for a table. Please input a smaller number.',...
                'Plot error','modal');
            return
        end
    otherwise
        if numPoints > 1000000
            errordlg('Too many plot points requested. Please input a smaller number.',...
                'Plot error','modal');
            return
        end
end

controls = get(h.listCtrl,'controls');
% get new expression
x = get(controls{num},'Value');

if ischar(x) ...
        || isempty(x) ...
        || ~isa(x,'double') ...
        || ~ismatrix(x) ...
        || ~any(size(x)==1) ...
        || ~isreal(x)
    errordlg('Some inputs not numeric. Input controls should catch this.',...
        'Plot Error','modal');
    return
else
    i_Display(hParent);
end

%-------------------------------------------------------------------
% SUBFUNCTION i_Exclusive
%-------------------------------------------------------------------
function i_Exclusive(hFig,factorNum)
% exclusive factor choice from popupmenu selectors
[Tool,m]= i_GetTool(hFig);
h = Tool.Hand;

% inputs are listCtrl indices
% facs are indices for factor popups
facs = get(h.factor,{'Value'});
facs = [facs{:}];


% what if < 3 inputs??
numFactors = nfactors(m); % = length of factor popup string
numControls = length(findobj(h.factor,'Visible','on'));
facs = facs(1:numControls);
if numFactors<numControls
    facs = facs(1:numFactors);
end

IsUnique = length(unique(facs))==length(facs);
if nargin ==2 && ~IsUnique
    % h.factor(factorNum) is the one just changed
    % keep this the same and change another factor
    change = setdiff(find(facs==facs(factorNum)),factorNum);
    freeEls = setdiff(1:numFactors,facs);
    if ~isempty(freeEls)
        set(h.factor(change),'Value',freeEls(1));
    else
        warning(message('mbc:mv_DialUp:InvalidState'));
    end
elseif ~IsUnique
    % If visible on has brought into play a control...must be YVar or TVar
    if numControls>1 && facs(2)==facs(1)
        freeEls = setdiff(1:numFactors,facs(1));
        if ~isempty(freeEls)
            set(h.factor(2),'Value',freeEls(1));
            facs(2) = freeEls(1);
        else
            warning(message('mbc:mv_DialUp:InvalidState'));
        end
    end
    if numControls==3 && any(facs(3)==facs(1:2)) % change TVar
        freeEls = setdiff(1:numFactors,facs(1:2));
        if ~isempty(freeEls)
            set(h.factor(3),'Value',freeEls(1));
        else
            warning(message('mbc:mv_DialUp:InvalidState'));
        end
    end
end



function iInitType(hFig,Tool,m,p)

h = Tool.Hand;


if Tool.RememberSettings
    % get default settings from testplan
    [x,DispType,factors] = getRespSurf(p.mdevtestplan,m);
    if length(x)~=nfactors(m)
        DefaultPlotSetup(p.mdevtestplan);
        [x,DispType,factors] = getRespSurf(p.mdevtestplan,m);
    end
else
    % do a 2-d plot on first variable
    Bnds= getcode(m);
    mid= sum(Bnds,2)/2;
    x= [{Bnds(1,1), Bnds(1,2),21}  num2cell(mid(2:end)')];
    DispType= 2;
    factors= 1;
end
for i= 1:length(x);
    if iscell(x{i})
        % expand {min,max,numpts}
        x{i}= linspace(x{i}{:});
    end
end
for i= 1:length(factors)
    set(h.factor(i),'Value',factors(i));
end
set(h.dispType,'Value',DispType);

iMakeControls(hFig,m,Tool,x,factors);


function iMakeControls(hParent,m,Tool,x,factors)

h = Tool.Hand;
DispType= get(h.dispType,'Value');
% work out default values
[L,U]= range(m);
if ~isempty(Tool.Hand.AbsX) && get(Tool.Hand.AbsX,'Value')
    % local variable is relative to datum (range is centered around 0)
    m1= (L(1)+U(1))/2;
    L(1)= -m1;
    U(1)= m1;
end

% =============================================================
%                MAKING NEW CONTROLS
% =============================================================
labels= get(m,'symbol');

nf = nfactors(m);
NewControls = cell(1,nf);
% Set non-plotted variables to the (arithmetic) mean

Pnl = get(h.listCtrl,'Frame');

for inputNum = 1:nf
    data = x{inputNum};
    if  ~any(inputNum==factors)
        if ~isscalar(data) % should be a constant
            data = (L(inputNum)+U(inputNum))/2;
        end
        % 5 steps through range
        stepVal= (U(inputNum)-L(inputNum))/5;
        hCtrl = xregclickinput(Pnl,...
            'name',labels{inputNum},...
            'Tag',sprintf('SVspinner_%d',inputNum),...
            'Min',L(inputNum),'Max',U(inputNum),...
            'ClickIncrement',stepVal);
        set(hCtrl,'Value',data);

    else
        % inputNum is a plot factor

        if isempty(data) ||  (isscalar(data) && DispType~=1) || DispType==2
            % second clause since DispType==1 (table) can have size of 1
            if (DispType==6 && inputNum==factors(3)) || (DispType==3 && inputNum==factors(2))
                % multiline or movie frames
                N=5;
            else
                %default num plot points
                N=21; 
            end
            data = linspace(L(inputNum),U(inputNum),N);
        end

        if DispType== 1 
            %table
            hCtrl = xregvectorinput(Pnl,labels{inputNum},data );
        else
            % range control has min,max,N
            hCtrl = xregrangeinput(Pnl,'name',labels{inputNum},...
                'value',data );
        end

    end
    NewControls{inputNum} = hCtrl;
end
set(h.listCtrl,'controls',NewControls);
set(h.listCtrl, 'Callback', {@i_CheckVals, hParent} );
x = get(h.listCtrl,'values');
set(h.listCtrl,'UserData',x);

    
function i_DisplayType(hParent,Tool,m,~)

if nargin < 4
    [Tool,m]=i_GetTool(hParent);
end
h = Tool.Hand;

% get data from controls
[x,XVar,YVar,TVar]=i_GetValues(Tool,0);

numActive = length([XVar,YVar,TVar]);
[xvar,yvar,tvar] = i_GetFactors(Tool);
factors = [xvar yvar tvar];
factors = factors(1:numActive);

if ~istransient(m)
    iMakeControls(hParent,m,Tool,x,factors)
else
    set([h.factor(2:end),h.text(2:end)],'Visible','off');
end
% now display the plot
i_Display(hParent);
    

%-------------------------------------------------------------------
% SUBFUNCTION i_Display
%-------------------------------------------------------------------
function i_Display(hParent,Tool,ModelInfo,~)

if nargin == 1
    [Tool,m,p]=i_GetTool(hParent);
else
    m= ModelInfo{3}{1};
    p= ModelInfo{2};
    if ~isempty(Tool.Hand.AbsX)
        AbsX= get(Tool.Hand.AbsX,'Value');
        if AbsX && isa(m,'xregtwostage') && get(m,'datumtype')
            set(m,'datum',0);
        end
    end
    
end
% get new response name
yi = yinfo(m);
Tool.RespName = yi.Name;


h = Tool.Hand;
set(h.text(2),'String','Y-axis factor:');

if istransient(m)
    set(h.controlsCard,'currentcard',1);
    delete(get(h.Axes,'Children'));
    set([h.factor(2:end),h.text(2:end)],'Visible','off');

    text(0.5,0.5,'No response surface for transient models',...
        'HorizontalAlignment','center',...
        'Parent',h.Axes,'Units','normalized');
    return
end

DispType= get(h.dispType,'Value');
set([h.factor(1),h.text(1)],'Visible','on');
switch DispType
    case 1
        % table
        set([h.factor(3),h.text(3)],'Visible','off');
        set(h.controlsCard,'currentcard',2);
        if size(h.listCtrl)<2
            set([h.factor(2),h.text(2)],'Visible','off');
        else
            set([h.factor(2),h.text(2)],'Visible','on');
        end
        i_DrawTable(hParent,Tool,m,p);
        set(h.displayPane, 'CurrentCard', 1);
    case 2
        % 2-D plot
        h = i_RemoveColorBar(h);
        set([h.factor(2:3),h.text(2:3)],'Visible','off');
        set(h.controlsCard,'currentcard',1);
        i_Plot2D(hParent,Tool,m,p);
        set(h.displayPane, 'CurrentCard', 2);
    case 3
        % multiline plot
        set(h.text(2),'String','Multiline factor:');
        set([h.factor(2),h.text(2)],'Visible','on');
        set([h.factor(3),h.text(3)],'Visible','off');
        set(h.controlsCard,'currentcard',1);
        i_Plot3D(hParent,DispType,Tool,m,p);
        set(h.displayPane, 'CurrentCard', 2);
    case 4
        % contour plot
        set([h.factor(2),h.text(2)],'Visible','on');
        set([h.factor(3),h.text(3)],'Visible','off');
        set(h.controlsCard,'currentcard',4);
        i_Plot3D(hParent,DispType,Tool,m,p);
        set(h.displayPane, 'CurrentCard', 2);
    case 5
        % surface
        set([h.factor(2),h.text(2)],'Visible','on');
        set([h.factor(3),h.text(3)],'Visible','off');
        set(h.controlsCard,'currentcard',3);
        i_Plot3D(hParent,DispType,Tool,m,p);
        set(h.displayPane, 'CurrentCard', 2);
    case 6
        % movie
        set([h.factor(2:3),h.text(2:3)],'Visible','on');
        % turn on replay vis
        set(h.controlsCard,'currentcard',5);
        i_Plot3D(hParent,DispType,Tool,m,p);
        set(h.displayPane, 'CurrentCard', 2);
end

% Reset display type list in case user has been playing while the plot is generated
if isgraphics(h.dispType)
    % Need to first check handle validity since the movie option allows for
    % figure destruction during its execution.
    set(h.dispType,'Value',DispType);
end


%-------------------------------------------------------------------
% SUBFUNCTION i_SetTool
%-------------------------------------------------------------------
% store userdata in validation tool and
function i_SetTool(hParent,Tool)
mv_ValidationTool('set',hParent,Tool)




%-------------------------------------------------------------------
% SUBFUNCTION i_GetTool
%-------------------------------------------------------------------
% get tool userdata and model from validation tool
function [Tool,m,p]=i_GetTool(hParent)

if nargout==1
    Tool= mv_ValidationTool('get',hParent);
else
    % get validation tool data
    [Tool,ModelInfo]= mv_ValidationTool('get',hParent);
    m= ModelInfo{3}{1};
    % Use relative Local Value
    if ~isempty(Tool.Hand.AbsX)
        AbsX= get(Tool.Hand.AbsX,'Value');
        if isa(m,'xregtwostage') && get(m,'datumtype') && AbsX
            % can't do PE Shading here
            set(Tool.Hand.PEcol,'Value',0,'Enable','off');
            set(m,'datum',0);
        else
            set(Tool.Hand.PEcol,'Enable','on');
        end
    end
    % pointer
    p= ModelInfo{2};
end


function cmodel = iGetBoundaryModel(m,p)

if isa(m,'localmod')
    % get current operating point
    cmodel= BoundaryModel(p.mdevtestplan,m,get(MBrowser,'CurrentTest'));
    if ~isempty(cmodel)
        % update range
        Rng = getcode(m);
        cif = getInputFactors(cmodel);
        cif = setRange(cif,Rng');
        cmodel = setInputFactors(cmodel,cif);
    end
else
    cmodel= BoundaryModel(p.mdevtestplan,m);
end

%-------------------------------------------------------------------
% SUBFUNCTION i_Plot3D
%-------------------------------------------------------------------
function i_Plot3D(hParent,DispType,Tool,m,p)
% get handles
h = Tool.Hand;

mv_ValidationTool('setmessage','Generating data for plot ... ');
fig = ancestor(hParent,'figure');
set(fig,'Pointer','watch');

% get Dial-Up Values
[x,XVar,YVar,TVar]= i_GetValues(Tool);
% XVar=[] is returned from i_GetValues as a check if values are not OK
if isempty(XVar)
    return
end

if Tool.RememberSettings
    % store settings
    xstore= x;
    for i= find(cellfun('prodofsize',x)>1)
        % turn into {min,max,numpts cell array
        xstore{i}= {x{i}(1) x{i}(end) length(x{i})};
    end
    if sum(cellfun('prodofsize',x)>1)==3
        VarList= [XVar,YVar,TVar];
    else
        VarList= [XVar,YVar];
    end
    setRespSurf(p.mdevtestplan,m,xstore,DispType,VarList);
end

set(h.Axes,'Visible','on');
set(fig,'CurrentAxes',h.Axes);

OldFig= get(0,'CurrentFigure');
set(0,'CurrentFigure',fig);
hvis= get(fig,'HandleVisibility');
set(fig,'HandleVisibility','on')

delete(get(h.Axes,'Children'));

h = i_RemoveColorBar(h);

mv_rotate3d(h.Axes,'off');

xtrans= YVar>XVar;
PEcol=0;

cmodel= [];
if get(h.Constraints,'Value')
    % show data boundary on surface
    cmodel = iGetBoundaryModel(m,p);
end

cmap= get(fig,'Colormap');
if isempty(cmodel) && isequal(cmap(end,:),mbcbdrycolor)
    % remove boundary color from map
    cmap= cmap(1:end-1,:);
    set(fig,'Colormap',cmap);
end

switch DispType %some sort of surface plot
    case 3 %multi-line
        h = iMultiline(m,x,hParent,h,xtrans,cmodel);

    case 4 %contour plot
        h = iContour(m,x,hParent,h,xtrans,cmodel);
    case 5 %surface
        [h,PEcol] = iSurface(m,x,hParent,h,xtrans,cmodel);

    case 6 %movie
        panel = findall(hParent,'Tag','ValidationViewPanel');
        [h,Tool.Movie,Tool.PanelPos] = iMovie(m,x,panel,h,xtrans,cmodel,TVar);
end
set(fig,'Pointer','arrow');
xregdialupmenu('updateplot',h.Axes);
mv_ValidationTool('setmessage','Ready');


% Save userdata
i_SetTool(hParent,Tool)
if PEcol
    i_PEthreshold(hParent)
end

set(fig,'HandleVisibility',hvis)
set(0,'CurrentFigure',OldFig);


function h = iMultiline(m,x,hParent,h,xtrans,cmodel)

cmap= xregdialupmenu('colormap',h.Axes);
lines = multiline(m,x,h.Axes,xtrans,cmodel,cmap);
set(lines(1), 'UserData', ...
    mbcgui.hgclassesutil.proplistener(ancestor(hParent,'figure'), 'ColorMap', 'PostSet', ...
    @(h,evt) i_updatemultiline(hParent)))
set(h.AxesLayout,'colsizes',[-1 30],...
    'elements',{h.axisPanel,[]},'gapx',0);
drawnow('expose');


function h = iContour(m,x,~,h,xtrans,cmodel)

udv= get(h.Btns(1),'UserData');
[~,patchH]= contour(m,x,h.Axes,udv.V,[udv.labels,udv.fill,xtrans],cmodel);
set(patchH, 'HitTest', 'off');
if udv.labels || isempty(patchH)
    h = i_RemoveColorBar(h);
else
    h = i_InsertColorBar(h);
end

drawnow('expose');

function [h,PEcol] = iSurface(m,x,~,h,xtrans,cmodel)

cv = get(h.Axes,'View');
if cv(1) == 0
    set(h.Axes, 'View',[-37.5 30]);
end
PEcol=get(h.PEcol,'Value');
if PEcol
    set(h.PEthresh,'Enable','on');
else
    set(h.PEthresh,'Enable','off');
end

% main surface plot
surface(m,x,h.Axes,[PEcol,xtrans],cmodel);

% store original PE limits in thresh ud
if PEcol
    yl = get(h.Axes,'CLim');
    if ~isempty(yl)
        set(h.PEthresh.Control,'UserData',yl,'String',num2str(yl(2)));
    end
    h = i_InsertColorBar(h);
else
    set(h.PEthresh.Control,'String','');
    h = i_RemoveColorBar(h);
end
drawnow('expose');


function [h,Movie,PanelPos] = iMovie(m,x,hParent,h,xtrans,cmodel,TVar)

% Area for Movie GetFrame
cv = get(h.Axes,'View');
if cv(1) == 0
    set(h.Axes, 'View',[-37.5 30]);
end

PanelPos = get(hParent,'Position');


Movie = [];
try
    % Movie generation can be interrupted by closing the figure,
    % and this will cause an error in movie.
    Movie= movie(m,x,TVar,h.Axes,PanelPos,xtrans,cmodel);
catch ME
    % Check whether the figure still exists
    if isgraphics(hParent)
        % The error seems to be something else
        rethrow(ME);
    end
end

%-------------------------------------------------------------------
% SUBFUNCTION i_Plot2D
%-------------------------------------------------------------------
function i_Plot2D(hParent,Tool,m,p)
% get handles
h = Tool.Hand;

% get Dial-Up Values
[x,XVar]= i_GetValues(Tool);
% XVar=[] is returned if values are not OK
if isempty(XVar)
    return
end

if Tool.RememberSettings
    % store settings
    setRespSurf(p.mdevtestplan,m,x,2,XVar);
end

% Delete any old Tables
if ~isempty(h.DispTable) && strcmp(get(h.DispTable,'Visible'),'on')
    set(h.DispTable,'Visible','off');
end

% Generate Table
fig=ancestor(hParent,'figure');
set(fig,'Pointer','watch');
Y2 = GenTable(m,x);

cmodel= [];
if get(h.Constraints,'Value')
    % show data boundary on surface
    cmodel = iGetBoundaryModel(m,p);
end


if ~isempty(cmodel)
    cvals= constraintDistanceGrid(cmodel,x)>0;
    Y2(cvals)=NaN;
end
set(fig,'CurrentAxes',h.Axes);
mv_rotate3d(h.Axes,'off');
delete(get(h.Axes,'Children'));

% draw plot
hL = plot(x{XVar},Y2(:),'Parent',h.Axes,'LineWidth',2,'Color',[0 0.5 0]);
xregGui.setLegendData(hL, 'Model fit');
set(h.AxesLayout,'colsizes',[-1 0],...
    'elements',{h.axisPanel,[]});
set(h.Axes,'XGrid','on','YGrid','on','Box','on');

Xlab= InputLabels(m);
Xlab = Xlab{XVar};
Ylab= ResponseLabel(m);
% label axes
if ischar(Xlab) && ischar(Ylab)
    set(get(h.Axes,'XLabel'),...
        'String',Xlab,'Interpreter','none');
    set(get(h.Axes,'YLabel'),...
        'String',Ylab,'Interpreter','none');
    set(get(h.Axes,'Title'),...
        'String',Ylab,'Interpreter','none');
end


set(h.Axes,'Visible','on');
set(fig,'Pointer','arrow');

% Save userdata
i_SetTool(hParent,Tool)

%-------------------------------------------------------------------
% SUBFUNCTION i_DrawTable
%-------------------------------------------------------------------
function i_DrawTable(hParent,Tool,m,p)

[x,XVar,YVar]= i_GetValues(Tool);
if isempty(XVar)
    return
end

if Tool.RememberSettings
    % store settings
    setRespSurf(p.mdevtestplan,m,x,1,[XVar,YVar]);
end

mv_ValidationTool('setmessage','Generating data for table...');

set(ancestor(hParent,'figure'),'Pointer','watch');
if isempty(Tool.Hand.DispTable)
    Tool.Hand.DispTable = mbcwidgets.Table2D(com.mathworks.toolbox.mbc.gui.peer.ConstrainedNumericTablePeer, ...
        'parent', get(Tool.Hand.displayPane,'Parent'), ...
        'visible', 'off');
    attach(Tool.Hand.displayPane, Tool.Hand.DispTable, 1);
end

cmodel= [];
if get(Tool.Hand.Constraints,'Value')
    % show data boundary on surface
    cmodel = iGetBoundaryModel(m,p);
end

Y= GenTable(m,x);
if size(Tool.Hand.listCtrl)>1
    [Xord,reord]= sort([XVar YVar]);
    %
    % Need to reshape Y so it is a 2D matrix for table
    Y= reshape(Y,length(x{Xord(1)}),length(x{Xord(2)}));
    if any(diff(reord)<0)
        % Transpose if Yind<Xind
        Y=Y';
    end
else
    Y=Y(:);
end

if ~isempty(cmodel)
    cvals = constraintDistanceGrid( cmodel, x ) > 0 ;
    if size(Tool.Hand.listCtrl)>1
        cvals= reshape(cvals,length(x{Xord(1)}),length(x{Xord(2)}));
        if any(diff(reord)<0)
            % Transpose if Yind<Xind
            cvals=cvals';
        end
    else
        cvals= cvals(:);
    end
else
    cvals= [];
end


% IS THIS AN ERROR IN SETTOOL??
if iscell(Tool.RespName)
    Tool.RespName = Tool.RespName{:};
end

% transponse the table
if nfactors(m)>1
    Y= Y';
    tmp= XVar;
    XVar=YVar;
    YVar=tmp;
    if ~isempty(cvals)
        cvals = cvals';
    end
end

tbl= Tool.Hand.DispTable;
lab= get(m, 'symbols');
if size(Tool.Hand.listCtrl)==1
    tbl.Peer.setConstrainedData(Y, Tool.RespName, x{XVar}(:), cvals>0);
    tbl.Peer.setCornerString(lab{XVar});
else
    tbl.Peer.setConstrainedData(Y,x{YVar}(:),x{XVar}(:), cvals>0);
    tbl.Peer.setCornerLabels(lab{XVar}, lab{YVar});
end

% No Movie for Tables
Tool.Movie = [];
i_SetTool(hParent,Tool)
mv_ValidationTool('setmessage','Ready');
set(ancestor(hParent,'figure'),'Pointer','arrow');

%-------------------------------------------------------------------
% SUBFUNCTION i_Export
%-------------------------------------------------------------------
function i_Export(~,~,hParent)

if nargin==0
    hParent=gcbf;
end

[Tool, m]= i_GetTool(hParent);
h = Tool.Hand;

x = i_GetValues(Tool,0);
Y = GenTable(m, x);

exportName1 = mbcMakeValidName(get(h.exportName1,'String'));
exportName2 = mbcMakeValidName(get(h.exportName2,'String'));

radio = get(h.exportRadios,'Value');
if radio(end)
    [savename, savepath]= uiputfile('','Select file to save variables');
    if savename
        eval([exportName1 '=x;']);
        eval([exportName2 '=Y;']);
        save([savepath, savename],exportName1,exportName2);
    end
else
    assignin('base',exportName1,x);
    assignin('base',exportName2,Y);
    
    msg = sprintf(['The input values have been written to the cell array %s ' ...
        'and the model output has been written to the array %s in ' ...
        'the MATLAB workspace.'], ...
        exportName1, exportName2);
    h = msgbox(msg, 'Export', 'modal');
    waitfor(h);
end

%-------------------------------------------------------------------
% SUBFUNCTION i_Replay
%-------------------------------------------------------------------
function i_Replay(~,~,hParent)

if nargin<3
    hParent=gcbf;
end

Tool= i_GetTool(hParent);

PanelPos = get(hParent,'Position');
if ~isequal(Tool.PanelPos,PanelPos)
    % figure size changed - redraw movie
    i_Display(hParent)

    Tool= i_GetTool(hParent);
    % now replay at chosen speed
end

fps = get(Tool.Hand.framePS.Control,'Value');

% replay the movie if it exists
if ~isempty(Tool.Movie);
    vvp = findall(ancestor(hParent,'figure'), 'Tag', 'ValidationViewPanel');
    setValidationViewPanelVisibleOn = onCleanup(@()set(vvp, 'Visible', 'on'));
    set(vvp, 'Visible', 'off')
    
    movie(ancestor(hParent,'figure'),Tool.Movie,1,max(fps,fix(size(Tool.Movie,2)/10)),PanelPos);
end


%-------------------------------------------------------------------
% SUBFUNCTION i_PEthreshold
%-------------------------------------------------------------------
function  i_PEthreshold(hParent)

Tool= i_GetTool(hParent);
h = Tool.Hand;
yl = get(h.Axes,'CLim');
if isempty(yl)
    return
end
    
newlim= str2double(get(h.PEthresh.Control,'String'));

if isempty(newlim)
    % userdata holds original PEV limits, get the upper limit.
    newlim=get(h.PEthresh.Control,'UserData'); 
    newlim=newlim(2);
elseif newlim<=yl(1) % must be nonempty
    newlim=get(h.PEthresh.Control,'UserData'); 
    newlim=newlim(1)+0.1*diff(newlim);
    msgbox('PE threshold must be greater than the lower limit of prediction error.',...
        'PE Threshold error','modal');
end
% always write reformatted number back in
newlimstr = sprintf('%0.4g',newlim);
set(h.PEthresh.Control,'String',newlimstr);

if newlim>yl(1)
    set(h.Axes,'CLim',[yl(1) newlim]);
end

Tool.Hand=h;
i_SetTool(hParent,Tool);


%-------------------------------------------------------------------
% SUBFUNCTION i_Print
%-------------------------------------------------------------------
function i_Print(Tool,TitleStr)

h = Tool.Hand;

DispType= get(h.dispType,'Value');

switch DispType
    case {1, 6}
        % currently not printing Table nor movie
        h = errordlg('The Movie display and the Table display cannot be printed.', ...
            'MBC Toolbox', 'modal');
        waitfor(h);
        return
    otherwise
        inputs = InputLabels(Tool.model);

        x= i_GetValues(Tool);
        for i=1:length(x)
            if numel(x{i})==1
                inputs{i}= sprintf('%20s = %.5g',inputs{i},x{i});
            else
                inputs{i}= sprintf('%20s = [%.5g,%.5g] ',inputs{i},x{i}([1 end]) );
            end
        end

        inputs = ['Input Factors';'';inputs(:)];

        fh = figure('Visible','off');
        lay = xreglayerlayout(fh,'border',[80 20 20 50]);
        font=get(0,'FixedWidthFontName');
        tH = axestext(fh,'units','pixels',...
            'fontweight','demi',...
            'fontName',font,...
            'interpreter','none',...
            'string',inputs);
        set(lay,'elements',{tH},'position',get(tH,'Extent'));

        if DispType == 1
            %  table view
            printlayout1(h.DispTable,lay,TitleStr);
        else
            printlayout1(h.Axes,lay,TitleStr);
        end
        close(fh);
end


% Listener callback that checks for colormap changes and forces an update
function i_updatemultiline(hParent)
i_DisplayType(hParent);

function iUpdateRanges(hParent,Tool,m,p,Change)
% update ranges for plots - this is mainly for localmulti
if nargin<4
    [Tool,m,p]=i_GetTool(hParent);
end
if nargin<5
    Change = false;
end    

if Tool.DoUpdateRanges 
    % update works by changing the settings for surface viewer stored in
    % the test plan 
    [x,DispType,factors] = getRespSurf(p.mdevtestplan,m);
    R = getcode(m);
    for i=1:length(x)
        data = x{i};
        % check points are within the ranges
        if isscalar(data)
            if data < R(i,1) || data > R(i,2)
                % use mean value
                data = mean(R(i,:));
                Change = true;
            end
        elseif iscell(data)
            % 3 linspace values
            if data{1} ~= R(i,1) || data{1} ~= R(i,2)
                data = {R(i,1),R(i,2),data{3}};
                Change = true;
            end
        elseif any(data < R(i,1) | data > R(i,2))
            %vector input
            data = linspace(R(i,1),R(i,2),length(data));
            Change = true;
        end
        x{i} = data;
    end
    % update stored values
    setRespSurf(p.mdevtestplan,m,x,DispType,factors);
end

if Change
    % update plot controls if a change has occurred
    iInitType(hParent,Tool,m,p)
end




function i_EditContours(src, ~, hParent)
CVals = get(src,  'UserData');
[CVals, OK] = mv_ContourValues(CVals);
if OK
    set(src, 'UserData', CVals);
    i_Display(hParent);
end


function hnd = i_RemoveColorBar(hnd)
% Remove colorbar from the layout structure
if get(hnd.ColorBarCard,'CurrentCard')~=1
    set(hnd.ColorBarCard,'CurrentCard',1);
    set(hnd.AxesLayout, 'colsizes', [-1 0]);
end

function hnd = i_InsertColorBar(hnd)

if get(hnd.ColorBarCard,'CurrentCard')~=2
    % Insert colorbar into the layout structure
    set(hnd.ColorBarCard,'CurrentCard',2);
    set(hnd.AxesLayout,'colsizes',[-1 60]);
end

%--------------------------------------------------------------------------
function i_setcolorbarclim(~, evt, hCBar)
%--------------------------------------------------------------------------

cl = get(evt.AffectedObject, 'CLim');
hCBar.ColorMap = get(ancestor(hCBar.Parent,'figure'), 'Colormap');
hCBar.setRange(cl);

function i_setcolormap(~, ~, hCBar)

hCBar.ColorMap = get(ancestor(hCBar.Parent,'figure'), 'Colormap');