cellxgene-census

Par mkurman · zorai

Interrogez le CELLxGENE Census (plus de 61 millions de cellules) par programmation. À utiliser lorsque vous avez besoin de données d'expression à travers des tissus, maladies ou types cellulaires issus du plus grand atlas unicellulaire curé. Idéal pour les requêtes à l'échelle populationnelle et les comparaisons avec des atlas de référence. Pour analyser vos propres données, utilisez scanpy ou scvi-tools.

npx skills add https://github.com/mkurman/zorai --skill cellxgene-census

CZ CELLxGENE Census

Aperçu

Le CZ CELLxGENE Census fournit un accès programmatique à une collection complète et versionnée de données de génomique de cellules uniques standardisées provenant de CZ CELLxGENE Discover. Cette skill permet une interrogation et une analyse efficaces de millions de cellules sur des milliers de datasets.

Le Census inclut :

  • Plus de 61 millions de cellules provenant d'humains et de souris
  • Métadonnées standardisées (types de cellules, tissus, maladies, donneurs)
  • Matrices d'expression génique brutes
  • Embeddings pré-calculés et statistiques
  • Intégration avec PyTorch, scanpy et autres outils d'analyse

Quand utiliser cette skill

Cette skill doit être utilisée quand :

  • Interroger des données d'expression de cellules uniques par type de cellule, tissu ou maladie
  • Explorer les datasets de cellules uniques et les métadonnées disponibles
  • Former des modèles d'apprentissage automatique sur des données de cellules uniques
  • Effectuer des analyses à grande échelle entre datasets
  • Intégrer les données du Census avec scanpy ou d'autres frameworks d'analyse
  • Calculer des statistiques sur des millions de cellules
  • Accéder aux embeddings pré-calculés ou aux prédictions de modèles

Installation et configuration

Installez l'API Census :

uv pip install cellxgene-census

Pour les workflows d'apprentissage automatique, installez des dépendances supplémentaires :

uv pip install cellxgene-census[experimental]

Modèles de flux de travail fondamentaux

1. Ouverture du Census

Utilisez toujours le gestionnaire de contexte pour assurer un nettoyage correct des ressources :

import cellxgene_census

# Ouvrir la dernière version stable
with cellxgene_census.open_soma() as census:
    # Travailler avec les données du census

# Ouvrir une version spécifique pour la reproductibilité
with cellxgene_census.open_soma(census_version="2023-07-25") as census:
    # Travailler avec les données du census

Points clés :

  • Utilisez le gestionnaire de contexte (instruction with) pour le nettoyage automatique
  • Spécifiez census_version pour des analyses reproductibles
  • Par défaut, ouvre la dernière version « stable »

2. Exploration des informations du Census

Avant d'interroger les données d'expression, explorez les datasets et métadonnées disponibles.

Accédez aux informations de synthèse :

# Obtenir des statistiques de synthèse
summary = census["census_info"]["summary"].read().concat().to_pandas()
print(f"Total cells: {summary['total_cell_count'][0]}")

# Obtenir tous les datasets
datasets = census["census_info"]["datasets"].read().concat().to_pandas()

# Filtrer les datasets par critères
covid_datasets = datasets[datasets["disease"].str.contains("COVID", na=False)]

Interrogez les métadonnées des cellules pour comprendre les données disponibles :

# Obtenir les types de cellules uniques dans un tissu
cell_metadata = cellxgene_census.get_obs(
    census,
    "homo_sapiens",
    value_filter="tissue_general == 'brain' and is_primary_data == True",
    column_names=["cell_type"]
)
unique_cell_types = cell_metadata["cell_type"].unique()
print(f"Found {len(unique_cell_types)} cell types in brain")

# Compter les cellules par tissu
tissue_counts = cell_metadata.groupby("tissue_general").size()

Important : Filtrez toujours pour is_primary_data == True pour éviter de compter les cellules dupliquées sauf si vous analysez spécifiquement les doublons.

3. Interrogation des données d'expression (petite à moyenne échelle)

Pour les requêtes retournant < 100 000 cellules qui tiennent en mémoire, utilisez get_anndata() :

# Requête basique avec filtres de type de cellule et de tissu
adata = cellxgene_census.get_anndata(
    census=census,
    organism="Homo sapiens",  # ou "Mus musculus"
    obs_value_filter="cell_type == 'B cell' and tissue_general == 'lung' and is_primary_data == True",
    obs_column_names=["assay", "disease", "sex", "donor_id"],
)

