OSCR

A deep learning pipeline for mapping in situ network-level neurovascular coupling in multi-photon fluorescence microscopy.

Code ↔ Paper

5 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 5 matches
  1. [1] § Methods › Segmentation and graph extraction › Model architecture ↔ novas3d/predict.py, lines 151 to 231 · score 0.74 · hidden layer, PyTorch, perceptron, dropout, weighted, map · Report a mismatch
  2. [2] § Methods › Segmentation and graph extraction › Model architecture ↔ novas3d/predict.py, lines 151 to 231 · score 0.66 · residual blocks, UNETR model, dropout, layers, weights, training · Report a mismatch
  3. [3] § Methods › Segmentation and graph extraction › Graph extraction of cerebrovascular networks ↔ novas3d/vessel_graph.py, lines 543 to 689 · score 0.63 · Richardson Lucy, gradient, Gaussian, smoothed, filter, sigma · Report a mismatch
  4. [4] § Methods › Segmentation and graph extraction › Graph extraction of cerebrovascular networks ↔ novas3d/predict.py, lines 233 to 285 · score 0.63 · sliding window inference, ROI, prediction, model · Report a mismatch
  5. [5] § Methods › Segmentation and graph extraction › Graph extraction of cerebrovascular networks ↔ novas3d/vessel_graph.py, lines 264 to 340 · score 0.58 · connected component, segmentation mask, iteratively, filled, union, binary · 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

