Cuando la expresión génica adquiere coordenadas, las preguntas a formular cambian
En S35 examinamos la estructura de los datos de transcriptómica espacial. Ahora debemos plantear preguntas con significado espacial sobre estos datos. Mientras que en scRNA-seq la pregunta central era "¿se expresa este gen en niveles altos en este clúster?", con los datos espaciales se añaden las siguientes preguntas:
- ¿Qué tipos celulares aparecen con frecuencia junto a qué otros tipos celulares? (Análisis de concentración vecinal)
- ¿La expresión de este gen está agrupada espacialmente o dispersa al azar? (Autocorrelación espacial)
- ¿Las células que expresan un ligando y las que expresan su receptor están realmente cerca entre sí? (Prueba de coexistencia espacial L-R)
En esta sección presentamos los métodos estadísticos para responder a estas tres preguntas y ejecutamos el análisis directamente con Squidpy.
Construcción del grafo espacial: definir los vecinos
El primer paso en todo análisis espacial es definir la relación de vecindad. Dado que las células (o los puntos de muestreo) tienen coordenadas 2D, es necesario convertirlas en un grafo. Los métodos principales son tres:
Grafo kNN: define como vecinos a los k células más cercanas de cada célula. La lógica es la misma que la utilizada para crear el kNN en el espacio génico en scRNA-seq (S29), pero aquí se utilizan las coordenadas físicas XY.
Triangulación de Delaunay: divide un conjunto de puntos en triángulos, asegurando que no haya otros puntos dentro del circuncírculo de ningún triángulo. Los pares de células conectados por los lados de los triángulos resultantes se consideran vecinos. Esto genera relaciones de vecindad naturales incluso en tejidos con densidad no uniforme.
Radio fijo: define como vecinos a todas las células situadas dentro de un radio r μm desde la célula de referencia. Es intuitivo porque permite establecer directamente una "distancia de contacto" biológicamente relevante, pero el número de vecinos puede dispararse en áreas densas.
import squidpy as sq
# Carga de datos Visiumadata = sq.datasets.visium_hne_adata()sc.pp.normalize_total(adata)sc.pp.log1p(adata)
# Construcción del grafo de vecinos espaciales (Delaunay)sq.gr.spatial_neighbors(adata, coord_type="generic", delaunay=True)Análisis de co-ocurrencia vecinal: ¿quién está junto a quién?
Si el tipo celular B aparece con mayor frecuencia de lo esperado junto al tipo celular A, se dice que estos dos tipos están espacialmente asociados. nhood_enrichment de Squidpy verifica esto mediante una prueba de permutación.
- Se calcula la frecuencia de cada tipo celular entre los vecinos de cada célula.
- Se aleatorizan (permutan) las etiquetas de los tipos celulares para generar la distribución nula.
- Si la frecuencia observada es significativamente alta (co-ocurrencia) o baja (evitación) en comparación con la distribución nula, se informa mediante el puntaje z.
# Análisis de enriquecimiento vecinalsq.gr.nhood_enrichment(adata, cluster_key="cluster")sq.pl.nhood_enrichment(adata, cluster_key="cluster")En el mapa de calor de resultados, los valores z positivos (rojo) indican agrupación espacial (dos tipos de células próximos entre sí), mientras que los valores z negativos (azul) indican segregación (separados entre sí). En el tejido cerebral, es típico que los oligodendrocitos se agrupen en las regiones de la sustancia blanca y se encuentren espacialmente separados de las neuronas.
Autocorrelación espacial: índice de Moran
El índice de Moran es la prueba clásica para responder a la pregunta: "¿La expresión de este gen presenta agrupación espacial?". Se aplica directamente a la transcriptómica espacial, utilizando el mismo enfoque que se emplea en la estadística espacial para datos geográficos.
La fórmula es la siguiente:
donde es el peso espacial entre las células y (1 si son vecinas, 0 en caso contrario), y es el valor de expresión génica.
- : Fuerte autocorrelación positiva — las células con alta expresión se agrupan entre sí, al igual que las de baja expresión.
- : No hay patrón espacial — distribución aleatoria.
- : Autocorrelación negativa — las células de alta y baja expresión se intercalan como un tablero de ajedrez.
# Cálculo de Moran's I para todos los genessq.gr.spatial_autocorr(adata, mode="moran")
# Verificación de genes con mayor variación espacialmoran_df = adata.uns["moranI"].sort_values("I", ascending=False)print(moran_df.head(10))
# Visualización de los genes superioressc.pl.spatial(adata, color=moran_df.index[:4].tolist(), spot_size=1.5)Los genes con un índice de Moran alto son los genes espacialmente variables (SVGs). Si los HVG (S28) de scRNA-seq seleccionan genes basándose en la variación entre células, los SVGs se seleccionan basándose en la variación espacial. Ambas listas solo se superponen parcialmente, ya que existen genes con una baja varianza intercelular, pero que son espacialmente interesantes (por ejemplo, marcadores específicos de capas).
Prueba de coexistencia espacial L-R: ¿es físicamente posible la señal?
En S34, inferimos la comunicación ligando-receptor con CellChat/CellPhoneDB; sin embargo, sin información espacial, no podíamos confirmar si "estas dos células están realmente cerca". Squidpy ligrec responde a esta pregunta.
# Prueba de interacción L-R basada en el espaciosq.gr.ligrec( adata, n_perms=1000, cluster_key="cluster", copy=False,)sq.pl.ligrec(adata, cluster_key="cluster", source_groups="Astrocyte", target_groups=["Neuron", "Oligodendrocyte"])Esto es similar a la prueba de permutación de CellPhoneDB, pero se realiza en el grafo de vecindad espacial. Dado que solo se registran como candidatos de interacción las parejas de células que expresan el ligando y el receptor cuando son espacialmente vecinas, se reduce la tasa de falsos positivos en comparación con los análisis basados en scRNA-seq.
Giotto: una alternativa en el ecosistema R
Si Squidpy se utiliza en el ecosistema Python/Scanpy, Giotto proporciona el mismo tipo de análisis en el ecosistema R. En particular, Giotto cuenta con funcionalidades únicas en la detección de dominios espaciales, el análisis de redes espaciales y la integración multimodal.
library(Giotto)
# Creación del objeto Giotto
g <- createGiottoObject(
expression = expr_matrix,
spatial_locs = spatial_coords
)
# red de espacial + Delaunay
g <- createSpatialNetwork(g, method = "Delaunay")
# genes de variación espacial (binSpect)
g <- binSpect(g, bin_method = "kmeans")
spatialDE_results <- g@spatial_enrichment$binSpectGiotto binSpect detecta genes con variación espacial utilizando la segmentación binaria basada en k-means, además de Moran's I, y es más rápido que Moran's I en conjuntos de datos grandes.
Correspondencias conceptuales
- Cuadrícula hash espacial: El índice espacial que acelera la búsqueda de vecinos se basa en el mismo principio que la cuadrícula hash espacial en los motores de juegos. Los árboles R y los árboles k-d entran en la misma categoría.
- Moran's I / Autocorrelación espacial: Es una extensión de la autocorrelación de series temporales (ACF) a un espacio 2D. También es una estadística fundamental en los sistemas de información geográfica (SIG).
- Triangulación de Delaunay: Un algoritmo fundamental en geometría computacional, directamente relacionado con los algoritmos geométricos en DryBench. Es el dual del diagrama de Voronoi.
Errores comunes
- Los resultados varían según la definición de vecino: La elección entre kNN, Delaunay o radio fijo afecta la agregación de vecinos y los valores de Moran's I. Es necesario realizar un análisis de sensibilidad (repitiendo con varios métodos).
- Aplicar la interpretación de una sola célula a datos basados en puntos: El valor de Moran's I en los puntos de Visium refleja el patrón espacial de las mezclas multicelulares, no el de las células individuales.
- Falta de corrección para pruebas múltiples: Calcular el valor de Moran's I para 20.000 genes dará como resultado cientos de resultados significativos por casualidad. La corrección de FDR (valor q) es esencial.
- Efectos de borde del tejido: Los puntos/células en los bordes del tejido tienen vecinos solo en un lado, lo que distorsiona las estadísticas. Es recomendable excluir o corregir los puntos de borde.
Para una exploración más profunda
El texto anterior es una narración reconstruida por BPD. Para un estudio más profundo, consulte los siguientes recursos autorizados.
- Documentación y tutoriales oficiales de Squidpy: Palla et al. (2022), Squidpy: a scalable framework for spatial omics analysis, Nature Methods 19:171. Un marco integrado para gráficos espaciales, análisis de vecinos y análisis de imágenes.
- Documentación oficial de Giotto: Dries et al. (2021), Giotto provides a toolbox for integrative analysis and visualization of spatial expression data, Genome Biology 22:78.
- SpatialDE (pionero en la detección de genes con variación espacial): Svensson et al. (2018), SpatialDE: identification of spatially variable genes, Nature Methods 15:343. Utiliza un enfoque basado en procesos gaussianos.
- Referencia: libro web gratuito: Single-cell best practices (sc-best-practices.org) — Capítulo sobre análisis espacial.
Ahora que hemos analizado las relaciones de vecindad y los patrones espaciales, queda un problema fundamental: ¿cómo resolver la mezcla de múltiples células en cada punto de Visium? En el siguiente artículo, S37, explicaremos cómo deconvolucionar los puntos para obtener una resolución a nivel de célula individual utilizando Tangram y cell2location.