OSCR

A multimodal spatial atlas of transcriptomic, morphological, and electrophysiological cell type densities in the mouse brain.

Code ↔ Paper

14 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 14 matches · 1 of them tie a paragraph to a whole file without given lines: a weak match, whose lines are not tinted
  1. [1] § Methods › Alignment of transcriptomic cell types with morphology and electrophysiology › Alignment of mRNA to established neuronal t-types. ↔ densities_app/Validation_compute_m_type_gene_expressions.ipynb, lines 89 to 190 · score 0.94 · log2 nonzero expression, gene selection, near zero, selects genes, gene expression, decay · Report a mismatch
  2. [2] § Methods › Atlas construction: whole-brain, voxel-scale cell-type density atlas › Estimation of cutting angles and coronal region volumes for MERFISH sections. ↔ t-types/notebooks/density1.1_missing_regions-Copy1.ipynb, lines 48 to 64 · score 0.79 · Golgi cells, Bergman glia, Purkinje cells, Purkinje layers, neurotransmitter, GABA · Report a mismatch
  3. [3] § Methods › Atlas construction: whole-brain, voxel-scale cell-type density atlas › Estimation of cutting angles and coronal region volumes for MERFISH sections. ↔ t-types/density1.1_missing_regions.py, lines 47 to 80 · score 0.76 · Golgi cells, Bergman glia, Purkinje cells, neurotransmitter, GABA, Glut · Report a mismatch
  4. [4] § Methods › Atlas construction: whole-brain, voxel-scale cell-type density atlas › Cell Density Estimation and Scaling Across Brain Regions. ↔ t-types/density1_estimation_all_region_53slices_average_reconstcords_voxvol.py, lines 74 to 115 · score 0.73 · voxelized region, parcellation substructures, region volumes, neurotransmitter, division, intersecting · Report a mismatch
  5. [5] § Methods › Atlas construction: whole-brain, voxel-scale cell-type density atlas › Cell Density Estimation and Scaling Across Brain Regions. ↔ t-types/notebooks/density1_estimation_all_region_53slices_average_reconstcords_voxvol-Copy1.ipynb, lines 29 to 104 · score 0.72 · parcellation substructures, MERFISH cell, region volumes, neurotransmitter, division, intersecting · Report a mismatch
  6. [6] § Methods › Alignment of transcriptomic cell types with morphology and electrophysiology › Elbow method to determine the number of clusters. ↔ densities_app/Validation_compute_m_type_gene_expressions.ipynb, lines 580 to 674 · score 0.72 · optimal cluster, UMAP projected, WCSS, Elbow, compositions, model · Report a mismatch
  7. [7] § Methods › Atlas construction: whole-brain, voxel-scale cell-type density atlas › Estimation of cutting angles and coronal region volumes for MERFISH sections. ↔ t-types/notebooks/density1_estimation_all_region_53slices_average_reconstcords_voxvol-Copy1.ipynb, lines 29 to 104 · score 0.72 · x_ccf, y_ccf, region ID, reconstructed, template, voxel · Report a mismatch
  8. [8] § Methods › Alignment of transcriptomic cell types with morphology and electrophysiology › Alignment of mRNA to established neuronal t-types. ↔ t-types/scripts/calc_av_jobarray_classesonly_writegpfs.py, the whole file · a weak match · score 0.71 · gene identifiers, gene expression, AnnData, libraries, trimmed, log2 · Report a mismatch
  9. [9] § Methods › Alignment of transcriptomic cell types with morphology and electrophysiology › Elbow method to determine the number of clusters. ↔ densities_app/transcribe_t_types_to_me_types.ipynb, lines 191 to 321 · score 0.69 · optimal cluster, UMAP projected, WCSS, Elbow, model, density · Report a mismatch
  10. [10] § Results › Data quality, technical considerations, and validation of density estimates ↔ t-types/notebooks/density5_calculate_total_cells_newjson-Copy1.ipynb, lines 1036 to 1095 · score 0.59 · fiber tracts, cerebral nuclei, olfactory areas, thresholds, cell · Report a mismatch
  11. [11] § Results › Data quality, technical considerations, and validation of density estimates ↔ t-types/notebooks/density1.3_print_info_unscaled-Copy1.ipynb, lines 164 to 202 · score 0.57 · fiber tracts, cerebral nuclei, olfactory areas, literature, validation · Report a mismatch
  12. [12] § Methods › Atlas construction: whole-brain, voxel-scale cell-type density atlas › Extending CCFv3’s hierarchical annotations and parcellations for comprehensive dataset integration. ↔ t-types/density0.1_update_parcellation_annotation_with_CRB_MOB.py, lines 18 to 68 · score 0.54 · Purkinje layers, glomerular layer, olfactory bulb, parcellation term, lobules, ontology · Report a mismatch
  13. [13] § Methods › Alignment of transcriptomic cell types with morphology and electrophysiology › Elbow method to determine the number of clusters. ↔ densities_app/Validation_compute_m_type_gene_expressions.ipynb, lines 410 to 495 · score 0.53 · mRNA, gene expression, Semilogarithmic, log10, brain regions, summed · Report a mismatch
  14. [14] § Methods › Alignment of transcriptomic cell types with morphology and electrophysiology › Elbow method to determine the number of clusters. ↔ densities_app/Validation_compute_m_type_gene_expressions.ipynb, lines 580 to 674 · score 0.52 · UMAP projection, UMAP1, UMAP2, composition, Elbow, cluster · Report a mismatch

Paper

