www.gusucode.com > mbctools 工具箱 matlab 源码程序 > mbctools/+xregbdrygui/BdryPairwiseData.m

    classdef BdryPairwiseData < mbcgui.widget.ScrollTableData
    %xregbdrygui.BdryPairwiseData class
    %   xregbdrygui.BdryPairwiseData extends mbcgui.widget.ScrollTableData
    %
    %    xregbdrygui.BdryPairwiseData properties:
    %       MessageService - Property is of type 'handle'
    %       NPoints - Property is of type 'int'
    %       NBins - Property is of type 'int'
    %       Primes - Property is of type 'MATLAB array'
    %       Points - Property is of type 'MATLAB array'
    %       Values - Property is of type 'MATLAB array'
    %       Bins - Property is of type 'MATLAB array'
    %       MidPoints - Property is of type 'MATLAB array'
    %       MainContours - Property is of type 'MATLAB array'
    %       HighlightContours - Property is of type 'MATLAB array'
    %       HighlightData - Property is of type 'MATLAB array'
    %
    %    xregbdrygui.BdryPairwiseData methods:
    %       getBlackDotXData - Get the XData required for the black dots
    %       getBlackDotYData - Get the YData required for the black dots
    %       getColumnCount - Return the number of columns in the data model.
    %       getEvaluationPoints - Access for evaluation points
    %       getHighlightContours - A short description of the function.
    %       getHighlightIndices - Get the indices of factors that are highlighted.
    %       getHighlightLineXData - Get the XData required for the highlight line
    %       getHighlightLineYData - Get the YData required for the highlight line.
    %       getMainContours - A short description of the function.
    %       getRedRingXData - Get the XData required for the red rings
    %       getRedRingYData - Get the YData required for the red rings
    %       getRowCount - Return the number of rows in the data model.
    %       getValidationXData - Get the XData required for the green dots
    %       getValidationYData - Get the YData required for the green dots
    %       setHighlight - Set a new highlight rectangle.
    
    % Copyright 2005-2015 The MathWorks, Inc. and Ford Global Technologies, Inc.
    
    properties (AbortSet)
        %MESSAGESERVICE Property is of type 'handle'
        MessageService = [];
        %NPOINTS Property is of type 'int'
        NPoints = 29791;
        %NBINS Property is of type 'int'
        NBins = 21;
        %PRIMES Property is of type 'MATLAB array'
        Primes = [];
        %POINTS Property is of type 'MATLAB array'
        Points = [];
        %VALUES Property is of type 'MATLAB array'
        Values = [];
        %BINS Property is of type 'MATLAB array'
        Bins = [];
        %MIDPOINTS Property is of type 'MATLAB array'
        MidPoints = [];
        %MAINCONTOURS Property is of type 'MATLAB array'
        MainContours = [];
        %HIGHLIGHTCONTOURS Property is of type 'MATLAB array'
        HighlightContours = [];
        %HIGHLIGHTDATA Property is of type 'MATLAB array'
        HighlightData = [];
    end
    
    
    methods  % constructor block
        function obj = BdryPairwiseData( varargin )
        % XREGBDRYGUI.BDRYPAIRWISEDATA class constructor
        
        
        % Get oursleves some prime numbers
        obj.Primes = primes( 100 );
        
        end  % BdryPairwiseData
        
    end  % constructor block
    
    methods
    end   % set and get functions
    
    methods  % public methods
        %----------------------------------------
        function X = getBlackDotXData(obj, R, C)
        %GETBLACKDOTXDATA Get the XData required for the black dots
        %   GETBLACKDOTXDATA(OBJ, R, C)
        
        BMS = obj.MessageService;
        data = BMS.getDataPoints;
        X = data(:,C);
        
        end  % getBlackDotXData
        
        %----------------------------------------
        function Y = getBlackDotYData(obj, R, C)
        %GETBLACKDOTYDATA Get the YData required for the black dots
        %   GETBLACKDOTYDATA(OBJ, R, C)
        
        BMS = obj.MessageService;
        data = BMS.getDataPoints;
        Y = data(:,R+1);
        
        end  % getBlackDotYData
        
        %----------------------------------------
        function nC = getColumnCount(obj)
        %GETCOLUMNCOUNT Return the number of columns in the data model.
        %   NC = GETCOLUMNCOUNT(OBJ) returns the number of columns in the data model.
        
        nC = obj.getRowCount;
        end  % getColumnCount
        
        %----------------------------------------
        function X = getEvaluationPoints(obj)
        %GETEVALUATIONPOINTS Access for evaluation points
        %   X = GETEVALUATIONPOINTS(OBJ)
        %   The points stored by the object are just a design on [0, 1]^d. This
        %   method provides access to points scalled on the correct domain for the
        %   current constraint.
        
        % We need to get some information about the current constraint from the
        % BMS.
        bms = obj.MessageService;
        cif = bms.getInputFactors;
        nf = length( cif );
        
        pUpdateEvaluationPoints( obj, obj.NPoints, nf );
        X = obj.Points(1:obj.NPoints,1:nf);
        
        % The evaluation points are then scaled on to the appropriate domain
        X = repmat( cif.Min, obj.NPoints, 1 ) + X * diag( cif.Max - cif.Min );
        
        end  % getEvaluationPoints
        
        %----------------------------------------
        function HC = getHighlightContours(obj, R, C)
        %GETHIGHLIGHTCONTOURS A short description of the function.
        %   GETHIGHLIGHTCONTOURS(OBJ, R, C)
        %   Returns a matrix of the form
        %        C = [level1 x1 x2 x3 ... level2 x2 x2 x3 ...;
        %             pairs1 y1 y2 y3 ... pairs2 y2 y2 y3 ...]
        %
        %   See also XREGCONTOURS2PATCHES.
        
        
        if isempty( obj.HighlightContours ),
            HC = [];
        else
            HC = obj.HighlightContours{C,R+1};
        end
        
        end  % getHighlightContours
        
        %----------------------------------------
        function [R, C] = getHighlightIndices(obj)
        %GETHIGHLIGHTINDICES Get the indices of factors that are highlighted.
        %   [R, C] = GETHIGHLIGHTINDICES(OBJ) returns the indices of the input
        %   factors on the row and column that are currently highlighted.
        
        R = 0;
        C = 0;
        
        HLData = obj.HighlightData;
        if ~isempty(HLData)
            bms = obj.MessageService;
            con = bms.getConstraint;
            if ~isempty(con)
                cif = getInputFactors(con);
                R = find(HLData.YFactor, cif);
                C = find(HLData.XFactor, cif);
            end
        end
        
        end  % getHighlightIndices
        
        %----------------------------------------
        function X = getHighlightLineXData(obj, R, C)
        %GETHIGHLIGHTLINEXDATA Get the XData required for the highlight line
        %   X = GETHIGHLIGHTLINEXDATA(OBJ, R, C)
        
        X = [];
        if ~isempty( obj.HighlightData )
            bms = obj.MessageService;
            con = bms.getConstraint;
            if ~isempty(con)
                cif = getInputFactors(con);
                if isequal(obj.HighlightData.XFactor, cif(C)) ...
                        && isequal(obj.HighlightData.YFactor, cif(R+1)) ...
                        X = obj.HighlightData.Rectangle([1,1,2,2,1],1);
                end
            end
        end
        
        end  % getHighlightLineXData
        
        %----------------------------------------
        function Y = getHighlightLineYData(obj, R, C)
        %GETHIGHLIGHTLINEYDATA Get the YData required for the highlight line.
        %   Y = GETHIGHLIGHTLINEYDATA(OBJ, R, C)
        
        Y = [];
        if ~isempty( obj.HighlightData )
            bms = obj.MessageService;
            con = bms.getConstraint;
            if ~isempty(con)
                cif = getInputFactors(con);
                if isequal(obj.HighlightData.XFactor, cif(C)) ...
                        && isequal(obj.HighlightData.YFactor, cif(R+1))
                    Y = obj.HighlightData.Rectangle([1,2,2,1,1],2);
                end
            end
        end
        
        end  % getHighlightLineYData
        
        %----------------------------------------
        function HC = getMainContours(obj, R, C)
        %GETMAINCONTOURS A short description of the function.
        %   GETMAINCONTOURS(OBJ, R, C)
        %   Returns a matrix of the form
        %        C = [level1 x1 x2 x3 ... level2 x2 x2 x3 ...;
        %             pairs1 y1 y2 y3 ... pairs2 y2 y2 y3 ...]
        %
        %   See also XREGCONTOURS2PATCHES.
        
        if isempty( obj.MainContours ),
            HC = [];
        else
            HC = obj.MainContours{C,R+1};
        end
        
        end  % getMainContours
        
        %----------------------------------------
        function X = getRedRingXData(obj, R, C)
        %GETREDRINGXDATA Get the XData required for the red rings
        %   GETREDRINGXDATA(OBJ, R, C)
        
        BMS = obj.MessageService;
        data = BMS.getDataPoints;
        bp = BMS.getBoundaryPoints;
        X = data(bp,C);
        
        end  % getRedRingXData
        
        %----------------------------------------
        function Y = getRedRingYData(obj, R, C)
        %GETREDRINGYDATA Get the YData required for the red rings
        %   GETREDRINGYDATA(OBJ, R, C)
        
        BMS = obj.MessageService;
        data = BMS.getDataPoints;
        bp = BMS.getBoundaryPoints;
        Y = data(bp,R+1);
        
        end  % getRedRingYData
        
        %----------------------------------------
        function nR = getRowCount(obj)
        %GETROWCOUNT Return the number of rows in the data model.
        %   NR = GETROWCOUNT(OBJ) returns the number of rows in the data model.
        
        bms = obj.MessageService;
        if isempty( bms )
            nR = 0;
        else
            nR = max(0,length( bms.getInputFactors ) - 1);
        end
        
        end  % getRowCount
        
        %----------------------------------------
        function [dotXs, crossXs] = getValidationXData(obj, R, C)
        %GETVALIDATIONXDATA Get the XData required for the green dots
        %   GETVALIDATIONXDATA(OBJ, R, C)
        
        BMS = obj.MessageService;
        [data, inside] = BMS.getValidationPoints;
        if ~isempty(data)
            crossXs = data(~inside,C);
            dotXs = data(inside,C);
        else
            crossXs = [];
            dotXs = [];
        end
        
        end  % getValidationXData
        
        %----------------------------------------
        function [dotYs, crossYs] = getValidationYData(obj, R, C)
        %GETVALIDATIONYDATA Get the YData required for the green dots
        %   GETVALIDATIONYDATA(OBJ, R, C)
        
        BMS = obj.MessageService;
        [data, inside] = BMS.getValidationPoints;
        if ~isempty(data)
            crossYs = data(~inside,R+1);
            dotYs = data(inside,R+1);
        else
            crossYs = [];
            dotYs = [];
        end
        end  % getValidationYData
        
        %----------------------------------------
        function contourData = pComputeContourData( obj, values )
        %PCOMPUTECONTOURDATA Compute the projection contours.
        %   CONTOURDATA = PCOMPUTECONTOURDATA( OBJ, VALUES )
        %   Note that this method requires that the distance values be passed in
        %   and that it returns the contour data. This allows this method to be
        %   used to compute both main and the highligh contours.
        
        
        % We need to get some information about the current constraint from the
        % BMS.
        bms = obj.MessageService;
        con = bms.getConstraint;
        cif = bms.getInputFactors;
        nf = length( cif );
        ai = getActiveIndices( con );
        
        % And some information from the object
        nBins = obj.NBins;
        bins  = obj.Bins;
        midPoints = obj.MidPoints;
        
        midPoints = repmat( cif.Min, obj.NBins, 1 ) + ...
            repmat( midPoints(:), 1, nf ) * diag( cif.Max - cif.Min );
        
        % Initialize the cell array into which the contour data will be put
        contourData = cell( nf, nf );
        
        % It is not uncommon to get some edges that don't look quite right. To
        % "fix" this, we convolve the resulting projection surface against the
        % following "mask". This smoothes out the edges a little.
        mask = [
            0 1 0
            1 2 1
            0 1 0
            ];
        
        effectiveInf = max( 1.0, 2 * max( values ) );
        nPoints = size( values, 1 );
        
        for i = 1:(nf-1),
            for j = (i+1):nf,
                
                D = repmat( effectiveInf, nBins, nBins );
                
                if any( ai == i ),
                    if any( ai == j ),
                        % Both i and j are active
                        for k = 1:nPoints,
                            ii = bins(k,i);
                            jj = bins(k,j);
                            
                            % We want to do something like:
                            %   >> D(ii,jj) = min( D(ii,jj), values(k) );
                            % but it is probably quicker to do:
                            if values(k) < D(ii,jj),
                                D(ii,jj) = values(k);
                            end
                        end
                        D = conv2( D, mask, 'same' );
                    else
                        % i is active but j is not
                        for k = 1:nPoints,
                            ii = bins(k,i);
                            % We want to do something like:
                            %   >> D(ii,:) = min( D(ii,:), values(k) );
                            % but it is probably quicker to do:
                            if values(k) < D(ii,1),
                                D(ii,:) = values(k);
                            end
                        end
                    end
                else
                    if any( ai == j ),
                        % j is active but i is not
                        for k = 1:nPoints,
                            jj = bins(k,j);
                            % We want to do something like:
                            %   >> D(:,jj) = min( D(:,jj), values(k) );
                            % but it is probably quicker to do:
                            if values(k) < D(1,jj),
                                D(:,jj) = values(k);
                            end
                        end
                    else
                        % neither is active
                        D(:) = -1;
                    end
                end
                
                if any( D(:) > 0 ),
                    
                    contourData{i,j} = i_FindContours( midPoints(:,i), midPoints(:,j), D.', 0 );
                    
                    %>> [xi, yi] = ndgrid( 0.5:obj.NBins+0.5 );
                    %>> D = interp2( D, 0.5:obj.NBins+0.5, (0.5:obj.NBins+0.5).' );
                    %>> obj.MainContours{i,j} = i_FindContours( edges(:,i), edges(:,j), D.', 0 );
                    
                else
                    %        C = [level1 x1 x2 x3 ... level2 x2 x2 x3 ...;
                    %             pairs1 y1 y2 y3 ... pairs2 y2 y2 y3 ...]
                    contourData{i,j} = [
                        0, cif(i).Min, cif(i).Min, cif(i).Max, cif(i).Max, cif(i).Min
                        5, cif(j).Min, cif(j).Max, cif(j).Max, cif(j).Min, cif(j).Min
                        ];
                end
            end
        end
        end  % pComputeContourData
        
        %----------------------------------------
        function pPostConstraintChange(obj)
        %PPOSTCONSTRAINTCHANGE Respond to a change in the constraint
        %   PPOSTCONSTRAINTCHANGE(OBJ)
        
        % We need to get some information about the current constraint from the
        % BMS.
        bms = obj.MessageService;
        con = bms.getConstraint;
        
        % If there is no constraint then there is nothing to do. We just leave all
        % the contours as empty.
        if isempty( con ),
            obj.MainContours = [];
            obj.HighlightContours = [];
            return
        end
        
        % Get evaluation points
        X = obj.getEvaluationPoints;
        
        % With the evaluation points all nicely set-up, the evaluation is easy:
        d = constraintDistance( con, X );
        obj.Values = d;
        
        % Find Contours
        obj.MainContours = obj.pComputeContourData( d );
        obj.pSelectHighlight;
        
        end  % pPostConstraintChange
        
        %----------------------------------------
        function pSelectHighlight(obj, RFactor, CFactor)
        %PSELECTHIGHLIGHT Respond to the highlight region being selected.
        %   PSELECTHIGHLIGHT(OBJ) redraws the highlight contour.
        
        highlightData = obj.HighlightData;
        
        if nargin==1
            % Derive R and C from the saved input factors
            [RFactor, CFactor] = obj.getHighlightIndices;
        end
        
        if  isempty( highlightData ) || RFactor==0 || CFactor==0
            obj.HighlightContours = [];
            return
        end
        
        % We should already have all the constraint evaluations inside the data
        % object (obj). If not, we'll have to fire the "pPostConstraintChange"
        % method.
        %
        % We need to compare the evaluation points with the ranges of the
        % highlight window. We can then set to +Inf the distance values for all
        % points outside the region.
        %
        % As the data has already been binned, we then just need to loops over all
        % the combinations of input factors computing the new contour data.
        
        % Check for appropriate data
        if isempty( obj.Points ) || isempty( obj.Values ) || isempty( obj.Bins ),
            obj.pPostConstraintChange;
        end
        
        
        % Check also the main contours. If these are all empty then there is
        % nothing for us to highlight and we should stop
        if isempty( obj.MainContours ) || all( cellfun( 'isempty', obj.MainContours(:) ) ),
            obj.HighlightContours = obj.MainContours;
            return
        end
        
        % Now the fun starts.
        
        bms = obj.MessageService;
        cif = bms.getInputFactors;
        
        
        X = obj.getEvaluationPoints;
        
        ai = highlightData.MinPoint(1);
        bi = highlightData.MaxPoint(1);
        ri = cif(CFactor).Max - cif(CFactor).Min;
        
        aj = highlightData.MinPoint(2);
        bj = highlightData.MaxPoint(2);
        rj = cif(RFactor).Max - cif(RFactor).Min;
        
        distances = max( [
            obj.Values, (ai - X(:,CFactor))/ri, (X(:,CFactor) - bi)/ri, ...
            (aj - X(:,RFactor))/rj, (X(:,RFactor) - bj)/rj
            ], [], 2 );
        
        % We now use the existing bins and edges to compute the highlight contours.
        obj.HighlightContours = obj.pComputeContourData( distances );
        
        end  % pSelectHighlight
        
        %----------------------------------------
        function pUpdateEvaluationPoints(obj, nPoints, nFactors)
        %PUPDATEEVALUATIONPOINTS Add more evaluation points as required.
        %   PUPDATEEVALUATIONPOINTS(OBJ, NPOINTS, NFACTORS) adds points to the list
        %   of evaluation points to ensure that there are at least NPOINTS points
        %   for at least NFACTORS input factors.
        
        doMakeNewBins = false;
        
        [np, nf] = size( obj.Points );
        
        if nf > 0,
            if np < nPoints,
                doMakeNewBins = true;
                % Add more rows
                % -- just add "Halton sequence" points to the end
                obj.Points = [
                    obj.Points
                    i_Halton( obj.Primes(1:nf), np, nPoints )
                    ];
            else
                nPoints = np;
            end
        end
        
        if nf < nFactors,
            doMakeNewBins = true;
            % Add more columns
            % -- need to add the corners to the beginning (rows) and "Halton
            %    sequence" points to end (columns)
            corners = cell( 1, nFactors );
            [corners{:}] = ndgrid( [0, 1] );
            corners = cell2mat( cellfun( @(x){x(:)}, corners ) );
            nOldCorners = 2^nf;
            
            obj.Points = [
                corners
                obj.Points((nOldCorners+1):end,:), ...
                i_Halton( obj.Primes((nf+1):nFactors), 0, nPoints - nOldCorners )
                ];
        end
        
        if doMakeNewBins,
            % Need to update the bin data
            nBins = obj.NBins;
            edges = linspace( 0, 1, nBins+1 );
            edges(end) = edges(end) + eps( 1 );
            % -- This last line ensure that points are inside the bins, i.e., all
            %    points will be less than edges(end). The small change also means
            %    that the last edge is numrically close enough to where the edge of
            %    the last bin and this will help us latter with the contour
            %    computation.
            [~, bins] = histc( obj.Points, edges );
            obj.Bins = bins;
            obj.MidPoints = 0.5 * (edges(1:end-1) + edges(2:end));
        end
        end  % pUpdateEvaluationPoints
        
        %----------------------------------------
        function setHighlight(obj, R, C, HLData)
        %SETHIGHLIGHT Set a new highlight rectangle.
        %   SETHIGHLIGHT(OBJ, R, C, HLDATA) set the rectangle defined by the data
        %   structure HLDATA in cell (R, C) of the view as the current highlight.
        %   HLDATA must be a structure containing the fields Rectangle, MinPoint
        %   and MaxPoint.
        
        % Convert (R, C) to the current input factors and save these along with the
        % rectangle information.
        bms = obj.MessageService;
        con = bms.getConstraint;
        
        if ~isempty(con)
            % Don't accept highlight data if there is no constraint being viewed
            cif = getInputFactors(con);
            HLData.XFactor = cif(C);
            HLData.YFactor = cif(R);
            obj.HighlightData = HLData;
            
            obj.pSelectHighlight(R, C);
        end
        
        end  % setHighlight
        
    end  % public methods
    
    
    methods (Hidden) % possibly private or hidden
        %----------------------------------------
        function Changed = guiEditResolution(obj)
        %GUIEDITRESOLUTION
        %    Changed = guiEditResolution(obj)
        
        d= mbcgui.container.Dialog('Name', 'Pairwise Projections Resolution',...
            'InfoHeight', 35, ...
            'InfoString',['To increase the resolution of the plot at the expense of greater calculation time, ',...
            'increase the number of evaluation points and bins.'],...
            'Size', [360 200], ...
            'ContentBorder',[0 0 0 0],...
            'Buttons', 'OK_CANCEL', ...
            'DefaultAction', 'OK', ...
            'CloseAction', 'CANCEL');
        figh = d.Figure;
        
        hNPoints = mbcgui.widget.Spinner( ...
            'Parent', figh, ...
            'Rule', 'int', ...
            'Min', 0, ...
            'Max', 2^31, ...
            'Value', obj.NPoints, ...
            'ClickIncrementMode', 'auto');
        hNPointsLabel = xregGui.labelcontrol('parent', figh, ...
            'String', 'Number of evaluation points:', ...
            'LabelSizeMode', 'absolute', ...
            'ControlSizeMode', 'absolute', ...
            'LabelSize', 150, ...
            'ControlSize', 70, ...
            'Control', hNPoints);
        
        hNBins = mbcgui.widget.Spinner( ...
            'Parent', figh, ...
            'Rule', 'int', ...
            'Min', 2, ...
            'Max', 2^8, ...
            'Value', obj.NBins, ...
            'ClickIncrementMode', 'auto');
        hNBinsLabel = xregGui.labelcontrol('parent', figh, ...
            'String', 'Number of bins per axes:', ...
            'LabelSizeMode', 'absolute', ...
            'ControlSizeMode', 'absolute', ...
            'LabelSize', 150, ...
            'ControlSize', 70, ...
            'Control', hNBins);
        
        hGrid = xreggridbaglayout(figh,...
            'Dimension',[2 1],...
            'RowSizes',[20 20],...
            'Gap', 5, ...
            'Border',[7 0 7 7],...
            'Elements',{hNPointsLabel,hNBinsLabel});
        
        d.Content = hGrid;
        
        closeMode = d.showDialog();
        
        Changed = false;
        if strcmp(closeMode,'OK')
            if hNBins.Value~=obj.NBins || hNPoints.Value~=obj.NPoints;
                obj.NBins   = hNBins.Value;
                obj.NPoints = hNPoints.Value;
                obj.Points = [];
                Changed = true;
            end
        end
        delete(d);
        
        end  % guiEditResolution
        
    end  % possibly private or hidden
    
end  % classdef

function C = i_FindContours( x, y, z, v )
z = -z;
[m, n] = size( z );

ii = isfinite( z );
if ~any( ii(:) ),
    C = [];
    return
end

% pading with a very large negative value is an easy way of getting the
% caps from contours
minz = min( z(ii) );
maxz = max( z(ii) );
pad = minz - 1e4*(maxz - minz);
if ~isfinite( pad ),
    pad = -realmax;
end
z(~ii) = pad;


z = [
    repmat( pad, 1, m + 2 );
    repmat( pad, n, 1 ), z,  repmat( pad, n, 1 );
    repmat( pad, 1, m + 2 );
    ];

x = [2*x(1)-x(2), x(:).', 2*x(end)-x(end-1)];
y = [2*y(1)-y(2), y(:).', 2*y(end)-y(end-1)];

% find the contours
C = contours( x, y, z, [v, v] );
end  % i_FindContours


%--------------------------------------------------------------------------
function X = i_Halton( p, start, finish )
%HALTON Simple Halton sequence.

np = finish - start;

% We want P as a row
p = p(:).';

% Initialize memory of X
X = zeros( np, numel( p ) );

L = ceil( log( finish )/log( min( p ) ) );


for j = 1:numel( p ),
    pp = p(j).^(0:L);
    for i = 1:np,
        thisN = start + i;
        for k = L:-1:1,
            d = floor( thisN/pp(k) );
            thisN = thisN - d * pp(k); % rem( thisN, pp(k) );
            X(i,j) = X(i,j) + d/(pp(k+1));
        end
    end
end
end  % i_Halton