Barchart

Name

barchart - Bar chart for plotting X-Y coordinate data.

Synopsis

barchart pathName ?option value? …

Description

The barchart command creates a bar chart for plotting two-dimensional data (X-Y coordinates). A bar chart is a graphic means of comparing numbers by displaying bars of lengths proportional to the y-coordinates of the points they represented. The bar chart has many configurable components: coordinate axes, elements, legend, grid lines, cross hairs, etc. They allow you to customize the look and feel of the graph.

Introduction

The barchart command creates a new window for plotting two-dimensional data (X-Y coordinates), using bars of various lengths to represent the data points. The bars are drawn in a rectangular area displayed in the center of the new window. This is the plotting area. The coordinate axes are drawn in the margins surrounding the plotting area. By default, the legend is drawn in the right margin. The title is displayed in top margin.

A barchart widget has several configurable components: coordinate axes, data elements, legend, grid, cross hairs, pens, postscript, and annotation markers. Each component can be queried or modified.

Syntax

Example

The barchart command creates a new bar chart.

# Create a new bar chart.  Plotting area is black.
barchart .b -plotbackground black

A new Tcl command .b is created. This command can be used to query and modify the bar chart. For example, to change the title of the graph to “My Plot”, you use the new command and the configure operation.

# Change the title.
.b configure -title "My Plot"

To add data elements, you use the command and the element component.

# Create a new element named "e1"
.b element create e1 -xdata {1 2 3 4 5 6 7 8 9 10}\
        -ydata {26.18 50.46 72.85 93.31 111.86 128.47 143.14 155.85 166.60 175.38}

The element’s X-Y coordinates are specified using lists of numbers. Alternately, RBC vectors could be used to hold the X-Y coordinates.

# Create two vectors and add them to the barchart.
vector xVector yVector
xVector set {1 2 3 4 5 6 7 8 9 10}
yVector set {26.18 50.46 72.85 93.31 111.86 128.47 143.14 155.85 166.60 175.38}
.b element create e1 -xdata xVector -ydata yVector

The advantage of using vectors is that when you modify one, the graph is automatically redrawn to reflect the new values.

# Change the y coordinate of the first point.
set yVector(0) 25.18

An element named e1 is now created in .b. It is automatically added to the display list of elements. You can use this list to control in what order elements are displayed. To query or reset the element display list, you use the element’s show operation.

# Get the current display list
set elemList [.b element show]
# Remove the first element so it won’t be displayed.
.b element show [lrange $elemList 0 end]

The element will be displayed by as many bars as there are data points (in this case there are ten). The bars will be drawn centered at the x-coordinate of the data point. All the bars will have the same attributes (colors, stipple, etc). The width of each bar is by default one unit. You can change this with using the -barwidth option.

# Change the scale of the x-coordinate data
xVector set {0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0}
# Make sure we change the bar width too.
.b configure -barwidth 0.2

The height of each bar is proportional to the ordinate (Y-coordinate) of the data point.

If two or more data points have the same abscissa (X-coordinate value), the bars representing those data points may be drawn in various ways. The default is to overlay the bars, one on top of the other. The ordering is determined from the of element display list. If the stacked mode is selected (using the -barmode configuration option), the bars are stacked, each bar above the previous.

# Display the elements as stacked.
.b configure -barmode stacked

If the aligned mode is selected, the bars having the same x-coordinates are displayed side by side. The width of each bar is a fraction of its normal width, based upon the number of bars with the same x-coordinate.

# Display the elements side-by-side.
.b configure -barmode aligned

By default, the element’s label in the legend will be also e1. You can change the label, or specify no legend entry, again using the element’s configure operation.

# Don’t display "e1" in the legend.
.b element configure e1 -label ""

You can configure more than just the element’s label. An element has many attributes such as stipple, foreground and background colors, relief, etc.

.b element configure e1 -fg red -bg pink \
  -stipple gray50

Four coordinate axes are automatically created: x, x2, y, and y2. And by default, elements are mapped onto the axes x and y. This can be changed with the -mapx and -mapy options.

# Map "e1" on the alternate y axis "y2".
.b element configure e1 -mapy y2

Axes can be configured in many ways too. For example, you change the scale of the Y-axis from linear to log using the axis component.

# Y-axis is log scale.
.b axis configure y -logscale yes

One important way axes are used is to zoom in on a particular data region. Zooming is done by simply specifying new axis limits using the -min and -max configuration options.

