Using Counters in Mathematica

P.J. Hinton
Mathematica Programming Group
Wolfram Research, Inc.

Last Revision: April 22, 1998

Introducing… the Versatile CounterBox[ ]!

Mathematica 3.0 introduced support for the use of  automatic numbering objects through the use of the CounterBox[ ].

The CounterBox[ ] can take one or two arguments.  The single-argument form:

CounterBox[counter style]

contains a string that identifies the name of a counter style.  This is just a labeling mechanism to distinguish between counters that may be numbering different things, such as a section, subsection,  a figure, or an equation.

A two-argument form also exists.

CounterBox[counter style,cell tag]

This allows you to make a reference to a previously used counter value.  The cell tag value is also a string.

A CounterBox[ ] can appear only in a TextData[ ] expression of a cell, so that means you can use them only cell styles associated with headings and body text.  They cannot be used in the contents of typeset math cells.

Prebuilt Example – Using Counters to Number Section Headings

Here is an example notebook expression that shows how the CounterBox[ ] structure can be used to number section headings.  Note that all CounterBox[ ] expressions appear as arguments to  TextData[ ] expressions.

Notebook[{
  Cell[CellGroupData[{
    Cell["Notebook's Title", "Title"],
      Cell[CellGroupData[{
        Cell[TextData[{
          CounterBox["Section"],
          " First Section"
        }], "Section"],
        Cell[TextData[{
          CounterBox["Subsection"],
          " Here is a subsection"
        }], "Subsection"]
      }, Open  ]],
      Cell[TextData[{
        CounterBox["Section"],
        " Here is a second section"
    }], "Section"]
  }, Open  ]]}]

You can see a copy of the notebook by clicking on the following button.

When the notebook opens, you'll see that the front end automatically shows numbers in place of the CounterBox[ ] expressions.  It's important to remember, that the underlying Cell[ ]expression still contains the box expressions.  If you swap the positions of the first and second subsection cells, you'll see the the front end adjusts the CounterBox[ ] values accordingly.

That's All Well and Good, but How Did You Get the CounterBox[ ] in the Cell?

In the example notebook above, we created these counters using the front end menu command Input -> Create Automatic Numbering Object…  Here is a step-by-step walkthrough of the procedure.

It's that simple.

What if I Want to Number an Equation?

We showed how one could use counters to number section headings, but we can also use them in numbering equations, just as done in a research paper.

Several of the style sheets that come with Mathematica have a style menu listing for NumberedEquation.

({{ArticleClassic, ArticleModern}, {Classic, Classroom}, {HelpBrowser, Report}})

All you need to do is set your notebook to use one of these shared style sheets.  A shared style sheet can be selected using the front end menu command Format -> Style Sheet.  Once a style sheet is selected, you can click on the front end menu command sequence Format -> Style -> NumberedEquation.  The cell will number itself in the right-hand margin automatically.

I mentioned earlier that you can't insert numbering objects in typeset math cells, so you may wonder how it is possible to add a counter to a typeset style cell?  The trick is that the numbering object resides in the right-hand frame label of the cell rather than in the contents of the cell itself.  That label contains a cell with a TextData[] expression, which holds the counter box.

You can inspect the low level trickery that is used by opening up the notebook's style sheet and unformatting the prototype cell for NumberedEquation.  I won't go into too much more detail except to say that frame labels for a cell are set with the option CellFrameLabels, which is somewhat similar to the FrameLabel option for graphics objects.

What's the Purpose of the Two-Argument Form of CounterBox[ ]?

The automatic numbering mechanism allows you to move things around without having to hand edit all the numbering labels, but the reason that you number sections, subsections, equations, etc. in the first place is so that you can refer to them elsewhere in your work.  The two argument CounterBox [ ] helps you to make easy references to numbered objects further on down the line.  Let's say that somewhere in our text, we derive a significant result, and then we want to refer to it in a subsequent paragraph.

Here is a sample "significant result" with a numbered equation.

(c^2)= (a^(2 ))+ (b^2)

The steps for making a reference are.

The counter value display will reflect whatever the equation number on the tagged cell resolves to.

Click on the following button to create a practice notebook for you to try out.

To see a worked solution, click on the next button.

How Does the Front End Know How What the CounterBox[ ] Value Should Be?

There are two options, usually set in the notebook's style sheet, tell the front end how to count.  The first is CounterAssignments, which says that the presencence of a cell of a given style sets the styles of certain counters to a pre-set value.  This is normally used to reset the counter to zero.

For example, the prototype for the Title cell style in the default style sheet makes the following assignments:

CounterAssignments->{{"Section", 0}, {"Equation", 0},
  {"Figure", 0},{"Subtitle", 0}, {"Subsubtitle", 0}}

Typically, you want to reset counters that are lower on the heading hierarchy.  The Section cell style, for example, has the following option:

CounterAssignments->{{"Subsection", 0}, 
  {"Subsubsection", 0}}

If you wanted to ensure that the mythical Equation counter style fell back to zero for each new section, you could edit the option to be:

CounterAssignments->{{"Subsection", 0},
  {"Subsubsection", 0},{"Equation", 0}}

The other option, CounterIncrements, controls how the presence of a cell of a particular style of will affect the uptick of values for counter styles.

For example, the prototype cell for the Section style contains this option:

CounterIncrements->"Section"

This means that a cell of this style will cause the Section counter style to increment by one.  Typically, the value of the CounterIncrements option will match the cell's style, but one could conceivably cause a cell to increase the value of a counter of a different style.

