scvi.model.utils.mde(data, accelerator='auto', device='auto', seed=None, **kwargs)[source]#

Util to run pymde.preserve_neighbors() for visualization of scvi-tools embeddings.

  • data (ndarray | DataFrame | spmatrix | Tensor) – The data of shape (n_obs, k), where k is typically defined by one of the models in scvi-tools that produces an embedding (e.g., SCVI.)

  • accelerator (str (default: 'auto')) – Supports passing different accelerator types (“cpu”, “gpu”, “tpu”, “ipu”, “hpu”, “mps, “auto”) as well as custom accelerator instances.

  • devices – The devices to use. Can be set to a non-negative index (int or str), a sequence of device indices (list or comma-separated str), the value -1 to indicate all available devices, or “auto” for automatic selection based on the chosen accelerator. If set to “auto” and accelerator is not determined to be “cpu”, then devices will be set to the first available device.

  • seed (int | None (default: None)) – Random seed for reproducibility passed into pymde.seed(). Defaults to scvi.settings.seed.

  • kwargs – Keyword args to pymde.preserve_neighbors()

Return type:



The pymde embedding, defaults to two dimensions.


This function is included in scvi-tools to provide an alternative to UMAP/TSNE that is GPU- accelerated. The appropriateness of use of visualization of high-dimensional spaces in single- cell omics remains an open research questions. See:

Chari, Tara, Joeyta Banerjee, and Lior Pachter. “The specious art of single-cell genomics.” bioRxiv (2021).

If you use this function in your research please cite:

Agrawal, Akshay, Alnur Ali, and Stephen Boyd. “Minimum-distortion embedding.” arXiv preprint arXiv:2103.02559 (2021).


>>> adata = anndata.read_h5ad(path_to_anndata)
>>> scvi.model.SCVI.setup_anndata(adata, batch_key="batch")
>>> vae = scvi.model.SCVI(adata)
>>> vae.train()
>>> adata.obsm["X_scVI"] = vae.get_latent_representation()
>>> adata.obsm["X_mde"] = scvi.model.utils.mde(adata.obsm["X_scVI"])