LIANA+: Framework for Cell-Cell Communication

repository·main·Indexed 43 days ago

https://github.com/saezlab/liana-py

A scalable framework for studying cell-cell communication (CCC) across single-cell, spatially-resolved, and multi-modal omics data. LIANA+ integrates multiple scoring methods—including CellPhoneDB, CellChat, Connectome, NATMI, SingleCellSignalR, and scSeqComm—into a unified ecosystem using AnnData and MuData objects. It provides tools for interaction scoring, spatial co-occurrence, and linking receptors to intracellular signaling via find_causalnet.

Tokens
23.5K
Snippets
70
Records
97
Agent score
56%

What's inside LIANA+

  1. Overview of LIANA+

    main

    LIANA+ is an all-in-one framework designed for cell-cell communication analysis. It adapts and extends existing methods and prior knowledge to work with single-cell, spatially-resolved, and multi-modal data.

    LIANA+ operates on standard single-cell data structures, specifically anndata.AnnData and mudata.MuData objects, and is a member of the scverse ecosystem.

  2. Overview of LIANA+ (liana) submodules and usage

    main

    LIANA+ is a cell-cell communication (CCC) inference framework. You can access its functionality via the liana package, typically imported as import liana as li.

    Core Submodules:

    • li.mt: Contains the core CCC methods (e.g., rank_aggregate, CellPhoneDB, inflow).
    • li.pp: Preprocessing tools, including spatial graph generation and transforms.
    • li.rs: Prior knowledge and ligand-receptor (LR) resources.
    • li.pl: Plotting functions (returns plotnine objects).
    • li.ms: Helpers for multi-sample analysis.
    • li.ds: Dataset loaders.

    All methods accept either an AnnData or a MuData object.

    import liana as li
  3. Handle spatial single-cell ligand-receptor inference

    main

    If your dataset contains spatial coordinates, you can constrain LR scores by cell-type proximity. This is supported by the standard scoring methods (e.g., li.mt.cellphonedb, li.mt.rank_aggregate) using the spatial_key and spatial_kwargs arguments.

    • spatial_key: The name of the coordinate key in adata (e.g., "spatial").
    • spatial_kwargs: A dictionary containing "bandwidth". The bandwidth is in coordinate units (e.g., µm).

    Scores are multiplied by the pair's proximity calculated via li.pp.spatial_pair_proximity. Pairs with fewer than min_cells_in_proximity=10 close cell pairs are set to 0.

    li.mt.rank_aggregate(
        adata, 
        groupby="cell_type", 
        spatial_key="spatial", 
        spatial_kwargs={"bandwidth": 100}
    )
  4. Analyze spatial and multi-modal data with LIANA+

    main

    LIANA+ extends beyond dissociated single-cell data to support:

    Spatially-resolved data

    Interactions can be restricted to spatial neighborhoods, scored per spot/cell using bivariate metrics, or modeled as spatial relationships using:

    • li.mt.MistyData
    • li.mt.lric

    Multi-modal data

    LIANA+ supports cases where ligands and receptors originate from different modalities (e.g., transcriptome and surface protein, or transcriptome and MALDI-MSI metabolites).

    Multi-sample/Condition analysis

    Interaction scores across samples can be reshaped into views and factorized using tools like MOFA or tensor-cell2cell to identify communication programs.

  5. How LIANA+ unifies cell-cell communication methods

    main

    LIANA+ provides a single interface to run multiple cell-cell communication scoring methods. It reimplements several tools—including CellPhoneDB, CellChat, Connectome, NATMI, SingleCellSignalR, and scSeqComm—to ensure they all accept the same input formats, use a consistent permutation scheme, and return standardized tables. This standardization allows for direct comparison between methods. To combine these different scores into a single consensus, you can use li.mt.rank_aggregate.

    # Example of combining scores into a rank consensus
    # (Note: actual usage depends on the input data object)
    consensus_scores = li.mt.rank_aggregate(data)
  6. Understand LIANA+ thresholds and output locations

    main

    LIANA+ uses specific thresholds and storage conventions that vary by method:

    Thresholds:

    • expr_prop: (Single-cell and lric cell-type mode) The fraction of cells within a cell-type group expressing a gene. Default is 0.05.
    • nz_prop: (Spatial methods only) The fraction of all cells or spots with a non-zero value. Default is 0.05.

    Output Locations:

    • Single-cell methods: Results are written to adata.uns["liana_res"] in place.
    • bivariate and inflow: These return a new AnnData object.
    • lric, cross_pcf, and MISTy: Results are written to .uns keys.
  7. Analyze spatial relationships with `MistyData`

    main

    For learning spatial relationships, LIANA+ uses MistyData objects (and genericMistyData or lrMistyData). These objects are used to model spatial interactions. When calling a MistyData object, you can specify a single-view model using the model= parameter.

    Supported single-view models include:

    • LinearModel
    • RandomForestModel
    • RobustLinearModel
  8. Understand the LIANA+ API namespaces

    main

    The LIANA+ public API is organized into six functional namespaces to help you navigate the framework's capabilities:

    • li.mt: Methods. Contains ligand-receptor method instances, spatial metrics, and intracellular helpers.
    • li.pp: Preprocessing. Tools for preparing data, such as coordinate expansion or spatial neighbor calculation.
    • li.ms: Multi-Sample. Functions for handling multi-sample data, tensor conversions, and NMF-based analysis.
    • li.rs: Resources / Prior Knowledge. Tools for managing ligand-receptor databases, translating resources, and building prior networks.
    • li.ds: Datasets. Built-in datasets and toy data generators for testing and benchmarking.
    • li.pl: Plotting. Visualization functions for dotplots, tileplots, connectivity, and spatial relationships.
  9. Understand the structure of the `liana_res` result table

    main

    The LIANA results are stored in adata.uns['liana_res'] or returned as a DataFrame. Each row represents a unique combination of a source cell type, target cell type, and Ligand-Receptor (LR) pair.

    Single Method Results

    When running a single method (e.g., li.mt.cellphonedb, natmi), the table includes:

    • source, target
    • ligand_complex, receptor_complex
    • ligand, receptor (the least-expressed subunit)
    • ligand_means, ligand_props, receptor_means, receptor_props
    • Method-specific score columns.

    rank_aggregate Results

    rank_aggregate provides the same columns as single methods but adds:

    • Aggregated score columns for each method used.
    • magnitude_rank
    • specificity_rank

    Note: rank_aggregate does not include per-entity intermediate columns (like ligand_zscores or ligand_logfc) unless you explicitly request them using the supp_columns= parameter.

  10. Manage ligand-receptor resources with LIANA+

    main

    In LIANA+, scoring methods and ligand-receptor resources (databases) are decoupled. This means any method can be used with any resource. You can manipulate these resources using the following functions:

    • li.rs.select_resource: Returns a curated consensus resource or specific ligand-receptor databases.
    • li.rs.translate_resource: Translates a resource from one organism to another.
    • li.rs.get_metalinks: Replaces ligands with metabolites in a resource.
  11. Inspect and prepare AnnData/MuData for LIANA+

    main

    Before running LIANA+ methods, ensure your data is in the correct format. LIANA+ typically expects non-negative, library-size normalised, log1p expression in .X or a specified layer.

    Important Data Checks:

    • Negative Values: Single-cell methods will raise a ValueError if the input matrix contains negative values (e.g., scaled or z-scored data). Use raw or log-normalised counts instead.
    • Log-transformation: If values are too large (max > ~709), it may indicate the data was not log-transformed correctly, which can cause overflows during log-fold-change calculations.
    • Spatial Data: If using spatial methods, ensure coordinate information is present in obsm['spatial'].

    Use the following snippet to inspect your object's structure, modalities, and expression ranges:

    import anndata as ad, mudata as mu, numpy as np
    
    a = mu.read(path) if path.endswith(".h5mu") else ad.read_h5ad(path)
    print(type(a).__name__, a.shape, "mods:", list(getattr(a, "mod", {})))
    for c in a.obs.columns:
        if a.obs[c].dtype.kind not in "biuf":
            u = a.obs[c].unique()
            print(c, len(u), list(u[:6]))
    print("obsm:", list(a.obsm), "obsp:", list(a.obsp), "uns:", list(a.uns))
    d = lambda M: M.toarray() if hasattr(M, "toarray") else np.asarray(M)
    for name, m in (a.mod.items() if hasattr(a, "mod") else [("", a)]):
        X = d(m.X[:200])
        print(name, "layers:", list(m.layers), "X min/max:", X.min(), X.max(),
              "integer-like:", np.allclose(X, X.round()), "var sample:", list(m.var_names[:5]))
        if m.raw is not None:
            R = d(m.raw.X[:200])
            print(name, "raw min/max:", R.min(), R.max(), "(negative = scaled, do not use)")
    if "spatial" in a.obsm:
        print(
            "coords min/max:",
            a.obsm["spatial"].min(0),
            a.obsm["spatial"].max(0),
            "uns spatial:",
            list(a.uns.get("spatial", {})),
        )