PROGRAMMING  TIPS

Front End Grab Bag

The version 3.0 front end allows some manipulations that can greatly improve efficiency in the creation and revision of notebooks.

by Lou D'Andria and Stan Wagon

In this column we will present several tricks that show how the front end can be used to improve one's efficiency when working with notebooks. There is no question that the new front end is an incredibly sophisticated object. And now that typeset notebooks can be easily sent via e-mail, these sophisticated features can be used to enhance mathematical communication.

. Automatic Numbering

It is quite easy to use automatic numbering to number the section heads in a single notebook. Place the cursor at the beginning of a section head and use the Create Automatic Numbering Object menu item to create a CounterBox object that counts sections. This numeral will take on the correct section number, assuming you do not use any section style cells that are not meant to be section heads.

A trickier application will be useful to writers of books or sets of notes, who might want the chapter number to appear several places within a chapter. It is convenient to change the chapter number in one place and have it change throughout the chapter. This can be done as follows. Type your chapter's title into a Title cell at the top of the notebook, as in

Chemotaxis

Now you need to change the CounterAssignments option to this cell. This can be done through the option inspector (lookup CounterAssignments) or by unformatting the cell (ShowExpression menu item), making the edit, and then reformatting the cell. Pursuing the latter course, edit as follows.

Cell["Chemotaxis", "Title",
  CounterAssignments->{{"Title", 7}}]

Then reformat. Now any title counter that you include (you can make these using the Create Automatic Numbering Object menu item) will display as the number , provided you use no other cells in this style.

. Automatic Figure Numbering

The default method of numbering figures via the NumberedFigure style in some style sheets is a little awkward, because the figure number is included as a cell label. This places it on the outside of the cell. But traditionally figure captions have the lead-in (Figure x.y) placed right before the caption, perhaps in boldface. Here is a method to do just that. It requires you to edit a private or shared style sheet.

While editing the style sheet, select the cells within the Body Text section that define the SmallText style, and copy them to the bottom of the style sheet. Then unformat the first cell (ShowExpression menu item) and change the cell so that references to SmallText are now references to a new style name, such as FigureCaption.  You can of course alter other aspects of this style's appearance by changing or adding options to this cell.

Cell[StyleData["FigureCaption"],
  CellMargins->{{29, 29}, {6, 1}},
  TextJustification->1,
  LineSpacing->{1,1},
  ParagraphIndent->-20,
  CounterIncrements->"FigureCaption",
  FontFamily->"Helvetica",
  FontSize->9]

Don't forget to change SmallText to FigureCaption in the cells that define this style for other environments, such as for printing. When you've done this, you can close the style sheet.

Now the FigureCaption style should appear in the style list (Format menu) and you can use it to create figure captions. If you begin the caption with an automatic numbering object (Input menu) that counts FigureCaption cells, then these numbers will automatically update when new captions are moved or added.

Moreover, you can use automatic numbering to refer to this figure anywhere in your notebook as Figure .; if you insert other captions, the numbers will properly change throughout. To do this you must add a cell tag (Find menu) to the FigureCaption cell, and then use that cell tag when creating the counter that refers to this figure.

. Deleting Graphics

We found that selecting all the graphics cells in a file (which can be done on most platforms by holding the option or alt key down and selecting any one such cell) and deleting them all at once uses up lots of memory, sometimes more than we have. The problem persists even when Clear is used as opposed to Cut. Here's a snippet of code that will delete graphics one at a time. This is a little slow, but you can work in other applications while Mathematica does this, and so we have found this a fine solution to the problem.

DeleteGraphics :=
Module[{nb = SelectedNotebook[]},
  While[
    NotebookFind[nb,"Graphics",Next,CellStyle,
      AutoScroll->False]=!=$Failed,
    NotebookDelete[nb]
  ];
];

. Converting Graphics

In Mathematica 3.0 bitmap graphics are platform-independent, a great innovation which allows memory-intensive PostScript graphics to be converted to bitmaps and shipped to users on varying platforms. However, we found that such conversions on a large scale occasionally changed aspect ratios.  One can carry out the conversion one image at a time by using the following bit of code, which we have set up to take Bitmap as the default target type. Macintosh users might sometimes wish to convert to PICTBitmap, another way to save memory. This function requires the user to enter the number of graphics cells to be converted; that number can be found using the Cell Size Statistics menu item.

ConvertGraphics[n_, t_:"Bitmap"] :=
Module[{nb = SelectedNotebook[]},
  Do[
    NotebookFind[nb,"Graphics",Next,CellStyle];
    FrontEndExecute[
      FrontEndToken[nb,"SelectionConvert",t]
    ],
  {n}];
];

. Automatic Code Generation

The scheme for making packages autoload when needed is now very nice. The default upon the first evaluation in any notebook is to evaluate the initialization cells. Mathematica also warns the user that this is happening, but that can be turned off in the option inspector (look up InitializationCellWarning at the notebook and global levels ). One application of this is to create an initialization cell with some DeclarePackage commands; then any functions that are declared can be used, and the package will load automatically. Here's an example.

