Front-End Operations, 3D Density Plots, and Non-numerical Arguments

Members of the Wolfram Research Technical Support  staff present articles on problems and questions we encounter.  In this column, we give examples of operating on notebooks from the kernel,  putting graphics  into separate windows, making 3-D versions of density plots, and writing functions which do not evaluate until final arguments are given.

Removing all cells of a given style

Alan DeGuzman

It is often useful to be able to perform the same operation on all cells of a style (i.e., all Input cells or all Text cells).  On some platforms, the Mathematica front end has the ability to select all cells of a given style in a few key strokes.  (See the Tricks column, The Mathematica Journal, vol 7, issue 1 (Winter, 1997), page 16.)  Mathematica 3.0 includes new  functions for manipulating notebooks  from the kernel, making available the ability to find and operate on all cells of a given style in a platform-independent manner.

Here is a simple example of notebook manipulation from the kernel.  When the function below runs, it steps through each cell in the notebook it is in.  When it finds a cell with a tag matching the style type, it deletes that cell.  It continues doing this until it reaches the end of the notebook.  

[Graphics:Images/miller_gr_1.gif]

You use it by evaluating the function with the desired style argument  in the notebook you would like cleaned up:

[Graphics:Images/miller_gr_2.gif]

Automate saving cells similarly

Tom Hildrich

This is an extension of  Alan's KillCells example above.  It steps through all the cells and executes (from the kernel) the front-end command Edit menu - Save Selection As for each cell of the given style.  It uses the capability of the kernel to issue front-end  commands, in particular, the FrontEndExecute and FrontEndToken  functions to execute menu commands.  (Please note that the names of the frontend tokens and their correspondence with specific menu items are subject to change from release to release.)

[Graphics:Images/miller_gr_3.gif]

As an example,  the following command saves  each Graphics cell encountered as a Windows Bitmap file  (each graphic is placed in a separate file).

[Graphics:Images/miller_gr_4.gif]

This function can support other types of cells as well as other types of graphics file format.  Specifically, you can use any type of graphic that is in the Edit menu - Save Selection As menu (i.e. Encapsulated Postscript, Windows Metafile, etc).   The file-selection dialog that is brought up cannot be automated; the user must still specify the file name and path for each graphic saved.

The next command runs the equivalent of Edit menu - Save Selection As - Package Format on each Input cell in turn.  (Each cell is placed in a separate file and the usual rule that cells without the Initialization Cell property are in comments applies.  The cell with this command is not saved, as it is already selected for evaluation and cannot be simultaneously selected for being operated on.)

SaveSelectionAs["Input","Package"]

If you want all the  Input cells saved in one file,  Edit menu  - Save Selection As - Package Format would be better.  To delete all the output cells before saving, use Kernel menu - Delete All Output.

Token names and corresponding menu items can be found (for version 3.0) under the Mathematica installation directory in  
         SystemFiles/FrontEnd/TextResources/<platform>/MenuSetup.tr.

The file separator characters are ":" for Macintosh and "\" for MS-Windows.

Graphics in an external window  

Tom Hildrich

People accustomed to using the Mathematica kernel directly in the UNIX environment are used to seeing  graphics in separate  Motif windows.  The same feature can be imitated simply on  MS-Windows  computers.  The additional function and variable definitions can be kept in a  file that is loaded into Mathematica as a package.  A sample is below;  the pathnames and application name will need to be  customized for one's own  system.

The function DisplayToApplication[] creates a pure function of one argument (indicated by the #, see sections 2.2.5 and 2.6.4 in the Mathematica book ).  This function sends a graphics object to the application.  See the examples below.

The arguments to be provided are:

DisplayApplication is the full pathname of  the application you will be using to display the image,

DisplayDirectory is the path to the directory where you would like the image file to be  created,

DisplayFileName is the name of the file you want to be created, and

DisplayFileType is the type of file (graphics format) that you are creating.

The following code includes definitions for displaying by either of two applications:

[Graphics:Images/miller_gr_5.gif]

Here are examples of its use:

[Graphics:Images/miller_gr_6.gif]

By reseting the global symbol $DisplayFunction, you can make the one of these applications the default graphics  display method.

[Graphics:Images/miller_gr_7.gif]

or

[Graphics:Images/miller_gr_8.gif]


After changing $DisplayFunction, whenever you create a graphic it will automatically be displayed in the program you chose without having to specify the DisplayFunction option in each plotting function.

If the code above were placed into a simple text file one could load the definitions with the package  command Get (shorthand: << ).  For example,

[Graphics:Images/miller_gr_9.gif]

Creating an Automatic Autonumbering Style

William Robert Hoggard, Jr.

Autonumbering counts all occurences of a cell Counter Type in order of appearance in a notebook. The first cell of a given Counter Type will have the counter value 1, the second 2, and so on.  The following three cells (one line each), as well as the cell this paragraph is in, have the style Text.  An Autonumbering Object has been applied to the Counter Type Text.

Text

Text

Text

Of the preceding four text cells, two cells visibly indicate an Autonumbering Object. The first and third text cells do not visibly indicate an Autonumbering Object. You cannot skip the numbering of a specific Counter Type - although the cell may not be numbered, it is still counted.  (Notice that the numbering is from the top of the notebook;  in this case, that is the whole Tech Support column.)

This can sometimes be a problem when you would like to create Autonumbering objects of the same cell style, but different numbering sequences.  For example, suppose I have several text cells

  text ]
