8
$\begingroup$

I'm using an initialization cell to import a lot of data:

data = Import[myFiles];

and then I use a custom function to display this data with Manipulate:

Manipulate[customFunction[data,variable],{variable,{0,1}}]

I have to keep these two commands in two seperate cells, because importing the data in customFunction each time I manipulate variable would take a lot of time.

The problem is, when I start my notebook, Manipulate is evaluated automatically and sends a lot of error messages, because data is not defined. I know it might go against what Manipulate is made for, but is there a way to prevent Manipulate from being evaluated until I import my data for the first time?

$\endgroup$
  • 1
    $\begingroup$ You could always make the importing cell an initialisation cell? $\endgroup$ – Verbeia Apr 4 '13 at 8:27
  • 1
    $\begingroup$ Can't you use SaveDefinitions->True ? $\endgroup$ – b.gates.you.know.what Apr 4 '13 at 8:50
  • $\begingroup$ @Verbeia no because initialization cells are evaluated only just before a first cell is evaluated in the notebook, whereas Manipulate is evaluated right away. $\endgroup$ – Sulli Apr 4 '13 at 9:24
  • $\begingroup$ @b.gatessucks I didn't know this option and it looks like it does what I want! So basically with this option I would only need to evaluate data = Import[myFiles]; once and then again only if myFiles change? Is there a bad side-effect of saving a lot of information with SaveDefinitions -> True (in terms of time for the notebook to load for example)? $\endgroup$ – Sulli Apr 4 '13 at 9:27
  • $\begingroup$ @su1 My understanding is that with that option Manipulate will remember the last state it was in, including all controls. As to performance issues, you just have to try and see. $\endgroup$ – b.gates.you.know.what Apr 4 '13 at 9:35
6
$\begingroup$

I see three methods:

1. ValueQ

Keep the two separate cells and make the last one depend on data. If data has no value for any reason, the Manipulate-part won't be evaluated at all. For sake of consistency, I've included a first cell that clears any previous value of data, but this (just as the second cell) should be only evaluated once, at the start of your session.

 In[1] := ClearAll[data];

 In[2] := data = Import[myFiles];

 In[3] := If[ValueQ[data], Manipulate[...], "do nothing"]

2. Initialization option

Create just one cell, but put in the option Initialization which ensures that its content gets evaluated before the body of Manipulate is displayed:

  Manipulate[
     customFunction[data, variable], {variable, {0, 1}},
     Initialization :> (data = Import[myFiles])]

Though note, that his will load myFiles each time the Manipulate is re-displayed. If myFiles is large, this imposes quite an overhead every time.

3. Initialization cell

Keep the two cells and make the first one an initialization cell (like Verbeia said) (right click on cell bracket > Initialization Cell. From now on, any time you open this notebook, the initialization cell will be evaluated automatically.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Probably the first option would be the best for me. "Initialization option" is not good enough because myFiles take a few seconds to be imported, so it's better to import them only once. "Initialization cells" are not good enough because they are not evaluated automatically at start, they are evaluated only after I evaluate any cell and click "Yes" when asked if I want to evaluate all initialization cells, whereas the cell containing Manipulate is evaluated automatically! $\endgroup$ – Sulli Apr 4 '13 at 9:16
3
$\begingroup$

Here is an alternative which encapsulates everything in a graphical user interface and needs no global variables:

longimport = (Pause[5]; RandomReal[]) &;
Manipulate[
 If[data =!= None,
  Manipulate[customFunction[data, variable], {variable, {0, 1}}],
  Panel["Please load data!"]
  ],
 {{data, None}, None},
 Control[Row[{
    Button[Dynamic[If[data === None, "Load Data", "Reload Data"]], 
     data = longimport[], Method -> "Queued"],
    Button["Clear Data", data = None, Method -> "Queued"]
    }]],
 AppearanceElements -> None
 ]

You can of course use whatever other expression you prefer instead of None to indicate that the data has not yet been imported. The custom longimport function is of course just for testing purposes, you could also let the user select a filename and then import within such a function...

| improve this answer | |
$\endgroup$
2
$\begingroup$

This did it for me:

Manipulate[customFunction[data,variable], {variable,{0,1}}, SaveDefinitions->True]

No performance side affects here.

Thanks to user b.gatessucks for providing this answer in the question's comments.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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