Cross-Condition Analysis#

import plotnine as pn
import scanpy as sc
import matplotlib.pyplot as plt
from partipy.datasets import load_ncM_lupus_data
import decoupler as dc

import partipy as pt

In this vignette, we focus on non-classical monocytes from [PGS+22].

In this study, PBMCs from healthy subjects and from SLE (Systemic lupus erythematosus) patients were analyzed using scRNA-seq.

Here, we use the data to highlight how archetypal analysis can be used in the cross-condition setting. We identify one archetype that is enriched in the disease context, and characterize this archetype.

Load Data#

adata = load_ncM_lupus_data()
adata
AnnData object with n_obs × n_vars = 47819 × 30867
    obs: 'library_uuid', 'author_cell_type', 'sample_uuid', 'disease_state', 'donor_id', 'Processing_Cohort', 'ct_cov', 'ind_cov', 'cell_type', 'assay', 'disease', 'sex', 'self_reported_ethnicity', 'development_stage', 'observation_joinid', 'Status'
    var: 'feature_is_filtered', 'feature_reference', 'feature_biotype', 'feature_length', 'feature_type'

Check the number of cells we have per condition:

adata.obs.value_counts("Status")
Status
Managed    31268
Healthy    15091
Flare       1460
Name: count, dtype: int64

Quality Control#

We follow the Scanpy tutorial to perform quality control on the dataset.

First, we compute the proportion of counts originating from mitochondrial, ribosomal, and hemoglobin genes:

adata.var["mt"] = adata.var_names.str.startswith("MT-")
adata.var["ribo"] = adata.var_names.str.startswith(("RPS", "RPL"))
adata.var["hb"] = adata.var_names.str.contains(("^HB[^(P)]"))
sc.pp.calculate_qc_metrics(
    adata, qc_vars=["mt", "ribo", "hb"], inplace=True, percent_top=[20], log1p=True
)

We can now examine key quality control metrics, including:

  • The number of genes expressed per cell

  • The total counts per cell

  • The percentage of counts originating from mitochondrial genes

sc.pl.violin(
    adata,
    ["total_counts", "n_genes_by_counts", "pct_counts_mt"],
    jitter=0.4,
    multi_panel=True,
)
../_images/b61d33f758ad5fd8bde49dc732f9a0e1c752812f0f99c41bac20d859fa5e8dd8.png

To remove low-quality data, we filter out cells with fewer than 100 detected genes and genes that are present in fewer than 3 cells. This ensures that only high-quality cells and genes are retained for downstream analysis.

print(f"Number of cells before filtering: {adata.n_obs} \nNumber of genes before filtering: {adata.n_vars}")
sc.pp.filter_cells(adata, min_genes=100)
sc.pp.filter_genes(adata, min_cells=3)
print(f"Number of cells after filtering of low quality cells: {adata.n_obs} \nNumber of genes after filtering of low quality genes: {adata.n_vars}")
Number of cells before filtering: 47819 
Number of genes before filtering: 30867
Number of cells after filtering of low quality cells: 47819 
Number of genes after filtering of low quality genes: 18496

Normalization and feature selection#

To ensure comparability across cells, we normalize the data to the median total counts per cell and apply a logarithmic transformation:

sc.pp.normalize_total(adata)
sc.pp.log1p(adata)

Next, we identify highly variable genes, which are key for downstream analysis. We also visualize them to assess their distribution:

sc.pp.highly_variable_genes(adata)
sc.pl.highly_variable_genes(adata)
../_images/a638ab304fa44651c436e6a25af7f6ccb451038d6d9205f89aed84f39c7d9c91.png

For the downstream enrichment analysis, we standardize the data by scaling gene expression values:

adata.layers["z_scaled"]= sc.pp.scale(adata.X, max_value=10, copy=True)

Dimension Reduction#

We compute a Principal Component Analysis (PCA) using only highly variable genes to reduce nosie and extract the most meaningful dimensions based on explained variance.

sc.pp.pca(adata, mask_var="highly_variable")
sc.pl.pca_scatter(adata, color="Status")
../_images/14b34cc716162080c81632beb6f4196af2771a2d5b06828225b6780104248642.png

To determine the optimal number of principal components (PCs) to retain, we inspect their contribution to the total variance:

