OSCR

Counterfactual Diffusion Modeling Enables Spatially Targeted Reprogramming of Tissue Microenvironments.

A correction to this paper has been published: the notice, 42651747, from Europe PMC.

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 · 4 of them tie a paragraph to a whole file, not to given lines: weak matches, whose lines are not tinted
  1. [1] § 2. Methods › 2.4. Forward Diffusion and Joint Training Objective ↔ metrics/loss_function.py, the whole file · a weak match · score 0.77 · Euclidean distance matrices, pairwise distance, position loss, MSE, predicted, Training
  2. [2] § 2. Methods › 2.3. Model Architecture: SPAD-CFR ↔ models/node_encoder.py, the whole file · a weak match · score 0.72 · hidden dimensions, Linear Attention Transformer, GELU, MLPs, Layer, Encoder
  3. [3] § 2. Methods › 2.3. Model Architecture: SPAD-CFR ↔ models/conditional_denoising_model.py, lines 23–109 · score 0.71 · hidden dimensions, Linear Attention Transformer, GELU, MLPs, point cloud, Layer
  4. [4] § 2. Methods › 2.5. Deterministic DDIM Inversion and Sampling ↔ utils/diffusion_model/diffusion/noise_model.py, lines 369–448 · score 0.69 · Denoising Diffusion Implicit, random noise, point cloud, DDIM, formulation, Prediction
  5. [5] § 2. Methods › 2.5. Deterministic DDIM Inversion and Sampling ↔ utils/counterfactual_prediction.py, lines 84–161 · score 0.66 · DDIM Inversion, inversion step, backward, point cloud, ODE, trajectory
  6. [6] § 2. Methods › 2.1. Datasets and Data Preprocessing ↔ utils/counterfactual_prediction.py, lines 15–81 · score 0.64 · inverse hyperbolic sine, TCF7, arcsinh, thresholds, transformed, cell
  7. [7] § 2. Methods › 2.3. Model Architecture: SPAD-CFR ↔ models/conditional_denoising_model.py, lines 23–109 · score 0.62 · Linear Attention Transformer, fused, heads, MLPs, point cloud, embeddings
  8. [8] § 2. Methods › 2.4. Forward Diffusion and Joint Training Objective ↔ metrics/loss_function.py, the whole file · a weak match · score 0.60 · Squared Error, feature loss, MSE, protein, predicted, Training
  9. [9] § 2. Methods › 2.2. Problem Formulation: A Structural Causal Model for Spatial Biology ↔ utils/counterfactual_prediction.py, lines 210–336 · score 0.56 · DDIM inversion, reconstruction, reproducible, encoding, inference, variable
  10. [10] § 2. Methods › 2.1. Datasets and Data Preprocessing ↔ scripts/split_by_expression.py, lines 1–40 · score 0.55 · arcsinh transformed, gating, IMC, thresholds, Melanoma, tumor
  11. [11] § 3. Results › 3.1. A Structural Causal Diffusion Framework for Spatial Counterfactual Inference ↔ models/node_encoder.py, the whole file · a weak match · score 0.54 · node encoder, linear attention, heads, branch, architecture, transformer
  12. [12] § 2. Methods › 2.1. Datasets and Data Preprocessing ↔ scripts/split_by_column.py, lines 1–55 · score 0.53 · Zurich, Triple, split, Basel, IMC, peripheral
  13. [13] § 2. Methods › 2.1. Datasets and Data Preprocessing ↔ scripts/run_inference.py, lines 1–67 · score 0.51 · MERFISH Mouse, L6, L2, Cortex, slices, training
  14. [14] § 3. Results › 3.1. A Structural Causal Diffusion Framework for Spatial Counterfactual Inference ↔ utils/diffusion_model/diffusion/noise_model.py, lines 369–448 · score 0.50 · Denoising Diffusion Implicit, point cloud, DDIM, noise, prediction, node

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 · 337 lines · 15 KB · MIT · 3 matches

  1. """
  2. Counterfactual prediction workflow
  3. """
  4. from typing import List, Optional, Union
  5. import torch
  6. import numpy as np
  7. import random
  8. from utils.data.dataholder import DataHolder
  9. from utils.data.load import remove_mean_with_mask
  10. from utils.diffusion_model.diffusion.noise_model import NoiseModel
  11. from utils.concept_discovery import apply_node_intervention
  12. def build_intervention_target(
  13. original_data: DataHolder,
  14. z_nodes: torch.Tensor,
  15. delta_c_node: torch.Tensor,
  16. alpha: float,
  17. target_cell_classes: Optional[List[Union[int, str]]],
  18. ) -> torch.Tensor:
  19. """
  20. Build the post-intervention node conditions z_nodes_target, supporting filtering by cell_class.
  21. """
  22. if target_cell_classes is not None and original_data.cell_class is not None:
  23. cls_tensor = original_data.cell_class
  24. if cls_tensor.dim() == 3 and cls_tensor.shape[-1] == 1:
  25. cls_tensor = cls_tensor.squeeze(-1)
  26. # Support string labels: requires cell_class_decoder to map int -> str
  27. cls_ids = []
  28. for cls in target_cell_classes:
  29. if isinstance(cls, str):
  30. if not hasattr(original_data, "cell_class_decoder"):
  31. raise ValueError("String label mapping is required, please ensure DataHolder carries cell_class_decoder.")
  32. decoder = original_data.cell_class_decoder
  33. inv_decoder = {v: k for k, v in decoder.items()}
  34. if cls not in inv_decoder:
  35. raise ValueError(f"Label {cls} is not in cell_class_decoder.")
  36. cls_ids.append(inv_decoder[cls])
  37. else:
  38. cls_ids.append(cls)
  39. target_mask = torch.zeros_like(cls_tensor, dtype=torch.bool)
  40. for cls_id in cls_ids:
  41. target_mask = target_mask | (cls_tensor == cls_id)
  42. if original_data.node_mask is not None:
  43. target_mask = target_mask & original_data.node_mask
  44. # # =================== USER SPECIFIC LOGIC ===================
  45. # # Filter TCF7+ PD1+ cells (can be commented out after running)
  46. # if hasattr(original_data, 'gene_names'):
  47. # gene_names = original_data.gene_names
  48. # if "TCF7" in gene_names and "PD1" in gene_names:
  49. # tcf7_idx = gene_names.index("TCF7")
  50. # pd1_idx = gene_names.index("PD1")
  51. # expr_matrix = original_data.node_features
  52. # # Apply inverse hyperbolic sine transformation np.arcsinh(expr_matrix / 1.0)
  53. # expr_arcsinh = torch.arcsinh(expr_matrix / 1.0)
  54. # # Apply threshold > 1.5
  55. # tcf7_mask = expr_arcsinh[..., tcf7_idx] > 1.5
  56. # pd1_mask = expr_arcsinh[..., pd1_idx] > 1.5
  57. # # target_mask = target_mask & tcf7_mask & pd1_mask
  58. # target_mask = target_mask & pd1_mask
  59. # # print(f"TCF7+ PD1+ filtering applied, current number of eligible cells: {target_mask.sum().item()}")
  60. # print(f"PD1+ filtering applied, current number of eligible cells: {target_mask.sum().item()}")
  61. # else:
  62. # print("Warning: TCF7 or PD1 gene not found in the data, cannot apply TCF7+ PD1+ filtering condition.")
  63. # # ===========================================================
  64. delta = delta_c_node.view(1, 1, -1) # [1,1,d]
  65. z_nodes_target = z_nodes.clone()
  66. z_nodes_target = z_nodes_target + alpha * delta * target_mask.unsqueeze(-1)
  67. return z_nodes_target
  68. else:
  69. # Apply intervention to all nodes by default
  70. return apply_node_intervention(z_nodes, delta_c_node, alpha)
  71. def run_ddim_inversion(
  72. model,
  73. noise_model: NoiseModel,
  74. data_start: DataHolder,
  75. target_t_int: int,
  76. cond_nodes: torch.Tensor,
  77. num_sampling_steps: int,
  78. ) -> DataHolder:
  79. """
  80. Use DDIM Inversion to reverse diffuse the original data to the specified time step target_t_int.
  81. """
  82. device = data_start.node_features.device
  83. batch_size = data_start.node_features.shape[0]
  84. if target_t_int == 0:
  85. z_t = data_start.copy()
  86. z_t.t_int = torch.zeros((batch_size, 1), device=device, dtype=torch.long)
  87. z_t.t = torch.zeros((batch_size, 1), device=device)
  88. z_t.diffusion_time = torch.zeros((batch_size, 1), device=device)
  89. return z_t
  90. inversion_step_size = 10
  91. # Engineering details: avoid the t=0 singularity, manually add a trace amount of noise to t=inversion_step_size (or target_t_int, whichever is smaller)
  92. start_t_int = min(inversion_step_size, target_t_int)
  93. t_int_array = torch.full((batch_size, 1), start_t_int, device=device, dtype=torch.long)
  94. t_float = t_int_array.float() / num_sampling_steps
  95. # Calculate the starting trace noise parameters
  96. a = noise_model.get_alpha_bar(t_int=t_int_array, key="p").unsqueeze(-1)
  97. s = noise_model.get_sigma_bar(t_int=t_int_array, key="p").unsqueeze(-1)
  98. # Add trace noise to coordinates
  99. noise_pos = torch.randn(data_start.positions.shape, device=device)
  100. noise_positions_masked = noise_pos * data_start.node_mask.unsqueeze(-1)
  101. pos_t = a * data_start.positions + s * noise_positions_masked
  102. # Add trace noise to protein expression
  103. noise_features = torch.randn(data_start.node_features.shape, device=device)
  104. noise_features_masked = noise_features * data_start.node_mask.unsqueeze(-1)
  105. features_t = a * data_start.node_features + s * noise_features_masked
  106. # Create the initial, slightly noised point cloud starting point
  107. z_t = DataHolder(
  108. node_features=features_t,
  109. positions=pos_t,
  110. cell_class=data_start.cell_class,
  111. cell_ID=data_start.cell_ID,
  112. node_mask=data_start.node_mask,
  113. t_int=t_int_array,
  114. t=t_float,
  115. diffusion_time=t_float,
  116. ).mask()
  117. # True DDIM Inversion: use the ODE solver to integrate backwards step-by-step from start_t_int to target_t_int
  118. for curr_t in range(start_t_int, target_t_int, inversion_step_size):
  119. next_t = min(curr_t + inversion_step_size, target_t_int)
  120. # Set the current time step
  121. curr_t_array = torch.full((batch_size, 1), curr_t, dtype=torch.long, device=device)
  122. curr_t_float = curr_t_array.float() / num_sampling_steps
  123. z_t.t_int = curr_t_array
  124. z_t.t = curr_t_float
  125. z_t.diffusion_time = curr_t_float
  126. # Predict x_0 (Note: use the original condition z_nodes to extract the most realistic diffusion trajectory)
  127. pred_x0 = model.denoising_model(z_t, cond_nodes)
  128. # Use the DDIM formula to calculate the next z_{t+\Delta t}
  129. next_t_array = torch.full((batch_size, 1), next_t, dtype=torch.long, device=device)
  130. z_t = noise_model.sample_zs_from_zt_and_pred(
  131. z_t=z_t,
  132. pred=pred_x0,
  133. s_int=next_t_array,
  134. )
  135. return z_t
  136. def run_ddim_denoising(
  137. model,
  138. noise_model: NoiseModel,
  139. z_t_init: DataHolder,
  140. cond_nodes: torch.Tensor,
  141. num_sampling_steps: int,
  142. ) -> DataHolder:
  143. """
  144. Start from the same noisy starting point z_t_init and run the complete denoising process under the given node conditions cond_nodes.
  145. """
  146. device = z_t_init.node_features.device
  147. batch_size = z_t_init.node_features.shape[0]
  148. z_t_run = z_t_init.copy()
  149. sample_interval = 10
  150. start_step = z_t_run.t_int[0, 0].item() # Start from the time step corresponding to the current noise level
  151. for s_int in reversed(range(0, int(start_step) + 1, sample_interval)):
  152. # The current model makes a prediction at time s_int
  153. t_array = torch.full((batch_size, 1), s_int, dtype=torch.long, device=device)
  154. t_float = t_array.float() / num_sampling_steps
  155. z_t_run.t_int = t_array
  156. z_t_run.t = t_float
  157. z_t_run.diffusion_time = t_float
  158. # Conditional denoising one step to predict x_0
  159. pred = model.denoising_model(z_t_run, cond_nodes)
  160. if s_int > 0:
  161. # According to the noise model, use the DDIM formula to go from the current time s_int to the next clearer time s_int - sample_interval
  162. next_s_int = max(0, s_int - sample_interval)
  163. next_s_array = torch.full((batch_size, 1), next_s_int, dtype=torch.long, device=device)
  164. z_t_run = noise_model.sample_zs_from_zt_and_pred(
  165. z_t=z_t_run,
  166. pred=pred,
  167. s_int=next_s_array,
  168. )
  169. else:
  170. # The final step (s_int == 0), directly use the predicted x_0
  171. z_t_run = pred
  172. return z_t_run
  173. def counterfactual_prediction(
  174. model,
  175. noise_model: NoiseModel,
  176. original_data: DataHolder,
  177. delta_c_node: torch.Tensor,
  178. alpha: float,
  179. num_sampling_steps: int = 1000,
  180. noise_level: float = None,
  181. target_cell_classes: Optional[List[Union[int, str]]] = None,
  182. seed: Optional[int] = 42,
  183. ) -> DataHolder:
  184. """
  185. Counterfactual prediction: Predict the point cloud after intervention
  186. Workflow:
  187. 1. Encoding: Z_nodes = Encoder_nodes(X). Get the latent variables of each cell's current state.
  188. 2. Intervention condition construction:
  189. - Based on the set target cell types (optional), intervene on the latent variables: Z_nodes_target = Z_nodes + α * Δc_node
  190. 3. True DDIM Inversion (forward reverse inference):
  191. - Avoid the t=0 singularity (trace noise addition), and integrate backwards step-by-step based on the original condition Z_nodes via the ODE solver.
  192. - Deterministically reach the target time step determined by noise_level, obtaining a high-fidelity noisy starting point z_t_init.
  193. 4. Two-stage denoising generation with "Reconstruction Error Correction":
  194. - Reconstruction: Starting from z_t_init, run denoising conditioned on Z_nodes to estimate the model's systematic bias in the observation space.
  195. - Intervention: Starting from z_t_init, run denoising conditioned on Z_nodes_target to generate the initial counterfactual results.
  196. - Calibration: Compensate the systematic bias into the initial counterfactual results to obtain the final counterfactual predicted point cloud X_counterfactual.
  197. Args:
  198. model: Trained diffusion model (includes node_encoder and denoising_model)
  199. noise_model: Noise model
  200. original_data: Original point cloud data
  201. delta_c_node: Node-level concept direction [d_node]
  202. alpha: Intervention strength
  203. num_sampling_steps: Sampling steps (default 1000, consistent with diffusion_steps during training)
  204. noise_level: Initial noise level (between 0-1)
  205. target_cell_classes: Apply intervention only to these cell_class, can be integer ID or string label; if None, apply to all nodes
  206. seed: Random seed to ensure reproducible noise addition. If None, no seed is set
  207. Returns:
  208. X_counterfactual: Counterfactual predicted point cloud
  209. """
  210. # Set random seed for reproducibility if provided
  211. if seed is not None:
  212. torch.manual_seed(seed)
  213. if torch.cuda.is_available():
  214. torch.cuda.manual_seed_all(seed)
  215. np.random.seed(seed)
  216. random.seed(seed)
  217. torch.backends.cudnn.deterministic = True
  218. torch.backends.cudnn.benchmark = False
  219. model.node_encoder.eval()
  220. model.denoising_model.eval()
  221. device = original_data.node_features.device
  222. batch_size = original_data.node_features.shape[0]
  223. num_nodes = original_data.node_features.shape[1]
  224. with torch.no_grad():
  225. # Step 1: Encode the original point cloud to get the latent variables of the current state of each cell
  226. z_nodes = model.node_encoder(original_data) # [B, N, d_node]
  227. # Step 2: Build intervention conditions (optional filtering by cell_class)
  228. z_nodes_target = build_intervention_target(
  229. original_data, z_nodes, delta_c_node, alpha, target_cell_classes
  230. )
  231. # Step 3: Conditional point cloud diffusion sampling
  232. if noise_level is None:
  233. raise ValueError("noise_level must be provided")
  234. # Map the noise level to the time step
  235. initial_t_int = int(noise_level * num_sampling_steps)
  236. initial_t_int = max(0, min(initial_t_int, num_sampling_steps)) # Ensure it is within the valid range
  237. z_t_init = run_ddim_inversion(
  238. model=model,
  239. noise_model=noise_model,
  240. data_start=original_data,
  241. target_t_int=initial_t_int,
  242. cond_nodes=z_nodes,
  243. num_sampling_steps=num_sampling_steps,
  244. )
  245. # ========= Two-stage denoising framework using "Reconstruction Error Correction" =========
  246. # Step 1: Reconstruction under α=0 condition, used to estimate the model's systematic bias in the observation space
  247. X_recon_0 = run_ddim_denoising(
  248. model=model,
  249. noise_model=noise_model,
  250. z_t_init=z_t_init,
  251. cond_nodes=z_nodes,
  252. num_sampling_steps=num_sampling_steps,
  253. )
  254. # Here, by default, we only correct the bias for protein expression (node_features);
  255. # If you want to correct coordinates as well in the future, you can similarly calculate and add bias to positions.
  256. bias_features = original_data.node_features - X_recon_0.node_features
  257. if original_data.node_mask is not None:
  258. bias_features = bias_features * original_data.node_mask.unsqueeze(-1)
  259. # Step 2: Generate counterfactual results under the intervention condition Z + αΔc
  260. X_cf_alpha = run_ddim_denoising(
  261. model=model,
  262. noise_model=noise_model,
  263. z_t_init=z_t_init,
  264. cond_nodes=z_nodes_target,
  265. num_sampling_steps=num_sampling_steps,
  266. )
  267. # Step 3: Apply translation calibration using the same bias as α=0
  268. X_cf_alpha.node_features = X_cf_alpha.node_features + bias_features
  269. z_t = X_cf_alpha
  270. # Keep cell class related information for subsequent visualization or filtering by type
  271. z_t.cell_class = original_data.cell_class
  272. if hasattr(original_data, "cell_class_decoder"):
  273. z_t.cell_class_decoder = original_data.cell_class_decoder
  274. # Keep cell_section information (if it exists), used for slice differentiation in batch mode
  275. if hasattr(original_data, "cell_section") and original_data.cell_section is not None:
  276. z_t.cell_section = original_data.cell_section
  277. if hasattr(original_data, "cell_section_decoder"):
  278. z_t.cell_section_decoder = original_data.cell_section_decoder
  279. # Return the counterfactual predicted point cloud
  280. return z_t