.b axis configure x -min 1.0 -max 1.5
.b axis configure y -min 12.0 -max 55.15

To zoom interactively, you link theaxis configure operations with some user interaction (such as pressing the mouse button), using the bind command. To convert between screen and graph coordinates, use the invtransform operation.

# Click the button to set a new minimum
bind .b <ButtonPress-1> {
    %W axis configure x -min [%W axis invtransform x %x]
    %W axis configure x -min [%W axis invtransform x %y]
}

By default, the limits of the axis are determined from data values. To reset back to the default limits, set the -min and -max options to the empty value.

# Reset the axes to autoscale again.
.b axis configure x -min {} -max {}
.b axis configure y -min {} -max {}

By default, the legend is drawn in the right margin. You can change this or any legend configuration options using the legend component.

# Configure the legend font, color, and relief
.b legend configure -position left -relief raised -font fixed -fg blue

To prevent the legend from being displayed, turn on the -hide option.

# Don’t display the legend.
.b legend configure -hide yes

The barchart has simple drawing procedures called markers. They can be used to highlight or annotate data in the graph. The types of markers available are bitmaps, polygons, lines, or windows. Markers can be used, for example, to mark or brush points. For example there may be a line marker which indicates some low-water value. Markers are created using the marker operation.

# Create a line represent the low water mark at 10.0
.b marker create line -name "low_water" -coords {-Inf 10.0 Inf 10.0} -dashes {2 4 2} -fg red -bg blue

This creates a line marker named low_water. It will display a horizontal line stretching across the plotting area at the y-coordinate 10.0. The coordinates “-Inf” and “Inf” indicate the relative minimum and maximum of the axis (in this case the x-axis). By default, markers are drawn last, on top of the bars. You can change this with the -under option.

# Draw the marker before elements are drawn.
.b marker configure low_water -under yes

You can add cross hairs or grid lines using the crosshairs and grid components.

# Display both cross hairs and grid lines.
.b crosshairs configure -hide no -color red
.b grid configure -hide no -dashes {2 2}

Finally, to get hardcopy of the graph, use the postscript component.

# Print the bar chart into file "file.ps"
.b postscript output file.ps -maxpect yes -decorations no

This generates a file file.ps containing the encapsulated PostScript of the graph. The option -maxpect says to scale the plot to the size of the page. Turning off the -decorations option denotes that no borders or color backgrounds should be drawn (i.e. the background of the margins, legend, and plotting area will be white).

Barchart operations

Barchart components

A graph is composed of several components: coordinate axes, data elements, legend, grid, cross hairs, postscript, and annotation markers. Instead of one big set of configuration options and operations, the graph is partitioned, where each component has its own configuration options and operations that specifically control that aspect or part of the graph.

Axis components

Four coordinate axes are automatically created: two X-coordinate axes (x and x2) and two Y-coordinate axes (y, and y2). By default, the axis x is located in the bottom margin, y in the left margin, x2 in the top margin, and y2 in the right margin.

An axis consists of the axis line, title, major and minor ticks, and tick labels. Major ticks are drawn at uniform intervals along the axis. Each tick is labeled with its coordinate value. Minor ticks are drawn at uniform intervals within major ticks.

The range of the axis controls what region of data is plotted. Data points outside the minimum and maximum limits of the axis are not plotted. By default, the minimum and maximum limits are determined from the data, but you can reset either limit.

You can create and use several axes. To create an axis, invoke the axis component and its create operation.

# Create a new axis called "temperature"
.b axis create temperature

You map data elements to an axis using the element’s -mapy and -mapx configuration options. They specify the coordinate axes an element is mapped onto.

# Now map the temperature data to this axis.
.b element create "temp" -xdata $x -ydata $tempData -mapy temperature

While you can have many axes, only four axes can be displayed simultaneously. They are drawn in each of the margins surrounding the plotting area. The axes x and y are drawn in the bottom and left margins. The axes x2 and y2 are drawn in top and right margins. Only x and y are shown by default. Note that the axes can have different scales.

To display a different axis, you invoke one of the following components: xaxis, yaxis, x2axis, and y2axis. The use operation designates the axis to be drawn in the corresponding margin: xaxis in the bottom, yaxis in the left, x2axis in the top, and y2axis in the right.

# Display the axis temperature in the left margin.
.b yaxis use temperature

