Introduction

When you are creating new scripts (QtScript *.qs) and you want to test it's functionality or if you want to track down a bug in your script it's important to know what tools you can use to debug your code. Currently BrainStim unfortunately doesn't have yet a fully flavored debugger for testing your code with various tools for adding breakpoints or running your program step by step and resolve values. Below here are some techniques/features described which you may like to use for debugging your scripts.

Using the Output Log window

The Output Log window is one of the most common tools for gathering information while a script is running. You can easily access and change this Output Log window from within the script. Appending a line of text can be easily done by using the Log() or BrainStim.write2OutputWindow() function. These functions are internally the same, they both accept a string value for the first parameter that contains the message that should be logged. The BrainStim.write2OutputWindow() function accepts another optional parameter that contains the name of the tab/sub-window to which the message should be written to, by default all messages are written to the standard 'Default' sub-window. Furthermore the Log() function is off course also quicker to type. Let's try this (the final result of the below steps are saved to the file OutputLogwindow.qs that is located in the Main Program Directory subfolder \Examples\BrainStim\QtScript Logging\):

  1. Create a QtScript document (File > New > QtScript Document) and enter (or copy/paste) the following text to the document:
     
    Log("My first logged message.");
    var sumResult = 3 + 4;
    BrainStim.write2OutputWindow("3 + 4 =" + sumResult);
  2. Execute (press the F5 key) the QtScript code and validate that some text was written to the 'Default' sub-window of the Output Log window.
  3. Aside standard text you can make use of some special characters and markup for the logged message, like:
    - '\n' a newline escape sequence that forces an end-of-line causing the message after this to appear on a new line.
    - '\t' a tab escape sequence that inserts a tab.
    You can even format your message using HTML/CSS. Let's try this by appending the following text to our document:
     
    Log("\nAdding\tSome\tTabs \nand Line-breaks.\n"); 
    Log("<h1>Header 1</h1>"); Log("<h2>Header 2</h2>"); 
    Log("<h3>Header 3</h3>"); Log("<h4>Header 4</h4>"); 
    Log("<font color=\"red\">This is some <em>custom</em> <strong>formatted</strong> text.</font>");
  4. Execute (press the F5 key) the QtScript code and validate the text that was written to the 'Default' sub-window of the Output Log window.
  5. As already mentioned the BrainStim.write2OutputWindow() function accepts another optional parameter that contains the name of the tab/sub-window to which the message should be written to. Before we can do this we need to make sure to add this sub-window using the BrainStim.addOutputWindow() providing the new sub-window name as the first parameter, like:

    BrainStim.addOutputWindow("custom sub-window");
    BrainStim.write2OutputWindow("Custom sub-window logged message.", "custom sub-window");
  6. Execute (press the F5 key) the QtScript code and validate the above code again.
  7. You can manually clear Output Log window sub-window by either closing it or by using the menu command Edit > Output Log > Clear All Output Item(s).

The above used functions are described in the BrainStim Main Application script reference. Some other interesting functions for controlling the Output Log window are:
-
BrainStim.clearOutputWindow() : Clears the Output Log window.
- BrainStim.removeOutputWindow() : Removes a named tab from the Output Log window.
- BrainStim.saveOutputWindow() : Saves the content of a Output Log window to a file.

Additional global functions

We already mentioned above here the Log() function that internally simply executes the BrainStim.write2OutputWindow() function passing the same first argument (the message) and setting the second argument to 'Default' (for making sure that this Output Log window sub-window name is used). This Log() function is not described in a script reference document because it's a global function that doesn't "belong" to a object or namespace, like the BrainStim.write2OutputWindow() function is part of the BrainStim object/namespace. There're some more global functions like this, these are:

Some examples using the above functions are used the file AdditionalFunctions.qs that is located in the Main Program Directory subfolder \Examples\BrainStim\QtScript Functions\).

Error handling