text ]
text ]
text ]

and want to number them

1 text ]
text ]
2 text ]
text ]

Instead  I get

   1 text ]
   text ]
   3 text ]
   text ]

because the counter is incremented even for cells which do not have the number displayed.

This  can be worked around by creating a new cell style, using one style for one numbering plan and the other style for the other plan.  The example below creates a new cell style, Question, with its own Automatic Autonumbering object separate from the autonumbering of Text cells.

Open a new notebook.

-Select Format menu > Edit  Style Sheet >Import Private Copy.

-Make a copy of the cell group Styles for Body Text  (we want to leave existing Text style unmodified)

-Rename the copied group   Styles for Body Question.

- Open the subgroups for  Styles for Body Question.

-Remove the  subgroup Prototype for style: "Small Text" .

-Open the subgroup  Prototype for style: "Text"

-Select  Show Expression from the Format menu.

-Change all occurences of  word "Text" to "Question" in the Styles for Body Question group.

e.g., change
        Cell[StyleData["Text"],

   CellMargins->{{12, 10}, {7, 7}},
LineSpacing->{1, 3},
   CounterIncrements->"Text"]

  to

   Cell[StyleData["Question"],
   CellMargins->{{12, 10}, {7, 7}},
LineSpacing->{1, 3},
   CounterIncrements->"Question"]
  

  and so on.
  
  -Close the Style Definitions notebook.
  
The new cell style, Question, should now appear in the Format menu - Style menu.

-Create a new cell  by typing the word  "Question".

-Select the cel l  bracket of the new cell and change the cell style to Question.

-From the Format  menu select Option Inspector (or from the Edit menu, select Preferences).

- Show option values for selection's style.

-In the Lookup field, enter  cellframelabels.

-Change the CellFrameLabels entry

    left----------------> None
to
    left---------------->Cell[TextData[CounterBox["Question"]]]

-Press Return (saves change)

-Close the Option Inspector.

The cell should now appear as

       1 Question            ]


-In a new cell type the word "Answer".

-Select the cell bracket and change the cell style to Text..

-From the Format menu, select Option Inspector (or from the Edit menu, select Preferences).

- Show option values for selection's  style.

-In the Lookup field, enter  cellframelabels.

-Under CellFrameLabels, change

    left-----------------> None
to
    left----------------->Cell[TextData[CounterBox["Text"]]]

-Press Return (saves change).

-Close the Option Inspector.

You should now see the following two cells in your notebook.

   1  Question ]
   1  Answer ]

-Create a new cell with the style Question.

-Create another cell with the style Text.

You should now have the following numbered cells.

   1 Question ]
   1 Answer ]
   2  Question ]
   2  Answer ]

One could also create a cell style,  Answer, with its own autonumbering variable.   Text cells could then be included among the Question and Answer cells  without changing their numbering.

Making a 3D version of a DensityPlot

Bruce Miller

The built-in function DensityPlot  indicates the value of the function by color.  Sometimes users decide after creating a DensityPlot that looks just right  to make a 3D version with the same color pattern.  They are surprised to find that simply switching to Plot3D does not give the same color pattern or even the same function values.

DensityPlot  uses function values differently from Plot3D.  DensityPlot uses the values at the center of each square to determine the color and Plot3D uses the average of the values at the corners of the squares.  By default, the same number of points are sampled by the two functions, but this means that one less square in each direction is generated by Plot3D.   If the PlotPoints  option is used to generate the same number of squares in each direction (the PlotPoints value one higher for Plot3D than for DensityPlot), the fact that the color can be based on different function values can still lead to some squares getting different colors.  ListDensityPlot and ListPlot3D have corresponding behavior - the values are interpreted as the centers of the squares in ListDensityPlot and as the corners  in ListPlot3D .   

