Activité des facteurs de transcription par cellule en R avec decoupleR & DoRothEA

Allez un niveau plus profond que l’activité des voies : inférez quels facteurs de transcription sont actifs dans chaque cellule à partir de l’expression de leur régulon — les gènes cibles qu’ils contrôlent — avec les régulons DoRothEA et decoupleR, validé par rapport à une réponse interféron connue

Un guide pratique de l’activité des facteurs de transcription (TF) par cellule pour le RNA-seq single-cell en R. Utilisez les régulons DoRothEA avec le modèle linéaire univarié de decoupleR (run_ulm) pour inférer l’activité de centaines de TF dans chaque cellule à partir de leurs gènes cibles, contrastez-les à travers une stimulation à l’interféron-bêta, et validez le résultat par rapport à la vérité terrain intégrée — l’IFN-bêta pilote le complexe ISGF3 (STAT1, STAT2, IRF9) et la famille IRF, donc l’activité de ces TF doit exploser dans les cellules stimulées. Inclut en quoi l’activité des TF diffère de l’activité des voies et de la notation de signatures géniques, et DoRothEA face au plus récent CollecTRI.

Date de publication

4 juillet 2026

Modifié

7 juillet 2026

AstucePoints clés
  • L’activité d’un facteur de transcription se lit dans son régulon, pas dans son propre ARNm. Un facteur de transcription (TF — une protéine qui active ou désactive des gènes) est souvent exprimé à un niveau plat et faible même lorsqu’il pilote une réponse massive. Ce qui bouge, c’est l’expression coordonnée des gènes qu’il contrôle — son régulon. Inférer l’activité d’un TF, c’est lire le régulon, pas le propre transcrit du TF.
  • DoRothEA fournit les régulons ; decoupleR les note par cellule. DoRothEA (une collection soigneusement choisie de régulons TF-vers-cibles avec des niveaux de confiance A–E et un mode de régulation signé) fournit quels gènes chaque TF régule (Garcia-Alonso et al., 2019) ; decoupleR exécute ce réseau sur chaque cellule pour renvoyer un score d’activité par cellule pour chaque TF (Badia-i-Mompel et al., 2022).
  • run_ulm est le choix par défaut recommandé — un modèle linéaire univarié. Il régresse l’expression de chaque cellule sur les poids cibles signés d’un TF, et la pente ajustée (sa valeur t) devient l’activité de ce TF. decoupleR offre aussi run_mlm, run_wsum et un consensus, mais run_ulm est le choix par défaut documenté pour l’activité des TF.
  • Validez par rapport à un contraste connu. La moitié des cellules ont été stimulées à l’interféron-bêta (IFN-β), qui active l’axe JAK-STAT et ses facteurs de transcription. Les TF dont l’activité bondit le plus entre les cellules contrôle et stimulées sont STAT2, IRF9, STAT1 et IRF1 — le complexe ISGF3 (STAT1 + STAT2 + IRF9) et la famille des facteurs de régulation de l’interféron, les TF canoniques de l’interféron de type I. Les régulons récupèrent la biologie à partir des seuls gènes cibles.
  • Ceci complète la trilogie de l’inférence fonctionnelle. La notation de signatures demande cette cellule exprime-t-elle cet ensemble de gènes ? ; l’activité des voies demande une voie de signalisation est-elle active ? ; l’activité des TF demande quel facteur de transcription pilote le programme ? — trois niveaux complémentaires de la même question fonctionnelle.

Introduction

Vous avez exécuté le workflow standard de RNA-seq single-cell (scRNA-seq — le séquençage de l’ARN cellule par cellule) : contrôle qualité, regroupement, annotation des types cellulaires. Vous avez commencé à quantifier ce que les cellules font — vous avez peut-être noté des signatures géniques et inféré quelles voies de signalisation sont actives. La question suivante est plus pointue encore : quels facteurs de transcription pilotent la réponse ? Une voie vous dit que le signal est allumé ; les facteurs de transcription sont la machinerie qui réécrit réellement le programme d’expression génique de la cellule.

Voici le piège qui rend l’activité des TF digne d’être inférée plutôt que simplement lue. Le propre ARNm d’un facteur de transcription est un mauvais indicateur de son activité. STAT1 peut siéger à un niveau d’expression faible et plat et pourtant, une fois phosphorylé par la signalisation interféron, activer des centaines de gènes. Son activité est invisible dans son propre transcrit — mais elle est inscrite partout dans les gènes qu’il contrôle. Cet ensemble de gènes contrôlés est le régulon du TF, et inférer l’activité d’un TF consiste à relire l’expression coordonnée du régulon vers un seul score d’activité par cellule.

Cette leçon construit l’activité des TF par cellule avec deux outils du laboratoire Saez-Rodriguez : DoRothEA (une collection soigneusement choisie de régulons de TF) fournit quels gènes chaque TF régule, et decoupleR note ce réseau dans chaque cellule. Nous travaillons sur le classique benchmark immunitaire PBMC IFN-β : des cellules mononucléées du sang périphérique (PBMC — les cellules immunitaires du sang) séparées en un groupe contrôle et un groupe stimulé à l’interféron-bêta (IFN-β) (Kang et al., 2018). L’IFN-β signale via l’axe JAK-STAT pour activer le complexe ISGF3 — un trimère des facteurs de transcription STAT1, STAT2 et IRF9 — et la famille des facteurs de régulation de l’interféron (IRF). Cela nous donne une vérité terrain intégrée : l’activité de ces TF doit être bien plus élevée dans les cellules stimulées. Si les régulons ne peuvent pas retrouver un signal aussi fort, nous ne devrions pas leur faire confiance sur un signal subtil.

