www.gusucode.com > mbctools 工具箱 matlab 源码程序 > mbctools/+tpsetup/ModelData.m
classdef ModelData < handle %ModelData Data model for test plan setup % Copyright 2014-2016 The MathWorks, Inc. and Ford Global Technologies, Inc. properties (Constant) %TypeList types of test plans TypeList = {'One-Stage','Two-Stage','Point-by-Point'} %Icon large icon for JList Icon = 'testplan.bmp'; end properties %BuiltIn builtin test plan templates BuiltIn = {}; %BuiltInNames names for builtin test plan templates BuiltInNames = {}; %CurrentTestplans test plans in current MBCMODEL project CurrentTestplans = {} %CurrentNames names of test plans in current MBCMODEL project CurrentNames = {}; %UserTemplateFiles test plan template files UserTemplateFiles = {}; %UserTemplateNames names of test plan templates UserTemplateNames = {}; %Boundary fit boundary model Boundary= true; %FinalTestplan final test plan to build FinalTestplan %ValidationPercent percentage of fitting data to use for validation ValidationPercent = 20; %ValidationData validation data set pointer ValidationData = xregpointer; end properties (AbortSet,SetObservable) %type of validation data ValidationType = 'none'; %SelectedIndex index to selected testplan SelectedIndex = 0; %InputsOK inputs defined for all stages InputsOK = true; end properties %Project MBC Model project pointer Project %OpenDataEditor OpenDataEditor = false; %UseDataRange = true; UseDataRange = true; %Dir template directory Dir FilterDatasets = true; end properties (Dependent,AbortSet,SetObservable) %pData pointer selected data set pData = xregpointer; %Selected selected test plan (mdevtestplan) Selected end properties (Access=private) %pDataStorage private storage for dependent property pData pDataStorage = xregpointer; %SelectedStorage private storage for dependent property Selected SelectedStorage end properties(Dependent) %TypeIndex index to current test plan type (1=One-Stage, 2=Two-stage, 3=Point-by-point) TypeIndex %pDataList list of data sets pDataList %index to pDataIndex %list of validation data sets pValidationSets end methods function obj = ModelData(pProject,pData,FilterDatasets) %ModelData constructor obj.Project = pProject; obj.Dir = mbcGetPath('mbcmodel', 'Designs'); addBuiltinTemplates(obj) if nargin>2 obj.FilterDatasets = FilterDatasets; end if nargin>1 obj.pData = pData; end addUserTemplates(obj); addCurrentTestplans( obj ); selectTestplan(obj,1); end function TypeIndex = get.TypeIndex(obj) TypeIndex = find(strcmpi(type(obj.Selected),obj.TypeList)); end function dp = get.pDataList(obj) dp = obj.Project.dataptrs; nf = nfactors( HSModel(designdev(obj.Selected) )); Valid= false(size(dp)); for i=1:length(dp) % dataset must have more than nf variables Valid(i)= dp(i).size(2) >= nf && dp(i).size(1)>0; end dp = dp(Valid); end function set.pData(obj,pData) if isempty(obj.Selected) || ismember(pData,obj.pDataList) % data set selected and in project list obj.pDataStorage = pData; addUserTemplates(obj); addCurrentTestplans( obj ) end end function pData = get.pData(obj) pData = obj.pDataStorage; end function set.Selected(obj,T) obj.SelectedStorage = T; dlist = obj.pDataList; if obj.FilterDatasets && ~any(obj.pData==dlist) if isempty(dlist) % select first valid data set % deselect data set obj.pData = xregpointer; else obj.pData = dlist(1); end end end function s = get.Selected(obj) s = obj.SelectedStorage; end function Index = get.pDataIndex(obj) Index = find(obj.pData==obj.pDataList); end function OK = hasData(obj) OK = ~isnull(obj.pData); end function addBuiltinTemplates(obj) %addBuiltinTemplates builtin test plan templates % load templates and populate the listbox % builtin templates=[]; load('tpbuiltintemps.mat'); % user obj.BuiltIn= templates; for i=1:length(obj.BuiltIn) obj.BuiltInNames{i} = name( templates{i} ); end end function addUserTemplates( obj,Dir ) %addUserTemplates add user defined templates to the listctrl if nargin>1 obj.Dir = Dir; end userfiles= dir(fullfile(obj.Dir, '*.MBT')); mbtnames = cell(1,length(userfiles)); if isnull(obj.pData) ChannelNames = {}; else ChannelNames = get(obj.pData.info,'Name'); end OK = true(1,length(userfiles)); for n=1:length(userfiles) [~,mbtnames{n}] = fileparts(userfiles(n).name); try Ti = struct2cell(load('-mat',fullfile(obj.Dir,userfiles(n).name))); checkmodel(Ti{1}); catch OK(n) = false; continue end if OK(n) && ~isempty(ChannelNames) % only show test plan if all inputs are in the data set Inps = getInputs(Ti{1}); Inps = cat(1,Inps{:}); OK(n)= all(ismember({Inps.Name},ChannelNames)); end end obj.UserTemplateFiles= userfiles(OK); obj.UserTemplateNames =mbtnames(OK); end function addCurrentTestplans( obj ) %addCurrentTestplans add test plans from current MBCMODEL project tps = obj.Project.children(@MakeTemplate); if ~isnull(obj.pData) OK = true(1,length(tps)); if isnull(obj.pData) || ~obj.FilterDatasets ChannelNames = {}; else ChannelNames = get(obj.pData.info,'Name'); end for i=1:length(tps) Inps = getInputs(tps{i}); Inps = cat(1,Inps{:}); OK(i)= all(ismember({Inps.Name},ChannelNames)); end tps = tps(OK); end obj.CurrentTestplans = tps; obj.CurrentNames = cellfun(@name,tps,'UniformOutput',false); end function selectTestplan(obj,ind) %selectTestplan select test plan from list if ind~=obj.SelectedIndex if ind<=length(obj.BuiltIn) % builtin T= obj.BuiltIn{ind}; else i = ind-length(obj.BuiltIn); if i<=length(obj.UserTemplateFiles) Ti = struct2cell(load('-mat',fullfile(obj.Dir,obj.UserTemplateFiles(i).name))); T= Ti{1}; else i = ind-length(obj.BuiltIn)-length(obj.UserTemplateFiles); T = obj.CurrentTestplans{i}; end end obj.Selected = T; obj.SelectedIndex = ind; end end function createTestplan(obj) %createTestplan create template T = obj.FinalTestplan; % create test plan and add to tree pTP = xregpointer(T); AddChild(info(obj.Project),pTP); % make name of test plan unique pTP.name(pTP.name); pTP.info = cacheTSSF(pTP.info); if ~isnull(obj.pData) % attach data to test plan if necessary T = info(pTP); T = setmatched(T,false); % prepare data for use in test plan % setupTSSF makes a copy of the data if the data is used in % another testplan. This could cause a new data pointer. T = setupTSSF(T,obj.pData); % don't broadcast these changes obj.pDataStorage = DataLinkPtr(T); % setup test groups [obj.pData.info,OK] = setupGroups(T,info(obj.pData)); if ~OK % setupGroups cancelled so clean up data % update private pDataStorage (required to set data to % null) obj.pDataStorage = xregpointer; T = DataLinkPtr(T,obj.pData); % clean up extra data created by setupTSSF cleanupData(info(obj.Project),address(T)); end obj.FinalTestplan = T; end obj.FinalTestplan = info(pTP); if pTP.isBrowserProject % add to browser and select if relevant treeview(MBrowser,pTP,'add') SelectNode(MBrowser,pTP); end end function fitmodels(obj) %fitmodels fit models to selected data T = obj.FinalTestplan; pFitData = obj.pData; % create validation data subset checkLargeData(obj,pFitData); % don't attempt to attach empty data if ~isempty(pFitData.info) switch obj.ValidationType case 'none' case {'random','last'} pFitData = createValidationSubset(obj); end % fit models in test plan T = setmatched(info(T),false); T = DataLinkPtr(T,xregpointer); if ~isnull(obj.ValidationData) % attach validation data first because it may be needed for % fit statistics valdata(info(T),sweepsetfilter(obj.ValidationData)); end attachData(info(T),pFitData,... 'UseDataRange',logical(obj.UseDataRange),... 'Boundary',logical(obj.Boundary)); end if address(T)==get(MBrowser,'CurrentNode') % setup framework again if necessary frameWork = GetViewData(MBrowser); change(frameWork,address(T)); end end function checkLargeData(obj,pFitData) %checkDataSizes use large data options ssf = info(pFitData); T = obj.FinalTestplan; D = designdev(T); TS = HSModel(D); ChangeModel = false; switch lower(type(T)) case 'one-stage' if size(ssf,1)>2000 % more than 2000 points mLarge = xregCreateModel(@xreggpr,TS); if ~isequal(mLarge,TS) ChangeModel = true; TS = mLarge; end end case 'two-stage' if size(ssf,3)>2000 % more than 1000 tests m = get(TS,'baseglobal'); m = xregCreateModel(@xregcubic,m); % use a polynomial mLarge = set(m,'order',2*ones(1,nfactors(m))); if ~isequal(mLarge,m) ChangeModel = true; TS = set(TS,'global',mLarge); end end case 'point-by-point' if size(ssf,3)>100 || any(tsizes(sweepset(ssf))>2000) % more than 100 tests or a test with more than 2000 % points ChangeModel = true; L = get(TS,'Local'); % use a default GPM m = xregCreateModel(@xreggpr,L); L = set(L,'models',{m}); TS = set(TS,'Local',L); end end if ChangeModel %update testplan response models updateResponseModels(T,TS); end end function sendToDataEditor(obj,varargin) %sendToDataEditor open data editor from test plan for fit models T = info( obj.FinalTestplan ); if nargin==1 Args = {obj.pData,T,[],true}; else Args = varargin; end % call processTestplanData to process data frameWork = GetViewData(MBrowser); ms = frameWork.MessageService; if isnull(ms.Pointer) % setup framework again if necessary change(frameWork,get(MBrowser,'CurrentNode')); end editData(ms, Args{:},@obj.processTestplanData); end function processTestplanData(obj,pSSF,newData,changes) %processTestplanData process test plan data after the test plan Fit models wizard % make validation data if necessary T = info( obj.FinalTestplan ); switch obj.ValidationType case {'random','last'} OldData = pSSF.info; pSSF.info = newData; pSSF = createValidationSubset(obj); newData = pSSF.info; pSSF.info = OldData; end if obj.UseDataRange Inputs = getInputs(T); % use data ranges for model inputs for i=1:length(Inputs) D = newData(:,{Inputs{i}.Name}); Inputs{i} = DataRange(Inputs{i},D); end T = setInputs(T,Inputs); end modifyData(T, pSSF, newData,changes); if obj.Boundary buildBoundaryModels(info(T)); end if ~isnull(obj.ValidationData) valdata(info(T),sweepsetfilter(obj.ValidationData)); end end function pValList = get.pValidationSets(obj) % list of possible validation data - must have all channels that are in the main dataset if ~isnull(obj.pData) Channels = get(obj.pData.info,'name'); pValList = obj.pDataList(obj.pDataList~=obj.pData); OK = parrayeval(pValList,@(D) all(ismember(Channels,get(D,'name'))),{},@false); pValList = pValList(OK); else pValList = mbcpointer(1,0); end end end methods (Access=private) function pFitData = createValidationSubset(obj) %createValidationSubset create validation data set as subset of fit data pFitData = obj.pData; T = info(obj.FinalTestplan); % add a variable to index validation data ssf = pFitData.info; vars = get(ssf,'name'); valVariable = 'mbcValSelector'; if any(strcmp(valVariable,vars)) % remove any mbcValSelector variables and filters from ssf f = get(ssf,'filters'); if ~isempty(f) remFilters = ~cellfun(@isempty,strfind({f.filterExp},valVariable)); if any(remFilters) ssf = removeFilter(ssf,remFilters); end end f = get(ssf,'sweepfilters'); if ~isempty(f) remFilters = ~cellfun(@isempty,strfind({f.filterExp},valVariable)); if any(remFilters) ssf = removeSweepFilter(ssf,remFilters); end end % remove user variables v = get(ssf,'variables'); if ~isempty(v) ssf = removeVariable(ssf,find(strcmp(valVariable,{v.varName}))); end v = get(ssf,'sweepvariables'); if ~isempty(v) ssf = removeSweepVariable(ssf,find(strcmp(valVariable,{v.varName}))); end end fAddFcn = @addVariable; if strcmp(obj.ValidationType,'random') % sample points at random vardef = sprintf('%s = mbcRandomSelection(%s,%d)',valVariable,vars{1},sum(clock)); else vardef = sprintf('%s = mbcLastSelection(%s)',valVariable,vars{1}); if strcmp(type(T),'Point-by-Point') % need indices per test for last % of tests fAddFcn = @addSweepVariable; end end ssf = fAddFcn(ssf,vardef); pFitData.info = ssf; % make a copy of the data for validation - this has a common base data with validation % selector variable ssf = copy(sweepsetfilter(ssf)); ssf = set(ssf,'Label',[get(ssf,'Label'),' Validation']); pValData = xregpointer(ssf); addData(obj.Project.info,pValData); % add filters switch type(T) case 'One-Stage' % one-stage has ordinary filters pFitData.info = addFilter(pFitData.info,sprintf('%s > prctile(%s,%g)',valVariable,valVariable,obj.ValidationPercent)); pValData.info = addFilter(pValData.info,sprintf('%s <= prctile(%s,%g)',valVariable,valVariable,obj.ValidationPercent)); case 'Point-by-Point' % point-by-point filters operate on a per sweep basis pFitData.info = addSweepFilter(pFitData.info,sprintf('%s > prctile(%s,%g)',valVariable,valVariable,obj.ValidationPercent)); pValData.info = addSweepFilter(pValData.info,sprintf('%s <= prctile(%s,%g)',valVariable,valVariable,obj.ValidationPercent)); case 'Two-Stage' % select whole sweeps based on first element in mbcValSelector for each sweep % last % will be based on record indices pFitData.info = addSweepFilter(pFitData.info,sprintf('~mbcTestSelector(%s,%d)',valVariable,obj.ValidationPercent)); pValData.info = addSweepFilter(pValData.info,sprintf('mbcTestSelector(%s,%d)',valVariable,obj.ValidationPercent)); end obj.ValidationData = pValData; end end end