Here is a DensityPlot.  The value of the  ColorFunction  option is the name of a function of one argument which returns a Mathematica color graphics primitive value.  Hue is a simple, colorful, choice.  Compared with the Plot3D which follows, the DensityPlot has the same color in the row and column closest to the axes and one more row and column.  (There are differences in the frames , labels, and ticks which I am not dealing with here.)

[Graphics:Images/miller_gr_10.gif]

[Graphics:Images/miller_gr_11.gif]

     -DensityGraphics-

[Graphics:Images/miller_gr_12.gif]

[Graphics:Images/miller_gr_13.gif]

     -SurfaceGraphics-


The best way to get the desired 3D replica of a  DensityPlot is to take the function values from the DensityPlot data structure (so the same colors will be generated), calculate the positions of the corners, and build 3D polygons from them.

Extract from the DensityPlot the array of z coordinates (the sampled function values).   If you evaluate FullForm[dp], you can see that the first argument to DensityGraphics is the array of z values .

[Graphics:Images/miller_gr_14.gif]

Find the highest and lowest values of the function.  These are needed to set the scale for calculating colors.  (The function indicated by the ColorFunction option is passed a value from 0 to 1, 0 corresponding to the lowest function value in the plot and 1 corresponding to the highest value in the plot.)

[Graphics:Images/miller_gr_15.gif]
[Graphics:Images/miller_gr_16.gif]

Create an array of colors corresponding to each square.  Here Hue should be replaced by the function set by  the ColorFunction  option, if different.  Notice that the z values  are scaled from their  actual range to 0-1.   The  & indicates a  pure function with the  # as the dummy argument (see sections 2.2.5 and 2.6.4 in the Mathematica book).  The Map applies the scaled Hue function to each element of the list of values zs to create an array of color primitives, Hue[value].

[Graphics:Images/miller_gr_17.gif]

Now create an array of {x,y,z} values of the corners.  There are 16 values in each direction, for the 15 squares.

[Graphics:Images/miller_gr_18.gif]
[Graphics:Images/miller_gr_19.gif]
     {2.0944, 0.837758, 0.983156}

We now have the corners of each square and the same colors for the squares as in the 2D  DensityPlot.  We can create Polygon[] objects and plot them with the Show function with whatever options are convenient.

[Graphics:Images/miller_gr_20.gif]

This  ViewPoint option gives a view from directly above.  This view make it easy to compare coloring with the original DensityPlot.

[Graphics:Images/miller_gr_21.gif]

[Graphics:Images/miller_gr_22.gif]

Here is the default view, from above and to the side.

[Graphics:Images/miller_gr_23.gif]

[Graphics:Images/miller_gr_24.gif]

The process described here is, in some sense, the reverse of the Shadow function in the Graphics`Graphics3D` Standard Add-On Package.  The ListSurfacePlot3D function in the Graphics`Graphics3D` Standard Add-On Package uses a function MakePolygons (by R. Maeder) with a compact algorithm to generate the corners of the polygons, but no coloring.

A function which does not evaluate

Bruce Miller

Most kernel functions will return unevaluated when given undefined symbols as arguments, for example,

Sin[x]
     Sin[x]

The standard way users write functions does not have this property.

f[q_] := q^2
f[x]
      2
     x

The way to get f[] to return unevaluated for non-numerical arguments is to write it in a way that is defined only for numerical arguments.

Clear[f]
f[q_?NumberQ] := q^2
f[x]
     f[x]

f[2.718]
     7.38752

The pattern  q_?NumberQ  will match one of anything, but only if it is a number.    In f[x], the x does not meet this criterion, so  the f[x] is just echoed as an undefined expression.

This  technique can be used to limit a function to just matrix arguments, integer arguments, etc, or to use the same function name with different definitions, depending on the type of argument.  Multiple pattern tests can be included in one function definition.

f[(n_?Positive)?IntegerQ] := n! 
f[n_] := Print["f expects a positive integer argument"]
f[3]
[Graphics:Images/miller_gr_25.gif]
f[2.4]
[Graphics:Images/miller_gr_26.gif]
f[-4]
[Graphics:Images/miller_gr_27.gif]

See section 2.3.5 in The Mathematica Book.

Document converted by Mathematica of Wolfram Research