Trois niveaux d’inférence fonctionnelle : quelle question posez-vous ?

L’activité des TF est la troisième de trois questions fonctionnelles apparentées mais distinctes. Il vaut la peine d’être précis sur la façon dont elles diffèrent, parce qu’elles sont faciles à confondre et répondent à des choses véritablement différentes.

Notation de signatures Activité des voies Activité des facteurs de transcription
Question Cette cellule exprime-t-elle cet ensemble de gènes ? Cette voie de signalisation est-elle active ? Quel facteur de transcription est actif ?
Gènes lus Les membres de l’ensemble lui-même Les gènes de réponse en aval d’une voie Le régulon d’un TF — les gènes qu’il régule
Ressource Votre liste choisie PROGENy (~14 voies) DoRothEA / CollecTRI (des centaines de TF)
Granularité Un programme Une poignée de voies de signalisation Des régulateurs individuels, des centaines
Outil AUCell, UCell PROGENy + decoupleR DoRothEA + decoupleR (cette leçon)

La notation de signatures interroge l’appartenance — à quel point une cellule est enrichie pour les gènes de l’ensemble. L’activité des voies et l’activité des TF sont toutes deux des modèles d’empreinte : elles infèrent l’activité d’un régulateur à partir des gènes sur lesquels il laisse une marque en aval, pas à partir de la propre expression du régulateur. La différence entre les deux est la résolution. L’activité des voies avec PROGENy résume le transcriptome en une quatorzaine de voies de signalisation larges — JAK-STAT, NF-κB, MAPK, etc. L’activité des TF va un niveau plus fin : au lieu de « la voie JAK-STAT est active », elle nomme quels facteurs de transcription — STAT1, STAT2, IRF9 — sont actifs, parmi des centaines de régulateurs. Les voies vous disent le système qui signale ; les TF vous disent les interrupteurs précis que l’on actionne.

Les trois appartiennent à la boîte à outils de l’analyse fonctionnelle, et aucun ne remplace les autres. Utilisez-les ensemble : notez les programmes choisis dont vous avez les listes de gènes, lisez l’activité des voies pour les systèmes de signalisation, et inférez l’activité des TF quand vous voulez nommer les régulateurs derrière la réponse.

Les données : des PBMC stimulés à l’interféron avec une vérité terrain intégrée

Le fichier commité ifnb_subset.rds est une tranche équilibrée du benchmark IFN-β de Kang : une matrice de comptage brute de 13 565 gènes répartis sur 3 000 cellules, plus une table de métadonnées. La colonne stim enregistre si chaque cellule était une cellule CTRL (contrôle) ou STIM (stimulée à l’IFN-β) — 1 500 de chaque — et seurat_annotations contient les 13 types cellulaires déjà appelés pour nous. Nous gardons ces étiquettes en réserve et n’utilisons que le contraste stim pour valider l’activité des TF que nous inférons.

library(Seurat)

d <- readRDS("_data/ifnb_subset.rds")
obj <- CreateSeuratObject(counts = d$counts, meta.data = d$meta)
obj <- NormalizeData(obj, verbose = FALSE)

dim(obj)              # genes x cells
[1] 13565  3000
table(obj$stim)       # the control / IFN-beta contrast: our ground truth

CTRL STIM 
1500 1500 

La log-normalisation (NormalizeData) est l’unique étape de prétraitement que suppose la méthode : l’activité est inférée à partir de l’expression normalisée, pas des comptages bruts. Chaque bloc ci-dessous reconstruit à partir exactement de ce point, de sorte que vous pouvez copier n’importe lequel d’entre eux et l’exécuter de façon autonome.

DoRothEA : le réseau de régulons

DoRothEA (Discriminant Regulon Expression Analysis) est une collection soigneusement choisie de régulons — pour chaque facteur de transcription, l’ensemble des gènes cibles qu’il régule (Garcia-Alonso et al., 2019). Chaque arête TF-vers-cible porte deux choses : un niveau de confiance de A (le plus élevé — soutenu par une littérature choisie et de multiples faisceaux de preuves) jusqu’à E (le plus bas — prédit seulement), et un mode de régulation (mor), un poids signé qui vaut +1 quand le TF active la cible et −1 quand il la réprime. Les signes comptent : un TF actif pousse ses cibles activées vers le haut et ses cibles réprimées vers le bas, et le modèle utilise les deux directions.

Les régulons sont livrés comme données intégrées au package, on les lit donc directement — aucun téléchargement. La pratique standard consiste à conserver les niveaux de haute confiance A, B et C et à écarter les prédictions D/E plus faibles.

library(dorothea)

data("dorothea_hs", package = "dorothea")   # built-in human regulons (offline)
net <- dorothea_hs[dorothea_hs$confidence %in% c("A", "B", "C"), ]