DeclarePackage["GraphColoring`", {"FourColor"}]

This command declares that FourColor is part of the GraphColoring package, so whenever FourColor is called, the package will be loaded if it has not already been loaded. So far so good. Now we need only place this in an initialization cell and then, when FourColor is called for the first time, the package will be loaded, all of this being transparent to the user. The problem is that a package might contain dozens of function names that want to be in the list of declared names. The serious package writer will be constantly editing the function names and adding options and the like. It will be a bother to constantly update the DeclarePackage line in a notebook that uses the package.

The following bit of code, to be used after the package is loaded, creates an initialization cell containing the DeclarePackage command that will work for the current state of the package; it can then be pasted into a notebook in place of the old version.

DeclareCell[str_] := Module[{nameStrs, cellStr},
  nameStrs = StringReplace[Names[str<>"*"],str ->""];
  cellStr = StringJoin[
    "DeclarePackage[",
    ToString[str,InputForm],
    ",",
    ToString[nameStrs,InputForm],
    "]" ];
  NotebookWrite[EvaluationNotebook[],
    Cell[cellStr, "Input", InitializationCell->True]]];

Here's an example that uses DeclareCell to create the necessary DeclarePackage command for the Calculus`DiracDelta` package.

Needs["Calculus`DiracDelta`"]

DeclareCell["Calculus`DiracDelta`"]

The result of the previous line is that the following cell appears in the notebook, already set up to be an initialization cell.

DeclarePackage["Calculus`DiracDelta`",{"DiracDelta", "SimplifyDiracDelta", "SimplifyUnitStep", "UnitStep", "ZeroValue"}]

. File Traffic Control

The user can place commands in an init.m file that will be loaded whenever the kernel is started. It is very useful to use this mechanism to change the $Path system command so that your packages can be placed in convenient directories, as opposed to the AddOns:ExtraPackages directory, which always works but might not be the best home for the packages.

First, be sure to identify the correct init file. The one we are using is in the Configuration:Kernel folder. By placing the following line in this file, the path will be enlarged. Be aware that when you upgrade your version of Mathematica you may have to recreate this command. To see what paths look like on your computer you can examine $Path in its default state, or use the Get File Path menu item. The following line will add a single location to the search path.

Join[$Path,
  {"MainDisk:TheMathematicaExplorer:PACKAGES:"}];

While you're at it, you might want to execute other commands, such as  Off[General::spell1] by including them in your init.m.

7. Front End Tokens

Typical front end actions can be programmed as kernel functions or front end buttons through the use of FrontEndTokens and other constructs
new to 3.0. These FrontEndTokens are executed directly in the front end, and
so when activated from a button do not require a kernel. There are tokens 
corresponding to most menu items and key strokes. For example, here is a
button that causes the cursor to go back to where the most recent hyperli=
nk was clicked.

Go Back

This executes the same bit of front end code as selecting Go Back from the Find menu. To create this button in a notebook, use the following unformat= ted code (unformat any cell, replace what is there by the code that follows, then reformat).

Cell[BoxData[
    ButtonBox["Go Back",
      ButtonFunction :> (FrontEndExecute[
          FrontEndToken["HyperlinkGoBack"]]&),
      ButtonEvaluator -> None,
      Active -> True,
      ButtonFrame ->  "DialogBox"]], "Input"]

You can alter this button by replacing HyperlinkGoBack with any other FrontEndToken, or a list of commands and tokens. For  example, the following cell is a subsection cell which when clicked opens  and closes its cell group, just as the Open/Close Group item in the Cell Grouping submenu would.

Cell[TextData[ButtonBox["Functions and arguments",
  ButtonFunction := > (FrontEndExecute[{
      FrontEnd`SelectionMove[
        FrontEnd`ButtonNotebook[ ], All, ButtonCell],
      FrontEndToken["OpenCloseGroup"]}]&),
  Active -> True,
  ButtonStyle -> None]], "Subsection"]

Other tokens can be found in the Mathematica book, and in the MenuSetup.tr and KeyEventTranslations.tr files in the Mathematica layout.

ABOUT THE AUTHORS

Lou D'Andria does quality assurance for Wolfram Research.  He is interested in front end and kernel programming, and is currently helping teach a course programming cellular automata in Mathematica at the University of Illinois at Urbana-Champaign.

Lou D'Andria
Wolfram Research, Inc.
100 Trade Center Dr.
Champaign, IL  61820
lou@wolfram.com


Stan Wagon uses Mathematica extensively in his research, teaching, and exposition and is especially appreciative of the new ways in which Mathematica allows us to look at mathematical objects. He is author or coauthor of several books, including Mathematica in Action, Animating Calculus, VisualDSolve, and Which Way Did the Bicycle Go?. He also teaches a high-altitude Mathematica course every July in the mountains of Colorado.

Stan Wagon
Department of Mathematics and Computer Science
Macalester College
St. Paul, MN 55105
wagon@macalester.edu

ELECTRONIC SUBSCRIPTIONS

Included in the distribution for each electronic subscription is the file GrabBag.nb containing Mathematica code for the material described in this article.