'Transform unconstrained parameters used by the optimizer to constrained
parameters used in likelihood evaluation
Parameters
unconstrained : array_like
Array of unconstrained parameters used by the optimizer, to be
transformed.
Returns
constrained : array_like
Array of constrained parameters which may be used in likelihood
evalation.
Notes
Constrains the factor transition to be stationary and variances to be
positive.'

def transform_params(self, unconstrained):

    unconstrained = np.array(unconstrained, ndmin=1)
    dtype = unconstrained.dtype
    constrained = np.zeros(unconstrained.shape, dtype=dtype)
    constrained[self._params_loadings] = unconstrained[self._params_loadings]
    constrained[self._params_exog] = unconstrained[self._params_exog]
    if (self.error_cov_type in ['scalar', 'diagonal']):
        constrained[self._params_error_cov] = (unconstrained[self._params_error_cov] ** 2)
    elif (self.error_cov_type == 'unstructured'):
        constrained[self._params_error_cov] = unconstrained[self._params_error_cov]
    if (self.enforce_stationarity and (self.factor_order > 0)):
        unconstrained_matrices = unconstrained[self._params_factor_transition].reshape(self.k_factors, self._factor_order)
        cov = self.ssm['state_cov', :self.k_factors, :self.k_factors].real
        (coefficient_matrices, variance) = constrain_stationary_multivariate(unconstrained_matrices, cov)
        constrained[self._params_factor_transition] = coefficient_matrices.ravel()
    else:
        constrained[self._params_factor_transition] = unconstrained[self._params_factor_transition]
    if (self.enforce_stationarity and (self.error_order > 0)):
        if self.error_var:
            unconstrained_matrices = unconstrained[self._params_error_transition].reshape(self.k_endog, self._error_order)
            start = self.k_factors
            end = (self.k_factors + self.k_endog)
            cov = self.ssm['state_cov', start:end, start:end].real
            (coefficient_matrices, variance) = constrain_stationary_multivariate(unconstrained_matrices, cov)
            constrained[self._params_error_transition] = coefficient_matrices.ravel()
        else:
            coefficients = unconstrained[self._params_error_transition].copy()
            for i in range(self.k_endog):
                start = (i * self.error_order)
                end = ((i + 1) * self.error_order)
                coefficients[start:end] = constrain_stationary_univariate(coefficients[start:end])
            constrained[self._params_error_transition] = coefficients
    else:
        constrained[self._params_error_transition] = unconstrained[self._params_error_transition]
    return constrained