Knowing how to handle script errors and how to debug them is important for when you're creating new scripts. Let's take a closer look into this topic using an existing example:

  1. Start BrainStim.
  2. Open the file ErrorHandling.qs that is located in the Main Program Directory subfolder \Examples\BrainStim\QtScript ErrorHandling\
    This example script contains different sections that can be uncommented by removing the double forward slashes (//) or by removing the start (/*) and stop (*/) commenting characters before each line or section of code.
    First execute (press the F5 key) the QtScript code to see what it does without any errors. Notice that a custom sub-window (named 'Script Output') is first added to the Output Log window. This sub-window is used for the output of custom messages so we can see what and when some script code has been executed. The 'Default' sub-window is only used for the automatic output of the internal script engine (error) messages. The two sub-windows should now contain something like:
     
    Default:
    ... Valid Script Syntax ...
    ... Script started Evaluating on 11:16:47...
    ... Total Time(ms): 4
    ... Script fully Evaluated on 11:16:47 ...
    Script Output:
    <<Script Start>>
    <<Script End>>

    In the 'Default' sub-window we see that the script syntax was valid and it took 4ms to execute, the 'Script Output' sub-window shows the two messages that are send to this sub-window at the start and end of the script execution. The 'Default' sub-window is automatically cleared each time you run a script, this is not the case for custom sub-windows that are added with the script function BrainStim.addOutputWindow() so we can do this using the script function BrainStim.clearOutputWindow() as we can see in the example document.
    Important!
    Because the next example generates syntax error that leads to a non execution of the script (and therefore not executing the BrainStim.clearOutputWindow() function) we have to clear the 'Script Output' Output Log window sub-window manually so we can better see what happens when we execute the script. Remove (clear) the 'Script Output' Output Log window sub-window manually by closing it.

  3. When you try to execute a QtScript document that contains one or more syntax errors then this is reported in the 'Default' sub-window of the Output Log window during evaluation of the script code (before the script is actually executed). When a syntax error is detected then the cursor will then automatically jump to the position in the script code where the syntax error was first detected and the 'Default' sub-windows shows a description of the syntax error containing the line and column of the syntax error position. Let's try this:
    Uncomment the QtScript code line that contains a syntax error:
    write2OutputWindow("forgot the last quote for closing this message, "Script Output");

    Execute (press the F5 key) the QtScript code and validate again the Output Log window sub-windows:

    Default:

    ... Invalid Script Syntax, the program contains a syntax error ...
    ... Script Syntax error at(line 7, col 70): Expected `;', `)' ...

    Notice that now the 'Script Output' Output Log window sub-window is not created by the script because the script is never executed because a script syntax error is detected! We can now see in the 'Default' Output Log window sub-window that a script syntax error was detected with some additional information about where (line, column) the syntax error was detected (notice that the cursor also automatically jumps to this section of the script code) and what it expected. Comment the line (move the cursor to the line and use the CTRL + k key combination), or reload (without saving!) (using the menu entry File > Reload) the document.

  4. Often an exception doesn't happen at the time the script is evaluated, but at the time the script code that raises the exception actually gets executed, let's try this by uncommenting the next script code lines from the example:
    BrainStim.write2OutputWindow("<<Before NonExistingFunctionCall()>>", "Script Output"); 
    NonExistingFunctionCall();//This function is nowhere defined BrainStim.
    write2OutputWindow("<<After NonExistingFunctionCall()>>", "Script Output");

    Note that the second line calls a function that doesn't exist because is nowhere defined, although this is syntaxial correct this line raises an exception when executed and causing the internal script engine to stop. Let's try this by executing (press the F5 key) the QtScript code and validate again the Output Log window sub-windows:

    Default:
    ... Valid Script Syntax ...
    ... Script started Evaluating on 13:31:31...
    ... Evaluate script::UncaughtException()
    Debug: MainWindow::executeScriptContent "... Evaluate script::UncaughtException()
    ... Script stopped Evaluating due to error on line 13: --> ReferenceError: Can't find variable: NonExistingFunctionCall...
    Script Output:
    <<Script Start>>
    <<Before NonExistingFunctionCall()>>

    Notice that now the 'Script Output' Output Log window sub-window shows us that the script actually started (because new messages are added) and ended some moment after the second message. The 'Default' Output Log window sub-window shows that the script code syntax was successfully validated and that the script was executed. At some moment an exception raised an error and the script stopped, the position and cause of the code that raised the exception are also shown here. This sub-window actually contained some more information, but for clarity reasons this is not shown in the above text.

    If we were in the middle of doing something important in the script code than this kind of error can be very unwanted because it leads to an immediate ending of the script. There's a solution for this which allows us to catch the exception and handle it before it raises an error causing the script to end. This is done by using a try/catch statements. Let's comment the above lines again (by selecting the lines to comment and then using the CTRL + k key combination), or reload the document (without saving!) (using the menu entry File > Reload) the document.

  5. Uncomment the next script code lines from the example document:

    try
    {
        BrainStim.write2OutputWindow("<<Before NonExistingFunctionCall()>>", "Script Output");
        NonExistingFunctionCall();//This function is nowhere defined
        BrainStim.write2OutputWindow("<<After NonExistingFunctionCall()>>", "Script Output");
    }
    catch (e)
    {
        BrainStim.write2OutputWindow(">> Error" + e, "Script Output");
    }

    Note that the above example script code is the same as the previous example code except for the try/catch statements. When an exception occurred inside the try block then the catch block is executed with the e parameter set to a exception description and the code is still further executed which gives us a possibility to handle it. Let's try this by executing (press the F5 key) the QtScript code and validate again the Output Log window sub-windows:

    Default:
    ... Valid Script Syntax ...
    ... Script started Evaluating on 13:57:42...
    ... Total Time(ms): 8
    ... Script fully Evaluated on 13:57:42 ...
    Script Output:
    <<Script Start>>
    <<Before NonExistingFunctionCall()>>
    >> ErrorReferenceError: Can't find variable: NonExistingFunctionCall
    <<Script End>>

    Notice that now the 'Script Output' Output Log window sub-window shows us again that the script started and completely finished (see last message). We can now also see that the script code inside the try block caused an exception causing it to immediately jump to the catch block where we used the e parameter to output some important information and proceed with the script. The 'Default' Output Log window sub-window shows that the script code syntax was successfully validated and that the script was executed.

Time critical script code

Sometimes you want to debug some time critical script code and need a way to gather some timing information while executing the script code. The easiest way for doing this is to make use of the Date object, see this online document for more information about this object. Let's try this:

  1. Open the file timecritical.qs that is located in the Main Program Directory subfolder \Examples\BrainStim\QtScript Timing\
  2. Execute (press the F5 key) the QtScript code and try to understand what it does by examining the code and Output Log window messages.
    Important here to understand is that the DateTime object is set to the current Date/Time at the moment that it's constructed like (using the new operator):
     
    objDateTime = new Date(); 

    The getTime() function simply returns the number of milliseconds between midnight of January 1, 1970 and the moment that the Date object was constructed like we did above here. We can then store the result of the getTime() function to a temporarily variable and re-construct (using the new operator) the Date object again followed by a getTime() function call and store that result in another temporarily variable. The difference between these temporarily variables is then the time it took to execute the code between the two moment that the Date object was constructed.

Additional debugging methods

It can happen that BrainStim or a plugin crashes while running an experiment or an script. Sometimes it's difficult to find out what caused this because the program stopped working. If this happens then you should first open and inspect the Main Log-file (stored in the Main User directory under the name logfile.txt) using BrainStim (or another text editor), read this document for more information about this topic.