24
$\begingroup$

If I am proficient on dedicated typesetting software (e.g. LaTeX) it makes sense to use that for typesetting but if I am not how can I use Mathematica to create good quality documents.

The question has been stimulated by an extended Q&A with David Stork.

$\endgroup$

1 Answer 1

28
$\begingroup$

If you are skilled in particular code or packages then the switching costs (in time, possibly also money) to adopt a new software/package are usually prohibitive. In the context of typesetting, if you already are well versed in a typesetting software, e.g. LaTeX then I don't see any reason to attempt publication quality documents with Mathematica. So the information below is really aimed at Mathematica users who do not have typesetting alternatives, or users who want to do development and publication from the one interface.

What I have written below was stimulated by my discussion with David Stork and is based on bits and pieces and scraps of code and notes I had lying around. It is definitely not exhaustive so I welcome other answers and any criticism of this answer. I've typeset a lot of pages over the years as an author of a book and then as publisher of Mathematica in Education and Research for 12 issues so I know from first hand experience that print ready documents can be created in Mathematica (but again, to be clear, I am not advocating Mathematica instead of e.g. LaTeX).

Stylesheets

Generally speaking you need to have a good (special) reason to style cells locally at the cell level. Doing this almost always leads to workflow problems if you need to make changes. It is much better, and more efficient, to use a custom stylesheet for you document creation. At the time of writing there were 539 questions tagged "stylesheet" on Mathematica StackExchange so information about configuring stylesheets should be sufficient, notwithstanding that it is not organised into a coherent tutorial for those starting from scratch. There is an introductory tutorial in the Mathematica documentation.

For what it is worth the way I generally create styles is firstly to create some content with several cell types, e.g. "Input", "Output", "Text" and so on. For "Text" I do not split cells at each paragraph. I keep entire blocks of text in one cell and use the options ParagraphSpacing, ParagraphIndent, LineSpacing, LineIndent to control the layout. So for text I might have something like this and I add a cell tag to the cell. Note that the code below is the underlying expression that you see from Cell > Show Expression.

Cell["\<Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\>", "Text",
 CellTags->"Text"]

With Format > ScreenEnvironment > Working I then use a combination of Format > Option Inspector and the text formatting options under the Format menu item to style the cell. The ruler toolbar can be used to set left and right cell margins. A bit more on that in another section. This leaves me with a "text" cell with lots of local options. These are the options that I want to use in my stylesheet. So I scrape them from the cell using code like this:

NotebookLocate["Text"];
cell = Cells[NotebookSelection[EvaluationNotebook[]]];
tmp = DeleteCases[NotebookRead[cell], CellTags -> _, {2}];
tmp /. Cell[_, x_String, y___] :> CellPrint@Cell[StyleData[x], y];

enter image description here

When using this method you should remove the highlighted options. If I want to give this a new style name but base it on the existing style then I do this:

NotebookLocate["Text"];
cell = Cells[NotebookSelection[EvaluationNotebook[]]];
tmp = DeleteCases[NotebookRead[cell], CellTags -> _, {2}];
tmp /. Cell[_, x_String, y___] :> 
   CellPrint@
    Cell[StyleData["MyNewStyle", StyleDefinitions -> StyleData[x]], 
     y];

So now we have a new working style that can be pasted into a stylesheet. Next step is to either remove all the local options or alternatively create a new cell with no options, then switch to With Format > ScreenEnvironment > Printout and repeat the above this time configuring the appearance with printing in mind. (Note that the default magnification might need to be changed in your Printout style)

NotebookLocate["Text"];
cell = Cells[NotebookSelection[EvaluationNotebook[]]];
tmp = DeleteCases[NotebookRead[cell], CellTags -> _, {2}];
tmp /. Cell[_, x_String, y___] :> 
   CellPrint@Cell[StyleData[x, "Printout"], y];

For setting colour schemes something like this might be useful.

Equations

If your objective is to display equations, possibly numbered, to convey some principle then I would recommend typesetting the equations directly into a text based cell such as "DisplayFormulaNumbered" or a custom cell derived from one of those cells. However equations can be rendered from Mathematica input. For example:

CellPrint[TextCell[Defer[y[x] == Integrate[x^2 Exp[-x], {x, 0, 1}]],"DisplayFormula"]]

enter image description here

