3. Via Human Hematopoiesis

This notebook uses VIA to interpret the CD34 Hematopoiesis dataset (Setty et al.,2019)

import pyVIA.core as via
import pyVIA.datasets_via as   datasets
import pandas as pd 
import scanpy as sc

import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')

Load data from directory

We use annotations given by SingleR which uses Novershtern Hematopoietic cell data as the reference. These are in line with the annotations given by Setty et al., 2019 but offer a slightly more granular annotation.

adata = datasets.scRNA_hematopoiesis()
sc.tl.pca(adata, svd_solver='arpack', n_comps=200)
tsnem = adata.obsm['tsne']
adata
Cell type CMP has  968 cells
Cell type PRE_B3 has  2 cells
Cell type B_a4 has  8 cells
Cell type pDC has  204 cells
Cell type HSC2 has  10 cells
Cell type GRAN1 has  3 cells
Cell type Nka3 has  5 cells
Cell type EOS2 has  3 cells
Cell type MONO1 has  186 cells
Cell type B_a1 has  27 cells
Cell type ERY3 has  104 cells
Cell type ERY1 has  773 cells
Cell type HSC1 has  2365 cells
Cell type MONO2 has  35 cells
Cell type ERY2 has  40 cells
Cell type mDC (cDC) has  96 cells
Cell type B_a2 has  1 cells
Cell type BASO1 has  2 cells
Cell type ERY4 has  53 cells
Cell type MEP has  339 cells
Cell type PRE_B2 has  515 cells
Cell type TCEL7 has  1 cells
Cell type GMP has  28 cells
Cell type MEGA1 has  12 cells
AnnData object with n_obs × n_vars = 5780 × 14651
    obs: 'clusters', 'palantir_pseudotime', 'palantir_diff_potential', 'label'
    uns: 'cluster_colors', 'ct_colors', 'palantir_branch_probs_cell_types', 'pca'
    obsm: 'tsne', 'MAGIC_imputed_data', 'palantir_branch_probs', 'X_pca'
    varm: 'PCs'

User’s choice of embedding

Three embedding exmaples: TSNE, UMAP, and PHATE Alternatively allow via.VIA() to compute an embedding using the underlying graph by setting: do_embedding = True AND embedding_type = ‘via-umap’ OR ‘via-mds’

# TSNE - same as the embedding used in the original Setty et al., publication
embedding = adata.obsm['tsne']

# # UMAP
# ncomp = 30
# embedding = umap.UMAP().fit_transform(adata.obsm['X_pca'][:, 0:ncomp])

# # PHATE
# ncomp = 30
# phate_op = phate.PHATE()
# embedding = phate_op.fit_transform(adata.obsm['X_pca'][:, 0:ncomp])

Run VIA

Key Parameters:

  • knn

  • root_user (root index of type int/ or celltype label of type string)

  • edgepruning_clustering_resolution (lower number means smaller (and more) clusters) typical range 0-1

  • memory (higher value means more focused search pathways to cell fates) typical range 2-50

  • cluster_graph_pruning (lower number means fewer edges) typical range 0-1

  • dataset (relates to the root_user parameter. if the root is an index, the leave as dataset =’’. If the root is a celltype label found in true_label paramters, then dataset=’group’)

ncomps=80
knn=30
v0_random_seed=4
root_user = [4823] #the index of a cell belonging to the HSC cell type
memory = 10
dataset = ''

'''
#NOTE1, if you decide to choose a cell type as a root, then you need to set the dataset as 'group'
#root_user=['HSC1']
#dataset = 'group'# 'humanCD34'
#NOTE2, if rna-velocity is available, considering using it to compute the root automatically- see RNA velocity tutorial
'''

v0 = via.VIA(data=adata.obsm['X_pca'][:, 0:ncomps], true_label=adata.obs['label'], 
             edgepruning_clustering_resolution=0.15, cluster_graph_pruning=0.15,
             knn=knn,  root_user=root_user, resolution_parameter=1.5,
             dataset=dataset, random_seed=v0_random_seed, memory=memory)#, do_compute_embedding=True, embedding_type='via-atlas')