colnames(net)                     # tf, confidence, target, mor
[1] "tf"         "confidence" "target"     "mor"       
nrow(net)                         # number of regulon edges kept
[1] 13223
length(unique(net$tf))            # number of transcription factors
[1] 271
head(net)
# A tibble: 6 × 4
  tf    confidence target   mor
  <chr> <chr>      <chr>  <dbl>
1 AHR   C          CYP1A1     1
2 AHR   C          CYP1A2     1
3 AHR   C          CYP1B1     1
4 AHR   C          FOS        1
5 AHR   C          MYC        1
6 AHR   C          UGT1A6     1

Conserver les niveaux A/B/C donne 13 223 arêtes de régulons à travers 271 facteurs de transcription — le réseau que decoupleR va noter. Chaque ligne est une arête (TF, cible, poids signé) ; le régulon d’un TF, c’est toutes ses lignes.

NoteDoRothEA ici, CollecTRI pour le travail réel

Nous utilisons DoRothEA parce qu’il est livré comme données de package hors ligne (dorothea::dorothea_hs), de sorte que les nombres de cette page sont déterministes et stables au bit près d’un rendu à l’autre. Pour de nouvelles analyses, le laboratoire Saez-Rodriguez recommande désormais CollecTRI — une ressource de régulons successeur plus récente et plus complète, couvrant bien plus de facteurs de transcription (Müller-Dott et al., 2023). Elle est récupérée avec decoupleR::get_collectri(), qui tire depuis le service web OmnipathR par le réseau :

# Illustrative only — needs OmnipathR + a network connection, so it is NOT run here
# (a live fetch would make this page non-reproducible). Use it in a real analysis.
library(decoupleR)
net <- get_collectri(organism = "human", split_complexes = FALSE)

Parce que cet appel est dépendant du réseau (et que sa ressource distante peut changer), il n’est pas reproductible dans une leçon figée — on enseigne donc avec le DoRothEA empaqueté et on montre l’appel CollecTRI pour référence. Dans une analyse réelle, préférez CollecTRI ; le reste du workflow est identique.

decoupleR : inférer l’activité des TF par cellule

decoupleR est un ensemble de méthodes qui infèrent des activités biologiques à partir de données omiques au sein d’un même cadre (Badia-i-Mompel et al., 2022). Étant donné une matrice d’expression et un réseau de sources (ici, des facteurs de transcription) et de leurs cibles signées, il renvoie un score d’activité pour chaque source dans chaque cellule.

La méthode recommandée pour l’activité des TF est run_ulm — un modèle linéaire univarié (ULM). Pour chaque cellule et chaque TF, elle ajuste une régression linéaire : l’expression génique de la cellule est la réponse, et les poids cibles signés du TF (le mode de régulation) sont le prédicteur. La valeur t de la pente ajustée devient le score d’activité de ce TF dans cette cellule — grande et positive quand les cibles activées du TF sont hautes et ses cibles réprimées basses, exactement l’empreinte d’un régulateur actif.

library(Seurat)
library(decoupleR)
library(dorothea)

d <- readRDS("_data/ifnb_subset.rds")
obj <- CreateSeuratObject(counts = d$counts, meta.data = d$meta)
obj <- NormalizeData(obj, verbose = FALSE)
mat <- as.matrix(GetAssayData(obj, layer = "data"))   # genes x cells, normalized

data("dorothea_hs", package = "dorothea")
net <- dorothea_hs[dorothea_hs$confidence %in% c("A", "B", "C"), ]

set.seed(42)
acts <- run_ulm(mat, net, .source = "tf", .target = "target", .mor = "mor", minsize = 5)
acts <- acts[acts$statistic == "ulm", ]   # keep the ULM score

head(acts)          # long: one row per TF (source) x cell (condition)
# A tibble: 6 × 5
  statistic source condition          score p_value
  <chr>     <chr>  <chr>              <dbl>   <dbl>
1 ulm       AHR    AAACATACCAGAAA.1 -0.0718   0.943
2 ulm       AHR    AAACATACCCGTAA.1 -1.17     0.240
3 ulm       AHR    AAACATACCCTCGT.1 -1.33     0.183
4 ulm       AHR    AAACATACCTCGCT.1 -1.37     0.171
5 ulm       AHR    AAACATACTCAGGT.1 -0.476    0.634
6 ulm       AHR    AAACATACTGCTGA.1 -0.449    0.653

La sortie est une table longue : pour chaque cellule (la colonne condition contient le code-barres de la cellule) et chaque TF (la colonne source), un score — l’activité de ce TF dans cette cellule. L’argument minsize = 5 écarte tout TF dont moins de cinq cibles sont présentes dans les données, de sorte qu’un score n’est jamais construit sur une poignée de gènes. À partir de là, toute l’analyse consiste à agréger et tracer ce seul score.

Validation : les facteurs de transcription de l’interféron explosent dans les cellules stimulées

Le test de l’approche, c’est la vérité terrain. L’IFN-β active le complexe ISGF3 (STAT1, STAT2, IRF9) et la famille IRF, donc l’activité de ces TF doit séparer les conditions. Moyennez l’activité de chaque TF au sein des cellules contrôle et stimulées, classez par la différence, et tracez les facteurs de transcription qui bougent le plus.