If you run into a problem where the values displayed by counters are not increasing with each additional appearance of a given cell style, then chances are that the CounterIncrements option has not been set for that cell style.

Can I Use Alternative Enumeration Systems, Like Roman Numerals?

The answer is "yes."  The appearance of the counter is controlled by the option CounterFunction, which is applied to the CounterBox[ ] itself. The default value is Identity, which results in Arabic numerals. Other supported types are listed in the table below.

({{Counter Function Type, CounterFunction :>}, {Roman Numerals, RomanNumeral}, {Capital Roman Numerals, CapitalRomanNumeral}, {abc... (lowercase 
	Latin characters), (Part[CharacterRange
	"a", "z"], #]&)}, {ABC... (uppercase 
	Latin characters), (Part[CharacterRange[
	"A", "Z"], #]&)}, {Greek Letters, (Part[CharacterRange[
	"\[Alpha]", 
	"\[Omega]"], #]&)}, {Capital Greek Letters, (Part[CharacterRange[
	"\[CapitalAlpha]",
	"\[CapitalOmega]"],
	 #]&)}, {Circled numbers, (Part[CharacterRange[
	"\:2460", "\:2469"], 
	#]&)}, {Black circled numbers, (Part[CharacterRange[ 
	" \:2776", "\:277f"], 
	#]&)}, {Black sansserifed 
	circled numbers, (Part[CharacterRange[
	"\:278a", "\:2793"], 
	#]&)}, {Days of the week, (Part[ 
	{"Monday", "Tuesday"
	"Wednesday", "Thursday",
	"Friday", "Saturday",
	"Sunday"}, #]&)}, {Months, (Part[ {"January", 
	"February",
  "March", "April", May",    
	"June", "July", 
	"August", "September",
	"October","November", 
	"December"}, #]&)}})

As you glance through this table, you may notice that many of these counter functions are written as pure functions.  Because the postfix form of Function (&) has a lower precedence than the infix form of RuleDelayed (:>), the pure function has to be enclosed in parentheses.

The CounterFunction option can also be inherited from an aggregate CounterBoxOptions option setting at a higher level.  This allows you to avoid having to set the appearance for each CounterBox[ ]that you create.

Some notes on Problems that You May Encounter...
If you use the Option Inspector to set CounterFunction option, you will notice that the scroll menu displays the names in the left-hand column of the table above, but the CounterFunction in the right hand column is what is placed in the underlying cell expression.  
Before you close the option inspector dialog, you may need to edit the function that is created because there are some problems in the strings for the characters.  These problems apply to the Greek characters and circled numbers.
For the two families of Greek characters, you will need to change the double backslashes to single backslashes.  For example, the function will have a string that looks like "\\[Alpha]" when it should be "\[Alpha]."
For the three families of circled numbers, you will need to change the quadruple backslashes to single backslashes.  For example, "\\\\:2776" will need to be changed to "\:2776". 
The circled number characters are represented by 16-bit hexadecimal Unicode values because Mathematica does not have any names for these characters.  They are mapped to character slots in the Zapf Dingbats font. In order for the appropriate glyphs to appear properly on screen, the Zapf Dingbats font must be installed on your system.
There is a problem with the Unix/X front end wherein the front end client's request for the font Zapf Dingbats includes a space in the family name field of the X logical font description. 
-adobe-zapf dingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific
Rather than the entry that is to be found in the fonts.dir file:
-adobe-zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific
You can work around the problem by addding a fonts.alias entry that maps the former font name to the latter font name.  See the X Window System User's Guide for information on how this is to be done.

What if I Want To Have Counters that Combine Values?

Many documents use a numbering system that combines counters from higher levels.  For example:

({{Section, 1}, {Subsection, 1.1}, {Subsubsection, 1.1.1}})

A way to create these types of counters is to enter subsequent counters.  However, this could become a tiresome task since, for example, you would have to repeat the Input -> Create Automatic Numbering Object…  menu sequence three times to create a single Subsubsection header.

You can streamline this process by creating Paste style buttons that insert a TextData expression that has the counters in a list.  Here is a way that you could create a counter that displays itself as Section.Subsection.Subsubsection:

ButtonBox[
        RowBox[{"Subsubsection", " ", "Counter"}],
        ButtonData:>TextData[ {
            CounterBox["Section"], ".", 
            CounterBox["Subsection"], ".", 
            CounterBox["Subsubsection"]}],
        ButtonStyle->"Paste"]

The Paste button style pastes the ButtonData option value whereever your text insertion cursor is placed.

Once the boxes are pasted, there may be a slight delay between the time you paste and the time the actual values are displayed, so you don't need to panic if you see "0.0.0" right from the start.

An palette which demonstrates this type of ButtonBox[ ] construction can be generated by clicking on the following button.

You may be able to use this as a template for your own work.

If this composite counter is to refer to a counter value from another section, you can select what has been pasted by the palette and then use the Option Inspector (set to the Selection scope) to change the reference tag option to be the appropriate cell tag value.  This will insert the chosen cell tag value into the second argument of every CounterBox[ ] in the selection.

This tutorial is Copyright © 1998 Wolfram Research, Inc.  All rights reserved.  It may be distributed without charge provided that its content remains unaltered.  No guarantees of support are made or implied.  Suggestions for improvement are welcome at e-mail address paulh@wolfram.com.  This notebook was composed and tested with Mathematica 3.0.2 for Linux (ELF binary).