v0.run_VIA()

#NOTE2: if you want to pre-specify terminal states you can do so by a list of group-level names corresponding to true-labels OR by a list of single cell indices
#E.G. user_defined_terminal_group=['pDC','ERY1', 'ERY3', 'MONO1','mDC (cDC)','PRE_B2']
2023-10-30 14:26:27.296505	Running VIA over input data of 5780 (samples) x 80 (features)
2023-10-30 14:26:27.296612	Knngraph has 30 neighbors
2023-10-30 14:26:31.954335	Finished global pruning of 30-knn graph used for clustering at level of 0.15. Kept 46.3 % of edges. 
2023-10-30 14:26:32.011295	Number of connected components used for clustergraph  is 1
2023-10-30 14:26:32.503636	Commencing community detection
2023-10-30 14:26:32.631581	Finished running Leiden algorithm. Found 212 clusters.
2023-10-30 14:26:32.637560	Merging 188 very small clusters (<10)
2023-10-30 14:26:32.642614	Finished detecting communities. Found 24 communities
2023-10-30 14:26:32.643731	Making cluster graph. Global cluster graph pruning level: 0.15
2023-10-30 14:26:32.673200	Graph has 1 connected components before pruning
2023-10-30 14:26:32.676487	Graph has 2 connected components after pruning
2023-10-30 14:26:32.678096	Graph has 1 connected components after reconnecting
2023-10-30 14:26:32.678934	0.0% links trimmed from local pruning relative to start
2023-10-30 14:26:32.678958	65.5% links trimmed from global pruning relative to start
2023-10-30 14:26:32.683710	component number 0 out of  [0]
2023-10-30 14:26:32.707100	The root index, 4823 provided by the user belongs to cluster number 1 and corresponds to cell type HSC1
2023-10-30 14:26:32.709534	Computing lazy-teleporting expected hitting times
2023-10-30 14:26:33.454240	 ended all multiprocesses, will retrieve and reshape
try rw2 hitting times setup
start computing walks with rw2 method
g.indptr.size, 25
memory for rw2 hittings times  2. Using rw2 based pt
do scaling of pt
2023-10-30 14:26:40.339327	Identifying terminal clusters corresponding to unique lineages...
2023-10-30 14:26:40.339362	Closeness:[1, 7, 8, 11, 12, 13, 15, 18]
2023-10-30 14:26:40.339379	Betweenness:[1, 3, 6, 7, 11, 12, 13, 15, 18, 20, 21, 22]
2023-10-30 14:26:40.339392	Out Degree:[1, 5, 7, 8, 9, 11, 12, 13, 15, 18, 20, 22]
2023-10-30 14:26:40.340052	Terminal clusters corresponding to unique lineages in this component are [7, 11, 12, 15, 18, 20, 22] 
TESTING rw2_lineage probability at memory 10
testing rw2 lineage probability at memory 10
g.indptr.size, 25
2023-10-30 14:26:44.688612	 Cluster or terminal cell fate 7 is reached 11.0 times
2023-10-30 14:26:44.769144	 Cluster or terminal cell fate 11 is reached 189.0 times
2023-10-30 14:26:44.857752	 Cluster or terminal cell fate 12 is reached 11.0 times
2023-10-30 14:26:44.957626	 Cluster or terminal cell fate 15 is reached 303.0 times
2023-10-30 14:26:45.048059	 Cluster or terminal cell fate 18 is reached 155.0 times
2023-10-30 14:26:45.125893	 Cluster or terminal cell fate 20 is reached 644.0 times
2023-10-30 14:26:45.201391	 Cluster or terminal cell fate 22 is reached 709.0 times
2023-10-30 14:26:45.213079	There are (7) terminal clusters corresponding to unique lineages {7: 'PRE_B2', 11: 'ERY3', 12: 'PRE_B2', 15: 'MONO1', 18: 'ERY1', 20: 'pDC', 22: 'mDC (cDC)'}
2023-10-30 14:26:45.213129	Begin projection of pseudotime and lineage likelihood
2023-10-30 14:26:46.728132	Cluster graph layout based on forward biasing
2023-10-30 14:26:46.732186	Starting make edgebundle viagraph...
2023-10-30 14:26:46.732218	Make via clustergraph edgebundle
2023-10-30 14:26:48.990054	Hammer dims: Nodes shape: (24, 2) Edges shape: (102, 3)
2023-10-30 14:26:48.991583	Graph has 1 connected components before pruning
2023-10-30 14:26:48.994114	Graph has 5 connected components after pruning
2023-10-30 14:26:48.998647	Graph has 1 connected components after reconnecting
2023-10-30 14:26:48.999453	53.9% links trimmed from local pruning relative to start
2023-10-30 14:26:48.999478	69.6% links trimmed from global pruning relative to start
2023-10-30 14:26:49.018135	Time elapsed 20.0 seconds