# Interroger des gènes spécifiques avec plusieurs filtres
adata = cellxgene_census.get_anndata(
    census=census,
    organism="Homo sapiens",
    var_value_filter="feature_name in ['CD4', 'CD8A', 'CD19', 'FOXP3']",
    obs_value_filter="cell_type == 'T cell' and disease == 'COVID-19' and is_primary_data == True",
    obs_column_names=["cell_type", "tissue_general", "donor_id"],
)

Syntaxe des filtres :

  • Utilisez obs_value_filter pour filtrer les cellules
  • Utilisez var_value_filter pour filtrer les gènes
  • Combinez les conditions avec and, or
  • Utilisez in pour plusieurs valeurs : tissue in ['lung', 'liver']
  • Sélectionnez uniquement les colonnes nécessaires avec obs_column_names

Obtenir les métadonnées séparément :

# Interroger les métadonnées des cellules
cell_metadata = cellxgene_census.get_obs(
    census, "homo_sapiens",
    value_filter="disease == 'COVID-19' and is_primary_data == True",
    column_names=["cell_type", "tissue_general", "donor_id"]
)

# Interroger les métadonnées des gènes
gene_metadata = cellxgene_census.get_var(
    census, "homo_sapiens",
    value_filter="feature_name in ['CD4', 'CD8A']",
    column_names=["feature_id", "feature_name", "feature_length"]
)

4. Requêtes à grande échelle (traitement hors mémoire)

Pour les requêtes dépassant la RAM disponible, utilisez axis_query() avec traitement itératif :

import tiledbsoma as soma

# Créer une requête axis
query = census["census_data"]["homo_sapiens"].axis_query(
    measurement_name="RNA",
    obs_query=soma.AxisQuery(
        value_filter="tissue_general == 'brain' and is_primary_data == True"
    ),
    var_query=soma.AxisQuery(
        value_filter="feature_name in ['FOXP2', 'TBR1', 'SATB2']"
    )
)

# Itérer sur la matrice d'expression par chunks
iterator = query.X("raw").tables()
for batch in iterator:
    # batch est une pyarrow.Table avec les colonnes :
    # - soma_data: valeur d'expression
    # - soma_dim_0: coordonnée de cellule (obs)
    # - soma_dim_1: coordonnée de gène (var)
    process_batch(batch)

Calcul de statistiques incrémentales :

# Exemple : Calculer l'expression moyenne
n_observations = 0
sum_values = 0.0

iterator = query.X("raw").tables()
for batch in iterator:
    values = batch["soma_data"].to_numpy()
    n_observations += len(values)
    sum_values += values.sum()

mean_expression = sum_values / n_observations

5. Apprentissage automatique avec PyTorch

Pour former des modèles, utilisez l'intégration PyTorch expérimentale :

from cellxgene_census.experimental.ml import experiment_dataloader

with cellxgene_census.open_soma() as census:
    # Créer un dataloader
    dataloader = experiment_dataloader(
        census["census_data"]["homo_sapiens"],
        measurement_name="RNA",
        X_name="raw",
        obs_value_filter="tissue_general == 'liver' and is_primary_data == True",
        obs_column_names=["cell_type"],
        batch_size=128,
        shuffle=True,
    )

    # Boucle d'entraînement
    for epoch in range(num_epochs):
        for batch in dataloader:
            X = batch["X"]  # Tenseur d'expression génique
            labels = batch["obs"]["cell_type"]  # Étiquettes de type de cellule

            # Passage avant
            outputs = model(X)
            loss = criterion(outputs, labels)

            # Passage arrière
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

Division train/test :

from cellxgene_census.experimental.ml import ExperimentDataset

# Créer un dataset à partir de l'expérience
dataset = ExperimentDataset(
    experiment_axis_query,
    layer_name="raw",
    obs_column_names=["cell_type"],
    batch_size=128,
)

# Diviser en entraînement et test
train_dataset, test_dataset = dataset.random_split(
    split=[0.8, 0.2],
    seed=42
)

6. Intégration avec Scanpy

Intégrez sans problème les données du Census aux flux de travail scanpy :

import scanpy as sc

# Charger les données du Census
adata = cellxgene_census.get_anndata(
    census=census,
    organism="Homo sapiens",
    obs_value_filter="cell_type == 'neuron' and tissue_general == 'cortex' and is_primary_data == True",
)