sc.pl.pca_variance_ratio(adata, n_pcs=50)
../_images/9349dbbaa690cfb5861bfde6c525ff8205de3ad8805ece677499e4d7f827be4e.png

Based on this, we select 7 PCs, as the variance explained plateaus beyond this point. For ease of use in downstream analysis, we store the selected number of dimensions of the PCA in adata.uns[“aa_config”] with the following function:

pt.set_obsm(adata=adata, obsm_key="X_pca", n_dimensions=7)

Number of Archetypes#

Next, we need to determine the optimal number of archetypes in our data—essentially, the number of vertices in the polyhedron.

We first assess how much variance is explained for different numbers of archetypes.

The function var_explained_aa() takes the 7D PCA data and calculates the explained variance for a range of archetypes (min_k to max_a). It computes:

  • The variance explained by each archetype.

  • The additional variance explained by each successive archetype.

  • The distance from the projected point to the line of the elbow plot.

  • An information criteria (IC)

pt.compute_selection_metrics(adata=adata, n_archetypes_list=range(2,10))

The results are stored in:

pt.summarize_aa_metrics(adata)
k n_archetypes n_restarts seed varexpl IC RSS
0 2 2 5 42 0.345126 44101.212524 219199.375000
1 3 3 5 42 0.512452 38643.200165 163190.234375
2 4 4 5 42 0.625245 38706.799687 125437.351562
3 5 5 5 42 0.713459 42202.905868 95911.164062
4 6 6 5 42 0.779241 45237.676820 73892.960938
5 7 7 5 42 0.835723 48805.377194 54987.296875
6 8 8 5 42 0.868597 52748.205372 43983.996094
7 9 9 5 42 0.884990 57209.086866 38496.464844

We visualize the explained variance for different models:

pt.plot_var_explained(adata)

In this plot, the grey line connects the first and last variance explained (EV) values, helping to identify the “elbow” of the black curve.

Visualize the trend of the IC:

pt.plot_IC(adata)

This analysis suggests that the best choice is 4-6 archetypes. We decide to use 4 archetypes, as later analyses show that the 5th archetype introduces no new tasks.

n_archetypes = 4

To validate the archetype stability, we apply bootstrapping. We sample the data 25 times and run Archetypal Analysis (AA) on each sample.

pt.compute_bootstrap_variance(adata=adata, n_bootstrap=50, n_archetypes_list=n_archetypes)

The positions of the archetypes and the mean variance per archetype and across all bootstrapped samples can be accessed using pt.get_aa_bootstrap

pt.get_aa_bootstrap(adata, n_archetypes=n_archetypes)
X_pca_0 X_pca_1 X_pca_2 X_pca_3 X_pca_4 X_pca_5 X_pca_6 archetype iter reference mean_variance variance_per_archetype
0 -4.816427 -3.540382 0.685227 -0.309495 0.276425 0.018469 0.135509 0 1 False 0.822806 0.314052
1 0.600345 3.903207 3.580197 -1.339453 0.443354 -0.066739 -0.171309 1 1 False 0.822806 1.289679
2 -1.430764 3.333933 -3.710526 1.043123 -0.464882 0.049811 -0.021669 2 1 False 0.822806 1.267447
3 6.307580 -2.459274 -0.703617 0.508641 -0.270054 -0.187655 0.121409 3 1 False 0.822806 0.420045
0 -3.734222 -3.449724 -1.146636 -1.181680 0.387082 0.298474 -0.082064 0 2 False 0.822806 0.314052
... ... ... ... ... ... ... ... ... ... ... ... ...
3 5.096452 -2.411780 2.652799 0.736679 0.016161 -0.178691 0.226363 3 50 False 0.822806 0.420045
0 -4.013512 -3.654292 -1.208841 -0.551198 0.161331 0.218104 -0.124733 0 0 True 0.822806 0.314052
1 -3.962077 2.977677 3.858459 1.793481 -0.317860 -0.247827 0.572696 1 0 True 0.822806 1.289679
2 1.994150 3.965207 -3.145393 -1.469313 0.277546 -0.147325 -0.481090 2 0 True 0.822806 1.267447
3 6.057837 -2.123687 1.216479 0.570489 -0.240843 -0.104882 0.146785 3 0 True 0.822806 0.420045

204 rows × 12 columns

