Repository: scipy/scipy
File: scipy/stats/_multivariate.py (Python)

Code before:
            The dimensions of the multivariate distribution corresponding
            with the marginal variables, that is, the indices of the dimensions
            that are being retained. The other dimensions are marginalized out.

        Returns
        -------
        marginal_multivariate_normal : multivariate_normal_frozen
            An object representing the marginal distribution.
        """
        params = self._process_parameters(mean, cov, allow_singular)
        n, mean, cov_object = params

        dims = np.atleast_1d(dimensions)

        if len(dims) == 0:
            msg = ("Cannot marginalize all dimensions.")
            raise ValueError(msg)

        if not np.issubdtype(dims.dtype, np.integer):
            msg = ("Elements of `dimensions` must be integers - the indices "
                   "of the marginal variables being retained.")
            raise ValueError(msg)

        original_dims = dims.copy()

        dims[dims < 0] = n + dims[dims < 0]

        if len(np.unique(dims)) != len(dims):
            msg = ("All elements of `dimensions` must be unique.")
            raise ValueError(msg)

        i_invalid = (dims < 0) | (dims >= n)
        if np.any(i_invalid):
            msg = (f"Dimensions {original_dims[i_invalid]} are invalid "
                   f"for a distribution in {n} dimensions.")
            raise ValueError(msg)

        mean = mean[dims]
        cov = cov_object.covariance[np.ix_(dims, dims)]
        
        return multivariate_normal_frozen(mean, cov, allow_singular)    

multivariate_normal = multivariate_normal_gen()


class multivariate_normal_frozen(multi_rv_frozen):
    __class_getitem__ = None

    def __init__(self, mean=None, cov=1, allow_singular=False, seed=None,
                 maxpts=None, abseps=1e-5, releps=1e-5):
        """Create a frozen multivariate normal distribution.

Review comment (suggestion):
This can mutate user input. If gh-9932 has the same issue, let's fix that at the same time. TBH, can we factor out some of this input validation into a function and share it between the two classes? Probably the same stuff is going to be needed for `multivariate_t`, anyway.

Code after:
        if x.ndim != 2:
            raise ValueError("`x` must be two-dimensional.")

        n_vectors, dim = x.shape

        # parameter estimation
        # reference: https://home.ttic.edu/~shubhendu/Slides/Estimation.pdf
        if fix_mean is not None:
            # input validation for `fix_mean`
            fix_mean = np.atleast_1d(fix_mean)
            if fix_mean.shape != (dim, ):
                msg = ("`fix_mean` must be a one-dimensional array the same "
                       "length as the dimensionality of the vectors `x`.")
                raise ValueError(msg)
            mean = fix_mean
        else:
            mean = x.mean(axis=0)

        if fix_cov is not None:
            # input validation for `fix_cov`
            fix_cov = np.atleast_2d(fix_cov)
            # validate shape
            if fix_cov.shape != (dim, dim):
                msg = ("`fix_cov` must be a two-dimensional square array "
                       "of same side length as the dimensionality of the "
                       "vectors `x`.")
                raise ValueError(msg)
            # validate positive semidefiniteness
            # a trimmed down copy from _PSD
            s, u = scipy.linalg.eigh(fix_cov, lower=True, check_finite=True)
            eps = _eigvalsh_to_eps(s)
            if np.min(s) < -eps:
                msg = "`fix_cov` must be symmetric positive semidefinite."
                raise ValueError(msg)
            cov = fix_cov
        else:
            centered_data = x - mean
            cov = centered_data.T @ centered_data / n_vectors
        return mean, cov

    def marginal(self, dimensions, mean=None, cov=1, allow_singular=False):
        """Return a marginal multivariate normal distribution.

        Parameters
        ----------
        dimensions : int or 1-d array_like
            The dimensions of the multivariate distribution corresponding
            with the marginal variables, that is, the indices of the dimensions
            that are being retained. The other dimensions are marginalized out.
        %(_mvn_doc_default_callparams)s