library(Seurat)
library(decoupleR)
library(dorothea)
library(ggplot2)

d <- readRDS("_data/ifnb_subset.rds")
obj <- CreateSeuratObject(counts = d$counts, meta.data = d$meta)
obj <- NormalizeData(obj, verbose = FALSE)
mat <- as.matrix(GetAssayData(obj, layer = "data"))
data("dorothea_hs", package = "dorothea")
net <- dorothea_hs[dorothea_hs$confidence %in% c("A", "B", "C"), ]

set.seed(42)
acts <- run_ulm(mat, net, .source = "tf", .target = "target", .mor = "mor", minsize = 5)
acts <- acts[acts$statistic == "ulm", ]
acts$stim <- obj$stim[match(acts$condition, colnames(obj))]

# Mean activity per TF per condition, then the top movers by STIM - CTRL (base R)
agg  <- aggregate(score ~ source + stim, data = acts, FUN = mean)
wide <- reshape(agg, idvar = "source", timevar = "stim", direction = "wide")
colnames(wide) <- c("tf", "CTRL", "STIM")
wide$diff <- wide$STIM - wide$CTRL
top <- head(wide[order(-wide$diff), ], 15)

# Long form for a grouped barplot
plt <- data.frame(tf    = rep(top$tf, 2),
                  stim  = rep(c("CTRL", "STIM"), each = nrow(top)),
                  score = c(top$CTRL, top$STIM))
plt$tf <- factor(plt$tf, levels = rev(top$tf))

ggplot(plt, aes(x = tf, y = score, fill = stim)) +
  geom_col(position = position_dodge(width = 0.7), width = 0.65) +
  coord_flip() +
  scale_fill_manual(values = c(CTRL = "#3a86d4", STIM = "#d1495b")) +
  labs(x = NULL, y = "Mean TF activity (ULM score)", fill = NULL,
       title = "Transcription factors most activated by IFN-β") +
  theme_minimal(base_size = 12) +
  theme(legend.position = "top")

A horizontal barplot of the fifteen transcription factors whose mean activity rises most between control and IFN-beta-stimulated PBMCs, control (blue) versus stimulated (red) bars. STAT2, IRF9, STAT1 and IRF1 top the list with by far the largest jumps in the stimulated cells; IRF2, NFKB1, FOXO4 and IRF3 follow. The ISGF3 complex (STAT1, STAT2, IRF9) and the interferon-regulatory-factor family dominate, exactly as the IFN-beta ground truth predicts.

L’image est sans ambiguïté. Les facteurs de transcription dont l’activité bondit le plus dans les cellules stimulées sont STAT2, IRF9, STAT1 et IRF1, suivis d’IRF2, NFKB1, FOXO4 et IRF3 — c’est le complexe ISGF3 (STAT1 + STAT2 + IRF9) et la famille des facteurs de régulation de l’interféron, les facteurs de transcription classiques de l’interféron de type I. En lire quelques-uns individuellement rend l’ampleur de l’effet concrète : l’activité STAT2 moyenne va d’environ 0.9 dans les contrôles à 10.0 dans les cellules stimulées ; IRF9 d’environ 0.5 → 9.4 ; STAT1 1.1 → 7.1 ; IRF1 2.0 → 7.2. NFKB1, le maître régulateur inflammatoire, monte plus modestement (3.3 → 5.0) — la stimulation interféron est inflammatoire, donc une hausse de NF-κB est exactement juste. Les régulons ont récupéré les facteurs de transcription précis derrière la réponse interféron, et les ont récupérés à partir des gènes cibles — jamais à partir des propres transcrits des TF, qui bougent à peine.

Voir le facteur de transcription sur la carte

L’activité des TF est une quantité par cellule, elle tombe donc directement sur un UMAP (uniform manifold approximation and projection — la projection en 2-D des cellules). Colorer la carte selon l’activité STAT1 montre la réponse à l’interféron comme une région du tissu qui s’illumine, suivant les cellules stimulées où qu’elles siègent.

set.seed(42)
library(Seurat)
library(decoupleR)
library(dorothea)
library(patchwork)
library(ggplot2)

d <- readRDS("_data/ifnb_subset.rds")
obj <- CreateSeuratObject(counts = d$counts, meta.data = d$meta)
obj <- NormalizeData(obj, verbose = FALSE)
mat <- as.matrix(GetAssayData(obj, layer = "data"))
data("dorothea_hs", package = "dorothea")
net <- dorothea_hs[dorothea_hs$confidence %in% c("A", "B", "C"), ]

acts <- run_ulm(mat, net, .source = "tf", .target = "target", .mor = "mor", minsize = 5)
acts <- acts[acts$statistic == "ulm", ]
s1 <- acts[acts$source == "STAT1", ]
obj$STAT1 <- s1$score[match(colnames(obj), s1$condition)]

# Standard embedding so the score has a map to land on
obj <- FindVariableFeatures(obj, nfeatures = 2000, verbose = FALSE) |>
  ScaleData(verbose = FALSE) |> RunPCA(npcs = 30, verbose = FALSE) |>
  RunUMAP(dims = 1:30, verbose = FALSE)