We visualize the bootstrapping results to show that the archetypes are mostly stable:

pt.plot_bootstrap_2D(adata, show_contours=True, result_filters={"n_archetypes": 4})

Archetype Analysis and Visualization of the Archetypes#

Now that we’ve determined the number of archetypes, we can investigate the four archetypes in more detail. The coordinates of the archetypes are given in

pt.get_aa_result(adata, n_archetypes=4)["Z"]
array([[-4.0135117 , -3.6542923 , -1.2088412 , -0.5511984 ,  0.16133077,
         0.21810366, -0.1247327 ],
       [-3.9620771 ,  2.977677  ,  3.8584588 ,  1.793481  , -0.31786036,
        -0.24782737,  0.57269555],
       [ 1.9941503 ,  3.9652069 , -3.1453931 , -1.4693129 ,  0.2775457 ,
        -0.1473254 , -0.4810897 ],
       [ 6.0578375 , -2.1236866 ,  1.2164787 ,  0.570489  , -0.24084304,
        -0.10488223,  0.14678527]], dtype=float32)

The RSS is also saved into “AA_results”. We can manually check for the convergence as follows:

plt.plot(pt.get_aa_result(adata, n_archetypes=4)["RSS"])
plt.grid()
plt.xlabel("Iteration", y="Residual Sum of Squares (RSS)")
plt.ylabel("Residual Sum of Squares (RSS)")
plt.yscale("log")
plt.show()
../_images/9ca8ba0ada613645c5a2b72f52bb61f7bd037943c3bec28ac859b56800bae591.png

We can visualize the polytope in both 2D and 3D with the coloring representing the disease status. Alternatively, we can color the plot based on a gene with distinct expression across archetypes. For example, using the gene IFI27.

To visualize the polytope in 2D use the following function:

pt.plot_archetypes_2D(adata=adata, show_contours=True, color="Status", alpha=0.5, size=0.5, result_filters={"n_archetypes": 4})

Identify representatives#

To assign tasks to the archetypes, we need to identify cells that are representative of each archetype. To do this, we calculate cell weights for each archetype.

First, we calculate the weights for each cell based on its distance from the archetypes with a Radial Basis Function (RBF) kernel. The length scale of the RBF kernel is automatically set as half the median distance from the data centroid to the archetypes. However, this can also be manually adjusted if needed.

pt.compute_archetype_weights(adata=adata, mode="automatic", result_filters={"n_archetypes": 4})
Applied length scale is 3.06.

The resulting cell weights for e.g. archetype 3 are:

arch_idx = 3
adata.obs[f"weights_archetype_{arch_idx}"] = pt.get_aa_cell_weights(adata, n_archetypes=4)[:, arch_idx]
pt.plot_archetypes_2D(adata=adata, color=f"weights_archetype_{arch_idx}", alpha=0.5, result_filters={"n_archetypes": 4})

Enrichment Metadata#

With the weights we can now calculate enrichment of interest. Since we have different cell status associated with healthy and disease, we want first to check the enrichment by the disease state and find our archetypes of interest.

meta_enrichment() calcualtes the enrichment of any specified metadata stored in .obs.

status_enrichment = pt.compute_meta_enrichment(adata=adata, meta_col="Status", result_filters={"n_archetypes": 4})
status_enrichment
Flare Managed Healthy
0 0.234499 0.302162 0.463339
1 0.161296 0.297869 0.540835
2 0.329187 0.355966 0.314847
3 0.557284 0.368842 0.073874

We find ncM with the “Flare” status enriched at an archetype. These results can be visualized in multiple ways:

pt.barplot_meta_enrichment(status_enrichment, meta="Status")
pt.heatmap_meta_enrichment(status_enrichment, meta="Status")
pt.radarplot_meta_enrichment(status_enrichment)
../_images/e6fcbb3d0700a6637f137c9c3969461c4ac33b52b67c7af3815b6f082b5c1c0a.png

Functional Enrichment MSigDB#

Next, we compute the archetypes “gene expression” using the z-scaled gene expression data and cell weights to observe differences in gene expression across the archetypes:

archetype_expression = pt.compute_archetype_expression(adata=adata, layer="z_scaled", result_filters={"n_archetypes": 4})
archetype_expression.iloc[:, 20:25]
TNFRSF4 SDF4 B3GALT6 C1QTNF12 ENSG00000260179.1
0 -257.661762 -373.689194 -209.559462 -382.375408 -347.789129
1 -93.357272 -17.415676 -15.345104 -162.569499 -164.947694
2 -188.547137 158.578746 -103.503072 -253.325774 -237.760378
3 -249.735386 232.526122 -91.851896 -257.211882 -220.419653

For functional enrichment, we use Decoupler with Gene Ontology (GO) biological processes. While other collections can be used, it’s recommended to choose those with less broad categories to avoid non-significant results.

We begin by loading the MSigDB resource and filtering for the GO biological processes collection:

msigdb_raw = dc.op.resource("MSigDB")
msigdb = msigdb_raw[msigdb_raw["collection"]=="go_biological_process"]
msigdb = msigdb[~msigdb.duplicated(["geneset", "genesymbol"])]
msigdb = msigdb.rename(columns={"geneset": "source", "genesymbol": "target"})
msigdb
target collection source
73 A1CF go_biological_process GOBP_MRNA_METABOLIC_PROCESS
78 A1CF go_biological_process GOBP_EMBRYO_IMPLANTATION
84 A1CF go_biological_process GOBP_MACROMOLECULE_CATABOLIC_PROCESS
87 A1CF go_biological_process GOBP_MRNA_MODIFICATION
88 A1CF go_biological_process GOBP_RNA_PROCESSING
... ... ... ...
5522215 ZZZ3 go_biological_process GOBP_PROTEIN_ACYLATION
5522223 ZZZ3 go_biological_process GOBP_HISTONE_H3_ACETYLATION
5522241 ZZZ3 go_biological_process GOBP_REGULATION_OF_MULTICELLULAR_ORGANISMAL_DE...
5522261 ZZZ3 go_biological_process GOBP_MACROMOLECULE_DEACYLATION
5522262 ZZZ3 go_biological_process GOBP_CELL_CYCLE

1026039 rows × 3 columns

Next, we run ULM from decoupler on the pseudobulk data using the filtered MSigDB resource. The resulting estimated enrichment scores and p-values are saved in acts_ulm_est and acts_ulm_est_p:

acts_ulm_est, acts_ulm_est_p = dc.mt.ulm(data=archetype_expression,
                                         net=msigdb)

acts_ulm_est
GOBP_10_FORMYLTETRAHYDROFOLATE_METABOLIC_PROCESS GOBP_2FE_2S_CLUSTER_ASSEMBLY GOBP_2_OXOGLUTARATE_METABOLIC_PROCESS GOBP_3_PHOSPHOADENOSINE_5_PHOSPHOSULFATE_METABOLIC_PROCESS GOBP_3_UTR_MEDIATED_MRNA_DESTABILIZATION GOBP_3_UTR_MEDIATED_MRNA_STABILIZATION GOBP_4FE_4S_CLUSTER_ASSEMBLY GOBP_5S_CLASS_RRNA_TRANSCRIPTION_BY_RNA_POLYMERASE_III GOBP_5_PHOSPHORIBOSE_1_DIPHOSPHATE_METABOLIC_PROCESS GOBP_7_METHYLGUANOSINE_CAP_HYPERMETHYLATION ... GOBP_XENOBIOTIC_TRANSPORT GOBP_XENOBIOTIC_TRANSPORT_ACROSS_BLOOD_BRAIN_BARRIER GOBP_XENOPHAGY GOBP_XMP_METABOLIC_PROCESS GOBP_XYLULOSE_5_PHOSPHATE_METABOLIC_PROCESS GOBP_ZINC_ION_IMPORT_ACROSS_PLASMA_MEMBRANE GOBP_ZINC_ION_IMPORT_INTO_ORGANELLE GOBP_ZINC_ION_TRANSPORT GOBP_ZYMOGEN_ACTIVATION GOBP_ZYMOGEN_INHIBITION
0 0.241079 0.672763 -0.030060 -0.378506 -4.176762 -2.494529 0.958651 0.367429 0.420109 0.827908 ... -0.331340 0.254343 -3.042813 -0.080069 -0.243916 0.345404 0.474443 0.803099 -2.633981 -0.253889
1 -0.203632 -1.988812 -0.867501 -0.684650 4.825518 3.437554 -1.052776 0.514176 0.050987 -2.969620 ... -0.443198 0.131471 1.155966 0.120715 -1.416573 0.605550 0.496199 0.463621 -3.180310 -0.683561
2 0.427570 2.635611 1.640959 0.700003 3.195863 3.441391 1.481129 0.828693 1.670545 2.539954 ... -1.333788 -0.563798 2.112109 1.854099 2.331447 0.442798 0.065135 0.473911 1.780707 0.669558
3 0.143610 1.260025 0.704676 0.509149 0.084102 0.423825 0.779055 0.459744 0.539227 2.436380 ... -0.889441 -0.585189 2.212209 -0.407028 0.648526 -0.093672 0.179846 0.227018 4.025651 1.801857

