# Model matrices for mixed-level orthogonal arrays

For mixed-level orthogonal arrays, we generate model matrices using Helmert contrasts. First, we define an example array and calculate the Helmert contrasts for 2 and 3 levels.

The Helmert contrasts for a given number of levels can be generated with `helmert_contrasts()`

.
The rows of the array generated by the method correspond to the levels.
`oapackage.oahelper.helmert_contrasts()`

. The contrasts are orthogonal and normalized.

Define mixed-level array and calculate Helmert contrasts

```
>>> array = oapackage.exampleArray(54,1)
exampleArray 54: root array in OA(6,2,3^1 2^1)
>>> array.showarray()
array:
0 0
0 1
1 0
1 1
2 0
2 1
>>> hc3 = oapackage.oahelper.helmert_contrasts(3)
>>> hc2 = oapackage.oahelper.helmert_contrasts(2)
>>> print(hc3)
[[-1.225 -0.707]
[ 1.225 -0.707]
[ 0. 1.414]]
>>> print(hc2)
[[-1.]
[ 1.]]
>>> # the Helmert contrasts are orthognal and normalized
>>> print(hc3.T.dot(hc3))
[[3. 0.]
[0. 3.]]
>>> print(hc2.T.dot(hc2))
[[2.]]
```

The main effects for a mixel-level array are created by replacing each level in the array by the corresponding Helmert contrast

Intercept and main effects

```
>>> X=oapackage.array2modelmatrix(array, 'main')
>>> print(X)
[[ 1. -1.225 -0.707 -1. ]
[ 1. -1.225 -0.707 1. ]
[ 1. 1.225 -0.707 -1. ]
[ 1. 1.225 -0.707 1. ]
[ 1. 0. 1.414 -1. ]
[ 1. 0. 1.414 1. ]]
```

Note the Helmert contrasts for the 2-level column are +1 and -1. So the calculation for mixel-level arrays for a 2-level array yields the same results as the direct calculation for a 2-level design.

The interaction effects are created by determining for all pair-wise combinations of columns the product between the elements of the contrast vectors. For this array, there is only one column combination: one 3-level factor and one 2-level factor. The number of columns in the interaction part is therefore \((3-1)(2-1) = 2\).

Interaction model and information matrix

```
>>> X=oapackage.array2modelmatrix(array, 'interaction')
>>> print(X)
[[ 1. -1.225 -0.707 -1. 1.225 0.707]
[ 1. -1.225 -0.707 1. -1.225 -0.707]
[ 1. 1.225 -0.707 -1. -1.225 0.707]
[ 1. 1.225 -0.707 1. 1.225 -0.707]
[ 1. 0. 1.414 -1. -0. -1.414]
[ 1. 0. 1.414 1. 0. 1.414]]
>>> M=X.T.dot(X)
>>> print(M)
[[6. 0. 0. 0. 0. 0.]
[0. 6. 0. 0. 0. 0.]
[0. 0. 6. 0. 0. 0.]
[0. 0. 0. 6. 0. 0.]
[0. 0. 0. 0. 6. 0.]
[0. 0. 0. 0. 0. 6.]]
```