p1 <- DimPlot(obj, group.by = "stim") + ggtitle("Condition")
p2 <- FeaturePlot(obj, features = "STAT1") +
  scale_color_viridis_c() + ggtitle("STAT1 activity")
p1 + p2

Two side-by-side UMAP embeddings of the 3,000 PBMCs. The left panel colours cells by condition, control versus IFN-beta-stimulated, which separate into two offset clouds. The right panel colours the same cells by their STAT1 transcription-factor activity on a viridis scale: the stimulated cloud is bright yellow (high STAT1 activity) and the control cloud is dark purple (low), so the TF-activity map mirrors the condition map almost exactly.

Les deux panneaux sont presque la même image : la région que l’UMAP remplit de cellules stimulées est exactement la région que la carte STAT1 peint en clair. Une activité de facteur de transcription que vous avez inférée à partir de cibles en aval et qui reproduit la condition expérimentale que vous voyez dans la projection — c’est la forme visuelle de la validation.

Où chaque facteur de transcription est actif à travers les types cellulaires

Le diagramme en barres a réduit chaque TF à un seul nombre par condition. L’activité varie aussi entre les types cellulaires, et une heatmap des principaux TF de l’interféron sur les 13 types cellulaires annotés montre le paysage. Pour comparer les profils entre types cellulaires sur une échelle commune, on met chaque TF (ligne) à l’échelle en un score z à travers les types cellulaires — de sorte que chaque ligne montre , relativement, ce facteur de transcription est le plus actif.

library(Seurat)
library(decoupleR)
library(dorothea)
library(ggplot2)

d <- readRDS("_data/ifnb_subset.rds")
obj <- CreateSeuratObject(counts = d$counts, meta.data = d$meta)
obj <- NormalizeData(obj, verbose = FALSE)
mat <- as.matrix(GetAssayData(obj, layer = "data"))
data("dorothea_hs", package = "dorothea")
net <- dorothea_hs[dorothea_hs$confidence %in% c("A", "B", "C"), ]

acts <- run_ulm(mat, net, .source = "tf", .target = "target", .mor = "mor", minsize = 5)
acts <- acts[acts$statistic == "ulm", ]
acts$ct <- obj$seurat_annotations[match(acts$condition, colnames(obj))]

# The interferon transcription factors, mean activity per TF per cell type, row z-scored
tfs <- c("STAT2", "IRF9", "STAT1", "IRF1", "IRF2", "NFKB1", "FOXO4", "IRF3")
sub <- acts[acts$source %in% tfs, ]
mn  <- tapply(sub$score, list(sub$source, sub$ct), mean)
z   <- t(scale(t(mn)))    # row-wise z-score across cell types

df <- data.frame(tf        = rownames(z)[row(z)],
                 cell_type = colnames(z)[col(z)],
                 z         = as.vector(z))
df$tf <- factor(df$tf, levels = rev(tfs))
ggplot(df, aes(cell_type, tf, fill = z)) +
  geom_tile(color = "white", linewidth = 0.3) +
  scale_fill_gradient2(low = "#3a86d4", mid = "grey95", high = "#d1495b",
                       midpoint = 0, name = "Row z") +
  labs(x = NULL, y = NULL, title = "Interferon TF activity across cell types (row-scaled)") +
  theme_minimal(base_size = 11) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

A heatmap of eight interferon transcription factors (rows: STAT2, IRF9, STAT1, IRF1, IRF2, NFKB1, FOXO4, IRF3) across 13 annotated PBMC cell types (columns), each row z-scored across cell types on a blue-to-red diverging scale. The interferon-TF rows are reddest (highest relative activity) over the myeloid cell types — CD14 and CD16 monocytes and dendritic cells — showing the interferon response peaks in the myeloid compartment.

Le signal interféron n’est pas réparti uniformément. Les facteurs de transcription de l’interféron culminent dans le compartiment myéloïde — les monocytes CD14 et CD16 et les cellules dendritiques — les répondeurs professionnels qui montent le programme interféron le plus fort. Un seul nombre au niveau de la condition aurait masqué cela ; les scores par cellule vous laissent voir dans quelles cellules chaque facteur de transcription est le plus actif.

Méthodes, honnêteté et reproductibilité

Quelques points à garder clairs pour utiliser ces outils avec exactitude et reproductibilité.

run_ulm est l’une de plusieurs méthodes de decoupleR. Pour l’activité des TF, le modèle linéaire univarié est le choix par défaut documenté : il note chaque facteur de transcription sur son propre régulon, ce qui est le bon modèle quand les régulons se chevauchent peu. decoupleR offre aussi run_mlm (un modèle multivarié qui ajuste toutes les sources conjointement, le choix par défaut pour une ressource dense comme PROGENy), run_wsum / run_wmean (sommes / moyennes pondérées), et decouple() / run_consensus pour combiner plusieurs méthodes. Pour l’activité des TF avec DoRothEA/CollecTRI, run_ulm est le choix par défaut sensé.