4 rows × 6910 columns

To identify the top enriched processes for each archetype, we extract the top 20 processes and order them in descending order:

top_processes = pt.extract_enriched_processes(est=acts_ulm_est, 
                                                     pval=acts_ulm_est_p, 
                                                     order="desc", 
                                                     n=20, 
                                                     p_threshold=0.05)

For example, for the archetype that is enriched in “Flare,” we observe an enrichment of processes related to the immune response to viruses and the response to interferon.

top_processes[arch_idx].round(2)
Process 0 1 2 3 specificity
0 GOBP_NEGATIVE_REGULATION_OF_VIRAL_GENOME_REPLI... -18.01 -13.64 0.96 29.23 28.27
1 GOBP_NEGATIVE_REGULATION_OF_VIRAL_PROCESS -20.22 -12.49 4.40 28.55 24.15
2 GOBP_DEFENSE_RESPONSE_TO_SYMBIONT -19.53 -8.42 5.86 27.08 21.22
3 GOBP_DEFENSE_RESPONSE_TO_OTHER_ORGANISM -23.68 -5.96 15.31 26.25 10.94
4 GOBP_INNATE_IMMUNE_RESPONSE -22.05 -6.81 14.06 25.93 11.87
5 GOBP_BIOLOGICAL_PROCESS_INVOLVED_IN_INTERSPECI... -24.11 -4.38 18.16 25.46 7.30
6 GOBP_RESPONSE_TO_VIRUS -19.20 -6.54 8.01 25.32 17.31
7 GOBP_DEFENSE_RESPONSE -24.52 -4.77 16.87 24.45 7.58
8 GOBP_IMMUNE_RESPONSE -24.45 -4.96 18.72 23.54 4.82
9 GOBP_REGULATION_OF_VIRAL_PROCESS -19.64 -9.11 9.03 23.50 14.47
10 GOBP_REGULATION_OF_VIRAL_GENOME_REPLICATION -15.75 -7.97 2.48 22.90 20.42
11 GOBP_RESPONSE_TO_TYPE_I_INTERFERON -13.37 -8.37 1.30 21.88 20.57
12 GOBP_RESPONSE_TO_INTERFERON_BETA -12.91 -11.05 2.45 20.61 18.16
13 GOBP_VIRAL_GENOME_REPLICATION -13.45 -5.71 4.16 19.29 15.13
14 GOBP_INTERFERON_MEDIATED_SIGNALING_PATHWAY -12.07 -7.06 2.23 18.95 16.72
15 GOBP_VIRAL_LIFE_CYCLE -15.42 -6.13 8.81 18.56 9.76
16 GOBP_VIRAL_PROCESS -14.60 -3.52 10.26 17.49 7.22
17 GOBP_NEGATIVE_REGULATION_OF_VIRAL_LIFE_CYCLE -12.57 -9.87 3.90 17.33 13.43
18 GOBP_REGULATION_OF_RESPONSE_TO_BIOTIC_STIMULUS -16.03 -1.83 10.50 17.15 6.65
19 GOBP_REGULATION_OF_IMMUNE_RESPONSE -18.81 -3.07 16.45 17.01 0.56

On the other hand, for the archetype that is enriched in healthy, we see task of upkeeping homeostasis and normal cellular function in the cells.