Python · 483 lines · 19 KB · GPL-3.0 · 3 matches

  1. from monai.utils import (
  2. ensure_tuple
  3. )
  4. from monai.transforms import (
  5. AsDiscrete,
  6. EnsureChannelFirstd,
  7. Compose,
  8. LoadImaged,
  9. ScaleIntensityRanged,
  10. Spacingd,
  11. EnsureTyped,
  12. EnsureType,
  13. )
  14. from monai.handlers.utils import from_engine
  15. from monai.networks.nets import UNETR
  16. from monai.networks.layers import Norm
  17. from monai.inferers import sliding_window_inference
  18. from monai.data import (
  19. DataLoader,
  20. Dataset,
  21. ImageReader
  22. )
  23. from monai.config import (
  24. KeysCollection,
  25. PathLike
  26. )
  27. import torch
  28. import matplotlib.pyplot as plt
  29. from os.path import exists
  30. import os
  31. from pathlib import Path
  32. from re import sub
  33. from skimage.io import imread
  34. from typing import (
  35. Optional,
  36. Union,
  37. Sequence,
  38. Dict,
  39. List
  40. )
  41. from monai.data.utils import is_supported_format
  42. from monai. data.image_reader import (
  43. _copy_compatible_dict,
  44. _stack_images
  45. )
  46. from nibabel.nifti1 import Nifti1Image
  47. from numpy import swapaxes, ndarray, eye, asarray, delete, empty, float16, save
  48. from tqdm import tqdm
  49. from monai.data import DataLoader, Dataset
  50. from torch import no_grad
  51. import pickle
  52. import warnings
  53. warnings.filterwarnings('ignore')
  54. class TIFFReader(ImageReader):
  55. def __init__(self, npz_keys: Optional[KeysCollection] = None, channel_dim: Optional[int] = None, **kwargs):
  56. super().__init__()
  57. if npz_keys is not None:
  58. npz_keys = ensure_tuple(npz_keys)
  59. self.npz_keys = npz_keys
  60. self.channel_dim = channel_dim
  61. self.kwargs = kwargs
  62. def verify_suffix(self, filename: Union[Sequence[PathLike], PathLike]) -> bool:
  63. """
  64. Verify whether the specified file or files format is supported by Numpy reader.
  65. Args:
  66. filename: file name or a list of file names to read.
  67. if a list of files, verify all the suffixes.
  68. Returns:
  69. bool: True if the file format is supported, False otherwise.
  70. """
  71. suffixes: Sequence[str] = ["tif", "tiff"]
  72. return is_supported_format(filename, suffixes)
  73. def read(self, data: Union[Sequence[PathLike], PathLike], **kwargs):
  74. """
  75. Read image data from specified file or files, it can read a list of `no-channel` data files
  76. and stack them together as multi-channels data in `get_data()`.
  77. Note that the returned object is Numpy array or list of Numpy arrays.
  78. Args:
  79. data (Union[Sequence[PathLike], PathLike]): The file name or a list of file names to read.
  80. **kwargs: Additional arguments for the `numpy.load` API except `allow_pickle`, which will override `self.kwargs` for existing keys.
  81. More details about available arguments can be found here: https://numpy.org/doc/stable/reference/generated/numpy.load.html
  82. Returns:
  83. Union[numpy.ndarray, List[numpy.ndarray]]: The loaded image data as a Numpy array or a list of Numpy arrays.
  84. """
  85. img_: List[Nifti1Image] = []
  86. filenames: Sequence[PathLike] = ensure_tuple(data)
  87. kwargs_ = self.kwargs.copy()
  88. kwargs_.update(kwargs)
  89. for name in filenames:
  90. img = imread(name, **kwargs_)
  91. img = img.astype('float32')
  92. if len(img.shape)==4:
  93. img = swapaxes(img,0,1)
  94. img = swapaxes(img,1,3)
  95. img_.append(img)
  96. return img_ if len(img_) > 1 else img_[0]
  97. def get_data(self, img):
  98. """
  99. Extract data array and meta data from loaded image and return them.
  100. This function returns two objects, first is numpy array of image data, second is dict of meta data.
  101. It constructs `affine`, `original_affine`, and `spatial_shape` and stores them in meta dict.
  102. When loading a list of files, they are stacked together at a new dimension as the first dimension,
  103. and the meta data of the first image is used to represent the output meta data.
  104. Args:
  105. img: a Numpy array loaded from a file or a list of Numpy arrays.
  106. Returns:
  107. Tuple: A tuple containing the following two objects:
  108. - img_array (numpy.ndarray): Numpy array of image data.
  109. - compatible_meta (dict): Dictionary of meta data.
  110. """
  111. img_array: List[ndarray] = []
  112. compatible_meta: Dict = {}
  113. if isinstance(img, ndarray):
  114. img = (img,)
  115. for i in ensure_tuple(img):
  116. header = {"affine":eye(5),
  117. "labels": {"0": "background",
  118. "1": "vessels",
  119. "2": "neurons",}
  120. }
  121. if isinstance(i, ndarray):
  122. # if `channel_dim` is None, can not detect the channel dim, use all the dims as spatial_shape
  123. spatial_shape = asarray(i.shape)
  124. if isinstance(self.channel_dim, int):
  125. spatial_shape = delete(spatial_shape, self.channel_dim)
  126. header["spatial_shape"] = spatial_shape
  127. img_array.append(i)
  128. header["original_channel_dim"] = self.channel_dim if isinstance(self.channel_dim, int) else "no_channel"
  129. _copy_compatible_dict(header, compatible_meta)
  130. return _stack_images(img_array, compatible_meta), compatible_meta
  131. def get_model(parameter_file='NOVAS3D_Vessel_and_Neuron_Segmentation/parameters.pickle',
  132. spatial_dims=3,
  133. in_channels=2,
  134. out_channels=3,
  135. img_size=(128, 128, 128),
  136. feature_size=16,
  137. hidden_size=768,
  138. mlp_dim=3072,
  139. pos_embed="perceptron",
  140. res_block=True,
  141. norm_name="instance",
  142. gpu = False):
  143. """
  144. Get the UNETR model for prediction.
  145. Args:
  146. parameter_file (str): Path to the parameter pickle file.
  147. spatial_dims (int): Number of spatial dimensions.
  148. in_channels (int): Number of input channels.
  149. out_channels (int): Number of output channels.
  150. img_size (tuple): Size of the input image.
  151. feature_size (int): Size of the feature maps.
  152. hidden_size (int): Size of the hidden layers.
  153. mlp_dim (int): Dimension of the MLP layers.
  154. pos_embed (str): Type of positional embedding.
  155. res_block (bool): Whether to use residual blocks.
  156. norm_name (str): Name of the normalization layer.
  157. Returns:
  158. torch.nn.Module: The UNETR model for prediction.
  159. """
  160. # Load parameters from pickle file
  161. with open(parameter_file, 'rb') as handle:
  162. params = pickle.load(handle)
  163. # Set device for model prediction
  164. device = torch.device("cuda" if (torch.cuda.is_available() and gpu == True) else "cpu")
  165. # Create UNETR model
  166. model = UNETR(
  167. spatial_dims=spatial_dims,
  168. in_channels=in_channels,
  169. out_channels=out_channels,
  170. img_size=img_size,
  171. feature_size=feature_size,
  172. hidden_size=hidden_size,
  173. mlp_dim=mlp_dim,
  174. pos_embed=pos_embed,
  175. res_block=res_block,
  176. norm_name=norm_name,
  177. dropout_rate=params["dropout"]
  178. )
  179. # Move model to device
  180. model.to(device)
  181. if (torch.cuda.is_available() and gpu == True):
  182. # Use DataParallel for multi-GPU training
  183. model = torch.nn.DataParallel(model)
  184. # Load pre-trained model weights
  185. model.load_state_dict(torch.load(
  186. sub('parameters.pickle', "model.pth",parameter_file)))
  187. else:
  188. from collections import OrderedDict
  189. state_dict = torch.load(sub('parameters.pickle', "model.pth",parameter_file), map_location='cpu')
  190. new_state_dict = OrderedDict()
  191. for k, v in state_dict.items():
  192. new_state_dict[k.replace("module.", "")] = v
  193. model.load_state_dict(new_state_dict)
  194. # Load pre-trained model weights
  195. #model.load_state_dict(torch.load(
  196. # sub('parameters.pickle', "model.pth",parameter_file),
  197. # map_location=torch.device('cpu')))
  198. model.eval()
  199. for m in model.modules():
  200. if m.__class__.__name__.startswith('Dropout'):
  201. m.train()
  202. return model
  203. def predict(pred_data,
  204. num_evals=20,
  205. num_channels_out=3,
  206. model = get_model(),
  207. device='cpu',
  208. roi_size = (128, 128, 128),
  209. sw_batch_size = 64):
  210. """
  211. Perform prediction using a sliding window inference approach.
  212. Args:
  213. pred_data (dict): Dictionary containing the input data for prediction.
  214. num_evals (int, optional): Number of evaluations to perform. Defaults to 20.
  215. num_channels_out (int, optional): Number of output channels. Defaults to 3.
  216. model (nn.Module, optional): Model to use for prediction. Defaults to get_model().
  217. device (str, optional): Device to use for computation. Defaults to 'cpu'.
  218. roi_size (tuple, optional): Size of the region of interest. Defaults to (128, 128, 128).
  219. sw_batch_size (int, optional): Batch size for sliding window inference. Defaults to 64.
  220. Returns:
  221. numpy.ndarray: Array containing the predicted outputs.
  222. """
  223. # Get the shape of the input image
  224. _shape = pred_data["image"].shape
  225. # Create an empty array to store the predicted outputs
  226. pred_array = empty((num_evals,num_channels_out,_shape[2],_shape[3],_shape[4]),dtype=float16)
  227. # Perform sliding window inference for the specified number of evaluations
  228. for j in range(num_evals):
  229. # define softmax for the predicted outputs
  230. softmax = torch.nn.Softmax(dim=1)
  231. # Perform sliding window inference
  232. pred_outputs = sliding_window_inference(
  233. pred_data["image"],
  234. roi_size,
  235. sw_batch_size,
  236. model,
  237. sw_device=device,
  238. device=device
  239. )
  240. # Apply softmax to the predicted outputs
  241. pred_outputs = softmax(pred_outputs)
  242. # Convert the predicted outputs to numpy array of float16 data type
  243. pred_outputs = float16(pred_outputs.cpu().detach().numpy())
  244. # Store the predicted outputs in the pred_array
  245. pred_array[j] = pred_outputs[:]
  246. del pred_outputs
  247. return pred_array
  248. def get_pred_transforms(spacing=(1, 1, 0.375), i_min=0, i_max=1024, b_min=0.0, b_max=1.0, clip=True, channel_dim=0):
  249. """
  250. Returns a composition of transforms for preprocessing the input image for prediction.
  251. Args:
  252. spacing (tuple): Voxel spacing in the input image. Default is (1, 1, 0.375).
  253. i_min (int): Minimum intensity value for rescaling. Default is 0.
  254. imax (int): Maximum intensity value for rescaling. Default is 1024.
  255. b_min (float): Minimum intensity value for scaling. Default is 0.0.
  256. b_max (float): Maximum intensity value for scaling. Default is 1.0.
  257. clip (bool): Whether to clip the intensity values. Default is True.
  258. channel_dim (int): Dimension index for channel. Default is 0.
  259. Returns:
  260. pred_transforms (Compose): Composition of transforms for preprocessing the input image.
  261. """
  262. # Define a composition of transforms
  263. pred_transforms = Compose(
  264. [
  265. LoadImaged(keys=["image"], reader=TIFFReader(channel_dim=channel_dim)), # Load the image using TIFFReader
  266. EnsureChannelFirstd(keys=["image"]), # Ensure the channel dimension is first
  267. Spacingd(keys=["image"], pixdim=spacing, mode=("bilinear")), # Resample the image with the given spacing
  268. ScaleIntensityRanged(
  269. keys=["image"], a_min=i_min, a_max=i_max, b_min=b_min, b_max=b_max, clip=clip
  270. ), # Rescale the intensity values of the image
  271. EnsureTyped(keys=["image"]), # Ensure the image is of the correct data type
  272. ]
  273. )
  274. return pred_transforms
  275. def get_post_transforms():
  276. """
  277. Returns the post-processing transforms for the prediction.
  278. Returns:
  279. Compose: A composition of post-processing transforms.
  280. """
  281. # Define post-processing transforms for prediction
  282. post_pred = Compose(
  283. [
  284. EnsureType(),
  285. AsDiscrete(argmax=True, to_onehot=3)
  286. ]
  287. )
  288. return post_pred
  289. class PredictWarped:
  290. """
  291. Class for performing prediction using the registered images. Saves the predicted images.
  292. Args:
  293. data_dict (dict): A dictionary containing the data for prediction.
  294. config (dict): A dictionary containing the configuration parameters.
  295. The configuration parameters include:
  296. - in_dir (str): The input directory.
  297. - out_dir (str): The output directory.
  298. - num_evals (int): The number of evaluations.
  299. - base_file_extension (str): The base file extension.
  300. - pred_file_extension (str): The prediction file extension.
  301. - mean_file_extension (str): The mean file extension.
  302. parameter_file (str): The file path to the parameter file.
  303. spatial_dims (int): The number of spatial dimensions.
  304. in_channels (int): The number of input channels.
  305. out_channels (int): The number of output channels.
  306. img_size (tuple): The size of the input image.
  307. feature_size (int): The size of the features.
  308. hidden_size (int): The size of the hidden layers.
  309. mlp_dim (int): The dimension of the MLP layers.
  310. pos_embed (bool): Whether to use positional embedding.
  311. res_block (bool): Whether to use residual blocks.
  312. norm_name (str): The name of the normalization method.
  313. spacing (tuple): The spacing between voxels. Reciprocal of the voxel size in um to resample to 1 um.
  314. i_min (float): The minimum intensity value of raw images.
  315. i_max (float): The maximum intensity value of raw images.
  316. b_min (float): The minimum background value after normalization.
  317. b_max (float): The maximum background value after noramlization.
  318. clip (bool): Whether to clip the values.
  319. channel_dim (int): The dimension index of the colour channel.
  320. gpu (bool): Whether to use the GPU.
  321. skip_existing (bool): Whether to skip images that have already been predicted.
  322. Methods:
  323. get_model(): Retrieves the model for prediction.
  324. get_pred_transforms(): Retrieves the prediction transforms.
  325. dataset_creation(): Creates the dataset for prediction.
  326. prediction(): Performs the prediction.
  327. """
  328. def __init__(self, data_dict, config, parameter_file, spatial_dims, in_channels, out_channels, img_size, feature_size, hidden_size, mlp_dim, pos_embed, res_block, norm_name,spacing, i_min, i_max, b_min, b_max, clip, channel_dim, gpu=False, skip_existing=False):
  329. self.data_dict = data_dict
  330. self.config = config
  331. self.parameter_file = parameter_file
  332. self.spatial_dims = spatial_dims
  333. self.in_channels = in_channels
  334. self.out_channels = out_channels
  335. self.img_size = img_size
  336. self.feature_size = feature_size
  337. self.hidden_size = hidden_size
  338. self.mlp_dim = mlp_dim
  339. self.pos_embed = pos_embed
  340. self.res_block = res_block
  341. self.norm_name = norm_name
  342. self.spacing = spacing
  343. self.i_min = i_min
  344. self.i_max = i_max
  345. self.b_min = b_min
  346. self.b_max = b_max
  347. self.clip = clip
  348. self.channel_dim = channel_dim
  349. self.gpu = gpu
  350. self.skip_existing = skip_existing
  351. def get_model(self):
  352. """
  353. Get the model for prediction.
  354. Returns:
  355. model: The model for prediction.
  356. """
  357. # Get the model for prediction
  358. model = get_model(self.parameter_file,
  359. self.spatial_dims,
  360. self.in_channels,
  361. self.out_channels,
  362. self.img_size,
  363. self.feature_size,
  364. self.hidden_size,
  365. self.mlp_dim,
  366. self.pos_embed,
  367. self.res_block,
  368. self.norm_name,
  369. self.gpu)
  370. return model
  371. def get_pred_transforms(self):
  372. """
  373. Get the prediction transforms.
  374. Returns:
  375. pred_transforms (list): List of prediction transforms.
  376. """
  377. # Get the prediction transforms
  378. pred_transforms = get_pred_transforms(self.spacing,
  379. self.i_min,
  380. self.i_max,
  381. self.b_min,
  382. self.b_max,
  383. self.clip,
  384. self.channel_dim)
  385. return pred_transforms
  386. def dataset_creation(self):
  387. """
  388. Create the dataset for prediction.
  389. Returns:
  390. pred_ds (Dataset): The dataset for prediction.
  391. """
  392. # Create the dataset for prediction
  393. data_dicts = self.data_dict
  394. pred_transforms = get_pred_transforms(self.spacing, self.i_min, self.i_max, self.b_min, self.b_max, self.clip, self.channel_dim)
  395. pred_ds = Dataset(data=data_dicts, transform=pred_transforms)
  396. self.assertEqual(len(pred_ds), 3)
  397. return pred_ds
  398. def prediction(self):
  399. """
  400. Perform prediction using the provided model and saves the data.
  401. Returns:
  402. None
  403. """
  404. # Perform the prediction
  405. model = get_model(self.parameter_file, self.spatial_dims, self.in_channels, self.out_channels, self.img_size, self.feature_size, self.hidden_size, self.mlp_dim, self.pos_embed, self.res_block, self.norm_name)
  406. pred_transforms = get_pred_transforms(self.spacing, self.i_min, self.i_max, self.b_min, self.b_max, self.clip, self.channel_dim)
  407. pred_ds = Dataset(data=self.data_dict, transform=pred_transforms)
  408. pred_loader = DataLoader(pred_ds, batch_size=1, shuffle=False)
  409. config = self.config
  410. with no_grad():
  411. for i, pred_data in tqdm(enumerate(pred_loader)):
  412. if self.skip_existing==False:
  413. new_file_name = sub(config["in_dir"], config["out_dir"], self.data_dict[i]["image"])
  414. pred_array = predict(pred_data, num_evals=config["num_evals"], model=model)
  415. #self.assertIsNotNone(pred_array)
  416. mean = float16(pred_array.mean(axis=0))
  417. save(sub(config["base_file_extension"], config['mean_file_extension'], new_file_name), mean)
  418. save(sub(config["base_file_extension"], config["pred_file_extension"], new_file_name), pred_array)
  419. elif not exists(sub(config["base_file_extension"], config["pred_file_extension"], sub(config["in_dir"], config["out_dir"], self.data_dict[i]["image"]))):
  420. new_file_name = sub(config["in_dir"], config["out_dir"], self.data_dict[i]["image"])
  421. pred_array = predict(pred_data, num_evals=config["num_evals"], model=model)
  422. #self.assertIsNotNone(pred_array)
  423. mean = float16(pred_array.mean(axis=0))
  424. save(sub(config["base_file_extension"], config['mean_file_extension'], new_file_name), mean)
  425. save(sub(config["base_file_extension"], config["pred_file_extension"], new_file_name), pred_array)

