www.gusucode.com > mbctools 工具箱 matlab 源码程序 > mbctools/+mbcmodelview/+testplan/MessageService.m
classdef MessageService < mbcmodelview.MessageService %MessageService Model cross-section MessageService for GraphView class % MessageService that can be used with the GraphView class to update % a cross-section plot for a model % Copyright 2014-2016 The MathWorks, Inc. and Ford Global Technologies, Inc. properties (AbortSet) %ShowDataPoints Boolean indicating if data points should be plotted % on the cross section view ShowDataPoints=true; %ShowConstraints Boolean indicating if constraint limits be plotted % on cross section view ShowConstraints=true; %ZoomConstraints Boolean indicating if X-axis should be zoomed in % on the boundary limits ZoomConstraints=false; %ShowErrorLines Boolean indicating if error lines should be plotted ShowErrorLines = true; %ConfidenceIntervalLevel Confidence interval as a percentage ConfidenceIntervalLevel = 95; %ShowCommonYAxis show common Y axis for all plots ShowCommonYAxis = true; %OperatingPointValues Values for operating points OperatingPointValues = []; %OperatingPointNames Operating point names OperatingPointNames = {}; %SelectionType block diagram selection type ('inputs','model','response') SelectionType=''; %CurrentStage currently selected stage (1,2,[]) CurrentStage %EditMode name of editor being used ('data','DoE','') EditMode = ''; end properties (SetAccess=private) %CurrentTest The currently selected test point CurrentTest = 1; %MaxTestNumber Number of tests in current node MaxTestNumber = 0; end properties (Dependent,SetAccess=private) %IsPointByPoint Flag indicating if the current model is point-by-point IsPointByPoint = false; %ModelFitted array indicating which response has fitted models ModelFitted %NumStages number of stages NumStages %StageName name for stage StageName end properties (Dependent) %DesignDev designdev for current stage DesignDev %Testplan current test plan object Testplan end properties (Access=private) IsInitializing = false; end properties(Dependent,SetAccess=private) %Title standard title is the name of the response Title end events (NotifyAccess=private) OptionChanged TestChanged end methods function obj=MessageService() %MessageService Constructor for MessageService obj.Actions = mbcmodelview.testplan.Actions(obj); end function set.ShowErrorLines(obj, value) %set.ShowErrorLines Set method for ShowErrorLines property % Will fire the OptionChanged event obj.ShowErrorLines = value; notifyOptionChanged(obj,'ShowErrorLines'); end function set.ConfidenceIntervalLevel(obj, value) %set.ConfidenceIntervalLevel Set method for ConfidenceIntervalLevel property % Will fire the OptionChanged event obj.ConfidenceIntervalLevel = value; notifyOptionChanged(obj,'ConfidenceIntervalLevel'); end function set.ShowDataPoints(obj, value) %set.ShowDataPoints Set method for ShowDataPoints property % Will fire the OptionChanged event obj.ShowDataPoints = value; data = xregEventData(struct('Option', 'ShowDataPoints')); notify(obj,'OptionChanged', data); end function set.ShowConstraints(obj, value) %set.ShowConstraints Set method for ShowConstraints property % Will fire the OptionChanged event obj.ShowConstraints = value; notifyOptionChanged(obj,'ShowConstraints'); end function set.ZoomConstraints(obj, value) %set.ZoomConstraints Set method for ZoomConstraints property % Will fire the OptionChanged event obj.ZoomConstraints = value; notifyOptionChanged(obj,'ZoomConstraints'); end function set.ShowCommonYAxis(obj, value) %set.ShowCommonYAxis Set method for ShowCommonYAxis property % Will fire the OptionChanged event obj.ShowCommonYAxis = value; notifyOptionChanged(obj,'ShowCommonYAxis'); end function d = get.DesignDev(obj) d = designdev(obj.Testplan); d= d(obj.CurrentStage); end function set.DesignDev(obj,ds) d = designdev(obj.Testplan); d(obj.CurrentStage)=ds; designdev(obj.Testplan,d); end function T = get.Testplan(obj) T = info(obj.Pointer); end function t = get.Title(obj) t = name(obj.Testplan); end function set.Testplan(obj,T) if obj.Pointer==address(T) xregpointer(T); else error('Invalid test plan'); end end function n = get.NumStages(obj) n = numstages(obj.Testplan); end function setNewTestPlan(obj, newPointer) %setNewTestPlan update message service to point to a new test plan node % Will fire the NodeChanged event obj.Pointer = newPointer; obj.EditMode = ''; if obj.IsPointByPoint && newPointer.IsMatched testData = getdata(newPointer.info,'Y'); obj.MaxTestNumber = size(testData, 3); if obj.CurrentTest>obj.MaxTestNumber obj.CurrentTest=obj.MaxTestNumber; end end obj.CurrentStage = obj.NumStages; updateOperatingPointValues(obj); fireNodeChanged(obj) end function updateCurrentTest(obj, testNumber) %updateCurrentTest Set the CurrentTest property % Will fire the NodeChanged and NodeUpdated events if testNumber<=obj.MaxTestNumber && testNumber>=1 obj.CurrentTest=testNumber; updateOperatingPointValues(obj) end fireNodeChanged(obj) update(obj) end function change(obj, newPointer) %change change or reset test plan % change(obj, newPointer) % change(obj) % change is the equivalent of a setNewTestPlan and update if nargin<2 % use current test plan newPointer = obj.Pointer; end if ~isnull(newPointer) setNewTestPlan(obj, newPointer) update(obj) end end function update(obj) %update update message services fireNodeUpdated(obj) end function OK = editing(obj,Mode) if nargin<2 OK = ~isempty(obj.EditMode); else OK = strcmpi(obj.EditMode,Mode); end end function deserialize(obj,s) %deserialize deserialize cross-section options to MessageService % don't fire events while deserializing obj.IsInitializing = true; % restore CurrentTest updateCurrentTest(obj, s.CurrentTest); % have to update MessageService copies of Options obj.ConfidenceIntervalLevel = s.ConfidenceIntervalLevel; obj.ShowDataPoints = s.ShowDataPoints; obj.ShowConstraints = s.ShowConstraints; obj.ZoomConstraints = s.ZoomConstraints; obj.ShowErrorLines = s.ShowErrorLines; obj.ShowCommonYAxis = s.ShowCommonYAxis; obj.IsInitializing = false; fireNodeChanged(obj) end function pbp = get.IsPointByPoint(obj) %get.IsPointByPoint returns boolean indicating if current node % is a point-by-point model pointer = obj.Pointer; pbp = ~isnull(pointer) && (pointer.numstages == 2); if pbp models = children(obj.Testplan,@model); isPBP = cellfun(@(m)isa(m, 'localmulti'), models); pbp = pbp && ((~isempty(models) && all(isPBP)) || strcmpi( type(obj.Testplan),'point-by-point')); end end function OK = get.ModelFitted(obj) if ~isempty(obj.Pointer) && obj.Pointer.numChildren>0 if obj.IsPointByPoint [~,OK] = obj.Pointer.children(@(mdev) LocalModel(mdev,obj.CurrentTest)); else OK = obj.Pointer.children(@hasBest); end OK = [OK{:}]; else OK = false(1,0); end end function s = get.StageName(obj) if obj.NumStages==1 s = ''; else if obj.CurrentStage == 1 s = 'Local'; elseif obj.IsPointByPoint s = 'Operating Point'; else s = 'Global'; end end end function editData(obj, pSSF,OldTP,oldTSSF,DO_DELETE,fProcessData) %editData Push a data object to the data editor % editData(obj, pSSF,OldTP,oldTSSF,DO_DELETE,fProcessData) T = obj.Testplan; if nargin < 2 pSSF = DataLinkPtr(T); end if nargin < 3 OldTP = T; end if nargin < 4 oldTSSF = info(DataLinkPtr(T)); end if nargin < 5 dataPointers = dataptrs( info(project(T)) ); DO_DELETE = ~any(T.DataLink==dataPointers); end if nargin<6 fProcessData = @obj.applyDataChanges; end % callback to close data editor fCloseEditor = mbcutils.callback(@obj.closeDataEditor, OldTP,oldTSSF,DO_DELETE,fProcessData); % always edit and test plan hData = xregdatagui.Editor.open(pSSF,true,true,fCloseEditor); if ~isempty(hData) % Register as a subfigure registerSubFigure(obj,hData.Figure); end end end methods (Access=protected) function notifyOptionChanged(obj,option) %notifyOptionChanged Fires a OptionChanged event with the event % data being the name of the option that was changed if ~obj.IsInitializing data = xregEventData(struct('Option', option)); notify(obj,'OptionChanged', data); end end function fireNodeChanged(obj) if ~obj.IsInitializing notify(obj,'NodeChanged'); end end function fireNodeUpdated(obj) if ~obj.IsInitializing notify(obj,'NodeUpdated'); end end function updateOperatingPointValues(obj) %updateOperatingPointValues Will update the operating point % names and values for the current node (and test if a % point-by-point model is selected) if obj.Pointer.IsMatched && obj.IsPointByPoint currNode = obj.Pointer.info; X = getdata(currNode,'fit'); numLocal = size(X{1},2); numGlobal = size(X{2},2); allInputs = factors(currNode); obj.OperatingPointNames = allInputs(numLocal+1:numLocal+numGlobal); obj.OperatingPointValues = X{2}{obj.CurrentTest}; else obj.OperatingPointValues = []; obj.OperatingPointNames = {}; end end function closeDataEditor(obj,hData, evt, originalT,oldTSSF,DO_DELETE,fProcessData) %closeDataEditor close data editor and process data % Make sure that testplan is uptodate T = obj.Testplan; % Get the pointer being edited pSSF = hData.UserData.ObjectBeingEdited; % Is the pointer location to copy back to still valid? - Clean up if not. % After this section we can assume that we have a valid pointer. Don't know % how this situation could arise but we'll keep this just in case! if ~isvalid(pSSF) xregerror('Data Error', 'Data heap corruption - try recreating this testplan'); % Update the view update(obj) return end newData = hData.NewData; % Need to ensure that one stage testplans have one stage data - maybe % in the long run 1 stage testplans will model the sweep mean of the % response in which case this special test doesn't need to exist. [newData,OK] = setupGroups(T,newData); if ~OK % ensure that users setup groups correctly evt.CancelClose = true; if numstages(T)==1 errordlg('You must use one-stage data for one-stage models','Data','modal'); else errordlg('You must use define test groups for two-stage or point-by-point models. Define test groups in the data editor.','Data','modal'); end return end % Apply the cluster settings to this copy - someone is going to want to % know about the design inside. newData = applyClusterSettings(newData); % Before we un-cache the data lets ask what has happened to it % Get some strings to display in the dialog boxes that appear [changes,questMsg] = pAssessDataChanges(T, newData); if changes.INPUT_SIGNAL_REMOVED || any(changes.RESPONSE_SIGNAL_REMOVED) % Split behaviour on INPUT_SIGNAL_REMOVED - can't really continue if this % is the case with the new data - so choice is to revert to old data or % cancel dlgopts = struct('Default', 'Cancel', 'Interpreter', 'tex'); out = questdlg(questMsg, 'Data Selection', 'OK', 'Cancel', dlgopts); if strcmp(out, 'OK') % Indicate that changes are not to be accepted out = 'No'; end elseif ~isempty(questMsg) % Only ask the user if there is something to ask about! dlgopts = struct('Default', 'Yes', 'Interpreter', 'tex'); out = questdlg(questMsg, 'Data Selection', 'Yes', 'No', 'Cancel', dlgopts); elseif isempty(newData) % don't update new data out = 'No'; else % Default - This means no discernable change has occurred - Probably % ought to go for No but if we only refit different models out = 'Yes'; end % Getting here indicates that the user clicked either yes or no, but not % cancel switch out case 'Yes' % Write the new data correctly into the project such that pSSF % now contains the new data try fProcessData(pSSF,newData,changes) catch ME Restore(T, originalT, oldTSSF,DO_DELETE); xregerror('Data Error',sprintf('Error updating testplan with new data: %s',ME.message)); end case 'No' Restore(T, originalT, oldTSSF,DO_DELETE); otherwise evt.CancelClose = true; return end obj.EditMode = ''; % Update the view % update view if pointer hasn't been changed if obj.Pointer==address(T) change(obj) end end function applyDataChanges(obj, pSSF, newData, changes) %applyChanges default method to apply data changes modifyData(obj.Testplan, pSSF, newData, changes); end end end