Closed ToeKneeFan closed 2 years ago
I assume you are using macOS. Be aware that macOS has some atypical ideas regrading modal dialogs, and they are not allowed to appear before the main form and can cause a crash if they occur early. Surfice is designed to allow scripting, and the scripts can occur at startup (e.g. an external Matlab or Python script could launch MRIcroGL or Surfice, have a figure generated and then close the program. This places clear constraints on how any errors are reported to the user.
Apologies, I should have clarified: I tested on both macOS Monterey 12.5 21G72 and Windows 10 21H2 build 19044.1889, and the issue is common across both.
Thank you, that makes sense. I suppose my main interest is the ability to be catch/check when a script issues an error. My use case is actually what you mentioned: calling Surfice in an external script then quitting. Calling Surfice will stop at a popup message with some errors (e.g., when an overlay is opened before a mesh) but not other errors (when the overlay is inaccessible or does not exist). Additionally, a nonzero exit code is not issued. Thus, the latter errors are somewhat invisible to the calling script. I mainly became aware of this because of #35.
Is there a way to catch when a script issues an error message when Surfice is called externally?
I have updated the macOS version of Surfice for you to test - this new version will report as version 1.0.20211212j
. I have tried to make the error messages from scripts more consistent. Further, if you run a script from another tool or the command line, it will report if the script completed successfully:
A successful script will ext with zero:
echo 'import gl\ngl.meshload("BrainMesh_ICBM152.rh.mz3")\ngl.overlayload("motor_4t95vol.nii.gz")\ngl.savebmp("tester123.png")\ngl.quit()\n' > tst.py
./surfice tst.py
echo $?
Unsuccessful scripts will exit with a non-zero value (1 for general error, 3 if the Python engine failed):
echo 'import gl\ngl.meshload("BrainMesh_ICBM152.rh.mz3")\ngl.overlayload("missing.nii.gz")\ngl.savebmp("tester123.png")\ngl.quit()\n' > tst.py
./surfice tst.py
echo $?
To use this, it is critical your scripts terminate with gl.quit()
. If you use the base Python methods to terminate (quit()
, exit()
or sys.exit(123)
the Python interpreter exit codes over-ride the Surfice exit codes (typically exiting with 0
). Another way to think about this is that gl.quit()
will stop the script and close the application gracefully while the base Python methods terminate the application abruptly.
This new version works well! When errors occur during processing (e.g., missing overlay or surfaces), Surfice terminates with a nonzero exit code as expected. Thank you very much for your time with this.
This may be intended behavior, but intuitively feels like an unintended inconsistency. When an overlay is loaded before a mesh has been loaded, a popup error message is raised ("Unable to load overlay: load background mesh first"). Yet, when an overlay fails to load because it does not exist, a message is printed in the Scripting output but does not raise a popup ("Unable to load overlay named ..."). This seems to be because the former error is raised by
showmessageX
in mesh.pas, whereas the latter is raised byGLForm1.ScriptOutputMemo.Lines.Add
in commandsu.pas. Called as a script (e.g.,\path\surfice.exe -S commands.txt
), the former failure is effectively silent. It is possible this is because errors that occur through scripting are not intended to raise popups. However, intuitively, I would expect failure to load an overlay to have a consistent behavior, independent of the path to that error.