predict.py at commit 49cba49, under GPL-3.0 · at the source

Overview

Authors: Matthew W Rozak1,2, James R Mester1,2, Ahmadreza Attarpour1,2, Adrienne Dorr2, Shruti Patel2, Margaret Koletar2, Mary E Hill3, Joanne McLaurin3,4,5, Maged Goubran1,2,5, Bojana Stefanovic1,2,5
  1. Department of Medical Biophysics, University of Toronto, Toronto, Canada
  2. Physical Sciences, Sunnybrook Research Institute, Toronto, Canada
  3. Biological Sciences, Sunnybrook Research Institute, Toronto, Canada
  4. Department of Laboratory Medicine and Pathobiology, University of Toronto, Toronto, Canada
  5. Hurvitz Brain Sciences, Sunnybrook Research Institute, Toronto, Canada
Institutions: University of Toronto (Canada); Sunnybrook Research Institute (Canada)
Journal: eLife, volume 13, article RP95525
Dates: published online 24 March 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.7554/elife.95525 · PMID 41873945 · PMCID PMC13012726 · OpenAlex W4393870627
Open access: gold, a free copy (OpenAlex)
Status: code verified (how the code is found and verified)
Categories: histology / microscopy (modality), optical imaging (calcium, voltage, 2-photon) (modality), mouse (organism), rat (organism), stroke (population)
Methods: Preprocessing, Connectivity, Statistics, Machine learning, Graphs, fMRI & imaging
Keywords: Mouse, Rat
MeSH: Brain*, Deep Learning*, Microscopy, Fluorescence, Multiphoton*, Neurovascular Coupling*, Animals, Cerebrovascular Circulation, Mice, Neurons, Optogenetics (* major topic)
Topic: Optical Imaging and Spectroscopy Techniques (Radiology, Nuclear Medicine and Imaging, Medicine), according to OpenAlex
Funding: CIHR (PJT376309, PJT178059, PJT156179); Canada Research Chair Program (CRC-2018-00042, CRC-2021-00374)
Citations: not cited yet (Europe PMC); 102 references in the paper

