NexScript Language

We recommend to use Python when developing new scripts.

NeuroExplorer also has a less powerful (than Python) internal scripting language NexScript. NexScript syntax resembles the Matlab language.

Lines and Comments in NexScript

Each line of the script may contain only one statement, for example:

x = 0

If the statement is very long, you can use the line continuation symbol (backslash \) to indicate that the next line contains the continuation of the current line. For example, instead of:

Dialog(doc, "D:\Experiment101\data\mydata\*.nex5", "Filter", "string")

you can write:

Dialog(doc, "D:\Experiment101\data\mydata\*.plx",\
"Filter"", "string")

The percent symbol (%) marks the beginning of a comment in NexScript, for example:

% this is a comment line
x = 0 % this is also a comment

Variable Names

The variable name in NexScript should begin with a letter and contain only letters, digits and the underscore sign.

The following names are valid:

Neuron01   Bar_press  Nr_1a    SPK02b

These variable names cannot be used in NexScript:

2Neuron   Bar-press

The variables from the opened data file can be accessed using the document reference with the variable name specified in the square brackets. For example, the spike train SPK01a from the active document can be addressed as:

doc["SPK01a"]

where doc is a reference to the document. You can get this reference by calling GetActiveDocument() or calling OpenDocument().

An alternative way to access file variable is by getting a reference to the variable:

SPK01a = GetVarByName(doc, "SPK01a")

Variable Types

NexScript supports numeric variables:

xmean = (xmax - xmin)/2.

and strings:

name = "SPK" + "01"

A variable can also be a reference to the existing variable in the file:

neuron1 = GetVar(doc, 1, "neuron")

or a reference to the opened document:

doc = GetActiveDocument()

A variable type can be changed if the right-hand side of the assignment has a different type. For example:

x = 0.005 % x now is a numeric variable
x = "SPK" % after this statement, x is a string

Global Variables

A variable can be declared global so that it can be accessed from several scripts:

Global name

Global statements should be placed at the beginning of the script.

Assignments Involving File Variables

If the left-hand side of the assignment is not a file variable:

v = doc["Neuron01"]

the script variable v will contain a reference (a shortcut) to the file variable Neuron01 and Neuron01 spike times will not be copied to v.

If the left-hand side of the assignment (doc["ContVarCopy"] below) is a file variable:

doc["ContVarCopy"] = doc["ContChannel01"]

all the data of the file variable ContChannel01 will be copied to the new file variable ContVarCopy.

For example, to create a new continuous variable containing rectified signal of continuous variable FP01, we can write the following code:

doc["FP01_Rectified"] = NewContVarWithFloats(doc, 10000)
for i=1 to GetContNumDataPoints(doc["FP01"])
    t = doc["FP01"][i,1]
    v = abs(doc["FP01"][i,2])
    AddContValue(doc["FP01_Rectified"], t, v)
end

We can achieve the same result using variable references and copying data to a new variable (and the code below will run more than 7 times faster than the code above):

doc["FP01_Rectified"] = doc["FP01"]
rectified = doc["FP01_Rectified"]
ContVarStoreValuesAsFloats( rectified )
n = GetContNumDataPoints( rectified )
for i=1 to n
   rectified[i,2] = abs( rectified[i,2] )
end

Access to the Data in File Variables

Timestamped Variables

You can access the timestamp value by specifying the timestamp index (1-based, i.e. the first timestamp has index 1) in square brackets:

doc = GetActiveDocument()
% first option: use doc["VarName"] notation
timestamp = doc["SPK01a"][3]
% second option: get variable by name and then use the variable directly
spikeTrain = doc["SPK01a"]
timestamp = spikeTrain[3]

You can assign a new value for any timestamp in the current file. For example, to assign the value 0.5 (sec) to the third timestamp of the variable SPK01a, you can use this script:

doc = GetActiveDocument()
doc["SPK01a"][3] = 0.5

You can also add timestamps to a variable using NexScript functions. See Modifying Variable Data Functions for details.

Interval Variables

IntVar[i,1] gives you read/write access to the start of the i-th interval, IntVar[i,2] gives you read/write access to the end of the i-th interval.

For example, to assign the value 27.5 seconds to the end of the first interval of interval variable Frame, you would use this script:

doc = GetActiveDocument()
doc["Frame"][1,2] = 27.5

You can also add intervals to an interval variable using NexScript functions. See Modifying Variable Data Functions for details.

Continuous Variables

ContVar[i,1] gives you read-only access to the timestamp of the i-th data point.

ContVar[i,2] gives you read-write access to the value of the i-th data point.

For example, the following script prints the timestamp and the value of the fifth data point in variable ContChannel01:

Trace("ts = ", doc["ContChannel01"][5,1], "value =" ,doc["ContChannel01"][5,2])

The following script line assigns the value of 100 to the fifth data point:

doc["ContChannel01"][5,2] = 100.0

Note that when you assign a value to a continuous variable that was imported from a file created by a data acquisition system, the assigned value might be clipped.

Data acquisition systems usually store continuous values as 2-byte integers. NeuroExplorer also stores imported analog data as 2-byte integers with some scaling factors.

For example, if analog to digital converter has input range from -1000mV to +1000mV, then maximum 2-byte value 32767 corresponds to 1000mV and the scaling factor is 1000/32768. If we try to assign the value that is outside the original input range, the value has to be clipped so that it could be stored as a 2-byte integer. For example, if we try to assign 2000mV, the stored value will be 32767 or 1000mV.

To avoid data clipping, use ContVarStoreValuesAsFloats() function to convert 2-byte integer storage to 4-byte float storage that does not have clipping problems.

Marker Variables

MarkerVar[i,1] gives you read-only access to the timestamp of the i-th marker.

MarkerVar[i,2] gives you read-only access to the value of the first field of the i-th marker. Note that marker field values are stored as strings, so you will need to use StrToNum() function to convert these values to numbers.

For example, the following script prints the timestamp and the first field value of the fifth marker in variable Strobed:

Trace("ts = ", doc["Strobed"][5,1], "marker value =" ,doc["Strobed"]5,2])

