Cell death analysis of inducible, titratable neurodegenerative disease models in zebrafish and human stem cell-derived retinal organoids.
The 3 matches
- [1] § MATERIALS AND METHODS › Transcriptomic data processing ↔ preprocessing_basics.ipynb, lines 208–237 · score 0.54 · highly variable genes, filtered, apoptosis, necroptosis, parthanatos
- [2] § MATERIALS AND METHODS › Cell death pathway scoring ↔ time_course.ipynb, lines 234–346 · score 0.53 · sham signatures, baseline, Scanpy, score, gene
- [3] § RESULTS › Cell death signatures in transcriptomic datasets of NTR 2.0/MTZ-based ablation ↔ time_course.ipynb, lines 234–346 · score 0.51 · gene signature, sham signatures, ablated, signaling, score, apoptosis
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Jupyter notebook · 647 lines · 20 KB · no license · 2 matches
- # %%
- import scanpy as sc
- import numpy as np
- import matplotlib.pyplot as plt
- import pandas as pd
- import scipy
- from pydeseq2.dds import DeseqDataSet
- from pydeseq2.default_inference import DefaultInference
- from pydeseq2.ds import DeseqStats
- from matplotlib.colors import LinearSegmentedColormap
- import matplotlib.cm as cm
- from misc_utils import score_colors
- # %%
- # data_annotated_path = "/home/bmb/haxx/working/ceisel_mumm/data/"
- data_annotated_path = "/Users/bbrener1/haxx/ceisel_mumm/data/"
- data = sc.read_h5ad(data_annotated_path + "full_annotations_leiden.h5ad")
- figure_path = "/Users/bbrener1/haxx/ceisel_mumm/figures/"
- data.shape
- # %%
- data.obs['time']=data.obs['time'].astype(int)
- # %% [markdown]
- # # Building A Timeline
- # %%
- plt.figure()
- plt.title("Log total counts vs time")
- plt.boxplot(
- [data.obs['log_total_counts'][data.obs['time'] == t] for t in [12,24,48,72]],
- showfliers=False,
- )
- plt.xticks(
- [1,2,3,4],
- ["12h","24h","48h","72h"]
- )
- plt.ylabel("Log total counts")
- plt.show()
- # %% [markdown]
- # # PCA IQR Timeline, Big Sheet
- # %% [markdown]
- # We can briefly look at the timecourse of each individual PC across the entire dataset with no filtering to sanity check our data and see the overall level of stability. We also want to observe whether or not there are obvious outliers
- # %%
- def extract_iqrs(data,low_percentile=25,high_percentile=75):
- return {
- 'low':np.percentile(data,low_percentile),
- 'center':np.median(data),
- 'high':np.percentile(data,high_percentile),
- }
- def extract_sems(data,sem_multiple=2):
- sem = scipy.stats.sem(data)
- mean = np.mean(data)
- return {
- 'low':mean - (sem*sem_multiple),
- 'center':mean,
- 'high':mean + (sem*sem_multiple),
- }
- import matplotlib.patheffects as pe
- def shadow_segments_to_ax(
- ax,
- shadowed_segments,
- label=None,ax_label=None,suppress_legend=False,
- plot_shadow=True,fill_label=None,
- color=None,outline=None,
- **kwargs
- ):
- times = sorted(shadowed_segments.keys())
- ln, = ax.plot(
- times,
- [shadowed_segments[t]['center'] for t in times],
- label=label,color=color,
- **kwargs
- )
- # plot outline
- if outline:
- ln.set_path_effects([
- pe.Stroke(linewidth=ln.get_linewidth()+outline, foreground='black'),
- pe.Normal(),
- ])
- if plot_shadow:
- ax.fill_between(
- times,
- [shadowed_segments[t]['low'] for t in times],
- [shadowed_segments[t]['high'] for t in times],
- label=fill_label,alpha=.2,
- color=ln.get_color()
- )
- ax.set_xlabel("Time (h)")
- ax.set_ylabel(ax_label)
- ax.set_title(ax_label)
- if label and not suppress_legend:
- ax.legend()
- return ax
- def get_compound_masks(
- data
- ):
- times = sorted(set(data.obs['time']))
- time_masks = [
- data.obs['time'] == t
- for t in times
- ]
- control_mask = data.obs['exp_condition'] == "Cntr"
- injury_mask = data.obs['exp_condition'] == "Mtz"
- combined_masks = {
- 'control':{
- time:control_mask & time_mask for time,time_mask in zip(times,time_masks)
- },
- 'ablated':{
- time: injury_mask & time_mask for time,time_mask in zip(times,time_masks)
- }
- }
- return combined_masks
- def map_over_leaves(compound,fn):
- return {
- outer_key: {inner_key: fn(v) for inner_key, v in inner.items()}
- for outer_key, inner in compound.items()
- }
- def get_compound_scores(
- compound_masks,target
- ):
- return map_over_leaves(compound_masks,lambda mask: target[mask])
- def get_compound_iqrs(
- compound_scores
- ):
- return map_over_leaves(compound_scores, extract_iqrs)
- def get_compound_means(
- compound_scores
- ):
- return map_over_leaves(compound_scores, extract_sems)
- def plot_timecourse(
- target,compound_masks,ax,
- label=None,fill_label=None,ax_label=None,central_tendency="median",
- plot_shadow=True,suppress_legend=False,alpha=1,color=None,outline=None,linewidth=None,
- ):
- compound_scores = get_compound_scores(compound_masks,target)
- compound_shadow = None
- shadow_label = None
- match central_tendency:
- case "median":
- compound_shadow = get_compound_iqrs(compound_scores)
- shadow_label = "IQR"
- case "mean":
- compound_shadow = get_compound_means(compound_scores)
- shadow_label = "SEM"
- case _: raise ValueError(f"Invalid central tendency: {central_tendency}")
- if fill_label is not None:
- shadow_label = fill_label
- for condition in compound_shadow:
- shadow_segments_to_ax(
- ax,compound_shadow[condition],
- label=f"{label} : {condition}",
- fill_label=shadow_label,
- ax_label=ax_label,plot_shadow=plot_shadow,suppress_legend=suppress_legend,alpha=alpha,
- color=color,outline=outline, **({"linestyle":"--"} if "control" in condition else {}),linewidth=linewidth
- )
- # %%
- compound_masks = get_compound_masks(data)
- fig,axes = plt.subplots(5,10,figsize=(30,15))
- for i in range(50):
- ax = axes[i//10,i%10]
- target = data.obsm['X_pca'][:,i]
- plot_timecourse(
- target,compound_masks,ax,
- label=f"PC{i}",
- ax_label=f'PC{i}',central_tendency="median",
- )
- fig.tight_layout()
- fig.show()
- # %% [markdown]
- # # Cell Death Scoring
- # %% [markdown]
- # The particulars of producing these scores are in the sister file "annotations", but this is the set of gene sets used by the TBI guys. They can be updated with alternatives on demand. (Swap in the gene sets and map the homologs to zebrafish genome)
- #
- # We want to plot the timecourse of the score, as well as the scores over the UMAP to see if there are any obvious patterns.
- #
- # Brief note: representing an uncertainty score here is a little fraught, I'm not a huge fan of either the IQR or the SEM, the former is too vague and the latter is too conservative (as written it is treating each cell as a unique observation)
- #
- # I want to check if there are biological replicate annotations, if so we can re-calculate the SEM on a per-sample basis, which will better represent the actual variation certainty. Please stand by for this.
- # %%
- parthanatos_mask = np.array(data.var['parthanatos'])
- apoptosis_mask = np.array(data.var['apoptosis'])
- necroptosis_mask = np.array(data.var['necroptosis'])
- parthanatos_signature = data.var_names[parthanatos_mask]
- apoptosis_signature = data.var_names[apoptosis_mask]
- necroptosis_signature = data.var_names[necroptosis_mask]
- print(f"Parthanatos: {parthanatos_signature}")
- print(f"Necroptosis: {necroptosis_signature}")
- print(f"Apoptosis: {apoptosis_signature}")
- sc.tl.score_genes(data,parthanatos_signature,score_name="parthanatos")
- sc.tl.score_genes(data,necroptosis_signature,score_name="necroptosis")
- sc.tl.score_genes(data,apoptosis_signature,score_name="apoptosis")
- # %% [markdown]
- # ### Sham Signature
- # %%
- # Let's also construct a sham gene signature to get a sense for "baseline" signal
- # First we want to establish the overall number of genes in ext signatures:
- print((
- f'Parthanatos: {np.sum(data.var['parthanatos'])}\n'
- f'Necroptosis: {np.sum(data.var['necroptosis'])}\n'
- f'Apoptosis: {np.sum(data.var['apoptosis'])}\n'
- ))
- def get_sham_percentiles(
- data,
- n_shams=1000,sham_size=17,
- verbose=False,
- central_tendency="median"
- ):
- compound_masks = get_compound_masks(data)
- n_features = len(data.var_names)
- times = sorted(data.obs['time'].unique())
- lotta_sham = [np.random.randint(0,n_features,size=sham_size) for _ in range(n_shams)]
- sham_timecourses = []
- for i,sham in enumerate(lotta_sham):
- if verbose:
- print(f"sham {i}",end="\r")
- sc.tl.score_genes(data,data.var_names[sham],score_name=f'sham_tmp')
- scores = get_compound_scores(compound_masks,data.obs['sham_tmp'])
- ucl = {}
- match central_tendency:
- case "median":
- ucl = get_compound_iqrs(scores)
- case "mean":
- ucl = get_compound_means(scores)
- case _: raise ValueError(f"Invalid central tendency: {central_tendency}")
- sham_timecourses.append(ucl)
- time_deltas = []
- for timecourse in sham_timecourses:
- deltas = [timecourse['ablated'][t]['center'] - timecourse['control'][t]['center'] for t in times]
- time_deltas.append(deltas)
- time_deltas = np.array(time_deltas)
- time_deltas
- delta_quantiles = {
- t:np.percentile(time_deltas[:,i],[np.arange(100)])[0] for i,t in enumerate(times)
- }
- delta_quantiles
- return sham_timecourses,time_deltas,delta_quantiles
- def plot_quantiles_to_ax(
- quantiles,ax,
- offsets=None,
- bound_ranges=None,
- alpha_multiple=.05,
- color='blue',
- ):
- if offsets is None:
- offsets = np.array([0] * len(quantiles))
- if bound_ranges is None:
- bound_ranges = [
- (1,99),
- (5,95),
- (15,85),
- (25,75),
- ]
- times = sorted(quantiles.keys())
- for lower,upper in bound_ranges:
- lower_bound = np.array([quantiles[t][lower] for t in times]) + offsets
- upper_bound = np.array([quantiles[t][upper] for t in times]) + offsets
- ax.fill_between(
- times,upper_bound,lower_bound,
- alpha=alpha_multiple,color=color,
- label=f"_quant_{lower}_{upper}"
- )
- return ax
- from matplotlib.patches import Patch as mpl_Patch
- def label_quantiles(ax,labels=None):
- quantile_artists = [
- a for a in ax.get_children()
- if str(a.get_label()).startswith("_quant")
- ]
- if labels is None:
- bounds = [qa.get_label().split("_quant_")[1].split("_") for qa in quantile_artists]
- labels = [f"{lower}-{upper} %" for lower,upper in bounds]
- for qa,label in zip(quantile_artists,labels):
- qa.set_label(label)
- legend_entries = {
- mpl_Patch(color=qa.get_facecolor(),alpha=qa.get_alpha()*(i+1)) : qa.get_label()
- for i,qa in enumerate(quantile_artists)
- }
- return legend_entries
- # %% [markdown]
- # ### RGC Shams
- # %%
- rgc_subset = data[data.obs['cell_type'] == "RGCs"]
- _,_,rgc_delta_quantiles = get_sham_percentiles(rgc_subset,verbose=True)
- _,_,global_delta_quantiles = get_sham_percentiles(data,verbose=True)
- # %%
- plt.figure()
- plt.title("RGC-Specific Null Distribution of Signature Deltas\n Ablation vs Control")
- plot_quantiles_to_ax(rgc_delta_quantiles,plt.gca())
- plt.xlabel("Time (h)")
- plt.ylabel("Signature Delta (ablation - control, arb units)")
- plt.show()
- # %% [markdown]
- # # Timecourse Plot
- # %%
- # Let's plot a timecourse for ablation vs control globally (all cell types)
- # Reminder: masks by condition and by time
- compound_masks = get_compound_masks(data)
- times = sorted(data.obs['time'].unique())
- fig,axes = plt.subplots(1,3,figsize=(15,5))
- for ax,score in zip(axes,['parthanatos','necroptosis','apoptosis']):
- score_values = data.obs[score]
- plot_timecourse(
- score_values,compound_masks,ax,
- label=score,ax_label=score,central_tendency="median",
- plot_shadow=False,suppress_legend=True,alpha=1,
- color=score_colors[score],outline=.5
- )
- score_iqrs = get_compound_iqrs(get_compound_scores(compound_masks,score_values))
- legend_spec = {handle:label for handle,label in zip(*(ax.get_legend_handles_labels()))}
- plot_quantiles_to_ax(
- global_delta_quantiles,ax,color=score_colors[score],
- offsets=[score_iqrs['control'][t]['center'] for t in times],
- alpha_multiple=.1,
- )
- legend_spec |= label_quantiles(ax)
- ax.legend(legend_spec.keys(),legend_spec.values())
- fig.tight_layout()
- fig.show()
- # %% [markdown]
- # ### UMAP Score Plots
- # %% [markdown]
- # We can see that the distribution of the scores is similar but not fully overlapping. We can probably confirm this intuition with a bunch of pairwise scatters, but this basically tracks with the lit anyway afaik.
- # %%
- fig,axes = plt.subplots(1,3,figsize=(25,5))
- axes = axes.flatten()
- sc.pl.umap(data,color='parthanatos',ax=axes[0],show=False)
- sc.pl.umap(data,color='necroptosis',ax=axes[1],show=False)
- sc.pl.umap(data,color='apoptosis',ax=axes[2],show=False)
- fig.show()
- # %% [markdown]
- # # Subset to Retinal Ganglion Cells
- # %% [markdown]
- # We want to check if the behavior of RGCs in particular is different than the rest of the pop with respect to the scores of interest.
- #
- # We will isolate just the RGCs using leiden mapping, and then re-plot some of our previous analysis
- # %%
- score_legend_spec = {}
- quantile_legend_spec = {}
- rgc_compound_masks = get_compound_masks(rgc_subset)
- fig,axes = plt.subplots(1,3,figsize=(15,5))
- fig.suptitle("RGC-Specific Death Score Timecourse")
- for ax,score in zip(axes,['parthanatos','necroptosis','apoptosis']):
- score_values = rgc_subset.obs[score]
- plot_timecourse(
- score_values,rgc_compound_masks,ax,
- label=score,ax_label=score,central_tendency="median",
- plot_shadow=False,suppress_legend=True,alpha=1,
- color=score_colors[score],outline=.5,linewidth=2,
- )
- score_iqrs = get_compound_iqrs(get_compound_scores(rgc_compound_masks,score_values))
- legend_spec = {handle:label for handle,label in zip(*(ax.get_legend_handles_labels()))}
- score_legend_spec |= legend_spec
- plot_quantiles_to_ax(
- rgc_delta_quantiles,ax,color=score_colors[score],
- offsets=[score_iqrs['control'][t]['center'] for t in times],
- alpha_multiple=.1,
- )
- quantile_legend_spec |= label_quantiles(ax)
- # Per axis legend
- # ax.legend(legend_spec.keys(),legend_spec.values())
- # unified_legend_spec = {**score_legend_spec,**dict(list(quantile_legend_spec.items())[-4:])}
- # ax.legend(unified_legend_spec.keys(),unified_legend_spec.values(),framealpha=1)
- # Unify the axes
- y_min = min([ax.get_ylim()[0] for ax in axes])
- y_max = max([ax.get_ylim()[1] for ax in axes])
- for ax in axes:
- ax.set_ylim(y_min,y_max)
- fig.tight_layout()
- fig.savefig(f"{figure_path}/rgc_vs_sham_timecourse.png",dpi=300)
- fig.show()
- # %% [markdown]
- # # RGC Vs Rest Comparison
- # %% [markdown]
- # Let's compare the RGCs to the rest of the population to observe any differences for our scores of interest
- # %%
- rgc_mask = data.obs['cell_type'] == "RGCs"
- rgc = data[rgc_mask]
- non_rgc = data[~rgc_mask]
- times = [12,24,48,72]
- rgc_time_masks = [
- rgc.obs['time'] == t
- for t in times
- ]
- non_rgc_time_masks = [
- non_rgc.obs['time'] == t
- for t in times
- ]
- rgc_control_mask = rgc.obs['exp_condition'] == "Cntr"
- rgc_injury_mask = rgc.obs['exp_condition'] == "Mtz"
- non_rgc_control_mask = non_rgc.obs['exp_condition'] == "Cntr"
- non_rgc_injury_mask = non_rgc.obs['exp_condition'] == "Mtz"
- fig,axes = plt.subplots(1,3,figsize=(15,5))
- for i,score in enumerate(['parthanatos','necroptosis','apoptosis']):
- time_rgc_control_iqrs = {}
- time_rgc_injury_iqrs = {}
- time_non_rgc_control_iqrs = {}
- time_non_rgc_injury_iqrs = {}
- for t,(rgc_time_mask,non_rgc_time_mask) in zip(times,zip(rgc_time_masks,non_rgc_time_masks)):
- combined_rgc_control_mask = rgc_control_mask & rgc_time_mask
- combined_rgc_injury_mask = rgc_injury_mask & rgc_time_mask
- combined_non_rgc_control_mask = non_rgc_control_mask & non_rgc_time_mask
- combined_non_rgc_injury_mask = non_rgc_injury_mask & non_rgc_time_mask
- time_rgc_control_iqrs[t] = extract_iqrs(rgc.obs[score][combined_rgc_control_mask])
- time_rgc_injury_iqrs[t] = extract_iqrs(rgc.obs[score][combined_rgc_injury_mask])
- time_non_rgc_control_iqrs[t] = extract_iqrs(non_rgc.obs[score][combined_non_rgc_control_mask])
- time_non_rgc_injury_iqrs[t] = extract_iqrs(non_rgc.obs[score][combined_non_rgc_injury_mask])
- ax = axes[i]
- # We're going to discard all the IQR stuff here because the shadows make this more or less unreadable.
- # But I do think it's important to visualize this in overlay to convey the idea
- ax.plot(times, [time_rgc_control_iqrs[t]['center'] for t in times], label="RGC Control", color='r')
- ax.plot(times, [time_rgc_injury_iqrs[t]['center'] for t in times], label="RGC injury", color='b')
- ax.plot(times, [time_non_rgc_control_iqrs[t]['center'] for t in times], label="Non-RGC Control", color='r', linestyle='--',alpha=.3)
- ax.plot(times, [time_non_rgc_injury_iqrs[t]['center'] for t in times], label="Non-RGC injury", color='b', linestyle='--',alpha=.3)
- ax.set_xlabel("Time (h)")
- ax.set_ylabel(f"{score}")
- ax.set_title(f"{score} (RGC vs Non-RGC)")
- ax.legend()
- fig.tight_layout()
- fig.show()
- # %% [markdown]
- # # PCA sanity check
- # %% [markdown]
- # We should check if any computed PCs meaningfully correspond to the computed cell death scores, as this would be a simple way to verify whether or not this is a relatively orthogonal signal
- # %%
- corr = np.corrcoef(data.obsm['X_pca'].T,data.obs[['parthanatos','necroptosis','apoptosis']].T)[50:,:50]
- plt.figure()
- plt.imshow(
- corr.T,
- cmap='bwr',vmin=-1,vmax=1,
- aspect='auto'
- )
- plt.ylabel("PCs")
- plt.xticks(np.arange(3),labels=['parthanatos','necroptosis','apoptosis'])
- plt.colorbar(label="Pearson Correlation")
- plt.title("Cell Death Scores vs PCA Scores")
- plt.show()
- # %%
- parthanatos_min,parthanatos_max = np.min(corr[0]),np.max(corr[0])
- necroptosis_min,necroptosis_max = np.min(corr[1]),np.max(corr[1])
- apoptosis_min,apoptosis_max = np.min(corr[2]),np.max(corr[2])
- parthanatos_min,parthanatos_max = np.around(parthanatos_min,3),np.around(parthanatos_max,3)
- necroptosis_min,necroptosis_max = np.around(necroptosis_min,3),np.around(necroptosis_max,3)
- apoptosis_min,apoptosis_max = np.around(apoptosis_min,3),np.around(apoptosis_max,3)
- print(f"Correlations: \t\tMin\t\tMax")
- print("========================================================")
- print(f"parthanatos \t\t{parthanatos_min},\t\t{parthanatos_max}")
- print(f"necroptosis \t\t{necroptosis_min},\t\t{necroptosis_max}")
- print(f"apoptosis \t\t{apoptosis_min},\t\t{apoptosis_max}")
- # %% [markdown]
- # Apoptosis seems to have popped out as the strongest but not by a massive amount. It has (negative) 33% correlation to PC 2. PC orientation is arbitrary, so they should be considered absolute.
- # %% [markdown]
- # # Population Plot
- # %%
- from misc_utils import auto_split_range
- reduced = data[data.obs['cell_type'] != "injury"]
- def get_pairwise_proportions(data,all_cell_types):
- sizes = np.array([np.sum(data.obs['cell_type'] == t) for t in all_cell_types])
- pairwise = np.outer((1+sizes),1/(1+sizes))
- np
- return pairwise
- compound_ratios = {'ablated':{},'control':{}}
- all_cell_types = sorted(reduced.obs['cell_type'].unique())
- n_cell_types = len(all_cell_types)
- compound_masks = get_compound_masks(reduced)
- fig,axes = plt.subplots(2,4,figsize=(20,10))
- for i,condition in enumerate(compound_masks):
- for j,time in enumerate(compound_masks[condition]):
- ax = axes[i][j]
- subset = reduced[compound_masks[condition][time]]
- pairwise = get_pairwise_proportions(subset,all_cell_types)
- compound_ratios[condition][time] = pairwise
- im = ax.imshow(
- np.log(pairwise),
- **auto_split_range(np.log(pairwise),force_range=10)
- )
- plt.colorbar(im,ax=ax)
- ax.set_xticks(np.arange(n_cell_types),labels=all_cell_types,rotation=90)
- ax.set_yticks(np.arange(n_cell_types),labels=all_cell_types)
- ax.set_title(f"{condition} {time}")
- fig.tight_layout()
- fig.show()
- # %%
- fig,axes = plt.subplots(1,4,figsize=(20,5))
- fig.suptitle("Control / Ablated Ratio of Ratios")
- for time,ax in zip(compound_masks['control'],axes):
- ror = (compound_ratios['control'][time])/(compound_ratios['ablated'][time])
- im = ax.imshow(
- np.log(ror),
- **auto_split_range(np.log(ror))
- )
- ax.set_xticks(np.arange(n_cell_types),labels=all_cell_types,rotation=90)
- ax.set_yticks(np.arange(n_cell_types),labels=all_cell_types)
- plt.colorbar(im,ax=ax)
- fig.tight_layout()
- fig.show()
- # %%
time_course.ipynb at commit 900c21f, no license · at the source
Overview
and 16 other authors
Daniel J. Choe1, Caroline E. Clouatre1, Diego Alfaro Carcoba1, Barak Reibman1, Catalina Rodriguez1, Kevin Yang1, Shreya Banerjee1, Frazer Matthews1, James H. Thierer1, Genevieve Stein-O'Brien7, Ted M. Dawson4,5,7,11, Valina L. Dawson4,5,7,11, David F. Ackerley8,9, M. Valeria Canto-Soler2, Liyun Zhang1,10, Jeff S. Mumm1,7- Wilmer Eye Institute, Johns Hopkins School of Medicine, Baltimore, MD 21231, USA
- Translational Vascular Medicine Branch, National Heart, Lung and Blood Institute, National Institutes of Health, Bethesda, MD 20814, USA
- Department of Pharmaceutical Sciences, University of Illinois-Chicago, Chicago, IL 60612, USA
- Neuroregeneration and Stem Cell Programs, Institute for Cell Engineering, Johns Hopkins University School of Medicine, Baltimore, MD 21205, USA
- Department of Neurology, Johns Hopkins University School of Medicine, Baltimore, MD 21205, USA
- CellSight Ocular Stem Cell and Regeneration Research Program, Department of Ophthalmology, Sue Anschutz-Rodgers Eye Center, University of Colorado Anschutz, Aurora, CO 80045, USA
- Solomon H. Snyder Department of Neuroscience, Johns Hopkins University School of Medicine, Baltimore, MD 21205, USA
- School of Biological Sciences, Victoria University of Wellington. Wellington 6140, New Zealand
- Te Matapihipihi - The Centre for Biodiscovery and Maurice Wilkins Centre for Molecular Biodiscovery, Victoria University of Wellington, Wellington 6140, New Zealand
- Department of Ophthalmology, University of Pittsburgh, Pittsburgh, PA 15219, USA
- Department of Physiology, Pharmacology and Therapeutics, Johns Hopkins University School of Medicine, Baltimore, MD 21205, USA
Abstract
Inducible disease models enable large-scale screening by providing control over pathology onset, such as cell death in neurodegenerative disease. The nitroreductase (NTR)/
Reproduced under the paper's license (CC BY), from the paper cited above.
Repository
Its files are read in the Code ↔ Paper reader above, with 3 matches between paragraphs and lines of code.
mummlab/Cell-Death-in-NTR2.0-mediated-RGC-Ablation
900c21f8408c85500dc5d06df62160866ba0c181, 12 May 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
6 files
- deseq.ipynb, Jupyter, 350 lines
- gseapy.ipynb, Jupyter, 328 lines
- misc_utils.py, Python, 158 lines
- preprocessing_basics.ipy
nb , Jupyter, 770 lines, 1 match - time_course.ipynb, Jupyter, 647 lines, 2 matches
- README.md, Text, 1 line
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 5 scripts, each with its path and the digest of its content;
- 3 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
Datasets cited
- geo:GSE268179, at NCBI GEO; found in the text, “Transcriptomic data processing”
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 27 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 36 authors, 6 keywords, 12 MeSH terms, 11 funders, 119 references.
Cite
This paper
Ceisel, A., Graziano, G., Emmerich, K., Shi, X., Kam, T.-I., Flores-Bellver, M., Vergara, M. N., Aparicio-Domingo, S., Brenerman, B. M., Vielle, A., Williams, E. M., Sharrock, A. V., Onuchuwku, U., Martinez, G. S., Sanders, L. G., Nwagbo, U., Wang, B., Xiao, H., Kroeschell, G., . . . Mumm, J. S. (2026). Cell death analysis of inducible, titratable neurodegenerative disease models in zebrafish and human stem cell-derived retinal organoids. Disease models & mechanisms, 19(7), dmm052747. https://
BibTeX
@article{ceisel2026cell,
author = {Ceisel, Anneliese and Graziano, Gianna and Emmerich, Kevin and Shi, Xiangqian and Kam, Tae-In and Flores-Bellver, Miguel and Vergara, M. Natalia and Aparicio-Domingo, Silvia and Brenerman, Boris M. and Vielle, Anne and Williams, Elsie M. and Sharrock, Abigail V. and Onuchuwku, Uche and Martinez, Georgina S. and Sanders, Lydia G. and Nwagbo, Uzoamaka and Wang, Beichen and Xiao, Huanhuan and Kroeschell, Grant and Gao, Yiqi and Choe, Daniel J. and Clouatre, Caroline E. and Carcoba, Diego Alfaro and Reibman, Barak and Rodriguez, Catalina and Yang, Kevin and Banerjee, Shreya and Matthews, Frazer and Thierer, James H. and Stein-O'Brien, Genevieve and Dawson, Ted M. and Dawson, Valina L. and Ackerley, David F. and Canto-Soler, M. Valeria and Zhang, Liyun and Mumm, Jeff S.},
title = {{Cell death analysis of inducible, titratable neurodegenerative disease models in zebrafish and human stem cell-derived retinal organoids}},
journal = {Disease models \& mechanisms},
year = {2026},
month = jul,
volume = {19},
number = {7},
pages = {dmm052747},
publisher = {Company of Biologists},
issn = {1754-8403},
doi = {10.1242/
url = {https://
pmid = {42497345},
pmcid = {PMC13474575}
}
RIS
TY - JOUR
AU - Ceisel, Anneliese
AU - Graziano, Gianna
AU - Emmerich, Kevin
AU - Shi, Xiangqian
AU - Kam, Tae-In
AU - Flores-Bellver, Miguel
AU - Vergara, M. Natalia
AU - Aparicio-Domingo, Silvia
AU - Brenerman, Boris M.
AU - Vielle, Anne
AU - Williams, Elsie M.
AU - Sharrock, Abigail V.
AU - Onuchuwku, Uche
AU - Martinez, Georgina S.
AU - Sanders, Lydia G.
AU - Nwagbo, Uzoamaka
AU - Wang, Beichen
AU - Xiao, Huanhuan
AU - Kroeschell, Grant
AU - Gao, Yiqi
AU - Choe, Daniel J.
AU - Clouatre, Caroline E.
AU - Carcoba, Diego Alfaro
AU - Reibman, Barak
AU - Rodriguez, Catalina
AU - Yang, Kevin
AU - Banerjee, Shreya
AU - Matthews, Frazer
AU - Thierer, James H.
AU - Stein-O'Brien, Genevieve
AU - Dawson, Ted M.
AU - Dawson, Valina L.
AU - Ackerley, David F.
AU - Canto-Soler, M. Valeria
AU - Zhang, Liyun
AU - Mumm, Jeff S.
TI - Cell death analysis of inducible, titratable neurodegenerative disease models in zebrafish and human stem cell-derived retinal organoids
T2 - Disease models & mechanisms
J2 - Dis Model Mech
PY - 2026
DA - 2026/
VL - 19
IS - 7
SP - dmm052747
SN - 1754-8403
PB - Company of Biologists
DO - 10.1242/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1242/
"type": "article-journal",
"title": "Cell death analysis of inducible, titratable neurodegenerative disease models in zebrafish and human stem cell-derived retinal organoids",
"container-title": "Disease models & mechanisms",
"author": [
{
"family": "Ceisel",
"given": "Anneliese"
},
{
"family": "Graziano",
"given": "Gianna"
},
{
"family": "Emmerich",
"given": "Kevin"
},
{
"family": "Shi",
"given": "Xiangqian"
},
{
"family": "Kam",
"given": "Tae-In"
},
{
"family": "Flores-Bellver",
"given": "Miguel"
},
{
"family": "Vergara",
"given": "M. Natalia"
},
{
"family": "Aparicio-Domingo",
"given": "Silvia"
},
{
"family": "Brenerman",
"given": "Boris M."
},
{
"family": "Vielle",
"given": "Anne"
},
{
"family": "Williams",
"given": "Elsie M."
},
{
"family": "Sharrock",
"given": "Abigail V."
},
{
"family": "Onuchuwku",
"given": "Uche"
},
{
"family": "Martinez",
"given": "Georgina S."
},
{
"family": "Sanders",
"given": "Lydia G."
},
{
"family": "Nwagbo",
"given": "Uzoamaka"
},
{
"family": "Wang",
"given": "Beichen"
},
{
"family": "Xiao",
"given": "Huanhuan"
},
{
"family": "Kroeschell",
"given": "Grant"
},
{
"family": "Gao",
"given": "Yiqi"
},
{
"family": "Choe",
"given": "Daniel J."
},
{
"family": "Clouatre",
"given": "Caroline E."
},
{
"family": "Carcoba",
"given": "Diego Alfaro"
},
{
"family": "Reibman",
"given": "Barak"
},
{
"family": "Rodriguez",
"given": "Catalina"
},
{
"family": "Yang",
"given": "Kevin"
},
{
"family": "Banerjee",
"given": "Shreya"
},
{
"family": "Matthews",
"given": "Frazer"
},
{
"family": "Thierer",
"given": "James H."
},
{
"family": "Stein-O'Brien",
"given": "Genevieve"
},
{
"family": "Dawson",
"given": "Ted M."
},
{
"family": "Dawson",
"given": "Valina L."
},
{
"family": "Ackerley",
"given": "David F."
},
{
"family": "Canto-Soler",
"given": "M. Valeria"
},
{
"family": "Zhang",
"given": "Liyun"
},
{
"family": "Mumm",
"given": "Jeff S."
}
],
"container-title-short":
"volume": "19",
"issue": "7",
"page": "dmm052747",
"DOI": "10.1242/
"PMID": "42497345",
"PMCID": "PMC13474575",
"ISSN": "1754-8403",
"publisher": "Company of Biologists",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
24
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1016/j.stemcr.2026.102966
- Optimized chemogenetic ablation and regeneration of enteric nervous system neurons in zebrafish.Journal: Stem cell reportsIn common: zebrafish, 5 references, author David F. Ackerley
- [2] doi:10.1126/sciadv.aeg3223 [code]
- The extreme diversity of retinal amacrine cells has deep evolutionary roots.Journal: Science advancesIn common: anndata, Scanpy, scikit-learn, 4 other tools, cellular / molecular, 1 reference
- [3] doi:10.1016/j.celrep.2026.117270 [code]
- Blocking apoptosis promotes survival and alters developmental dynamics of human retinal ganglion cells in retinal organoids.Journal: Cell reportsIn common: anndata, Scanpy, scikit-learn, 4 other tools, 1 reference
- [4] doi:10.1016/j.xcrm.2026.102766 [code]
- A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.Journal: Cell reports. MedicineIn common: anndata, Scanpy, scikit-learn, 4 other tools, other condition, cellular / molecular, 1 reference
- [5] doi:10.1038/s41586-026-10658-6 [code]
- An AI system to help scientists write expert-level empirical software.Journal: NatureIn common: anndata, Scanpy, scikit-learn, 4 other tools, zebrafish, other condition
- [6] doi:10.1038/s41586-026-10629-x [code]
- Whole-genome duplication shaped cell-type evolution in the vertebrate brain.Journal: NatureIn common: anndata, Scanpy, scikit-learn, 4 other tools, cellular / molecular, 1 reference
- [7] doi:10.1038/s41592-026-03057-2 [code]
- CREsted: modeling genomic and synthetic cell-type-specific enhancers across tissues and species.Journal: Nature methodsIn common: anndata, Scanpy, scikit-learn, 4 other tools, zebrafish
- [8] doi:10.1371/journal.pcbi.1014327 [code]
- Supervised deep learning with gene functional annotation for cell classification.Journal: PLoS computational biologyIn common: anndata, Scanpy, scikit-learn, 4 other tools, other condition, cellular / molecular
- [9] doi:10.1038/s41593-026-02300-5 [code]
- Integrated single-cell and spatial transcriptomic profiling in ALS uncovers peripheral-to-central immune infiltration and reprogramming.Journal: Nature neuroscienceIn common: anndata, Scanpy, scikit-learn, 4 other tools, other condition, cellular / molecular
- [10] doi:10.1093/bib/bbag404 [code]
- Navigating cell maps by deep learning integration of single-cell and spatially resolved transcriptomics.Journal: Briefings in bioinformaticsIn common: anndata, Scanpy, scikit-learn, 4 other tools, other condition, cellular / molecular
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 1 repository of the authors' code, each at its verified commit and with its license, 5 scripts, and 3 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:c8c676050128ae34…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
