In this notebook, we sub-cluster B cell types after filtering out Immunoglobulin-related genes. Because these genes are highly and discretely expressed by B cells, their expression can mask other functional features of B cell populations in approaches like PCA, which is used as input for our neighborhood finding, clustering, and 2D embeddings.
After reclustering, we also subset and iteratively cluster non-effector Memory B cells to identify specific subsets of cells within this population. These deeper looks at B cell populations were used to guide expert annotation of B cells at a high resolution.
import warnings
# Suppress warnings about future changes to pandas
warnings.simplefilter(action='ignore', category=FutureWarning)
# Suppress warnings about casting values to strings
warnings.simplefilter(action='ignore', category=RuntimeWarning)
from datetime import date
import hisepy
import scanpy as sc
import pandas as pd
import numpy as np
import os
import scanpy.external as sce
import matplotlib.pyplot as plt
import math
This helper function allows us to select clusters based on a gene detection cutoff.
def select_clusters_by_gene_frac(adata, gene, cutoff, clusters = 'leiden'):
gene_cl_frac = sc.pl.dotplot(
adata,
groupby = clusters,
var_names = gene,
return_fig = True
).dot_size_df
select_cl = gene_cl_frac.index[gene_cl_frac[gene] > cutoff].tolist()
return select_cl
h5ad_uuid = 'a3bfe22e-a082-4800-a51a-c5c121637e0c'
h5ad_path = '/home/jupyter/cache/{u}'.format(u = h5ad_uuid)
if not os.path.isdir(h5ad_path):
hise_res = hisepy.reader.cache_files([h5ad_uuid])
downloading fileID: a3bfe22e-a082-4800-a51a-c5c121637e0c Files have been successfully downloaded!
h5ad_filename = os.listdir(h5ad_path)[0]
h5ad_file = '{p}/{f}'.format(p = h5ad_path, f = h5ad_filename)
adata = sc.read_h5ad(h5ad_file)
adata
AnnData object with n_obs × n_vars = 177994 × 1274 obs: 'barcodes', 'batch_id', 'cell_name', 'cell_uuid', 'chip_id', 'hto_barcode', 'hto_category', 'n_genes', 'n_mito_umis', 'n_reads', 'n_umis', 'original_barcodes', 'pbmc_sample_id', 'pool_id', 'well_id', 'sample.sampleKitGuid', 'cohort.cohortGuid', 'subject.subjectGuid', 'subject.biologicalSex', 'subject.race', 'subject.ethnicity', 'subject.birthYear', 'sample.visitName', 'sample.drawDate', 'file.id', 'subject.cmv', 'subject.bmi', 'celltypist.low', 'seurat.l1', 'seurat.l1.score', 'seurat.l2', 'seurat.l2.score', 'seurat.l2.5', 'seurat.l2.5.score', 'seurat.l3', 'seurat.l3.score', 'predicted_doublet', 'doublet_score', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_50_genes', 'pct_counts_in_top_100_genes', 'pct_counts_in_top_200_genes', 'pct_counts_in_top_500_genes', 'total_counts_mito', 'log1p_total_counts_mito', 'pct_counts_mito', 'leiden', 'leiden_resolution_1', 'leiden_resolution_1.5', 'leiden_resolution_2' var: 'mito', 'n_cells_by_counts', 'mean_counts', 'log1p_mean_counts', 'pct_dropout_by_counts', 'total_counts', 'log1p_total_counts', 'highly_variable', 'means', 'dispersions', 'dispersions_norm', 'mean', 'std' uns: 'celltypist.low_colors', 'hvg', 'leiden', 'leiden_colors', 'log1p', 'neighbors', 'pca', 'seurat.l2.5_colors', 'umap' obsm: 'X_pca', 'X_pca_harmony', 'X_umap' varm: 'PCs' obsp: 'connectivities', 'distances'
adata = adata.raw.to_adata()
Genes with Ig heavy chain (IGH) and kappa and lambda light chain (IGK and IGL, respectively) prefixes are identified within our dataset here:
igl_genes = [gene for gene in adata.var_names if gene.startswith("IGL")]
igk_genes = [gene for gene in adata.var_names if gene.startswith("IGK")]
ighc_genes = [gene for gene in adata.var_names if gene.startswith("IGH")]
exl_genes = igl_genes + igk_genes + ighc_genes
We then reset our B cell data, select highly variable genes, and then filter out these features for our analysis:
adata.raw = adata
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata)
adata = adata[:, adata.var_names[adata.var['highly_variable']]]
filtered_genes = [gene for gene in adata.var_names if gene not in exl_genes]
adata = adata[:, filtered_genes]
WARNING: adata.X seems to be already log-transformed.
sc.pp.scale(adata)
sc.tl.pca(adata, svd_solver='arpack')
sce.pp.harmony_integrate(
adata,
'cohort.cohortGuid',
max_iter_harmony = 30
)
/opt/conda/lib/python3.10/site-packages/scanpy/preprocessing/_simple.py:843: UserWarning: Received a view of an AnnData. Making a copy. view_to_actual(adata) 2024-02-28 20:29:21,385 - harmonypy - INFO - Computing initial centroids with sklearn.KMeans... 2024-02-28 20:30:21,756 - harmonypy - INFO - sklearn.KMeans initialization complete. 2024-02-28 20:30:22,696 - harmonypy - INFO - Iteration 1 of 30 2024-02-28 20:32:25,129 - harmonypy - INFO - Iteration 2 of 30 2024-02-28 20:34:25,810 - harmonypy - INFO - Converged after 2 iterations
sc.pp.neighbors(
adata,
n_neighbors = 50,
use_rep = 'X_pca_harmony',
n_pcs = 30)
sc.tl.umap(adata, min_dist=0.05)
sc.tl.leiden(
adata,
resolution = 2,
key_added = "ms_leiden_2"
)
IOStream.flush timed out IOStream.flush timed out IOStream.flush timed out IOStream.flush timed out
out_dir = 'output'
if not os.path.isdir(out_dir):
os.makedirs(out_dir)
cell_class = 'b-cells-no-ig'
no_ig_h5ad = 'output/ref_pbmc_{c}_subset_{d}.h5ad'.format(c = cell_class, d = date.today())
adata.write_h5ad(no_ig_h5ad)
umap_mat = adata.obsm['X_umap']
umap_df = pd.DataFrame(umap_mat, columns = ['umap_1', 'umap_2'])
obs = adata.obs
obs['umap_1'] = umap_df['umap_1']
obs['umap_2'] = umap_df['umap_2']
no_ig_csv = 'output/ref_{c}_clustered_umap_meta_{d}.csv'.format(c = cell_class, d = date.today())
obs.to_csv(no_ig_csv)
no_ig_parquet = 'output/ref_{c}_clustered_umap_meta_{d}.parquet'.format(c = cell_class, d = date.today())
obs = obs.to_parquet(no_ig_parquet)
adata = adata.raw.to_adata()
adata
AnnData object with n_obs × n_vars = 177994 × 33538 obs: 'barcodes', 'batch_id', 'cell_name', 'cell_uuid', 'chip_id', 'hto_barcode', 'hto_category', 'n_genes', 'n_mito_umis', 'n_reads', 'n_umis', 'original_barcodes', 'pbmc_sample_id', 'pool_id', 'well_id', 'sample.sampleKitGuid', 'cohort.cohortGuid', 'subject.subjectGuid', 'subject.biologicalSex', 'subject.race', 'subject.ethnicity', 'subject.birthYear', 'sample.visitName', 'sample.drawDate', 'file.id', 'subject.cmv', 'subject.bmi', 'celltypist.low', 'seurat.l1', 'seurat.l1.score', 'seurat.l2', 'seurat.l2.score', 'seurat.l2.5', 'seurat.l2.5.score', 'seurat.l3', 'seurat.l3.score', 'predicted_doublet', 'doublet_score', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_50_genes', 'pct_counts_in_top_100_genes', 'pct_counts_in_top_200_genes', 'pct_counts_in_top_500_genes', 'total_counts_mito', 'log1p_total_counts_mito', 'pct_counts_mito', 'leiden', 'leiden_resolution_1', 'leiden_resolution_1.5', 'leiden_resolution_2', 'ms_leiden_2', 'umap_1', 'umap_2' var: 'mito', 'n_cells_by_counts', 'mean_counts', 'log1p_mean_counts', 'pct_dropout_by_counts', 'total_counts', 'log1p_total_counts' uns: 'celltypist.low_colors', 'hvg', 'leiden', 'leiden_colors', 'log1p', 'neighbors', 'pca', 'seurat.l2.5_colors', 'umap' obsm: 'X_pca', 'X_pca_harmony', 'X_umap' obsp: 'connectivities', 'distances'
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
WARNING: adata.X seems to be already log-transformed.
sc.pl.umap(adata, color = 'ms_leiden_2', legend_loc='on data', legend_fontsize=6)
/opt/conda/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:394: UserWarning: No data for colormapping provided via 'c'. Parameters 'cmap' will be ignored cax = scatter(
sc.pl.umap(adata, color=['doublet_score'])
Cells in Clusters 19 and 22 are likely doublets that have snuck through our scrublet processing.
gene_symbols = [
'PRDM1', 'XBP1', 'MZB1',
'CD27', 'AIM2', 'ZEB2',
'FCRL5', 'MEF2C', 'ITGAX',
'TBX21', 'MME', 'CD9',
'CD24', 'CD38', 'ISG15',
'STAT1'
]
sc.pl.dotplot(adata, gene_symbols, groupby='ms_leiden_2')
/opt/conda/lib/python3.10/site-packages/scanpy/plotting/_dotplot.py:747: UserWarning: No data for colormapping provided via 'c'. Parameters 'cmap', 'norm' will be ignored dot_ax.scatter(x, y, **kwds)
adata.shape
(177994, 33538)
Immunoglobulin heavy chain expression may vary between our two cohorts.
We'll select plasma cells to get a preview of heavy chain usage in BR1 (young adult) and BR2 (older adult) plasma cells
# Plasma Cells
prdm1_pos_cl = select_clusters_by_gene_frac(adata, gene = 'PRDM1', cutoff = 0.5, clusters = 'ms_leiden_2')
plasma_cluster = prdm1_pos_cl
plasma = adata[adata.obs['ms_leiden_2'].isin(plasma_cluster)]
plasma = plasma[plasma.obs['cohort.cohortGuid'].isin(['BR1', 'BR2'])]
igh_genes = ['IGHD', 'IGHM', 'IGHE', 'IGHA1', 'IGHA2', 'IGHG1', 'IGHG2', 'IGHG3', 'IGHG4']
sc.pl.dotplot(plasma, igh_genes, groupby='cohort.cohortGuid')
/opt/conda/lib/python3.10/site-packages/scanpy/plotting/_dotplot.py:747: UserWarning: No data for colormapping provided via 'c'. Parameters 'cmap', 'norm' will be ignored dot_ax.scatter(x, y, **kwds)
To assist with annotation, we'll plot sets of marker genes associated with B cell subpopulations.
markers = {
'plasma': ['PRDM1', 'XBP1', 'MZB1'],
'effector': ['CD27', 'ITGAX', 'TBX21', 'ZEB2', 'FCRL5', 'MEF2C'],
'transitional': ['MME', 'CD9', 'CD24', 'CD38'],
'naive': ['IGHD', 'CD27', 'CD44', 'CD9', 'STAT1', 'IFI44L'],
'memory': ['CD27', 'AIM2', 'IGHD'],
't2': ['FCER2', 'IL4R', 'IGHE', 'MEF2C'],
'cd95': ['CD27', 'AIM2', 'FAS'],
'hbb': ['HBB', 'HBA2', 'HBA1'],
'isg_naive': ['IFI44L', 'STAT1'],
}
for panel,genes in markers.items():
titles = [panel + ': ' + g for g in genes]
sc.pl.umap(
adata,
color = genes,
size = 1,
ncols = 3,
frameon = True,
title = titles
)
sc.pl.umap(
adata,
color = ['leiden_resolution_2'],
legend_loc = 'on data',
size = 2,
show = False,
ncols = 1,
frameon = False)
/opt/conda/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:394: UserWarning: No data for colormapping provided via 'c'. Parameters 'cmap' will be ignored cax = scatter(
<Axes: title={'center': 'leiden_resolution_2'}, xlabel='UMAP1', ylabel='UMAP2'>
To get additional resolution on Memory B cell types, we'll select AIM2-positive clusters, and remove effector memory cells (ZEB2-positive clusters), and plasma cells (PRDM1-positive clusters), then perform another iterative round of clustering to get additional resolution.
# Most memory clusters
aim2_pos_cl = select_clusters_by_gene_frac(adata, gene = 'AIM2', cutoff = 0.3, clusters = 'ms_leiden_2')
sc.pl.umap(adata, color = 'ms_leiden_2', groups = aim2_pos_cl,
legend_loc='on data', legend_fontsize=6)
/opt/conda/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:394: UserWarning: No data for colormapping provided via 'c'. Parameters 'cmap' will be ignored cax = scatter(
# Effectors
zeb2_pos_cl = select_clusters_by_gene_frac(adata, gene = 'ZEB2', cutoff = 0.5, clusters = 'ms_leiden_2')
sc.pl.umap(adata, color = 'ms_leiden_2', groups = zeb2_pos_cl,
legend_loc='on data', legend_fontsize=6)
/opt/conda/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:394: UserWarning: No data for colormapping provided via 'c'. Parameters 'cmap' will be ignored cax = scatter(
# Plasma Cells
prdm1_pos_cl = select_clusters_by_gene_frac(adata, gene = 'PRDM1', cutoff = 0.5, clusters = 'ms_leiden_2')
sc.pl.umap(adata, color = 'ms_leiden_2', groups = prdm1_pos_cl,
legend_loc='on data', legend_fontsize=6)
/opt/conda/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:394: UserWarning: No data for colormapping provided via 'c'. Parameters 'cmap' will be ignored cax = scatter(
keep_cl = set(aim2_pos_cl) - set(zeb2_pos_cl)
keep_cl = keep_cl - set(prdm1_pos_cl)
keep_cl = list(keep_cl)
keep_cl.sort()
keep_cl
['13', '14', '16', '2', '27', '4', '5']
sc.pl.umap(adata, color = 'ms_leiden_2', groups = keep_cl,
legend_loc='on data', legend_fontsize=6)
/opt/conda/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:394: UserWarning: No data for colormapping provided via 'c'. Parameters 'cmap' will be ignored cax = scatter(
allmem_MBCs = adata[adata.obs['ms_leiden_2'].isin(keep_cl)]
As for the broader B cell clustering, we trim Immunoglobulin genes, then perform harmony and clustering.
allmem_MBCs.raw = allmem_MBCs
sc.pp.normalize_total(allmem_MBCs, target_sum=1e4)
sc.pp.log1p(allmem_MBCs)
WARNING: adata.X seems to be already log-transformed.
sc.pp.highly_variable_genes(allmem_MBCs)
igl_genes = [gene for gene in adata.var_names if gene.startswith("IGL")]
igk_genes = [gene for gene in adata.var_names if gene.startswith("IGK")]
ighc_genes = [gene for gene in adata.var_names if gene.startswith("IGH")]
exl_genes = igl_genes + igk_genes + ighc_genes
allmem_MBCs = allmem_MBCs[:, allmem_MBCs.var_names[allmem_MBCs.var['highly_variable']]]
filtered_genes = [gene for gene in allmem_MBCs.var_names if gene not in exl_genes]
allmem_MBCs = allmem_MBCs[:, filtered_genes]
sc.pp.scale(allmem_MBCs)
sc.tl.pca(allmem_MBCs, svd_solver='arpack')
sce.pp.harmony_integrate(allmem_MBCs, 'cohort.cohortGuid',max_iter_harmony = 30)
sc.pp.neighbors(allmem_MBCs, n_neighbors=50,use_rep='X_pca_harmony', n_pcs=30)
sc.tl.umap(allmem_MBCs,min_dist=0.05)
/opt/conda/lib/python3.10/site-packages/scanpy/preprocessing/_simple.py:843: UserWarning: Received a view of an AnnData. Making a copy. view_to_actual(adata) 2024-02-28 22:24:40,423 - harmonypy - INFO - Computing initial centroids with sklearn.KMeans... 2024-02-28 22:25:01,371 - harmonypy - INFO - sklearn.KMeans initialization complete. 2024-02-28 22:25:01,669 - harmonypy - INFO - Iteration 1 of 30 2024-02-28 22:25:25,869 - harmonypy - INFO - Iteration 2 of 30 2024-02-28 22:25:50,412 - harmonypy - INFO - Iteration 3 of 30 2024-02-28 22:26:07,510 - harmonypy - INFO - Iteration 4 of 30 2024-02-28 22:26:14,336 - harmonypy - INFO - Iteration 5 of 30 2024-02-28 22:26:21,154 - harmonypy - INFO - Iteration 6 of 30 2024-02-28 22:26:27,783 - harmonypy - INFO - Converged after 6 iterations
sc.tl.leiden(allmem_MBCs, resolution = 2, key_added = "ms_leiden_2.5")
cell_class = 'b-cells-mem-no-ig'
mem_h5ad = 'output/ref_pbmc_{c}_subset_{d}.h5ad'.format(c = cell_class, d = date.today())
allmem_MBCs.write_h5ad(mem_h5ad)
umap_mat = allmem_MBCs.obsm['X_umap']
umap_df = pd.DataFrame(umap_mat, columns = ['umap_1', 'umap_2'])
obs = allmem_MBCs.obs
obs['umap_1'] = umap_df['umap_1']
obs['umap_2'] = umap_df['umap_2']
mem_csv = 'output/ref_{c}_clustered_umap_meta_{d}.csv'.format(c = cell_class, d = date.today())
obs.to_csv(mem_csv)
mem_parquet = 'output/ref_{c}_clustered_umap_meta_{d}.parquet'.format(c = cell_class, d = date.today())
obs = obs.to_parquet(mem_parquet)
allmem_MBCs=allmem_MBCs.raw.to_adata()
allmem_MBCs.shape
(47886, 33538)
sc.pp.normalize_total(allmem_MBCs, target_sum=1e4)
sc.pp.log1p(allmem_MBCs)
WARNING: adata.X seems to be already log-transformed.
sc.pl.umap(allmem_MBCs, color = 'ms_leiden_2.5', legend_loc='on data', legend_fontsize=6)
/opt/conda/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:394: UserWarning: No data for colormapping provided via 'c'. Parameters 'cmap' will be ignored cax = scatter(
mem_markers = {
'markers_t2': ['IL4R', 'IGHE', 'FCER2', 'COCH', 'MEF2C'],
'markers_cd95': ['FAS', 'ITGAX', 'AIM2', 'CD27'],
'non_switch_b': ['IGHD', 'IGHM'],
'early_mem': ['IGHD', 'IGHM', 'CD27', 'CD79B', 'FCGR2B', 'MEF2C', 'AIM2'],
'ap1': ['JUN', 'MYC', 'CD69', 'FOS'],
}
for panel,genes in mem_markers.items():
titles = [panel + ': ' + g for g in genes]
sc.pl.umap(
allmem_MBCs,
color = genes,
size = 3,
ncols = 3,
frameon = True,
title = titles
)
mem_marker_list = ['IGHD', 'IGHM', 'FAS',
'ITGAX', 'AIM2', 'CD27',
'CD79B', 'FCGR2B', 'MEF2C',
'IGHE', 'IL4R', 'FCER2',
'COCH', 'JUN', 'MYC',
'CD69', 'FOS']
sc.pl.dotplot(allmem_MBCs, mem_marker_list, groupby = 'ms_leiden_2.5')
/opt/conda/lib/python3.10/site-packages/scanpy/plotting/_dotplot.py:747: UserWarning: No data for colormapping provided via 'c'. Parameters 'cmap', 'norm' will be ignored dot_ax.scatter(x, y, **kwds)
Finally, we'll use hisepy.upload.upload_files()
to send a copy of our output to HISE to use for downstream analysis steps.
study_space_uuid = '64097865-486d-43b3-8f94-74994e0a72e0'
title = 'B cell no-Ig reclustering {d}'.format(d = date.today())
in_files = [h5ad_uuid]
in_files
['a3bfe22e-a082-4800-a51a-c5c121637e0c']
out_files = [no_ig_h5ad, no_ig_csv, no_ig_parquet,
mem_h5ad, mem_csv, mem_parquet]
out_files
['output/ref_pbmc_b-cells-no-ig_subset_2024-02-28.h5ad', 'output/ref_b-cells-no-ig_clustered_umap_meta_2024-02-28.csv', 'output/ref_b-cells-no-ig_clustered_umap_meta_2024-02-28.parquet', 'output/ref_pbmc_b-cells-mem-no-ig_subset_2024-02-28.h5ad', 'output/ref_b-cells-mem-no-ig_clustered_umap_meta_2024-02-28.csv', 'output/ref_b-cells-mem-no-ig_clustered_umap_meta_2024-02-28.parquet']
hisepy.upload.upload_files(
files = out_files,
study_space_id = study_space_uuid,
title = title,
input_file_ids = in_files
)
Cannot determine the current notebook. 1) /home/jupyter/scRNA-Reference-IH-A/03-Subclustering/08a-Python_Myeloid_cells_cdc.ipynb 2) /home/jupyter/scRNA-Reference-IH-A/03-Subclustering/07a-Python_B_cells_without_Igs.ipynb 3) /home/jupyter/scRNA-Reference-IH-A/version_adaptation/01-Python_adapt_Myeloid.ipynb Please select (1-3)
you are trying to upload file_ids... ['output/ref_pbmc_b-cells-no-ig_subset_2024-02-28.h5ad', 'output/ref_b-cells-no-ig_clustered_umap_meta_2024-02-28.csv', 'output/ref_b-cells-no-ig_clustered_umap_meta_2024-02-28.parquet', 'output/ref_pbmc_b-cells-mem-no-ig_subset_2024-02-28.h5ad', 'output/ref_b-cells-mem-no-ig_clustered_umap_meta_2024-02-28.csv', 'output/ref_b-cells-mem-no-ig_clustered_umap_meta_2024-02-28.parquet']. Do you truly want to proceed?
{'trace_id': '0e6fa457-8f35-49f4-9061-41daf9d2deba', 'files': ['output/ref_pbmc_b-cells-no-ig_subset_2024-02-28.h5ad', 'output/ref_b-cells-no-ig_clustered_umap_meta_2024-02-28.csv', 'output/ref_b-cells-no-ig_clustered_umap_meta_2024-02-28.parquet', 'output/ref_pbmc_b-cells-mem-no-ig_subset_2024-02-28.h5ad', 'output/ref_b-cells-mem-no-ig_clustered_umap_meta_2024-02-28.csv', 'output/ref_b-cells-mem-no-ig_clustered_umap_meta_2024-02-28.parquet']}
import session_info
session_info.show()
----- anndata 0.10.3 hisepy 0.3.0 matplotlib 3.8.0 numpy 1.24.0 pandas 2.1.4 scanpy 1.9.6 session_info 1.0.0 -----
PIL 10.0.1 anyio NA arrow 1.3.0 asttokens NA attr 23.2.0 attrs 23.2.0 babel 2.14.0 beatrix_jupyterlab NA brotli NA cachetools 5.3.1 certifi 2023.11.17 cffi 1.16.0 charset_normalizer 3.3.2 cloudpickle 2.2.1 colorama 0.4.6 comm 0.1.4 cryptography 41.0.7 cycler 0.10.0 cython_runtime NA dateutil 2.8.2 db_dtypes 1.1.1 debugpy 1.8.0 decorator 5.1.1 defusedxml 0.7.1 deprecated 1.2.14 exceptiongroup 1.2.0 executing 2.0.1 fastjsonschema NA fqdn NA google NA greenlet 2.0.2 grpc 1.58.0 grpc_status NA h5py 3.10.0 harmonypy NA idna 3.6 igraph 0.10.8 importlib_metadata NA ipykernel 6.28.0 ipython_genutils 0.2.0 ipywidgets 8.1.1 isoduration NA jedi 0.19.1 jinja2 3.1.2 joblib 1.3.2 json5 NA jsonpointer 2.4 jsonschema 4.20.0 jsonschema_specifications NA jupyter_events 0.9.0 jupyter_server 2.12.1 jupyterlab_server 2.25.2 jwt 2.8.0 kiwisolver 1.4.5 leidenalg 0.10.1 llvmlite 0.41.0 lz4 4.3.2 markupsafe 2.1.3 matplotlib_inline 0.1.6 mpl_toolkits NA mpmath 1.3.0 natsort 8.4.0 nbformat 5.9.2 numba 0.58.0 opentelemetry NA overrides NA packaging 23.2 parso 0.8.3 pexpect 4.8.0 pickleshare 0.7.5 pkg_resources NA platformdirs 4.1.0 plotly 5.18.0 prettytable 3.9.0 prometheus_client NA prompt_toolkit 3.0.42 proto NA psutil NA ptyprocess 0.7.0 pure_eval 0.2.2 pyarrow 13.0.0 pycparser 2.21 pydev_ipython NA pydevconsole NA pydevd 2.9.5 pydevd_file_utils NA pydevd_plugins NA pydevd_tracing NA pygments 2.17.2 pynndescent 0.5.11 pynvml NA pyparsing 3.1.1 pyreadr 0.5.0 pythonjsonlogger NA pytz 2023.3.post1 referencing NA requests 2.31.0 rfc3339_validator 0.1.4 rfc3986_validator 0.1.1 rpds NA scipy 1.11.4 send2trash NA shapely 1.8.5.post1 six 1.16.0 sklearn 1.3.2 sniffio 1.3.0 socks 1.7.1 sparse 0.14.0 sql NA sqlalchemy 2.0.21 sqlparse 0.4.4 stack_data 0.6.2 sympy 1.12 termcolor NA texttable 1.7.0 threadpoolctl 3.2.0 torch 2.1.2+cu121 torchgen NA tornado 6.3.3 tqdm 4.66.1 traitlets 5.9.0 typing_extensions NA umap 0.5.5 uri_template NA urllib3 1.26.18 wcwidth 0.2.12 webcolors 1.13 websocket 1.7.0 wrapt 1.15.0 xarray 2023.12.0 yaml 6.0.1 zipp NA zmq 25.1.2 zoneinfo NA zstandard 0.22.0
----- IPython 8.19.0 jupyter_client 8.6.0 jupyter_core 5.6.1 jupyterlab 4.0.10 notebook 6.5.4 ----- Python 3.10.13 | packaged by conda-forge | (main, Dec 23 2023, 15:36:39) [GCC 12.3.0] Linux-5.15.0-1052-gcp-x86_64-with-glibc2.31 ----- Session information updated at 2024-02-28 22:43