Synchronized Data Presentations in a Programmatic GUI

Techniques Illustrated in the Example

The example shows how to interact with a uitable and the data it holds by:

  • Graphing specific columns of data

  • Brushing the graph when the user selects cells in the table

A 2-D axes displays line graphs of the data in response to selecting check boxes and in real time, the results of selecting observations in the table.

About the Example

The example GUI presents data in a three-column table (a uitable object) and enables the user to plot any column of data as a line graph. When the user selects data values in the table, the plot displays markers for the selected observations.

This figure shows the results of plotting two columns and selecting a subset of values in each column.

The GUI displays and removes line plots when the user selects and clears the three check boxes. The circle markers appear and disappear dynamically as the user selects cells in the table. The user need not plot lines to display the markers.

The table displays MATLAB® sample data (count.dat) containing hourly counts of vehicles passing three locations. The example does not provide a way to change the data, except by modifying the tableplot.m main function to read in a different data set. Then, you can manually assign appropriate column names and a different title for the plot. A more natural way to add this capability is to allow the user to supply input arguments to the GUI to identify a data file or workspace variable, and to supply text strings to use for column headers.

View the Example Code

To obtain copies of the GUI files for this example, follow these steps:

  1. Set your current folder to one to which you have write access.

  2. Copy the example code and display it in the Editor by issuing the following MATLAB commands:

    copyfile(fullfile(docroot, 'techdoc','creating_guis',...
      'examples','tableplot.m')),...
      fileattrib('tableplot.m', '+w');
    edit tableplot.m
    

Set Up and Interact with the uitable

This example has one file, tableplot.m, that contains its main function plus two local functions (uicontrol callbacks). The main tableplot function creates a figure and populates it with uicontrols and one axes.

The function hides the figure's menu bar because it is not needed.

% Create a figure that will have a uitable, axes and checkboxes
figure('Position', [100, 300, 600, 460],...
       'Name', 'TablePlot',...  % Title figure
       'NumberTitle', 'off',... % Do not show figure number
       'MenuBar', 'none');      % Hide standard menu bar menus

The main tableplot function sets up the uitable immediately after loading a data matrix into the workspace. The table's size adapts to the matrix size (matrices for uitables must be 1-D or 2-D).

% Load some tabular data (traffic counts from somewhere)
count = load('count.dat');
tablesize = size(count);    % This demo data is 24-by-3

% Define parameters for a uitable (col headers are fictional)
colnames = {'Oak Ave', 'Washington St', 'Center St'};
% All column contain numeric data (integers, actually)
colfmt = {'numeric', 'numeric', 'numeric'};
% Disallow editing values (but this can be changed)
coledit = [false false false];
% Set columns all the same width (must be in pixels)
colwdt = {60 60 60};
% Create a uitable on the left side of the figure
htable = uitable('Units', 'normalized',...
                 'Position', [0.025 0.03 0.375 0.92],...
                 'Data',  count,... 
                 'ColumnName', colnames,...
                 'ColumnFormat', colfmt,...
                 'ColumnWidth', colwdt,...
                 'ColumnEditable', coledit,...
                 'ToolTipString',...
                 'Select cells to highlight them on the plot',...
                 'CellSelectionCallback',{@select_callback});

The tableplot function performs these tasks:

  • Passes the count matrix to the table as the Data parameter.

  • Specifies the column names using the ColumnName property

  • Specifies that all columns hold numeric data using the ColumnFormat property

  • Specifies that all columns have a width of 60 pixels

    MATLAB always interprets the ColumnWidth property in pixels

  • Provides a tooltip string for the table

  • Accepts default values for most of the remaining Uitable Properties.

In the next block of code, the tableplot function sets up an axes on the right side of the figure. It plots lines and markers in response to the user's actions.

% Create an axes on the right side; set x and y limits to the
% table value extremes, and format labels for the demo data.
haxes = axes('Units', 'normalized',...
             'Position', [.465 .065 .50 .85],...
             'XLim', [0 tablesize(1)],...
             'YLim', [0 max(max(count))],...
             'XLimMode', 'manual',...
             'YLimMode', 'manual',...
             'XTickLabel',...
             {'12 AM','5 AM','10 AM','3 PM','8 PM'});
title(haxes, 'Hourly Traffic Counts')   % Describe data set
% Prevent axes from clearing when new lines or markers are plotted
hold(haxes, 'all')

In the next block of code, the tableplot function plots the lineseries for the markers with a call to plot. The plot function graphs the entire count data set (which remains in the workspace after being copied into the table). However, the function hides the markers immediately, only to be revealed when the user selects cells in the data table.