Abstract

Functional hyperemia is a well-established hallmark of healthy brain function, whereby local brain blood flow adjusts in response to a change in the activity of the surrounding neurons. Although functional hyperemia has been extensively studied at the level of both tissue and individual vessels, vascular network-level coordination remains largely unknown. To bridge this gap, we developed a deep learning-based pipeline that uses two-photon fluorescence microscopy images of cerebral microcirculation to enable automated reconstruction and quantification of the geometric changes across the microvascular network, comprising hundreds of interconnected blood vessels, pre and post-activation of the neighboring neurons. The pipeline’s utility was demonstrated in the Thy1-ChR2 optogenetic mouse model, where we observed network-wide vessel radius changes to depend on the photostimulation intensity, with both dilations and constrictions occurring across the cortical depth, at an average of 16.1±14.3 μm (mean ± SD) away from the most proximal neuron for dilations; and at 21.9±14.6 μm away for constrictions. We observed a significant heterogeneity of the vascular radius changes within vessels, with radius adjustment varying by an average of 24 ± 28% of the resting diameter, likely reflecting the heterogeneity of the distribution of contractile cells on the vessel walls. A graph theory-based network analysis revealed that the assortativity of adjacent blood vessel responses rose by 152 ± 65% at 4.3 mW/mm2 of blue photostimulation vs. the control, with a 4% median increase in the efficiency of the capillary networks during this level of blue photostimulation in relation to the baseline. Interrogating individual vessels is thus not sufficient to predict how the blood flow is modulated in the network. Our pipeline, enables tracking of the microvascular network geometry over time, relating caliber adjustments to vessel wall-associated cells’ state, and mapping network-level flow distribution impairments in experimental models of disease.

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

