v1.11 — Édition 2026. Un guide complet sur l'analyse single-cell à l'aide de Scanpy (v1.11 - 2026). Apprenez à prétraiter, visualiser, regrouper et déduire des trajectoires pour des données d'expression génique single-cell à grande échelle.
Découvrez les concepts fondateurs de Scanpy et pourquoi il a été conçu pour l'analyse single-cell à grande échelle. Nous explorons l'objet AnnData, la structure de données centrale qui maintient les matrices, les annotations et les embeddings parfaitement alignés. Vous apprendrez le modèle mental nécessaire pour naviguer dans l'écosystème de Scanpy.
3m 54s
2
Métriques de contrôle qualité
Nous explorons comment effectuer un contrôle qualité initial sur des données single-cell à l'aide de Scanpy. En isolant des populations de gènes spécifiques comme l'ARN mitochondrial, nous pouvons identifier les cellules stressées ou mourantes. Vous apprendrez à calculer et interpréter ces métriques de contrôle qualité cruciales.
3m 08s
3
Filtrage et normalisation
Cet épisode couvre les étapes critiques du filtrage et de la normalisation des matrices d'expression single-cell. Nous expliquons comment écarter les données de mauvaise qualité et appliquer une mise à l'échelle de la profondeur de comptage avec une transformation log1p. Vous apprendrez comment rendre directement comparables des cellules ayant des profondeurs de séquençage différentes.
3m 31s
4
Détection de doublets avec Scrublet
Nous nous plongeons dans la détection de doublets, une étape cruciale pour repérer les artefacts techniques dans le séquençage single-cell microfluidique. Nous détaillons comment Scrublet simule des doublets artificiels pour signaler les cellules suspectes. Vous apprendrez à identifier et supprimer ces combinaisons artificielles de votre jeu de données.
3m 33s
5
Sélection de caractéristiques et gènes hautement variables
Nous examinons le concept de sélection de caractéristiques et pourquoi il est nécessaire d'identifier les gènes hautement variables. En écartant le bruit de fond, nous concentrons l'analyse sur les moteurs biologiques. Vous apprendrez à utiliser Scanpy pour isoler les gènes les plus informatifs pour les étapes ultérieures.
3m 34s
6
Scoring du cycle cellulaire et régression
Nous explorons comment gérer les facteurs de confusion en évaluant et en régressant les phases du cycle cellulaire. Nous discutons de la façon de calculer les scores S et G2M et d'utiliser la régression pour supprimer leur influence. Vous apprendrez comment empêcher la division cellulaire active de ruiner la topologie de votre clustering.
3m 27s
7
Réduction de dimensionnalité avec PCA
Cet épisode explique l'Analyse en Composantes Principales (PCA) dans le contexte des données single-cell. Nous discutons de la façon dont la PCA débruite le jeu de données et pourquoi le choix du bon nombre de composantes est important. Vous apprendrez à réduire des milliers de gènes en une base gérable pour les algorithmes avancés.
3m 24s
8
Le graphe des plus proches voisins et UMAP
Nous décortiquons le cœur absolu de la topologie single-cell moderne : le graphe des plus proches voisins. Nous expliquons ensuite comment UMAP traduit ce réseau complexe en un graphique 2D lisible. Vous apprendrez pourquoi le graphe des voisins est le prérequis pour presque tous les outils avancés de Scanpy.
3m 22s
9
Clustering avec Leiden
Nous explorons comment trouver des populations discrètes de cellules à l'aide de l'algorithme de clustering Leiden. En optimisant la modularité sur le graphe de voisinage, Leiden isole des communautés hautement connectées. Vous apprendrez à ajuster le paramètre de résolution pour trouver des groupes stables et biologiquement pertinents.
3m 38s
10
Découverte de gènes marqueurs
Nous nous plongeons dans la découverte de gènes marqueurs et les tests d'expression différentielle. Nous expliquons comment les tests statistiques identifient les signatures transcriptomiques uniques de vos clusters. Vous apprendrez à passer de clusters numérotés anonymes à des types cellulaires biologiques étiquetés avec certitude.
3m 45s
11
Intégration de données avec Ingest
Cet épisode couvre l'intégration de données à l'aide de l'outil Ingest. Nous expliquons comment projeter de nouveaux jeux de données sur l'espace PCA et UMAP d'un atlas de référence pré-annoté. Vous apprendrez une méthode rapide et invariante pour cartographier les étiquettes à travers différentes expériences.
3m 16s
12
Visualisation des modèles d'expression
Nous explorons des techniques de visualisation avancées pour évaluer l'expression génique à travers les clusters. Nous nous concentrons sur les dot plots et les matrix plots, en détaillant comment ils encodent à la fois l'intensité et la rareté de l'expression. Vous apprendrez à valider visuellement vos annotations de types cellulaires en un coup d'œil.
3m 17s
13
Exploration de variétés avec Diffusion Maps
Nous introduisons Diffusion Maps, une technique d'embedding puissante pour les données biologiques continues. Nous la comparons à UMAP, en expliquant pourquoi la diffusion est mieux adaptée à l'analyse de la différenciation cellulaire. Vous apprendrez à visualiser les transitions continues et les processus de développement.
3m 37s
14
Graphes abstraits avec PAGA
Cet épisode couvre l'abstraction de graphes basée sur des partitions, ou PAGA. Nous discutons de la façon de mesurer la connectivité réelle entre les clusters pour préserver la topologie globale. Vous apprendrez à utiliser PAGA pour découvrir les véritables relations de lignage cachées dans vos données.
3m 23s
15
Inférence de trajectoire avec DPT
Nous explorons l'inférence de trajectoire à l'aide du Diffusion Pseudotime (DPT). Nous expliquons comment désigner une cellule racine et calculer les distances géodésiques à travers le graphe cellulaire. Vous apprendrez à disposer les cellules le long d'une chronologie de développement continue.
3m 16s
16
Mise à l'échelle expérimentale avec Dask
Dans notre dernier épisode, nous examinons la frontière expérimentale de Scanpy : la mise à l'échelle avec Dask. Nous expliquons comment gérer les jeux de données qui dépassent la RAM de votre machine en utilisant l'évaluation paresseuse et le traitement out-of-core. Merci de nous avoir rejoints dans cette plongée approfondie dans Scanpy !
3m 28s
Épisodes
1
L'identité de Scanpy et AnnData
3m 54s
Découvrez les concepts fondateurs de Scanpy et pourquoi il a été conçu pour l'analyse single-cell à grande échelle. Nous explorons l'objet AnnData, la structure de données centrale qui maintient les matrices, les annotations et les embeddings parfaitement alignés. Vous apprendrez le modèle mental nécessaire pour naviguer dans l'écosystème de Scanpy.
Salut, c'est Alex de DEV STORIES DOT EU. Analyse single-cell avec Scanpy, épisode 1 sur 16. En quelques années seulement, les datasets single-cell ont explosé, passant de quelques milliers à des millions de cellules. Essaie de charger ce volume dans des toolkits plus anciens et gourmands en mémoire, et ta machine va planter. C'est exactement le problème que Scanpy résout.
Scanpy est un toolkit scalable conçu pour analyser des datasets massifs d'expression génique single-cell en Python. Il gère la mémoire efficacement en s'appuyant sur une structure de données fondamentale très spécifique. Cette structure s'appelle Annotated Data, ou AnnData.
Les gens qui viennent des données tabulaires classiques pensent souvent qu'AnnData est juste un dataframe pandas customisé. Ce n'est pas le cas. Un simple dataframe est beaucoup trop plat pour la biologie single-cell. Dans une expérience single-cell, tu as une matrice massive de counts d'expression, mais tu as aussi des métadonnées complexes sur les cellules et des métadonnées complètement séparées sur les gènes. AnnData est un conteneur multidimensionnel qui lie étroitement la matrice principale et toutes ses métadonnées associées dans un seul objet synchronisé.
Imagine un scénario où tu charges un dataset d'un million de cellules. Au centre de ton objet AnnData se trouve la matrice de données principale, accessible via l'attribut point X. C'est une matrice en deux dimensions qui contient tes vraies valeurs numériques, généralement les counts d'expression génique. Les lignes représentent toujours les observations, qui sont tes cellules individuelles, et les colonnes représentent toujours les variables, qui sont tes gènes. Pour un dataset d'un million de cellules, point X est presque toujours stocké sous forme de sparse matrix pour économiser de la RAM.
Voici le point clé. La matrice dans point X ne stocke pas ses propres noms de lignes ou de colonnes. Elle s'appuie entièrement sur deux dataframes de métadonnées dédiés pour fournir ce contexte.
Le premier, ce sont les métadonnées d'observation, accessibles via l'attribut point obs. C'est un dataframe pandas standard mappé directement sur les lignes de ta matrice point X. Il contient tout ce que tu sais sur les cellules. Pour ton dataset d'un million de cellules, point obs aura exactement un million de lignes. C'est là que se trouvent tes barcodes cellulaires, tes batch labels, tes métriques de contrôle qualité et tes assignations de clustering.
Le deuxième, ce sont les métadonnées de variables, accessibles via l'attribut point var. C'est un autre dataframe mappé directement sur les colonnes de ta matrice point X. Il contient tout ce que tu sais sur les gènes ou les features que tu as mesurés. C'est là que tu stockes les symboles des gènes, les localisations chromosomiques et les métriques statistiques comme les flags de gènes hautement variables.
Parce que point obs et point var sont strictement alignés sur les dimensions de point X, tu peux slicer l'objet AnnData en toute sécurité. Si tu filtres les cellules mortes de point obs, l'objet AnnData supprime automatiquement les lignes correspondantes de la matrice point X. L'alignement dimensionnel ne se casse jamais.
Il y a une autre couche cruciale dans la structure AnnData. À mesure que tu traites tes données single-cell, tu génères des représentations multidimensionnelles de tes cellules, comme les composantes principales ou les coordonnées UMAP. Ces outputs ne rentrent pas proprement dans une seule colonne de point obs. À la place, ils vont dans un dictionnaire séparé appelé point obsm, qui signifie observation matrices. La seule règle, c'est que toute matrice que tu places dans point obsm doit avoir exactement le même nombre de lignes que point X.
En gardant la matrice principale, les métadonnées des cellules et les métadonnées des gènes verrouillées dans une seule structure qui se met à jour toute seule, AnnData garantit que tes données restent parfaitement synchronisées, de la première étape de filtrage jusqu'à la visualisation finale.
Si tu trouves ces épisodes utiles, tu peux soutenir l'émission en cherchant DevStoriesEU sur Patreon. Comme toujours, merci pour ton écoute. On se retrouve dans le prochain épisode.
2
Métriques de contrôle qualité
3m 08s
Nous explorons comment effectuer un contrôle qualité initial sur des données single-cell à l'aide de Scanpy. En isolant des populations de gènes spécifiques comme l'ARN mitochondrial, nous pouvons identifier les cellules stressées ou mourantes. Vous apprendrez à calculer et interpréter ces métriques de contrôle qualité cruciales.
Salut, c'est Alex de DEV STORIES DOT EU. Analyse unicellulaire avec Scanpy, épisode 2 sur 16. Le moyen le plus rapide de ruiner une analyse unicellulaire est de garder, sans le savoir, des cellules mourantes ou vides dans le dataset. Tu pourrais croire que tu découvres une nouvelle sous-population, alors qu'en réalité tu fais juste un clustering de débris cellulaires. Détecter ces cellules compromises repose entièrement sur les Quality Control Metrics.
Mettons les choses au clair tout de suite. On confond souvent le calcul des métriques de qualité avec le fait de filtrer les mauvaises données. Ce n'est pas la même chose. La fonction Scanpy calculate qc metrics ne supprime pas une seule cellule ni un seul gène de ton dataset. C'est strictement un outil d'annotation. Elle calcule des statistiques et les attache comme de nouvelles colonnes à ton dataframe obs, qui suit les cellules, et à ton dataframe var, qui suit les gènes. La suppression réelle des mauvaises cellules se fait dans une étape séparée.
Pourquoi a-t-on besoin de ces métriques spécifiques ? Prends l'exemple d'un échantillon de moelle osseuse. Pendant l'extraction, le stress physique peut déchirer les cellules fragiles. Quand la membrane cellulaire se rompt, l'ARN cytoplasmique fuit et est éliminé. Cependant, les mitochondries sont enfermées dans leurs propres membranes, donc l'ARN mitochondrial reste piégé à l'intérieur de la coquille de la cellule brisée. Si tu séquences cette gouttelette, tu obtiendras une forte concentration de gènes mitochondriaux et très peu d'autres choses. C'est une cellule morte.
Pour identifier ces cellules rompues, tu dois suivre des populations de gènes spécifiques. Dans les datasets humains, les gènes mitochondriaux commencent généralement par le préfixe MT tiret. Les gènes ribosomiques peuvent commencer par RPS ou RPL. Avant de pouvoir calculer des métriques pour ces populations, tu dois les labelliser dans ton dataset. Tu fais ça en créant une nouvelle colonne boolean dans ton dataframe var. Par exemple, tu crées une colonne appelée mt qui est évaluée à True si le nom du gène commence par MT tiret, et à False sinon.
Une fois que tu as flaggué ces gènes, tu lances la fonction calculate qc metrics. Par défaut, cette fonction calcule des statistiques de base standards, comme le nombre total de counts d'ARN par cellule et le nombre de gènes exprimés par cellule. Mais tu peux aussi lui dire de regarder les populations de gènes spécifiques que tu viens de définir. Tu passes le nom de ta colonne boolean, comme mt, dans l'argument qc vars.
La fonction calcule ensuite la proportion de counts provenant de ce groupe de gènes spécifique. Elle ajoute de nouvelles colonnes à ton dataframe obs. Une colonne montrera le total des counts de gènes mitochondriaux pour chaque cellule. Une autre colonne, plus critique, montrera le pourcentage des counts totaux qui proviennent des gènes mitochondriaux. Si une cellule montre que trente pour cent de son ARN est mitochondrial, tu sais que c'est probablement une cellule rompue et mourante à cause du processus d'extraction.
Voici l'information clé. La fonction calculate qc metrics transforme des matrices de counts brutes et ininterprétables en signaux biologiques sur la santé cellulaire. Elle ne prend pas de décisions à ta place, mais en taggant des populations de gènes spécifiques, elle te donne les preuves numériques exactes dont tu as besoin pour séparer la vraie biologie du bruit d'extraction.
Merci d'avoir passé quelques minutes avec moi. À la prochaine, prends soin de toi.
3
Filtrage et normalisation
3m 31s
Cet épisode couvre les étapes critiques du filtrage et de la normalisation des matrices d'expression single-cell. Nous expliquons comment écarter les données de mauvaise qualité et appliquer une mise à l'échelle de la profondeur de comptage avec une transformation log1p. Vous apprendrez comment rendre directement comparables des cellules ayant des profondeurs de séquençage différentes.
Salut, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 3 sur 16. Tu regardes deux cellules dans ton dataset. L'une semble exprimer deux fois plus d'ARN que l'autre. Mais ce n'est pas une différence biologique : une gouttelette a simplement été séquencée deux fois plus en profondeur par la machine. Si tu les compares directement, toute ton analyse downstream sera faussée par des artefacts techniques. Le filtrage et la normalisation sont les outils qui résolvent cette disparité.
Avant de pouvoir ajuster la profondeur de séquençage, tu dois éliminer les déchets. Les données single-cell brutes sont pleines de cellules mortes, de gouttelettes vides et de bruit aléatoire. Tu nettoies ça selon deux axes distincts : les cellules et les gènes. On confond parfois ces deux étapes, mais elles font des choses complètement différentes. Tu gères d'abord les cellules en utilisant la fonction filter cells. Tu dis à Scanpy d'éliminer toute cellule qui exprime moins d'un nombre minimum de gènes. Si une gouttelette ne contient que deux cents gènes détectés alors qu'une cellule saine devrait en avoir deux mille, cette gouttelette est probablement vide ou contient une cellule endommagée et mourante. Tu la drop complètement.
Ensuite, tu filtres les gènes sur l'ensemble de ton dataset. Avec la fonction filter genes, tu supprimes les gènes qui sont exprimés dans trop peu de cellules. Si un gène spécifique n'est détecté que dans une ou deux cellules sur dix mille, il n'apporte aucune valeur statistique pour le clustering ou la classification des types cellulaires par la suite. C'est juste du bruit de calcul. Tu drop ce gène entièrement.
Une fois que les cellules de basse qualité et les gènes non informatifs ont disparu, tu fais toujours face au problème de la profondeur de séquençage. C'est là que tu normalises les total counts. Le but est de scale chaque cellule pour qu'elles semblent toutes avoir le même nombre total de read counts. Prends un scénario où la Cellule A a cinq mille total counts et la Cellule B en a vingt mille. Tu choisis un size factor commun, typiquement dix mille. Scanpy applique un scaling factor à chaque cellule individuellement. Il double les counts de la Cellule A et réduit de moitié les counts de la Cellule B. Maintenant, les deux cellules ont une somme de dix mille total counts. Quand tu regardes un gène spécifique dans les deux cellules, tu compares leur vraie expression relative, de façon complètement indépendante de la profondeur à laquelle la machine de séquençage les a échantillonnées.
Rendre les totaux égaux n'est que la moitié des maths. Les données d'expression biologique sont massivement skewed. Une poignée de gènes aura des nombres de counts énormes, alors que la plupart en auront très peu. Si tu passes ces données skewed dans des calculs de variance ou des algorithmes de dimensionality reduction plus tard, ces quelques gènes massifs vont dominer les maths et noyer les signaux biologiques subtils. Tu corriges ça en utilisant une transformation log plus un. Tu appelles la fonction log one p dans Scanpy, qui applique un logarithme népérien à tous tes counts normalisés. La partie plus un de la fonction est critique car ta data matrix est principalement composée de zéros, qui représentent les gènes qui ne sont pas exprimés dans une cellule donnée. Le log de zéro n'est pas défini, mais le log de zéro plus un est zéro. Cette simple étape compresse les valeurs extrêmement hautes tout en gardant les zéros exactement là où ils sont, ce qui donne une distribution beaucoup plus équilibrée.
Voici l'idée clé. Le filtrage et la normalisation ne modifient pas la biologie sous-jacente de ton échantillon. Ils éliminent les biais mécaniques du hardware de séquençage pour que la vraie biologie puisse émerger. Merci d'avoir écouté, happy coding tout le monde !
4
Détection de doublets avec Scrublet
3m 33s
Nous nous plongeons dans la détection de doublets, une étape cruciale pour repérer les artefacts techniques dans le séquençage single-cell microfluidique. Nous détaillons comment Scrublet simule des doublets artificiels pour signaler les cellules suspectes. Vous apprendrez à identifier et supprimer ces combinaisons artificielles de votre jeu de données.
Salut, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 4 sur 16. Parfois, deux cellules complètement différentes se retrouvent piégées dans la même gouttelette microfluidique, ce qui crée une signature transcriptomique de Frankenstein qui ressemble à un état biologique totalement inédit. Ce n'est pas une découverte. C'est une erreur, et si tu ne la détectes pas très vite, elle va contaminer ton analyse. C'est exactement le problème que le Doublet Detection avec Scrublet est censé résoudre.
Quand tu lances une expérience single-cell en microfluidique à gouttelettes, tu pousses une suspension cellulaire à travers un canal, avec pour but d'avoir une cellule par gouttelette. Statistiquement, ce process n'est pas parfait. De temps en temps, deux cellules partagent une seule gouttelette. Prends le scénario où un monocyte et une T-cell se retrouvent piégés ensemble. Le séquenceur lit leur ARN combiné comme une seule entité, et sort un profil qui mélange les gènes des deux types de cellules. On confond souvent ces profils mixtes avec de vrais états de transition biologiques, comme une cellule en pleine différenciation. Il faut être super clair. Les doublets sont des artefacts purement techniques. Ils n'existent pas dans le tissu, et ils doivent être supprimés.
Dans Scanpy, tu gères ça avec la fonction scrublet dans le module de preprocessing. Scrublet se base sur un principe hyper efficace pour trouver ces fausses cellules. Si tu veux détecter des doublets, tu dois savoir à quoi ressemble un doublet dans ton dataset spécifique. Vu que l'algorithme ne sait pas lesquelles de tes cellules observées sont des erreurs, il fabrique les siennes.
D'abord, Scrublet prend la matrice d'expression de tes cellules observées. Ensuite, il choisit au hasard des paires de ces cellules réelles et additionne de façon computationnelle leurs profils d'expression génique. Ces profils combinés sont tes doublets simulés. Ensuite, Scrublet mappe à la fois tes cellules observées réelles et ces nouveaux doublets simulés dans le même espace à haute dimension. Il construit un classifieur nearest-neighbor pour analyser les relations entre eux.
C'est ça l'idée clé. Scrublet évalue le voisinage immédiat de chaque cellule réelle dans ton dataset. Si une cellule observée est principalement entourée de doublets simulés, cette cellule réelle a l'air mathématiquement identique à un mashup artificiel. Scrublet lui attribue un doublet score élevé. À l'inverse, si une cellule observée se trouve dans un cluster avec d'autres cellules réelles et très peu de doublets simulés, elle reçoit un score faible. Il y a de fortes chances que ce soit une vraie single cell.
La fonction ne s'arrête pas à l'attribution d'un score continu. Elle évalue la distribution de tous les doublet scores à travers ton dataset pour calculer automatiquement un cutoff threshold. Elle cherche une séparation entre le grand pic de cellules normales et la petite queue de doublets suspects. En se basant sur ce threshold, Scrublet tague chaque cellule de ton dataset avec une valeur booléenne, la marquant true si c'est un doublet prédit, et false si c'est un singlet. Ces résultats sont sauvegardés directement dans ton data object, ce qui te permet de filtrer les fausses cellules avant de passer à l'analyse downstream.
La force fondamentale de Scrublet, c'est qu'il ne s'appuie pas sur des bases de données de référence externes pour trouver les erreurs techniques. Il apprend les failure modes exacts de ton expérience spécifique en combinant les cellules mêmes que tu as séquencées.
C'est tout pour cet épisode. Merci d'avoir écouté, et keep building !
5
Sélection de caractéristiques et gènes hautement variables
3m 34s
Nous examinons le concept de sélection de caractéristiques et pourquoi il est nécessaire d'identifier les gènes hautement variables. En écartant le bruit de fond, nous concentrons l'analyse sur les moteurs biologiques. Vous apprendrez à utiliser Scanpy pour isoler les gènes les plus informatifs pour les étapes ultérieures.
Salut, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 5 sur 16. Sur les quelque 30 000 gènes du génome humain, la plupart font juste de la maintenance cellulaire de base. Si tu essaies de tous les analyser en même temps, le volume énorme d'activité de base va noyer la vraie biologie que tu recherches. Pour trouver le vrai signal, tu as besoin de la Feature Selection et des Highly Variable Genes.
D'abord, une petite distinction. Tu as déjà utilisé une fonction de filtrage basique pour supprimer les gènes qui sont à peine détectés dans ton dataset. Cette étape nettoie le bruit technique et les empty droplets. La sélection des Highly Variable Genes fait quelque chose de complètement différent. Elle part du principe que les gènes restants sont réels, mais se demande lesquels sont vraiment informatifs.
Vois ça comme ça. Trier des dizaines de milliers de gènes pour trouver ceux qui créent les différences entre les types de cellules, ça veut dire écarter les housekeeping genes de base qui sont ennuyeux. Un housekeeping gene est actif dans presque toutes les cellules, à peu près au même niveau. Son expression est stable, ce qui le rend inutile pour distinguer une cellule T d'une cellule B. On veut des gènes qui sont fortement exprimés dans certaines cellules et totalement silencieux dans d'autres. Ce sont ça, les Highly Variable Genes. Généralement, tu veux réduire ton dataset à environ deux mille de ces gènes clés.
Dans Scanpy, tu gères ça avec la fonction highly variable genes. Mais tu ne peux pas simplement classer les gènes par variance brute. Dans les données de séquençage, la variance augmente avec l'expression moyenne. Si un gène est fortement exprimé partout, sa variance brute sera naturellement élevée, même s'il n'est pas biologiquement intéressant. L'algorithme doit découpler la variance de l'expression moyenne.
Il fait ça en divisant les gènes dans des bins en fonction de leur niveau d'expression moyen. Ensuite, il calcule une dispersion normalisée à l'intérieur de chaque bin. Ça te dit à quel point un gène varie, comparé uniquement aux autres gènes qui sont exprimés à des niveaux de base similaires. Scanpy propose différentes méthodes statistiques pour faire ces calculs, qu'on appelle des flavors.
Le flavor Seurat traditionnel s'attend à ce que tes données soient d'abord log-normalisées. Il calcule la dispersion, place les données dans des bins, et standardise les valeurs. Il y a aussi un flavor Seurat v3 plus récent, qui nécessite explicitement des données de comptage brutes, non loggées, pour modéliser correctement la variance. Sinon, le flavor CellRanger utilise une approche légèrement différente pour calculer la dispersion normalisée à partir des counts. Le flavor que tu choisis dicte simplement la distribution statistique spécifique utilisée pour modéliser cette relation entre la moyenne et la variance.
Quand tu lances cette fonction, elle ne supprime pas le reste de tes données. À la place, elle ajoute quelques nouvelles colonnes à ton array d'annotations de variables. La plus importante est une colonne booléenne simplement appelée highly variable, qui marque true pour les deux mille premiers gènes et false pour le reste. Les futures étapes de ton pipeline vont automatiquement chercher ce flag et n'utiliseront que ces gènes sélectionnés pour l'analyse downstream.
Voici l'idée clé. La Feature Selection n'est pas juste une astuce informatique pour faire tourner ton code plus vite ; c'est le processus délibéré d'élimination du bruit blanc biologique pour que les vraies identités cellulaires aient la place d'émerger.
Merci d'avoir passé ce moment avec moi. J'espère que tu as appris quelque chose de nouveau.
6
Scoring du cycle cellulaire et régression
3m 27s
Nous explorons comment gérer les facteurs de confusion en évaluant et en régressant les phases du cycle cellulaire. Nous discutons de la façon de calculer les scores S et G2M et d'utiliser la régression pour supprimer leur influence. Vous apprendrez comment empêcher la division cellulaire active de ruiner la topologie de votre clustering.
Salut, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 6 sur 16. Ton algorithme de clustering vient de séparer des lymphocytes T identiques en deux groupes distincts. C'est exactement le même type cellulaire, mais l'algorithme les a séparés simplement parce qu'un groupe est en pleine division alors que l'autre est au repos. Pour corriger ça, on utilise le Cell-Cycle Scoring et la régression.
L'hétérogénéité du cycle cellulaire est une énorme source de variance dans les données single-cell. Si on ne fait rien, les gènes fortement exprimés qui pilotent la mitose vont écraser les signatures génétiques subtiles qui définissent les vrais types cellulaires. Tu te retrouves avec des clusters définis par un état temporaire plutôt que par une vraie identité biologique. Pour résoudre ce problème, Scanpy propose une fonction dédiée pour scorer les gènes en fonction du cycle cellulaire.
Tu passes à cette fonction ton dataset single-cell avec deux listes spécifiques de gènes marqueurs connus. Une liste contient les gènes actifs pendant la phase S, la phase de synthèse du cycle cellulaire. L'autre liste contient les gènes actifs pendant la phase G2M, la phase de mitose. La fonction de scoring évalue chaque cellule et calcule deux métriques continues : un S-score et un G2M-score. Elle fait ça en regardant à quel point ces gènes de phase spécifiques sont exprimés par rapport au niveau d'expression de fond de la cellule. En se basant sur ces deux scores, la fonction attribue aussi un label de phase catégoriel à chaque cellule dans tes metadata, en la marquant comme S, G2M, ou G1 si aucun des scores n'est particulièrement élevé.
Maintenant que tu as quantifié cet effet, tu dois nettoyer son influence du dataset. C'est là que tu utilises la fonction regress out. Tu dis à regress out de regarder les colonnes S-score et G2M-score qui viennent d'être ajoutées aux metadata de tes cellules. L'algorithme construit ensuite un modèle linéaire pour l'expression de chaque gène à travers toutes les cellules, en utilisant ces deux scores de cycle cellulaire comme variables prédictives. Il calcule le résidu, qui est la quantité exacte d'expression génique qui ne peut pas être expliquée par la position de la cellule dans le cycle cellulaire. Cette valeur résiduelle devient le nouveau niveau d'expression corrigé dans ton dataset.
Voici le point clé. On confond souvent la régression avec la batch correction. Ce sont des concepts liés, mais ce sont des outils fondamentalement différents. Les méthodes de batch correction sont conçues pour aligner des groupes discrets et catégoriels, comme des échantillons prélevés à des jours différents ou séquencés sur des machines différentes. Regress out est spécifiquement conçu pour les variables de confusion continues. Tu l'utilises pour des gradients numériques continus comme ces scores de cycle cellulaire, les total counts par cellule, ou le pourcentage de gènes mitochondriaux. Il modélise une pente mathématique et l'aplanit.
Une fois que tu as lancé cette étape de régression, le lourd biais biologique de la division cellulaire est mathématiquement retiré de la matrice d'expression. Quand tu relances ton algorithme de clustering sur ces données corrigées, ces lymphocytes T en division et ces lymphocytes T au repos vont se regrouper en un seul cluster cohérent. L'algorithme n'est plus distrait par le bruit de la réplication de l'ADN. Faire un regress out des scores de cycle cellulaire garantit que ta downstream analysis va clusteriser les cellules strictement selon ce qu'elles sont, plutôt que selon ce qu'elles étaient en train de faire au moment où elles ont été séquencées.
C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
7
Réduction de dimensionnalité avec PCA
3m 24s
Cet épisode explique l'Analyse en Composantes Principales (PCA) dans le contexte des données single-cell. Nous discutons de la façon dont la PCA débruite le jeu de données et pourquoi le choix du bon nombre de composantes est important. Vous apprendrez à réduire des milliers de gènes en une base gérable pour les algorithmes avancés.
Salut, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 7 sur 16. Le cerveau humain ne peut pas visualiser deux mille dimensions. Pire encore, les algorithmes de clustering complexes se retrouvent paralysés par tout ça, englués dans un mélange de vrai signal biologique et de bruit technique aléatoire. Tu as besoin d'un moyen d'extraire la structure de base de tes données avant de les analyser. La réduction de dimensionnalité avec la Principal Component Analysis, c'est comme ça que tu résous ça.
Avant d'entrer dans la mécanique, on doit dissiper un malentendu très courant. Les gens pensent souvent que la PCA, c'est juste un scatter plot qui montre PC1 par rapport à PC2, pensé comme une visualisation finale pour les yeux humains. Ce n'est pas le cas. Même si tu peux faire un plot des deux premiers components, la PCA est fondamentalement une base mathématique. Elle compresse une matrice sparse et bruitée vers un format dense pour alimenter des outils downstream comme les neighbor graphs.
Pense à ton point de départ. Tu viens d'isoler environ deux mille gènes très variables. Chaque gène représente une dimension indépendante dans ton dataset. Tu lances la fonction scanpy tools pca pour calculer les principal components. Cette fonction évalue tout ton dataset et écrase ces deux mille dimensions de gènes en un ensemble beaucoup plus petit de dimensions synthétiques, généralement autour de cinquante.
Ces dimensions synthétiques sont triées selon la quantité de variance qu'elles expliquent. Le premier principal component représente l'axe de variation absolument le plus fort dans tes cellules. Le deuxième représente le suivant, et ainsi de suite. Voici l'idée clé. La première poignée de components capture les vraies différences biologiques structurées. Plus tu descends dans la liste des components, moins ils capturent de biologie et plus ils capturent de bruit technique aléatoire. En coupant la fin de ces components, tu es en gros en train de débruiter ta data matrix.
Pour évaluer cette réduction, tu dois décider combien de components garder. Tu utilises la fonction scanpy plot pca variance ratio. Cette commande génère un line chart qui montre la fraction de variance totale expliquée par chaque component individuel. Tu parcours cette ligne en cherchant l'elbow point, là où la chute abrupte s'aplatit soudainement pour former une longue traîne.
Si la courbe s'aplatit au component quinze, tu pourrais supposer que tu n'as besoin que de quinze components. Cependant, dans les workflows single-cell, on surestime délibérément le nombre de principal components. Tu pourrais voir l'elbow à quinze, mais dire à tes fonctions downstream d'en utiliser cinquante quand même. Les algorithmes de clustering downstream sont très robustes. Ils peuvent facilement ignorer le léger bruit technique contenu dans les components seize à cinquante. Ce qu'ils ne peuvent pas faire, c'est récupérer le signal biologique que tu as jeté trop tôt. Si le component vingt-deux contient la signature de variance d'un type de cellule très rare, le supprimer signifie que ce type de cellule disparaît complètement de ton analyse.
Tu calcules les components, tu vérifies le variance ratio pour confirmer la structure des données, et tu passes à la suite. Le point le plus important à retenir, c'est que la PCA n'est pas une image à regarder, mais un filtre mathématique ciblé qui sacrifie la profondeur dimensionnelle brute pour éliminer le bruit et exposer les vrais axes biologiques de tes données.
J'espère que ça t'a été utile. Merci d'avoir écouté, et passe une bonne fin de journée.
8
Le graphe des plus proches voisins et UMAP
3m 22s
Nous décortiquons le cœur absolu de la topologie single-cell moderne : le graphe des plus proches voisins. Nous expliquons ensuite comment UMAP traduit ce réseau complexe en un graphique 2D lisible. Vous apprendrez pourquoi le graphe des voisins est le prérequis pour presque tous les outils avancés de Scanpy.
Salut, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 8 sur 16. Le secret de l'analyse single-cell moderne, ce n'est pas juste de placer des points sur une grille. C'est de comprendre exactement quelles cellules sont voisines dans un espace massif en haute dimension. Si tu te trompes sur cette structure sous-jacente, toutes les visualisations qui suivent vont t'induire en erreur. Le mécanisme pour capturer cette structure, c'est le nearest neighbor graph, et aujourd'hui on va voir comment le construire et le projeter avec UMAP.
À ce stade dans un pipeline classique, tu as déjà fait une Principal Component Analysis. Tu as condensé des milliers de gènes en peut-être quarante ou cinquante principal components. Mais cinquante dimensions, ça reste impossible à visualiser, et ça ne nous dit pas explicitement quelles cellules appartiennent à la même communauté locale. On a besoin de construire un réseau de connexions. Dans Scanpy, tu fais ça en utilisant la fonction sc dot pp dot neighbors. Cette étape calcule le neighborhood graph de tes cellules.
Calculer les distances entre des dizaines de milliers de cellules sur trente mille gènes bruts, c'est brutal au niveau des calculs et super sensible au bruit. En calculant plutôt les neighbors sur les principal components, les maths sont rapides et le bruit technique est déjà éliminé. Pour chaque cellule, l'algorithme regarde ses coordonnées sur ces principal components et trouve ses pairs les plus proches. Par défaut, il relie une cellule à ses quinze nearest neighbors. L'output est un réseau mathématique où les cellules sont des nœuds, et les edges entre elles représentent une forte similarité. Ce neighborhood graph devient la data structure de base pour les tâches downstream.
Une fois que tu as ce réseau, tu veux vraiment le visualiser. C'est là qu'intervient UMAP, appelé via sc dot tl dot umap. Voici l'idée clé. Une idée fausse très courante, c'est que UMAP calcule les distances directement à partir de tes données brutes d'expression génique. Ce n'est pas le cas. UMAP est complètement aveugle à tes gènes. C'est simplement un layout engine. Son seul job, c'est de prendre ce nearest neighbor graph précalculé et de l'aplatir dans un espace en deux dimensions.
UMAP fonctionne en optimisant un layout pour qu'il corresponde au graphe. Il tire les neighbors connectés les uns vers les autres tout en repoussant les cellules déconnectées. Comme il repose entièrement sur les connexions locales définies à l'étape précédente, il est exceptionnellement doué pour préserver la structure locale. Si un groupe de cellules était étroitement connecté dans le graphe en haute dimension, il formera une île distincte et compacte sur ton plot UMAP 2D. Mais sois conscient que l'espace vide entre les îles séparées sur un plot UMAP ne veut pas dire grand-chose. UMAP sacrifie la précision spatiale globale pour s'assurer que les neighbors locaux restent collés ensemble.
Cette separation of concerns est vitale. La forme que tu vois sur un UMAP est complètement dictée par le neighbor graph construit juste avant. Si tu veux changer la sensibilité de ton layout aux types de cellules rares, tu n'ajustes pas UMAP. Tu reviens en arrière et tu ajustes le nombre de neighbors dans la construction du graphe elle-même.
Si tu trouves ces épisodes utiles et que tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
9
Clustering avec Leiden
3m 38s
Nous explorons comment trouver des populations discrètes de cellules à l'aide de l'algorithme de clustering Leiden. En optimisant la modularité sur le graphe de voisinage, Leiden isole des communautés hautement connectées. Vous apprendrez à ajuster le paramètre de résolution pour trouver des groupes stables et biologiquement pertinents.
Salut, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 9 sur 16. Les algorithmes de clustering traditionnels supposent que tes données se présentent sous forme de blobs parfaitement ronds organisés autour d'un point central. Mais les vraies données biologiques sont désordonnées, interconnectées et forment des structures continues et complexes. Quand tu essaies de forcer ces structures complexes dans de simples sphères, tu finis par diviser des types cellulaires uniques en fragments artificiels. Le clustering avec Leiden résout ça en regardant comment les cellules se connectent entre elles, plutôt que juste là où elles se trouvent dans un espace abstrait.
On a souvent le réflexe de penser au clustering comme au K-means, où tu définis un point central et tu regroupes tout ce qui est à proximité en utilisant des distances physiques standards. Leiden ne fonctionne pas comme ça. C'est un algorithme de clustering basé sur les graphes. Il ignore complètement les distances euclidiennes par rapport à un centroid. À la place, il se base entièrement sur la densité des edges dans le neighbor graph que tu as construit plus tôt dans ton analyse.
Vois le neighbor graph comme un immense réseau social. Les cellules sont des individus, et les edges entre elles sont des amitiés. Leiden fait ce qu'on appelle de la community detection. Il cherche des groupes de cellules qui ont un très grand nombre de connexions au sein de leur propre groupe, mais très peu de connexions vers le réseau extérieur.
Pour y arriver, l'algorithme optimise une métrique appelée modularity. La modularity mesure la densité des liens à l'intérieur des communautés par rapport aux liens auxquels tu t'attendrais si le réseau était totalement aléatoire. L'algorithme commence par assigner chaque cellule à sa propre communauté individuelle. Ensuite, il fusionne ces communautés de manière itérative, en déplaçant les nodes dans un sens et dans l'autre, en vérifiant constamment si le nouveau regroupement augmente le score global de modularity. Leiden est spécifiquement conçu pour affiner ces partitions avec soin, en garantissant que les communautés finales sont densément connectées en interne et ne souffrent pas de fragments déconnectés, ce qui était un problème connu dans l'ancien algorithme Louvain.
Dans Scanpy, tu lances ça en utilisant la fonction tool Leiden. Tu lui passes ton data object principal, et il opère directement sur le neighbor graph existant. L'output est une nouvelle colonne catégorielle ajoutée à tes données, qui contient un numéro de cluster pour chaque cellule.
Voici le point clé. Le contrôle le plus important que tu as sur tout ce processus, c'est le paramètre resolution. Ce paramètre agit comme une molette qui dicte avec quelle agressivité l'algorithme divise les groupes. Par défaut, Scanpy utilise une resolution de un. Si tu augmentes la valeur de resolution, tu obtiens plus de clusters. L'algorithme devient très sensible, et casse le graphe en sous-populations plus petites et très spécifiques. Si tu diminues la valeur de resolution, tu obtiens moins de clusters. L'algorithme devient plus tolérant, et regroupe de plus grandes portions du graphe ensemble.
Supposons que tu lances Leiden et que tu regardes la map qui en résulte. Tu pourrais remarquer qu'un seul type cellulaire biologique connu a été divisé en cinq minuscules sous-populations sur-fragmentées. L'algorithme a trouvé de légères différences, mais biologiquement, ces cinq groupes vont ensemble et forment un seul état cellulaire distinct. Pour corriger ça, tu relances simplement la fonction Leiden, mais cette fois tu passes explicitement un nombre plus bas à l'argument resolution. En baissant la resolution, tu indiques à l'algorithme de relâcher ses critères. Ces cinq petits fragments vont fusionner à nouveau en un seul cluster solide et biologiquement pertinent.
La resolution exacte dont tu as besoin n'est jamais une vérité mathématique fixe ; c'est une molette ajustable que tu tournes jusqu'à ce que les communautés statistiques dans le graphe reflètent précisément les réalités biologiques de ton tissu.
Merci d'avoir été là. J'espère que tu as appris quelque chose de nouveau.
10
Découverte de gènes marqueurs
3m 45s
Nous nous plongeons dans la découverte de gènes marqueurs et les tests d'expression différentielle. Nous expliquons comment les tests statistiques identifient les signatures transcriptomiques uniques de vos clusters. Vous apprendrez à passer de clusters numérotés anonymes à des types cellulaires biologiques étiquetés avec certitude.
Salut, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 10 sur 16. Tu as isolé un cluster de cellules distinct et bien resserré dans ton dataset, mais comment savoir s'il s'agit d'une cellule T, d'une cellule B ou d'un état totalement inconnu ? Les maths les ont regroupées, mais c'est la biologie qui doit te dire ce qu'elles sont. Cette étape de traduction repose entièrement sur la découverte de gènes marqueurs.
Avant de regarder les outils, on doit tracer une ligne claire entre le clustering et l'annotation. Les algorithmes de clustering regroupent simplement les cellules en fonction de leur similarité statistique sur des milliers de dimensions et leur attribuent un label arbitraire, comme Cluster 0 ou Cluster 1. Ce chiffre ne veut rien dire biologiquement. La découverte de gènes marqueurs, c'est le processus qui permet de trouver les gènes spécifiques qui pilotent ce regroupement statistique, ce qui te permet d'attribuer de vrais noms biologiques à ces clusters.
Dans Scanpy, tu trouves ces gènes moteurs en utilisant une fonction appelée rank genes groups. Cette fonction fait une analyse d'expression différentielle. Elle prend un regroupement catégoriel, généralement tes clusters calculés, et compare l'expression des gènes des cellules à l'intérieur d'un cluster avec les cellules de tous les autres clusters combinés. Le but est de trouver des gènes qui sont fortement exprimés dans ton cluster cible, mais presque silencieux partout ailleurs. Par défaut, elle compare chaque cluster à l'union du reste des cellules, mais tu peux aussi la configurer pour comparer un cluster à un groupe de référence spécifique si tu cherches des différences subtiles entre deux types de cellules très proches.
Pour décider si un gène est vraiment un marqueur, Scanpy lance un test statistique pour scorer la différence d'expression. Tu peux choisir un t-test standard, mais le test rank-sum de Wilcoxon est fortement recommandé et c'est le choix standard pour les données single-cell. L'expression des gènes en single-cell ne suit pas une courbe en cloche normale ; elle est très variable, fortement asymétrique et pleine de valeurs zéro là où un gène n'a tout simplement pas été détecté. Le test de Wilcoxon ne présuppose pas une distribution normale. Au lieu de regarder les valeurs moyennes brutes, il classe les valeurs d'expression sur toutes les cellules et compare les rangs entre ton cluster cible et le reste du dataset. Ça le rend beaucoup plus robuste face aux outliers extrêmes.
Regardons un scénario spécifique. Tu as un dataset avec plusieurs clusters et tu veux interroger le Cluster 3. Tu appelles la fonction rank genes groups, tu lui dis d'utiliser tes labels de cluster existants, et tu règles la méthode sur Wilcoxon. Scanpy fait les calculs et classe chaque gène en fonction de la façon dont il définit le Cluster 3 de manière unique. Tu inspectes ensuite les premiers résultats. Tu vois que les gènes les mieux classés sont CD8A et GZMK. Si tu connais ton immunologie, tu reconnais immédiatement que ce sont des marqueurs classiques pour les cellules T cytotoxiques. Parce que ces gènes spécifiques sont uniquement surexprimés ici par rapport au reste du dataset, tu peux labelliser le Cluster 3 en toute confiance comme une cellule T CD8 positive.
L'output de cette fonction est stocké discrètement dans ton objet AnnData sous l'attribut uns. Scanpy sauvegarde des arrays de noms de gènes, de scores statistiques, de p-values et de log-fold changes pour chaque cluster simultanément. Tu peux extraire ces arrays pour construire des dataframes, les sauvegarder dans un fichier csv, ou les passer directement à des outils d'annotation en aval.
Voici l'idée clé. L'expression différentielle transforme des formes mathématiques arbitraires en identités biologiques actionnables. Sans gènes marqueurs, tu as juste une carte de nombres ; avec eux, tu as un système biologique cartographié.
C'est tout pour cet épisode. Merci pour ton écoute, et continue à développer !
11
Intégration de données avec Ingest
3m 16s
Cet épisode couvre l'intégration de données à l'aide de l'outil Ingest. Nous expliquons comment projeter de nouveaux jeux de données sur l'espace PCA et UMAP d'un atlas de référence pré-annoté. Vous apprendrez une méthode rapide et invariante pour cartographier les étiquettes à travers différentes expériences.
Salut, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 11 sur 16. Tu as un dataset de référence parfaitement annoté, et un tout nouvel échantillon patient que tu dois analyser. Normalement, les combiner implique de faire une batch correction, de recalculer tes principal components, et d'attendre le rendu de zéro d'une énorme UMAP conjointe. L'intégration de données avec Ingest offre une alternative plus rapide et non destructive.
On confond souvent Ingest avec la batch correction standard. Les outils de batch correction traditionnels prennent plusieurs datasets et calculent un tout nouveau modèle conjoint. Ils modifient la représentation sous-jacente de tes données de référence pour forcer un alignement. Ingest fait l'inverse. C'est une projection asymétrique. Ton dataset de référence sert de ground truth absolue. Le modèle spatial est verrouillé, et les nouvelles données sont simplement poussées à travers sans altérer le modèle original du tout.
Prends un atlas de référence de Peripheral Blood Mononuclear Cells magnifiquement annoté. Chaque cluster est vérifié et labellisé. Tu viens de recevoir un échantillon patient non annoté et en vrac. Tu veux appliquer ces labels d'atlas à ton nouvel échantillon, et tu veux plotter les nouvelles cellules dans le même espace de coordonnées que la référence.
Pour que ça marche, les variables de tes deux datasets doivent s'aligner. Ça veut dire que les deux datasets doivent partager exactement les mêmes gènes. En pratique, tu filtres ton nouveau query dataset pour que ses gènes correspondent aux highly variable genes déjà identifiés dans ton atlas de référence.
Ton dataset de référence doit être entièrement processé avant de commencer. Il a besoin d'une Principal Component Analysis existante, d'un neighborhood graph calculé, et d'une représentation UMAP. Il contient aussi les labels catégoriels que tu veux transférer, stockés dans ses observation metadata.
L'exécution se fait en une seule commande. Tu appelles la fonction ingest, en lui passant ton nouveau query dataset, ton dataset de référence annoté, et la colonne d'observation spécifique que tu veux mapper, comme le label du type cellulaire.
Voici l'idée clé. Quand tu déclenches la fonction, ingest prend les profils d'expression de tes nouvelles cellules et les projette mathématiquement dans l'espace des principal components existant de l'atlas de référence. Il évite complètement de calculer une nouvelle Principal Component Analysis globale.
Une fois que les query cells atterrissent dans cette disposition spatiale partagée, l'algorithme cherche les nearest neighbors. Il mappe les query cells directement sur le neighbor graph préexistant du dataset de référence. Le gros du travail de calcul pour construire un graphe a déjà été fait par le modèle de référence.
Comme les nouvelles cellules ont maintenant des voisins établis dans les données de référence, deux transferts finaux ont lieu. Premièrement, les coordonnées UMAP des voisins de référence sont assignées aux nouvelles cellules. Deuxièmement, les labels de metadata, comme tes types cellulaires, sont copiés en se basant sur le majority voting de ces voisins de référence les plus proches.
Le résultat est un query dataset qui porte exactement la disposition UMAP et les annotations de type cellulaire de ton atlas. Tu peux superposer l'échantillon patient précédemment non annoté directement sur ta visualisation de référence, et les populations biologiques correspondantes tomberont proprement dans les clusters visuels établis.
En projetant de nouvelles cellules sur un modèle existant, ingest fait passer ton workflow de la reconstruction constante d'espaces globaux fragiles, à la construction d'un seul atlas de référence robuste, en y faisant passer de manière fluide toutes tes futures expériences.
C'est tout pour cet épisode. Merci d'avoir écouté, et keep building !
12
Visualisation des modèles d'expression
3m 17s
Nous explorons des techniques de visualisation avancées pour évaluer l'expression génique à travers les clusters. Nous nous concentrons sur les dot plots et les matrix plots, en détaillant comment ils encodent à la fois l'intensité et la rareté de l'expression. Vous apprendrez à valider visuellement vos annotations de types cellulaires en un coup d'œil.
Bonjour, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 12 sur 16. Un feature plot standard est super pour montrer où un gène spécifique est actif, mais ça ne marche plus du tout quand tu dois comparer simultanément vingt gènes différents sur dix clusters distincts. Pour résoudre ça, on va regarder la visualisation des patterns d'expression. Quand tu vérifies des gènes marqueurs, le premier réflexe c'est souvent de faire une heatmap. Tu alignes toutes tes cellules, tu alignes tes gènes, et tu cherches des blocs de couleur. Mais les données de séquençage ARN single-cell sont notoirement sparse. La plupart des cellules ont des counts à zéro pour la majorité des gènes. Dans une heatmap single-cell standard, cette sparsity crée du bruit visuel. Tu te retrouves à fixer un océan de couleur de fond, en essayant de deviner si un gène est vraiment un marqueur spécifique pour un cluster ou s'il a juste drop out au hasard partout ailleurs. C'est là que le dot plot entre en jeu. Au lieu de plotter les cellules individuellement, un dot plot les agrège. Tu places tes groupes de cellules, comme tes clusters de Leiden, sur un axe, et tes gènes d'intérêt sur l'autre. À chaque intersection, tu obtiens un cercle. Voici l'idée clé. Un dot plot encode deux informations complètement différentes dans ce seul cercle. Premièrement, la couleur du point représente le niveau d'expression moyen du gène dans ces cellules. Des couleurs plus foncées ou plus intenses signifient une expression plus élevée. Deuxièmement, la taille du point représente la fraction de cellules dans ce cluster qui expriment réellement le gène. Un gros point signifie que presque toutes les cellules du cluster ont au moins un peu d'ARN pour ce gène. Un tout petit point signifie que seules quelques cellules l'expriment. Ce double encodage est incroyablement puissant pour les données sparse. Il sépare la quantité de gène présente de sa distribution globale. Disons que tu regardes quinze gènes marqueurs candidats sur cinq clusters de Leiden. Tu passes tes données, ta liste de gènes et tes labels de clusters à la fonction dot plot. Tu peux voir instantanément si tes marqueurs de monocytes attendus sont à la fois fortement et largement exprimés dans le Cluster un, tout en étant totalement absents dans les quatre autres clusters. Tu n'as pas besoin de plisser les yeux sur des lignes de cellules individuelles. Les gros points foncés dans la ligne du Cluster un te donnent une validation immédiate. Parfois, tu n'as pas besoin de l'information de fréquence donnée par la taille du point. Tu veux juste une grille propre qui montre l'expression moyenne. Pour ça, Scanpy propose la fonction matrix plot. Vois un matrix plot comme une heatmap groupée. Il agrège toujours tes cellules par cluster, mais il remplit toute la case de la grille avec une couleur qui représente la valeur d'expression moyenne. Il n'y a pas de tailles de points qui changent. C'est un moyen plus rapide et plus dense de vérifier des patterns d'expression globaux quand tu as une liste massive de gènes et que la fraction de cellules qui les expriment t'importe moins. Les deux outils prennent ton objet de données, une liste de tes gènes cibles, et la catégorie de metadata par laquelle tu veux grouper. Ils s'exécutent rapidement et scalent super bien sur des dizaines de gènes. Quand tu gères la sparsity en single-cell, séparer l'intensité d'expression de la fréquence d'expression est le moyen le plus fiable de confirmer qu'un gène marqueur définit vraiment un cluster. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
13
Exploration de variétés avec Diffusion Maps
3m 37s
Nous introduisons Diffusion Maps, une technique d'embedding puissante pour les données biologiques continues. Nous la comparons à UMAP, en expliquant pourquoi la diffusion est mieux adaptée à l'analyse de la différenciation cellulaire. Vous apprendrez à visualiser les transitions continues et les processus de développement.
Salut, c'est Alex de DEV STORIES DOT EU. Analyse single-cell avec Scanpy, épisode 13 sur 16. UMAP est fantastique pour séparer des types cellulaires distincts, mais il peut violemment déchirer des processus biologiques continus. Quand tu étudies le développement cellulaire, tu ne veux pas d'îlots de cellules disjoints ; tu as besoin de voir le continuum fluide des changements d'état. Explorer les manifolds avec les Diffusion Maps résout exactement ce problème.
Dans Scanpy, tu calcules ça en utilisant l'outil diffmap. Les utilisateurs choisissent souvent UMAP par défaut pour toute réduction de dimensionnalité. Comprends bien qu'UMAP est une technique d'embedding optimisée pour trouver des clusters distincts et préserver les voisinages locaux. Les Diffusion Maps sont fondamentalement différentes. Elles préservent la probabilité mathématique continue de transition entre les états. Ça en fait le choix idéal pour analyser des processus continus comme la différenciation cellulaire.
L'algorithme diffmap traite ton data manifold comme un réseau continu. Il repose entièrement sur le nearest neighbor graph de tes cellules. Une fois ce graphe établi, l'algorithme simule un random walk à travers les connexions. Vois ça comme la modélisation d'un processus de diffusion, un peu comme la chaleur qui se propage dans un matériau physique. L'algorithme évalue avec quelle facilité un signal peut voyager à travers les régions denses de tes données. Il calcule la probabilité de passer d'un état cellulaire à un autre sur un nombre spécifique d'étapes. Les cellules qui partagent une forte probabilité de transition sont placées plus près les unes des autres dans l'espace final de plus basse dimension.
Imagine que tu traces une cellule souche hématopoïétique qui se différencie en érythrocyte. Si tu projettes ces données en utilisant un embedding qui favorise la séparation discrète, les cellules progénitrices intermédiaires sont souvent forcées dans des clusters séparés et artificiels. Les mathématiques sous-jacentes fracturent la chronologie biologique. Si tu lances diffmap à la place, l'algorithme calcule les probabilités de transition le long de tout le chemin de développement. Le résultat est une trajectoire fluide et continue. La cellule souche se trouve à une extrémité, l'érythrocyte mature à l'autre. Chaque état intermédiaire est tracé le long d'un chemin connecté, basé strictement sur la probabilité de transition d'état. Tu ne regardes pas des snapshots isolés de types cellulaires distincts. Tu regardes un événement biologique fluide.
Appliquer ça dans Scanpy suit une séquence rigide. D'abord, tu dois calculer le neighborhood graph dans ton objet. La Diffusion Map ne peut pas tourner sans ces connexions de voisins précalculées. Ensuite, tu appelles l'outil diffmap et tu lui passes ton objet AnnData. Tu peux optionnellement spécifier le nombre de components que tu veux calculer, ce qui définit les dimensions de l'output. Scanpy calcule la Diffusion Map et stocke les nouvelles coordonnées dans l'attribut d'observation multidimensionnelle de ton objet, sous la clé X diffmap.
L'outil stocke aussi les eigenvalues dans l'attribut de données non structurées. Ces valeurs te disent combien de variance chaque diffusion component capture. Une chute brutale de ces eigenvalues indique que tu as capturé les transitions biologiques les plus importantes, et que les components suivants sont probablement du bruit. Dans un dataset de différenciation typique, le premier diffusion component non trivial s'aligne directement avec l'axe temporel de développement principal.
Voici l'idée clé. Dans une Diffusion Map, la distance physique entre deux cellules sur le plot n'est pas juste une mesure générique de similarité transcriptomique. Cette distance représente explicitement la probabilité mathématique qu'une transition biologique se produise entre ces deux états spécifiques.
C'est tout pour cette fois. À la prochaine !
14
Graphes abstraits avec PAGA
3m 23s
Cet épisode couvre l'abstraction de graphes basée sur des partitions, ou PAGA. Nous discutons de la façon de mesurer la connectivité réelle entre les clusters pour préserver la topologie globale. Vous apprendrez à utiliser PAGA pour découvrir les véritables relations de lignage cachées dans vos données.
Salut, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 14 sur 16. Ce n'est pas parce que deux clusters de cellules sont côte à côte sur un plot UMAP qu'ils sont biologiquement liés. La proximité visuelle en deux dimensions est souvent une illusion mathématique, et si tu t'y fies pour tracer des trajectoires de développement, tu risques de relier des points qui ne se touchent pas vraiment dans un espace en haute dimension. Pour mapper une connectivité réelle et validée statistiquement, tu as besoin des Abstracted Graphs avec PAGA.
PAGA signifie Partition-based Graph Abstraction. Il faut tout de suite dissiper une idée reçue très courante. PAGA n'est pas un embedding de réduction de dimensionnalité comme t-SNE ou UMAP. Il ne calcule pas les coordonnées des cellules individuelles pour dessiner un scatter plot. À la place, PAGA crée un graphe simplifié, coarse-grained. Les nodes de ce graphe sont des clusters entiers, ou des partitions, de cellules. Les edges qui relient ces nodes représentent la confiance statistique que ces clusters partagent une frontière continue.
Quand tu appelles la fonction PAGA sur tes données annotées, tu la pointes vers un set spécifique de labels de groupes, généralement tes clusters Leiden ou Louvain. L'algorithme évalue ensuite les frontières entre ces groupes en creusant dans le neighborhood graph single-cell sous-jacent. Il regarde les cellules individuelles du cluster A et compte combien de leurs voisins directs appartiennent au cluster B. En comptabilisant toutes ces connexions cross-cluster et en les comparant à un modèle random, PAGA génère une connectivity matrix quantifiable. Une valeur élevée signifie que les clusters sont profondément imbriqués, ce qui suggère une transition biologique. Une valeur faible signifie que ce sont des îles séparées.
Prenons un scénario concret. Tu suis le développement de cellules immunitaires et tu dois prouver qu'un cluster de progéniteurs spécifique donne directement naissance à un cluster de cellules T effectrices. Sur un plot visuel standard, l'algorithme de layout pourrait jeter un cluster qui n'a rien à voir pile entre les deux, ce qui donnerait l'impression que leur relation est indirecte. En examinant la connectivity matrix de PAGA, tu contournes cette distorsion visuelle. Tu regardes directement le edge weight mathématique entre tes groupes de progéniteurs et d'effecteurs. PAGA te permet de définir un threshold de connectivité minimum. Quand tu appliques ce threshold, tu filtres les connexions parasites à faible confiance. Si le edge fort entre tes deux clusters cibles survit au cut, tu as établi un lien statistiquement robuste.
C'est ça la partie importante. PAGA ne fait pas juste qu'accompagner tes embeddings ; il peut les corriger. Parce que PAGA préserve la topologie globale de façon très fiable, tu peux utiliser l'abstracted graph pour initialiser un embedding UMAP. Au lieu de laisser UMAP démarrer depuis un layout spatial random, tu lui dis de positionner les cellules individuelles en se basant sur le graphe PAGA coarse-grained. Ça ancre ta visualisation 2D finale à la vraie réalité en haute dimension, ce qui garantit que des états biologiques distants ne soient pas artificiellement écrasés ensemble.
Les visualisations déformeront toujours les données complexes pour les faire tenir sur un écran plat, mais l'abstraction d'un neighborhood graph repose entièrement sur la proximité mathématique. Fais confiance au graphe plutôt qu'à l'image.
C'est tout pour cet épisode. Merci d'avoir écouté, et continue de coder !
15
Inférence de trajectoire avec DPT
3m 16s
Nous explorons l'inférence de trajectoire à l'aide du Diffusion Pseudotime (DPT). Nous expliquons comment désigner une cellule racine et calculer les distances géodésiques à travers le graphe cellulaire. Vous apprendrez à disposer les cellules le long d'une chronologie de développement continue.
Salut, c'est Alex de DEV STORIES DOT EU. Scanpy Single-Cell Analysis, épisode 15 sur 16. Le séquençage single-cell détruit la cellule même que tu cherches à étudier. Tu obtiens un snapshot statique de son expression génique, ce qui veut dire que tu ne peux pas enregistrer une vidéo d'une cellule souche en train de se différencier vers un état mature. Pour voir ce parcours de développement, tu dois inférer une timeline mathématiquement en calculant des distances transcriptomiques. C'est exactement ce qu'on fait en utilisant la Trajectory Inference avec DPT.
DPT, ça veut dire Diffusion Pseudotime. Avant de regarder comment l'algorithme fonctionne, on doit clarifier ce que ce nom veut vraiment dire. Le pseudotime n'est pas un vrai temps chronologique. Il ne mesure pas les heures, les jours, ou l'âge biologique d'une cellule. C'est strictement une métrique de distance transcriptomique. Il mesure combien de changements d'expression incrémentaux une cellule a subis par rapport à un point de départ spécifique.
Pour lancer ça dans Scanpy, tu utilises la fonction qui s'appelle sc point tl point dpt. Cette fonction opère sur le neighborhood graph existant de ton dataset, qui connecte les cellules en fonction de leur similarité. Cependant, un graphe tout seul n'a pas de direction inhérente. Pour lui donner une direction, tu dois définir un point de départ. Tu fais ça en définissant une root cell.
Imagine un scénario où tu étudies le développement du sang. Tu examines tes clusters et tu identifies les cellules souches hématopoïétiques naïves. Tu choisis un index de cellule spécifique dans ce groupe et tu l'assignes comme root dans la structure de ton dataset. Ça agit comme le point d'origine, ou le temps zéro, pour tout le calcul.
Une fois que la root est établie, tu exécutes la fonction DPT. Voici l'idée clé. L'algorithme ne mesure pas une distance droite et linéaire entre la root et une autre cellule. Le développement biologique n'est pas une ligne droite, il suit des chemins complexes qui se ramifient. Pour capturer ça, DPT calcule des distances géodésiques le long de ton neighborhood graph. Il évalue la structure de la data en simulant des random walks à partir de la root. Il avance de cellule en cellule à travers les edges denses du graphe, pour trouver les chemins les plus probables de changement transcriptomique.
Le résultat de ce calcul, c'est un nouvel array de valeurs ajouté à tes annotations de cellules. Chaque cellule de ton dataset reçoit un score de pseudotime. La root cell est à zéro. À mesure que la distance géodésique depuis la root augmente, le score monte. Dans notre scénario de développement du sang, une cellule progénitrice intermédiaire pourrait obtenir un score de zéro virgule quatre, tandis qu'une cellule complètement mature à l'extrémité terminale d'une branche obtient un score proche de un.
Tu as ainsi mappé un cluster statique de points vers un ordre de développement continu, en les triant du moins au plus différencié. Tu peux maintenant utiliser cet axe numérique pour tracker la dynamique individuelle des gènes, en plottant exactement quand un facteur de transcription spécifique s'active le long du chemin de développement.
La fiabilité de ta Trajectory Inference dépend entièrement de ton point de départ, ce qui veut dire qu'une root mal choisie va donner une timeline parfaitement calculée, mais biologiquement dénuée de sens.
Si tu trouves ces épisodes utiles et que tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon. C'est tout pour celui-ci. Merci d'avoir écouté, et continue de développer !
16
Mise à l'échelle expérimentale avec Dask
3m 28s
Dans notre dernier épisode, nous examinons la frontière expérimentale de Scanpy : la mise à l'échelle avec Dask. Nous expliquons comment gérer les jeux de données qui dépassent la RAM de votre machine en utilisant l'évaluation paresseuse et le traitement out-of-core. Merci de nous avoir rejoints dans cette plongée approfondie dans Scanpy !
Salut, c'est Alex de DEV STORIES DOT EU. Analyse single-cell avec Scanpy, épisode 16 sur 16. Que se passe-t-il quand ton dataset single-cell atteint cinq millions de cellules et sature complètement la mémoire de ton ordi ? Tu ne peux pas le filtrer, tu ne peux pas le normaliser, et ton kernel plante tout simplement. La solution à cette limite de mémoire stricte, c'est le Scale-Up expérimental avec Dask.
Souvent, quand on entend Dask, on pense tout de suite au traitement parallèle sur un cluster distribué pour accélérer le code. Même si Dask peut faire ça, son vrai superpouvoir dans Scanpy en ce moment, c'est la gestion de la mémoire out-of-core grâce à la lazy evaluation. Il ne s'agit pas juste d'aller plus vite. Il s'agit de faire des choses qui étaient avant impossibles sur une seule machine.
Les workflows Scanpy standards reposent sur des arrays in-memory. Ça demande que tout le dataset réside dans ta RAM active. Quand tu utilises le backend Dask, Scanpy remplace ces arrays standards à l'intérieur de ton objet AnnData par des arrays Dask. Un array Dask, c'est en gros une collection de plein de petits arrays, qu'on appelle des chunks. Au lieu de charger toute la matrice en mémoire d'un coup, Dask laisse le gros des données en sécurité sur le disque.
Quand tu lances une fonction de preprocessing Scanpy basée sur Dask, ça ne calcule pas le résultat tout de suite. C'est là qu'intervient la lazy evaluation. Au lieu de faire des calculs, Dask construit une recette. Il crée un task graph qui décrit exactement quelles opérations mathématiques doivent être effectuées sur chaque chunk de données individuel.
Imagine un scénario où tu as un dataset massif de deux millions de cellules sur le disque, et tu dois calculer des métriques de quality control. Si tu essaies de faire ça avec un array standard, ton système va freezer en essayant de tout tirer dans la RAM. Mais si ton objet AnnData contient un array Dask, tu appelles simplement la fonction de quality control standard de Scanpy. La fonction retourne presque instantanément. Ta mémoire ne fait pas de pic, parce qu'aucun chiffre n'a encore été réellement traité. Scanpy a juste noté ton intention.
Quand tu es enfin prêt à plotter ces métriques ou à sauvegarder les summary statistics, tu dis explicitement à Dask de calculer le résultat. C'est la partie qui compte. À ce moment précis, Dask récupère le premier chunk de données depuis ton disque dur, calcule les métriques juste pour ce chunk, stocke le petit résultat, puis jette immédiatement le chunk de données brutes hors de la mémoire. Ensuite, il passe au chunk suivant. Ton empreinte mémoire active reste minuscule. Elle est dictée entièrement par la taille d'un seul chunk, et non par les millions de cellules de tout le dataset.
En ce moment, ce backend Dask dans Scanpy est catégorisé comme expérimental. Toutes les fonctions de l'écosystème ne le supportent pas encore. Cependant, les étapes de preprocessing de base comme la normalisation, le scaling et la sélection de highly variable genes sont parfaitement équipées pour gérer des opérations out-of-core massives.
Quand tu passes d'un eager processing in-memory à un lazy processing sur disque, la taille de ton dataset n'est plus limitée par la RAM de ton hardware, mais uniquement par ta patience.
Ça nous amène à la fin de notre série single-cell. Je t'encourage vivement à explorer la documentation officielle de Scanpy et à essayer de construire ces data graphs toi-même. Si tu as des idées sur les technologies qu'on devrait couvrir dans notre prochaine série, visite devstories dot eu et dis-le-nous. Merci d'avoir écouté, et happy coding à tous !
Tap to start playing
Browsers block autoplay
Share this episode
Episode
—
Copy this episode in another language:
Ce site n'utilise pas de cookies. Notre hébergeur peut enregistrer votre adresse IP à des fins d'analyse. En savoir plus.