Cluster Level Trajectory Plots

fig, ax, ax1 = via.plot_piechart_viagraph(via_object=v0, show_legend=False)
fig.set_size_inches(12,5)
../_images/6cbcf2b577978c4f2537be3a28904ca8800542783239e8b11cfb6da05fb86a62.png

Visualise gene/feature graph

View the gene expression along the VIA graph. We use the computed HNSW small world graph in VIA to accelerate the gene imputation calculations (using similar approach to MAGIC) as follows:

df_ = pd.DataFrame(adata.X)
df_.columns = [i for i in adata.var_names]

gene_list_magic = ['IL3RA', 'IRF8', 'GATA1', 'GATA2', 'ITGA2B', 'MPO', 'CD79B', 'SPI1', 'CD34', 'CSF1R', 'ITGAX']

#optional to do gene expression imputation

df_magic = v0.do_impute(df_, magic_steps=3, gene_list=gene_list_magic)

fig, axs = via.plot_viagraph(via_object=v0, type_data='gene', df_genes=df_magic, gene_list=gene_list_magic[0:3], arrow_head=0.1)
fig.set_size_inches(15,5)
shape of transition matrix raised to power 3 (5780, 5780)
../_images/17950f8b701ad73325290792309f8f43cb204b9954a637995d0120ce623f43a3.png

Trajectory projection

Visualize the overall VIA trajectory projected onto a 2D embedding (UMAP, Phate, TSNE etc) in different ways.

  1. Draw the high-level clustergraph abstraction onto the embedding;

  2. Draw high-edge resolution directed graph

  3. Draw a vector field/stream plot of the more fine-grained directionality of cells along the trajectory projected onto an embedding.

Key Parameters:

  • scatter_size

  • scatter_alpha

  • linewidth

  • draw_all_curves (if too crowded, set to False)