AICONSlab/novas3d

License: GPL-3.0
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: 49cba490403840a820885171e44fa053dde0e8de, 23 March 2026
Languages: Python (6), Jupyter (1), MATLAB (1)
Size: 50 files, 8 scripts
Software Heritage: not archived
Found in: “Data availability”
Holds: README, license file, environment (pyproject.toml, docs/requirements.txt), documentation, 1 notebook
Not found: CITATION.cff, tests, continuous integration
Tools: NumPy (5 files), scikit-image (3 files), SciPy (2 files), ANTs (1 file), Image Processing Toolbox (1 file), Matplotlib (1 file), MONAI (1 file), NetworkX (1 file), NiBabel (1 file), PyTorch (1 file), tifffile (1 file)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
10 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;
  • 8 scripts, each with its path and the digest of its content;
  • 5 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

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

Data availability

Imaging data used in this paper was deposited in the Federated Research Data Repository (FRDR) and is available at https://doi.org/10.20383/103.01588. The code for the analyses presented in this paper is openly accessible at https://github.com/AICONSlab/novas3d (copy archived at Rozak and Osmann , 2026).

The following dataset was generated:

Rozak M, Mester J, Attarpour A, Dorr A, Patel S, Koletar M, Hill M, McLaurin J, Goubran M, Stefanovic B. 2026. THY1-ChR2-EYFP mouse images used to train and test the NOVAS3D pipeline. Federated Research Data Repository.

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, pages, dates, 10 authors, 2 keywords, 9 MeSH terms, 2 funders, 96 references.

