Note

This page was generated from mimic_2_fate.ipynb. Some tutorial content may look better in light mode.

MIMIC-II IAC Patient Fate#

In the previous introduction tutorial, we explored the MIMIC-II IAC dataset, comprising electronic health records (EHR) of 1776 patients in 46 features, and identified patient group-specific clusters using ehrapy. Please go through the MIMIC-II IAC introduction before performing this tutorial to get familiar with the dataset.

As a next step, we want to determine patient fate. The goal is to detect terminal states and the corresponding origins based on pseudotime. Real time very rarely reflects the actual progression of a disease. When measurements are done on a certain day, some patients will show no sign of disease (e.g. healthy or recovered), some are at the onset of a specific disease and some are in a more severe stage or even at the height. For an appropriate analysis, we are interested in a continuous transition of states, such as from healthy to diseased to death, for which the real time is therefore not informative. Identification of transition states can be achieved by identifying source states (e.g. healthy) and then calculating pseudotime from this state. Based on Markov chain modelling, we uncover patient dynamics using CellRank. For more details, please read the CellRank paper.

In this tutorial we will be using CellRank to:

  1. Simulate patient trajectories with random walks.

  2. Compute patient macrostates and infer fate probabilities towards predicted terminal states.

  3. Identify potential driver features for each identified trajectory.

  4. Visualize feature trends along specific patient states, while accounting for the continuous nature of fate determination.

Before performing this tutorial, we highly recommend to read the extensive and well written CellRank documentation, especially the general tutorial chapter is useful. If you are not familiar with single-cell data, do not be afraid and replace cells with patients visits and genes with features in your mind.

This tutorial requires cellrank to be installed. As this packages is not a dependency of ehrapy, it must be installed separately.

[1]:
%%capture --no-display
!pip install cellrank

Before we start with the patient fate analysis of the MIMIC-II IAC dataset, we set up our environment including the import of packages and preparation of the dataset.


Environment setup#

Ensure that the latest version of ehrapy is installed. A list of all dependency versions can be found at the end of this tutorial.

[2]:
import ehrapy as ep
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import rcParams
import pandas as pd
import cellrank as cr
import scvelo as scv
import numpy as np

We are ignoring a few warnings for readability reasons.

[3]:
import warnings

warnings.filterwarnings("ignore")

Getting and preprocessing the MIMIC-II dataset#

This tutorial is based on the MIMIC-II IAC dataset which was previously introduced in the MIMIC-II IAC introduction tutorial. We will load the encoded version of the dataset as an AnnData object, ehrapy’s default encoding is a simple one-hot encoding in this case.

[4]:
%%capture
adata = ep.dt.mimic_2(encoded=False)
adata
2023-08-10 17:59:28,683 - root INFO - Added all columns to `obs`.
2023-08-10 17:59:28,699 - root INFO - Transformed passed dataframe into an AnnData object with n_obs x n_vars = `1776` x `46`.

The MIMIC-II dataset has 1776 patients with 46 features. Now that we have our AnnData object ready, we need to perform the standard preprocessing steps as performed in the introduction tutorial again before we can use ehrapy and CellRank for patient fate analysis.

[5]:
%%capture
adata = ep.pp.encode(adata, encodings={"one_hot_encoding": ["service_unit", "day_icu_intime"]})
ep.pp.knn_impute(adata, n_neighbours=5)
ep.pp.log_norm(adata, vars=['iv_day_1', "po2_first"], offset=1)
ep.pp.pca(adata)
ep.pp.neighbors(adata, n_pcs=10)
ep.tl.umap(adata)
ep.tl.leiden(adata, resolution=0.3, key_added="leiden_0_3")
2023-08-10 17:59:28,707 - root INFO - The original categorical values `['service_unit', 'day_icu_intime']` were added to uns.
2023-08-10 17:59:28,739 - root INFO - Updated the original layer after encoding.
2023-08-10 17:59:28,747 - root INFO - Added `['service_unit', 'day_icu_intime']` columns to `X`.
2023-08-10 17:59:28,751 - root INFO - The original categorical values `['service_unit', 'day_icu_intime']` were added to obs.
2023-08-10 17:59:28,883 - root INFO - Added the calculated metrics to AnnData's `obs` and `var`.
2023-08-10 17:59:29,208 - root INFO - Values in columns ['iv_day_1', 'po2_first'] were replaced by [[5.2832036 7.7105975]
 [5.1973915 6.398595 ]
 [5.7004437 7.643866 ]
 ...
 [5.757007  5.0657544]
 [4.4426513 3.125444 ]
 [6.35437   8.38229  ]].
