OSCR

Evaluating exon skipping in the central nervous system in Duchenne muscular dystrophy using spatial transcriptomics.

Code ↔ Paper

8 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 8 matches
  1. [1] § Results › Spatial localization of Dmd isoforms in the wildtype brain ↔ Xenium_marker_dotplot.ipynb, lines 94–109 · score 0.96 · DG IMN Glut, CNU HYa GABA, CTX MGE GABA, CTX CGE GABA, NP CT L6b, Astro Epen
  2. [2] § Results › Spatial divergence and coexpression of full-length and shorter Dmd isoforms in the wildtype mouse brain ↔ Xenium_marker_dotplot.ipynb, lines 94–109 · score 0.94 · CNU HYa Glut, CNU HYa GABA, CNU LGE GABA, CTX MGE GABA, NP CT L6b, OPC Oligo
  3. [3] § STAR★Methods › Method details › Differential expression analysis between exon 51-positive and exon 51-negative cells ↔ Skipping_DE.ipynb, lines 1250–1320 · score 0.87 · log fold change, rank genes, skipped positive, positive cells, Scanpy, iterations
  4. [4] § Results › Mdx52 mice show altered full-length isoform expression ↔ Xenium_marker_dotplot.ipynb, lines 172–189 · score 0.75 · medial amygdalar nucleus, olfactory areas, ventricular system, CA2, basolateral
  5. [5] § Results › Efficacy of exon 51-skipping events in the brain after therapeutic intervention ↔ Xenium_marker_dotplot.ipynb, lines 172–189 · score 0.63 · cortex L2, ventricular system, L5, CA1, L6b, cluster
  6. [6] § Results › Spatial localization of Dmd isoforms in the wildtype brain ↔ Isoform_comparison.ipynb, lines 1284–1306 · score 0.58 · Dp427p2, Dp427m, Dp427c, Dp71, Dp40, WT
  7. [7] § Results › Dp427-sized isoform restoration in exon 51-skipped cells ↔ Isoform_comparison.ipynb, lines 1146–1180 · score 0.52 · Dp427p, Dp427m, Dp427c, isoform, cells
  8. [8] § Results › Dp427-sized isoform restoration in exon 51-skipped cells ↔ Coexpression_Isoforms.ipynb, lines 41–136 · score 0.51 · Dp427p, Dp427m, Dp427c, isoform, cells

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 · 497 lines · 15 KB · GPL-3.0 · 4 matches

  1. # %%
  2. import spatialdata as sd
  3. import decoupler as dc
  4. from spatialdata_io import xenium
  5. import numpy as np
  6. import pandas as pd
  7. import scipy.sparse as sp
  8. import matplotlib as mpl
  9. import matplotlib.pyplot as plt
  10. import seaborn as sns
  11. import anndata as ad
  12. import scanpy as sc
  13. import squidpy as sq
  14. sc.set_figure_params(figsize=(12,12))
  15. mpl.rcParams['figure.dpi'] = 300
  16. # %%
  17. Sample_895=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_895.h5ad")
  18. Sample_894=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_894.h5ad")
  19. Sample_898=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_898.h5ad")
  20. Sample_896=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_896.h5ad")
  21. Sample_897=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_897.h5ad")
  22. Sample_18=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_18.h5ad")
  23. Sample_886=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_886.h5ad")
  24. Sample_890=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_890.h5ad")
  25. Sample_891=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_891.h5ad")
  26. Sample_4=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_4.h5ad")
  27. Sample_5=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_5.h5ad")
  28. Sample_3=sc.read_h5ad("/exports/archive/hg-exon-skip/Qirong/Xenium/scanpy_object/Sample_3.h5ad")
  29. # %%
  30. adatas = Sample_895.concatenate(Sample_894,Sample_898,Sample_896,Sample_897,Sample_18,Sample_886,Sample_890,Sample_891,Sample_4,Sample_5,Sample_3)
  31. # %%
  32. adatas.layers["counts"] = adatas.X.copy()
  33. adatas.obs_names_make_unique()
  34. # %%
  35. sc.pp.normalize_total(adatas)
  36. sc.pp.log1p(adatas)
  37. # %%
  38. sc.tl.rank_genes_groups(adatas, 'Class', method='wilcoxon',pts=True)
  39. # %%
  40. rank_genes_df = sc.get.rank_genes_groups_df(adatas, group=None)
  41. # %%
  42. rank_genes_df
  43. # %%
  44. rank_genes_df.to_excel("/exports/humgen/qmao/Xenium_celltype_rank_genes.xlsx", index=False, engine="openpyxl")
  45. # %%
  46. filtered_genes = rank_genes_df[(rank_genes_df['pvals_adj'] <0.05)]
  47. # %%
  48. filtered_genes
  49. # %%
  50. filtered_genes = rank_genes_df[(rank_genes_df['logfoldchanges'] > 1)]
  51. # %%
  52. filtered_genes = rank_genes_df[(rank_genes_df['logfoldchanges'] > 1) &
  53. (rank_genes_df['pct_nz_group'] > 0.7) &
  54. (rank_genes_df['pct_nz_reference'] < 0.5)]
  55. # %%
  56. top_genes_per_cluster = (
  57. filtered_genes.groupby('group') # 'group' column represents clusters
  58. .apply(lambda x: x.nlargest(3, 'logfoldchanges')) # Select top 5 genes by logFC
  59. .reset_index(drop=True)
  60. )
  61. # Extract unique gene names
  62. selected_genes = top_genes_per_cluster['names'].unique()
  63. # %%
  64. Class_order = [
  65. 'IT-ET Glut', 'NP-CT-L6b Glut', 'DG-IMN Glut', 'CTX-CGE GABA', 'CTX-MGE GABA',
  66. 'CNU-LGE GABA', 'CNU-HYa GABA', 'CNU-HYa Glut', 'HY GABA', 'HY Glut',
  67. 'MH-LH Glut', 'TH Glut', 'Astro-Epen', 'OPC-Oligo', 'Vascular', 'Immune'
  68. ]
  69. # Convert the `group` column to a categorical type with the desired order
  70. top_genes_per_cluster["group"] = pd.Categorical(
  71. top_genes_per_cluster["group"],
  72. categories=Class_order,
  73. ordered=True
  74. )
  75. # Sort the DataFrame by the `group` column
  76. top_genes_per_cluster = top_genes_per_cluster.sort_values(by="group")
  77. # %%
  78. selected_genes=top_genes_per_cluster["names"]
  79. # %%
  80. sc.pl.dotplot(adatas, var_names=selected_genes.unique(), groupby='Class', swap_axes=False,show=False, dot_max=0.5, standard_scale='var')
  81. # %%
  82. # Update rcParams for consistent formatting
  83. plt.rcParams.update({
  84. 'figure.dpi': 300,
  85. 'savefig.dpi': 300,
  86. 'font.size': 12,
  87. 'axes.titlesize': 12,
  88. 'axes.labelsize': 12,
  89. 'xtick.labelsize': 12,
  90. 'ytick.labelsize': 12,
  91. 'legend.fontsize': 12
  92. })
  93. mpl.rcParams['font.family'] = 'DejaVu Sans' # or 'Arial'
  94. mpl.rcParams['svg.fonttype'] = 'none'
  95. width_per_gene = 0.3 # inches per gene (adjust to taste)
  96. figsize = (len(selected_genes.unique()) * width_per_gene, 6)
  97. sc.pl.dotplot(adatas, var_names=selected_genes.unique(),figsize=figsize,groupby='Class', swap_axes=False,show=False,categories_order=Class_order, dot_max=1.0, dot_min=0.0, smallest_dot=0.1, standard_scale='var')
  98. plt.savefig(f"/exports/humgen/qmao/Dotplot_marker_class.svg",format="svg",dpi=300, bbox_inches='tight')
  99. plt.show()
  100. # %%
  101. sc.tl.rank_genes_groups(adatas, 'Region', method='wilcoxon',pts=True)
  102. # %%
  103. sc.tl.rank_genes_groups(adatas, 'Region', method='wilcoxon',pts=True)
  104. # %%
  105. rank_genes_df = sc.get.rank_genes_groups_df(adatas, group=None)
  106. # %%
  107. rank_genes_df.to_excel("/exports/humgen/qmao/Xenium_region_rank_genes.xlsx", index=False, engine="openpyxl")
  108. # %%
  109. filtered_genes = rank_genes_df[(rank_genes_df['logfoldchanges'] > 0.5) &
  110. (rank_genes_df['pct_nz_group'] > 0.6) &
  111. (rank_genes_df['pct_nz_reference'] < 0.5)]
  112. # %%
  113. top_genes_per_cluster = (
  114. filtered_genes.groupby('group') # 'group' column represents clusters
  115. .apply(lambda x: x.nlargest(3, 'logfoldchanges')) # Select top 5 genes by logFC
  116. .reset_index(drop=True)
  117. )
  118. # Extract unique gene names
  119. selected_genes = top_genes_per_cluster['names'].unique()
  120. # %%
  121. # Define the specific order of row names (regions)
  122. region_order = [
  123. 'Cortex L1', 'Cortex L2/3', 'Cortex L4', 'Cortex L5', 'Cortex L6a', 'Cortex L6b','Retrosplenial cortex', 'Olfactory areas',
  124. 'CA1', 'CA2/3', 'Dendate gyrus', 'HPF field', 'Thalamus 1', 'Thalamus 2', 'Reticular nucleus', 'Lateral habenula', 'Medial habenula','Hypothalamus',
  125. 'Basolateral amygdalar nucleus',
  126. 'Central amygdalar nucleus', 'Medial amygdalar nucleus', 'Caudoputamen', 'Ventricular system','Fiber tracts','Unassigned'] # Example
  127. # Convert the `group` column to a categorical type with the desired order
  128. top_genes_per_cluster["group"] = pd.Categorical(
  129. top_genes_per_cluster["group"],
  130. categories=region_order,
  131. ordered=True
  132. )
  133. # Sort the DataFrame by the `group` column
  134. top_genes_per_cluster = top_genes_per_cluster.sort_values(by="group")
  135. selected_genes=top_genes_per_cluster["names"]
  136. # %%
  137. top_genes_per_cluster
  138. # %%
  139. selected_genes=top_genes_per_cluster["names"]
  140. adatas.obs["Region"].cat.reorder_categories(region_order)
  141. # %%
  142. # Update rcParams for consistent formatting
  143. plt.rcParams.update({
  144. 'figure.dpi': 300,
  145. 'savefig.dpi': 300,
  146. 'font.size': 12,
  147. 'axes.titlesize': 12,
  148. 'axes.labelsize': 12,
  149. 'xtick.labelsize': 12,
  150. 'ytick.labelsize': 12,
  151. 'legend.fontsize': 12
  152. })
  153. mpl.rcParams['font.family'] = 'DejaVu Sans' # or 'Arial'
  154. mpl.rcParams['svg.fonttype'] = 'none'
  155. width_per_gene = 0.3 # inches per gene (adjust to taste)
  156. figsize = (len(selected_genes.unique()) * width_per_gene, 8)
  157. sc.pl.dotplot(adatas, var_names=selected_genes.unique(),figsize=figsize,groupby='Region', swap_axes=False,show=False,categories_order=region_order, dot_max=1.0, dot_min=0.0, smallest_dot=0.1, standard_scale='var')
  158. plt.savefig(f"/exports/humgen/qmao/Dotplot_marker_region.svg",format="svg",dpi=300, bbox_inches='tight')
  159. plt.show()
  160. # %%
  161. import matplotlib.pyplot as plt
  162. import seaborn as sns
  163. import numpy as np
  164. adata=adatas
  165. # Replace with your gene names
  166. gene1 = "Slc17a7"
  167. gene2 = "Gfap"
  168. # Extract log-normalized expression values
  169. x = adata[:, gene1].X.toarray().flatten() if hasattr(adata[:, gene1].X, 'toarray') else adata[:, gene1].X.flatten()
  170. y = adata[:, gene2].X.toarray().flatten() if hasattr(adata[:, gene2].X, 'toarray') else adata[:, gene2].X.flatten()
  171. # Plot
  172. plt.figure(figsize=(6, 6))
  173. sns.scatterplot(x=x, y=y, s=10, alpha=0.6)
  174. plt.xlabel(f'{gene1} (Raw)')
  175. plt.ylabel(f'{gene2} (Raw)')
  176. plt.title(f'Scatter Plot: {gene1} vs {gene2}')
  177. plt.grid(True)
  178. plt.show()
  179. # %%
  180. # %%
  181. # %%
  182. counts_df=counts_df.fillna(0)
  183. # %%
  184. counts_df
  185. # %%
  186. # Step 1: Calculate the total number of cells for each sample (i.e., sum across rows for each column)
  187. total_cells_per_sample = counts_df.sum(axis=0)
  188. # Step 2: Calculate the percentage of cells in each region for each sample
  189. percentage_df = counts_df.div(total_cells_per_sample, axis=1) * 100
  190. # %%
  191. total_cells_per_sample
  192. # %%
  193. percentage_df
  194. # %%
  195. ### Immune
  196. # %%
  197. # List of AnnData objects (e.g., adata1, adata2, ...)
  198. adatas = [Sample_895, Sample_894, Sample_898,Sample_896,Sample_897,Sample_18,Sample_886,Sample_890,Sample_891,Sample_4,Sample_5,Sample_3,Sample_706,Sample_707,Sample_709T] # Replace with your actual AnnData objects
  199. # Initialize an empty list to store the counts per region for each sample in each AnnData object
  200. region_counts = []
  201. # Loop through each AnnData object to count occurrences of regions
  202. for adata in adatas:
  203. # Count the occurrences of each region in the "Regions" column
  204. adata = adata[adata.obs["Class"].isin(["Immune"]), :]
  205. counts_per_region = adata.obs["Region"].value_counts()
  206. # Append the result (this will be a pandas Series for each adata)
  207. region_counts.append(counts_per_region)
  208. # Convert the list of Series into a DataFrame
  209. counts_df = pd.DataFrame(region_counts).transpose()
  210. # Label columns (each corresponds to an AnnData object)
  211. counts_df.columns = [f"adata{i+1}" for i in range(len(adatas))]
  212. counts_df.columns = [adata.obs["Sample"].iloc[0] for adata in adatas]
  213. # %%
  214. # Define the specific order of row names (regions)
  215. region_order = [
  216. 'Cortex L1', 'Cortex L2/3', 'Cortex L4', 'Cortex L5', 'Cortex L6a', 'Cortex L6b','Retrosplenial cortex', 'Olfactory areas',
  217. 'CA1', 'CA2/3', 'Dendate gyrus', 'HPF field', 'Thalamus 1', 'Thalamus 2', 'Reticular nucleus', 'Lateral habenula', 'Medial habenula','Hypothalamus',
  218. 'Basolateral amygdalar nucleus',
  219. 'Central amygdalar nucleus', 'Medial amygdalar nucleus', 'Caudoputamen', 'Ventricular system','Fiber tracts','Unassigned'] # Example
  220. # Reorder rows based on the desired order (ensure all regions in `desired_region_order` exist in the counts_df index)
  221. counts_df = counts_df.loc[region_order]
  222. # %%
  223. counts_df=counts_df.fillna(0)
  224. # %%
  225. counts_df
  226. # %%
  227. # Step 1: Calculate the total number of cells for each sample (i.e., sum across rows for each column)
  228. total_cells_per_sample = counts_df.sum(axis=0)
  229. # Step 2: Calculate the percentage of cells in each region for each sample
  230. percentage_df = counts_df.div(total_cells_per_sample, axis=1) * 100
  231. # %%
  232. total_cells_per_sample
  233. # %%
  234. percentage_df
  235. # %%
  236. sq.pl.spatial_scatter(
  237. Sample_4,
  238. library_id="spatial",
  239. shape=None,
  240. color=[
  241. "Region",
  242. ],
  243. wspace=0.4,
  244. )
  245. # %%
  246. sq.pl.spatial_scatter(
  247. Sample_4,
  248. library_id="spatial",
  249. shape=None,
  250. color=[
  251. "Class",
  252. ],
  253. wspace=0.4,
  254. )
  255. # %%
  256. # List of AnnData objects (e.g., adata1, adata2, ...)
  257. adatas = [Sample_895, Sample_894, Sample_898,Sample_896,Sample_897,Sample_18,Sample_886,Sample_890,Sample_891,Sample_4,Sample_5,Sample_3,Sample_706,Sample_707,Sample_709T] # Replace with your actual AnnData objects
  258. # Initialize an empty list to store the counts per region for each sample in each AnnData object
  259. region_counts = []
  260. # Loop through each AnnData object to count occurrences of regions
  261. for adata in adatas:
  262. # Count the occurrences of each region in the "Regions" column
  263. counts_per_region = adata.obs["Class"].value_counts()
  264. # Append the result (this will be a pandas Series for each adata)
  265. region_counts.append(counts_per_region)
  266. # Convert the list of Series into a DataFrame
  267. counts_df = pd.DataFrame(region_counts).transpose()
  268. # Label columns (each corresponds to an AnnData object)
  269. counts_df.columns = [f"adata{i+1}" for i in range(len(adatas))]
  270. counts_df.columns = [adata.obs["Sample"].iloc[0] for adata in adatas]
  271. # %%
  272. counts_df.fillna(0)
  273. # %%
  274. df=counts_df
  275. # Plot stacked barplot
  276. fig, ax = plt.subplots(figsize=(8, 6))
  277. # Cumulative bottom for stacking
  278. bottom = None
  279. # Define colors for each category
  280. colors = ['skyblue', 'orange', 'green']
  281. # Loop through each row (category)
  282. for (category, row_values), color in zip(df.iterrows(), colors):
  283. ax.bar(df.columns, row_values, label=category, bottom=bottom, color=color)
  284. bottom = row_values if bottom is None else bottom + row_values
  285. # Customizations
  286. ax.set_ylabel("Counts")
  287. ax.set_title("Stacked Barplot of Count Table")
  288. ax.legend(title="Category")
  289. plt.show()
  290. # %%
  291. percentage_df = counts_df.div(counts_df.fillna(0).sum(axis=0), axis=1) * 100
  292. # %%
  293. percentage_df.T.plot(kind="bar", stacked=True, figsize=(10, 6), cmap="tab20")
  294. # %%
  295. percentage_df
  296. # %%
  297. # List of AnnData objects (e.g., adata1, adata2, ...)
  298. adatas = [Sample_895, Sample_894, Sample_898,Sample_896,Sample_897,Sample_18,Sample_886,Sample_890,Sample_891,Sample_4,Sample_5,Sample_3,Sample_706,Sample_707,Sample_709T] # Replace with your actual AnnData objects
  299. region_labels = Sample_895.obs["Region"].unique()
  300. # Initialize an empty list to store the counts per region for each sample in each AnnData object
  301. region_counts = []
  302. # Loop through each AnnData object to count occurrences of regions
  303. for adata in adatas:
  304. for region_label in region_labels:
  305. # Count the occurrences of each region in the "Regions" column
  306. adata = adata[adata.obs["Region"].isin([region_label]), :]
  307. counts_per_region = adata.obs["Class"].value_counts()
  308. # Append the result (this will be a pandas Series for each adata)
  309. region_counts.append(counts_per_region)
  310. # Convert the list of Series into a DataFrame
  311. counts_df = pd.DataFrame(region_counts).transpose()
  312. # Label columns (each corresponds to an AnnData object)
  313. counts_df.columns = [f"adata{i+1}" for i in range(len(adatas))]
  314. counts_df.columns = [adata.obs["Sample"].iloc[0] for adata in adatas]
  315. # %%
  316. # List of AnnData objects (e.g., adata1, adata2, ...)
  317. adatas = [Sample_895, Sample_894, Sample_898,Sample_896,Sample_897,Sample_18,Sample_886,Sample_890,Sample_891,Sample_4,Sample_5,Sample_3,Sample_706,Sample_707,Sample_709T] # Replace with your actual AnnData objects
  318. region_labels = Sample_895.obs["Region"].unique()
  319. # Initialize an empty list to store the counts per region for each sample in each AnnData object
  320. # Initialize dictionaries to store count and percentage DataFrames by region
  321. region_counts_dfs = {}
  322. region_percentages_dfs = {}
  323. # Iterate over each region label
  324. for region_label in region_labels:
  325. # Filter columns corresponding to the current region
  326. region_columns = [col for col in region_counts_df.columns if f"_{region_label}" in col]
  327. # Create a DataFrame for the current region
  328. region_df = region_counts_df[region_columns]
  329. # Rename columns to sample names
  330. region_df.columns = [col.split('_')[0] for col in region_columns]
  331. # Store the count DataFrame
  332. region_counts_dfs[region_label] = region_df
  333. # Calculate percentages by dividing each value by the column total and multiplying by 100
  334. region_percentages_df = region_df.div(region_df.sum(axis=0), axis=1) * 100
  335. # Store the percentage DataFrame
  336. region_percentages_dfs[region_label] = region_percentages_df
  337. # %%
  338. region_dfs["Cortex L5"]
  339. # %%
  340. region_dfs["Hypothalamus"]
  341. # %%
  342. region_percentages_dfs["Hypothalamus"]
  343. # %%
  344. region_dfs["Fiber tracts"]
  345. # %%
  346. region_dfs["Thalamus 2"]
  347. # %%
  348. region_percentages_dfs["Thalamus 2"]
  349. # %%
  350. region_dfs["Cortex L6b"]
  351. # %%
  352. region_percentages_dfs["Cortex L6b"]
  353. # %%