Cite

This paper

Rozak, M. W., Mester, J. R., Attarpour, A., Dorr, A., Patel, S., Koletar, M., Hill, M. E., McLaurin, J., Goubran, M., & Stefanovic, B. (2026). A deep learning pipeline for mapping in situ network-level neurovascular coupling in multi-photon fluorescence microscopy. eLife, 13, RP95525. https://doi.org/10.7554/elife.95525

BibTeX

@article{rozak2026deep,
author = {Rozak, Matthew W and Mester, James R and Attarpour, Ahmadreza and Dorr, Adrienne and Patel, Shruti and Koletar, Margaret and Hill, Mary E and McLaurin, Joanne and Goubran, Maged and Stefanovic, Bojana},
title = {{A deep learning pipeline for mapping in situ network-level neurovascular coupling in multi-photon fluorescence microscopy}},
journal = {eLife},
year = {2026},
month = mar,
volume = {13},
pages = {RP95525},
publisher = {eLife Sciences Publications, Ltd},
issn = {2050-084X},
doi = {10.7554/elife.95525},
url = {https://doi.org/10.7554/elife.95525},
pmid = {41873945},
pmcid = {PMC13012726}
}

RIS

TY - JOUR
AU - Rozak, Matthew W
AU - Mester, James R
AU - Attarpour, Ahmadreza
AU - Dorr, Adrienne
AU - Patel, Shruti
AU - Koletar, Margaret
AU - Hill, Mary E
AU - McLaurin, Joanne
AU - Goubran, Maged
AU - Stefanovic, Bojana
TI - A deep learning pipeline for mapping in situ network-level neurovascular coupling in multi-photon fluorescence microscopy
T2 - eLife
J2 - eLife
PY - 2026
DA - 2026/03/24
VL - 13
SP - RP95525
SN - 2050-084X
PB - eLife Sciences Publications, Ltd
DO - 10.7554/elife.95525
UR - https://doi.org/10.7554/elife.95525
LA - en
ER -

CSL-JSON

{
"id": "10.7554/elife.95525",
"type": "article-journal",
"title": "A deep learning pipeline for mapping in situ network-level neurovascular coupling in multi-photon fluorescence microscopy",
"container-title": "eLife",
"author": [
{
"family": "Rozak",
"given": "Matthew W"
},
{
"family": "Mester",
"given": "James R"
},
{
"family": "Attarpour",
"given": "Ahmadreza"
},
{
"family": "Dorr",
"given": "Adrienne"
},
{
"family": "Patel",
"given": "Shruti"
},
{
"family": "Koletar",
"given": "Margaret"
},
{
"family": "Hill",
"given": "Mary E"
},
{
"family": "McLaurin",
"given": "Joanne"
},
{
"family": "Goubran",
"given": "Maged"
},
{
"family": "Stefanovic",
"given": "Bojana"
}
],
"container-title-short": "eLife",
"volume": "13",
"page": "RP95525",
"DOI": "10.7554/elife.95525",
"PMID": "41873945",
"PMCID": "PMC13012726",
"ISSN": "2050-084X",
"publisher": "eLife Sciences Publications, Ltd",
"URL": "https://doi.org/10.7554/elife.95525",
"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.1038/s41592-024-02583-1 [code]
A deep learning pipeline for three-dimensional brain-wide mapping of local neuronal ensembles in teravoxel light-sheet microscopy.
Journal: Nature methods
In common: MONAI, PyTorch, NumPy, histology / microscopy, mouse, 5 references, 2 authors
[2] doi:10.3390/biomedicines13010072 [code]
Modeling of Blood Flow Dynamics in Rat Somatosensory Cortex.
Journal: Biomedicines
In common: NetworkX, SciPy, Matplotlib, 1 other tool, rat, 8 references
[3] doi:10.1016/j.crmeth.2023.100436 [code]
Rapid and fully automated blood vasculature analysis in 3D light-sheet image volumes of different organs.
Journal: Cell reports methods
In common: tifffile, NetworkX, scikit-image, 3 other tools, histology / microscopy, mouse, 5 references
[4] doi:10.1242/dev.202703 [code]
Examining the NEUROG2 lineage and associated gene expression in human cortical organoids.
Journal: Development (Cambridge, England)
In common: scikit-image, SciPy, Matplotlib, 1 other tool, 2 authors
[5] doi:10.1073/pnas.2521872123 [code]
Microvascular architecture and physiological fluctuations constrain the control of cerebral microcirculation.
Journal: Proceedings of the National Academy of Sciences of the United States of America
In common: tifffile, NetworkX, scikit-image, 4 other tools, stroke, histology / microscopy, 3 references
[6] doi:10.1038/s41592-024-02245-2 [code]
Virtual reality-empowered deep-learning analysis of brain cells.
Journal: Nature methods
In common: MONAI, tifffile, scikit-image, 6 other tools, mouse, 2 references
[7] doi:10.1073/pnas.2321021121
Capillary regression leads to sustained local hypoperfusion by inducing constriction of upstream transitional vessels.
Journal: Proceedings of the National Academy of Sciences of the United States of America
In common: optical imaging (calcium, voltage, 2-photon), stroke, mouse, 7 references
[8] doi:10.3389/fncir.2022.977700 [code]
Igneous: Distributed dense 3D segmentation meshing, neuron skeletonization, and hierarchical downsampling.
Journal: Frontiers in neural circuits
In common: tifffile, NetworkX, scikit-image, 5 other tools, histology / microscopy, 2 references
[9] doi:10.1016/j.crmeth.2026.101473 [code]
AmygdalaGo-BOLT for boundary-aware segmentation of the human amygdala.
Journal: Cell reports methods
In common: MONAI, ANTs, scikit-image, 6 other tools, 1 reference
[10] doi:10.1093/gigascience/giad035 [code]
FriendlyClearMap: an optimized toolkit for mouse brain mapping and analysis.
Journal: GigaScience
In common: tifffile, scikit-image, NiBabel, 5 other tools, histology / microscopy, mouse, 2 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.7554/elife.95525.svg)](https://openscicode.org/badge/doi/10.7554/elife.95525)
<!-- oscr-badge:end -->
reStructuredText
.. oscr-badge:start

.. image:: https://openscicode.org/badge/doi/10.7554/elife.95525.svg
   :target: https://openscicode.org/badge/doi/10.7554/elife.95525
   :alt: OSCR

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