8
$\begingroup$

I would have some functions, for instance Plot, to generate their output using a different Cell's style rather than "Output". The reason is that I'm producing some documents with many images and, for editing reasons, I need to adjust some options of their cell's style.

Unfortunately, I cannot change the "Output" style, because other kind of outputs don't have the same formatting as images. Just to make and example, suppose I want all graphics centered in the cell, while other output left aligned. So, I would assign a custom style to the output generate by Plot. Is there any suggestion?

$\endgroup$
3
  • $\begingroup$ of course, I don't want to add CellPrint, ExpressionCell, and similar wrapper to the Plot command, I'm looking for something to set at StyleSheet level. $\endgroup$
    – bobknight
    Commented Jan 5, 2015 at 13:06
  • $\begingroup$ you could change the cell style of plots post generation. Just click on the cell bracket and select a different style $\endgroup$ Commented Jan 5, 2015 at 21:37
  • $\begingroup$ Thanks Mike for the reply. That's what I actually do, but working with hundreds of notebooks, each one having many graphics, I would be happy to have a programmatic way to achieve this. However, I guess it's not possible. $\endgroup$
    – bobknight
    Commented Jan 6, 2015 at 20:24

4 Answers 4

4
$\begingroup$

For Graphics output specifically there is a nice approach using $DisplayFunction:

(* create a new output style -- overwrites existing custom style sheet *)
SetOptions[EvaluationNotebook[],
 StyleDefinitions -> 
  Notebook[{Cell[StyleData[StyleDefinitions -> "Default.nb"]], 
    Cell[StyleData["altOutput"], TextAlignment -> Center]}, 
   StyleDefinitions -> "PrivateStylesheetFormatting.nb"]
 ]

(* define a display function *)
altOutput[expr_] := CellPrint @ ExpressionCell[expr, "altOutput"]

$DisplayFunction = altOutput;

Graphics output in this Notebook will now be centered. You could also set the DisplayFunction option for individual plot types independently rather than using the global $DisplayFunction parameter.

$\endgroup$
5
  • $\begingroup$ +1 Nice. Before they changed the default DisplayFunction/graphics typesetting behavior (V5, maybe?), I used the option all the time. Now I've forgotten that it exists. $\endgroup$
    – Michael E2
    Commented Jan 8, 2015 at 16:20
  • 1
    $\begingroup$ @MichaelE2 Thanks. The change came in version 6. You can still load the old graphics subsystem with << Version5`Graphics` and reload the new one with << Version6`Graphics` $\endgroup$
    – Mr.Wizard
    Commented Jan 8, 2015 at 16:21
  • $\begingroup$ I'd forgotten about DisplayFunction too! $\endgroup$ Commented Jan 8, 2015 at 22:33
  • $\begingroup$ Thanks Mr.Wizard, both the solutions you provided are useful for me. Indeed, that one using $DisplayFunction is easy and allows to customize each plot function in a different style, whereas the other one, that using "GeneratedCellStyles" allows to manage different kind of outputs and not only Graphics. $\endgroup$
    – bobknight
    Commented Jan 9, 2015 at 9:18
  • $\begingroup$ @bobknight You're welcome, and I'm glad I could help. :-) It would be nice if there were a more accessible interface for this kind of thing. $\endgroup$
    – Mr.Wizard
    Commented Jan 9, 2015 at 9:19
7
$\begingroup$

It is possible to change the style used for output with this Front End option:

"GeneratedCellStyles" -> {"Output" -> (* style *)}

One can change this style as part of the output formatting routine using $PrePrint, like this:

defaultOut[] := SetOptions[EvaluationNotebook[],
  "GeneratedCellStyles" -> {"Output" -> "Output"}]

altOut[] := SetOptions[EvaluationNotebook[],
  "GeneratedCellStyles" -> {"Output" -> "altOutput"}]

output[gr_Graphics] := (altOut[]; gr)
output[other_] := (defaultOut[]; other)

$PrePrint = output;

Now (bare) Graphics objects will be output with a Cell style of "altOutput" rather than "Output" yet other expressions will be handled normally. One could extend output to handle an arbitrary number of heads as needed. (Graphics is merely an example here.)

$\endgroup$
3
  • $\begingroup$ Is there any easy way to do this for just one output cell? Right now I'm using SetOptions[EvaluationNotebook[], "GeneratedCellStyles" -> {"Output" -> "Output2"}]; before the output and then SetOptions[EvaluationNotebook[], "GeneratedCellStyles" -> {"Output" -> "Output"}]; after it to restore future outputs back to normal. But this seems too complicated. Any help would be appreciated. $\endgroup$
    – RoberRM
    Commented Apr 27, 2018 at 19:49
  • 1
    $\begingroup$ I've asked this question (with more details) here: mathematica.stackexchange.com/questions/172125/… $\endgroup$
    – RoberRM
    Commented Apr 28, 2018 at 13:02
  • $\begingroup$ What is especially valuable with "GeneratedCellStyles", it is that this option can be set on the level of individual Cell: an example. Is this option (semi-)documented somewhere? $\endgroup$ Commented Oct 16, 2019 at 14:50