fig, ax, ax1 = via.plot_trajectory_curves(via_object=v0,embedding=tsnem, draw_all_curves=False)
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:01 Time:  0:00:01
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (11 of 11) |########################| Elapsed Time: 0:00:00 Time:  0:00:00
2023-10-30 13:55:26.039883	Super cluster 7 is a super terminal with sub_terminal cluster 7
2023-10-30 13:55:26.040203	Super cluster 9 is a super terminal with sub_terminal cluster 9
2023-10-30 13:55:26.040240	Super cluster 11 is a super terminal with sub_terminal cluster 11
2023-10-30 13:55:26.040271	Super cluster 12 is a super terminal with sub_terminal cluster 12
2023-10-30 13:55:26.040304	Super cluster 15 is a super terminal with sub_terminal cluster 15
2023-10-30 13:55:26.040351	Super cluster 18 is a super terminal with sub_terminal cluster 18
2023-10-30 13:55:26.040382	Super cluster 20 is a super terminal with sub_terminal cluster 20
2023-10-30 13:55:26.040412	Super cluster 21 is a super terminal with sub_terminal cluster 21
2023-10-30 13:55:26.040441	Super cluster 22 is a super terminal with sub_terminal cluster 22
../_images/df3ecfbb545bbb1899f57726752facff65d0ed9d289ac570c01b3c66ffb73173.png
v0.embedding = tsnem
fig, ax = via.plot_atlas_view(via_object=v0,  n_milestones=150, sc_labels=adata.obs['label'], fontsize_labels=3, extra_title_text='Atlas View colored by pseudotime')
fig.set_size_inches(4,3)
inside add sc embedding second if
../_images/734038af0479fd753bc9dfcd6fa758dbf965aa38ff63211b5558fb3f97cbe35f.png
# edge plots can be made with different edge resolutions. Run hammerbundle_milestone_dict() to recompute the edges for plotting. Then provide the new hammerbundle as a parameter to plot_edge_bundle()
# it is better to compute the edges and save them to the via_object. this gives more control to the merging of edges
decay = 0.6 #increasing decay increasing merging of edges
i_bw = 0.02 #increasing bw increases merging of edges
global_visual_pruning = 0.5 #higher number retains more edges
n_milestones = 200

v0.hammerbundle_milestone_dict= via.make_edgebundle_milestone(via_object=v0, n_milestones=n_milestones, decay=decay, initial_bandwidth=i_bw, global_visual_pruning=global_visual_pruning)
2023-10-30 15:03:28.888865	Start finding milestones
2023-10-30 15:03:33.107973	End milestones with 200
2023-10-30 15:03:33.130700	Recompute weights
2023-10-30 15:03:33.163942	pruning milestone graph based on recomputed weights
2023-10-30 15:03:33.165341	Graph has 1 connected components before pruning
2023-10-30 15:03:33.166303	Graph has 1 connected components after pruning
2023-10-30 15:03:33.166606	Graph has 1 connected components after reconnecting
2023-10-30 15:03:33.168703	regenerate igraph on pruned edges
2023-10-30 15:03:33.183040	Setting numeric label as single cell pseudotime for coloring edges
2023-10-30 15:03:33.235016	Making smooth edges
fig, ax = via.plot_atlas_view(via_object=v0,  add_sc_embedding=True, sc_labels_expression=adata.obs['label'], cmap='jet', sc_labels=adata.obs['label'], text_labels=True, extra_title_text='Atlas View by Cell type', fontsize_labels=3)
fig.set_size_inches(6,4)
inside add sc embedding second if
../_images/508ed8320492523c461bd0d63ef909675c73f14302fe0e0dc52ce49bcbf700d6.png
# via_streamplot() requires you to either provide an ndarray as embedding as an input parameter OR for via to have an embedding attribute
fig, ax = via.via_streamplot(v0, embedding=tsnem, density_grid=0.8, scatter_size=30, scatter_alpha=0.3, linewidth=0.5)
fig.set_size_inches(4,3)
../_images/49d6ea3ad9c053ebafde2db102ac486db54c38f6340f5308914d00b44c9d0e81.png
#Colored by pseudotime

fig, ax = via.via_streamplot(v0,density_grid=0.8, scatter_size=30, color_scheme='time', linewidth=0.5, 
                             min_mass = 1, cutoff_perc = 5, scatter_alpha=0.3, marker_edgewidth=0.1, 
                             density_stream = 2, smooth_transition=1, smooth_grid=0.5)
fig.set_size_inches(4,3)
../_images/e019a4479e01ab1a064f770667b8a17d9bb478441abf9ca95c959cf75eb0cf8d.png

Probabilistic pathways and Memory

Visualize the probabilistic pathways from root to terminal state as indicated by the lineage likelihood. The higher the linage likelihood, the greater the potential of that particular cell to differentiate towards the terminal state of interest. Changing the memory paramater will alter the specificity of the lineage pathway. This can be visualized at the single-cell level but also combined with the Atlas View which visualizes cell-cell connectivity and pathways