You can configure axes in many ways. The axis scale can be linear or logarithmic. The values along the axis can either monotonically increase or decrease. If you need custom tick labels, you can specify a Tcl procedure to format the label any way you wish. You can control how ticks are drawn, by changing the major tick interval or the number of minor ticks. You can define non-uniform tick intervals, such as for time-series plots.

Only four axes can be displayed simultaneously. By default, they are x, y, x2, and y2. You can swap in a different axis with use operation of the special axis components: xaxis, x2axis, yaxis, and y2axis.

.g create axis temp
.g create axis time
.g xaxis use temp
.g yaxis use time

Only the axes specified for use are displayed on the screen.

The xaxis, x2axis, yaxis, and y2axis components operate on an axis location rather than a specific axis like the more general axis component does. The xaxis component manages the X-axis located in the bottom margin (whatever axis that happens to be). Likewise, yaxis uses the Y-axis in the left margin, x2axis the top X-axis, and y2axis the right Y-axis.

They implicitly control the axis that is currently using to that location. By default, xaxis uses the x axis, yaxis uses y, x2axis uses x2, and y2axis uses y2. These components can be more convenient to use than always determining what axes are current being displayed by the graph.

The following operations are available for axes. They mirror exactly the operations of the axis component. The axis argument must be xaxis, x2axis, yaxis, or y2axis.

Designates the axis axisName is to be displayed at this location. AxisName can not be already in use at another location. This command returns the name of the axis currently using this location.

Crosshairs component

Cross hairs consist of two intersecting lines (one vertical and one horizontal) drawn completely across the plotting area. They are used to position the mouse in relation to the coordinate axes. Cross hairs differ from line markers in that they are implemented using XOR drawing primitives. This means that they can be quickly drawn and erased without redrawing the entire widget.

The following operations are available for cross hairs:

Element components

A data element represents a set of data. It contains x and y vectors which are the coordinates of the data points. Elements are displayed as bars where the length of the bar is proportional to the ordinate of the data point. Elements also control the appearance of the data, such as the color, stipple, relief, etc.

When new data elements are created, they are automatically added to a list of displayed elements. The display list controls what elements are drawn and in what order.

The following operations are available for elements.

Grid component

Grid lines extend from the major and minor ticks of each axis horizontally or vertically across the plotting area. The following operations are available for grid lines.

Legend component

The legend displays a list of the data elements. Each entry consists of the element’s symbol and label. The legend can appear in any margin (the default location is in the right margin). It can also be positioned anywhere within the plotting area.

The following operations are valid for the legend.

Pen components

Pens define attributes for elements. Pens mirror the configuration options of data elements that pertain to how symbols and lines are drawn. Data elements use pens to determine how they are drawn. A data element may use several pens at once. In this case, the pen used for a particular data point is determined from each element’s weight vector (see the element’s -weight and -style options).

One pen, called activeBar, is automatically created. It’s used as the default active pen for elements. So you can change the active attributes for all elements by simply reconfiguring this pen.

.g pen configure "activeBar" -fg green -bg green4

You can create and use several pens. To create a pen, invoke the pen component and its create operation.

.g pen create myPen

You map pens to a data element using either the element’s -pen or -activepen options.

.g element create "e1" -xdata $x -ydata $tempData \
    -pen myPen

An element can use several pens at once. This is done by specifying the name of the pen in the element’s style list (see the -styles option).

.g element configure "e1" -styles { myPen 2.0 3.0 }

This says that any data point with a weight between 2.0 and 3.0 is to be drawn using the pen myPen. All other points are drawn with the element’s default attributes.

The following operations are available for pen components.

Postscript component

The barchart can generate encapsulated PostScript output. There are several configuration options you can specify to control how the plot will be generated. You can change the page dimensions and borders. The plot itself can be scaled, centered, or rotated to landscape. The PostScript output can be written directly to a file or returned through the interpreter.

The following postscript operations are available.

Marker components

Markers are simple drawing procedures used to annotate or highlight areas of the graph. Markers have various types: text strings, bitmaps, images, connected lines, windows, or polygons. They can be associated with a particular element, so that when the element is hidden or un-hidden, so is the marker. By default, markers are the last items drawn, so that data elements will appear in behind them. You can change this by configuring the -under option.

Markers, in contrast to elements, don’t affect the scaling of the coordinate axes. They can also have elastic coordinates (specified by -Inf and Inf respectively) that translate into the minimum or maximum limit of the axis. For example, you can place a marker so it always remains in the lower left corner of the plotting area, by using the coordinates -Inf,-Inf.