6
$\begingroup$

If you want to do it all programmatically you could import the notebook containing the cells with graphics and change the cell style for cells containing graphics:

changeStyle[file_String, newStyle_String] := 
  Module[{nb = NotebookOpen[file], nb1},
   nb1 = NotebookGet[nb];
   NotebookClose[nb];
   nb = nb1 /. (p1 : Cell[BoxData[GraphicsBox[_, ___]], "Output", ___] :> (p1 /. 
         "Output" -> newStyle) );
   NotebookSave[nb, file];
   ];

changeStyle["/pathTo/Untitled.nb", "Text"]

To address @MichaelE2 concerns:

changeStyle[file_String, newStyle_String] := 
  Module[{nb = NotebookOpen[file], nb1, newfile},
   nb1 = NotebookGet[nb];
   NotebookClose[nb];
   nb = nb1 /. (p1 : 
        Cell[BoxData[GraphicsBox[_, ___]], "Output", ___] :> (p1 /. 
         "Output" -> newStyle));
   newfile = 
    SystemDialogInput[
     "FileSave", {NotebookDirectory[], {"New File \"*.nb\"" -> {"*.nb"}}}, WindowTitle -> "Saved New Notebook"];
   If[newfile =!= $Canceled && newfile =!= $Failed,
    NotebookSave[nb, newfile]
    ]
   ];
$\endgroup$
2
  • 1
    $\begingroup$ +1. I might save the restyled notebook in a different file or directory, just because I'm a nervous ninny. $\endgroup$
    – Michael E2
    Commented Jan 7, 2015 at 0:55
  • $\begingroup$ thanks Mike, that seems to be a suitable workaround. I'll try it! $\endgroup$
    – bobknight
    Commented Jan 7, 2015 at 9:05
3
$\begingroup$

An alternative is to use $Post to post-process output automatically as it is generated.

For instance, the following outputs anything with the head Graphics in a style "centeredOutput", which could be defined in whatever manner one wants.

centerGraphics[g_Graphics | g_Graphics3D] := CellPrint@ExpressionCell[g, "centeredOutput"];
centerGraphics[x_] := x;

$Post = centerGraphics

One could center the graphics also by wrapping it in Pane:

centerGraphics[g_Graphics | g_Graphics3D] := Pane[g, Alignment -> Center, ImageSize -> Full];

Update: From a suggestion by Mr.Wizard, with this definition, formatting the graphics could be handled more gracefully by setting $PrePrint = centerGraphics and $Post =. (or leave $Post unset). Then the value of Out will be the graphics instead of the Pane.

Notes (updated) --

Any existing graphics would have to be reevaluated.

One should be aware that $Post affects the output value. For example, after executing Plot, the head of % would be Cell, if using the first definition of centerGraphics.

One can circumvent $Post by wrapping the graphics in a head that does not affect typesetting. For instance, Defer@Evaluate@Plot[Sin[x], {x, 0, 10}] would be printed in a normal "Output" cell but the graphics will still be centered.

Because of this, if one wishes to Deploy graphics, one might want to add a rule to centerGraphics to handle Deploy. For example, centerGraphics[g : Deploy[Graphics[__]] | ...] := ...

One need not create a special style. One can set options directly in ExpressionCell, such as with this body for the definition of centerGraphics:

CellPrint@ExpressionCell[g, "Output", TextAlignment -> Center]
$\endgroup$
3
  • $\begingroup$ Is there a reason you are using $Post rather than $PrePrint? The latter would address your concern regarding % unless I'm not thinking clearly. $\endgroup$
    – Mr.Wizard
    Commented Jan 8, 2015 at 15:52
  • $\begingroup$ @Mr.Wizard I'll check it out. I don't use these processors and forgot about $PrePrint -- Thanks! $\endgroup$
    – Michael E2
    Commented Jan 8, 2015 at 15:57
  • 1
    $\begingroup$ @Mr.Wizard The return value of $PrePrint seems to be wrapped in an "Output" cell. So it works for the Pane version of centerGraphics but not for the cell version. For that solution, $PrePrint seems preferable to me. I'm stuck for a workaround for the cell method at this point. $\endgroup$
    – Michael E2
    Commented Jan 8, 2015 at 16:05

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