This rendering is probably not what you expected given the options for my "DisplayFormula" style. The reason is that the evaluation produces BoxData rather than TextData:

enter image description here

What is needed here is a FormBox and TextData. We can try appending TraditionalForm:

CellPrint[TraditionalForm@
TextCell[Defer[y[x] == Integrate[x^2 Exp[-x], {x, 0, 1}]], "DisplayFormula", StripOnInput -> True]]

enter image description here

Close, but no cigar. The code did create an inline cell however, so the typeset equation can be cut and pasted.

Normally I type equations directly into a text cell, where I mean text in a generic sense, i.e. "Text", "DisplayFormula" and so on. The three assistant palettes are often useful for this. There is a catch however. Firstly try typing an equation in a Text cell.

enter image description here

Compare the box code of the last example with the code from the Text cell:

enter image description here

The problem is that "DisplayFormula" has an option DefaultFormatType->DefaultInputFormatType which seems to lead to the creation of BoxData cells rather than TextData cells. So a modified style is required:

Cell[StyleData["DisplayFormulaNumbered"],
 CellFrameMargins->False,
 CellFrameLabels->{{None, 
    Cell[
     TextData[{"(", 
       CounterBox["DisplayFormulaNumbered"], ")   "}]]}, {None, None}},
 DefaultFormatType->DefaultTextFormatType,
 TextAlignment->Center,
 ScriptSizeMultipliers->0.71,
 ScriptMinSize->7,
 ScriptLevel->0,
 SingleLetterItalics->True,
 SpanMaxSize->Infinity,
 CounterIncrements->"DisplayFormulaNumbered",
 MenuSortingValue->1710,
 FormatTypeAutoConvert->False,
 FontFamily->"Times",
 UnderoverscriptBoxOptions->{LimitsPositioning->False},
 FractionBoxOptions->{AllowScriptLevelChange->False}]

This style includes other useful options.

Now the equation is typeset as expected.

enter image description here

The underlying box code now looks much like you got in the Text cell:

enter image description here

Use SingleLetterItalics->True to ensure that your variables are italicised. A problem sometimes arise when you have several variables together. Suppose you had variables x, y, and z multiplied together. There may be a style guide that you need to conform to, to represent multiplication, e.g. centre dot, but assuming you simply want to make it clear that you have 3 variables and not one variable called xyz then one way to ensure each variable is treated as a single character is to insert an invisible character between them.

enter image description here

In this GIF an invisible space was inserted. Lists of these special characters are available here and here.

MakeBoxes, Format, Notations package

More on this section later. The Notations package is rather maligned on this site but it can be quite useful, when used within its limitations.

Automatic numbering and hyperlinking

More on this section later

Bulk changes

It is often convenient to hide code from documents. Common ways to do this are to close cell groups, set cell sizes to zero or delete the cell. To hide all input by selecting output cells and closing the cell group evaluate this:

NotebookFind[EvaluationNotebook[], "Output", All, CellStyle];
FrontEndTokenExecute["OpenCloseGroup"]

To only close selected cell groups, tag the cells you want to hide and then evaluate this:

NotebookLocate["HideMe"];
FrontEndTokenExecute["OpenCloseGroup"]

To close selected cells, tag the cells you want to close and then evaluate this:

NotebookLocate["CloseMe"];
SetOptions[NotebookSelection[EvaluationNotebook[]], CellOpen -> False]

To delete cells use the same methods to find and select the cells and then use NotebookDelete.

NotebookLocate["DeleteMe"];
NotebookDelete[EvaluationNotebook[]]

In addition to modification done within a notebook it is also possible to "bulk modify" several notebooks. For example if all notebooks you want to modify are in the same directory then obtain a list of the file names:

files = FileNames["*.nb", "../PathTo/YourDocuments/", 2]

Next you may want to modify a copyright notice in each of the notebooks and change some notebook options:

Clear[modifyNotebook];