[6]:
ep.settings.set_figure_params(figsize=(5, 4), dpi = 100)
ep.pl.umap(adata, color=["leiden_0_3"], title="Leiden 0.3",  size = 20)
../../_images/tutorials_notebooks_mimic_2_fate_17_0.png

This UMAP embedding is exactly the same as previously computed in the MIMIC-II IA introduction tutorial. Now we continue with the patient fate analysis.


Analysis using ehrapy and CellRank#

Depending on the data it may not always be possible to clearly define a cluster or specific patient visits as the origin or terminus of a trajectory. Working with single-cell data simplifies matters since the detection of stem cells generally signifies the start of cell differentiation.

In this tutorial, we will define a patient cluster as the origin (root cluster) and explore possible terminal states.

Pseudotime calculation#

As the root cluster for pseudotime calculation we choose cluster 0 since patients in that cluster do not show very severe comorbidities and features yet. Then we calculate the Diffusion Pseudotime with the el.dpt() function.

[7]:
adata.uns["iroot"] = np.flatnonzero(adata.obs["leiden_0_3"] == "0")[0]
ep.tl.dpt(adata)
WARNING: Trying to run `tl.dpt` without prior call of `tl.diffmap`. Falling back to `tl.diffmap` with default parameters.

Now we define the kernel, compute the transition matrix and plot a projection onto the UMAP.

Determining patient fate with a PseudotimeKernel#

The PseudotimeKernel computes direct transition probabilities based on a KNN graph and pseudotime.

The KNN graph contains information about the (undirected) conductivities among cells, reflecting their similarity. Pseudotime can be used to either remove edges that point against the direction of increasing pseudotime, or to downweight them.

[8]:
from cellrank.kernels import PseudotimeKernel
pk = PseudotimeKernel(adata, time_key = "dpt_pseudotime")
pk.compute_transition_matrix()
[8]:
PseudotimeKernel[n=1776, dnorm=False, scheme='hard', frac_to_keep=0.3]
[9]:
ep.settings.set_figure_params(figsize=(5, 4), dpi = 100)
pk.plot_projection(basis="umap", color="leiden_0_3")
../../_images/tutorials_notebooks_mimic_2_fate_29_0.png

We observe that two main trajectories originating from cluster 0 going to clusters 4 and 2. Let’s check the metadata again.

[10]:
ep.pl.umap(adata, color = "censor_flg", title = "Censored or Death (0 = death, 1 = censored)")
ep.pl.umap(adata, color = "mort_day_censored", title = "Day post ICU admission of censoring or death")
../../_images/tutorials_notebooks_mimic_2_fate_31_0.png
../../_images/tutorials_notebooks_mimic_2_fate_31_1.png

Cluster 2 consists of patients that deceased and had severe comorbidities while cluster 4 includes patients with a high day post ICU admission.

Simulating transitions with random walks#

Cellrank makes it easy to simulate the behavior of random walks from specific clusters. This allows us to not only visualize where the patients end up, but also roughly how many in which clusters after a defined number of iterations. We can either just start walking…

[11]:
pk.plot_random_walks(
    seed=0,
    n_sims=100,
    start_ixs={"leiden_0_3": ["0"]},
    legend_loc="right",
    dpi=100,
    show_progress_bar=False
)
../../_images/tutorials_notebooks_mimic_2_fate_35_0.png

… or set a number of required hits in one or more terminal clusters. Here, we require 50 hits in cluster 2 or 4.

[12]:
pk.plot_random_walks(
    seed=0,
    n_sims=100,
    start_ixs={"leiden_0_3": ["0"]},
    stop_ixs={"leiden_0_3": ["2", "4"]},
    successive_hits = 50,
    legend_loc="right",
    dpi=100,
    show_progress_bar=False
)
../../_images/tutorials_notebooks_mimic_2_fate_37_0.png