Expressions

Standard algebraic expressions are supported:

xmean = (xmax - xmin)/2.

Addition operation can also be applied to the strings:

name = "SPK" + "01"

Logical expressions may be used in if and while statements:

x = 2

if x >= 2
    Trace("x is greater or equal to 2")
end

if x > 2
    Trace("x > 2")
end

if x <= 2
    Trace("x <= 2")
end

if x == 2
   Trace("x equals 2")
end

if x <> 1
   Trace("x is not equal to 1")
end

Logical expressions may be combined using logical AND (&) or logical OR (|) operators:

if (x >= 2) & (y <4)
    Trace("x <=2 and y <4")
end

if (x >= 2) | (y <4)
    Trace("x <=2 or y <4")
end

Flow Control in NexScript

Loops

NexScript supports two types of loops: for loops and while loops.

for loop has the following syntax:

for variable = expression to expression
   statements ...
end

Example:

for i = 1 to 10
    SelectVar(doc, i, "neuron")
end

while loop has the following syntax:

while logical_expression
   statements ...
end

Example:

i = 1
while i < 10
    SelectVar(doc, i, "neuron")
    i = i + 1
end

break

break statement causes an immediate exit from the loop.

The following loop

for i = 1 to 10
   Trace(i)
   if i == 5
      break
   end
end

will produce output: 1 2 3 4 5

continue

continue statement returns to the loop’s beginning skipping the statements that follow it.

The following loop

for i = 1 to 5
   if i == 3
      continue
   end
   Trace(i)
end

will produce output: 1 2 4 5

return

return statement causes an immediate exit from the script.

Conditional operators

Operator if has the following syntax:

if logical_expression
   statements ...
end

or

if logical_expression
   statements ...
else
   statements ...
end

Example

% select a variable if it has at lest one spike
% otherwise, deselect the variable

if GetVarCount(doc, i, "neuron") > 0
    SelectVar(doc, i, "neuron")
else
    DeselectVar(doc, i, "neuron")
end