Home > src > sosPlots.m

# sosPlots

## PURPOSE

- object used to create detailed plots of SOS optimization

## SYNOPSIS

This is a script file.

## DESCRIPTION

     - object used to create detailed plots of SOS optimization

     copyright 2009-2012 Blair Armstrong, Christine Watson, David Plaut

        This file is part of SOS

        SOS is free software: you can redistribute it and/or modify
        it for academic and non-commercial purposes
        under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.  For commercial or for-profit
        uses, please contact the authors (sos@cnbc.cmu.edu).

        SOS is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.

## CROSS-REFERENCE INFORMATION

This function calls:

- plt - plt package by Paul Mennen
- sosPlots - object used to create detailed plots of SOS optimization
- verbosePrint - master print function that regulates cmd line output based on verbosity flags

This function is called by:

- sos - SOS optimization object
- sosPlots - object used to create detailed plots of SOS optimization

## SUBFUNCTIONS

- function obj = sosPlots(sosObj,histObj,dispIt,startIt)
- function updatePlots(obj)
- function namesBTN(obj,~,~,t)
- function curLim = updateAxis(obj,x,curLim,subPlotIndex)

## SOURCE CODE

    0001 % - object used to create detailed plots of SOS optimization
    0002 %
    0003 % copyright 2009-2012 Blair Armstrong, Christine Watson, David Plaut
    0004 %
    0005 %    This file is part of SOS
    0006 %
    0007 %    SOS is free software: you can redistribute it and/or modify
    0008 %    it for academic and non-commercial purposes
    0009 %    under the terms of the GNU General Public License as published by
    0010 %    the Free Software Foundation, either version 3 of the License, or
    0011 %    (at your option) any later version.  For commercial or for-profit
    0012 %    uses, please contact the authors (sos@cnbc.cmu.edu).
    0013 %
    0014 %    SOS is distributed in the hope that it will be useful,
    0015 %    but WITHOUT ANY WARRANTY; without even the implied warranty of
    0016 %    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    0017 %    GNU General Public License for more details.
    0018
    0019 %    You should have received a copy of the GNU General Public License
    0020 %    along with SOS (see COPYING.txt).
    0021 %    If not, see <http://www.gnu.org/licenses/>.
    0022
    0023 classdef sosPlots < handle
    0024     %% plots detailed history data
    0025     %
    0026     % This class provides support for creating plots of various metrics
    0027     % related to the optimization process.
    0028     % plots various metrics related to the optimization process
    0029     % Specifically, the following items are recorded:
    0030     %
    0031     % creates plots for several optimization parameters, as follows:
    0032     %   - cost
    0033     %   - deltaCost
    0034     %   - temperature
    0035     %   - pFlipHistory
    0036     %   - sosStatTestpvals (for all stat tests in the sos Object)
    0037     %
    0038     % This code uses the plt library by Paul Mennen (may 11, 2010 version)
    0039     % and also takes some of its implementational inspiration
    0040     % from the demos therein.
    0041     %
    0042     % This class also inherits from the handle CLASS to gain standard
    0043     % object-oriented behavior
    0044     %
    0045     % PROPERTIES
    0046     %     sosObj % the sos object the plots are associated with
    0047     %     histObj % pointer to history object in SOS object that is to be displayed
    0048     %     hFig % handle to the plot graphic object
    0049     %     pFig % pointer to traces in figure
    0050     %     dispIt % range of iterations to show on the plots at any one time
    0051     %     startIt % iteration that the plot was created at (plots from then on after)
    0052     %     startRow % starting row when plotObj was created from which information will begin being plotted
    0053     %     pvalTestNames % names of the stat tests to plot. these names are stored seperately than those in histObj so as to be able to discern if the stat tests to plot have changed.
    0054     %     curXLim % range limit for x-axis
    0055     %     curCostYLim % range limit for Cost Y axis
    0056     %     curdeltaCostYLim % range limit for deltaCost Y axis
    0057     %     curTempYLim % range limit for tempreature Y axis
    0058     %
    0059     % METHODS
    0060     %   sosPlots(sosObj,histObj,dispIt,startIt) % constructor
    0061     %   updatePlots() % updates the plot based on the most recent history information
    0062     %   namesBTN(~,~,t) % call linked to names button that toggles display of stat test names.
    0063     %   namesBTN(obj,~,~,t) % call linked to names button that toggles display of stat test names.
    0064
    0065     %% PROPERTIES
    0066     properties
    0067         sosObj % the sos object the plots are associated with
    0068         histObj % pointer to history object in SOS object that is to be displayed
    0069         hFig % handle to the plot graphic object
    0070         pFig % pointer to traces in figure
    0071         dispIt % range of iterations to show on the plots at any one time
    0072         startIt % iteration that the plot was created at (plots from then on after)
    0073         startRow % starting row when plotObj was created from which information will begin being plotted
    0074         pvalTestNames % names of the stat tests to plot. these names are stored seperately than those in histObj so as to be able to discern if the stat tests to plot have changed.
    0075         curXLim % range limit for x-axis
    0076         curCostYLim % range limit for Cost Y axis
    0077         curdeltaCostYLim % range limit for deltaCost Y axis
    0078         curTempYLim % range limit for tempreature Y axis
    0079     end
    0080
    0081     %% METHODS
    0082     methods
    0083
    0084         %% obj = sosPlots(sosObj,histObj,dispIt,startIt) CONSTRUCTOR
    0085         function obj = sosPlots(sosObj,histObj,dispIt,startIt)
    0086            % creates plots of optimization history metrics
    0087            %
    0088            % PARAMETERS:
    0089            %    sosObj % sos object associated with the plot
    0090            %    histObj % history object whose data will be plotted
    0091            %    dispIt % default number of iterations to display on the plot at any one time
    0092            %    startit % iteration that the plot was started on (plotting begins thereafter)
    0093
    0094             % validate inputs
    0095             if exist('dispIt','var') == 0
    0096                 dispIt = 100000;
    0097             else
    0098                 validateattributes(dispIt, {'numeric'}, ...
    0099                 {'scalar', 'integer', 'positive', '>', 0});
    0100             end
    0101
    0102             obj.sosObj = sosObj;
    0103             obj.histObj = histObj;
    0104             obj.dispIt = dispIt;
    0105             obj.startIt = startIt;
    0106             obj.pvalTestNames = obj.histObj.pvalTestNames;
    0107
    0108             % begin the plot creation process:
    0109
    0110             % prepare abbreviated trace names for p-vals
    0111             shortNames = {};
    0112             for i=1:length(obj.pvalTestNames)
    0113                 shortNames = [shortNames ; strcat('Test #',num2str(i))]; %#ok<AGROW>
    0114             end
    0115
    0116
    0117             minX = obj.startIt;
    0118
    0119             % find the row in the history that the starting iteration
    0120             % appears in
    0121             obj.startRow = 1;
    0122             for i=1:length(obj.histObj.itHistory)
    0123                 if obj.histObj.itHistory(i) < minX
    0124                     obj.startRow = i+1;
    0125                 else
    0126                     break;
    0127                 end
    0128             end
    0129
    0130             %need to include NaN's for as many traces as there are
    0131             %statTests when first buiding the stat test.  There also needs
    0132             %to be at least 1 stat test so that the stat test plot is
    0133             %created, even if it will ultimately be empty.
    0134             numStatTests = length(obj.pvalTestNames);
    0135
    0136             initStatTraces = nan(1,max(numStatTests,1));
    0137
    0138             % create initial x-limits based on the starting iteration and
    0139             % the number of iterations to keep on the screen.
    0140             obj.curXLim = [minX minX+obj.dispIt];
    0141
    0142             % set the initial ranges for the y axis of the plots
    0143
    0144             % create a small initial range on the axes;  The intent is to
    0145             % have this range be overridden with the real data range
    0146             % because that range will be bigger than smallNum.  This is a
    0147             % somewhat awkward bit of the code that hopefully won't be too
    0148             % troublesome, but is apparently needed because the plot must
    0149             % take two real value min and max bounds such that min<max, and
    0150             % more sophisticated overriding code probably isn't worth it
    0151             % presently.
    0152             smallNum = 0.0000001;
    0153
    0154             % range of probabilities is always 0-1
    0155             probYLim = [0 1];
    0156
    0157             % cost and deltaCost can have both positive and negative
    0158             % values, so make their initial ranges symmetric around 1
    0159             obj.curdeltaCostYLim = [-smallNum smallNum];
    0160             obj.curCostYLim = [-smallNum smallNum];
    0161             %temperature can only be negative, have it be bounded by zero
    0162             obj.curTempYLim = [0 smallNum];
    0163
    0164             % create empty initial traces for as many traces as will
    0165             % ultimately be in the plot.
    0166             initYs = [NaN,NaN,NaN,NaN,initStatTraces];
    0167
    0168             % have each individual data point marked with a star, below.
    0169             % There are as many stars for trace marks as there are traces,
    0170             % above.
    0171             mark = '';
    0172             for j=1:length(initYs)
    0173                 mark = strcat(mark,'*');
    0174             end
    0175
    0176             % create the figure.
    0177             obj.pFig = plt(NaN,initYs, ... % create NaN's for x-axis and y-axis traces
    0178                 'FigName','plotObj', ... % name of figure
    0179                 'SubPlot',[20 20 20 20 20] ... % percent of figure occupied by each subplot
    0180                 ,'Xlim',obj.curXLim, ... % set initial Xlimits
    0181                 'Options','Ticks',... init plots /w tick marks
    0182                 'Options','-Ylog',... % remove logy transform of y axis
    0183                 'Options','-Xlog',...% remove logx transform of xaxis
    0184                 'Options','-Rotate',... % 2-d plots don't need 3d rotation
    0185                 'Options','-Help',... % remove (non-existent) help access
    0186                 'Options','S',... % enable x-axis slider
    0187                 'ENApre', [0 0],... % disables unit scaling and uses scientific notation.
    0188                 'TraceID',shortNames,... % name all of the stat test traces
    0189                 'Markers',mark,... % add marks for each actual value on the plot that is not interpolated
    0190                 'LabelX','Iteration',...
    0191                 'LabelY',{'p-val','p(swap)','deltaCost','cost','temperature'},...
    0192                 'FigBKc',[0.3 0.3 0.3]);  % sets plot bg color to dark grey
    0193
    0194             % get a pointer to the newly created figure.
    0195             obj.hFig = gcf();
    0196
    0197             %update the axes for all of the other plots to their
    0198             %default bounds
    0199             hAxes = getappdata(obj.hFig,'axis');
    0200
    0201             set(hAxes(1),'Ylim',probYLim); % pval plot
    0202             set(hAxes(2),'Ylim',probYLim); % p(swap) plot
    0203             set(hAxes(3),'Ylim',obj.curdeltaCostYLim); % deltaCost
    0204             set(hAxes(4),'Ylim',obj.curCostYLim); % cost
    0205             set(hAxes(5),'Ylim',obj.curTempYLim); % temperature
    0206
    0207
    0208             % create a message listing the names of all the stat tests
    0209             dispMsg = sprintf('\nThe names of the stats tests are:\n\n');
    0210
    0211             for i=1:length(obj.pvalTestNames)
    0212                 dispMsg = sprintf('  %s#%s: %s\n',dispMsg,num2str(i),...
    0213                                     obj.pvalTestNames{i});
    0214             end
    0215
    0216             %add the 'names' button that displays the plot names
    0217             % snippet inspired from plt demo trigplt.m by Paul Mennen
    0218             plot.names = text(2,3,dispMsg,... % first 2 params are x,y offset
    0219                           'HorizontalAlignment','left',...
    0220                           'BackgroundColor',[0.5 0.5 0.5],...
    0221                           'EdgeColor','red','Color','black','Editing','off');
    0222
    0223             % try to adjust the color (plt seems to override this on
    0224             % initialization though).
    0225             set(plot.names,'units','norm','color',[1 .7 .7]);
    0226
    0227             % add the names button
    0228             uicontrol('string','Names','pos',[5 500 50 20],...
    0229                         'CallBack',{@obj.namesBTN,plot.names});
    0230
    0231             % hide names on plot creation.
    0232             set(plot.names,'visible','off');
    0233
    0234             % if the plot is closed via the plot's gui, have it delete the
    0235             % plotObj in the main SOS variable:
    0236             set(obj.hFig, 'closeReq',strcat('delete(',num2str(obj.hFig),...
    0237                     '); mySOS.plotObj = {}; '));
    0238
    0239
    0240             % ensure that the whole plot has been updated.
    0241             drawnow;
    0242
    0243             verbosePrint('Plotting detailed optimization history...', ...
    0244                 'sosPlots_constructor_end');
    0245
    0246         end % constructor
    0247
    0248
    0249         %% function updatePlots() METHOD
    0250         function updatePlots(obj)
    0251             % updates the plot based on the most recent history information
    0252
    0253             %number of data points in the history
    0254             histLength = length(obj.histObj.itHistory);
    0255
    0256             if histLength == 0
    0257                 error('updatePlots() was called but detailed optimization was not stored');
    0258             else
    0259                 lastPoint = histLength;
    0260                 firstPoint = obj.startRow;
    0261
    0262                 % find the number of iterations on the last datapoint
    0263                 lastIt = max(obj.dispIt,obj.histObj.itHistory(length(obj.histObj.itHistory)));
    0264                 firstIt = max(0,lastIt-obj.dispIt);
    0265
    0266                 % check to see if the x-axes need to be updated.  This
    0267                 % should only happen if there are at least two datapoints;
    0268                 newXLim = [firstIt lastIt];
    0269
    0270                 % only try updating the original axes if more than one data
    0271                 % point is present; otherwise the initial value will be
    0272                 % fine
    0273                 if firstPoint < lastPoint && ...
    0274                         (newXLim(1) ~= obj.curXLim(1) || ...
    0275                          newXLim(2) ~= obj.curXLim(2))
    0276                     hAxes = getappdata(obj.hFig,'axis');
    0277                     obj.curXLim = newXLim;
    0278
    0279                     for i=1:5 % for every subplot
    0280                     set(hAxes(i),'Xlim', ...
    0281                         obj.curXLim);
    0282                     end
    0283                 end
    0284
    0285                 % update datapoints on the p-val plot
    0286                 for i=1:length(obj.pvalTestNames)
    0287                     set(obj.pFig(i),'x',obj.histObj.itHistory(firstPoint:lastPoint), ...
    0288                        'y',obj.histObj.pvalHistory(firstPoint:lastPoint,i));
    0289                 end
    0290
    0291
    0292                 nextIndex = i+1;
    0293
    0294                 % update pFlip
    0295                 set(obj.pFig(nextIndex),'x',obj.histObj.itHistory(firstPoint:lastPoint), ...
    0296                        'y',obj.histObj.pFlipHistory(firstPoint:lastPoint));
    0297
    0298
    0299                 % from hereon out, it may be necessary to update the YLim
    0300                 % since they are not bounded
    0301
    0302                 % update deltaCost Axis
    0303                 obj.curdeltaCostYLim = obj.updateAxis(...
    0304                             obj.histObj.deltaCostHistory(lastPoint), ...
    0305                             obj.curdeltaCostYLim, 3);
    0306
    0307                 % update deltaCost plot
    0308                 nextIndex = nextIndex+1;
    0309                 set(obj.pFig(nextIndex),'x',obj.histObj.itHistory(firstPoint:lastPoint), ...
    0310                    'y',obj.histObj.deltaCostHistory(firstPoint:lastPoint));
    0311
    0312
    0313                % same for cost
    0314                 obj.curCostYLim = obj.updateAxis(...
    0315                             obj.histObj.costHistory(lastPoint), ...
    0316                             obj.curCostYLim, 4);
    0317
    0318                 nextIndex = nextIndex+1;
    0319                 set(obj.pFig(nextIndex),'x',obj.histObj.itHistory(firstPoint:lastPoint), ...
    0320                         'y',obj.histObj.costHistory(firstPoint:lastPoint));
    0321
    0322                 % same for temp
    0323
    0324                 obj.curTempYLim = obj.updateAxis(...
    0325                             obj.histObj.tempHistory(lastPoint), ...
    0326                             obj.curTempYLim, 5);
    0327
    0328                 nextIndex = nextIndex+1;
    0329                 set(obj.pFig(nextIndex),'x',obj.histObj.itHistory(firstPoint:lastPoint), ...
    0330                         'y',obj.histObj.tempHistory(firstPoint:lastPoint));
    0331
    0332
    0333             end % if histLength == 0
    0334
    0335             drawnow;
    0336
    0337         end % updatePlots
    0338
    0339
    0340
    0341
    0342
    0343
    0344         %% namesBTN(~,~,t) METHOD
    0345         function namesBTN(obj,~,~,t)
    0346             % call linked to names button that toggles display of stat test
    0347             % names.
    0348             %
    0349             % PARAMETERS:
    0350             % ~ -- standard graphic parameters for button calls - not used.
    0351             %   t - pionter to text object that displays the names
    0352             %
    0353             % snippet inspried from plt demo trigplt.m by Paul Mennen, in
    0354             % the plt package demos
    0355
    0356             dispMsg = sprintf('\nThe names of the stats tests are:\n');
    0357
    0358             for i=1:length(obj.pvalTestNames)
    0359                 dispMsg = sprintf('%s#%s: %s\n',dispMsg,num2str(i), ...
    0360                     obj.pvalTestNames{i});
    0361             end
    0362
    0363            v = get(t(1),'visible');
    0364            if v(2)=='n'; v='off'; else v='on'; end;
    0365            set(t,'visible',v);
    0366
    0367            drawnow;
    0368
    0369         end
    0370
    0371     end % methods
    0372
    0373
    0374     %% METHODS (Access = private)
    0375     methods (Access = private)
    0376
    0377         %% curLim = updateAxis(x,curLim,subPlotIndex) METHOD
    0378         function curLim = updateAxis(obj,x,curLim,subPlotIndex)
    0379             % determines whether the y-axis for a given plot need to be
    0380             % updated based on the new data, which may have changed the
    0381             % min/max values for the axis.
    0382             %
    0383             % PARAMETERS:
    0384             %   x - new data point in history array
    0385             %   curLim - 2-entry array containing the current min/max vals
    0386             %   subPlotIndex - index of subplot in hFig handle obj
    0387
    0388             update = false;
    0389
    0390             if x < curLim(1)
    0391                 curLim(1) = x;
    0392                 update = true;
    0393             end
    0394
    0395             if x > curLim(2)
    0396                 curLim(2) = x;
    0397                 update = true;
    0398             end
    0399
    0400             if update == true
    0401                 hAxes = getappdata(obj.hFig,'axis');
    0402                 set(hAxes(subPlotIndex),'Ylim', ...
    0403                     curLim);
    0404             end
    0405
    0406         end
    0407     end
    0408
    0409 end
    0410
    0411