Key Parameters:

marker_lineages (list) of terminal clusters

fig, axs= via.plot_sc_lineage_probability(via_object=v0, marker_lineages=[7,11,12,15,20,22], embedding=tsnem) #marker_lineages=v0.terminal_clusters to plot all
fig.set_size_inches(12,5)
2023-10-30 14:42:00.472388	Marker_lineages: [7, 11, 12, 15, 20, 22]
2023-10-30 14:42:00.476814	The number of components in the original full graph is 1
2023-10-30 14:42:00.476862	For downstream visualization purposes we are also constructing a low knn-graph 
2023-10-30 14:42:05.171433	Check sc pb 0.9999999999999999 
f getting majority comp
2023-10-30 14:42:05.475235	Cluster path on clustergraph starting from Root Cluster 1 to Terminal Cluster 7: [1, 2, 0, 4, 16, 8, 12, 7]
2023-10-30 14:42:05.475274	Cluster path on clustergraph starting from Root Cluster 1 to Terminal Cluster 11: [1, 13, 3, 6, 17, 11]
2023-10-30 14:42:05.475293	Cluster path on clustergraph starting from Root Cluster 1 to Terminal Cluster 12: [1, 2, 0, 4, 16, 8, 12]
2023-10-30 14:42:05.475311	Cluster path on clustergraph starting from Root Cluster 1 to Terminal Cluster 15: [1, 2, 0, 4, 16, 5, 15]
2023-10-30 14:42:05.475328	Cluster path on clustergraph starting from Root Cluster 1 to Terminal Cluster 18: [1, 13, 3, 18]
2023-10-30 14:42:05.475345	Cluster path on clustergraph starting from Root Cluster 1 to Terminal Cluster 20: [1, 2, 0, 4, 16, 20]
2023-10-30 14:42:05.475362	Cluster path on clustergraph starting from Root Cluster 1 to Terminal Cluster 22: [1, 2, 0, 4, 22]
2023-10-30 14:42:05.605789	Revised Cluster level path on sc-knnGraph from Root Cluster 1 to Terminal Cluster 7 along path: [1, 1, 1, 8, 12, 12, 12]
2023-10-30 14:42:05.640568	Revised Cluster level path on sc-knnGraph from Root Cluster 1 to Terminal Cluster 11 along path: [1, 1, 2, 6, 11, 11, 11, 11]
2023-10-30 14:42:05.678481	Revised Cluster level path on sc-knnGraph from Root Cluster 1 to Terminal Cluster 12 along path: [1, 1, 1, 8, 12, 12, 12, 12]
2023-10-30 14:42:05.724775	Revised Cluster level path on sc-knnGraph from Root Cluster 1 to Terminal Cluster 15 along path: [1, 1, 2, 9, 15]
2023-10-30 14:42:05.761232	Revised Cluster level path on sc-knnGraph from Root Cluster 1 to Terminal Cluster 20 along path: [1, 1, 1, 8, 20, 20, 20, 20]
2023-10-30 14:42:05.805373	Revised Cluster level path on sc-knnGraph from Root Cluster 1 to Terminal Cluster 22 along path: [1, 1, 1, 8, 22, 22, 22]
../_images/e3a7d520f40fe204fb92ee319933bc87b6ecafc803a8269b6338e987a941c8d0.png
fig, axs= via.plot_atlas_view(via_object=v0, lineage_pathway=[7,11,12,15,20,22]) #marker_lineages=v0.terminal_clusters to plot all
fig.set_size_inches(12,5)
location of 7 is at [0] and 0
location of 11 is at [1] and 1
location of 12 is at [2] and 2
location of 15 is at [3] and 3
location of 20 is at [5] and 5
location of 22 is at [6] and 6
../_images/b91c125aec0be3c96f3426868f70872b97de3de6e100333d2e986d612e658519.png

Gene Dynamics

The gene dynamics along pseudotime for all detected lineages are automatically inferred by VIA. These can be interpreted as the change in gene expression along any given lineage.

