www.gusucode.com > mbctools 工具箱 matlab 源码程序 > mbctools/+mbcmodelview/SurfaceViewer.m
classdef SurfaceViewer < mbcgui.multiview.View %mbcmodelview.SurfaceViewer model browser surface viewer % Copyright 2015-2016 The MathWorks, Inc. and Ford Global Technologies, Inc. properties (Constant) %ViewInfo view description ViewInfo = { @mbcmodelview.SurfaceViewer; '&Response Surface'; xregrespath('surfviewer.bmp'); 'Response surface'; 1}; end properties %InputIndices input indices for axes InputIndices = 1:2 %NumAxes number of axes (1 or 2) NumAxes = 2; %ZoomToBoundary show region outside boundary model (to model range) ZoomToBoundary = false; %ShowLight show light (only for surface) ShowLight = false; %PlotType type of plot {'Line','Surface','Contour','Multi-line'} PlotType = 'Surface'; end properties (Dependent,SetAccess=private) SlicePoints end properties (SetAccess=private) %hPlotType handle to popup for plot type hPlotType %hAxes handle to axes hAxes %hDataPoints handle to line for data points hDataPoints %hValidationPoints handle to line for validation data points hValidationPoints %hSliceTable handle to table for slice and tolerance points hSliceTable %hSelectButton handle to button for popup hSelectButton %hAxisLabels handle to label controls for axes popups hAxisLabels %hAxisPopups handle to axes popups hAxisPopups %InputRange range for inputs InputRange %InputSymbols input symbols InputSymbols %CrossSection cross section points [Values,Tolerance] CrossSection end methods function obj=SurfaceViewer(varargin) %SurfaceViewer constructor obj@mbcgui.multiview.View(varargin{:}); create(obj) if strcmp(obj.Visible,'on') && hasData(obj.MessageService) reset(obj) update(obj) end % add message service listeners addMessageServiceListener(obj, 'NodeUpdated',@obj.onNodeUpdated) addMessageServiceListener(obj, 'NodeReset',@obj.onNodeReset) end function x=get.SlicePoints(obj) values = obj.hSliceTable.getNumericValues; types = obj.hSliceTable.VariableTypes; x = cell(1,size(values,1)); inp = getInputs(obj.MessageService.Model); for i=1:length(x) switch types(i,1) case 1 % scalar x{i}= values{i,1}; case 2 % linspace x{i} = values{i,1}; if isscalar(x{i}) % can't have scalars x{i}= linspace(inp(i).Range(1),inp(i).Range(2),51); end end end if obj.ZoomToBoundary % zoom ranges inside boundary model x = zoomConstraints(obj,x); end end function str = gettitle(obj) %#ok<MANU> %GETTITLE Return string to use as title for view % % STR = GETTITLE(OBJ) returns a string that should be used as a title for % the container the view sits in. str = 'Response Surface'; end % gettitle function update(obj) %update main update method ms = obj.MessageService; [LB,UB]=range(ms.Model); s = get(ms.Model,'symbols'); if ~isequal(obj.InputRange,[LB,UB]) || ~isequal(obj.InputSymbols,s) obj.InputRange = [LB,UB]; obj.InputSymbols = s; initialize(obj); end if obj.MessageService.Status~=0 && ~istransient(ms.Model) set(allchild(obj.hAxes),'Visible','on'); drawResponseSurface(obj) else set(allchild(obj.hAxes),'Visible','off'); end title(obj.hAxes,obj.MessageService.Title,'Interpreter','none') end function s = serializeView(obj) %SERIALIZEVIEW Get serializable setup data for the view % % OUT = SERIALIZEVIEW(OBJ) retuns a MATLAB array that contains the setup % data that will allow this view to be recreated via the deserializeView % function in the future. Typically this function will return a cell % array of property names and values, however any MATLAB array type is % allowed. s.InputIndices = obj.InputIndices; s.ZoomToBoundary = obj.ZoomToBoundary; s.ShowLight = obj.ShowLight; s.PlotType = obj.PlotType; s.CrossSection = obj.CrossSection; end % serializeView function deserializeView(obj,s) %DESERIALIZEVIEW Set saved state data % DESERIALIZEVIEW(OBJ, DATA) sets a copy of the serialized state of this % View. DATA is a MATLAB array that will have been created by a % previous call to SERIALIZEVIEW on this View object. if obj.hasData && isstruct(s) && isfield(s,'CrossSection') obj.InputIndices = s.InputIndices; obj.NumAxes = length(obj.InputIndices); obj.PlotType = s.PlotType; obj.CrossSection = s.CrossSection; if isfield(s,'ZoomToBoundary') obj.ZoomToBoundary = s.ZoomToBoundary; obj.Actions(1).Selected = s.ZoomToBoundary; end obj.ShowLight = s.ShowLight; obj.Actions(2).Selected = s.ShowLight; end end % serializeView function ah = printCopy(obj, fig) %PRINTCOPY Create a printable version of the component % NEWOBJ = PRINTCOPY(H, FIG) creates and returns a handle to a new % component, NEWOBJ, parented by the specified figure, FIG. The new % object will be used for printing a copy of this component. % % Normally the printable version of a component is not a complete % copy of the object. There are often controls that should not % appear, such as popup menus, or components whose information needs % to be transformed, such as edit boxes. % % See also canPrint, print, printSize. if isgraphics(obj.hAxes) ah = copyobj(obj.hAxes,fig); set(ah,'Units',get(fig,'DefaultAxesUnits'),... 'Position',get(fig,'DefaultAxesPosition')); else ah = []; end end function OK = canPrint(obj) %#ok<MANU> OK = true; end function reset(obj) %reset reset slice point % reset cross-section point to the mid-point of the model range cs= obj.MessageService.CrossSection; inp = getInputs(obj.MessageService.Model); nInputs = length( inp ); needsReset = size(obj.CrossSection,1)~=nInputs; for i=1:nInputs % check whether current slice point is outside input range needsReset = needsReset || obj.CrossSection(i,1)<inp(i).Range(1) || obj.CrossSection(i,1)>inp(i).Range(2); % center slice at mean with a tolerance of 2% cs(i,:) = [mean(inp(i).Range), diff(inp(i).Range)/50]; end if needsReset % update cross-section values if current value is outside input % range obj.MessageService.CrossSection = cs; obj.CrossSection = cs; end initialize(obj) end end methods (Access=private) function create(obj) %create create view graphics SC = xregGui.SystemColorsDbl; lytAxesPanel = mbcgui.widget.AxesContainer(... 'Parent',obj.Parent, ... 'Border',[10 10 10 10],... 'PositionSetting', 'outer'); obj.hAxes = lytAxesPanel.AxesHandle; set(obj.hAxes,... 'Box','on',... 'XGrid','on',... 'YGrid','on',... 'ZGrid','on',... 'Units','pixels',... 'Layer','top', ... 'NextPlot','add',... 'HitTest', 'off'); mbcxlabel( obj.hAxes, '', 'Interpreter', 'none' ); mbcylabel( obj.hAxes, '', 'Interpreter', 'none' ); mbczlabel( obj.hAxes, '', 'Interpreter', 'none' ); obj.hDataPoints = line('Parent',obj.hAxes,... 'LineStyle','none',... 'Marker','.',... 'MarkerSize',15, ... 'XData', [], ... 'YData', [], ... 'ZData', []); obj.hValidationPoints = line('Parent',obj.hAxes,... 'LineStyle','none',... 'Marker', '^', ... 'MarkerFaceColor', [50, 200, 50]/255, ... 'MarkerSize', 5, ... 'XData', [], ... 'YData', [], ... 'ZData', [], ... 'PickableParts', 'none'); SlicePanel = mbcgui.container.layoutpanel(... 'Parent', obj.Parent); % Slice control table % -- This table is what the user used to control the evlaution points for % the slice and the associated tolerance on the data points to be shown % in the slice. obj.hSliceTable = mbcwidgets.VariableEditorTable( ... 'Parent', SlicePanel, ... 'ValueColumnCount', 2, ... 'ValueColumnHeader', {'Value', 'Tolerance'}, ... 'ValueChangedCallback', @obj.editSlice, ... 'ValueConstraint', 'plot'); obj.hSelectButton = uicontrol(... 'Parent', SlicePanel, ... 'Style','pushbutton',... 'String','Select Data Point...',... 'Interruptible','off',... 'Callback', @obj.selectDataPoint ); % Create the pop-up menus and label controls for the axes chooser axisNames = {'X', 'Y', 'Z'}; hLabels = cell(1, obj.NumAxes ); hPopups = cell(1, obj.NumAxes ); SelectorPanel = mbcgui.container.layoutpanel(... 'Parent', SlicePanel, ... 'BorderType', 'none'); for i = 1:obj.NumAxes hPopups{i} = uicontrol(... 'Parent', SelectorPanel, ... 'Style', 'popupmenu', ... 'String', ' ', ... 'Value', 1, ... 'BackgroundColor', SC.WINDOW_BG, ... 'Callback', @(h,evt) obj.editInputIndex(i)); hLabels{i} = xregGui.labelcontrol( ... 'parent', SelectorPanel, ... 'String', sprintf('%s-axis:', axisNames{i}), ... 'LabelSize', 40, ... 'LabelSizeMode', 'absolute', ... 'ControlSize', 1, ... 'ControlSizeMode', 'relative', ... 'Control', hPopups{i} ); end hPopups = [hPopups{:}]; hLabels = [hLabels{:}]; obj.hAxisLabels = hLabels; obj.hAxisPopups = hPopups; % Layouts % Create the layout for the axes selectors lytSelectors = xreggridbaglayout( SelectorPanel, ... 'packgroup', 'XREG_PERM_ON', ... 'packstatus', 'off', ... 'dimension', [obj.NumAxes, 1], ... 'rowsizes', repmat( 21, 1, obj.NumAxes ), ... 'gapy', 5, ... 'elements', num2cell( obj.hAxisLabels )); set(SelectorPanel, 'LayoutComponent', {lytSelectors}); obj.hPlotType = uicontrol(... 'Parent', SlicePanel, ... 'Style', 'popupmenu', ... 'String', {'Line','Surface','Contour','Multi-line'}, ... 'Value', 2, ... 'BackgroundColor', SC.WINDOW_BG, ... 'Callback', @obj.onSelectPlotType ); hPlotTypeLabel = xregGui.labelcontrol( ... 'parent', SlicePanel, ... 'String', 'Plot:', ... 'LabelSize', 40, ... 'LabelSizeMode', 'absolute', ... 'ControlSize', 1, ... 'ControlSizeMode', 'relative', ... 'Control', obj.hPlotType ); % Create the layout that combines the slice table and axes selectors. This % is the slice control lytSliceControl = xreggridbaglayout( SlicePanel, ... 'packgroup', 'XREG_PERM_ON', ... 'Dimension', [4, 2], ... 'ColSizes', [-1, 105], ... 'RowSizes', [20 obj.NumAxes*26+3,-1,25], ... 'gapy', 2, ... 'border', [0 0 0 2], ... 'MergeBlock', {[1 1], [1 2]}, ... 'MergeBlock', {[2 2], [1 2]}, ... 'MergeBlock', {[3 3], [1 2]}, ... 'elements', {hPlotTypeLabel,SelectorPanel, obj.hSliceTable,[],... [],[],[],obj.hSelectButton}); set(SlicePanel, 'LayoutComponent', {lytSliceControl}); % Create the main layout for the view lyt = xregsplitlayout( obj.Parent,... 'packgroup', 'XREG_PERM_ON',... 'orientation', 'lr', ... 'dividerstyle', 'flat', ... 'dividerwidth', 4, ... 'minwidth',[180,300],... 'split', [0.1, 0.9], ... 'left', SlicePanel,... 'right', lytAxesPanel,... 'packstatus','on' ); attachContentHandle(obj,lyt); createActions(obj) end %Axes Selector X,Y fixed =1,2 for now function initialize(obj) %initialize initialize controls nf = nfactors(obj.MessageService.Model); inp = getInputs(obj.MessageService.Model); if size(obj.CrossSection,1)~=nf % initialize cross section point from testplan reset(obj) end if obj.hAxisPopups(1).Value>nf setInputIndex(obj, 1, 1) end set(obj.hAxisPopups(1),... 'String',{inp.Symbol},... 'Value',obj.InputIndices(1)) set(obj.hPlotType,'Value',find( strcmp(obj.PlotType, obj.hPlotType.String) )) if nf==1 % change to a line plot obj.PlotType = 'Line'; obj.NumAxes = 1; obj.InputIndices = 1; set(obj.hPlotType,'Value',1,'Enable','off'); set(obj.hAxisLabels(2),'Visible','off'); set(obj.hAxisPopups(2),'String',{'<none>'},... 'Value',1,... 'Enable','off'); else set(obj.hPlotType,'Enable','on'); if obj.NumAxes>1 set(obj.hAxisLabels(2),'Visible','on'); set(obj.hAxisPopups(2),'Enable','on') if obj.hAxisPopups(2).Value>nf setInputIndex(obj, 2, 2) end set(obj.hAxisPopups(2),... 'String',{inp.Symbol},... 'Value',obj.InputIndices(2)) else set(obj.hAxisPopups(2),'Enable','off') set(obj.hAxisPopups(2),... 'String',{inp.Symbol},... 'Value',1) end end updateTableValues(obj); end function range = getSliceRange(obj,sliceData) %GETSLICERANGE Get slice range from slice control table % % [RANGE, INDICES] = GETSLICERANGE(OBJ) % % RANGE is a two by nFactors matrix. The first row is the minimum value % of the slice range and the second row is the maximum. For factors where % there is no constraint on the slice, i.e., those factors that are the % axes of the slice, the min and max value will be -Inf and +Inf. % if nargin<2 sliceData = obj.SlicePoints; end % Get raw values from tables values = obj.hSliceTable.getNumericValues; types = obj.hSliceTable.VariableTypes; nf = size( values, 1 ); boundedFactors = (types(:,1) == 1); range = zeros( 2, nf ); for i = 1:nf if boundedFactors( i ) % Min range(1,i) = values{i,1} - values{i,2}; % Max range(2,i) = values{i,1} + values{i,2}; else % This factor is a axis of the slice range(:,i) = [sliceData{i}(1); sliceData{i}(end)]; end end end % Surface function drawResponseSurface(obj) %drawResponseSurface sliceData=obj.SlicePoints; delete( get(obj.hAxes,'Children') ) if obj.MessageService.Status switch obj.PlotType case 'Line' plotLine(obj,sliceData); case 'Surface' plotSurface(obj,sliceData); case 'Contour' plotContour(obj,sliceData); case 'Multi-line' plotMultiline(obj,sliceData); end drawPoints(obj,sliceData) end end function drawPoints(obj,sliceData) %drawPoints Draw the data/validation points that are in the current slice % % drawPoints(OBJ,sliceData) % % Assign the X-, Y- and Z-data for points and rings in the current slice. % if ~obj.MessageService.Status return end if nargin<2 sliceData = obj.SlicePoints; end % Get the current node and the data associated with that node. data = double(obj.MessageService.XData); dataOK = obj.MessageService.DataOK; % Get the slice information % -- Slice subspace factors % -- Slice point and thickness (tolerance) sliceRange = obj.getSliceRange(sliceData); % Work out which points are in the slice ind = find( all( bsxfun(@le,sliceRange(1,:), data) & bsxfun(@ge,sliceRange(2,:), data), 2 ) & dataOK); if ~isempty(obj.MessageService.ValidationXData) xvaldata = double(obj.MessageService.ValidationXData); yvaldata = double(obj.MessageService.ValidationYData); valind = find( all( bsxfun(@le,sliceRange(1,:) , xvaldata) & bsxfun(@ge,sliceRange(2,:) , xvaldata), 2 ) ); else xvaldata = []; valind = []; end XValData = []; YValData = []; ZValData = []; % Assign the data to the line objects switch lower(obj.PlotType) case {'line','multi-line'} Xdata = data(ind,obj.InputIndices(1)); Ydata =double(obj.MessageService.YData(ind)); Zdata = []; if ~isempty(xvaldata) XValData = xvaldata(valind,obj.InputIndices(1)); YValData = yvaldata(valind); ZValData = []; end case 'surface' % 2D plot Xdata = data(ind,obj.InputIndices(1)); Ydata = data(ind,obj.InputIndices(2)); Zdata = double(obj.MessageService.YData(ind)); if ~isempty(xvaldata) XValData = xvaldata(valind,obj.InputIndices(1)); YValData = xvaldata(valind,obj.InputIndices(2)); ZValData = yvaldata(valind); end case 'contour' % 1D plot Xdata = data(ind,obj.InputIndices(1)); Ydata = data(ind,obj.InputIndices(2)); Zdata = []; if ~isempty(xvaldata) XValData = xvaldata(valind,obj.InputIndices(1)); YValData = xvaldata(valind,obj.InputIndices(2)); ZValData = []; end end obj.hDataPoints = line('Parent',obj.hAxes,... 'LineStyle','none',... 'Marker','.',... 'MarkerSize',15, ... 'XData', Xdata,... 'YData', Ydata,... 'ZData', Zdata); obj.hValidationPoints = line('Parent',obj.hAxes,... 'LineStyle','none',... 'Marker', '^', ... 'MarkerFaceColor', [50, 200, 50]/255, ... 'MarkerSize', 5, ... 'XData', XValData,... 'YData', YValData,... 'ZData', ZValData,... 'PickableParts', 'none'); % The callback on the dots needs to be able to map between the points that % are displayed and the actual data points. Hence for displayed point we % store the indices of the that point in the original data set set( obj.hDataPoints, 'UserData', ind ); set( obj.hValidationPoints,'UserData', valind ); end function updateTableValues(obj) %PUPDATETABLEVALUES Update the values in the slice table % % PUPDATETABLEVALUES(OBJ) % % This is usually called in response to change in the pop-ups that control % which subspace the slice is in. % % Will cause a redraw of the constraint % #define TYPE_SCALAR = 1; TYPE_LINEAR = 2; TYPE_LINKED = 4; if strcmp(obj.PlotType,'Multi-line') AXES_NAMES = {'X-Axis', 'Lines'}; else AXES_NAMES = {'X-Axis', 'Y-Axis', 'Z-Axis'}; end % Get some input factor data from the object cs= obj.CrossSection; inp = getInputs(obj.MessageService.Model); nInputs = length( inp ); % Get the current variable type and values types = zeros(nInputs,2); values = cell(nInputs,2); % Check each one in turn % -- If the type matches what it should be for the obj.InputIndices then we leave % it as is. If it is the wrong type then we change the type and set the % value to some default. switch length(unique(obj.InputIndices)) case 1 Resolution = 101; case 2 Resolution = 51; otherwise Resolution = 21; end for i = 1:nInputs [tf, loc] = ismember( i, obj.InputIndices ); if tf % This factor is an axis of the plot and we want it to be a vector % type % This factor needs it type set [TYPE_LINEAR, TYPE_LINKED] and % appropriate values set types(i,:) = [TYPE_LINEAR, TYPE_LINKED]; if strcmp(obj.PlotType,'Multi-line') && i==obj.InputIndices(2) values{i,1} = [inp(i).Range, 11]; else values{i,1} = [inp(i).Range, Resolution]; end values{i,2} = AXES_NAMES{loc}; else % This factor is not an axis of the plot and so it must be a scalar % type and it must have a tolerance % We need to set the type for this factor to scalar and the % values to the midpoint and to 2% of the range types(i,:) = [TYPE_SCALAR, TYPE_SCALAR]; values(i,:) = { cs(i,1), cs(i,2) }; end end obj.hSliceTable.setVariables( {inp.Symbol}', types, values ); for i=1:length(obj.InputIndices) set(obj.hAxisPopups(i),... 'String', {inp.Symbol}',... 'Value',obj.InputIndices(i)); end end function setInputIndex(obj, newIndex, index) %setInputIndex Set the indices of the axes in a boundary slice view % % setInputIndex(OBJ, newIndex) % % setInputIndex(OBJ, newIndex, index) allows one axis to be changed by specifying % the index of the axis to change in this case the newly created AXES % vector is checked to ensure that there are no two entries the same and % it there are, other entries are modified to fix this. No such checking % happens in the first form. if nargin == 3 % Need to check the new axes value to ensure that the same axis % isn't slected twice. In the case that one axis is selected twice, % we modify a different value in the "axes" vector to the one being % set by the pop-up. currentIndices = obj.InputIndices; currentIndices(index) = newIndex; tf = currentIndices == currentIndices(index); tf(index) = false; if any( tf ) % Two pop-ups have the same value otherValues = setdiff( 1:obj.NumAxes, currentIndices ); currentIndices(tf) = otherValues(1:nnz( tf )); % -- If the previous line errors it could be because there are % insufficient factors for the view. We shouldn't get into % this code in that situation. end elseif length( newIndex ) ~= obj.NumAxes || ~isnumeric( newIndex ) error(message('mbc:xregbdrygui:AbstractBdrySlice:InvalidArgument', obj.NumAxes)); else currentIndices = newIndex; end % Set the axes in the object % -- also updates the pop-ups obj.InputIndices = currentIndices; % Set the slice table to have the correct columns linked and the other % columns obj.updateTableValues; % Draw the new constraint obj.drawResponseSurface; end function setSlicepoint(obj,point) cs = obj.CrossSection; cs(:,1) = point(:); obj.CrossSection = cs; end function updateCrossSection(obj) cs = obj.CrossSection; values = obj.hSliceTable.getNumericValues; types = obj.hSliceTable.VariableTypes; for i=1:length(values) switch types(i,1) case 1 % scalar cs(i,:) = [values{i,:}]; end end obj.CrossSection = cs; end function onNodeUpdated(obj,~,~) update(obj) end function onNodeChanged(obj,~,~) initialize(obj) end function onNodeReset(obj,~,~) %onNodeReset reset inputs to mid range reset(obj) end function onZoomToBoundary(obj,~,~) obj.ZoomToBoundary = ~obj.ZoomToBoundary; update(obj); end function onShowLight(obj,~,~) obj.ShowLight = ~obj.ShowLight; update(obj); end function onSelectPlotType(obj,~,~) NewType = obj.hPlotType.String{obj.hPlotType.Value}; if ~strcmp(NewType,obj.PlotType) obj.PlotType = obj.hPlotType.String{obj.hPlotType.Value}; if strcmp(obj.PlotType,'Line') % Line only has one axes obj.NumAxes = 1; obj.InputIndices = obj.InputIndices(1); set(obj.hAxisLabels(2),'Enable','off','Visible','off') else set(obj.hAxisLabels(2),'Enable','on','Visible','on') obj.NumAxes = 2; if isscalar(obj.InputIndices) % change from Line (one axes) to two obj.InputIndices = [obj.InputIndices,rem(obj.InputIndices,obj.MessageService.NumInputs)+1]; set(obj.hAxisPopups(2),'Value',obj.InputIndices(2)); end end initialize(obj) update(obj); end end function createActions(obj) obj.Actions = [mbcgui.actions.ToggleAction(@obj.onZoomToBoundary,... '&Zoom to Boundary','Zoom to boundary constraint') mbcgui.actions.ToggleAction(@obj.onShowLight,... 'Show &Light','Show light')]; obj.Actions(1).Selected = obj.ZoomToBoundary; obj.Actions(2).Selected = obj.ShowLight; end function plotSurface(obj,x) [az,el] = view(obj.hAxes); hs=surface(obj.MessageService.Model,x,obj.hAxes,... [0,obj.InputIndices(1)>obj.InputIndices(2),~obj.ZoomToBoundary,obj.ShowLight],... obj.MessageService.BoundaryModel); set(hs,'FaceAlpha',0.7); set(hs,'Tag','MainResponse') % If the old view angle was 2d we swap to 3d default, other wise we leave % it alone. So if we swap between models we retain the same view angle. if( az==0 && el==90 ) view(obj.hAxes, 3); else view(obj.hAxes, [az, el]); end mv_rotate3d(obj.hAxes,'ON'); end function plotContour(obj,x) view(obj.hAxes,[0 90]); mv_rotate3d(obj.hAxes,'off'); cmodel = obj.MessageService.BoundaryModel; [~,hs]=contour(obj.MessageService.Model,x,obj.hAxes,[],... [1,1,obj.InputIndices(1)<obj.InputIndices(2)],... cmodel); set(hs,'HitTest','off','Tag','MainResponse'); end function plotLine(obj,x) %plotLine view(obj.hAxes,[0 90]); mv_rotate3d(obj.hAxes,'off'); xi = x{obj.InputIndices(1)}; mdl = obj.MessageService.Model; bdry = xregGui.intervalPatch1D('Parent', obj.hAxes, ... 'FaceColor', mbcbdrycolor); col = obj.hAxes.ColorOrder; if pevcheck(mdl) % can calculate confidence interval df = dferror(mdl); if isfinite(df) && df<1000 ni = tinv(0.975,df); else ni = norminv(0.975); end % use pevgrid to generate pe and yhat [PE,~,~,yi]= pevgrid(mdl,x); yi= squeeze(yi); p = squeeze(sqrt(PE)); % ci's yhi= yi+ni*p; ylo= yi-ni*p; % include confidence intervals in plot h = plot(obj.hAxes,xi,yi,'-',... xi,yhi,'--',xi,ylo,'--',... 'Color',col(1,:)); else % just evaluate response YI = GenTable(mdl,x); yi = squeeze(YI); h = plot(obj.hAxes,xi,yi,'-',... 'Color',col(1,:)); end set(h(1),'Tag','MainResponse') % boundary model cmodel = obj.MessageService.BoundaryModel; if ~isempty(cmodel) cvals= squeeze(constraintDistanceGrid(cmodel,x)); ConstraintEdges = xregGui.intervalPatch1D.convertConstraintVector( xi, cvals); set(bdry,'OpenIntervals',ConstraintEdges); end xlab =InputLabels(mdl); xlabel(obj.hAxes,xlab{obj.InputIndices},'Interpreter','none') ylabel(obj.hAxes,ResponseLabel(mdl),'Interpreter','none') end function x = zoomConstraints(obj,x) %zoomConstraints zoom ranges inside boundary model cmodel = obj.MessageService.BoundaryModel; if ~isempty(cmodel) cvals= squeeze(constraintDistanceGrid(cmodel,x)); indices = sort(obj.InputIndices); if length(obj.InputIndices)>1 inside = any(cvals<1e-6,2); x{indices(1)} = findRegion(x{indices(1)},inside); inside = any(cvals<1e-6,1); x{indices(2)} = findRegion(x{indices(2)},inside); else inside = cvals<1e-6; x{indices} = findRegion(x{indices},inside); end end end function plotMultiline(obj,x) view(obj.hAxes,[0 90]); mv_rotate3d(obj.hAxes,'off'); if obj.ZoomToBoundary cmodel = []; else cmodel = obj.MessageService.BoundaryModel; end mdl = obj.MessageService.Model; h = multiline(mdl,x,obj.hAxes,obj.InputIndices(1)<obj.InputIndices(2),cmodel,'parula'); set(h,'Tag','MainResponse') end function selectDataPoint( obj, ~, ~ ) X = double(obj.MessageService.XData); X = X(obj.MessageService.DataOK,:); nX = size( X, 1 ); list = num2str( [(1:nX).', X], 4 ); % Throw up a list dialog [index, ok] = mv_listdlg( ... 'ListString', list, ... 'SelectionMode', 'Single', ... 'InitialValue', 1, ... 'ListSize', [320 300], ... % [width height] of listbox in pixels 'Name', 'Select Data Point', ... 'OkString', 'OK', ... 'uh', 25, ... 'ffs', 3 ); if ok point = X(index,:); obj.setSlicepoint(point) obj.updateTableValues % Draw the new surface obj.drawResponseSurface; end end function editSlice(obj,~, evt) % If the user edits the first column (value) then a complete % re-draw is required. However, if they only edit a tolerance then % we only need to redisplay the points. types = obj.hSliceTable.VariableTypes; switch evt.Data.Columns case 2 % The user is editing column one, the evaluation points if types(evt.Data.Rows,1)==1 obj.CrossSection(evt.Data.Rows,1) = evt.Data.NewValue.getScalar; obj.drawResponseSurface; end case 3 % The user is editing column two, the tolerances obj.CrossSection(evt.Data.Rows,2) = evt.Data.NewValue.getScalar; obj.drawPoints; end end function editInputIndex(obj, index ) obj.setInputIndex( obj.hAxisPopups(index).Value, index ); end end end function x = findRegion(x,inside) %findRegion find region inside boundary % inside is a logical array first = find(inside,1,'first'); last = find(inside,1,'last'); if ~isempty(first) first = max(first-1,1); last = min(last+1,length(inside)); x = linspace(x(first),x(last),length(x)); end end