Xenium_marker_dotplot.ipynb at commit 47b52cd, under GPL-3.0 · at the source

Overview

Authors: Qirong Mao1, Alireza Ahmadi1, Sharon de Vries1, Laura GM Heezen1, Ophélie Vacca2, Mathilde Doisy2, Annemieke Aartsma-Rus1,3, Maaike van Putten1,3, Aurélie Goyenvalle2, Ahmed Mahfouz1,4, Pietro Spitali1,3
  1. Department of Human Genetics, Leiden University Medical Center, Leiden, the Netherlands
  2. Université Paris-Saclay, UVSQ, Inserm, END-ICAP, Versailles, France
  3. Duchenne Center Netherlands, the Netherlands
  4. Delft Bioinformatics Lab, Delft University of Technology, Delft, the Netherlands
Journal: iScience, volume 29, issue 8, article 116906
Dates: received 8 January 2026; accepted 7 July 2026; published online 23 July 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1016/j.isci.2026.116906 · PMID 42542656 · PMCID PMC13427662 · OpenAlex W7170180882
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), mouse (organism), other condition (population), clinical / translational (subfield)
Methods: Connectivity, Spectral & time-frequency, Statistics
Keywords: Duchenne muscular dystrophy, central nervous system, dystrophin isoforms, exon-skipping therapy, spatial transcriptomics
Topic: Muscle Physiology and Disorders (Molecular Biology, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Funding: Leids Universitair Medisch Centrum; Université Paris-Saclay; Horizon 2020 (847826); Niigata University; Institut National de la Santé et de la Recherche Médicale; Horizon 2020 Framework Programme
Citations: not cited yet (Europe PMC); 70 references in the paper

Abstract

Duchenne muscular dystrophy (DMD) causes progressive muscle degeneration due to dystrophin deficiency. Dystrophin is also expressed in the brain during development and postnatally, yet a characterization of dystrophin isoform expression across brain cells and regions is lacking, limiting our understanding of the cognitive impairment affecting one-third of the patients and hampering the development of dystrophin-restoring drugs in the central nervous system (CNS). Here, we applied spatial transcriptomics to map Dmd isoforms across mouse brain regions and cell types. Mdx52 mice received exon 51-skipping therapies restoring the Dp427-sized isoform at the transcript and protein levels. We observed distinct spatial patterns: full-length isoforms localized to deeper cortical layers and CA1, while shorter isoforms were enriched in cortical layer 1 and dentate gyrus. We present evidence of isoform restoration, immune activation following treatment, and a framework to evaluate exon-skipping therapies in the CNS using spatial transcriptomics.

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 8 matches between paragraphs and lines of code.

Qirongmao97/Xenium_DMD_brain

License: GPL-3.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 47b52cdeea5441f8cf059863a3e7876f60e7e83e, 6 July 2026
Languages: Jupyter (13), R (1)
Size: 16 files, 14 scripts
Software Heritage: not archived
Found in: “Data and code availability”
Holds: README, license file, 13 notebooks
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Matplotlib (8 files), pandas (8 files), anndata (7 files), NumPy (7 files), Scanpy (7 files), seaborn (7 files), SciPy (6 files), Squidpy (6 files), data.table (1 file), ggplot2 (1 file), Seurat (1 file), statannotations (1 file), statsmodels (1 file), tidyverse (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
12 files

The paper's code and data availability statement is in the Data section.

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;
  • 10 scripts, each with its path and the digest of its content;
  • 8 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

Data and code availability

Raw and processed Xenium data have been deposited in NCBI’s Gene Expression Omnibus and are accessible through Series accession number GSE318507 (https://ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE318507) (https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE318507) and are publicly available as of the date of publication.

As a reference for cell type annotation, adult mouse scRNA-seq (v2 chemistry) from the Allen Brain Atlas can be downloaded from the public data repository (https://allen-brain-cell-atlas.s3.us-west-2.amazonaws.com/index.html#expression_matrices/WMB-10Xv2/20230630/).

All analysis scripts and code used for data preprocessing and visualization are provided in a public GitHub repository (https://github.com/Qirongmao97/Xenium_DMD_brain) and are publicly available as of the date of publication.

Any additional information required to reanalyze the data reported in this paper is available from the corresponding authors upon request.

Reproduced under the paper's license (CC BY), from the paper cited above.

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 2, 28 September 2026

  • Authors: added Qirong Mao (0000-0001-7938-6660); Pietro Spitali (0000-0003-2783-688X); removed Qirong Mao; Pietro Spitali

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 11 authors, 5 keywords, 6 funders, 67 references, 5 RRIDs.

Cite

This paper

Mao, Q., Ahmadi, A., de Vries, S., Heezen, L. G., Vacca, O., Doisy, M., Aartsma-Rus, A., van Putten, M., Goyenvalle, A., Mahfouz, A., & Spitali, P. (2026). Evaluating exon skipping in the central nervous system in Duchenne muscular dystrophy using spatial transcriptomics. iScience, 29(8), 116906. https://doi.org/10.1016/j.isci.2026.116906

BibTeX

@article{mao2026evaluating,
author = {Mao, Qirong and Ahmadi, Alireza and de Vries, Sharon and Heezen, Laura GM and Vacca, Ophélie and Doisy, Mathilde and Aartsma-Rus, Annemieke and van Putten, Maaike and Goyenvalle, Aurélie and Mahfouz, Ahmed and Spitali, Pietro},
title = {{Evaluating exon skipping in the central nervous system in Duchenne muscular dystrophy using spatial transcriptomics}},
journal = {iScience},
year = {2026},
month = jul,
volume = {29},
number = {8},
pages = {116906},
publisher = {Elsevier},
issn = {2589-0042},
doi = {10.1016/j.isci.2026.116906},
url = {https://doi.org/10.1016/j.isci.2026.116906},
pmid = {42542656},
pmcid = {PMC13427662}
}

RIS

TY - JOUR
AU - Mao, Qirong
AU - Ahmadi, Alireza
AU - de Vries, Sharon
AU - Heezen, Laura GM
AU - Vacca, Ophélie
AU - Doisy, Mathilde
AU - Aartsma-Rus, Annemieke
AU - van Putten, Maaike
AU - Goyenvalle, Aurélie
AU - Mahfouz, Ahmed
AU - Spitali, Pietro
TI - Evaluating exon skipping in the central nervous system in Duchenne muscular dystrophy using spatial transcriptomics
T2 - iScience
J2 - iScience
PY - 2026
DA - 2026/07/23
VL - 29
IS - 8
SP - 116906
SN - 2589-0042
PB - Elsevier
DO - 10.1016/j.isci.2026.116906
UR - https://doi.org/10.1016/j.isci.2026.116906
LA - en
ER -

CSL-JSON

{
"id": "10.1016/j.isci.2026.116906",
"type": "article-journal",
"title": "Evaluating exon skipping in the central nervous system in Duchenne muscular dystrophy using spatial transcriptomics",
"container-title": "iScience",
"author": [
{
"family": "Mao",
"given": "Qirong"
},
{
"family": "Ahmadi",
"given": "Alireza"
},
{
"family": "de Vries",
"given": "Sharon"
},
{
"family": "Heezen",
"given": "Laura GM"
},
{
"family": "Vacca",
"given": "Ophélie"
},
{
"family": "Doisy",
"given": "Mathilde"
},
{
"family": "Aartsma-Rus",
"given": "Annemieke"
},
{
"family": "van Putten",
"given": "Maaike"
},
{
"family": "Goyenvalle",
"given": "Aurélie"
},
{
"family": "Mahfouz",
"given": "Ahmed"
},
{
"family": "Spitali",
"given": "Pietro"
}
],
"container-title-short": "iScience",
"volume": "29",
"issue": "8",
"page": "116906",
"DOI": "10.1016/j.isci.2026.116906",
"PMID": "42542656",
"PMCID": "PMC13427662",
"ISSN": "2589-0042",
"publisher": "Elsevier",
"URL": "https://doi.org/10.1016/j.isci.2026.116906",
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
23
]
]
}
}

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.1038/s41592-026-03194-8 [code]
Beyond benchmarking: an expert-guided consensus approach to spatially aware clustering.
Journal: Nature methods
In common: Squidpy, anndata, Scanpy, 9 other tools, genetics / omics, 4 references, author Ahmed Mahfouz
[2] doi:10.1016/j.cell.2026.05.047 [code]
An emergent disease-associated motor neuron state precedes cell death in ALS.
Journal: Cell
In common: Squidpy, statannotations, anndata, 10 other tools, genetics / omics, other condition, mouse, 3 references
[3] doi:10.1038/s42003-026-10034-0 [code]
Region- and cell type-specific changes in gene expression in the cerebellum after classical fear conditioning.
Journal: Communications biology
In common: Squidpy, anndata, Scanpy, 10 other tools, genetics / omics, mouse, 3 references
[4] doi:10.1186/s13059-026-04177-w [code]
Genomic sequence evolution underlying human neocortical interareal diversification.
Journal: Genome biology
In common: Squidpy, anndata, Scanpy, 9 other tools, genetics / omics, mouse, 3 references
[5] doi:10.1038/s41467-026-71759-4 [code]
CellNiche represents cellular microenvironments in atlas-scale spatial omics data with contrastive learning.
Journal: Nature communications
In common: Squidpy, anndata, Scanpy, 5 other tools, other condition, mouse, 6 references
[6] doi:10.1038/s41467-026-71803-3 [code]
Charting the transition from in vitro gliogenesis to the in vivo maturation of human glial progenitor cells transplanted into the hypomyelinated mouse brain.
Journal: Nature communications
In common: Squidpy, anndata, Scanpy, 9 other tools, genetics / omics, mouse, 2 references
[7] doi:10.1038/s41467-026-68596-w [code]
Spatial cartography of human thymus enables the geopositioning of lineage transcription factors in rare mimetic thymic epithelial cells.
Journal: Nature communications
In common: Squidpy, anndata, Scanpy, 9 other tools, genetics / omics, 2 references
[8] doi:10.1186/s13073-026-01704-z [code]
Gene expression profiling enables refined parcellation of cortical layers in the heterogeneous human cerebral cortex.
Journal: Genome medicine
In common: anndata, Scanpy, Seurat, 8 other tools, genetics / omics, mouse, 3 references
[9] doi:10.21203/rs.3.rs-9676637/v1 [code]
A Comprehensive Benchmarking of Spatial Deconvolution and Domain Detection Methods across Diverse Tissues and Spatial Transcriptomic Technologies
Journal: Research Square (preprint)
In common: Squidpy, anndata, Scanpy, 9 other tools, genetics / omics, 1 reference
[10] doi:10.1016/j.isci.2026.116055 [code]
Mapping the transcriptional diversity of calcium signaling in the mouse and human brain.
Journal: iScience
In common: Squidpy, anndata, Scanpy, 9 other tools, genetics / omics, mouse, 1 reference

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.

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.