I would like to evaluate a section several times for different values of some variables. I can evaluate it once with a simple command, but not in a loop.
To evaluate it only once, this code works
aValue = 6; activateB = True;
evaluateSection["mySection"]
where somewhere in the notebook there is a section called "mySection" containing this code
If[activateB , aValue * 100, aValue];
%//Print
Pause[2]
And the code of evaluateSection
is
Clear[evaluateSection]
evaluateSection[title_String]:=Module[{titleCell},
titleCell = SelectFirst[Cells[],
MatchQ[NotebookRead[#],
Cell[title,"Title"|"Subtitle"|"Chapter"|"Section"|"Subsection"|"Subsubsection",___]]&];
SelectionMove[titleCell,All,CellGroup];
SelectionEvaluate[EvaluationNotebook[]]
]
The code that does not work for me (it ignores the Pause, spitting all the namerun
at once (correctly) but does not evaluate the section with the required input values)
Do[
aValue = $aValue; activateB = $activateB;
evaluateSection["mySection"];
namerun = StringJoin[{"A", aValue, "B", If[activateB, "1", "0"]} // Map[ToString]];
Print[namerun];
,{$aValue,{0,2,4}}
,{$activateB,{True,False}}
]
EDIT
To be specific about the issue. Something is causing delayed or deferred evaluation of SelectionEvaluate
, which does not run at the same time as the Do
loop. Maybe (maybe) this should be expected, since the evaluation of the cell with Do
, has not finished, and therefore the evaluation of the cells inside mySection cannot be executed until the loop finishes. The instruction of SelectionEvaluate
is nonetheless kept in a sort of cue, and when the loop finishes, mySection is indeed evaluated as many times as the loop Do
requested, but without changing the variables, only using the last value that the variables had assigned.
Attempts at solutions:
If the problem is (close to) that, then something like taking in memory the contents of mySection and executing it inside the Do loop should work. For that (I guessed that) NotebookWrite and NotebookExecute might help. But with no success. Another attempt was to convert the execution of mySection to a (kind of more abstract) TaskObject
, and forcing it to execute with TaskExecute[SessionSubmit[SelectionEvaluate[...]]]
, and TaskWait
. No success either.
Another solution if the above is truly impossible:
Now I am thinking of changing the approach, and not using a Do
loop. But of course I still want to execute mySection, from another cell of the same notebook, iteratively for different values of the variables/flags. Maybe adding something at the end of mySection that, when it has finished running, returns the ball to the cell where the initial execution started (previously with the Do
loop), and from there, change the variables and call SelectionEvaluate again to evaluate mySection, until some condition stops it.
Conclusion: I think that managing to do this would improve the (already great) versatility of Mathematica. In my case, I developed a calculation in mySection, that now I need to run 72 times for different values of some parameters. If just adding a little code after mySection allowed me to do that, it would be awesome (for me and for the users of the package I am developing). If there are experts on the front end to help diagnose the problem, or some creative soul willing to give it a try, I would be so grateful.
aValue
andactivateB
are "localized" symbols insideDo
loop. They are not the same as the global symbols, which is why your section doesn't see their values. You could do some ugly things like:Do[aValue = $aValue; evaluateSection["mySection"], {$aValue, {0, 2, 4}}]
... But as I've said: Think about rewriting your code in a more standard way. $\endgroup$aValue
andactivateB
as parameters, and execute your code. Or you could make a separate Wolfram Language script file, and call it with command line arguments ... Also, what exactly do you mean by "without success"? Are you referring to the solution I've posted? It should work ... $\endgroup$Do[aValue = $aValue; evaluateSection["mySection"], {$aValue, {0, 2, 4}}]
$\endgroup$