top_processes[1].round(2)
Process 0 1 2 3 specificity
0 GOBP_CYTOPLASMIC_TRANSLATION 3.68 16.35 30.72 -23.19 -14.37
1 GOBP_POSITIVE_REGULATION_OF_RNA_METABOLIC_PROCESS -2.70 14.80 7.49 2.44 7.32
2 GOBP_POSITIVE_REGULATION_OF_MACROMOLECULE_BIOS... -2.34 13.88 8.45 2.14 5.43
3 GOBP_POSITIVE_REGULATION_OF_TRANSCRIPTION_BY_R... -3.80 12.60 4.82 1.21 7.78
4 GOBP_NEGATIVE_REGULATION_OF_BIOSYNTHETIC_PROCESS -2.74 11.90 5.86 1.27 6.04
5 GOBP_NEGATIVE_REGULATION_OF_NUCLEOBASE_CONTAIN... -2.31 11.88 4.94 1.09 6.94
6 GOBP_CHROMATIN_ORGANIZATION 3.59 11.15 2.17 -0.47 7.56
7 GOBP_PEPTIDE_BIOSYNTHETIC_PROCESS 2.28 10.73 23.44 -7.30 -12.71
8 GOBP_NEGATIVE_REGULATION_OF_RNA_BIOSYNTHETIC_P... -2.34 10.65 3.71 0.89 6.94
9 GOBP_MRNA_METABOLIC_PROCESS 2.83 10.47 8.01 3.19 2.46
10 GOBP_AMIDE_BIOSYNTHETIC_PROCESS 2.66 10.31 21.92 -6.38 -11.61
11 GOBP_CELLULAR_MACROMOLECULE_BIOSYNTHETIC_PROCESS 2.86 10.28 19.71 -5.09 -9.43
12 GOBP_PEPTIDE_METABOLIC_PROCESS 1.50 10.17 23.31 -6.04 -13.14
13 GOBP_NEGATIVE_REGULATION_OF_TRANSCRIPTION_BY_R... -1.94 10.08 2.33 -0.09 7.75
14 GOBP_REGULATION_OF_MRNA_METABOLIC_PROCESS 1.15 10.00 5.62 -0.58 4.38
15 GOBP_PHOSPHORYLATION -3.42 9.82 5.48 2.45 4.33
16 GOBP_POST_TRANSCRIPTIONAL_REGULATION_OF_GENE_E... 1.11 9.48 9.52 -1.26 -0.04
17 GOBP_HISTONE_MODIFICATION 2.41 9.16 2.99 1.00 6.18
18 GOBP_REGULATION_OF_CELLULAR_MACROMOLECULE_BIOS... 1.17 9.12 9.17 -1.65 -0.04
19 GOBP_RNA_PROCESSING 5.58 9.02 11.41 2.10 -2.39

To identify processes specific to a particular archetype, meaning they are in the top enriched processes of one archetype, we can filter for the highest specificity score, by apply the following function:

specific_processes = pt.extract_specific_processes(est=acts_ulm_est,
                                                          pval=acts_ulm_est_p, 
                                                          n=10,
                                                          p_threshold=0.05)

specific_processes[2].round(2)
Process 0 1 2 3 specificity
0 GOBP_PEPTIDE_ANTIGEN_ASSEMBLY_WITH_MHC_CLASS_I... -27.00 -17.47 47.16 6.92 40.24
1 GOBP_PEPTIDE_ANTIGEN_ASSEMBLY_WITH_MHC_PROTEIN... -25.15 -16.37 43.50 7.42 36.08
2 GOBP_ANTIGEN_PROCESSING_AND_PRESENTATION_OF_EX... -23.33 -16.47 38.43 9.22 29.21
3 GOBP_ANTIGEN_PROCESSING_AND_PRESENTATION_OF_PE... -21.71 -14.97 35.35 9.06 26.29
4 GOBP_ANTIGEN_PROCESSING_AND_PRESENTATION_OF_EX... -23.43 -15.77 35.55 11.36 24.20
5 GOBP_ANTIGEN_PROCESSING_AND_PRESENTATION_OF_EX... -22.24 -14.90 33.00 11.14 21.86
6 GOBP_ANTIGEN_PROCESSING_AND_PRESENTATION_OF_PE... -20.82 -13.78 29.52 11.89 17.63
7 GOBP_IMMUNOGLOBULIN_PRODUCTION_INVOLVED_IN_IMM... -12.21 -5.75 20.46 3.85 16.61
8 GOBP_DENDRITIC_CELL_ANTIGEN_PROCESSING_AND_PRE... -13.76 -7.24 20.94 5.19 15.75
9 GOBP_CYTOPLASMIC_TRANSLATION 3.68 16.35 30.72 -23.19 14.37

