OSCR

Critical point drying of brain tissue for X-ray phase-contrast imaging.

Code ↔ Paper

The paper beside its authors' code: matches between them have not been computed for this paper yet.

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 · 221 lines · 6.8 KB · MIT

  1. # %% [markdown]
  2. # # ID16A Line-Profile Processing (Example)
  3. #
  4. # This notebook demonstrates the workflow for a **single** ID16A dataset (one CSV):
  5. # 1. Plot the **raw** line profiles.
  6. # 2. Compute and apply a **baseline correction** using specified baseline windows.
  7. # 3. Plot the **averaged corrected** line profile with ±1 standard deviation.
  8. # 4. Export the averaged profile + std to CSV.
  9. #
  10. # - Column 0: distance in **pixels** → converted to µm using `0.100 µm/pixel`.
  11. # - Intensity columns: every other column starting from column 1.
  12. # %%
  13. import os
  14. import numpy as np
  15. import pandas as pd
  16. import matplotlib.pyplot as plt
  17. from matplotlib.ticker import ScalarFormatter
  18. # ==== Parameters ====
  19. FILE_PATH = "data/ID16A/ID16A_Epon_lineprofiles_SK186_p2_n100.csv" # <-- set this to one CSV file
  20. PIXELS_TO_UM = 0.100 # µm per pixel for ID16A (100 nm)
  21. SAVE_FIGS = True
  22. FIG_DPI = 300
  23. EPS = 1e-12 # small number to avoid division-by-zero if ever needed
  24. # %%
  25. # defaults
  26. plt.rcParams.update({
  27. "font.size": 14,
  28. "xtick.direction": "in",
  29. "ytick.direction": "in",
  30. "xtick.top": True,
  31. "ytick.right": True,
  32. "axes.linewidth": 1.5,
  33. "figure.dpi": 150
  34. })
  35. # %%
  36. def safe_read_csv(file_path):
  37. """Safely read a CSV file with basic error handling."""
  38. if not os.path.exists(file_path):
  39. raise FileNotFoundError(f"File not found: {file_path}")
  40. return pd.read_csv(file_path, header=None, low_memory=False)
  41. def build_baseline_mask(dist_um):
  42. """Return a boolean mask for baseline regions with fixed windows in µm."""
  43. baseline_windows_um = [(0, 1.8), (6.2, 8)]
  44. mask = np.zeros_like(dist_um, dtype=bool)
  45. for lo, hi in baseline_windows_um:
  46. mask |= (dist_um >= lo) & (dist_um <= hi)
  47. return mask
  48. def extract_profiles(df, pixels_to_um=0.100):
  49. """
  50. From a raw dataframe:
  51. - Convert the first column (pixels) -> distance in µm
  52. - Take every other column starting at col 1 as profiles
  53. - Multiply profiles by conversion factor to match P14 units (rad/voxel)
  54. Returns: dist_um (N,), profiles (N, M) in P14 units
  55. """
  56. dist_um = df.iloc[:, 0].to_numpy(dtype=float) * pixels_to_um
  57. profiles = df.iloc[:, 1::2].to_numpy(dtype=float)
  58. # --- Conversion factor (per cm → rad/voxel as in P14 units) [see text below]---
  59. conversion_factor = 0.512 * 0.325 * 1e-4
  60. profiles = profiles * conversion_factor
  61. return dist_um, profiles
  62. def baseline_correct_profiles(dist_um, profiles):
  63. """
  64. Subtract per-profile baseline mean using fixed windows:
  65. - 0 → 1.8 µm
  66. - 6.2 → 8 µm
  67. Returns: corrected_profiles (N, M), baseline_means (M,)
  68. """
  69. base_mask = build_baseline_mask(dist_um)
  70. corrected = np.empty_like(profiles)
  71. baseline_means = np.empty(profiles.shape[1])
  72. for i in range(profiles.shape[1]):
  73. base_mean = np.mean(profiles[base_mask, i])
  74. baseline_means[i] = base_mean
  75. corrected[:, i] = profiles[:, i] - base_mean
  76. return corrected, baseline_means
  77. def compute_avg_and_std(corrected_profiles):
  78. """Compute mean and std across profiles (axis=1)."""
  79. mean_profile = np.mean(corrected_profiles, axis=1)
  80. std_profile = np.std(corrected_profiles, axis=1, ddof=0)
  81. return mean_profile, std_profile
  82. # %% [markdown]
  83. # ### Unit Conversion (ID16A → P14)
  84. #
  85. # At ID16A, the holotomographic reconstruction provides values as:
  86. #
  87. # $$
  88. # \omega = - \frac{2\pi}{\lambda} \, \delta
  89. # $$
  90. #
  91. # in units of **cm$^{-1}$**.
  92. #
  93. # To compare directly with P14 (which reports in **rad/voxel**), each line profile
  94. # is multiplied by the conversion factor:
  95. #
  96. # $$
  97. # \text{factor} = 0.512 \times 0.325 \times 10^{-4}
  98. # $$
  99. #
  100. # where 0.512 arrises from the the ratio of the X-ray wavelength (energies) at P14 to ID16A, and 0.325 $\times 10^{-4}$ is the pixel size at P14 in per cm units.
  101. #
  102. # This converts ID16A values into the same effective units as P14.
  103. # %%
  104. df = safe_read_csv(FILE_PATH)
  105. dist_um, profiles = extract_profiles(df, pixels_to_um=PIXELS_TO_UM)
  106. print(f"Loaded: {FILE_PATH}")
  107. print(f"Distance array length: {dist_um.size}, profiles shape: {profiles.shape}")
  108. # %%
  109. fig, ax = plt.subplots(figsize=(7, 5))
  110. for i in range(profiles.shape[1]):
  111. ax.plot(dist_um, profiles[:, i], alpha=0.3, linewidth=1)
  112. ax.axhline(0, linestyle='--', linewidth=1)
  113. ax.set_xlabel("Distance (µm)")
  114. ax.set_ylabel("relative phase-shift (rad/voxel) [raw signal]")
  115. ax.set_xlim(0, 8)
  116. ax.set_ylim(-1e-2, 1e-3)
  117. # Force scientific notation on y-axis if needed
  118. fmt = ScalarFormatter(useMathText=True)
  119. fmt.set_scientific(True)
  120. fmt.set_powerlimits((0, 0))
  121. ax.yaxis.set_major_formatter(fmt)
  122. ax.tick_params(axis='both', length=6, width=1.5)
  123. for spine in ax.spines.values():
  124. spine.set_linewidth(1.5)
  125. plt.tight_layout()
  126. if SAVE_FIGS:
  127. plt.savefig("ID16A_raw_profiles.svg", format='svg', dpi=FIG_DPI, bbox_inches='tight')
  128. plt.show()
  129. # %%
  130. corrected_profiles, baseline_means = baseline_correct_profiles(dist_um, profiles)
  131. print(f"Computed baseline means for {profiles.shape[1]} profiles. "
  132. f"Example (first 5): {baseline_means[:5]}")
  133. # %%
  134. fig, ax = plt.subplots(figsize=(7, 5))
  135. for i in range(corrected_profiles.shape[1]):
  136. ax.plot(dist_um, corrected_profiles[:, i], alpha=0.3, linewidth=1)
  137. ax.axhline(0, linestyle='--', linewidth=1)
  138. ax.set_xlabel("Distance (µm)")
  139. ax.set_ylabel("Corrected phase-shift (rad/voxel)")
  140. ax.set_xlim(0, 8)
  141. ax.set_ylim(-1e-2, 1e-3)
  142. fmt = ScalarFormatter(useMathText=True)
  143. fmt.set_scientific(True)
  144. fmt.set_powerlimits((0, 0))
  145. ax.yaxis.set_major_formatter(fmt)
  146. ax.tick_params(axis='both', length=6, width=1.5)
  147. for spine in ax.spines.values():
  148. spine.set_linewidth(1.5)
  149. plt.tight_layout()
  150. if SAVE_FIGS:
  151. plt.savefig("ID16A_corrected_profiles.svg", format='svg', dpi=FIG_DPI, bbox_inches='tight')
  152. plt.show()
  153. # %%
  154. mean_profile, std_profile = compute_avg_and_std(corrected_profiles)
  155. fig, ax = plt.subplots(figsize=(7, 5))
  156. ax.plot(dist_um, mean_profile, linewidth=2, label='Mean profile')
  157. ax.fill_between(dist_um, mean_profile - std_profile, mean_profile + std_profile,
  158. alpha=0.15, label='±1σ')
  159. ax.axhline(0, linestyle='--', linewidth=1)
  160. ax.set_xlabel("Distance (µm)")
  161. ax.set_ylabel("Corrected phase-shift (rad/voxel)")
  162. ax.set_xlim(0, 8)
  163. ax.set_ylim(-1e-2, 1e-3)
  164. fmt = ScalarFormatter(useMathText=True)
  165. fmt.set_scientific(True)
  166. fmt.set_powerlimits((0, 0))
  167. ax.yaxis.set_major_formatter(fmt)
  168. ax.legend(frameon=False)
  169. ax.tick_params(axis='both', length=6, width=1.5)
  170. for spine in ax.spines.values():
  171. spine.set_linewidth(1.5)
  172. plt.tight_layout()
  173. if SAVE_FIGS:
  174. plt.savefig("ID16A_corrected_mean_with_std.svg", format='svg', dpi=FIG_DPI, bbox_inches='tight')
  175. plt.show()
  176. # %%
  177. export_df = pd.DataFrame({
  178. 'Distance (µm)': dist_um,
  179. 'Mean Corrected Profile': mean_profile,
  180. 'Standard Deviation': std_profile
  181. })
  182. out_csv = "ID16A_averaged_corrected_profile.csv"
  183. export_df.to_csv(out_csv, index=False)
  184. print(f"Saved: {out_csv}")