Loaded from Europe PMC by your browser; OSCR does not store it: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Jupyter notebook · 816 lines · 29 KB · Apache-2.0 · 4 matches

  1. # %%
  2. !pip freeze
  3. # %%
  4. import pandas as pd
  5. import numpy as np
  6. # %%
  7. import pandas as pd
  8. import numpy as np
  9. extended_p_me_t = pd.read_csv("../probabilistic_mapping_extention/extended_p_me_t.csv", index_col=0)
  10. common_t_types = extended_p_me_t.index
  11. msk_t_types = np.asarray([("IMN" not in x) & ("NN" not in x) for x in common_t_types])
  12. common_t_types = common_t_types[msk_t_types]
  13. extended_p_me_t = extended_p_me_t.reindex(common_t_types, axis=0)
  14. extended_p_me_t = extended_p_me_t.div(np.sum(extended_p_me_t, axis=1), axis=0)
  15. np.sum(extended_p_me_t,axis=1)
  16. # %%
  17. # mt_labels = pd.read_csv("../probabilistic_mapping_extention/t_and_m_types.csv", index_col=0)
  18. # dict_mclass = {0.0: "PC", 1.0: "IN"}
  19. # dict_dendclass = {x: "dend_" + str(int(x)) for x in np.unique(mt_labels["dendrites"])}
  20. # dict_axclass = {x: "ax_" + str(int(x)) for x in np.unique(mt_labels["axon"])}
  21. # dict_mlabels = {"class": dict_mclass, "dendrites": dict_dendclass, "axon": dict_axclass}
  22. # m_labels = ["_".join([dict_mlabels["class"][mt_labels["class"][x]],
  23. # dict_mlabels["dendrites"][mt_labels["dendrites"][x]],
  24. # dict_mlabels["axon"][mt_labels["axon"][x]]
  25. # ]) for x in mt_labels.index]
  26. # t_labels = mt_labels["AIBS lvl 0"]
  27. # %%
  28. neur_list = ["IN_", "PC_"]
  29. dend_list = [f"dend_{x}_" for x in range(10)]
  30. ax_list = [f"ax_{x}" for x in range(10)]
  31. m_types_list = []
  32. for neur in neur_list:
  33. for dend in dend_list:
  34. for ax in ax_list:
  35. m_types_list.append(neur+dend+ax)
  36. pd.DataFrame(m_types_list, columns=["canonical m-type"]).to_csv("/Users/yroussel/Documents/projects/probabilistic_mapping_wholebrain/lida_m_types/m_types_list.csv")
  37. # %%
  38. import mygene
  39. def convert_gene_tags_to_labels(dataframe):
  40. """
  41. Convert gene tags to gene labels using MyGeneInfo API.
  42. :param dataframe: Pandas DataFrame containing gene tags as column names.
  43. :return: Pandas DataFrame with gene labels replacing gene tags.
  44. """
  45. mg = mygene.MyGeneInfo()
  46. ens = dataframe.columns.to_list()
  47. ginfo = mg.querymany(ens, scopes='ensembl.gene')
  48. dict_id_to_symbol = {}
  49. for g in ginfo:
  50. try:
  51. dict_id_to_symbol[g["query"]] = g["symbol"]
  52. except:
  53. dict_id_to_symbol[g["query"]] = g["query"]
  54. return dataframe.rename(dict_id_to_symbol, axis=1)
  55. yao = pd.read_csv("../experimental_data/yao/all_clusters_trim_mean25_g32285ct5322.csv", index_col="gene_identifier").T
  56. # yao = convert_gene_tags_to_labels(yao)
  57. # %%
  58. # df = pd.concat([yao.T[t_labels].T,
  59. # pd.DataFrame(m_labels, index=t_labels, columns=["m_type"])],
  60. # axis=1)
  61. # df.head()
  62. # %%
  63. # mean_df = df.groupby("m_type").mean()
  64. # std_df = df.groupby("m_type").std()
  65. # sum_df = df.groupby("m_type").sum()
  66. # %%
  67. from scipy import sparse
  68. import seaborn as sns
  69. import matplotlib.pyplot as plt
  70. def geneSelection(data, threshold=0, atleast=10,
  71. yoffset=.02, xoffset=5, decay=1.5, n=None,
  72. plot=True, markers=None, genes=None, figsize=(6,3.5),
  73. markeroffsets=None, labelsize=10, alpha=1, verbose=1):
  74. if sparse.issparse(data):
  75. zeroRate = 1 - np.squeeze(np.array((data>threshold).mean(axis=0)))
  76. A = data.multiply(data>threshold)
  77. # A.data = np.log2(A.data)
  78. A.data = A.data
  79. meanExpr = np.zeros_like(zeroRate) * np.nan
  80. detected = zeroRate < 1
  81. meanExpr[detected] = np.squeeze(np.array(A[:,detected].mean(axis=0))) / (1-zeroRate[detected])
  82. else:
  83. zeroRate = 1 - np.mean(data>threshold, axis=0)
  84. meanExpr = np.zeros_like(zeroRate) * np.nan
  85. detected = zeroRate < 1
  86. mask = data[:,detected]>threshold
  87. logs = np.zeros_like(data[:,detected]) * np.nan
  88. # logs[mask] = np.log2(data[:,detected][mask])
  89. logs[mask] = data[:,detected][mask]
  90. meanExpr[detected] = np.nanmean(logs, axis=0)
  91. lowDetection = np.array(np.sum(data>threshold, axis=0)).squeeze() < atleast
  92. zeroRate[lowDetection] = np.nan
  93. meanExpr[lowDetection] = np.nan
  94. if n is not None:
  95. up = 10
  96. low = 0
  97. for t in range(100):
  98. nonan = ~np.isnan(zeroRate)
  99. selected = np.zeros_like(zeroRate).astype(bool)
  100. selected[nonan] = zeroRate[nonan] > np.exp(-decay*(meanExpr[nonan] - xoffset)) + yoffset
  101. if np.sum(selected) == n:
  102. break
  103. elif np.sum(selected) < n:
  104. up = xoffset
  105. xoffset = (xoffset + low)/2
  106. else:
  107. low = xoffset
  108. xoffset = (xoffset + up)/2
  109. if verbose>0:
  110. print('Chosen offset: {:.2f}'.format(xoffset))
  111. else:
  112. nonan = ~np.isnan(zeroRate)
  113. selected = np.zeros_like(zeroRate).astype(bool)
  114. selected[nonan] = zeroRate[nonan] > np.exp(-decay*(meanExpr[nonan] - xoffset)) + yoffset
  115. if plot:
  116. if figsize is not None:
  117. plt.figure(figsize=figsize)
  118. plt.ylim([0, 1])
  119. if threshold>0:
  120. plt.xlim([np.log2(threshold), np.ceil(np.nanmax(meanExpr))])
  121. # plt.xlim([threshold, np.ceil(np.nanmax(meanExpr))])
  122. else:
  123. plt.xlim([0, np.ceil(np.nanmax(meanExpr))])
  124. x = np.arange(plt.xlim()[0], plt.xlim()[1]+.1,.1)
  125. y = np.exp(-decay*(x - xoffset)) + yoffset
  126. if decay==1:
  127. plt.text(.4, 0.2, '{} genes selected\ny = exp(-x+{:.2f})+{:.2f}'.format(np.sum(selected),xoffset, yoffset),
  128. color='k', fontsize=labelsize, transform=plt.gca().transAxes)
  129. else:
  130. plt.text(.4, 0.2, '{} genes selected\ny = exp(-{:.1f}*(x-{:.2f}))+{:.2f}'.format(np.sum(selected),decay,xoffset, yoffset),
  131. color='k', fontsize=labelsize, transform=plt.gca().transAxes)
  132. plt.plot(x, y, color=sns.color_palette()[1], linewidth=2)
  133. xy = np.concatenate((np.concatenate((x[:,None],y[:,None]),axis=1), np.array([[plt.xlim()[1], 1]])))
  134. t = plt.matplotlib.patches.Polygon(xy, color=sns.color_palette()[1], alpha=.4)
  135. plt.gca().add_patch(t)
  136. plt.scatter(meanExpr, zeroRate, s=1, alpha=alpha, rasterized=True)
  137. if threshold==0:
  138. plt.xlabel('Mean log2 nonzero expression')
  139. plt.ylabel('Frequency of zero expression')
  140. else:
  141. plt.xlabel('Mean log2 nonzero expression')
  142. plt.ylabel('Frequency of near-zero expression')
  143. plt.tight_layout()
  144. if markers is not None and genes is not None:
  145. if markeroffsets is None:
  146. markeroffsets = [(0, 0) for g in markers]
  147. for num,g in enumerate(markers):
  148. i = np.where(genes==g)[0]
  149. plt.scatter(meanExpr[i], zeroRate[i], s=10, color='k')
  150. dx, dy = markeroffsets[num]
  151. plt.text(meanExpr[i]+dx+.1, zeroRate[i]+dy, g, color='k', fontsize=labelsize)
  152. return selected
  153. selected_genes_level0 = geneSelection(yao.values, threshold=0, atleast=10,
  154. yoffset=.02, xoffset=5, decay=1.5)
  155. selected_genes_level0 = yao.columns[selected_genes_level0]
  156. # %%
  157. # x = std_df[selected_genes_level0].mean(axis=0)
  158. # y = std_df[selected_genes_level0].std(axis=0)
  159. # plt.plot(x, y, "o")
  160. # selected_genes_level1 = (x < 2) & (y > 1.5)
  161. # plt.plot(x[selected_genes_level1], y[selected_genes_level1], "o")
  162. # selected_genes_level1 = selected_genes_level0[selected_genes_level1]
  163. # plt.xlabel('in m-type gene variability (std)')
  164. # plt.ylabel('cross m-type gene variability (std)')
  165. # plt.show()
  166. # %%
  167. # m_type_gene_expression = convert_gene_tags_to_labels(mean_df[selected_genes_level1])
  168. # m_type_gene_expression.to_csv('./m_type_gene_expression.csv')
  169. # %%
  170. # m_type_gene_expression.head(3)
  171. # %%
  172. # m_type_gene_expression_sum = convert_gene_tags_to_labels(sum_df[selected_genes_level1])
  173. # m_type_gene_expression_sum.to_csv('./m_type_gene_expression_sum.csv')
  174. # %%
  175. # t_type_gene_expression = convert_gene_tags_to_labels(df[selected_genes_level1].drop_duplicates())
  176. # t_type_gene_expression.to_csv('./t_type_gene_expression.csv')
  177. # %%
  178. # t_type_gene_expression = t_type_gene_expression.rename({x : "_".join(x.split(" ")) for x in t_type_gene_expression.index}, axis=0)
  179. # %%
  180. # %%
  181. file = './Brain_regions_me_types_composition.csv'
  182. me_types_densities = pd.read_csv(file, index_col=0, header=[0, 1])
  183. # Sum the columns within each "m-type" group
  184. m_types_densities = me_types_densities.T.groupby(level='m-type').sum().T
  185. me_types_densities.columns = [f"{col[0]}|{col[1]}" for col in me_types_densities.columns]
  186. m_types_densities.head()
  187. # %%
  188. import pickle
  189. import pandas as pd
  190. def concatenate_dataframes(dataframes_dict):
  191. """
  192. Concatenates a dictionary of DataFrames into a single DataFrame.
  193. Parameters:
  194. - dataframes_dict (dict): Dictionary where keys are strings and values are DataFrames with a single column named 'density'.
  195. Returns:
  196. - pd.DataFrame: A single concatenated DataFrame with columns renamed to the keys of the input dictionary.
  197. """
  198. # Create an empty list to hold the renamed DataFrames
  199. renamed_dfs = []
  200. # Iterate over the dictionary
  201. for key, df in dataframes_dict.items():
  202. # Rename the 'density' column to the key
  203. renamed_df = df.rename(columns={'density_mm3': key})
  204. # Append the renamed DataFrame to the list
  205. renamed_dfs.append(renamed_df)
  206. # Concatenate all DataFrames along the columns
  207. concatenated_df = pd.concat(renamed_dfs, axis=1)
  208. return concatenated_df
  209. # Open the pickle file in binary read mode
  210. with open('./scaled_densities_t_types_as_keys.pickle', 'rb') as file:
  211. # Load the data from the file
  212. data = pickle.load(file)
  213. # Now you can use the data variable which contains the deserialized object
  214. # print(data)
  215. sorted_data = {k: data[k] for k in sorted(data)}
  216. t_densities_df = concatenate_dataframes(sorted_data)
  217. t_tpes_dict = {x: x.replace(" ", "_") for x in t_densities_df.columns}
  218. t_densities_df = t_densities_df.rename(t_tpes_dict, axis=1)
  219. t_densities_df.head()
  220. # %%
  221. # %%
  222. # t_densities_df.columns
  223. # len(common_ttypes)
  224. # t_densities_df[common_ttypes]
  225. # t_type_gene_expression.T[common_ttypes].T
  226. # %%
  227. # common_ttypes = t_type_gene_expression.index.intersection(t_densities_df.columns)
  228. # ish_true = t_densities_df[common_ttypes].fillna(0) @ t_type_gene_expression.T[common_ttypes].T.fillna(0)
  229. # %%
  230. # common_mtypes = m_type_gene_expression.index.intersection(m_types_densities.columns)
  231. # ish_pred = m_types_densities[common_mtypes].fillna(0) @ m_type_gene_expression.T[common_mtypes].T.fillna(0)
  232. # ish_pred_sum = m_types_densities[common_mtypes].fillna(0) @ m_type_gene_expression_sum.T[common_mtypes].T.fillna(0)
  233. # %%
  234. extended_p_me_t
  235. # %%
  236. yao_df = yao.rename({x : "_".join(x.split(" ")) for x in yao.index}, axis=0)
  237. comon_yaotypes = yao_df.index.intersection(extended_p_me_t.index)
  238. comon_yaotypes = comon_yaotypes[extended_p_me_t.T[comon_yaotypes].fillna(0).sum() > 0]
  239. common_ttypes = comon_yaotypes.intersection(t_densities_df.columns)
  240. ttype_gene_expression = convert_gene_tags_to_labels(yao_df[selected_genes_level0][selected_genes_level0].T[common_ttypes].fillna(0).T)
  241. me_type_gene_expression = ttype_gene_expression.T @ extended_p_me_t.T[common_ttypes].T.fillna(0)
  242. me_type_gene_expression = me_type_gene_expression.T
  243. common_brain_regions = t_densities_df.index.intersection(me_types_densities.index)
  244. me_types_densities = t_densities_df.reindex(common_brain_regions)[common_ttypes].fillna(0) @ extended_p_me_t.T[common_ttypes].T.fillna(0)
  245. # common_metypes = me_type_gene_expression.index.intersection(me_types_densities.columns)
  246. me_types_used = extended_p_me_t.columns[extended_p_me_t.T[comon_yaotypes].fillna(0).sum(axis=1) > 0]
  247. correction = (len(comon_yaotypes) / len(me_types_used))
  248. ish_me = me_types_densities.reindex(common_brain_regions).fillna(0) / correction @ me_type_gene_expression / correction
  249. ish_true = t_densities_df.reindex(common_brain_regions)[common_ttypes].fillna(0) @ ttype_gene_expression
  250. # %%
  251. print(len(me_types_used))
  252. print(len(comon_yaotypes))
  253. print((len(me_types_used)/ len(comon_yaotypes))**2)
  254. # %%
  255. print(me_type_used)
  256. # %%
  257. print(
  258. np.mean(t_densities_df.reindex(common_brain_regions)[common_ttypes].fillna(0), axis=1).mean(),
  259. np.mean(me_types_densities.reindex(common_brain_regions).fillna(0), axis=1).mean()
  260. )
  261. print(
  262. ttype_gene_expression.mean().mean(),
  263. me_type_gene_expression.mean().mean()
  264. )
  265. (len(common_ttypes) / len(me_types_densities.columns)) **2
  266. # %%
  267. plt.figure(figsize=(20,4))
  268. plt.semilogy(np.sum(t_densities_df.reindex(common_brain_regions)[common_ttypes].fillna(0), axis=1), 'o')
  269. plt.semilogy(np.sum(me_types_densities.reindex(common_brain_regions).fillna(0), axis=1), 'o', alpha=.5)
  270. plt.xticks(rotation=90)
  271. plt.show()
  272. plt.figure(figsize=(20,4))
  273. plt.semilogy(np.abs(
  274. np.sum(t_densities_df.reindex(common_brain_regions)[common_ttypes].fillna(0), axis=1) - np.sum(me_types_densities.reindex(common_brain_regions).fillna(0), axis=1)
  275. ),
  276. 'o')
  277. plt.xticks(rotation=90)
  278. plt.show()
  279. # %%
  280. plt.figure(figsize=(20,4))
  281. plt.semilogy(np.sum(ttype_gene_expression, axis=0), 'o')
  282. plt.semilogy(np.sum(me_type_gene_expression, axis=0), 'o', alpha=.5)
  283. plt.xticks(rotation=90)
  284. plt.show()
  285. # %%
  286. # %%
  287. from sklearn.preprocessing import StandardScaler
  288. # ish_pred = StandardScaler().fit_transform(ish_pred)
  289. # ish_true = StandardScaler().fit_transform(ish_true)
  290. # err = np.abs(ish_pred - ish_true) / np.abs(ish_true)
  291. # err_sum = np.abs(ish_pred_sum - ish_true) / np.abs(ish_true)
  292. err_me = np.abs(ish_me - ish_true + 1e-1) / np.abs(ish_true + 1e-1)
  293. err_me
  294. # %%
  295. me_types_used = extended_p_me_t.columns[extended_p_me_t.T[comon_yaotypes].fillna(0).sum(axis=1) > 0]
  296. (len(comon_yaotypes) / len(me_types_used))**2
  297. # %%
  298. plt.figure(figsize=(12,4))
  299. plt.plot(extended_p_me_t.T[comon_yaotypes].fillna(0).sum(), 'o')
  300. plt.xticks(rotation=90)
  301. plt.show()
  302. plt.figure(figsize=(12,4))
  303. plt.plot(extended_p_me_t.T[comon_yaotypes].fillna(0).sum(axis=1), 'o')
  304. plt.xticks(rotation=90)
  305. plt.show()
  306. # %%
  307. showed_brain_regions
  308. # %%
  309. # Defining the global font properties
  310. plt.rcParams.update({
  311. 'font.size': 16, # Default font size for text
  312. 'font.family': 'Helvetica Neue', # Font family (e.g., 'serif', 'sans-serif')
  313. 'axes.titleweight': 'bold', # Title font weight (e.g., 'bold', 'normal')
  314. 'axes.labelsize': 12, # Font size for axis labels
  315. 'xtick.labelsize': 8, # Font size for x-tick labels
  316. 'ytick.labelsize': 8, # Font size for y-tick labels
  317. 'figure.titlesize': 16, # Font size for figure title
  318. 'figure.titleweight': 'bold',# Font weight for figure title
  319. 'axes.titlepad': 20, # Padding between title and plot
  320. 'figure.figsize': (10, 6), # Default figure size (width, height)
  321. 'axes.titlelocation': 'center' # Center-align the title
  322. })
  323. showed_brain_regions = common_brain_regions[::20].drop('y')
  324. showed_genes = ish_true.columns[::10]
  325. plt.figure(figsize=(11.8,4))
  326. plt.subplot(221)
  327. plt.semilogy(err_me.sum()[showed_genes], 'o')
  328. plt.xticks([], [], rotation=90)
  329. plt.ylabel(r'$\sum_{regions}^{} \frac{|mRNA_{t} - mRNA_{me}|}{mRNA_{t}}$')
  330. plt.subplot(222)
  331. plt.semilogy(err_me.T.sum()[showed_brain_regions], 'o')
  332. plt.xticks([], [], rotation=90)
  333. plt.ylabel(r'$\sum_{genes}^{} \frac{|mRNA_{t} - mRNA_{me}|}{mRNA_{t}}$')
  334. plt.subplot(223)
  335. plt.semilogy(ish_true.sum()[showed_genes], 'o')
  336. plt.semilogy((ish_me).sum()[showed_genes], 'o') #/70
  337. plt.ylabel(r'$\sum_{regions}^{} mRNA$')
  338. plt.xticks(rotation=90)
  339. plt.legend([r'$mRNA_{t}$', r'$mRNA_{me}$'])
  340. plt.subplot(224)
  341. plt.semilogy(ish_true.T.sum()[showed_brain_regions], 'o')
  342. plt.semilogy(ish_me.T.sum()[showed_brain_regions], 'o') #/70
  343. plt.ylabel(r'$\sum_{genes}^{} mRNA$')
  344. plt.xticks(rotation=90)
  345. plt.legend([r'$mRNA_{t}$', r'$mRNA_{me}$'])
  346. plt.tight_layout()
  347. plt.show()
  348. plt.figure(figsize=(11.8,11.8/3))
  349. plt.subplot(131)
  350. plt.imshow(np.log10(ish_true.reindex(showed_brain_regions)[showed_genes] + 1), vmin=0, vmax=7)
  351. plt.title(r'$log_{10}(mRNA_{t})$')
  352. plt.xticks(np.arange(len(showed_genes)), showed_genes, rotation=90)
  353. plt.yticks(np.arange(len(showed_brain_regions)), showed_brain_regions)
  354. # plt.colorbar()
  355. plt.subplot(132)
  356. plt.imshow(np.log10(ish_me.reindex(showed_brain_regions)[showed_genes] + 1), vmin=0, vmax=7)
  357. plt.title(r'$log_{10}(mRNA_{me})$')
  358. plt.xticks(np.arange(len(showed_genes)), showed_genes, rotation=90)
  359. plt.yticks(np.arange(len(showed_brain_regions)), showed_brain_regions)
  360. plt.yticks([], [])
  361. # plt.colorbar()
  362. plt.subplot(133)
  363. plt.imshow(np.log10(err_me.reindex(showed_brain_regions)[showed_genes] + 1), vmin=0, vmax=7)
  364. plt.title(r'$log_{10}(\frac{|mRNA_{t} - mRNA_{me}|}{mRNA_{t}})$')
  365. plt.xticks(np.arange(len(showed_genes)), showed_genes, rotation=90)
  366. plt.yticks(np.arange(len(showed_brain_regions)), showed_brain_regions)
  367. plt.yticks([], [])
  368. # plt.colorbar()
  369. plt.tight_layout()
  370. plt.show()
  371. plt.figure(figsize=(11.8/3,11.8/3))
  372. plt.imshow(np.log10(err_me.reindex(showed_brain_regions)[showed_genes] + 1), vmin=0, vmax=7)
  373. plt.title(r'$log_{10}(\frac{|mRNA_{t} - mRNA_{me}|}{mRNA_{t}})$')
  374. plt.xticks(np.arange(len(showed_genes)), showed_genes, rotation=90)
  375. plt.xticks([], [])
  376. plt.yticks(np.arange(len(showed_brain_regions)), showed_brain_regions)
  377. plt.yticks([], [])
  378. plt.colorbar(label=r'$density \ log_{10}$', location='bottom', orientation='horizontal')
  379. plt.show()
  380. # %%
  381. print(
  382. ish_true.sum().sum(),
  383. (ish_me).sum().sum(),
  384. (ish_true.sum().sum() - (ish_me).sum().sum() )/ ish_true.sum().sum()
  385. )
  386. # %%
  387. ish_true
  388. # %%
  389. ish_me/26.5
  390. # %%
  391. import matplotlib.pyplot as plt
  392. def plot_map(data, title, filename):
  393. """Plot and save heatmap of data."""
  394. plt.figure(figsize=(5, 3))
  395. heatmap = plt.pcolor(data.values, cmap="jet")
  396. # for y in range(data.shape[0]):
  397. # for x in range(data.shape[1]):
  398. # if 0 < data.values[y, x] < 1.:
  399. # plt.text(x + 0.5, y + 0.5, int(100 * data.values[y, x]),
  400. # horizontalalignment='center',
  401. # verticalalignment='center')
  402. plt.colorbar(heatmap, label =r"$log_{10}(mm^{3})$")
  403. plt.xticks(np.arange(len(data.columns)) + .5, data.columns, rotation=90)
  404. plt.yticks(np.arange(len(data.index)) + .5, data.index)
  405. plt.title(title)
  406. # plt.tight_layout()
  407. plt.savefig(filename)
  408. # %%
  409. # showed_brain_regions_heatmap = common_brain_regions[::20].drop('y')
  410. me_types_used_heatmap = me_types_used[::12]
  411. plot_map(np.log10(me_types_densities.reindex(showed_brain_regions)[me_types_used_heatmap] + 1.),
  412. r"$me-types \ densities$",
  413. "me_types_densities_.png")
  414. plt.show()
  415. # %%
  416. import pandas as pd
  417. import umap
  418. import matplotlib.pyplot as plt
  419. def plot_umap(df, types, showed_reg):
  420. """
  421. Plot a UMAP of the dataset and print the sample names next to the datapoints.
  422. Parameters:
  423. df (pd.DataFrame): Input dataframe with sample names as the index and feature values as the values.
  424. """
  425. # Initialize UMAP model
  426. reducer = umap.UMAP()
  427. # Fit and transform the data
  428. embedding = reducer.fit_transform(df.values)
  429. # Create a scatter plot
  430. plt.figure(figsize=(5, 5))
  431. plt.scatter(embedding[:, 0], embedding[:, 1], s=100, alpha=0.5)
  432. # Annotate points with sample names
  433. for i, sample_name in enumerate(df.index):
  434. if sample_name in showed_reg:
  435. plt.annotate(sample_name, (embedding[i, 0], embedding[i, 1]), fontsize=9, alpha=0.75)
  436. # Set plot title and labels
  437. plt.title(f'UMAP of the {types} compositon')
  438. plt.xlabel('UMAP1')
  439. plt.ylabel('UMAP2')
  440. # Show the plot
  441. plt.show()
  442. # %%
  443. showed_brain_regions_umap = common_brain_regions[::10].drop('y')
  444. plot_umap(np.log10(me_types_densities + 1), "me-types", showed_brain_regions_umap)
  445. plot_umap(np.log10(t_densities_df[common_ttypes].fillna(0) + 1), "t-types", showed_brain_regions_umap)
  446. # %%
  447. import pandas as pd
  448. import umap
  449. import matplotlib.pyplot as plt
  450. from sklearn.cluster import KMeans
  451. from scipy.cluster.hierarchy import dendrogram, linkage
  452. import seaborn as sns
  453. def plot_umap_and_clusters(df, types, showed_reg, max_clusters=10):
  454. """
  455. Plot a UMAP projection and perform clustering.
  456. Use the Elbow Method to determine the optimal number of clusters.
  457. Plot a dendrogram and a bar plot of e-type distribution within clusters.
  458. Parameters:
  459. df (pd.DataFrame): Input dataframe with sample names as the index and feature values as the values.
  460. max_clusters (int): Maximum number of clusters to test for the Elbow Method.
  461. """
  462. # Initialize UMAP model
  463. reducer = umap.UMAP()
  464. # Fit and transform the data
  465. embedding = reducer.fit_transform(df.values)
  466. # Determine the optimal number of clusters using the Elbow Method
  467. wcss = []
  468. for n in range(1, max_clusters + 1):
  469. kmeans = KMeans(n_clusters=n, random_state=42)
  470. # kmeans.fit(embedding)
  471. kmeans.fit_predict(df.values)
  472. wcss.append(kmeans.inertia_)
  473. # Plot the Elbow Method graph
  474. plt.figure(figsize=(5, 2.5))
  475. plt.plot(range(1, max_clusters + 1), wcss, marker='o')
  476. plt.title('Elbow Method for Optimal Number of Clusters')
  477. plt.xlabel('Number of clusters')
  478. plt.ylabel('WCSS')
  479. plt.show()
  480. # Ask the user to input the optimal number of clusters based on the Elbow plot
  481. optimal_clusters = int(input("Enter the optimal number of clusters based on the Elbow plot: "))
  482. # Perform K-Means clustering with the selected number of clusters
  483. kmeans = KMeans(n_clusters=optimal_clusters, random_state=42)
  484. df['cluster'] = kmeans.fit_predict(embedding)
  485. # df['cluster'] = kmeans.fit_predict(df.values)
  486. df['cluster'] = ['cluster_' + str(x) for x in df['cluster']]
  487. # Plot UMAP projection with cluster labels
  488. plt.figure(figsize=(11.8 / 3, 4))
  489. scatter = plt.scatter(embedding[:, 0], embedding[:, 1],
  490. c=[int(x.split("_")[1]) for x in df['cluster']],
  491. cmap='viridis', s=100, alpha=0.5)
  492. # plt.title('UMAP projection with K-Means clusters')
  493. plt.title(f'{types} compositon UMAP')
  494. plt.xlabel('UMAP1')
  495. plt.ylabel('UMAP2')
  496. plt.legend(*scatter.legend_elements(), title="Clusters", fontsize=8)
  497. # Annotate points with sample names
  498. for i, sample_name in enumerate(df.index):
  499. if sample_name in showed_reg:
  500. plt.annotate(sample_name, (embedding[i, 0], embedding[i, 1]), fontsize=9, alpha=0.75)
  501. plt.show()
  502. # try:
  503. # # Hierarchical Clustering and Dendrogram
  504. # Z = linkage(df.drop('cluster', axis=1), method='ward')
  505. # plt.figure(figsize=(30, 8))
  506. # dendrogram(Z, labels=df.index, leaf_rotation=90, leaf_font_size=8, color_threshold=0)
  507. # plt.title('Hierarchical Clustering Dendrogram')
  508. # plt.xlabel('Sample Index')
  509. # plt.ylabel('Distance')
  510. # plt.show()
  511. # except:
  512. # print("HCA error")
  513. # try:
  514. # # Bar plot of e-type distribution within clusters
  515. # cluster_counts = df.groupby('cluster').size()
  516. # type_distribution = df.groupby(['cluster'])[df.columns[:-1]].sum()
  517. # # e_type_distribution_percent = e_type_distribution.div(cluster_counts, axis=0) * 100
  518. # type_distribution_percent = type_distribution.div(np.sum(type_distribution, axis=1), axis=0) * 100
  519. # type_distribution_percent.plot(kind='bar', stacked=True, figsize=(5, 5), colormap='jet')
  520. # plt.title('Type Distribution within Clusters')
  521. # plt.xlabel('Cluster')
  522. # plt.ylabel('Percentage')
  523. # # plt.legend(title='Type', bbox_to_anchor=(1.05, 1), loc='upper left')
  524. # plt.show()
  525. # except:
  526. # print("bar plot error")
  527. return df
  528. # %%
  529. showed_brain_regions_umap = common_brain_regions[::10].drop('y')
  530. me_types_densities_clusters = plot_umap_and_clusters(np.log10(me_types_densities + 1.),
  531. "me-types",
  532. showed_brain_regions_umap,
  533. max_clusters=20)
  534. # %%
  535. t_types_densities_clusters = plot_umap_and_clusters(np.log10(t_densities_df[common_ttypes].fillna(0) + 1),
  536. "t-types",
  537. showed_brain_regions_umap,
  538. max_clusters=20)
  539. # %%
  540. import seaborn as sns
  541. # Merge the two dataframes on index and keep only the cluster columns
  542. df_merged = pd.DataFrame({'cluster_t': t_types_densities_clusters['cluster'], 'cluster_me': me_types_densities_clusters['cluster']})
  543. # Create the contingency table using `pd.crosstab`
  544. contingency_table = pd.crosstab(df_merged['cluster_me'], df_merged['cluster_t'])
  545. # Plot the contingency table as a heatmap
  546. plt.figure(figsize=(11.8 / 3, 4))
  547. sns.heatmap(contingency_table, annot=True, cmap="YlGnBu", cbar=True)
  548. plt.xlabel("t-types clusters")
  549. plt.ylabel("me-types clusters")
  550. plt.title("Shared Regions Between Clusters")
  551. plt.show()
  552. # %%
  553. def get_example_indices(df_me):
  554. # Group by the cluster column and get the first index from each cluster
  555. example_indices = df_me.groupby('cluster').apply(lambda x: x.index[0])
  556. return example_indices
  557. def create_pie_charts(df, df_c, example_indices, threshold=1):
  558. # Determine the layout of subplots based on the number of clusters
  559. n_clusters = len(example_indices)
  560. n_cols = 3 # Define how many columns per row
  561. n_rows = (n_clusters + n_cols - 1) // n_cols # Calculate rows needed
  562. fig, axes = plt.subplots(n_rows, n_cols, figsize=(11.8, (11.8 / n_cols) * n_rows))
  563. axes = axes.flatten() # Flatten to make indexing easier
  564. # Loop over each region and create a pie chart in a subplot
  565. for i, reg in enumerate(example_indices):
  566. data = df.T[reg].T
  567. values = data / data.sum() # Normalize to get percentages
  568. labels = data.index
  569. # Filter out labels with less than threshold percentage
  570. filtered_labels = [label if pct > threshold else '' for label, pct in zip(labels, values * 100)]
  571. filtered_pct = [f'{pct:.1f}%' if pct > threshold else '' for pct in values * 100]
  572. # Plot pie chart in the corresponding subplot
  573. axes[i].pie(values, labels=filtered_labels, autopct=lambda pct: f'{pct:.1f}%' if pct > threshold else '', startangle=140)
  574. axes[i].set_title(f'{reg} ({df_c["cluster"][reg]})')
  575. # Remove any unused subplots
  576. for j in range(i + 1, len(axes)):
  577. fig.delaxes(axes[j])
  578. # plt.tight_layout()
  579. plt.show()
  580. # %%
  581. import matplotlib.pyplot as plt
  582. import matplotlib.colors as mcolors
  583. import numpy as np
  584. def get_example_indices(df_me):
  585. # Group by the cluster column and get the first index from each cluster
  586. example_indices = df_me.groupby('cluster').apply(lambda x: x.index[0])
  587. return example_indices
  588. def create_pie_charts(df, df_c, example_indices, threshold=1):
  589. # Determine the layout of subplots based on the number of clusters
  590. n_clusters = len(example_indices)
  591. n_cols = 3 # Define how many columns per row
  592. n_rows = (n_clusters + n_cols - 1) // n_cols # Calculate rows needed
  593. fig, axes = plt.subplots(n_rows, n_cols, figsize=(11.8, (11.8 / n_cols) * n_rows))
  594. axes = axes.flatten() # Flatten to make indexing easier
  595. # Define a perceptually uniform colormap
  596. cmap = colormaps["jet"]
  597. colors = cmap(np.linspace(0, 1, len(df.index))) # Generate distinct colors for all labels
  598. # Loop over each region and create a pie chart in a subplot
  599. for i, reg in enumerate(example_indices):
  600. data = df.T[reg].T
  601. values = data / data.sum() # Normalize to get percentages
  602. labels = data.index
  603. # Filter out labels with less than threshold percentage
  604. filtered_labels = [label if pct > threshold else '' for label, pct in zip(labels, values * 100)]
  605. filtered_pct = [f'{pct:.1f}%' if pct > threshold else '' for pct in values * 100]
  606. # Select corresponding colors
  607. chart_colors = [colors[j] for j in range(len(labels))]
  608. # Plot pie chart in the corresponding subplot
  609. axes[i].pie(
  610. values,
  611. labels=filtered_labels,
  612. autopct=lambda pct: f'{pct:.1f}%' if pct > threshold else '',
  613. startangle=140,
  614. colors=chart_colors
  615. )
  616. axes[i].set_title(f"{reg} ({df_c['cluster'][reg]})")
  617. # Remove any unused subplots
  618. for j in range(i + 1, len(axes)):
  619. fig.delaxes(axes[j])
  620. plt.tight_layout()
  621. plt.show()
  622. # %%
  623. showed_brain_regions
  624. # %%
  625. example_indices
  626. # %%
  627. from matplotlib import colormaps
  628. cmap = colormaps["jet"]
  629. example_indices = get_example_indices(me_types_densities_clusters.reindex(showed_brain_regions))
  630. create_pie_charts(me_types_densities, me_types_densities_clusters, example_indices, threshold=4.9)
  631. # %%
  632. example_indices = get_example_indices(t_types_densities_clusters.reindex(showed_brain_regions))
  633. create_pie_charts(t_densities_df[common_ttypes].fillna(0), t_types_densities_clusters, example_indices, threshold=4.9)
  634. # %%