# Flux de travail scanpy standard
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata, n_top_genes=2000)

# Réduction de dimensionnalité
sc.pp.pca(adata, n_comps=50)
sc.pp.neighbors(adata)
sc.tl.umap(adata)

# Visualisation
sc.pl.umap(adata, color=["cell_type", "tissue", "disease"])

7. Intégration multi-datasets

Interrogez et intégrez plusieurs datasets :

# Stratégie 1 : Interroger plusieurs tissus séparément
tissues = ["lung", "liver", "kidney"]
adatas = []

for tissue in tissues:
    adata = cellxgene_census.get_anndata(
        census=census,
        organism="Homo sapiens",
        obs_value_filter=f"tissue_general == '{tissue}' and is_primary_data == True",
    )
    adata.obs["tissue"] = tissue
    adatas.append(adata)

# Concaténer
combined = adatas[0].concatenate(adatas[1:])

# Stratégie 2 : Interroger plusieurs datasets directement
adata = cellxgene_census.get_anndata(
    census=census,
    organism="Homo sapiens",
    obs_value_filter="tissue_general in ['lung', 'liver', 'kidney'] and is_primary_data == True",
)

Concepts clés et bonnes pratiques

Toujours filtrer pour les données primaires

Sauf lors de l'analyse de doublons, incluez toujours is_primary_data == True dans les requêtes pour éviter de compter les cellules plusieurs fois :

obs_value_filter="cell_type == 'B cell' and is_primary_data == True"

Spécifier la version du Census pour la reproductibilité

Spécifiez toujours la version du Census dans les analyses en production :

census = cellxgene_census.open_soma(census_version="2023-07-25")

Estimer la taille de la requête avant le chargement

Pour les grandes requêtes, vérifiez d'abord le nombre de cellules pour éviter les problèmes de mémoire :

# Obtenir le nombre de cellules
metadata = cellxgene_census.get_obs(
    census, "homo_sapiens",
    value_filter="tissue_general == 'brain' and is_primary_data == True",
    column_names=["soma_joinid"]
)
n_cells = len(metadata)
print(f"Query will return {n_cells:,} cells")

# Si trop grand (>100 000), utilisez le traitement hors mémoire

Utiliser tissue_general pour les groupements plus larges

Le champ tissue_general fournit des catégories plus coarses que tissue, utiles pour les analyses entre tissus :

# Groupement plus large
obs_value_filter="tissue_general == 'immune system'"

# Tissu spécifique
obs_value_filter="tissue == 'peripheral blood mononuclear cell'"

Sélectionner uniquement les colonnes nécessaires

Minimisez le transfert de données en spécifiant uniquement les colonnes de métadonnées requises :

obs_column_names=["cell_type", "tissue_general", "disease"]  # Pas toutes les colonnes

Vérifier la présence du dataset pour les requêtes spécifiques de gènes

Lors de l'analyse de gènes spécifiques, vérifiez quels datasets les ont mesurés :

presence = cellxgene_census.get_presence_matrix(
    census,
    "homo_sapiens",
    var_value_filter="feature_name in ['CD4', 'CD8A']"
)

Flux de travail en deux étapes : explorer puis interroger

Explorez d'abord les métadonnées pour comprendre les données disponibles, puis interrogez l'expression :

# Étape 1 : Explorer ce qui est disponible
metadata = cellxgene_census.get_obs(
    census, "homo_sapiens",
    value_filter="disease == 'COVID-19' and is_primary_data == True",
    column_names=["cell_type", "tissue_general"]
)
print(metadata.value_counts())

# Étape 2 : Interroger en fonction des résultats
adata = cellxgene_census.get_anndata(
    census=census,
    organism="Homo sapiens",
    obs_value_filter="disease == 'COVID-19' and cell_type == 'T cell' and is_primary_data == True",
)

Champs de métadonnées disponibles

Métadonnées des cellules (obs)

Champs clés pour le filtrage :

  • cell_type, cell_type_ontology_term_id
  • tissue, tissue_general, tissue_ontology_term_id
  • disease, disease_ontology_term_id
  • assay, assay_ontology_term_id
  • donor_id, sex, self_reported_ethnicity
  • development_stage, development_stage_ontology_term_id
  • dataset_id
  • is_primary_data (Booléen : True = cellule unique)