L’activité d’un TF n’est pas sa propre expression — c’est tout l’enjeu. Ne vérifiez pas la cohérence d’un score d’activité de TF par rapport au propre transcrit du TF. L’ARNm de STAT1 est presque plat entre les conditions alors que son activité inférée est multipliée par sept, parce que l’activité est lue à partir des cibles du régulon, pas de STAT1 lui-même. Si vous tracez le propre gène d’un TF et voyez peu de changement, c’est attendu, pas un bug.

DoRothEA ici, CollecTRI pour le travail réel. Comme noté plus haut, dorothea::dorothea_hs est hors ligne et déterministe, tandis que decoupleR::get_collectri() récupère la ressource plus récente depuis le service web OmnipathR (dépendant du réseau, non reproductible). Les résultats de cette page ont été produits avec le DoRothEA empaqueté et sont stables au bit près d’un rendu à l’autre ; pour de nouvelles analyses, CollecTRI est la ressource la plus complète et recommandée.

Le package R decoupleR est désormais l’interface héritée. Depuis 2025, le laboratoire Saez-Rodriguez a unifié le développement sur le decoupler 2.0 de Python, une réimplémentation plus rapide et plus économe en mémoire qui fait partie de l’écosystème single-cell scverse ; le package R est décrit comme la version héritée et est en maintenance. Le package R fonctionne toujours et est enseigné ici parce qu’il s’insère directement dans un workflow R fondé sur Seurat — mais si vous construisez de nouveaux pipelines, surtout en Python/scanpy, c’est la direction que prend le développement. Les concepts — régulons, inférence par empreinte, ULM/MLM — sont identiques dans les deux.

Quand utiliser l’activité des TF vs l’activité des voies vs la notation de signatures

Les trois méthodes d’inférence fonctionnelle répondent à des questions différentes ; choisissez selon ce que vous voulez nommer.

  • Ayez recours à DoRothEA/CollecTRI + decoupleR quand la question est quel facteur de transcription — les régulateurs précis qui pilotent un programme, parmi des centaines de TF, lus à partir de leurs régulons. C’est la plus fine des trois : elle nomme STAT1 et IRF9, pas seulement « la voie interféron ».
  • Ayez recours à l’activité des voies (PROGENy + decoupleR) quand la question est quelle voie de signalisation — un résumé large, à ~14 voies, des systèmes de signalisation qui sont actifs. Plus grossier que l’activité des TF, mais un aperçu compact.
  • Ayez recours à la notation de signatures (AUCell, UCell) quand vous avez un ensemble de gènes choisi — un lignage, un état cellulaire, un module personnalisé — dont vous voulez quantifier l’appartenance par cellule.

En pratique, elles se superposent : notez vos signatures choisies, lisez les empreintes de voies pour les systèmes de signalisation, et inférez l’activité des TF pour nommer les régulateurs derrière la réponse. Les trois valident de la même façon — par rapport à un contraste connu, comme nous l’avons fait ici avec la vérité terrain IFN-β.

Problèmes courants

get_collectri() ou get_dorothea() bloque ou renvoie une erreur au sujet d’OmnipathR / d’une connexion réseau. Ces fonctions de commodité téléchargent les régulons depuis le service web OmnipathR, qui nécessite internet et peut se figer derrière un pare-feu — et sa ressource distante peut changer, donc les résultats ne sont pas reproductibles. Pour une leçon reproductible, utilisez plutôt les régulons empaquetés hors ligne : data("dorothea_hs", package = "dorothea"), puis filtrez sur confidence %in% c("A","B","C"). C’est hors ligne, déterministe et identique en structure à ce que decoupleR attend. (Pour le travail réel où la reproductibilité est gérée séparément, CollecTRI est la ressource la plus complète.)

Le propre gène d’un facteur de transcription paraît plat mais son activité inférée est élevée. Ce n’est pas un bug — c’est la raison même d’inférer l’activité. Un TF est fréquemment régulé par phosphorylation ou translocation nucléaire, pas par transcription, de sorte que son ARNm bouge à peine alors qu’il active des centaines de cibles. Le score d’activité lit ces cibles (le régulon), il peut donc être élevé même quand le propre transcrit du TF est inchangé. Ne validez jamais un score de TF par rapport à la propre expression du TF.

Un facteur de transcription est écarté, ou son score est construit sur très peu de gènes. L’argument minsize = 5 écarte tout TF dont le régulon a moins de cinq cibles présentes dans votre matrice. Si des TF que vous attendez sont absents, vérifiez que vos noms de features correspondent aux symboles de gènes des régulons (symboles vs identifiants Ensembl, capitalisation d’espèce) — une incohérence de nomenclature affame silencieusement le régulon. Inclure le niveau de confiance C (comme nous le faisons) élargit déjà la couverture ; ne baissez minsize que si vous acceptez qu’un score sur très peu de cibles est bruité.

Foire aux questions

Les deux sont des modèles d’empreinte — ils infèrent l’activité d’un régulateur à partir des gènes qu’il affecte, pas de sa propre expression — mais à des résolutions différentes. L’activité des voies avec PROGENy résume le transcriptome en environ 14 voies de signalisation larges (JAK-STAT, NF-κB, …). L’activité des TF avec DoRothEA/CollecTRI va plus fin : elle nomme les facteurs de transcription individuels — STAT1, STAT2, IRF9 — parmi des centaines de régulateurs. Les voies vous disent le système qui signale ; les TF vous disent les interrupteurs précis que l’on actionne.

