neurolabusc / surf-ice

GLSL surface rendering source code. Compiled versions available from NITRC. Loads 3DS, CTM, DXF, FreeSurfer, GII (GIfTI), GTS, LWO2, MS3D, MZ3, NV (BrainNetViewer), OBJ, OFF, PLY, STL, VTK. Tractography formats include BFloat, PDB, TCK, TRK, and VTK. Also NIfTI format voxelwise images.
https://www.nitrc.org/plugins/mwiki/index.php/surfice:MainPage
BSD 2-Clause "Simplified" License
105 stars 23 forks source link

"Unable to load overlay" fails somewhat silently depending on how error is caused #34

Closed ToeKneeFan closed 2 years ago

ToeKneeFan commented 2 years ago

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 by GLForm1.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.

neurolabusc commented 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.

ToeKneeFan commented 2 years ago

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?

neurolabusc commented 2 years ago

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.

ToeKneeFan commented 2 years ago

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.