Black and yellow dots indicate random walk start and terminal patient visits, respectively.

Determining macrostates and terminal states#

To find the terminal states of cluster 0, well will use an estimator to predict the patient fates using the above calculated transition matrix. The main objective is to decompose the patient state space into a set of macrostates, that represent the slow-time scale dynamics of the process and predict terminal states. Here, we will use an Generalized Perron Cluster Cluster Analysis (GPCCA) estimator.

As a first step we try to identify macrostates in the data using the fit() function.

[13]:
g = cr.estimators.GPCCA(pk)
g.fit(cluster_key="leiden_0_3")
g.macrostates_memberships
WARNING: Unable to import `petsc4py` or `slepc4py`. Using `method='brandts'`
WARNING: For `method='brandts'`, dense matrix is required. Densifying
[13]:
2_12_24
0.2699160.7299330.000151
0.0315730.1974380.770989
0.0327020.1901960.777102
0.0726950.9272740.000031
0.0347330.8521210.113145
0.0249490.4350040.540046
0.0261080.7373800.236511
0.0698140.8689420.061245
0.0302650.2180870.751648
0.0170000.9829990.000001
.........
0.0840160.9150380.000945
0.0189460.9810510.000003
0.0072530.0642320.928515
0.0296280.1319990.838373
0.1387100.8612140.000076
0.0246210.4827750.492604
0.1011630.8987780.000060
0.2322160.7676570.000128
0.0101510.9898210.000027
0.2849320.7097940.005274

1776 cells x 3 lineages

[14]:
g.predict_terminal_states()
g.plot_macrostates(which="terminal")
../../_images/tutorials_notebooks_mimic_2_fate_42_0.png
[15]:
g.plot_macrostates(which = "terminal", same_plot=False)
../../_images/tutorials_notebooks_mimic_2_fate_43_0.png

As a next step we will calculate the fate probabilities. For each patient visit, this computes the probability of being absorbed in any of the terminal states by aggregating over all random walks that start in a given patient visit and end in some terminal population.

[16]:
g.compute_fate_probabilities(preconditioner="ilu", tol=1e-15)
g.plot_fate_probabilities()
WARNING: Unable to import petsc4py. For installation, please refer to: https://petsc4py.readthedocs.io/en/stable/install.html.
Defaulting to `'gmres'` solver.
WARNING: `3` solution(s) did not converge
../../_images/tutorials_notebooks_mimic_2_fate_45_3.png

The plot above combines fate probabilities towards all terminal states, each patient visit is colored according to its most likely fate, color intensity reflects the degree of fate priming.