counterfactual_prediction.py at commit 3b034fa, under MIT · at the source

Overview

Authors: Wenhui Ding1, Zhenhua Luo1, Yuanyan Xiong2
ORCID iDs: Wenhui Ding
  1. Institute of Precision Medicine, The First Affiliated Hospital, Sun Yat-sen University, Guangzhou 510080, China
  2. Key Laboratory of Gene Engineering of the Ministry of Education, Institute of Healthy Aging Research, School of Life Sciences, Sun Yat-sen University, Guangzhou 510275, China
Journal: Biology, volume 15, issue 14, article 1097
Dates: received 15 June 2026; accepted 6 July 2026; published online 8 July 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.3390/biology15141097 · PMID 42510645 · PMCID PMC13406000 · OpenAlex W7167743505
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), other condition (population)
Methods: Statistics, Machine learning, Preprocessing
Keywords: generative model, in silico simulation, spatial transcriptomics, spatial proteomics, tumor microenvironment
Topic: Mathematical Biology Tumor Growth (Modeling and Simulation, Mathematics), according to OpenAlex
Funding: Basic and Applied Basic Research Foundation of Guangdong Province (2025A1515010559); Guangdong Provincial Natural Science Foundation (2025A1515011628)
Citations: cited by 1 paper (Europe PMC); 41 references in the paper
Notices: A correction to this paper has been published (42651747, from Europe PMC)