Pour de nouvelles analyses, CollecTRI — c’est le successeur plus récent et plus complet, couvrant bien plus de facteurs de transcription (Müller-Dott et al., 2023), récupéré avec decoupleR::get_collectri(). DoRothEA (Garcia-Alonso et al., 2019) est la ressource plus ancienne avec des niveaux de confiance A–E ; elle est utilisée dans cette leçon parce qu’elle est livrée comme données de package hors ligne, ce qui garde les nombres rendus reproductibles. get_collectri() récupère par le réseau (OmnipathR), il n’est donc pas reproductible dans un document figé — mais dans le travail réel, préférez CollecTRI.

Parce que l’ARNm d’un TF est un mauvais indicateur de son activité. Les facteurs de transcription sont couramment activés par phosphorylation ou translocation nucléaire, pas par transcription, de sorte que le propre gène du TF peut rester plat alors qu’il pilote des centaines de cibles. Lire le régulon — l’expression coordonnée des gènes cibles que le TF contrôle — récupère l’activité que le propre transcrit du TF cache. Dans cette leçon, l’activité de STAT1 est multipliée par sept entre les conditions alors que son propre ARNm bouge à peine.

Chaque arête de régulon DoRothEA est notée de A (confiance la plus élevée — choisie, multiples faisceaux de preuves) à E (la plus basse — prédite seulement), reflétant à quel point le lien TF-vers-cible est bien soutenu. La pratique standard consiste à conserver les niveaux de haute confiance A, B et C et à écarter D/E, ce qui échange un peu de couverture contre des régulons bien plus propres. C’est le filtre confidence %in% c("A","B","C") utilisé ici — il donne 13 223 arêtes à travers 271 facteurs de transcription.

run_ulm (modèle linéaire univarié) note chaque facteur de transcription sur son propre régulon, un à la fois, et est le choix par défaut documenté pour l’activité des TF avec DoRothEA/CollecTRI. run_mlm (multivarié) ajuste toutes les sources conjointement, de sorte que le score d’une source est ajusté pour les cibles qu’elle partage avec d’autres — le choix par défaut sensé pour une ressource dense comme PROGENy, mais moins adapté à un grand réseau de régulons parcimonieux. decoupleR offre aussi run_wsum, run_wmean et un consensus sur les méthodes.

Testez votre compréhension

En utilisant ifnb_subset.rds et les régulons DoRothEA A/B/C, inférez l’activité des TF avec run_ulm, puis trouvez quel type cellulaire annoté a la plus forte activité STAT2 moyenne dans les cellules stimulées uniquement. La réponse interféron se concentre-t-elle là où vous vous y attendriez — le compartiment myéloïde ?

Après run_ulm, filtrez la sortie sur statistic == "ulm" et source == "STAT2". Mappez la condition de chaque cellule (le code-barres) vers obj$stim et obj$seurat_annotations, gardez uniquement les cellules STIM, puis tapply(score, cell_type, mean) et triez par ordre décroissant.

library(Seurat); library(decoupleR); library(dorothea)
d <- readRDS("_data/ifnb_subset.rds")
obj <- CreateSeuratObject(counts = d$counts, meta.data = d$meta)
obj <- NormalizeData(obj, verbose = FALSE)
mat <- as.matrix(GetAssayData(obj, layer = "data"))
data("dorothea_hs", package = "dorothea")
net <- dorothea_hs[dorothea_hs$confidence %in% c("A", "B", "C"), ]

set.seed(42)
acts <- run_ulm(mat, net, .source = "tf", .target = "target", .mor = "mor", minsize = 5)
acts <- acts[acts$statistic == "ulm", ]

s2 <- acts[acts$source == "STAT2", ]
s2$stim <- obj$stim[match(s2$condition, colnames(obj))]
s2$ct   <- obj$seurat_annotations[match(s2$condition, colnames(obj))]

# STAT2 activity by cell type, stimulated cells only
sort(tapply(s2$score[s2$stim == "STIM"], s2$ct[s2$stim == "STIM"], mean), decreasing = TRUE)

L’activité STAT2 dans les cellules stimulées est la plus élevée dans les types cellulaires myéloïdes — les monocytes CD14 et CD16 et les cellules dendritiques — les répondeurs professionnels à l’interféron, avec les sous-ensembles lymphoïdes plus bas. C’est exactement là où un programme interféron de type I devrait culminer, et c’est une seconde confirmation, au niveau du type cellulaire (au-delà du contraste de condition), que l’activité des TF inférée suit une biologie réelle.

A. Le score d’activité doit être faux — l’activité d’un TF devrait suivre sa propre expression. B. L’activité des TF est inférée à partir du régulon du TF — l’expression coordonnée des gènes cibles qu’il régule — pas à partir du propre transcrit du TF ; l’interféron active STAT1 de façon post-transcriptionnelle, donc ses cibles montent (et son activité avec elles) même si le propre ARNm de STAT1 est presque plat. C. Le score n’est élevé que parce que les données n’ont pas été normalisées.

