Realistic PET image synthesis from MRI for automated inference of brain atrophy and Alzheimer's.
The 13 matches
- [1] § Results › MRI2PET generates realistic PET images from MRI scans ↔ src/evaluation/calcFID.py, lines 1–32 · score 0.77 · Fr chet inception, inception v3, axial slicing, distance, FID, trained
- [2] § STAR★Methods › Method details › MRI2PET › Denoising with DDPM ↔ src/models/diffusionModel.py, lines 1–30 · score 0.65 · timestep embedding, diffusion models, CNN, DDPM, architectures, linear
- [3] § Results › MRI2PET generates realistic PET images from MRI scans ↔ src/evaluation/calcRealFID.py, lines 1–32 · score 0.63 · Fr chet, inception v3, distance, FID, model, PET
- [4] § STAR★Methods › Method details › MRI2PET › Laplacian Pyramid Loss Formalization ↔ src/models/diffusionModel.py, lines 287–299 · score 0.62 · Laplacian Pyramid loss, predicted image, predicted noise, model
- [5] § STAR★Methods › Method details › MRI2PET › Laplacian Pyramid Loss Formalization ↔ src/train_scripts/tune_MRI2PET.py, lines 1–61 · score 0.58 · noise prediction, Laplacian Pyramid, weighted, DDPM, loss, training
- [6] § STAR★Methods › Method details › MRI2PET › Style-Transferred Pre-Training ↔ src/utils/styleTransfer.py, lines 1–29 · score 0.57 · style transfer, neural, template, MRIs, real PET, layers
- [7] § STAR★Methods › Method details › MRI2PET › Style-Transferred Pre-Training ↔ src/train_scripts/pretrain_MRI2PET.py, lines 1–60 · score 0.55 · style transfer, added noise, diffusion model, real PET, tuning, training
- [8] § Results › Dataset ↔ src/utils/PET_PreProcessing.py, lines 1–53 · score 0.54 · rigidly registered, affine registered, frame, PET, MRI
- [9] § STAR★Methods › Method details › MRI2PET ↔ src/utils/styleTransfer.py, lines 1–29 · score 0.54 · synthesizing PET, Style Transferred, MRI2PET, Training
- [10] § Results › MRI2PET enhances downstream machine learning tasks ↔ src/evaluation/calcUtilityMMSE.py, lines 1–32 · score 0.54 · Mini Mental State, MMSE, utility, score, ADNI, prediction
- [11] § STAR★Methods › Method details › Experimental Setup ↔ src/generation/generateDownstream.py, lines 1–34 · score 0.54 · downstream utility, MRI2PET model, cluster, ADNI, train
- [12] § Results › MRI2PET enhances downstream machine learning tasks ↔ src/evaluation/calcUtility.py, lines 1–42 · score 0.52 · MMSE regression, synthetic PET, AUROC, real PET, accuracy, classification
- [13] § Results › Baseline comparisons › External baselines ↔ src/baselines/models/cdcGAN.py, lines 1–21 · score 0.51 · cross domain correspondences, CDC, GAN, External, baselines
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Python · 334 lines · 13 KB · MIT · 2 matches
- """MRI-conditioned 3D diffusion model used by MRI2PET.
- This module defines the main generative architecture in the paper: a 3D
- U-Net DDPM that takes a T1-weighted MRI volume as context and predicts the
- noise that was added to a paired amyloid-PET volume.
- Layout:
- * ``ImageEncoder`` — a small 3D CNN that produces a fixed-size embedding of
- the MRI context volume. The embedding is added to the standard
- sinusoidal timestep embedding and threaded through every U-Net block.
- * ``RMSNorm`` / ``LinearAttention`` / ``DoubleConv`` /
- ``DownBlock`` / ``UpBlock`` — building blocks of the U-Net.
- * ``DiffusionModel`` — the full model. Implements the standard DDPM noise
- schedule, an optional Laplacian-pyramid auxiliary loss (the paper's
- ``L_lap`` term, weighted by ``config.laplace_lambda``), DDPM ancestral
- sampling, and per-image NLL evaluation used by
- ``src/evaluation/calcBitsPerDim.py``.
- Checkpoints written by ``src/train_scripts/pretrain_MRI2PET.py`` and
- ``src/train_scripts/tune_MRI2PET.py`` store this model's state dict under
- the ``'model'`` key.
- """
- import torch
- import numpy as np
- from tqdm import tqdm
- import torch.nn as nn
- import torch.nn.functional as F
- from einops import rearrange
- class ImageEncoder(nn.Module):
- def __init__(self, config):
- super(ImageEncoder, self).__init__()
- self.depth = config.n_mri_channels
- self.image_dim = config.mri_image_dim
- self.conv1 = nn.Conv3d(1, 8, kernel_size=3, stride=1, padding=1)
- self.conv2 = nn.Conv3d(8, 16, kernel_size=3, stride=1, padding=1)
- self.conv3 = nn.Conv3d(16, 32, kernel_size=3, stride=1, padding=1)
- self.conv4 = nn.Conv3d(32, 64, kernel_size=3, stride=1, padding=1)
- self.flat_dim = 64 * (self.depth // 16) * (self.image_dim // 16) * (self.image_dim // 16)
- self.fc1 = nn.Linear(self.flat_dim, config.embed_dim)
- self.fc2 = nn.Linear(config.embed_dim, config.embed_dim)
- def forward(self, x):
- # Convolution + ReLU + MaxPooling
- x = F.relu(self.conv1(x))
- x = F.max_pool3d(x, 2)
- x = F.relu(self.conv2(x))
- x = F.max_pool3d(x, 2)
- x = F.relu(self.conv3(x))
- x = F.max_pool3d(x, 2)
- x = F.relu(self.conv4(x))
- x = F.max_pool3d(x, 2)
- # Flattening the output
- x = x.view(-1, self.flat_dim)
- # Passing through the fully connected layers
- x = F.relu(self.fc1(x))
- x = self.fc2(x)
- return x
- class RMSNorm(nn.Module):
- def __init__(self, dim):
- super().__init__()
- self.g = nn.Parameter(torch.ones(1, dim, 1, 1, 1))
- def forward(self, x):
- return F.normalize(x, dim = 1) * self.g * (x.shape[1] ** 0.5)
- class LinearAttention(nn.Module):
- def __init__(self, dim, heads=4, dim_head=32):
- super().__init__()
- self.heads = heads
- hidden_dim = dim_head * heads
- self.to_qkv = nn.Conv3d(dim, hidden_dim * 3, 1, bias = False)
- self.to_out = nn.Conv3d(hidden_dim, dim, 1)
- def forward(self, x):
- b, c, d, h, w = x.shape
- qkv = self.to_qkv(x)
- q, k, v = rearrange(qkv, 'b (qkv heads c) d h w -> qkv b heads c (d h w)', heads = self.heads, qkv=3)
- k = k.softmax(dim=-1)
- context = torch.einsum('bhdn,bhen->bhde', k, v)
- out = torch.einsum('bhde,bhdn->bhen', context, q)
- out = rearrange(out, 'b heads c (d h w) -> b (heads c) d h w', heads=self.heads, d=d, h=h, w=w)
- return self.to_out(out)
- class DoubleConv(nn.Module):
- def __init__(self, in_channels, out_channels, mid_channels=None, residual=False):
- super(DoubleConv, self).__init__()
- self.residual = residual
- if not mid_channels:
- mid_channels = out_channels
- self.double_conv = nn.Sequential(
- nn.Conv3d(in_channels, mid_channels, kernel_size=3, padding=1, bias=False),
- nn.GroupNorm(1, mid_channels),
- nn.GELU(),
- nn.Conv3d(mid_channels, out_channels, kernel_size=3, padding=1, bias=False),
- nn.GroupNorm(1, out_channels),
- )
- def forward(self, x):
- if self.residual:
- return F.gelu(x + self.double_conv(x))
- else:
- return self.double_conv(x)
- class DownBlock(nn.Module):
- def __init__(self, in_channels, out_channels, emb_dim=128):
- super(DownBlock, self).__init__()
- self.maxpool_conv = nn.Sequential(
- nn.MaxPool3d(2),
- DoubleConv(in_channels, in_channels, residual=True),
- DoubleConv(in_channels, out_channels),
- )
- self.emb_layer = nn.Sequential(
- nn.SiLU(),
- nn.Linear(
- emb_dim,
- out_channels
- ),
- )
- def forward(self, x, t):
- x = self.maxpool_conv(x)
- emb = self.emb_layer(t)[:, :, None, None, None].repeat(1, 1, x.shape[-3], x.shape[-2], x.shape[-1])
- return x + emb
- class UpBlock(nn.Module):
- def __init__(self, in_channels, out_channels, emb_dim=128):
- super(UpBlock, self).__init__()
- self.up = nn.Upsample(scale_factor=2, mode="trilinear", align_corners=True)
- self.conv = nn.Sequential(
- DoubleConv(in_channels, in_channels, residual=True),
- DoubleConv(in_channels, out_channels, in_channels // 2),
- )
- self.emb_layer = nn.Sequential(
- nn.SiLU(),
- nn.Linear(
- emb_dim,
- out_channels
- ),
- )
- def forward(self, x, skip_x, t):
- x = self.up(x)
- x = torch.cat([skip_x, x], dim=1)
- x = self.conv(x)
- emb = self.emb_layer(t)[:, :, None, None, None].repeat(1, 1, x.shape[-3], x.shape[-2], x.shape[-1])
- return x + emb
- class DiffusionModel(nn.Module):
- def __init__(self, config, laplace=0):
- super(DiffusionModel, self).__init__()
- self.num_timesteps = config.num_timesteps
- self.beta_start = config.beta_start
- self.beta_end = config.beta_end
- self.beta = torch.linspace(self.beta_start, self.beta_end, self.num_timesteps)
- self.alpha = 1 - self.beta
- self.alpha_hat = torch.cumprod(self.alpha, dim=0)
- self.image_dim = config.pet_image_dim
- self.n_channels = config.n_pet_channels
- self.embed_dim = config.embed_dim
- self.llambda = laplace
- self.contextEmbedding = ImageEncoder(config)
- self.inc = DoubleConv(1, 8)
- self.down1 = DownBlock(8, 16, self.embed_dim)
- self.sa1 = LinearAttention(16)
- self.down2 = DownBlock(16, 32, self.embed_dim)
- self.sa2 = LinearAttention(32)
- self.down3 = DownBlock(32, 64, self.embed_dim)
- self.sa3 = LinearAttention(64)
- self.down4 = DownBlock(64, 128, self.embed_dim)
- self.sa4 = LinearAttention(128)
- self.bot1 = DoubleConv(128, 128)
- self.bot2 = DoubleConv(128, 128)
- self.bot3 = DoubleConv(128, 128)
- self.up1 = UpBlock(192, 64, self.embed_dim)
- self.sa5 = LinearAttention(64)
- self.up2 = UpBlock(96, 32, self.embed_dim)
- self.sa6 = LinearAttention(32)
- self.up3 = UpBlock(48, 16, self.embed_dim)
- self.sa7 = LinearAttention(16)
- self.up4 = UpBlock(24, 8, self.embed_dim)
- self.sa8 = LinearAttention(8)
- self.outc = nn.Conv3d(8, 1, kernel_size=1)
- def timestep_embedding(self, t, channels, max_period=100):
- inv_freq = 1.0 / (
- max_period
- ** (torch.arange(0, channels, 2, device=t.device).float() / channels)
- )
- pos_enc_a = torch.sin(t.unsqueeze(1).repeat(1, channels // 2) * inv_freq)
- pos_enc_b = torch.cos(t.unsqueeze(1).repeat(1, channels // 2) * inv_freq)
- pos_enc = torch.cat([pos_enc_a, pos_enc_b], dim=-1)
- return pos_enc
- def sample_timesteps(self, n, device='cpu'):
- return torch.randint(low=1, high=self.num_timesteps, size=(n,), device=device)
- def noise_images(self, x, t, noise_level=1):
- "Add noise to images at instant t"
- self.alpha_hat = self.alpha_hat.to(x.device)
- sqrt_alpha_hat = torch.sqrt(self.alpha_hat.to(t.device)[t])[:, None, None, None].to(x.device)
- sqrt_one_minus_alpha_hat = torch.sqrt(1 - self.alpha_hat[t])[:, None, None, None].to(x.device)
- Ɛ = torch.randn_like(x)
- Ɛ = noise_level * Ɛ
- return sqrt_alpha_hat * x + sqrt_one_minus_alpha_hat * Ɛ, Ɛ
- def _forward(self, noised_images, t, condImage):
- "Forward pass through the model"
- noised_images = noised_images.unsqueeze(1)
- condImage = condImage.unsqueeze(1)
- emb = self.timestep_embedding(t, self.embed_dim, max_period=self.num_timesteps)
- emb += self.contextEmbedding(condImage)
- x1 = self.inc(noised_images)
- x2 = self.down1(x1, emb)
- x2 = self.sa1(x2)
- x3 = self.down2(x2, emb)
- x3 = self.sa2(x3)
- x4 = self.down3(x3, emb)
- x4 = self.sa3(x4)
- x5 = self.down4(x4, emb)
- x5 = self.sa4(x5)
- x5 = self.bot1(x5)
- x5 = self.bot2(x5)
- x5 = self.bot3(x5)
- x = self.up1(x5, x4, emb)
- x = self.sa5(x)
- x = self.up2(x, x3, emb)
- x = self.sa6(x)
- x = self.up3(x, x2, emb)
- x = self.sa7(x)
- x = self.up4(x, x1, emb)
- x = self.sa8(x)
- x = self.outc(x)
- x = x.squeeze(1)
- condImage = condImage.squeeze(1)
- return x
- def construct_image(self, noised_x, t, pred_noise):
- sqrt_alpha_hat = torch.sqrt(self.alpha_hat[t])[:, None, None, None].to(noised_x.device)
- sqrt_one_minus_alpha_hat = torch.sqrt(1 - self.alpha_hat[t])[:, None, None, None].to(noised_x.device)
- pred_x = (1 / sqrt_alpha_hat) * noised_x - (sqrt_one_minus_alpha_hat / sqrt_alpha_hat) * pred_noise
- return pred_x
- def laplacian_pyramid_loss(self, img1, img2, max_levels=5):
- def pyr_down(image):
- return F.avg_pool2d(image, kernel_size=2, stride=2, padding=0)
- def laplacian_pyramid(image, max_levels):
- current = image
- pyramid = []
- for _ in range(max_levels):
- down = pyr_down(current)
- up = F.interpolate(down, size=current.shape[-2:], mode='bilinear', align_corners=False)
- diff = current - up
- pyramid.append(diff)
- current = down
- return pyramid
- pyramid1 = laplacian_pyramid(img1, max_levels)
- pyramid2 = laplacian_pyramid(img2, max_levels)
- loss = sum(F.mse_loss(a, b) for a, b in zip(pyramid1, pyramid2))
- return loss
- def forward(self, context, input_images, gen_loss=True, noise_level=1, includeLaplace=False):
- noise_level = torch.sqrt(torch.tensor(noise_level))
- t = self.sample_timesteps(input_images.size(0), context.device)
- noised_images, noise = self.noise_images(input_images, t, noise_level)
- predictedNoise = self._forward(noised_images, t, context)
- if gen_loss:
- loss = F.mse_loss(noise, predictedNoise)
- if includeLaplace and self.llambda > 0:
- predictedImage = self.construct_image(noised_images, t, predictedNoise)
- laplace_loss = self.laplacian_pyramid_loss(input_images, predictedImage)
- loss += self.llambda * laplace_loss
- return loss, predictedNoise
- return predictedNoise
- def generate(self, context):
- n = context.size(0)
- x = torch.randn(n, self.n_channels, self.image_dim, self.image_dim, device=context.device)
- for timestep in tqdm(reversed(range(1, self.num_timesteps)), total=self.num_timesteps-1):
- t = (torch.ones(n) * timestep).long().to(context.device)
- predicted_noise = self._forward(x, t, context)
- alpha = self.alpha[t][:, None, None, None].to(context.device)
- alpha_hat = self.alpha_hat[t][:, None, None, None].to(context.device)
- beta = self.beta[t][:, None, None, None].to(context.device)
- if timestep > 1:
- noise = torch.randn_like(x, device=context.device)
- else:
- noise = torch.zeros_like(x, device=context.device)
- x = 1 / torch.sqrt(alpha) * (x - ((1 - alpha) / (torch.sqrt(1 - alpha_hat))) * predicted_noise) + torch.sqrt(beta) * noise
- return x
- def calculate_nll(self, context, input_images):
- nll = 0.0
- for timestep in tqdm(range(1, self.num_timesteps), leave=False):
- t = torch.ones(input_images.size(0), device=context.device, dtype=torch.long) * timestep
- noised_images, actual_noise = self.noise_images(input_images, t)
- predicted_noise = self._forward(noised_images, t, context)
- # Calculate the mean squared error between predicted and actual noise
- mse = torch.mean((predicted_noise - actual_noise) ** 2).cpu().numpy()
- # Convert MSE to log-likelihood assuming Gaussian noise
- sigma_t = torch.sqrt(1 - self.alpha_hat[t]).cpu().numpy()
- log_likelihood = -mse / (2 * sigma_t**2) - 0.5 * np.log(2 * np.pi * sigma_t**2)
- # Accumulate NLL
- nll += log_likelihood
- return [- nll[i].mean().item() * input_images[i].numel() for i in range(input_images.size(0))]
diffusionModel.py at commit 2a978e3, under MIT · at the source
Overview
- Department of Computer Science, University of Illinois at Urbana-Champaign, Urbana, IL, USA
- Center for Alzheimer’s and Related Dementias, National Institutes of Health, Bethesda, MD, USA
- DataTecnica, LLC, Washington, DC, USA
- University of Virginia, Department of Radiology and Medical Imaging, Charlottesville, VA, USA
- Laboratory of Neurogenetics, National Institute on Aging, National Institutes of Health, Bethesda, MD, USA
Abstract
The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.
Repositories
Its files are read in the Code ↔ Paper reader above, with 13 matches between paragraphs and lines of code.
Zenodo 15089724
Availability: 1 check, the latest on 29 September 2026: the link answers (HTTP 200)
- 29 September 2026: the link answers (HTTP 200)
btheodorou99/MRI2PET
2a978e3eda78246c6dd3fa28cbf7382b05c1f287, 20 May 2026Availability: 1 check, the latest on 29 September 2026: the link answers
- 29 September 2026: the link answers
124 files
- baseline_jobs/
cdcGAN.sh , Shell, 14 lines - baseline_jobs/
dclGAN.sh , Shell, 14 lines - baseline_jobs/
diffAugmentGAN.sh , Shell, 14 lines - baseline_jobs/
maskedGAN.sh , Shell, 14 lines - baseline_jobs/
paDiffusion.sh , Shell, 14 lines - evaluation_jobs/
evaluateBPD.sh , Shell, 13 lines - evaluation_jobs/
evaluateBaselines.sh , Shell, 20 lines - evaluation_jobs/
evaluateBaselinesFID.sh , Shell, 14 lines - evaluation_jobs/
evaluateBaselinesNonFID. , Shell, 14 linessh - evaluation_jobs/
evaluateFID.sh , Shell, 13 lines - evaluation_jobs/
evaluateIS.sh , Shell, 13 lines - evaluation_jobs/
evaluatePSNR.sh , Shell, 11 lines - evaluation_jobs/
evaluateRealFID.sh , Shell, 13 lines - evaluation_jobs/
evaluateSSIM.sh , Shell, 11 lines - evaluation_jobs/
evaluateUtility.sh , Shell, 12 lines - evaluation_jobs/
evaluateUtilityBinary.sh , Shell, 12 lines - evaluation_jobs/
evaluateUtilityFull.sh , Shell, 12 lines - evaluation_jobs/
evaluateUtilityFullPiece , Shell, 13 lineswise.sh - evaluation_jobs/
evaluateUtilityMMSE.sh , Shell, 12 lines - generation_jobs/
generateDataset.sh , Shell, 13 lines - generation_jobs/
generateDownstream.sh , Shell, 13 lines - generation_jobs/
generateDownstreamParall , Shell, 14 linesel.sh - generation_jobs/
generateDownstreamParall , Shell, 14 lineselTweaked.sh - generation_jobs/
generateSamples.sh , Shell, 13 lines - scripts/
list_subjects.py , Python, 197 lines - src/
__init__.py , Python, 1 line - src/
baselines/ , Python, 1 line__init__.py - src/
baselines/ , Python, 1 lineevaluation/ __init__.py - src/
baselines/ , Python, 94 linesevaluation/ calcFID.py - src/
baselines/ , Python, 78 linesevaluation/ calcIS.py - src/
baselines/ , Python, 48 linesevaluation/ calcPSNR.py - src/
baselines/ , Python, 48 linesevaluation/ calcSSIM.py - src/
baselines/ , Python, 90 linesgeneration/ generate_cdcGAN.py - src/
baselines/ , Python, 87 linesgeneration/ generate_dclGAN.py - src/
baselines/ , Python, 89 linesgeneration/ generate_diffAugmentGAN. py - src/
baselines/ , Python, 87 linesgeneration/ generate_maskedGAN.py - src/
baselines/ , Python, 81 linesgeneration/ generate_paDiffusion.py - src/
baselines/ , Python, 1 linemodels/ __init__.py - src/
baselines/ , Python, 206 lines, 1 matchmodels/ cdcGAN.py - src/
baselines/ , Python, 229 linesmodels/ dclGAN.py - src/
baselines/ , Python, 81 linesmodels/ diffAugmentGAN.py - src/
baselines/ , Python, 208 linesmodels/ maskedGAN.py - src/
baselines/ , Python, 368 linesmodels/ paDiffusion.py - src/
baselines/ , Python, 1 linetrain_scripts/ __init__.py - src/
baselines/ , Python, 208 linestrain_scripts/ train_cdcGAN.py - src/
baselines/ , Python, 186 linestrain_scripts/ train_dclGAN.py - src/
baselines/ , Python, 127 linestrain_scripts/ train_diffAugmentGAN.py - src/
baselines/ , Python, 206 linestrain_scripts/ train_maskedGAN.py - src/
baselines/ , Python, 171 linestrain_scripts/ train_paDiffusion.py - src/
config.py , Python, 75 lines - src/
evaluation/ , Python, 1 line__init__.py - src/
evaluation/ , Python, 98 linescalcBitsPerDim.py - src/
evaluation/ , Python, 102 lines, 1 matchcalcFID.py - src/
evaluation/ , Python, 88 linescalcIS.py - src/
evaluation/ , Python, 55 linescalcPSNR.py - src/
evaluation/ , Python, 91 lines, 1 matchcalcRealFID.py - src/
evaluation/ , Python, 57 linescalcSSIM.py - src/
evaluation/ , Python, 192 lines, 1 matchcalcUtility.py - src/
evaluation/ , Python, 180 linescalcUtilityBinary.py - src/
evaluation/ , Python, 196 linescalcUtilityFull.py - src/
evaluation/ , Python, 203 linescalcUtilityFullPiecewise .py - src/
evaluation/ , Python, 277 lines, 1 matchcalcUtilityMMSE.py - src/
generation/ , Python, 1 line__init__.py - src/
generation/ , Python, 174 linesgenerateAlzheimers.py - src/
generation/ , Python, 194 linesgenerateCaseStudies.py - src/
generation/ , Python, 102 linesgenerateDataset.py - src/
generation/ , Python, 79 lines, 1 matchgenerateDownstream.py - src/
generation/ , Python, 84 linesgenerateDownstreamParall el.py - src/
generation/ , Python, 144 linesgenerateExploration.py - src/
generation/ , Python, 65 linesgeneratePlots.py - src/
generation/ , Python, 167 linesgenerateSamples.py - src/
models/ , Python, 1 line__init__.py - src/
models/ , Python, 334 lines, 2 matchesdiffusionModel.py - src/
models/ , Python, 118 linesdownstreamModel.py - src/
models/ , Python, 160 linesganModel.py - src/
train_scripts/ , Python, 1 line__init__.py - src/
train_scripts/ , Python, 122 lines, 1 matchpretrain_MRI2PET.py - src/
train_scripts/ , Python, 117 linespretrain_noisyPretrained Diffusion.py - src/
train_scripts/ , Python, 114 linespretrain_selfPretrainedD iffusion.py - src/
train_scripts/ , Python, 118 linestrain_MRI2PET_noPretrain .py - src/
train_scripts/ , Python, 116 linestrain_baseDiffusion.py - src/
train_scripts/ , Python, 109 linestrain_baseGAN.py - src/
train_scripts/ , Python, 129 lines, 1 matchtune_MRI2PET.py - src/
train_scripts/ , Python, 119 linestune_MRI2PET_noLoss.py - src/
train_scripts/ , Python, 115 linestune_noisyPretrainedDiff usion.py - src/
train_scripts/ , Python, 116 linestune_selfPretrainedDiffu sion.py - src/
utils/ , Python, 30 linesMRI_PostProcessing.py - src/
utils/ , Python, 48 linesMRI_PreProcessing.py - src/
utils/ , Python, 88 linesPET_ConvertAgain.py - src/
utils/ , Python, 102 linesPET_ConvertToNifti.py - src/
utils/ , Python, 50 linesPET_ExploreQuality.py - src/
utils/ , Python, 56 linesPET_PostProcessing.py - src/
utils/ , Python, 91 lines, 1 matchPET_PreProcessing.py - src/
utils/ , Python, 54 linesPET_PreProcessingSafe.py - src/
utils/ , Python, 59 linesPET_PreProcessingSingle. py - src/
utils/ , Python, 1 line__init__.py - src/
utils/ , Python, 43 linesarchive/ mergeADNI.py - src/
utils/ , Python, 108 linesarchive/ processMRI.py - src/
utils/ , Python, 50 linesarchive/ scaleImages.py - src/
utils/ , Python, 158 linesbuildDataset.py - src/
utils/ , Python, 53 linesscalePretrain.py - src/
utils/ , Python, 209 lines, 2 matchesstyleTransfer.py - train_jobs/
baseDiffusion.sh , Shell, 13 lines - train_jobs/
baseGAN.sh , Shell, 13 lines - train_jobs/
mri2pet_noPretrain.sh , Shell, 13 lines - train_jobs/
pretrain_mri2pet.sh , Shell, 13 lines - train_jobs/
pretrain_noisyPretrained , Shell, 13 linesDiffusion.sh - train_jobs/
pretrain_selfPretrainedD , Shell, 13 linesiffusion.sh - train_jobs/
tune_mri2pet.sh , Shell, 13 lines - train_jobs/
tune_mri2pet_noLoss.sh , Shell, 13 lines - train_jobs/
tune_noisyPretrainedDiff , Shell, 13 linesusion.sh - train_jobs/
tune_selfPretrainedDiffu , Shell, 13 linession.sh - utils_jobs/
__init__.py , Python, 1 line - utils_jobs/
utils_buildDataset.sh , Shell, 9 lines - utils_jobs/
utils_convertPetToNifti. , Shell, 9 linessh - utils_jobs/
utils_mriPostprocess.sh , Shell, 10 lines - utils_jobs/
utils_mriPreprocess.sh , Shell, 10 lines - utils_jobs/
utils_petPostprocess.sh , Shell, 10 lines - utils_jobs/
utils_petPreprocess.sh , Shell, 10 lines - utils_jobs/
utils_petPreprocessSafe. , Shell, 10 linessh - utils_jobs/
utils_scalePretrain.sh , Shell, 10 lines - utils_jobs/
utils_styleTransfer.sh , Shell, 12 lines - LICENSE, License, 21 lines
- README.md, Text, 201 lines
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;
- 122 scripts, each with its path and the digest of its content;
- 13 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.
Code and data availability statement
The paper has a code and data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:
- it says that the data are available on request
Read it in the paper: doi.org/10.1016/j.isci.2026.115747.
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, 29 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 6 authors, 4 keywords, 6 funders, 23 references.
Cite
This paper
Theodorou, B., Dadu, A., Avants, B., Nalls, M., Sun, J., & Faghri, F. (2026). Realistic PET image synthesis from MRI for automated inference of brain atrophy and Alzheimer's. iScience, 29(5), 115747. https://
BibTeX
@article{theodorou2026re
author = {Theodorou, Brandon and Dadu, Anant and Avants, Brian and Nalls, Mike and Sun, Jimeng and Faghri, Faraz},
title = {{Realistic PET image synthesis from MRI for automated inference of brain atrophy and Alzheimer's}},
journal = {iScience},
year = {2026},
month = apr,
volume = {29},
number = {5},
pages = {115747},
publisher = {Elsevier},
issn = {2589-0042},
doi = {10.1016/
url = {https://
pmid = {42164525},
pmcid = {PMC13185845}
}
RIS
TY - JOUR
AU - Theodorou, Brandon
AU - Dadu, Anant
AU - Avants, Brian
AU - Nalls, Mike
AU - Sun, Jimeng
AU - Faghri, Faraz
TI - Realistic PET image synthesis from MRI for automated inference of brain atrophy and Alzheimer's
T2 - iScience
J2 - iScience
PY - 2026
DA - 2026/
VL - 29
IS - 5
SP - 115747
SN - 2589-0042
PB - Elsevier
DO - 10.1016/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1016/
"type": "article-journal",
"title": "Realistic PET image synthesis from MRI for automated inference of brain atrophy and Alzheimer's",
"container-title": "iScience",
"author": [
{
"family": "Theodorou",
"given": "Brandon"
},
{
"family": "Dadu",
"given": "Anant"
},
{
"family": "Avants",
"given": "Brian"
},
{
"family": "Nalls",
"given": "Mike"
},
{
"family": "Sun",
"given": "Jimeng"
},
{
"family": "Faghri",
"given": "Faraz"
}
],
"container-title-short":
"volume": "29",
"issue": "5",
"page": "115747",
"DOI": "10.1016/
"PMID": "42164525",
"PMCID": "PMC13185845",
"ISSN": "2589-0042",
"publisher": "Elsevier",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
15
]
]
}
}
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/s41597-026-07248-6 [code]
- A large-scale fMRI dataset for vision-language semantic association.Journal: Scientific dataIn common: dcm2niix, ANTs, scikit-image, 8 other tools, methods / tools
- [2] doi:10.3390/jimaging12070276 [code]
- Hyperelastic Regularization for Near-Diffeomorphic Transformer-Based Brain MRI Registration.Journal: Journal of imagingIn common: ANTs, scikit-image, Pillow, 7 other tools, methods / tools, structural MRI / diffusion
- [3] doi:10.1002/alz.71649 [code]
- Postmortem brain MRI reveals differential associations of subcortical and limbic volumes with cortical thinning and neurodegenerative pathologies.Journal: Alzheimer's & dementia : the journal of the Alzheimer's AssociationIn common: ANTs, scikit-image, Pillow, 7 other tools, Alzheimer's / dementia, structural MRI / diffusion
- [4] doi:10.1371/journal.pcbi.1014555 [code]
- Body surface potential driven personalisation of electrophysiological digital twins in hypertrophic cardiomyopathy.Journal: PLoS computational biologyIn common: ANTs, scikit-image, Pillow, 7 other tools, structural MRI / diffusion
- [5] doi:10.2463/mrms.mp.2024-0149 [code]
- Image Distortion Correction for Diffusion MR Imaging Using a Transformer-based U-Net.Journal: Magnetic resonance in medical sciences : MRMS : an official journal of Japan Society of Magnetic Resonance in MedicineIn common: ANTs, scikit-image, Pillow, 7 other tools, structural MRI / diffusion
- [6] doi:10.1038/s41467-026-73373-w [code]
- Mapping neuro-vascular unit communications reveals distinct angiogenic programs across developing mouse brain regions.Journal: Nature communicationsIn common: ANTs, scikit-image, Pillow, 7 other tools
- [7] doi:10.1038/s41467-026-71918-7 [code]
- Developmental disinhibition gates language lateralization in childhood.Journal: Nature communicationsIn common: dcm2niix, ANTs, NiBabel, 6 other tools
- [8] doi:10.1038/s41467-026-71719-y [code]
- Brain functional-structural gradient coupling reflects development, behavior and genetic influences.Journal: Nature communicationsIn common: dcm2niix, ANTs, NiBabel, 6 other tools
- [9] doi:10.1162/imag.a.1164 [code]
- Bias and generalizability of brain age prediction models: A multi-cohort evaluation with anatomical and interpretability insights.Journal: Imaging neuroscience (Cambridge, Mass.)In common: ANTs, Pillow, NiBabel, 6 other tools, Alzheimer's / dementia, structural MRI / diffusion
- [10] doi:10.1038/s41597-026-06869-1 [code]
- Individual Brain Charting: fifth release of high-resolution fMRI data for cognitive mapping.Journal: Scientific dataIn common: ANTs, scikit-image, Pillow, 6 other tools, methods / tools
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 2 repositories of the authors' code, each at its verified commit and with its license, 122 scripts, and 13 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:dcbe4ec880e6d3d3…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