Validation_compute_m_type_gene_expressions.ipynb at commit b55ee2e, under Apache-2.0 · at the source

Overview

Authors: Csaba Verasztó1, Yann Roussel1, Lida Kanari1,2, Sébastien Piluso1, Henry Markram1,3, Daniel Keller1,3
  1. Blue Brain Project, École polytechnique fédérale de Lausanne (EPFL), Geneva, Switzerland
  2. Department of Mathematics, University of Oxford, Oxford, United Kingdom
  3. Open Brain Institute, Lausanne, Switzerland
Institutions: École Polytechnique Fédérale de Lausanne (Switzerland); University of Oxford (United Kingdom); Open Brain Institute (Switzerland)
Journal: PLoS computational biology, volume 22, issue 3, article e1014106
Dates: received 15 July 2025; accepted 7 March 2026; published online 24 March 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1371/journal.pcbi.1014106 · PMID 41875149 · PMCID PMC13120702 · OpenAlex W7140225840
Open access: gold, a free copy (OpenAlex)
Status: code verified (how the code is found and verified)
Categories: genetics / omics (modality), mouse (organism), cellular / molecular (subfield)
Methods: Connectivity, Smoothing, state filtering, decompositions, Machine learning, Statistics
MeSH: Brain*, Neurons*, Transcriptome*, Animals, Cell Count, Computational Biology, Electrophysiological Phenomena, Gene Expression Profiling, Mice, Spatial Transcriptomics (* major topic)
Journal subjects: Biology and Life Sciences, Computational Biology, Genome Analysis, Transcriptome Analysis, Genetics, Genomics, Cell Biology, Cellular Types, Animal Cells, Neurons, Neuroscience, Cellular Neuroscience, Physiology, Electrophysiology, Anatomy, Nervous System, Central Nervous System, Medicine and Health Sciences, Research and Analysis Methods, Bioassays and Physiological Analysis, Electrophysiological Techniques, Brain Electrophysiology, Neurophysiology, Earth Sciences, Geography, Cartography, Neuronal Morphology, Neuronal Dendrites
Topic: Single-cell and spatial transcriptomics (Molecular Biology, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Citations: not cited yet (Europe PMC); 66 references in the paper

Abstract

Brain cells can be classified according to their transcriptomic, morphological, and electrophysiological features. Comprehensive data on the spatial density of cell types that integrate all three properties are critical for improving models of how neuronal diversity contributes to brain function, yet existing atlases lack this information. To address this gap, we created a quantitative, three-dimensional atlas of cell type density distributions in the mouse brain. We began by generating a transcriptomic cell type atlas, scaling regional density estimates from brain slices using cell counts and anatomical dimensions. For densely populated regions like the cerebellum, we further refined these estimates by applying voxel-wise corrections based on average Nissl staining intensity. To connect transcriptomic identities with functional characteristics, we leveraged patch-sequencing datasets that combine single-neuron mRNA profiles, morphological reconstructions, and electrophysiological recordings from cortical neurons. Transcriptomic types were determined from gene expression data, morphological types were assigned based on structural reconstructions, and electrophysiological types were identified using K-means clustering. The resulting whole-brain atlas (consisting of 5274 transcriptomic clusters and 458 functional morphological-electrophysiological types) and computational tools offer a high-resolution (25 μm3 voxel size), integrative resource compatible with a broad range of neuroscience applications and enable the parsing of individual cell types to reveal previously unrecognized features.

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

Repositories

Its files are read in the Code ↔ Paper reader above, with 14 matches between paragraphs and lines of code.

BlueBrain/Molsys-transcriptomic-atlas

License: Apache-2.0
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: 1b3064e95e59f8397b3bddcde294279d35699024, 19 December 2024
Languages: Python (15), Jupyter (14), Shell (5)
Size: 38 files, 34 scripts
Software Heritage: not archived
Found in: “Data Availability”
Holds: README, license file, 14 notebooks
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: pandas (29 files), NumPy (28 files), Matplotlib (7 files), SciPy (6 files), SimpleITK (3 files), anndata (2 files), OpenCV (2 files), seaborn (1 file)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
36 files

cveraszto/TME-types

License: MIT
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: 2a04aabfb4fef7e3fbade6e1eec258491d5a3201, 3 March 2026
Languages: Jupyter (18), Python (6), Shell (2)
Size: 28 files, 26 scripts
Software Heritage: not archived
Found in: “Data Availability”
Holds: README, environment (requirements.txt), 18 notebooks
Not found: license file, CITATION.cff, tests, continuous integration, documentation
Tools: pandas (24 files), NumPy (23 files), SciPy (7 files), Matplotlib (6 files), anndata (4 files), OpenCV (1 file), seaborn (1 file), SimpleITK (1 file)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
27 files

YannRoussel/probabilistic_mapping_extention

License: Apache-2.0
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: b55ee2e8d8bf3f654630511b4240283d60164249, 10 March 2026
Languages: Jupyter (19), Python (15), Shell (2)
Size: 1,156 files, 36 scripts
Software Heritage: not archived
Found in: “Data Availability”
Holds: README, license file, environment (pyproject.toml, requirements.txt), 15 notebooks
Not found: CITATION.cff, tests, continuous integration, documentation
Tools: NumPy (9 files), pandas (9 files), Matplotlib (5 files), scikit-learn (4 files), SciPy (4 files), seaborn (4 files), UMAP (4 files)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
11 files

BlueBrain/ccfv3a-extended-atlas

License: Apache-2.0
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: 7e02bfbcd437811a0ec0164f478c26c695561838, 13 December 2024
Languages: Python (11)
Size: 14 files, 11 scripts
Software Heritage: archived
Found in: “Data Availability”
Holds: README, license file, environment (requirements.txt)
Not found: CITATION.cff, tests, continuous integration, documentation
Tools: NumPy (10 files), NiBabel (2 files), Nipype (2 files), Matplotlib (1 file)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
13 files

registry.opendata.aws/bluebrain_opendata

License: none: the authors keep all their rights
State: the link answers, verified on 30 September 2026
Evidence: the link answers
Software Heritage: not checked
Found in: “Data Availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
  • 30 September 2026: the link answers (HTTP 200)

Zenodo 15176439

License: CC-BY-4.0
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Size: 17 files
Software Heritage: not checked
Found in: “Data Availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
  • 30 September 2026: the link answers (HTTP 200)

YannRoussel/probabilistic_mapping_extension

License: Apache-2.0
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: b55ee2e8d8bf3f654630511b4240283d60164249, 10 March 2026
Languages: Jupyter (19), Python (15), Shell (2)
Size: 1,156 files, 36 scripts
Software Heritage: not archived
Found in: the text, “Alignment of mRNA to established neuronal t-type”
Holds: README, license file, environment (pyproject.toml, requirements.txt), 15 notebooks
Not found: CITATION.cff, tests, continuous integration, documentation
Tools: NumPy (9 files), pandas (9 files), Matplotlib (5 files), scikit-learn (4 files), SciPy (4 files), seaborn (4 files), UMAP (4 files)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
11 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:

  • 7 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 89 scripts, each with its path and the digest of its content;
  • 14 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 Availability

The code and data necessary to reproduce our results are publicly available at the following repositories: https://github.com/BlueBrain/Molsys-transcriptomic-atlas, https://github.com/cveraszto/TME-types, https://github.com/YannRoussel/probabilistic_mapping_extention, https://github.com/BlueBrain/ccfv3a-extended-atlas, https://registry.opendata.aws/bluebrain_opendata/, https://zenodo.org/records/15176439.

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 1, 30 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 6 authors, 10 MeSH terms, 1 funder, 61 references.

Cite

This paper

Verasztó, C., Roussel, Y., Kanari, L., Piluso, S., Markram, H., & Keller, D. (2026). A multimodal spatial atlas of transcriptomic, morphological, and electrophysiological cell type densities in the mouse brain. PLoS computational biology, 22(3), e1014106. https://doi.org/10.1371/journal.pcbi.1014106

BibTeX

@article{veraszto2026multimodal,
author = {Verasztó, Csaba and Roussel, Yann and Kanari, Lida and Piluso, Sébastien and Markram, Henry and Keller, Daniel},
title = {{A multimodal spatial atlas of transcriptomic, morphological, and electrophysiological cell type densities in the mouse brain}},
journal = {PLoS computational biology},
year = {2026},
month = mar,
volume = {22},
number = {3},
pages = {e1014106},
publisher = {PLOS},
issn = {1553-734X},
doi = {10.1371/journal.pcbi.1014106},
url = {https://doi.org/10.1371/journal.pcbi.1014106},
pmid = {41875149},
pmcid = {PMC13120702}
}

RIS

TY - JOUR
AU - Verasztó, Csaba
AU - Roussel, Yann
AU - Kanari, Lida
AU - Piluso, Sébastien
AU - Markram, Henry
AU - Keller, Daniel
TI - A multimodal spatial atlas of transcriptomic, morphological, and electrophysiological cell type densities in the mouse brain
T2 - PLoS computational biology
J2 - PLoS Comput Biol
PY - 2026
DA - 2026/03/24
VL - 22
IS - 3
SP - e1014106
SN - 1553-734X
PB - PLOS
DO - 10.1371/journal.pcbi.1014106
UR - https://doi.org/10.1371/journal.pcbi.1014106
LA - en
ER -

CSL-JSON

{
"id": "10.1371/journal.pcbi.1014106",
"type": "article-journal",
"title": "A multimodal spatial atlas of transcriptomic, morphological, and electrophysiological cell type densities in the mouse brain",
"container-title": "PLoS computational biology",
"author": [
{
"family": "Verasztó",
"given": "Csaba"
},
{
"family": "Roussel",
"given": "Yann"
},
{
"family": "Kanari",
"given": "Lida"
},
{
"family": "Piluso",
"given": "Sébastien"
},
{
"family": "Markram",
"given": "Henry"
},
{
"family": "Keller",
"given": "Daniel"
}
],
"container-title-short": "PLoS Comput Biol",
"volume": "22",
"issue": "3",
"page": "e1014106",
"DOI": "10.1371/journal.pcbi.1014106",
"PMID": "41875149",
"PMCID": "PMC13120702",
"ISSN": "1553-734X",
"publisher": "PLOS",
"URL": "https://doi.org/10.1371/journal.pcbi.1014106",
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
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.1371/journal.pcbi.1010058 [code]
Mapping of morpho-electric features to molecular identity of cortical inhibitory neurons.
Journal: PLoS computational biology
In common: scikit-learn, pandas, SciPy, 2 other tools, mouse, cellular / molecular, 7 references, 3 authors
[2] doi:10.1038/s41586-023-06812-z [code]
A high-resolution transcriptomic and spatial atlas of cell types in the whole mouse brain.
Journal: Nature
In common: anndata, UMAP, pandas, 2 other tools, portal.brain-map.org/atlases-and-data/bkp, genetics / omics, mouse, 13 references
[3] doi:10.1162/imag_a_00565 [code]
An extended and improved CCFv3 annotation and Nissl atlas of the entire mouse brain.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: Nipype, NiBabel, scikit-learn, 3 other tools, mouse, 7 references, 2 authors
[4] doi:10.1038/s41467-025-64259-4 [code]
Data-driven fine-grained region discovery in the mouse brain with transformers.
Journal: Nature communications
In common: anndata, seaborn, scikit-learn, 4 other tools, portal.brain-map.org/atlases-and-data/bkp, genetics / omics, mouse, 7 references
[5] doi:10.1038/s41467-024-53971-2 [code]
scPair: Boosting single cell multimodal analysis by leveraging implicit feature selection and single cell atlases.
Journal: Nature communications
In common: anndata, UMAP, seaborn, 5 other tools, portal.brain-map.org/atlases-and-data/bkp, genetics / omics, mouse, 6 references
[6] doi:10.1038/s41586-023-06808-9 [code]
Molecularly defined and spatially resolved cell atlas of the whole mouse brain.
Journal: Nature
In common: SimpleITK, anndata, OpenCV, 6 other tools, portal.brain-map.org/atlases-and-data/bkp, genetics / omics, mouse, cellular / molecular, 5 references
[7] doi:10.1371/journal.pcbi.1010739 [code]
A method to estimate the cellular composition of the mouse brain from heterogeneous datasets.
Journal: PLoS computational biology
In common: pandas, SciPy, NumPy, mouse, 5 references, 2 authors
[8] doi:10.1038/s41592-026-03194-8 [code]
Beyond benchmarking: an expert-guided consensus approach to spatially aware clustering.
Journal: Nature methods
In common: anndata, NiBabel, seaborn, 5 other tools, portal.brain-map.org/atlases-and-data/bkp, genetics / omics, 6 references
[9] doi:10.1038/s41588-025-02120-6 [code]
Quantitative characterization of cell niches in spatially resolved omics data.
Journal: Nature genetics
In common: anndata, UMAP, seaborn, 5 other tools, genetics / omics, mouse, 8 references
[10] doi:10.1038/s41467-022-35288-0 [code]
Spatial-ID: a cell typing method for spatially resolved transcriptomics via transfer learning and spatial embedding.
Journal: Nature communications
In common: anndata, pandas, Matplotlib, 1 other tool, genetics / omics, mouse, cellular / molecular, 11 references

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.

Add the badge to the code's README

OSCR: the badge of this paper

If you are an author or a maintainer of this paper's code, you can add this badge. It says what OSCR knows of the paper (its code, its validated tracing map) and links the code to this page. Paste one of these snippets under the README's title. Keep the two marks around it, so that the badge can be replaced in place and is never added twice. OSCR changes nothing in your repository.

Markdown
<!-- oscr-badge:start -->
[![OSCR](https://openscicode.org/badge/doi/10.1371/journal.pcbi.1014106.svg)](https://openscicode.org/badge/doi/10.1371/journal.pcbi.1014106)
<!-- oscr-badge:end -->
reStructuredText
.. oscr-badge:start

.. image:: https://openscicode.org/badge/doi/10.1371/journal.pcbi.1014106.svg
   :target: https://openscicode.org/badge/doi/10.1371/journal.pcbi.1014106
   :alt: OSCR

.. oscr-badge:end
HTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/doi/10.1371/journal.pcbi.1014106"><img src="https://openscicode.org/badge/doi/10.1371/journal.pcbi.1014106.svg" alt="OSCR"></a>
<!-- oscr-badge:end -->

On GitHub, open the README, choose Edit (the pencil), paste the snippet under the title, then "Commit changes".

If you choose to, you can have the badge kept up to date for you, with oscr badge --write from the command line or with the GitHub Action in your repository's workflows. Every other form and option (a card, AsciiDoc, LaTeX, shields.io) is on the badge 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: code errors and mismatches between the code and the paper about this paper and its code, from readers and its authors, beside the paper and its tracing map.

Report a mismatch between the code and the paper · Report a code error (signed in)

Reproductions: reports from readers who ran the authors' code and did not get the paper's result, what they ran, with which environment, commit and data.

Report a reproduction failure (signed in)

Versions of its code: the releases of its code tied to a version of this paper (the preprint, the accepted manuscript, the version of record…), each with the tracing map versioned with it.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.