B. C’est exactement ce que l’inférence fondée sur les régulons est conçue pour capter. Les facteurs de transcription sont fréquemment activés par phosphorylation ou translocation nucléaire plutôt que par transcription, de sorte que le propre ARNm du TF est un mauvais indicateur de son activité. run_ulm lit l’activité de STAT1 à partir de son régulon — les gènes cibles qui répondent quand STAT1 est actif — qui montent fortement sous IFN-β, de sorte que l’activité inférée bondit même si le propre transcrit de STAT1 bouge à peine. (La réponse A a la logique à l’envers ; C est fausse — le pipeline normalise avec NormalizeData et le contraste est réel.)

Conclusion

La notation de signatures demande si une cellule exprime un ensemble de gènes ; l’activité des voies demande si une voie de signalisation est active ; l’activité des facteurs de transcription demande quel régulateur pilote le programme — inférée à partir du régulon du TF, les gènes cibles qu’il contrôle, pas à partir du propre transcrit du TF. DoRothEA fournit les régulons et le run_ulm de decoupleR les note dans chaque cellule. Sur le benchmark IFN-β, la méthode a récupéré la vérité terrain proprement : les facteurs de transcription qui ont le plus bondi étaient STAT2, IRF9, STAT1 et IRF1 — le complexe ISGF3 et la famille IRF, les TF canoniques de l’interféron de type I — avec l’activité lue à partir des seuls gènes cibles pendant que les propres transcrits des TF restaient plats, et les cellules myéloïdes pilotant la réponse. Conservez les régulons de haute confiance (niveaux A/B/C), validez par rapport à un contraste connu, préférez CollecTRI pour le travail réel et DoRothEA pour une sortie reproductible. L’activité des TF complète la trilogie de l’inférence fonctionnelle aux côtés de l’activité des voies et de la notation de signatures — trois niveaux complémentaires, d’un ensemble de gènes choisi aux régulateurs individuels que les cellules activent.

Leçons associées

🟢 Avec un agent IA

Demandez à Prova « comment inférer l’activité des facteurs de transcription par cellule sur mon propre objet Seurat avec les régulons DoRothEA et decoupleR, et la valider par rapport à un contraste connu ? » — elle répond avec du code R que vous pouvez exécuter sur vos propres données : lire les régulons, filtrer sur les niveaux de haute confiance, appeler run_ulm(), ajouter les scores à votre objet, et les vérifier par rapport à une condition que vous connaissez déjà. The runtime is the judge. Demander à Prova →

Cette page vous a-t-elle été utile ?

Recevez les nouvelles leçons R & Python par e-mail

Pratique, reproductible, sans spam. Désinscription à tout moment.

Double opt-in. Nous ne partageons jamais votre e-mail.

Partager cette pageXLinkedInRedditHN
Note

Cette leçon est reproductible : chaque figure et chaque nombre ont été produits par le code montré, rendu hors ligne dans l’image Docker datanovia/quarto-bioinformatics — copiez n’importe quel bloc et exécutez-le pour les reproduire. The runtime is the judge.

References

  • Garcia-Alonso, L., Holland, C. H., Ibrahim, M. M., Türei, D., & Saez-Rodriguez, J. (2019). Benchmark and integration of resources for the estimation of human transcription factor activities — introduit les régulons DoRothEA. Genome Research, 29(8), 1363–1375. https://doi.org/10.1101/gr.240663.118
  • Müller-Dott, S., Tsirvouli, E., Vazquez, M., Ramirez Flores, R. O., Badia-i-Mompel, P., Fallegger, R., Türei, D., Lægreid, A., & Saez-Rodriguez, J. (2023). Expanding the coverage of regulons from high-confidence prior knowledge for accurate estimation of transcription factor activities — introduit CollecTRI. Nucleic Acids Research, 51(20), 10934–10949. https://doi.org/10.1093/nar/gkad841
  • Badia-i-Mompel, P., Vélez Santiago, J., Braunger, J., Geiss, C., Dimitrov, D., Müller-Dott, S., Taus, P., Dugourd, A., Holland, C. H., Ramirez Flores, R. O., & Saez-Rodriguez, J. (2022). decoupleR: ensemble of computational methods to infer biological activities from omics data. Bioinformatics Advances, 2(1), vbac016. https://doi.org/10.1093/bioadv/vbac016
  • Kang, H. M., et al. (2018). Multiplexed droplet single-cell RNA-sequencing using natural genetic variation — la source du jeu de données PBMC stimulé à l’IFN-β. Nature Biotechnology, 36, 89–94. https://doi.org/10.1038/nbt.4042

Réutilisation

Citation

BibTeX
@online{2026,
  author = {},
  title = {Activité des facteurs de transcription par cellule en R avec
    decoupleR \& DoRothEA},
  date = {2026-07-04},
  url = {https://www.datanovia.com/learn/bioinformatics/single-cell/scrnaseq-tf-activity-decoupler.html},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
“Activité des facteurs de transcription par cellule en R avec decoupleR & DoRothEA.” 2026. July 4. https://www.datanovia.com/learn/bioinformatics/single-cell/scrnaseq-tf-activity-decoupler.html.