Abstract

Spatially resolved single-cell technologies can provide deep insights into cellular heterogeneity and tissue structural characteristics. However, the data obtained are purely observational and cannot reveal the specific mechanisms by which tissues respond to particular perturbations. Most computational models of single-cell perturbations either operate in a non-spatial latent space or fix tissue geometry within a static spatial structure, thereby limiting their ability to integrate molecular profiles with tissue topological remodeling. We propose SPAD-CFR (Spatial Point-cloud Attention-based Diffusion for CounterFactual Reprogramming). Each tissue is treated as a spatial point cloud containing cellular molecular profiles and physical coordinates. We implement Pearl’s three-step workflow for causal inference through deterministic diffusion inversion and sampling. This model can apply interventions to individual cells and generate counterfactual-style tissues in which molecular profiles and spatial coordinates change together. In validation across three datasets, SPAD-CFR reproduces the hierarchical structure of the mouse cerebral cortex, simulates phenotypic distribution differences across different histological grades of breast cancer, and reconstructs hypoxia-associated mesenchymal phenotypes at the invasion margins of triple-negative tumors. In melanoma, activation interventions targeting PD-1+ CD8+ T cells produce spatially confined, distance-dependent bystander cytotoxic effects. Based on these findings, we propose SPAD-CFR, a biologically informed generative framework for conducting counterfactual-style spatial simulations to validate hypotheses regarding microenvironment reprogramming.

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

