Jeffrey P. Morrill 617-873-4561
Contents1. What is Scigraph? 2. Compiling and Loading the System 3. Examples of Making and Displaying Graphs 3.1. Running the Demo 3.2. Graphing a Sequence of XY Pairs 3.3. Graphing Multidimensional Data 4. Graphical User Interface 4.1. Common Graph Commands 4.2. Common Annotation Commands 4.3. Common Dataset Commands 5. Programmer's Interface 5.1. Dataset Classes 5.2. Graph Classes 5.3. Commonly Used Functions 5.4. Dataset Protocols 5.5. Hashtable Dataset Example 5.6. Modifying Dataset Display Behavior 5.7. Coordinate Systems 6. Acknowledgements 7. Copyright Notice
1. What is Scigraph?Scigraph is object oriented Common Lisp software for graphing numeric data. Scigraph provides two groups of objects for plotting data, "graphs" and "datasets". The default behavior of these objects is to handle all the details, including axis limits, data styles, legend position, and axis ticks/labels/precision. Pointer sensitivity provides users with interactive control over all plot options. There is also full programmatic control over these options. A graph can be thought of as a container for one or more datasets. The datasets are displayed on the interior of the graph, while the graph itself provides labels, axes, and other annotations. Several dataset classes are provided. The easiest to use simply requires a sequence of X,Y pairs. Such a dataset can be displayed as a line, a set of scattered points, or a bar graph. Other dataset classes can display equations, histograms, or contour data. Other user objects can be displayed as datasets if the user provides the dataset protocol described in section 5. Graphs support textual annotations. The graph title, axis labels, and legend are annotations. These can be moved with the pointer, and their character styles can be changed. Annotations also allow the user to label a graph with the x,y values of particular data points, or to compute statistics for a region of data that the user lassoes with the pointer. Scigraph requires Common Lisp and has been tested on Symbolics, Allegro, and Lucid Lisp environments under Dynamic Windows and CLIM (version 0.9 or later). Graphs may be displayed on either color or monochrome screens. This document begins by showing examples of how to create and display a simple graph. Then user interface operations such as editing, zooming, and annotating are discussed. Finally, portions of the software are documented for programmers who wish to embed Scigraph in other applications. The file DEMO-FRAME.LISP gives examples of making and displaying graphs.
2. Compiling and loading the system.First you must compile and load the DWIM system. Do this by compiling and loading the file dwim/load-dwim.lisp. Second, compile and load the file scigraph/load-scigraph.lisp. When loading each of these files for the first time, you will need to create a directory for the binary files to be placed in. The loading process will error if this directory does not exist, but there should be a debugger proceed option to allow one to resume after the directory is created.
Examples of Making and Displaying GraphsThese examples are for tutorial introduction to the facilities of Scigraph. Here and elsewhere, the package is assumed to be GRAPH. (in-package :graph)
3.1. Running the demo.The following makes a noisy sine wave dataset, an equation dataset, and graphs them in a popup window (see demo-frame.lisp for its source code): (make-demo-frame) The following makes a simple bar graph: (make-bar-demo) This writes a graph to a postscript file: (save-sample-graph)
3.2. Graphing a Sequence of XY PairsAs a simple example, suppose your data takes the form of a list of x-y pairs. The following example shows how to make a graph. (setq raw-data '((0 0) (1 -1.5) (2 3) (3 22) (4 8) (5 22))) (setq dataset (make-instance 'graph-data :symbologies '(:line-symbol) :data raw-data)) (setq graph (make-instance 'annotated-graph :title "Some Data" :x-label "Fortnights" :y-label "Furlongs")) (add-dataset graph dataset) The value of GRAPH is a graph object that is ready to be displayed. There are several ways to display it. If you want to pop up a window showing only the specified graph, try: (view-graphs (list graph)) If you want to display the graph on a specific stream, with some specified position and size, try: (stream-set-cursor-position* stream x y) (display-graph graph :width width :height height :stream stream) If you want a column of graphs (or several columns of graphs) use FILL-WINDOW-WITH-GRAPHS. The result is a graph of the raw data drawn on the specified stream, whose upper-left corner begins at the current cursor position and whose width and height are specified in pixels. The graph has a title, axis labels, a legend, and of course the data itself. Various parts of the graph are pointer sensitive, and moving the pointer around shows this. Click right over the center of the graph to get a menu of operations appropriate to the graph as a whole. Click right over the graph title (or any other pointer sensitive part to the graph) to get a menu of operations appropriate to it. The purpose of the dataset object is to understand the structure of the raw data and be capable of mapping over the x-y pairs. The default behavior is to assume that data points are lists of length 2, and that the raw data is a list of such points. However, applications may override this default behavior to accomodate virtually any data structure. The default display behavior of a dataset is to use one or more symbologies. A "symbology" is the name of a way to draw a data point. Available symbologies are: :SCATTER, :LINE, :LINE-SYMBOL, :STEP, :BAR. Within the :SCATTER symbology, users may pick symbols such as :DIAMOND and :CIRCLE, filled or unfilled, in some color. The purpose of the graph object is to take care of coordinate transformations, clipping, zooming, textual annotations, and the various options relating to borders and labels. Users may display several datasets on a single graph using the ADD-DATASET function repeatedly. Initially, the graph is scaled such that all the data can be seen and such that it fills the graph; this is called autoscaling. Autoscaling may be turned off to enable explicit control of axis limits. Alternatively, datasets may selectively provide information used in autoscaling.
3.3. Graphing Multidimensional DataHere is a more complex example. In this example, individual datums are not simply x, y pairs, but rather represent feature vectors with many dimensions. The application must provide accessor functions for extracting the X and Y values from the datum. The dimensions displayed on the graph may be changed simply by changing the accessor functions. (setq raw-data '( (0 0 0 0) (1 -1.5 2 4.5) (2 3 4 5) (3 22 11 6) (4 8 12 17) (5 22 19 15))) (setq dataset (make-instance 'multidimensional-data :symbologies '(:scatter) :data raw-data) (setq graph (make-instance 'graph-with-reselectable-axes)) (add-dataset graph dataset) (set-axes graph #'first #'third) (view-graphs (list graph)) ; graph of 1st vs. 3rd (set-axes graph #'second #'fourth) (view-graphs (list graph)) ; redisplays using axes 2nd vs. 4th
4. Graphical User Interface
4.1. Common Graph CommandsGraph commands are generally invoked using the pointer, by clicking right on the graph. This section documents those commands. The commands are placed in a command table called GRAPH, and applications that use graphs should include this table in the command table for the application.
Display Legend. The Legend displays an icon for each dataset in the margin area below the graph. Each dataset in the legend is pointer- sensitive, and clicking on the icon provides a menu of dataset operations. This field controls whether or not the Legend is displayed.
Autoscaling Options. Autoscaling sets the initial axis edges such that all the data can be seen and it fills the display. These options can be used to selectively turn off the autoscale behavior.
Display Grid. A grid is superimposed on the graph.
Labels and Borders. Set axis options such as labels, tick spacing, and tick numbering.
Axis Limits. Explicitly enter the x and y limits to use as the edges of the graph.
Scigraph puts its commands into the :GRAPH command table as well as the :GLOBAL command table. Programs that incorporate graphs should include one of these command tables in the command table of the program. In CLIM, this is done as follows:
(defpackage my-package (:use common-lisp graph))
(define-command-table 'my-command-table :inherit-from (:graph))
The parameters, a and b, may be edited to change the appearance of the dataset.
(make-instance 'equation-data :variable 'x :equation '(* (sin (* a x)) (sin (* b x))) :parameters '((a 2) (b 3)) :min 0 :max 10 :increment .1)
(setq set-of-values '(1 3 5 3 9 0 2 3 ...)) (make-instance 'histogram-data :sample-data set-of-values)>The values are collected into bins and displayed as a bar graph. If you want 20 bins (and thus 20 bars), supply the keyword :BIN-COUNT 20 to make-instance. Alternatively, you may specify the keyword :BIN-SIZE to specify the width of each bin. Neither of these keywords is required.
(VIEW-GRAPHS graphs &key columns autoscale reverse-video title left bottom width height)
(FILL-WINDOW-WITH-GRAPHS graphs &key columns autoscale stream reverse-video)
(DISPLAY-GRAPHS graphs &key stream width height)
(DISPLAY-GRAPH graph &key stream width height)>
(SAVE-POSTSCRIPT-GRAPH graph filename &key width height)
(REFRESH graph stream)
(ADD-DATASET graph dataset)
The following protocols are required: Display Data protocol: DISPLAY-DATA - How to display the dataset. MAP-DATA - Map function over each dataum of the dataset. MAP-DATA-XY - Map function over the x,y values of each datum. DATUM-POSITION - Return the position of a datum. DATUM-DISPLAYER - Function to display a datum. DATUM-STYLE-DISPLAYER - Function to display datum in a named style. Autoscale protocol: AUTO-SCALE-LIMITS - Provide information on scale requirements. The following protocols are optional: Presentation protocol: PRESENT-SELF-P - Am I presentable? GRAPH-PRESENT-INFERIORS-P - Should I present my inferiors? GRAPH-PRESENTATION-TYPE - Type of presentation. Legend Protocol SHOW-LEGEND - Show legend for this dataset? DISPLAY-LEGEND-DATASET - How to display the dataset for this dataset. ... See legend.lisp for details. Popup Accept Protocol: POPUP-ACCEPT - How to edit an object. POPUP-ACCEPTABLE - Is object editable? POPUP-ACCEPT-ITEMS - Items to accept. POPUP-ACCEPT-LABEL - A label for the editor window. Graph Label protocol: TITLE - Suggest a title for the graph. X-LABEL - Suggest an x axis label for the graph. Y-LABEL - Suggest a y axis label for the graph.
The application program may also control the presentation type of the displayed datums. The default presentation type is simply EXPRESSION.(defclass hash-data-mixin () ) (defmethod map-data ((self hash-data-mixin) (function t) (data t)) "Apply the function to each datum" (maphash #'(lambda (key value) (declare (ignore key)) (funcall function value)) data)) (defmethod datum-position ((self hash-data-mixin) (datum array)) "Get the actual X and Y values to plot." (values (aref datum 0) (aref datum 1)))
(defmethod datum-presentation-type ((self hash-data-mixin) (datum t)) 'hash-datum)
(DISPLAY-DATA dataset stream graph)
(DATUM-DISPLAYER dataset graph)
(DATUM-STYLE-DISPLAYER dataset graph style-type)
#'(lambda (STREAM U V DATUM) (declare (ignore datum)) (multiple-value-setq (u v) (uv-to-screen stream u v)) (draw-point* stream u v))
XY Coordinates. This is the coordinates of your data. UV Coordinates. This is like the stream coordinates except that the positive direction of the vertical axis is upward instead of downward. SCREEN Coordinates. This is the coordinates of the stream. It probably should be called stream coordinates.There are various functions for converting between coordinate systems. For example XY-TO-UV and UV-TO-STREAM.
To: RShapiro@bbn.com Cc: Kanderson@bbn.com From: Ken Anderson
Subject: histograms Date: Thu, 17 Oct 1996 17:07:14 -0400 Sender: firstname.lastname@example.org Content-Type: text X-UIDL: e70be37f6766209ee3dbac2d14f7614c Status: RO ;;; This makes a simple histogram of gaussian data. (in-package graph) (defun draw-it () (let* ((d (make-instance 'histogram-data :sample-data (gaussian-random-sample 500) :pattern t :color +red+)) (g (make-instance 'annotated-graph :x-tick-numbering :each :y-tick-numbering :each ))) (add-dataset g d) (view-graphs (list g)))) For scatter plots when you make a dataset use :symbologies (list :scatter) :data-symbol :circle. See equation.lisp you can set things up to switch quickly from on x vs y to another: ;;; The following dataset (MULTIDIMENSIONAL-DATA) and graph class ;;; (GRAPH-WITH-RESELECTABLE-AXES) go together. They are for the case where ;;; individual datums are not really xy pairs but more like feature vectors with many ;;; dimensions. You provide two accessor functions, one each for the x and y axes, ;;; using the SET-AXES function. Those two axes will then be displayed. SET-AXES ;;; may then be used to change the dimensions being displayed without having to make ;;; a new graph.