9
$\begingroup$

I would like to make Mathematica documents with hidden calculations, such that they can be visualized on demand. In general it can be done in several forms and I actually use some. I would like to ask about one specific way of doing that. Namely, I would like to make a button incorporated into either inline or input cell. Upon pressing on this button a separate notebook should open containing the calculations.

It is easy to make this, if the document only contains output cells. For instance, this

button1[expr_, sz_] := Button["Evaluate expression",
   CreateDocument[expr, WindowSize -> {sz, sz}]];

button1[Expand[(x + y)^2], 300]

makes a button which opens the window with the result x^2+2xy+y^2.

It is easy to make a notebook with a cell that can be later evaluated:

button2[expr_, sz_] := Button["Evaluate expression",
   CreateDocument[
    ExpressionCell[expr, "Input"],
    WindowSize -> {sz, sz}]];
button2[Expand[(x + y)^2], 300]

but it also returns the already evaluated result. For whatever reason this:

SetAttributes[button2, HoldFirst];

does not help.

One can also show the both unevaluated input and the output like this:

button3[expr_, sz_: 300] :=
  Button["Show expression",
   nb = CreateDocument[
       {ExpressionCell[Unevaluated[expr], "Input"], 
      ExpressionCell[Button["Evaluate", Print@Evaluate[expr]], 
       "Input" ]},
     WindowSize -> {sz, sz}
     ]];
button3[Expand[(x + y)^2]]

However, I would like to get rid of the operator Unevaluated in the first cell.

My aim is to get a separate notebook that is generated from the initial document. This notebook should have an input and the corresponding output cell (or cells), which a) shows how some result has been achieved in the past and what was this result and b) in which I could try to change something in the input cell(s) and see what would happen, while the source code lays somewhere unchanged. Thank you, Alexei

$\endgroup$
0

2 Answers 2

3
$\begingroup$

With minor modification of your code, you can use

   button3[expr_, sz_: 300] := 
   Button["Show expression", 
   nb = CreateDocument[{ExpressionCell[expr, "Input"], 
   ExpressionCell[
   Button["Evaluate", 
    CellPrint@ExpressionCell[expr /. Defer[x_] :> x, "Output"]], 
   "Input"]}, WindowSize -> {sz, sz}]];
   button3[Defer@Expand[(x + y)^2]]

or

   button3[expr_, sz_: 300] := 
   Button["Show expression", 
   nb = CreateDocument[{ExpressionCell[expr, "Input"], 
   ExpressionCell[
   Button["Evaluate", 
    CellPrint@ExpressionCell[ReleaseHold@expr, "Output"]], 
   "Input"]}, WindowSize -> {sz, sz}]];
   button3[HoldForm@Expand[(x + y)^2]]

EDIT: I would go with Heike's s solution. But the following maybe of pedagocial value: ClearAll[func] preceeding definitions of functions that you edit/re-edit until you find a working version is a good practice. Forgetting this is the reason for the convoluted workaround in my original answer. So, the following works as OP intended:

   ClearAll[button4]; 
   SetAttributes[button4, HoldFirst]; 
   button4[expr_, sz_: 300] := 
   Button["Show expression", 
   nb = CreateDocument[{ExpressionCell[Defer@expr, "Input"], 
   ExpressionCell[expr,"Output"], 
   ExpressionCell[Button["Close window", NotebookClose[nb]]]}, 
   WindowSize -> {sz, sz}]]; 
   button4[Expand[(x + y)^2]]
$\endgroup$
6
  • $\begingroup$ Thank you. In principle, my Evaluate button is somewhat misleading. I used it, since could not see a better way to separate the input and output. The minimalistic code that fits my needs is the version of the first of the above possibilities: $\endgroup$ May 3, 2012 at 14:11
  • $\begingroup$ which is button4[expr_, sz_: 300] := Button["Show expression", nb = CreateDocument[{ExpressionCell[expr, "Input"], ExpressionCell[Evaluate[expr /. Defer[x_] :> x], "Output"], ExpressionCell[Button["Close window", NotebookClose[nb]]] }, WindowSize -> {sz, sz}] ]; button4[Defer@Expand[(x + y)^2]] $\endgroup$ May 3, 2012 at 14:12
  • $\begingroup$ I cannot understand, however, why one needs to use Defer as it is used in your code, rather than placing it inside the function like follows: ... ExpressionCell[Defer@expr, "Input"] ...? I tried and it does not work. Can you explain, why? $\endgroup$ May 3, 2012 at 14:17
  • $\begingroup$ @AlexeiBoulbitch, actually that's what I tried first for both Defer and HoldForm. I, too, find it puzzling that both ExpressionCell[HoldForm[expr]] and ExpressionCell[Defer[expr]] evaluate when they are inside CreateDocument. $\endgroup$
    – kglr
    May 3, 2012 at 17:00
  • $\begingroup$ But does not when both the attribute HoldFirst and defer are applied. I did not notice any trace of such a strategy in documentation. Good to know. Thank you. I also like the Heike's solution. It works beautifully. However, for a massive use I prefer a simple code that I fully understand and can change, if necessary. $\endgroup$ May 4, 2012 at 8:52
4
$\begingroup$

Not sure if this is what you had in mind, but maybe you could do something like this

SetAttributes[button, HoldFirst];
button[expr_, sz_: 300] := 
  Button["Show expression", 
   nb = CreateDocument[{ExpressionCell[Defer[expr], "Input", 
       CellTags -> "input"], ExpressionCell[Button["Evaluate",
        Module[{cell},
         NotebookLocate["input"];
         cell = NotebookRead[ButtonNotebook[]];
         SelectionMove[ButtonNotebook[], After, Notebook];
         CellPrint[Cell[cell[[1]], "Input", Editable -> False]];
         CellPrint[ExpressionCell[ToExpression[cell[[1]]], "Output", Editable -> False]]
         ]], "Input"]}, WindowSize -> {sz, sz}]];

button[Expand[(x + y)^2]]

Pressing the Show Expression button will create a popup notebook with the input form of the expression plus an Evaluate button. Every time you press this button the first input cell plus the corresponding output will be copied at the bottom of the notebook. This will allow you to keep track of the changes made to the original expression.

screenshot

$\endgroup$
4
  • $\begingroup$ uhhhh - nice drop shadow ;-) $\endgroup$
    – Yves Klett
    May 3, 2012 at 13:09
  • $\begingroup$ @YvesKlett that's the default when taking a screenshot of a window in OS X. $\endgroup$
    – Heike
    May 3, 2012 at 13:17
  • $\begingroup$ Coming from the strictly rectangular Windows desktop world, I had that one down as nifty Mathematica-based post-processing... might be worthy eyecandy for the upload palette. $\endgroup$
    – Yves Klett
    May 3, 2012 at 13:22
  • $\begingroup$ Thank you, it is nice, but I feel guilty, since I mislead everybody with the use of the evaluate button. I explained it in detail in the comment to the first answer, could you kindly have a look? $\endgroup$ May 3, 2012 at 14:17

Your Answer

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

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