2
$\begingroup$

I am doing a time-intensive calculation and I would like to have the option to stop the calculation but obtain the current (last) result. Generally, I do some groundwork as what can be done before asking a question but this time I don't even know where to start. I wrote the "toy" version of my problem.

Here is the user interface that I would like to insert the "ABORT" button. and the "time-dependent" package.

BeginPackage["AbortCal`"];

  MainAbortCal::usage=" ";

Begin["`Private`"];

  MainAbortCal[tfinal_]:=Module[{a}
  , a=ConstantArray[1, {50, 50}]
  ; Do[a=a+1; Pause[2];,{i,tfinal}]
  ; plta=ListPlot3D[a,ImageSize->Full]
  ; {plta, a}
  ]


End[];
EndPackage[];


Panel[
  Framed[
    DynamicModule[
      {tfinal = 100}
    , Column[{
        Style["Compute","Subsection"],
        Row[{Style["Final Time ",12,Blue], InputField[Dynamic[tfinal]]},Spacer[5]],
        Button[Style["Compute",Green,Bold]
        , Res=AbortCal`MainAbortCal[tfinal]
        ; Plt=Res[[1]]
        ; a=Res[[2]]
        , Method->"Queued"
        ],
        Row[{Button["Stop",Interrupt[];Print[Dynamic[a]]]}],
        Row[{Style["Plot  ",12,Red],InputField[Dynamic[Plt],FieldSize->{50,15},Enabled->False,BaseStyle->{12}]},Spacer[15]]
      }]
    ]
  , Background->Lighter[Gray,.6]
  ]
]

I have the Pause[2] command there just to give me a time. I am not sure if there is a way to do what I want to do. Thank you for the help.

$\endgroup$
  • $\begingroup$ I edited your code so it is easier to use. $\endgroup$ – Kuba Apr 17 '18 at 11:58
2
$\begingroup$

Here is what I'd do:

  • decouple calculations from presenting results (Plot3D) , it gives you more control and is a very good habit for gui construction

  • how to capture, and if it is possible at all, calculations state after an abort is a case dependent problem. here we can pass a variable that will be updated live so once abort happens we can always use it

  • we can abort using FrontEndToken["EvaluatorAbort"] which is more reliable

Minor changes:

  • finished variable tracks whether the calculation is ongoing in order to display a progress indicator or something. users need to know :)

  • Internal`WithLocalSettings is used to make sure finished is set True despite aborting. If you want to use more documented method check CheckAbort and friends.

See closely related solution in: Button action monitored with progress bar

BeginPackage["AbortCal`"];

MainCalculation;
PlotMainCalculationResults;

Begin["`Private`"];

MainCalculation//Attributes = {HoldFirst};
MainCalculation[a_, tfinal_]:=Module[{}
, a=ConstantArray[1, {50, 50}]
; Do[a=a+1; Pause[2];,{i,tfinal}]
; a

]

PlotMainCalculationResults[a_]:=ListPlot3D[a, ImageSize->300]

End[];
EndPackage[];


    Panel @ DynamicModule[
      {tfinal = 100, a, finished = True, compute, display}
    , Grid[{
        {Style["Compute","Subsection"], SpanFromLeft},
        {"Final Time", InputField[Dynamic[tfinal]]},
        {"", Button["Compute", compute[], Method->"Queued"      ]},
        {"", Button["Stop", FrontEndExecute[FrontEndToken["EvaluatorAbort"]]]},
        {"Plot  ", Dynamic[display[]]}
      }]
    , Initialization:>(
        compute[]:= Internal`WithLocalSettings[
          finished = False,
          MainCalculation[a,tfinal],
          finished = True
        ];
        display[]:=Which[
          Not @ finished, Dynamic @ ProgressIndicator[Appearance->"Indeterminate"]
        , ArrayQ[a], PlotMainCalculationResults[a]
        , True, "compute first"]



      )
    ]

enter image description here

$\endgroup$
  • $\begingroup$ I think I can build on this one. I even started by adding "b" matrix. MainCalculation[a_,b_, tfinal_] and inside the code b=a; Do[a=a+1; b=b-50;Pause[2];,{i,tfinal}] and b everywhere that see a, except ArrayQ[a] . I plot c = a + b; ListPlot3D[c, ImageSize -> 300]] It is working but in the original version I can stop the calculation and push compute it starts over. My version gives an error.Cannot assign to raw object and gives minus values which is c matrix that I am creating. It does that even I do only ` ListPlot3D[a+b, ImageSize -> 300]]`. Do you know why? $\endgroup$ – Erdem Apr 17 '18 at 17:33
  • $\begingroup$ @erdem now you need HoldAll not HoldFirst. $\endgroup$ – Kuba Apr 17 '18 at 17:35
  • $\begingroup$ Awesome...works like a charm. Now time for me to build on that :) $\endgroup$ – Erdem Apr 17 '18 at 17:40

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.