3
$\begingroup$

I have a notebook that calculates some data in a relatively large time so I want to keep these data saved inside the notebook without recalculate them every time I open the notebook.

I know I can save them to an external file but this is not what I want.

Imagine that the first time I run the notebook after some time I get an array data. Now I close the notebook, I reopened it and I want to use the data stored in data without having to evaluate the notebook again.

$\endgroup$
  • $\begingroup$ You might take a look at the option SaveDefinitions->True with Manipulate or at DynamicModule as these should address your problem. $\endgroup$ – gwr Dec 19 '13 at 10:29
1
$\begingroup$

How about using

notebookHasData[] := Length[Cells[CellTags -> "data"]] > 0;

myData[] := RandomReal[1, 1000];

and

If[
 notebookHasData[],
 NotebookEvaluate[EvaluationNotebook[], 
   EvaluationElements -> {"Tags" -> {"data"}}, 
   InsertResults -> True];
 ,
 data = myData[];
 NotebookDelete[Cells[CellTags -> "data"]];
 CellPrint@
  Cell[BoxData@
    ReleaseHold@
     Hold[MakeBoxes][Hold[Set][Hold[data], Hold@Evaluate@data]], 
   "Input", CellTags -> "data"]
 ]

evaluating the big piece of code generates a cell that looks like

what the printed cell looks like

It checks if such a cell already exists. If it does, it evaluates that cell, rather than generating the data and the cell again.

This still requires you to evaluate one cell, whether it is the generated cell or a cell containing/refering to the "big piece of code" I show above. You could further automate this process by using an InitializationCell (which will prompt you), or by using some more advanced stuff using Dynamics or CellEvaluationFunction (this is hacky), which allow for solutions that will not prompt you.

This stores the data in quite an ineffecient way, with a lot of RowBoxes. We could make a text cell to store all the numbers and maybe make it invisible. Then we could probably make a function to extract the data from this cell by some other means than evaluation.

Do you want to share your notebooks with others and is that the reason you don't want to work with files? If there is no special reason, my advice would be not to get too perfectionistic about this, as I think solutions using files are usually better.

$\endgroup$
1
$\begingroup$

You can use DynamicModule:-

From documentation: "Symbols specified in a DynamicModule will by default have their values maintained even across Mathematica sessions."

In the example below the data in x is saved in list when 'save' is clicked. The 'save' button has to remain in the notebook, and in fact it needs to be visible before list is ready for use, (so a docked cell could be handy). When the notebook is reopened list is ready for use.

DynamicModule[{savelist = Null},
 Dynamic[Button["save", savelist = list = x],
  Initialization :> (list = savelist)]]

enter image description here

x = {1, 2, 3, 4};

Click 'save'.

list

{1, 2, 3, 4}

Save, close, quit and reopen. list is ready for use :-

list * 2

{2, 4, 6, 8}

$\endgroup$

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