modifyNotebook[$file_] := 
 Module[{nb = 
    NotebookOpen[$file, StyleDefinitions -> "MyStylesheet.nb"], 
   content, new},
  SelectionMove[nb, All, Notebook];
  content = NotebookRead[nb];
  new = content /. {Cell[_, "Copyright", ___] :> 
      Cell[TextData[{"Version 6.33\ncopyright © 2016 Acme Publishing"}], "Copyright", ShowCellBracket -> False]};
  NotebookDelete[nb];
  SetOptions[nb,
   WindowSize -> {600, 700},
   ShowCellTags -> False,
   Magnification -> 1.0,
   StyleDefinitions -> "MyStylesheet.nb"];
  Scan[NotebookWrite[nb, #] &, Flatten[{new}]];
  NotebookSave[nb];
  NotebookClose[nb]]

modifyNotebook /@ files;

Tweeking

Use tools such as these manipulates to figure out the best options for things like FractionBox

Manipulate[
 Column[{
   Dynamic@
    Style[Row[{"some  text ", 
        FractionBox["10", "2", Beveled -> b, 
         DenominatorAlignment -> d, NumeratorAlignment -> n], 
        " more text "}] // DisplayForm,
     48],
   Button["Paste",
    Print@(FractionBoxOptions -> {Beveled -> b, 
        DenominatorAlignment -> d, NumeratorAlignment -> n}),
    ImageSize -> 100]
   }],
 {{b, True, "Beveled"}, {True, False}},
 {{n, 0, "Numerator Alignment"}, -1, 1, 0.1},
 {{d, 0, "Denominator Alignment"}, -1, 1, 0.1}
 ]

enter image description here

You may need to have tildas or hats as overscripts to symbols:

Manipulate[
 Column[{
   Style[Row[{"some  text ", OverscriptBox["A", AdjustmentBox["^",
         BoxBaselineShift -> a,
         BoxMargins -> {{l, 0}, {0, 0}}], 
        DiacriticalPositioning -> f], " more text "}] // DisplayForm,
    48],
   Button["Paste",
    CellPrint[ExpressionCell[OverscriptBox["A", AdjustmentBox["^",
        BoxBaselineShift -> a,
        BoxMargins -> {{l, 0}, {0, 0}}], DiacriticalPositioning -> f],
       "Input"]],
    ImageSize -> 100]
   }],
 {{f, True, "Diacritical Positioning"}, {True, False}},
 {{a, 0, "Up/Down"}, -2, 2},
 {{l, 0, "Left/Right"}, -1, 1}
 ]

enter image description here

Manipulate[
 Column[{
   Style[Row[{Subscript["H", 3], Superscript["O", "+"]}], 
    ScriptBaselineShifts -> {b, t}, 36],
   Button["Paste",
    Print@
     ToBoxes@Style[Row[{Subscript["H", 3], Superscript["O", "+"]}], 
       ScriptBaselineShifts -> {b, t}],
    ImageSize -> 100]
   }],
 {{b, 1}, -2, 2},
 {{t, 1}, -2, 2}
 ]

enter image description here

Once you have customised the appearance for these special typeset items you can use the settings in a paste button. (I'll add an example later on).

Use AlignmentMarker to align equations. (I'll add an example later on)

Fixing unmatched brackets:

enter image description here

The option SpanMaxSize->Infinity expands the { to encapsulate all terms

enter image description here

Layout tweeking

Left and right hand cell margins can be adjusted using the Ruler toolbar. For typesetting a print ready document it is often useful to adjust cell margins. This code allows you to adjust cells margins to create or reduce space so as to getter a better fit of content within a page.

Module[{margins, nb = InputNotebook[]},
 Grid[{{Button["Top +1", SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     margins += {{0, 0}, {0, 1}}; 
     SetOptions[NotebookSelection[nb], CellMargins -> margins]], 
    Button["Top -1", SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     margins += {{0, 0}, {0, -1}}; 
     SetOptions[NotebookSelection[nb], 
      CellMargins -> margins]]}, {Button["Bottom +1", 
     SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     margins += {{0, 0}, {1, 0}}; 
     SetOptions[NotebookSelection[nb], CellMargins -> margins]], 
    Button["Bottom -1", SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     margins += {{0, 0}, {-1, 0}}; 
     SetOptions[NotebookSelection[nb], 
      CellMargins -> margins]]}, {Button["Left +1", 
     SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     margins += {{1, 0}, {0, 0}}; 
     SetOptions[NotebookSelection[nb], CellMargins -> margins]], 
    Button["Left -1", SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     margins += {{-1, 0}, {0, 0}}; 
     SetOptions[NotebookSelection[nb], 
      CellMargins -> margins]]}, {Button["Right +1", 
     SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     margins += {{0, 1}, {0, 0}}; 
     SetOptions[NotebookSelection[nb], CellMargins -> margins]], 
    Button["Right -1", SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     margins += {{0, -1}, {0, 0}}; 
     SetOptions[NotebookSelection[nb], 
      CellMargins -> margins]]}, {Button["Top 0", 
     SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     SetOptions[NotebookSelection[nb], 
      CellMargins -> {margins[[1]], {margins[[2, 1]], 0}}]], 
    Button["Bottom 0", SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     SetOptions[NotebookSelection[nb], 
      CellMargins -> {margins[[1]], {0, margins[[2, 2]]}}]]}, {Button[
     "Left 0", SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     SetOptions[NotebookSelection[nb], 
      CellMargins -> {{0, margins[[1, 2]]}, margins[[2]]}]], 
    Button["Right 0", SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     SetOptions[NotebookSelection[nb], 
      CellMargins -> {{margins[[1, 1]], 0}, margins[[2]]}]]}, {Button[
     "Default", SelectionMove[nb, All, Cell]; 
     margins = 
      CellMargins /. Options[NotebookSelection[nb], CellMargins]; 
     SetOptions[NotebookSelection[nb], 
      CellMargins -> {{Inherited, Inherited}, {Inherited, 
         Inherited}}]], Null}},
  ItemSize -> {Automatic, Automatic}]
 ]

Nudging elements within equations is also very useful (Insert > Typesetting). More information can be found in the documentation.

Print Settings

Print settings can be stored in a customised stylesheet or set locally for each notebook:

SetOptions[EvaluationNotebook[],
  PrintingStartingPageNumber -> 100,

  PageHeaders -> {
    {Cell[TextData[{CounterBox["Page"]}], "PageNumber"], 
     Cell[TextData[{"Title"}], "Header"], None},
    {None, None, 
     Cell[TextData[{CounterBox["Page"]}], "PageNumber"]}},

  PageFooters -> {{None, None, None}, {None, None, None}},
  PrintingOptions -> {
    "PrintingMargins" -> {{90, 90}, {60, 90}},
    "PaperSize" -> {596, 794},
    "PageSize" -> {596, 794},
    "PageHeaderMargins" -> {60, 60},
    "PageFooterMargins" -> {30, 30},
    "FirstPageFace" -> Right,
    "FirstPageHeader" -> False,
    "FirstPageFooter" -> False,
    "PrintRegistrationMarks" -> False}];

Headers and Footers

Headers and/or footers can include sections names in the running header (footer). For example suppose you had 6 named sections in your notebook. The options below will display a printed page that has the document title on the left hand page and section name on the right hand page. To use this code just enter the list of your section names, and your desired document title.

PageHeaders -> {
  {Cell[TextData[{CounterBox["Page"]}], "PageNumber"], 
   Cell[TextData[{"Document Title"}], "Header"], None},
  {None, Cell[
    TextData[
     CounterBox["Section", 
      CounterFunction :> (Part[{"Section 1", "Section 2", "Section 3",
            "Section 4", "Section 5", "Section 6"}, #] &)]], 
    "Header"], Cell[TextData[{CounterBox["Page"]}], "PageNumber"]}}
$\endgroup$
4
  • $\begingroup$ I am having trouble at the start. I copy the paragraph Lorem ipsum, .. and paste into a fresh notebook. I change the PargraphSpacing with Option Inpsector. But when I evaluate NotebookLocate["Text"]; cell = Cells[NotebookSelection[EvaluationNotebook[]]]; tmp = DeleteCases[NotebookRead[cell], CellTags -> _, {2}]; tmp /. Cell[_, x_String, y___] :> CellPrint@Cell[StyleData[x], y] I get a *Local definition for style "Text": Text` but the output is Null. I don't see the style information. $\endgroup$ Feb 28, 2016 at 17:14
  • $\begingroup$ @JackLaVigne my example was a bit confusing because I was showing the underlying expression. Just make a text cell and add some text to it -- best to use several paragraphs, and then add a cell tag called "Text" and now retry the style generating code. $\endgroup$ Feb 28, 2016 at 23:55
  • $\begingroup$ See the comment placed into an answer below. I still am experiencing problems. $\endgroup$ Mar 2, 2016 at 17:11
  • $\begingroup$ I am slow witted. ShowExpression on the Local definition for style "Text" is what I was missing. Thank you for your patience. $\endgroup$ Mar 3, 2016 at 23:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.