WenhuiDing/SPAD-CFR

License: MIT
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 3b034fa1b929facb13453dccab46a388feccbdcc, 17 May 2026
Languages: Python (34)
Size: 49 files, 34 scripts
Software Heritage: not archived
Found in: “Data Availability Statement”
Holds: README, license file, environment (environment.yml, requirements.txt, utils/diffusion_model/setup/setup.py), tests
Not found: CITATION.cff, continuous integration, documentation
Tools: PyTorch (20 files), NumPy (9 files), pandas (8 files), PyTorch Lightning (4 files), PyTorch Geometric (3 files), SciPy (2 files), Matplotlib (1 file), Scanpy (1 file), seaborn (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
36 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;
  • 34 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 Statement

All datasets analyzed in this study are publicly available from their original publications. The MERFISH mouse primary motor cortex dataset [18] is accessible via the Brain Image Library at https://doi.org/10.35077/g.21. The IMC breast cancer datasets (Basel and Zurich cohorts) [19] are available on Zenodo at https://doi.org/10.5281/zenodo.3518284. The multiplexed melanoma IMC dataset [20] is available on Zenodo, with raw single-cell expression data at https://doi.org/10.5281/zenodo.6004986, and processed data at https://doi.org/10.5281/zenodo.5994136. The source code, configuration files, and preprocessing scripts are available at https://github.com/WenhuiDing/SPAD-CFR (accessed on 5 July 2026). The processed training and test datasets and the trained model checkpoints are permanently archived on Zenodo (DOI: https://doi.org/10.5281/zenodo.20254865).

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

Recorded: type, language, journal, volume, issue, pages, dates, 3 authors, 5 keywords, 2 funders, 35 references, 1 integrity notice.

Cite

This paper

Ding, W., Luo, Z., & Xiong, Y. (2026). Counterfactual Diffusion Modeling Enables Spatially Targeted Reprogramming of Tissue Microenvironments. Biology, 15(14), 1097. https://doi.org/10.3390/biology15141097

BibTeX

@article{ding2026counterfactual,
author = {Ding, Wenhui and Luo, Zhenhua and Xiong, Yuanyan},
title = {{Counterfactual Diffusion Modeling Enables Spatially Targeted Reprogramming of Tissue Microenvironments}},
journal = {Biology},
year = {2026},
month = jul,
volume = {15},
number = {14},
pages = {1097},
publisher = {Multidisciplinary Digital Publishing Institute (MDPI)},
issn = {2079-7737},
doi = {10.3390/biology15141097},
url = {https://doi.org/10.3390/biology15141097},
pmid = {42510645},
pmcid = {PMC13406000}
}

RIS

TY - JOUR
AU - Ding, Wenhui
AU - Luo, Zhenhua
AU - Xiong, Yuanyan
TI - Counterfactual Diffusion Modeling Enables Spatially Targeted Reprogramming of Tissue Microenvironments
T2 - Biology
J2 - Biology (Basel)
PY - 2026
DA - 2026/07/08
VL - 15
IS - 14
SP - 1097
SN - 2079-7737
PB - Multidisciplinary Digital Publishing Institute (MDPI)
DO - 10.3390/biology15141097
UR - https://doi.org/10.3390/biology15141097
LA - en
ER -

CSL-JSON

{
"id": "10.3390/biology15141097",
"type": "article-journal",
"title": "Counterfactual Diffusion Modeling Enables Spatially Targeted Reprogramming of Tissue Microenvironments",
"container-title": "Biology",
"author": [
{
"family": "Ding",
"given": "Wenhui"
},
{
"family": "Luo",
"given": "Zhenhua"
},
{
"family": "Xiong",
"given": "Yuanyan"
}
],
"container-title-short": "Biology (Basel)",
"volume": "15",
"issue": "14",
"page": "1097",
"DOI": "10.3390/biology15141097",
"PMID": "42510645",
"PMCID": "PMC13406000",
"ISSN": "2079-7737",
"publisher": "Multidisciplinary Digital Publishing Institute (MDPI)",
"URL": "https://doi.org/10.3390/biology15141097",
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
8
]
]
}
}

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/s41467-026-71759-4 [code]
CellNiche represents cellular microenvironments in atlas-scale spatial omics data with contrastive learning.
Journal: Nature communications
In common: PyTorch Geometric, Scanpy, PyTorch, 5 other tools, other condition, 2 references
[2] doi:10.1371/journal.pcbi.1014327 [code]
Supervised deep learning with gene functional annotation for cell classification.
Journal: PLoS computational biology
In common: PyTorch Geometric, Scanpy, PyTorch, 5 other tools, genetics / omics, other condition, 1 reference
[3] doi:10.1523/eneuro.0362-25.2026 [code]
Similarities between <i>Ciona</i> Dorsal Motor Ganglion and Vertebrate Cerebellum: Did a Chordate Ancestor Already Show D/V Subdivision within a Hindbrain Precursor?
Journal: eNeuro
In common: PyTorch Lightning, PyTorch Geometric, Scanpy, 6 other tools
[4] doi:10.1038/s42003-026-10259-z [code]
Spatial transcriptomic profiling of developing mouse hearts reveals a spatially patterned signaling environment.
Journal: Communications biology
In common: PyTorch Lightning, Scanpy, PyTorch, 5 other tools, genetics / omics, 1 reference
[5] doi:10.1093/bib/bbag298 [code]
Empowering multifaceted analysis of spatial transcriptomics data with RGAST.
Journal: Briefings in bioinformatics
In common: PyTorch Geometric, Scanpy, PyTorch, 5 other tools, genetics / omics, 1 reference
[6] doi:10.1038/s41586-026-10214-2 [code]
Multidimensional profiling of heterogeneity in supratentorial ependymomas.
Journal: Nature
In common: PyTorch Lightning, Scanpy, seaborn, 4 other tools, genetics / omics, other condition, 1 reference
[7] doi:10.1016/j.isci.2026.117206 [code]
ReliST: A model-agnostic risk layer for spatial transcriptomics deconvolution.
Journal: iScience
In common: Scanpy, PyTorch, seaborn, 4 other tools, genetics / omics, 2 references
[8] doi:10.1093/nar/gkag706 [code]
scDifformer: diffusion-based post-training for virtual cell modeling across large-scale single-cell data.
Journal: Nucleic acids research
In common: PyTorch Geometric, Scanpy, PyTorch, 5 other tools, 1 reference
[9] doi:10.1093/bioinformatics/btag652 [code]
mmVelo: a deep generative model for estimating cell state-dependent dynamics across multiple modalities.
Journal: Bioinformatics (Oxford, England)
In common: PyTorch Lightning, Scanpy, PyTorch, 5 other tools, genetics / omics
[10] doi:10.1093/bib/bbag259 [code]
PVAED: prior-guided variational autoencoders with diffusion denoising for interpretable single-cell representation learning.
Journal: Briefings in bioinformatics
In common: Scanpy, PyTorch, pandas, 3 other tools, genetics / omics, 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.

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.