Métadonnées des gènes (var)

  • feature_id (ID de gène Ensembl, par ex. « ENSG00000161798 »)
  • feature_name (Symbole de gène, par ex. « FOXP2 »)
  • feature_length (Longueur du gène en paires de bases)

Documentation de référence

Cette skill inclut une documentation de référence détaillée :

references/census_schema.md

Documentation complète de :

  • Structure et organisation des données du Census
  • Tous les champs de métadonnées disponibles
  • Syntaxe des filtres de valeur et opérateurs
  • Types d'objets SOMA
  • Critères d'inclusion des données

Quand lire : Quand vous avez besoin d'informations détaillées sur le schéma, de la liste complète des champs de métadonnées ou de la syntaxe des filtres complexes.

references/common_patterns.md

Exemples et modèles pour :

  • Requêtes exploratoires (métadonnées uniquement)
  • Requêtes petites à moyennes (AnnData)
  • Grandes requêtes (traitement hors mémoire)
  • Intégration PyTorch
  • Workflows d'intégration Scanpy
  • Intégration multi-datasets
  • Bonnes pratiques et pièges courants

Quand lire : Lors de l'implémentation de modèles de requête spécifiques, de la recherche d'exemples de code ou du dépannage de problèmes courants.

Cas d'utilisation courants

Cas d'utilisation 1 : Explorer les types de cellules dans un tissu

with cellxgene_census.open_soma() as census:
    cells = cellxgene_census.get_obs(
        census, "homo_sapiens",
        value_filter="tissue_general == 'lung' and is_primary_data == True",
        column_names=["cell_type"]
    )
    print(cells["cell_type"].value_counts())

Cas d'utilisation 2 : Interroger l'expression de gènes marqueurs

with cellxgene_census.open_soma() as census:
    adata = cellxgene_census.get_anndata(
        census=census,
        organism="Homo sapiens",
        var_value_filter="feature_name in ['CD4', 'CD8A', 'CD19']",
        obs_value_filter="cell_type in ['T cell', 'B cell'] and is_primary_data == True",
    )

Cas d'utilisation 3 : Former un classifieur de types de cellules

from cellxgene_census.experimental.ml import experiment_dataloader

with cellxgene_census.open_soma() as census:
    dataloader = experiment_dataloader(
        census["census_data"]["homo_sapiens"],
        measurement_name="RNA",
        X_name="raw",
        obs_value_filter="is_primary_data == True",
        obs_column_names=["cell_type"],
        batch_size=128,
        shuffle=True,
    )

    # Former le modèle
    for epoch in range(epochs):
        for batch in dataloader:
            # Logique d'entraînement
            pass

Cas d'utilisation 4 : Analyse entre tissus

with cellxgene_census.open_soma() as census:
    adata = cellxgene_census.get_anndata(
        census=census,
        organism="Homo sapiens",
        obs_value_filter="cell_type == 'macrophage' and tissue_general in ['lung', 'liver', 'brain'] and is_primary_data == True",
    )

    # Analyser les différences de macrophages entre tissus
    sc.tl.rank_genes_groups(adata, groupby="tissue_general")

Dépannage

La requête retourne trop de cellules

  • Ajouter des filtres plus spécifiques pour réduire la portée
  • Utiliser tissue au lieu de tissue_general pour une granularité plus fine
  • Filtrer par dataset_id spécifique si connu
  • Passer au traitement hors mémoire pour les grandes requêtes

Erreurs de mémoire

  • Réduire la portée des requêtes avec des filtres plus restrictifs
  • Sélectionner moins de gènes avec var_value_filter
  • Utiliser le traitement hors mémoire avec axis_query()
  • Traiter les données par lots

Cellules dupliquées dans les résultats

  • Toujours inclure is_primary_data == True dans les filtres
  • Vérifier si l'on interroge intentionnellement plusieurs datasets

Gène non trouvé

  • Vérifier l'orthographe du nom de gène (sensible à la casse)
  • Essayer l'ID Ensembl avec feature_id au lieu de feature_name
  • Vérifier la matrice de présence du dataset pour voir si le gène a été mesuré
  • Certains gènes peuvent avoir été filtrés lors de la construction du Census

Incohérences de version

  • Toujours spécifier census_version explicitement
  • Utiliser la même version dans toutes les analyses
  • Vérifier les notes de version pour les modifications spécifiques à la version

Skills similaires