ID16A_Analysing_LineProfile_CPD-Paper.ipynb at commit 7087f77, under MIT · at the source

Overview

  1. Sensory Circuits and Neurotechnology Laboratory The Francis Crick Institute London United Kingdom
  2. European Molecular Biology Laboratory Hamburg Unit c/o DESY Hamburg Germany
  3. ESRF – The European Synchrotron, Grenoble, France
  4. Department of Bioengineering Imperial College London London United Kingdom
  5. Department of Materials Imperial College London London United Kingdom
  6. Department of Neuroscience, Physiology and Pharmacology University College London United Kingdom
Journal: Journal of synchrotron radiation, volume 33, issue Pt 3, pages 759-768
Dates: received 17 December 2025; accepted 10 February 2026; published online 23 March 2026; in print May 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1107/s1600577526001402 · PMID 41871047 · PMCID PMC13148618 · OpenAlex W7140132694
Open access: gold, a free copy (OpenAlex)
Status: code verified (how the code is found and verified)
Categories: mouse (organism)
Methods: Connectivity, fMRI & imaging
Keywords: phase contrast, X-ray, sample preparation, neuroscience, tissue
MeSH: Brain*, Desiccation*, Animals, Mice, Synchrotrons (* major topic)
Topic: Advanced X-ray Imaging Techniques (Radiation, Physics and Astronomy), according to OpenAlex
Funding: Deutsches Elektronen-Synchrotron, Hamburg (XIMG-13); European Synchrotron Radiation Facility (IHMA106, LS3231); EPSRC (EP/V007661/1, EP/W024292/1); Cancer Research UK (CRUK) (CC2036); Medical Research Council (CC2036); Wellcome Trust (CC2036, 110174/Z/15/Z, EP/W024292/1); European Commission (101094250); European Research Council (852455)
Citations: not cited yet (Europe PMC); 42 references in the paper