The following operations are available for markers.

Bitmap markers

A bitmap marker displays a bitmap. The size of the bitmap is controlled by the number of coordinates specified. If two coordinates, they specify the position of the top-left corner of the bitmap. The bitmap retains its normal width and height. If four coordinates, the first and second pairs of coordinates represent the corners of the bitmap. The bitmap will be stretched or reduced as necessary to fit into the bounding rectangle.

Bitmap markers are created with the marker’s create operation in the form:

There may be many option-value pairs, each sets a configuration options for the marker. These same option-value pairs may be used with the marker’s configure operation.

The following options are specific to bitmap markers:

Image markers

A image marker displays an image. Image markers are created with the marker’s create operation in the form:

The following options are specific to image markers:

Line markers

A line marker displays one or more connected line segments. Line markers are created with marker’s create operation in the form:

Polygon markers

A polygon marker displays a closed region described as two or more connected line segments. It is assumed the first and last points are connected. Polygon markers are created using the marker create operation in the form:

Text markers

A text marker displays a string of characters on one or more lines of text. Embedded newlines cause line breaks. They may be used to annotate regions of the graph. Text markers are created with the create operation in the form:

Window markers

A window marker displays a widget at a given position. Window markers are created with the marker’s create operation in the form:

Graph component bindings

Specific barchart components, such as elements, markers and legend entries, can have a command trigger when event occurs in them, much like canvas items in Tk’s canvas widget. Not all event sequences are valid. The only binding events that may be specified are those related to the mouse and keyboard (such as Enter, Leave, ButtonPress, Motion, and KeyPress).

Only one element or marker can be picked during an event. This means, that if the mouse is directly over both an element and a marker, only the uppermost component is selected. This isn’t true for legend entries. Both a legend entry and an element (or marker) binding commands will be invoked if both items are picked.

It is possible for multiple bindings to match a particular event. This could occur, for example, if one binding is associated with the element name and another is associated with one of the element’s tags (see the -bindtags option). When this occurs, all of the matching bindings are invoked. A binding associated with the element name is invoked first, followed by one binding for each of the element’s bindtags. If there are multiple matching bindings for a single tag, then only the most specific binding is invoked. A continue command in a binding script terminates that script, and a break command terminates that script and skips any remaining scripts for the event, just as for the bind command.

The -bindtags option for these components controls addition tag names which can be matched. Implicitly elements and markers always have tags matching their names. Setting the value of the -bindtags option doesn’t change this.

C language API

You can manipulate data elements from the C language. There may be situations where it is too expensive to translate the data values from ASCII strings. Or you might want to read data in a special file format.

Data can manipulated from the C language using BLT vectors. You specify the X-Y data coordinates of an element as vectors and manipulate the vector from C. The barchart will be redrawn automatically after the vectors are updated.

From Tcl, create the vectors and configure the element to use them.

vector X Y
.g element configure line1 -xdata X -ydata Y

To set data points from C, you pass the values as arrays of doubles using the Blt_ResetVector call. The vector is reset with the new data and at the next idle point (when Tk re-enters its event loop), the graph will be redrawn automatically.

#include <tcl.h>
#include <blt.h>

register int i;
Blt_Vector *xVec, *yVec;
double x[50], y[50];

/* Get the BLT vectors "X" and "Y" (created above from Tcl) */
if ((Blt_GetVector(interp, "X", 50, &xVec) != TCL_OK) ||
    (Blt_GetVector(interp, "Y", 50, &yVec) != TCL_OK)) {
    return TCL_ERROR;
}

for (i = 0; i < 50; i++) {
    x[i] = i * 0.02;
    y[i] = sin(x[i]);
}


/* Put the data into BLT vectors */
if ((Blt_ResetVector(xVec, x, 50, 50, TCL_VOLATILE) != TCL_OK) ||
    (Blt_ResetVector(yVec, y, 50, 50, TCL_VOLATILE) != TCL_OK)) {
   return TCL_ERROR;
}

See the vector manual page for more details.

Speed tips

There may be cases where the bar chart needs to be drawn and updated as quickly as possible. If drawing speed becomes a big problem, here are a few tips to speed up displays.

Limitations

Auto-scale routines do not use requested min/max limits as boundaries when the axis is logarithmically scaled.

The PostScript output generated for polygons with more than 1500 points may exceed the limits of some printers (See PostScript Language Reference Manual, page 568). The work-around is to break the polygon into separate pieces.