For visualization we can plot the obtained results:

pt.barplot_functional_enrichment(top_processes)
../_images/e283861281c9bcf410be96fe1da4182a2c4afcdff0725f4c1d6fb06529c6ff34.png ../_images/872289b2653423e3d0c249834ec9edc701cfbeb40dcc67c98093bbb740b77418.png ../_images/0209997b6acde0b1d39dc6bf40ec07138c6e89ca99df0a20908792d56e3e47b7.png ../_images/14a1f5c56c48b43c1b5267389344d6067e307721e5adb6cdc0f77fd173e81dd9.png
[<plotnine.ggplot.ggplot at 0x388012990>,
 <plotnine.ggplot.ggplot at 0x386ebb8d0>,
 <plotnine.ggplot.ggplot at 0x313696cd0>,
 <plotnine.ggplot.ggplot at 0x35bfd8190>]
pt.barplot_enrichment_comparison(specific_processes[2]) + pn.theme(figure_size=(15, 5))

Session Info#

import session_info2
print(session_info2.session_info(dependencies=True))
plotnine	0.14.5
pandas	2.2.3
scanpy	1.11.2
matplotlib	3.10.3
partipy	0.0.1
decoupler	2.0.6
anndata	0.11.4
numpy	2.2.6
----	----
igraph	0.11.8
annotated-types	0.7.0
threadpoolctl	3.6.0
pyparsing	3.2.3
plotly	6.1.2
certifi	2025.4.26 (2025.04.26)
PyYAML	6.0.2
setuptools	80.8.0
tornado	6.5.1
zarr	2.18.7
executing	2.2.0
pyzmq	26.4.0
idna	3.10
urllib3	2.4.0
typing_extensions	4.13.2
Pygments	2.19.1
importlib_metadata	8.7.0
zipp	3.22.0
ipython	9.2.0
pybiomart	0.2.0
pydantic	2.12.0
narwhals	1.41.0
wrapt	1.17.2
parso	0.8.4
cloudpickle	3.1.1
joblib	1.5.1
docrep	0.3.2
tqdm	4.67.1
debugpy	1.8.14
traitlets	5.14.3
stack-data	0.6.3
legendkit	0.3.5
ipykernel	6.29.5
adjustText	1.3.0
pyarrow	20.0.0
seaborn	0.13.2
six	1.17.0
typing-inspection	0.4.2
psutil	7.0.0
wcwidth	0.2.13
future	1.0.0
crc32c	2.7.1
scikit-learn	1.6.1
llvmlite	0.44.0
numcodecs	0.15.1
session-info2	0.1.2
texttable	1.7.0
url-normalize	2.2.1
Deprecated	1.2.18
scipy	1.15.2
colorama	0.4.6
toolz	1.0.0
decorator	5.2.1
mizani	0.13.5
h5py	3.13.0
xgboost	3.0.2
kiwisolver	1.4.8
python-dateutil	2.9.0.post0
appnope	0.1.4
ipywidgets	8.1.7
cycler	0.12.1
pillow	11.2.1
asciitree	0.3.3
marsilea	0.5.3
requests-cache	1.2.1
pydantic_core	2.41.1
comm	0.2.2
jupyter_client	8.6.3
asttokens	3.0.0
matplotlib-inline	0.1.7
pure_eval	0.2.3
jedi	0.19.2
charset-normalizer	3.4.2
platformdirs	4.3.8
requests	2.32.3
pytz	2025.2
numba	0.61.2
legacy-api-wrap	1.4.1
natsort	8.4.0
jupyter_core	5.8.1
packaging	25.0
dask	2024.11.2
patsy	1.0.1
attrs	25.3.0
cattrs	24.1.3
xarray	2024.11.0
prompt_toolkit	3.0.51
statsmodels	0.14.4
dcor	0.6
----	----
Python	3.11.0 | packaged by conda-forge | (main, Jan 14 2023, 12:26:40) [Clang 14.0.6 ]
OS	macOS-15.7.1-arm64-arm-64bit
Updated	2025-10-14 12:27