Key Parameters

  • n_splines

  • spline_order

  • gene_exp (dataframe) single-cell level gene expression of select genes (gene imputation is an optional pre-step)

marker_genes =['ITGA2B', 'IL3RA', 'IRF8', 'MPO', 'CSF1R', 'GATA2', 'CD79B', 'CD34']
df = pd.DataFrame(adata.X, columns = adata.var_names)
df_magic = v0.do_impute(df, magic_steps=3, gene_list=gene_list_magic) #optional
fig, axs=via.get_gene_expression(via_object=v0, gene_exp=df_magic[marker_genes])
fig.set_size_inches(14,7)
shape of transition matrix raised to power 3 (5780, 5780)
../_images/07f44b4ed0cf846566a108ba1e94bb7083afbfea9e0100c6655e6d377684465f.png

Gene Dynamics

Heatmaps of genes along pseudotimetime

Key Parameters

  • df_gene_exp (dataframe) single-cell level gene expression of selected genes

  • marker_lineages (list, optional) to specify which lineages to plot heatmaps for

fig, axs = via.plot_gene_trend_heatmaps(via_object=v0, df_gene_exp=df_magic, cmap='plasma',
                             marker_lineages=[7,11])
fig.set_size_inches(5,5)
branches [7, 11]
../_images/18beee593add4909323fb14b83aabddf46b31871c3c5d3eb484a195e7182e0a8.png

Various Visualizations

Visualizations of the trajectory can be plotted at various edge resolutions

Edge bundle plot

Key Parameters (default):

  • alpha_bundle_factor=1

  • linewidth_bundle=2

  • cmap:str = ‘plasma_r’

  • size_scatter:int=2

  • alpha_scatter:float = 0.2

  • headwidth_bundle=0.1

Animated Stream plot

sc.settings.set_figure_params(dpi=120, facecolor='white')
#the streamlines load very slowly through the Notebook, so see the code below to open the file and view the animation properly
via.animated_streamplot(v0, embedding=tsnem, cmap_stream='Blues', scatter_size=200, scatter_alpha=0.2, marker_edgewidth=0.15, 
                        density_grid=0.7, linewidth=0.1, segment_length=1.5, saveto='/home/shobi/Trajectory/Datasets/HumanCD34/HumanCD34_animation_Jan3.gif')
2023-01-03 09:32:23.524989	Inside animated. File will be saved to location /home/shobi/Trajectory/Datasets/HumanCD34/HumanCD34_animation_Jan3.gif
  0%|          | 0/250 [00:00<?, ?it/s]
total number of stream lines 201

../_images/5b918a5c2b1098e5ab53dcc3bab20b24b3755887e20070fd99b034538fe1db3a.png
(<Figure size 1200x720 with 1 Axes>, <AxesSubplot:>)
from IPython.display import Image

with open('./Figures/HumanCD34_animation.gif','rb') as file:
    display(Image(file.read()))

Animated edge bundle plot

via.animate_edge_bundle(via_object=v0, extra_title_text='test animation', n_milestones=None,
                        saveto='./Figures/human_edgebundle_test.gif')