% Create an invisible marker plot of the data and save handles
% to the lineseries objects; use this to simulate data brushing.
hmkrs = plot(count, 'LineStyle', 'none',...
                    'Marker', 'o',...
                    'MarkerFaceColor', 'y',...
                    'HandleVisibility', 'off',...
                    'Visible', 'off');

The main function defines three check boxes to control plotting of the three columns of data and two static text strings. You can see the code for this if you display tableplot.m.

The Cell Selection Callback

The select_callback function for the CellSelectionCallback property, shows and hides markers on the axes. When the user selects data values in the table, the plot displays markers for the selected observations. This technique is called data brushing. However, the data brushing performed by this GUI does not rely on MATLAB data brushing feature.

Here is the select_callback code:

function select_callback(hObject, eventdata)
    % hObject    Handle to uitable1 (see GCBO)
    % eventdata  Currently selected table indices
    % Callback to erase and replot markers, showing only those
    % corresponding to user-selected cells in table. 
    % Repeatedly called while user drags across cells of the uitable

        % hmkrs are handles to lines having markers only
        set(hmkrs, 'Visible', 'off') % turn them off to begin
        
        % Get the list of currently selected table cells
        sel = eventdata.Indices;     % Get selection indices (row, col)
                                     % Noncontiguous selections are ok
        selcols = unique(sel(:,2));  % Get all selected data col IDs
        table = hObject.Data; % Get copy of uitable data
        
        % Get vectors of x,y values for each column in the selection;
        for idx = 1:numel(selcols)
            col = selcols(idx);
            xvals = sel(:,1);
            xvals(sel(:,2) ~= col) = [];
            yvals = table(xvals, col)';
            % Create Z-vals = 1 in order to plot markers above lines
            zvals = col*ones(size(xvals));
            % Plot markers for xvals and yvals using a line object
            hmkrs(col).Visible =  'on';.
            hmkrs(col).XData = xvals;
            hmkrs(col).YData = yvals;
            hmkrs(col).ZData = zvals;
        end
    end

The function passes the rows and columns of the user-selected cells in eventdata.Indices and copies them into sel. For example, if the user selects all three columns in row 3 of the table, then

eventdata = 
    Indices: [3x2 double]

sel =
     3     1
     3     2
     3     3

If the user selects rows 5, 6, and 7 of columns 2 and 3, then

eventdata = 
    Indices: [6x2 double]

sel =
     5     2
     5     3
     6     2
     6     3
     7     2
     7     3

After hiding all the markers, the callback performs these tasks:

  1. Identifies the unique columns that the user selected.

  2. Iterates over the unique columns to find the row indices for the selection.

  3. Sets the x-values for all row indices that do not appear in the selection to empty.

  4. Uses the vector of x-values to copy y-values from the table and specify dummy z-values.

    Setting the z-values ensures that the markers plot on top of the lines.

  5. Assigns x-, y-, and z-values to the XData, YData, and ZData of each vector of markers, and makes the markers visible again.

    Only markers with nonempty data display.

The Plot Check Box callback

The three Plot check boxes all share the same callback, plot_callback. It has a column argument in addition to the standard hObject and eventdata parameters. The column argument identifies which box (and column of data) the callback is for.

The plot_callback also uses handles found in the function workspace for the following purposes:

  • htable — To fetch table data and column names for plotting the data and deleting lines; the column argument identifies which column to draw or erase.

  • haxes — To draw lines and delete lines from the axes.

  • hprompt — To remove the prompt (which only displays until the first line is plotted) from the axes.

Keying on the column argument, the callback takes the following actions:

  • Extracts data from the table and calls plot, specifying data from the given column as YData, and setting its DisplayName property to the column's name.

  • Deletes the appropriate line from the plot when a check box is deselected, based on the line's DisplayName property.

Here is the plot_callback code:

function plot_callback(hObject, eventdata, column)
    % hObject     Handle to Plot menu
    % eventdata   Not used
    % column      Number of column to plot or clear

    colors = {'b','m','r'}; % Use consistent color for lines
    colnames = htable.ColumnName;
    colname = colnames{column};
    if (hObject.Value)
        % Turn off the advisory text; it never comes back
        hprompt.Visible = 'off';
        % Obtain the data for that column
        ydata = htable.Data;
        haxes.NextPlot =  'Add';
        % Draw the line plot for column
        plot(haxes, ydata(:,column),...
            'DisplayName', colname,...
            'Color', colors{column});
    else % Adding a line to the plot
        % Find the lineseries object and delete it
        delete(findobj(haxes, 'DisplayName', colname))
    end
end
Was this topic helpful?