[17]:
g.plot_fate_probabilities(same_plot=False)
╭─────────────────────────────────────── Traceback (most recent call last) ───────────────────────────────────────╮
 /home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/IPython/core/formatters.py:223 in                
 catch_format_error                                                                                              
                                                                                                                 
    220 def catch_format_error(method, self, *args, **kwargs):                                                   
    221 """show traceback on failed format call"""                                                           
    222 try:                                                                                                 
  223 │   │   r = method(self, *args, **kwargs)                                                                
    224 except NotImplementedError:                                                                          
    225 │   │   # don't warn on NotImplementedErrors                                                             
    226 │   │   return self._check_return(None, args[0])                                                         
                                                                                                                 
 /home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/IPython/core/formatters.py:340 in __call__       
                                                                                                                 
    337 │   │   │   except KeyError:                                                                             
    338 │   │   │   │   pass                                                                                     
    339 │   │   │   else:                                                                                        
  340 │   │   │   │   return printer(obj)                                                                      
    341 │   │   │   # Finally look for special method names                                                      
    342 │   │   │   method = get_real_method(obj, self.print_method)                                             
    343 │   │   │   if method is not None:                                                                       
                                                                                                                 
 /home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/IPython/core/pylabtools.py:169 in retina_figure  
                                                                                                                 
   166 .. versionadded:: 7.29                                                                                
   167 │   │   base64 argument                                                                                   
   168 """                                                                                                   
 169 pngdata = print_figure(fig, fmt="retina", base64=False, **kwargs)                                     
   170 # Make sure that retina_figure acts just like print_figure and returns                                
   171 # None when the figure is empty.                                                                      
   172 if pngdata is None:                                                                                   
                                                                                                                 
 /home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/IPython/core/pylabtools.py:152 in print_figure   
                                                                                                                 
   149 │   │   from matplotlib.backend_bases import FigureCanvasBase                                             
   150 │   │   FigureCanvasBase(fig)                                                                             
   151                                                                                                       
 152 fig.canvas.print_figure(bytes_io, **kw)                                                               
   153 data = bytes_io.getvalue()                                                                            
   154 if fmt == 'svg':                                                                                      
   155 │   │   data = data.decode('utf-8')                                                                       
                                                                                                                 
 /home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/matplotlib/backend_bases.py:2353 in print_figure 
                                                                                                                 
   2350 │   │   │   │   │   bbox_inches = bbox_inches.padded(pad_inches)                                         
   2351 │   │   │   │                                                                                            
   2352 │   │   │   │   # call adjust_bbox to save only the given area                                           
 2353 │   │   │   │   restore_bbox = _tight_bbox.adjust_bbox(                                                  
   2354 │   │   │   │   │   self.figure, bbox_inches, self.figure.canvas.fixed_dpi)                              
   2355 │   │   │   │                                                                                            
   2356 │   │   │   │   _bbox_inches_restore = (bbox_inches, restore_bbox)                                       
                                                                                                                 
 /home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/matplotlib/_tight_bbox.py:28 in adjust_bbox      
                                                                                                                 
   25 for ax in fig.axes:                                                                                    
   26 │   │   locator = ax.get_axes_locator()                                                                    
   27 │   │   if locator is not None:                                                                            
 28 │   │   │   ax.apply_aspect(locator(ax, None))                                                             
   29 │   │   locator_list.append(locator)                                                                       
   30 │   │   current_pos = ax.get_position(original=False).frozen()                                             
   31 │   │   ax.set_axes_locator(lambda a, r, _pos=current_pos: _pos)                                           
                                                                                                                 
 /home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/matplotlib/colorbar.py:156 in __call__           
                                                                                                                 
    153                                                                                                      
    154 def __call__(self, ax, renderer):                                                                    
    155 │   │   if self._orig_locator is not None:                                                               
  156 │   │   │   pos = self._orig_locator(ax, renderer)                                                       
    157 │   │   else:                                                                                            
    158 │   │   │   pos = ax.get_position(original=True)                                                         
    159 │   │   if self._cbar.extend == 'neither':                                                               
                                                                                                                 
 /home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/mpl_toolkits/axes_grid1/inset_locator.py:73 in   
 __call__                                                                                                        
                                                                                                                 
    70                                                                                                       
    71 def __call__(self, ax, renderer):                                                                     
    72 │   │   self.axes = ax                                                                                    
  73 │   │   bbox = self.get_window_extent(renderer)                                                           
    74 │   │   px, py = self.get_offset(bbox.width, bbox.height, 0, 0, renderer)                                 
    75 │   │   bbox_canvas = Bbox.from_bounds(px, py, bbox.width, bbox.height)                                   
    76 │   │   tr = ax.figure.transSubfigure.inverted()                                                          
                                                                                                                 
 /home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/matplotlib/offsetbox.py:399 in get_window_extent 
                                                                                                                 
    396 def get_window_extent(self, renderer=None):                                                          
    397 │   │   # docstring inherited                                                                            
    398 │   │   if renderer is None:                                                                             
  399 │   │   │   renderer = self.figure._get_renderer()                                                       
    400 │   │   bbox = self.get_bbox(renderer)                                                                   
    401 │   │   try:  # Some subclasses redefine get_offset to take no args.                                     
    402 │   │   │   px, py = self.get_offset(bbox, renderer)                                                     
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'NoneType' object has no attribute '_get_renderer'
<Figure size 1500x400 with 6 Axes>

We can also visualize the fate probabilities jointly in a circular projection where each dot represents a patient visit, colored by cluster labels. Patient visits are arranged inside the circle according to their fate probabilities, fate biased visits are placed next to their corresponding corner while undetermined patient fates are placed in the middle.

[18]:
cr.pl.circular_projection(adata, keys="leiden_0_3", legend_loc="right")
../../_images/tutorials_notebooks_mimic_2_fate_49_0.png

Identification of driver features#

We uncover putative driver features by correlating fate probabilities with gene expression using the compute_lineage_drivers() method. In other words, if a feature is systematically higher or lower in patient visits that are more or less likely to differentiate towards a given terminal states, respectively, then we call this feature a putative driver feature.

We calculate these driver features for our three lineages 2_1, 2_2 and 4.

[19]:
%%capture
ep.settings.set_figure_params(figsize=(3, 3), dpi = 100)
[20]:
drivers_2_1 = g.compute_lineage_drivers(lineages="2_1")
adata.obs["fate_probs_2_1"] = g.fate_probabilities["2_1"].X.flatten()

ep.pl.umap(
    adata,
    color=["fate_probs_2_1"] + list(drivers_2_1.index[:8]),
    color_map="viridis",
    s=50,
    ncols=3,
    vmax="p96",
)
/home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:163: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
  cmap = copy(get_cmap(cmap))
../../_images/tutorials_notebooks_mimic_2_fate_53_1.png
[21]:
drivers_2_2 = g.compute_lineage_drivers(lineages="2_2")
adata.obs["fate_probs_2_2"] = g.fate_probabilities["2_2"].X.flatten()

ep.pl.umap(
    adata,
    color=["fate_probs_2_2"] + list(drivers_2_2.index[:8]),
    color_map="viridis",
    s=50,
    ncols=3,
    vmax="p96",
)
/home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:163: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
  cmap = copy(get_cmap(cmap))
../../_images/tutorials_notebooks_mimic_2_fate_54_1.png
[22]:
drivers_4 = g.compute_lineage_drivers(lineages="4")
adata.obs["fate_probs_4"] = g.fate_probabilities["4"].X.flatten()

ep.pl.umap(
    adata,
    color=["fate_probs_4"] + list(drivers_4.index[:8]),
    color_map="viridis",
    s=50,
    ncols=3,
    vmax="p96",
)
/home/zeth/miniconda3/envs/ehrapy/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:163: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
  cmap = copy(get_cmap(cmap))
../../_images/tutorials_notebooks_mimic_2_fate_55_1.png

The lineage 2_1 seems to have a lot of patients that deceased in hospital, are of high age and had a high platelet measurement, while lineage 2_2 consists of patients that deceased in hospital, had a high first SAPS I and SOFA score and lineage 4 consists of patients with a high day after ICU release.

Conclusion#

In this tutorial we applied CellRank and ehrapy to identify patient visit trajectories from selected root clusters, computed macrostates of clusters and pointed out features that are driving those trajectories. Following that, we visualized feature trends across the pseudotime for the patient trajectories. In particular, we inspected trajectories of patients originating from cluster 0, which was defined by less severe features, and identified 3 major trajectories. Two trajectories (2_1 and 2_2) were terminated in a bad outcome cluster and were driven by severity features such as age, death and comorbidities.

As a next tutorial, we suggest to have a closer look at our survival analysis, continue with that tutorials or go back to our tutorial overview page.


References#

  • Raffa, J. (2016). Clinical data from the MIMIC-II database for a case study on indwelling arterial catheters (version 1.0). PhysioNet. https://doi.org/10.13026/C2NC7F.

  • Raffa J.D., Ghassemi M., Naumann T., Feng M., Hsu D. (2016) Data Analysis. In: Secondary Analysis of Electronic Health Records. Springer, Cham

  • Goldberger, A., Amaral, L., Glass, L., Hausdorff, J., Ivanov, P. C., Mark, R., … & Stanley, H. E. (2000). PhysioBank, PhysioToolkit, and PhysioNet: Components of a new research resource for complex physiologic signals. Circulation [Online]. 101 (23), pp. e215–e220.

  • Marius Lange, Volker Bergen, Michal Klein, Manu Setty, Bernhard Reuter, Mostafa Bakhti, Heiko Lickert, Meshal Ansari, Janine Schniering, Herbert B. Schiller, Dana Pe’er, and Fabian J. Theis. Cellrank for directed single-cell fate mapping. Nat. Methods, 2022. doi:10.1038/s41592-021-01346-6.

  • Lars Velten, Simon F. Haas, Simon Raffel, Sandra Blaszkiewicz, Saiful Islam, Bianca P. Hennig, Christoph Hirche, Christoph Lutz, Eike C. Buss, Daniel Nowak, Tobias Boch, Wolf-Karsten Hofmann, Anthony D. Ho, Wolfgang Huber, Andreas Trumpp, Marieke A. G. Essers, and Lars M. Steinmetz. Human haematopoietic stem cell lineage commitment is a continuous process. Nature Cell Biology, 19(4):271–281, 2017. doi:10.1038/ncb3493.

  • Bergen, V., Lange, M., Peidli, S. et al. Generalizing RNA velocity to transient cell states through dynamical modeling. Nat Biotechnol 38, 1408–1414 (2020). https://doi.org/10.1038/s41587-020-0591-3

  • Haghverdi, L., Büttner, M., Wolf, F. et al. Diffusion pseudotime robustly reconstructs lineage branching. Nat Methods 13, 845–848 (2016). https://doi.org/10.1038/nmeth.3971


Package versions#

[25]:
%%capture --no-display
ep.print_versions()
-----
ehrapy              0.6.0
rich                NA
session_info        1.0.0
-----
Levenshtein                 0.21.1
PIL                         10.0.0
absl                        NA
aiofiles                    NA
aiohttp                     3.8.5
aiosignal                   1.3.1
anndata                     0.9.2
anyio                       NA
argcomplete                 NA
arrow                       1.2.3
astor                       0.8.1
asttokens                   NA
async_timeout               4.0.2
attr                        23.1.0
attrs                       23.1.0
autograd                    NA
autograd_gamma              NA
babel                       2.12.1
backcall                    0.2.0
backoff                     2.2.1
blis                        NA
bs4                         4.12.2
cachetools                  5.3.1
catalogue                   NA
category_encoders           2.6.1
cellrank                    1.5.2.dev242+ge0f46cd
certifi                     2023.07.22
cffi                        1.15.1
charset_normalizer          3.2.0
chex                        0.1.7
click                       8.1.6
comm                        0.1.3
confection                  NA
contextlib2                 NA
croniter                    NA
cryptography                41.0.1
cvxopt                      1.3.1
cycler                      0.10.0
cymem                       NA
cython_runtime              NA
datasets                    2.14.4
dateutil                    2.8.2
db_dtypes                   1.1.1
debugpy                     1.6.7
decorator                   5.1.1
deep_translator             1.9.1
deepdiff                    6.3.1
deepl                       1.15.0
defusedxml                  0.7.1
dill                        0.3.7
docrep                      0.3.2
dot_parser                  NA
dowhy                       0.10
etils                       1.3.0
executing                   1.2.0
fastapi                     0.100.0
fastjsonschema              NA
fhiry                       3.0.0
filelock                    3.12.2
flax                        0.7.0
formulaic                   0.6.4
fqdn                        NA
frozenlist                  1.4.0
fsspec                      2023.6.0
future                      0.18.3
gensim                      4.3.1
google                      NA
graphlib                    NA
graphviz                    0.20.1
grpc                        1.56.2
grpc_status                 NA
h5py                        3.9.0
html5lib                    1.1
huggingface_hub             0.16.4
idna                        3.4
igraph                      0.10.6
importlib_resources         NA
interface_meta              1.3.0
ipykernel                   6.24.0
ipywidgets                  8.1.0
isoduration                 NA
jax                         0.4.13
jaxlib                      0.4.13
jedi                        0.19.0
jinja2                      3.0.3
joblib                      1.3.1
json5                       NA
jsonpickle                  3.0.1
jsonpointer                 2.4
jsonschema                  4.18.0
jsonschema_specifications   NA
jupyter_events              0.7.0
jupyter_server              2.7.0
jupyterlab_server           2.24.0
kiwisolver                  1.4.4
langcodes                   NA
leidenalg                   0.10.1
lifelines                   0.27.7
lightning                   2.0.5
lightning_cloud             NA
lightning_utilities         0.9.0
llvmlite                    0.40.1
markdown_it                 2.2.0
markupsafe                  2.1.3
matplotlib                  3.7.2
matplotlib_inline           0.1.6
mdurl                       0.1.2
medcat                      1.9.0
missingno                   0.5.2
ml_collections              NA
ml_dtypes                   0.2.0
mpl_toolkits                NA
mpmath                      1.3.0
msgpack                     1.0.5
mudata                      0.2.3
multidict                   6.0.4
multipart                   0.0.6
multipledispatch            0.6.0
multiprocess                0.70.15
murmurhash                  NA
natsort                     8.4.0
nbformat                    5.9.1
networkx                    3.1
numba                       0.57.1
numpy                       1.24.4
numpyro                     0.12.1
nvfuser                     NA
opt_einsum                  v3.3.0
optax                       0.1.5
ordered_set                 4.1.0
overrides                   NA
packaging                   23.1
pandas                      2.0.3
parso                       0.8.3
patsy                       0.5.3
pexpect                     4.8.0
pickleshare                 0.7.5
pkg_resources               NA
platformdirs                3.10.0
preshed                     NA
progressbar                 4.2.0
prometheus_client           NA
prompt_toolkit              3.0.39
psutil                      5.9.5
ptyprocess                  0.7.0
pure_eval                   0.2.2
pyarrow                     12.0.1
pycparser                   2.21
pydantic                    1.10.12
pydev_ipython               NA
pydevconsole                NA
pydevd                      2.9.5
pydevd_file_utils           NA
pydevd_plugins              NA
pydevd_tracing              NA
pydot                       1.4.2
pygam                       0.8.0
pygments                    2.16.1
pygpcca                     1.0.4
pynndescent                 0.5.10
pyparsing                   3.0.9
pyro                        1.8.5
python_utils                NA
pythonjsonlogger            NA
pytz                        2023.3
rapidfuzz                   3.2.0
referencing                 NA
regex                       2.5.132
requests                    2.31.0
rfc3339_validator           0.1.4
rfc3986_validator           0.1.1
rpds                        NA
ruamel                      NA
scanpy                      1.9.3
scipy                       1.11.1
scvelo                      0.3.0
scvi                        1.0.2
seaborn                     0.12.2
send2trash                  NA
setuptools                  68.0.0
shellingham                 1.5.0.post1
six                         1.16.0
sklearn                     1.1.3
smart_open                  6.3.0
sniffio                     1.3.0
soupsieve                   2.4.1
spacy                       3.6.1
sparse                      0.14.0
sphinxcontrib               NA
srsly                       2.4.7
stack_data                  0.6.2
starlette                   0.27.0
statsmodels                 0.14.0
sympy                       1.12
texttable                   1.6.7
thefuzz                     0.19.0
thinc                       8.1.11
threadpoolctl               3.2.0
tokenizers                  0.12.1
tomli                       2.0.1
toolz                       0.12.0
torch                       2.0.1+cu117
torchmetrics                1.0.1
tornado                     6.3.2
tqdm                        4.65.0
traitlets                   5.9.0
tree                        0.1.8
typer                       0.9.0
typing_extensions           NA
umap                        0.5.3
uri_template                NA
urllib3                     2.0.4
uvicorn                     0.23.1
wasabi                      NA
wcwidth                     0.2.6
webcolors                   1.13
webencodings                0.5.1
websocket                   1.6.1
websockets                  11.0.3
wrapt                       1.15.0
xarray                      2023.7.0
xxhash                      NA
yaml                        6.0.1
yarl                        1.9.2
zmq                         25.1.0
zoneinfo                    NA
-----
IPython             8.14.0
jupyter_client      8.3.0
jupyter_core        5.3.1
jupyterlab          4.0.3
-----
Python 3.10.12 | packaged by conda-forge | (main, Jun 23 2023, 22:40:32) [GCC 12.3.0]
Linux-6.4.8-arch1-1-x86_64-with-glibc2.38
-----
Session information updated at 2023-08-10 18:01