Abstract

X-ray phase-contrast tomography can efficiently image brain tissue at sub­cellular resolution. However, current sample preparation methods are not optimized to exploit the full potential of X-ray contrast mechanisms. Here we propose to replace interstitial material by air to enhance X-ray phase contrast of the ultrastructural features. Critical point drying (CPD) of heavy-metal-stained mouse brain tissue produced samples with preserved ultrastructure, a nanofoam-like material that remains compatible with follow-up conventional resin embedding. Using two synchrotron-based setups, namely, a high-throughput microtomography beamline and a nanoscale holographic tomography beamline, we found that CPD samples consistently showed 2–4× stronger phase-shift signal than samples embedded in resin. CPD offers a versatile route for preparing tissue for sub­cellular and ultrastructural-resolution X-ray imaging. It retains structural detail while improving signal, and is compatible with follow-up protocols involving femtosecond laser milling or electron microscopy, paving the path for biological tissue imaging beyond the mm3 scale.

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

Repositories

Its files are read in the Code ↔ Paper reader above.

safekhan/CPDtissuesXray

License: MIT
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: 7087f77b5bdf06a5074a5cd9bbf12e0427babade, 18 March 2026
Languages: Jupyter (4)
Size: 25 files, 4 scripts
Software Heritage: not archived
Found in: “Data availability”
Holds: README, license file, 4 notebooks
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Matplotlib (4 files), NumPy (4 files), pandas (4 files)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
6 files

