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: This function is called by:

SUBFUNCTIONS ^

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

Generated on Fri 27-Jan-2012 16:18:41 by m2html © 2005