Scripting 5.7. Vectors and matrices

### 1. What is a vector?

A numeric vector is an array of numbers, regarded as a single object. For instance, the squares of the first five integers can be collected in the vector { 1, 4, 9, 16, 25 }. In a Praat script, you can put a vector into a variable whose name ends in a number sign (“`#`”):

```    squares# = { 1, 4, 9, 16, 25 }```

After this, the variable `squares#` contains the value { 1, 4, 9, 16, 25 }. We say that the vector `squares#` has five dimensions, i.e. it contains five numbers.

Whereas in Scripting 3.2. Numeric variables we talked about a numeric variable as being analogous to a house where somebody (the numeric value) could live, a numeric vector with five dimensions can be seen as a street that contains five houses, which are numbered with the indexes 1, 2, 3, 4 and 5, each house containing a numeric value. Thus, the street `squares#` contains the following five houses: `squares#` [1], `squares#` [2], `squares#` [3], `squares#` [4] and `squares#` [5]. Their values (the numbers that currently live in these houses) are 1, 4, 9, 16 and 25, respectively.

To list the five values with a loop, you could do:

```    writeInfoLine: “Some squares:”``` ```    for i from 1 to size (squares#)``` ```       appendInfoLine: “The square of ”, i, “ is ”, squares# [i]``` ```    endfor```

Instead of the above procedure to get the vector `squares#`, with a pre-computed list of five squares, you could compute the five values with a formula, as in the example of Scripting 5.6. Arrays and dictionaries. However, in order to put a value into an element of the vector, you have to create the vector first (i.e., you have to build the whole street before you can put something in a house), so we start by creating a vector with five zeroes in it:

```    squares# = zero# (5)```

After this, `squares#` is the vector { 0, 0, 0, 0, 0 }, i.e., the value of each element is zero. Now that the vector (street) exists, we can put values into (populate) the five elements (houses):

```    for i from 1 to size (squares#)``` ```       squares# [i] = i * i``` ```    #endfor```

After this, the variable `squares#` has the value { 1, 4, 9, 16, 25 }, as before, but now we had the computer compute the squares.

### 2. Creating a vector

You can create a vector in many ways. The first way we saw was with a vector literal, i.e. a series of numbers (or numeric formulas) between braces:

```    lengths# = { 1.83, 1.795, 1.76 }```

The second way we saw was to create a series of zeroes. To create a vector consisting of 10,000 zeroes, you do

```    zero# (10000)```

Another important type of vector is a series of random numbers. To create a vector consisting of 10,000 values drawn from a Gaussian distribution with true mean 0.0 and true standard deviation 1.0, you could do

```    noise# = randomGauss# (10000, 0.0, 1.0)```

To create a vector consisting of 10,000 values drawn from a uniform distribution of real numbers with true minimum 0.0 and true maximum 1.0, you use

```    randomUniform# (10000, 0.0, 1.0)```

To create a vector consisting of 10,000 values drawn from a uniform distribution of integer numbers with true minimum 1 and true maximum 10, you use

```    randomInteger# (10000, 1, 10)```

To create a vector containing the integer numbers 1 through 64, you use

```    to# (64)```

To create a vector containing the integer numbers 10 through 20, you use

```    from_to# (10, 20)```

To create a vector containing linearly increasing (not necessarily integer) numbers from 10 through 20 in steps of 2, you use

```    from_to_by# (10, 20, 2)```

To create five linearly increasing numbers between 0 and 10 (i.e. { 0, 2.5, 5, 7.5, 10 }), you use

```    from_to_count# (0, 10, 5)```

To divide the range between 0 and 12 symmetrically with step 5 (i.e. { 1, 6, 11 }), you use

```    between_by# (0, 12, 5)```

To divide the range between 0 and 10 into five equal parts and list their centres (i.e. { 1, 3, 5, 7, 9 }), you use

```    between_count# (0, 10, 5)```

To sort the numbers in a vector (e.g. { 7.4, 1.3, 3.6 }), you use

```    sort# ({ 7.4, 1.3, 3.6 })```

which yields { 1.3, 3.6, 7.4 }.

To randomly shuffle the numbers in a vector (e.g. { 7.4, 1.3, 3.6 }), you use

```    shuffle# ({ 7.4, 1.3, 3.6 })```

which can yield { 1.3, 7.4, 3.6 } or any of the five other orders of the elements.

Vectors can also be created by some menu commands. For instance, to get vectors representing the times and pitch frequencies of the frames in a Pitch object, you can do

```    selectObject: myPitch``` ```    times# = List all frame times``` ```    pitches# = List values in all frames: “Hertz”```

### 3. Turning a vector into a number

For the vector defined above, you can compute the sum of the five values as

```    sum (squares#)```

which gives 55. You compute the average of the five values as

```    mean (squares#)```

which gives 11. You compute the standard deviation of the values as

```    stdev (squares#)```

which gives 9.669539802906858 (the standard deviation is undefined for vectors with fewer than 2 elements). The center of gravity of the distribution defined by regarding the five values as relative frequencies as a function of the index from 1 to 5 is computed by

```    center (squares#)```

which gives 4.090909090909091 (for a vector with five elements, the result will always be a number between 1.0 and 5.0). You compute the inner product of two equally long vectors as follows:

```    other# = { 2, 1.5, 1, 0.5, 0 }``` ```    result = inner (squares#, other#)```

which gives 1*2 + 4*1.5 + 9*1 + 16*0.5 + 25*0 = 25. The formula for this is ∑i=15 squares[i] * other[i], so that an alternative piece of code could be

```    result = sumOver (i to 5, squares# [i] * other# [i])```

### 4. Converting vectors to vectors

```    a# = squares# + 5 ; adding a number to each element of a vector```

causes `a#` to become the vector { 6, 9, 14, 21, 30 }.

```    b# = a# + { 3.14, 2.72, 3.16, -1, 7.5 } ; adding two vectors of the same length```

causes `b#` to become the vector { 9.14, 11.72, 17.16, 20, 37.5 }.

```    c# = b# / 2 ; dividing each element of a vector```

causes `c#` to become the vector { 4.57, 5.86, 8.58, 10, 18.75 }.

```    d# = b# * c# ; elementwise multiplication```

causes `d#` to become the vector { 41.7698, 68.6792, 147.2328, 200, 703.125 }.

A vector can also be given to a menu command that returns another vector. For instance, to get a vector representing the pitch frequencies at 0.01-second intervals in a Pitch object, you can do

```    selectObject: myPitch``` ```    tmin = Get start time``` ```    tmax = Get end time``` ```    times# = between_by# (tmin, tmax, 0.01)``` ```    pitches# = List values at times: times#, "hertz", "linear"```

### 5. What is a matrix?

A numeric matrix is a two-indexed array of numbers, regarded as a single object. In a Praat script, you can put a matrix into a variable whose name ends in two number signs (“`##`”):

```    confusion## = {{ 3, 6, 2 }, { 8, 2, 1 }}```

After this, the variable `confusion##` contains the value {{ 3, 6, 2 }, { 8, 2, 1 }}. We say that the matrix `confusion##` has two rows and three columns, i.e. it contains six numbers.

Whereas a numeric vector with five dimensions could be seen (see above) as a street that contains five houses, the matrix `confusion##` can be seen as a city district with two avenues crossed by three streets, where everybody lives on an intersection (the analogies start to get less realistic).

### 6. Creating a matrix

You can create a matrix in many ways. The first way we saw was with a matrix literal, i.e. a series of series of numbers (or numeric formulas) between nested braces.

The second way is as a matrix of zeroes. To create a matrix consisting of 100 rows of 10,000 zeroes, you do

```    a## = zero## (100, 10000)```

After this,

```    numberOfRows (a##)```

is 100, and

```    numberOfColumns (a##)```

is 10000.

Another important type of matrix is one filled with random numbers. To create a matrix consisting of 100 rows of 10,000 values drawn from a Gaussian distribution with true mean 0.0 and true standard deviation 1.0, you can do

```    noise## = randomGauss## (100, 10000, 0.0, 1.0)```

You can create a matrix as the outer product of two vectors:

```    m## = outer## (u#, v#)```

which is the same as

```    m## = zeros## (size (u#), size (v#))``` ```    for irow to size (u#)``` ```       for icol to size (v#)``` ```          m## [irow, icol] = u# [irow] * v# [icol]``` ```       endfor``` ```    endfor```

or in mathematical notation

 mij = ui vj (i = 1..M, j = 1..N)

where M is the number of rows and N is the number of columns.

### 7. Computations with matrices

```    c## = a## + b##```

Elementwise multiplication:

```    c## = a## * b##```

which does

 cij = aij bij (i = 1..M, j = 1..N)

Matrix multiplication:

```    c## = mul## (a##, b##)```

which does

 mij = ∑k=1K aik bkj (i = 1..M, j = 1..N)

where M is the number of rows of a, N is the number of columns of b, and K is the number of columns of a, which has to be equal to the number if rows of b.

Matrix-by-vector multiplication:

```    v# = mul# (m##, u#)```

which does

 vi = ∑j=1N mij uj (i = 1..M)

where M is the number of rows of m, and N is the number of columns of m, which has to be equal to the dimension of u. Also

```    v# = mul# (u#, m##)```

which does

 vj = ∑i=1M ui mij (j = 1..N)

where M is the number of rows of m, which has to be equal to the dimension of u, and N is the number of columns of m.

### 8. String vectors

You can create string vectors in the following ways:

```    a\$# = { "hello", "goodbye" }```

creates a vector with two strings, which you can access as `a\$# [1]`, which is “hello”, and `a\$# [2]`, which is “goodbye”.

```    a\$# = empty\$# (10)```

creates a vector with 10 empty strings, which you can access as `a\$# [1]` through `a\$# [10]`.

```    text\$# = readLinesFromFile\$# ("hello.txt")```

creates a vector with 100 strings if the file `hello.text` contains 100 lines of text.

```    fileNames\$# = fileNames\$# ("sound/*.wav")```

creates a vector containing the names of all WAV files in the folder `sound`.

```    folderNames\$# = folderNames\$# (".")```

creates a vector containing the names of all folders in the folder where the script resides.

```    inks\$# = splitByWhitespace\$# ("Hello, how are you?")```

creates a vector containing the strings “Hello,” (including the comma), “how”, “are”, and “you?”.