Zenodo 17035301

License: MIT
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Matplotlib (4 files), NumPy (4 files), pandas (4 files)
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
  • 30 September 2026: the link answers (HTTP 200)
6 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:

  • 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 8 scripts, each with its path and the digest of its content;
  • no match between paragraphs and code yet;
  • 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

No dataset and no data link were found in the paper.

Data availability

All 3D-reconstructed tomograms reported in this study and tables containing source data for all quantitative analyses are accessible through the associated code repository. Analysis code is available from https://github.com/safekhan/CPDtissuesXray.

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, 16 authors, 5 keywords, 5 MeSH terms, 8 funders, 23 references.

Cite

This paper

Khan, S., Albers, J., Vorobyev, A., Zhang, Y., Reichmann, J., Svetlove, A., De Marco, F., Denisova, K., Yang, Y., Seichepine, F., Douglas, J. O., Duke, E., Cloetens, P., Pacureanu, A., Schaefer, A. T., & Bosch, C. (2026). Critical point drying of brain tissue for X-ray phase-contrast imaging. Journal of synchrotron radiation, 33(Pt 3), 759-768. https://doi.org/10.1107/s1600577526001402

BibTeX

@article{khan2026critical,
author = {Khan, Safe and Albers, Jonas and Vorobyev, Artem and Zhang, Yuxin and Reichmann, Jakob and Svetlove, Angelika and De Marco, Fabio and Denisova, Ksenia and Yang, Yikai and Seichepine, Florent and Douglas, James O. and Duke, Elizabeth and Cloetens, Peter and Pacureanu, Alexandra and Schaefer, Andreas T. and Bosch, Carles},
title = {{Critical point drying of brain tissue for X-ray phase-contrast imaging}},
journal = {Journal of synchrotron radiation},
year = {2026},
month = mar,
volume = {33},
number = {Pt 3},
pages = {759--768},
publisher = {International Union of Crystallography},
issn = {0909-0495},
doi = {10.1107/s1600577526001402},
url = {https://doi.org/10.1107/s1600577526001402},
pmid = {41871047},
pmcid = {PMC13148618}
}

RIS

TY - JOUR
AU - Khan, Safe
AU - Albers, Jonas
AU - Vorobyev, Artem
AU - Zhang, Yuxin
AU - Reichmann, Jakob
AU - Svetlove, Angelika
AU - De Marco, Fabio
AU - Denisova, Ksenia
AU - Yang, Yikai
AU - Seichepine, Florent
AU - Douglas, James O.
AU - Duke, Elizabeth
AU - Cloetens, Peter
AU - Pacureanu, Alexandra
AU - Schaefer, Andreas T.
AU - Bosch, Carles
TI - Critical point drying of brain tissue for X-ray phase-contrast imaging
T2 - Journal of synchrotron radiation
J2 - J Synchrotron Radiat
PY - 2026
DA - 2026/03/23
VL - 33
IS - Pt 3
SP - 759
EP - 768
SN - 0909-0495
PB - International Union of Crystallography
DO - 10.1107/s1600577526001402
UR - https://doi.org/10.1107/s1600577526001402
LA - en
ER -

CSL-JSON

{
"id": "10.1107/s1600577526001402",
"type": "article-journal",
"title": "Critical point drying of brain tissue for X-ray phase-contrast imaging",
"container-title": "Journal of synchrotron radiation",
"author": [
{
"family": "Khan",
"given": "Safe"
},
{
"family": "Albers",
"given": "Jonas"
},
{
"family": "Vorobyev",
"given": "Artem"
},
{
"family": "Zhang",
"given": "Yuxin"
},
{
"family": "Reichmann",
"given": "Jakob"
},
{
"family": "Svetlove",
"given": "Angelika"
},
{
"family": "De Marco",
"given": "Fabio"
},
{
"family": "Denisova",
"given": "Ksenia"
},
{
"family": "Yang",
"given": "Yikai"
},
{
"family": "Seichepine",
"given": "Florent"
},
{
"family": "Douglas",
"given": "James O."
},
{
"family": "Duke",
"given": "Elizabeth"
},
{
"family": "Cloetens",
"given": "Peter"
},
{
"family": "Pacureanu",
"given": "Alexandra"
},
{
"family": "Schaefer",
"given": "Andreas T."
},
{
"family": "Bosch",
"given": "Carles"
}
],
"container-title-short": "J Synchrotron Radiat",
"volume": "33",
"issue": "Pt 3",
"page": "759-768",
"DOI": "10.1107/s1600577526001402",
"PMID": "41871047",
"PMCID": "PMC13148618",
"ISSN": "0909-0495",
"publisher": "International Union of Crystallography",
"URL": "https://doi.org/10.1107/s1600577526001402",
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
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.1364/boe.559263 [code]
Scaling up X-ray holographic nanotomography for neuronal tissue imaging.
Journal: Biomedical optics express
In common: Matplotlib, NumPy, 7 references, 4 authors
[2] doi:10.1038/s41592-025-02891-0 [code]
Nondestructive X-ray tomography of brain tissue ultrastructure.
Journal: Nature methods
In common: mouse, 7 references, 4 authors
[3] doi:10.1242/jcs.261953 [code]
Synchrotron X-ray imaging of soft biological tissues - principles, applications and future prospects.
Journal: Journal of cell science
In common: pandas, NumPy, 5 references, 3 authors
[4] doi:10.3389/fcell.2022.880696 [code]
Sample Preparation and Warping Accuracy for Correlative Multimodal Imaging in the Mouse Olfactory Bulb Using 2-Photon, Synchrotron X-Ray and Volume Electron Microscopy.
Journal: Frontiers in cell and developmental biology
In common: mouse, 4 references, 4 authors
[5] doi:10.1101/2023.11.16.567403 [code]
Non-destructive X-ray tomography of brain tissue ultrastructure
Journal: bioRxiv (preprint)
In common: 4 authors
[6] doi:10.1111/bpa.70044 [code]
3D imaging of neuronal inclusions and protein aggregates in human neurodegeneration by multiscale x-ray phase-contrast tomography.
Journal: Brain pathology (Zurich, Switzerland)
In common: pandas, Matplotlib, NumPy, 5 references, author Jakob Reichmann
[7] doi:10.1002/advs.202416879 [code]
Synchrotron Radiation-Based Tomography of an Entire Mouse Brain with Sub-Micron Voxels: Augmenting Interactive Brain Atlases with Terabyte Data.
Journal: Advanced science (Weinheim, Baden-Wurttemberg, Germany)
In common: pandas, NumPy, mouse, 4 references
[8] doi:10.1371/journal.pbio.3002837 [code]
Functional networks of inhibitory neurons orchestrate synchrony in the hippocampus.
Journal: PLoS biology
In common: pandas, Matplotlib, NumPy, mouse, author Artem Vorobyev
[9] doi:10.1101/2025.05.14.653752 [code]
Mice discriminate odour source distance via sub-sniff temporal features of odour plumes
Journal: bioRxiv (preprint)
In common: pandas, Matplotlib, NumPy, mouse, author Andreas T. Schaefer
[10] doi:10.1371/journal.pone.0297754 [code]
Quantifying spectral information about source separation in multisource odour plumes.
Journal: PloS one
In common: pandas, Matplotlib, NumPy, mouse, author Andreas T. Schaefer

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.1107/s1600577526001402.svg)](https://openscicode.org/badge/doi/10.1107/s1600577526001402)
<!-- oscr-badge:end -->
reStructuredText
.. oscr-badge:start

.. image:: https://openscicode.org/badge/doi/10.1107/s1600577526001402.svg
   :target: https://openscicode.org/badge/doi/10.1107/s1600577526001402
   :alt: OSCR

.. oscr-badge:end
HTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/doi/10.1107/s1600577526001402"><img src="https://openscicode.org/badge/doi/10.1107/s1600577526001402.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.