# 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.]]