making hammerbundle
2022-11-08 16:46:46.082215	Start kmeans milestone
2022-11-08 16:46:50.162267	End kmeans milestone
2022-11-08 16:46:50.230431	Recompute weights
2022-11-08 16:46:50.348908	pruning milestone graph based on recomputed weights
2022-11-08 16:46:50.358479	Graph has 1 connected components before pruning
2022-11-08 16:46:50.358479	Graph has 1 connected components before pruning
2022-11-08 16:46:50.368028	regenerate igraph on pruned edges
2022-11-08 16:46:50.456737	make node dataframe
2022-11-08 16:46:50.472879	Setting numeric label as time_series_labels or other sequential metadata for coloring edges
2022-11-08 16:46:50.592365	Hammer bundling
seg weight 0.1311759587041706
MovieWriter imagemagick unavailable; using Pillow instead.
2022-11-08 16:47:46.937861	Finished plotting edge bundle
times series order set [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
number cycles if no time_series labels given 40.0
complete animate
inside update 0 out of 120
inside update 0 out of 120
inside update 1 out of 120
inside update 2 out of 120
inside update 3 out of 120
inside update 4 out of 120
inside update 5 out of 120
inside update 6 out of 120
inside update 7 out of 120
inside update 8 out of 120
inside update 9 out of 120
inside update 10 out of 120
inside update 11 out of 120
inside update 12 out of 120
inside update 13 out of 120
inside update 14 out of 120
inside update 15 out of 120
inside update 16 out of 120
inside update 17 out of 120
inside update 18 out of 120
inside update 19 out of 120
inside update 20 out of 120
inside update 21 out of 120
inside update 22 out of 120
inside update 23 out of 120
inside update 24 out of 120
inside update 25 out of 120
inside update 26 out of 120
inside update 27 out of 120
inside update 28 out of 120
inside update 29 out of 120
inside update 30 out of 120
inside update 31 out of 120
inside update 32 out of 120
inside update 33 out of 120
inside update 34 out of 120
inside update 35 out of 120
inside update 36 out of 120
inside update 37 out of 120
inside update 38 out of 120
inside update 39 out of 120
inside update 40 out of 120
inside update 41 out of 120
inside update 42 out of 120
inside update 43 out of 120
inside update 44 out of 120
inside update 45 out of 120
inside update 46 out of 120
inside update 47 out of 120
inside update 48 out of 120
inside update 49 out of 120
inside update 50 out of 120
inside update 51 out of 120
inside update 52 out of 120
inside update 53 out of 120
inside update 54 out of 120
inside update 55 out of 120
inside update 56 out of 120
inside update 57 out of 120
inside update 58 out of 120
inside update 59 out of 120
inside update 60 out of 120
inside update 61 out of 120
inside update 62 out of 120
inside update 63 out of 120
inside update 64 out of 120
inside update 65 out of 120
inside update 66 out of 120
inside update 67 out of 120
inside update 68 out of 120
inside update 69 out of 120
inside update 70 out of 120
inside update 71 out of 120
inside update 72 out of 120
inside update 73 out of 120
inside update 74 out of 120
inside update 75 out of 120
inside update 76 out of 120
inside update 77 out of 120
inside update 78 out of 120
inside update 79 out of 120
inside update 80 out of 120
inside update 81 out of 120
inside update 82 out of 120
inside update 83 out of 120
inside update 84 out of 120
inside update 85 out of 120
inside update 86 out of 120
inside update 87 out of 120
inside update 88 out of 120
inside update 89 out of 120
inside update 90 out of 120
inside update 91 out of 120
inside update 92 out of 120
inside update 93 out of 120
inside update 94 out of 120
inside update 95 out of 120
inside update 96 out of 120
inside update 97 out of 120
inside update 98 out of 120
inside update 99 out of 120
inside update 100 out of 120
inside update 101 out of 120
inside update 102 out of 120
inside update 103 out of 120
inside update 104 out of 120
inside update 105 out of 120
inside update 106 out of 120
inside update 107 out of 120
inside update 108 out of 120
inside update 109 out of 120
inside update 110 out of 120
inside update 111 out of 120
inside update 112 out of 120
inside update 113 out of 120
inside update 114 out of 120
inside update 115 out of 120
inside update 116 out of 120
inside update 117 out of 120
inside update 118 out of 120
inside update 119 out of 120
saved animation
../_images/f88bb1efaa184ecf3c49aa8c77031cf12988aadc7f04a62aff45a2576696c772.png
from IPython.display import Image
with open('/home/user/Github_local/VIA/Figures/human_edgebundle_test.gif','rb') as file:
    display(Image(file.read()))
../_images/f705d11425b733263e424e82ed3844dcb7381d4fbb9e25be463025dc9531cd1d.png