OSCR

iAODE for benchmarking and continuum modeling of single-cell chromatin accessibility.

Code ↔ Paper

31 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 31 matches · 7 of them tie a paragraph to a whole file, not to given lines: weak matches, whose lines are not tinted
  1. [1] § Methods › iAODE training strategy and dataset splitting ↔ api/static/_next/static/chunks/e59f297117d25863.js, the whole file · a weak match · score 0.89 · negative binomial, log transformed, random seed, TF IDF, reconstruction loss, NB
  2. [2] § Methods › iAODE training strategy and dataset splitting ↔ frontend/out/_next/static/chunks/3eec792fef995ed6.js, the whole file · a weak match · score 0.88 · negative binomial, log transformed, random seed, TF IDF, reconstruction loss, NB
  3. [3] § Results › iAODE framework and standardized multi-modal benchmark resources ↔ frontend/out/_next/static/chunks/1940ffdbe51fa4eb.js, the whole file · a weak match · score 0.82 · multi modal, single cell RNA, PyTorch, scRNA, Scanpy, Explorer
  4. [4] § Results › iAODE framework and standardized multi-modal benchmark resources ↔ api/static/_next/static/chunks/e59f297117d25863.js, the whole file · a weak match · score 0.82 · highly variable peak, TF IDF, model training, scRNA, algorithms, static
  5. [5] § Results › iAODE framework and standardized multi-modal benchmark resources ↔ frontend/out/_next/static/chunks/3eec792fef995ed6.js, the whole file · a weak match · score 0.82 · highly variable peak, TF IDF, model training, scRNA, algorithms, static
  6. [6] § Methods › Comprehensive evaluation of continuity, embedding quality, clustering, and coupling ↔ iaode/DRE.py, lines 56–82 · score 0.82 · pairwise distance matrices, Spearman correlation, global structural preservation, Distance correlation, low dimensions, spaces
  7. [7] § Methods › iAODE latent ODE-VAE architecture and irecon bottleneck design ↔ iaode/module.py, lines 226–324 · score 0.78 · softmax normalized, decoder network, accessibility measurements, nature, discrete, sparse
  8. [8] § Results › Robustness and deployability of iAODE across hyperparameters, encoder architectures, and computational cost ↔ iaode/agent.py, lines 16–108 · score 0.71 · KL divergence weight, MLP encoders, Encoder architecture, loss weight, Computational, scATAC
  9. [9] § Results › Multi-scale trajectory reconstruction and biological interpretability of latent dynamics ↔ iaode/datasets.py, lines 213–281 · score 0.67 · peripheral blood mononuclear, human PBMC, cell, iAODE, space
  10. [10] § Results › Robustness and deployability of iAODE across hyperparameters, encoder architectures, and computational cost ↔ iaode/model.py, lines 14–64 · score 0.66 · KL divergence weight, reconstruction weight, encoder architectures, computational, iAODE, Dimensionality
  11. [11] § Results › Cross-modal transferability of iAODE components in the scRNA-seq modality and clustering-coupling performance ↔ iaode/BEN.py, lines 87–156 · score 0.66 · Davies Bouldin, Calinski Harabasz, t-SNE, single cell, silhouette, intrinsic
  12. [12] § Methods › Comprehensive evaluation of continuity, embedding quality, clustering, and coupling ↔ iaode/DRE.py, lines 230–285 · score 0.65 · co ranking matrix, low dimension, high dimension, neighbor, global, quality
  13. [13] § Results › Continuum and clustering benchmarks against linear dimensionality reduction and manifold-learning methods ↔ iaode/BEN.py, lines 87–156 · score 0.65 · Davies Bouldin, Calinski Harabasz, t-SNE, silhouette, UMAP, ASW
  14. [14] § Results › Robustness and deployability of iAODE across hyperparameters, encoder architectures, and computational cost ↔ iaode/model.py, lines 14–64 · score 0.64 · KL divergence weight, Encoder architecture, loss weight, Computational, MLP, scATAC
  15. [15] § Methods › Baseline models and unified implementation of regularization terms ↔ iaode/agent.py, lines 16–108 · score 0.64 · MMD weight, InfoVAE, DIP, reproduce, KL, reconstruction
  16. [16] § Methods › iAODE latent ODE-VAE architecture and irecon bottleneck design ↔ iaode/agent.py, lines 391–509 · score 0.62 · Transition probabilities, transition matrices, velocity fields, iAODE, latent
  17. [17] § Results › Topological simulations and continuum metrics on real scATAC data, behavior and hyperparameter priors ↔ iaode/LSE.py, lines 349–416 · score 0.61 · Noise Resilience, core metrics, Spectral Decay, Participation Ratio, Manifold Dimensionality, Trajectory Directionality
  18. [18] § Methods › iAODE latent ODE-VAE architecture and irecon bottleneck design ↔ iaode/module.py, lines 380–417 · score 0.60 · compressed representation, reconstruction loss, latent space, ZINB, module, bottleneck
  19. [19] § Results › Multi-scale trajectory reconstruction and biological interpretability of latent dynamics ↔ iaode/datasets.py, lines 213–281 · score 0.59 · peripheral blood mononuclear, human PBMC, cells, iAODE, space
  20. [20] § Methods › Comprehensive evaluation of continuity, embedding quality, clustering, and coupling ↔ iaode/DRE.py, lines 230–285 · score 0.59 · co ranking, distance correlation, high dimensional, quality, metrics
  21. [21] § Methods › iAODE latent ODE-VAE architecture and irecon bottleneck design ↔ examples/trajectory_inference_atac.py, lines 1–34 · score 0.58 · chromatin accessibility, velocity field, Neural ODE, scATAC, seq, iAODE
  22. [22] § Methods › Comprehensive evaluation of continuity, embedding quality, clustering, and coupling ↔ iaode/mixin.py, lines 311–359 · score 0.56 · normalized mutual, ARI, NMI, latent space, DAV, ASW
  23. [23] § Methods › iAODE latent ODE-VAE architecture and irecon bottleneck design ↔ iaode/module.py, lines 226–324 · score 0.56 · dispersion parameters, reconstruction loss, dropouts, scATAC, ZINB, peak
  24. [24] § Results › Component synergy and ablations in multi-scale scATAC data ↔ iaode/LSE.py, lines 418–485 · score 0.55 · Noise Resilience, Spectral Decay, Participation Ratio, Manifold Dimensionality, Trajectory Directionality, Anisotropy
  25. [25] § Methods › iAODE software and visualization ecosystem for training, data browsing, and continuum exploration ↔ api/static/_next/static/chunks/702abde7a71e95b7.js, the whole file · a weak match · score 0.55 · PyTorch, management, web, hosted, Pages, static
  26. [26] § Results › Continuum and clustering benchmarks against linear dimensionality reduction and manifold-learning methods ↔ iaode/mixin.py, lines 311–359 · score 0.55 · Davies Bouldin, Calinski Harabasz, silhouette, ASW, correlation, scores
  27. [27] § Results › Cross-modal transferability of iAODE components in the scRNA-seq modality and clustering-coupling performance ↔ iaode/LSE.py, lines 349–416 · score 0.54 · Noise Resilience, Spectral Decay, Participation Ratio, Manifold Dimensionality, Trajectory Directionality, Anisotropy
  28. [28] § Methods › Comprehensive evaluation of continuity, embedding quality, clustering, and coupling ↔ iaode/LSE.py, lines 418–485 · score 0.54 · developmental axis, noise resilience, Trajectory directionality, dominance, ratio, quality
  29. [29] § Methods › iAODE latent ODE-VAE architecture and irecon bottleneck design ↔ iaode/module.py, lines 327–377 · score 0.54 · chromatin accessibility, Neural ODE, latent space, scATAC, temporal, dynamics
  30. [30] § Methods › iAODE software and visualization ecosystem for training, data browsing, and continuum exploration ↔ frontend/out/_next/static/chunks/1940ffdbe51fa4eb.js, the whole file · a weak match · score 0.52 · PyTorch, web, hosted, Pages, static, iAODE
  31. [31] § Results › Robustness and deployability of iAODE across hyperparameters, encoder architectures, and computational cost ↔ iaode/BEN.py, lines 159–197 · score 0.51 · GPU memories, scVI, PoissonVI, PeakVI, architecture, epoch

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 · 586 lines · 19 KB · MIT · 4 matches

  1. # module.py
  2. import torch
  3. import torch.nn as nn
  4. import torch.nn.functional as F
  5. from torch.distributions import Normal
  6. from typing import Tuple, Union, Literal, Optional
  7. from .mixin import NODEMixin
  8. class Encoder(nn.Module):
  9. """
  10. Variational encoder mapping input states to latent distributions.
  11. Supports multiple encoder architectures:
  12. - 'mlp': Two-layer fully connected network (default)
  13. - 'mlp_residual': Multi-layer residual MLP
  14. - 'linear': Single-layer linear encoding
  15. - 'transformer': TransformerEncoder as feature extraction backbone
  16. Parameters
  17. ----------
  18. state_dim : int
  19. Dimension of input state (number of peaks for scATAC-seq)
  20. hidden_dim : int
  21. Dimension of hidden layers
  22. action_dim : int
  23. Dimension of latent space
  24. use_ode : bool, default=False
  25. Whether to use ODE for trajectory inference
  26. encoder_type : {'mlp', 'mlp_residual', 'linear', 'transformer'}, default='mlp'
  27. Type of encoder architecture
  28. encoder_num_layers : int, default=2
  29. Number of encoder layers
  30. encoder_n_heads : int, default=4
  31. Number of attention heads (for transformer only)
  32. encoder_d_model : int, optional
  33. Model dimension for transformer (defaults to hidden_dim if None)
  34. Input Shape
  35. -----------
  36. x : torch.Tensor
  37. (batch_size, state_dim) or (state_dim,)
  38. Single cells automatically expand to batch_size=1
  39. Output Shape
  40. ------------
  41. q_z : torch.Tensor
  42. Sampled latent vector (batch_size, action_dim)
  43. q_m : torch.Tensor
  44. Mean of latent distribution (batch_size, action_dim)
  45. q_s : torch.Tensor
  46. Log-variance of latent distribution (batch_size, action_dim)
  47. t : torch.Tensor, optional
  48. Inferred pseudotime (batch_size,), only when use_ode=True
  49. """
  50. def __init__(
  51. self,
  52. state_dim: int,
  53. hidden_dim: int,
  54. action_dim: int,
  55. use_ode: bool = False,
  56. encoder_type: Literal["mlp", "mlp_residual", "linear", "transformer"] = "mlp",
  57. encoder_num_layers: int = 2,
  58. encoder_n_heads: int = 4,
  59. encoder_d_model: Optional[int] = None,
  60. ):
  61. super().__init__()
  62. self.use_ode = use_ode
  63. self.encoder_type = encoder_type
  64. # Build encoder backbone
  65. if encoder_type == "mlp":
  66. layers: list[nn.Module] = []
  67. in_dim = state_dim
  68. for _ in range(encoder_num_layers):
  69. layers.append(nn.Linear(in_dim, hidden_dim))
  70. layers.append(nn.ReLU())
  71. in_dim = hidden_dim
  72. self.base_network = nn.Sequential(*layers)
  73. self.out_dim = hidden_dim
  74. elif encoder_type == "mlp_residual":
  75. self.input_proj = nn.Linear(state_dim, hidden_dim)
  76. blocks = []
  77. for _ in range(encoder_num_layers):
  78. blocks.append(
  79. nn.Sequential(
  80. nn.Linear(hidden_dim, hidden_dim),
  81. nn.ReLU(),
  82. )
  83. )
  84. self.res_blocks = nn.ModuleList(blocks)
  85. self.out_dim = hidden_dim
  86. elif encoder_type == "linear":
  87. self.base_network = nn.Sequential(
  88. nn.Linear(state_dim, hidden_dim),
  89. nn.ReLU(),
  90. )
  91. self.out_dim = hidden_dim
  92. elif encoder_type == "transformer":
  93. if encoder_d_model is None:
  94. encoder_d_model = hidden_dim
  95. self.d_model = encoder_d_model
  96. self.input_proj = nn.Linear(state_dim, encoder_d_model)
  97. encoder_layer = nn.TransformerEncoderLayer(
  98. d_model=encoder_d_model,
  99. nhead=encoder_n_heads,
  100. dim_feedforward=hidden_dim * 4,
  101. batch_first=True,
  102. )
  103. self.transformer = nn.TransformerEncoder(
  104. encoder_layer, num_layers=encoder_num_layers
  105. )
  106. self.pool = nn.AdaptiveAvgPool1d(1)
  107. self.out_dim = encoder_d_model
  108. else:
  109. raise ValueError(f"Unknown encoder_type: {encoder_type}")
  110. # Latent distribution parameters
  111. self.latent_params = nn.Linear(self.out_dim, action_dim * 2)
  112. # Pseudotime inference head (ODE mode)
  113. if use_ode:
  114. self.time_encoder = nn.Sequential(
  115. nn.Linear(self.out_dim, 1),
  116. nn.Sigmoid(),
  117. )
  118. self.apply(self._init_weights)
  119. @staticmethod
  120. def _init_weights(m: nn.Module) -> None:
  121. """Initialize network weights using Xavier initialization"""
  122. if isinstance(m, nn.Linear):
  123. nn.init.xavier_normal_(m.weight)
  124. nn.init.constant_(m.bias, 0.01)
  125. def _encode_features(self, x: torch.Tensor) -> torch.Tensor:
  126. """
  127. Encode input to hidden representation.
  128. Parameters
  129. ----------
  130. x : torch.Tensor
  131. Input tensor (batch_size, state_dim)
  132. Returns
  133. -------
  134. hidden : torch.Tensor
  135. Encoded features (batch_size, out_dim)
  136. """
  137. # Ensure batch dimension exists
  138. if x.dim() == 1:
  139. x = x.unsqueeze(0)
  140. if self.encoder_type in ["mlp", "linear"]:
  141. hidden = self.base_network(x)
  142. elif self.encoder_type == "mlp_residual":
  143. h = self.input_proj(x)
  144. for block in self.res_blocks:
  145. h = h + block(h) # Residual connection
  146. hidden = h
  147. elif self.encoder_type == "transformer":
  148. # Add sequence dimension: (batch, state_dim) -> (batch, 1, state_dim)
  149. if x.dim() == 2:
  150. x = x.unsqueeze(1)
  151. x_emb = self.input_proj(x) # (batch, seq_len, d_model)
  152. h = self.transformer(x_emb) # (batch, seq_len, d_model)
  153. # Pool over sequence dimension
  154. h = h.transpose(1, 2) # (batch, d_model, seq_len)
  155. hidden = self.pool(h).squeeze(-1) # (batch, d_model)
  156. else:
  157. raise RuntimeError("Unsupported encoder_type")
  158. return hidden
  159. def forward(
  160. self, x: torch.Tensor
  161. ) -> Union[
  162. Tuple[torch.Tensor, torch.Tensor, torch.Tensor],
  163. Tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor],
  164. ]:
  165. """
  166. Forward pass through encoder.
  167. Returns
  168. -------
  169. q_z : torch.Tensor
  170. Sampled latent vector
  171. q_m : torch.Tensor
  172. Latent mean
  173. q_s : torch.Tensor
  174. Latent log-variance
  175. t : torch.Tensor, optional
  176. Inferred pseudotime (only when use_ode=True)
  177. """
  178. # Extract features
  179. hidden = self._encode_features(x)
  180. # Compute latent distribution parameters
  181. latent_output = self.latent_params(hidden)
  182. q_m, q_s = torch.split(latent_output, latent_output.size(-1) // 2, dim=-1)
  183. # Reparameterization trick
  184. std = F.softplus(q_s) + 1e-6
  185. dist = Normal(q_m, std)
  186. q_z = dist.rsample()
  187. # Infer pseudotime (ODE mode)
  188. if self.use_ode:
  189. t = self.time_encoder(hidden).squeeze(-1)
  190. return q_z, q_m, q_s, t
  191. return q_z, q_m, q_s
  192. class Decoder(nn.Module):
  193. """
  194. Decoder network mapping latent vectors back to input space.
  195. Supports three loss modes tailored for scATAC-seq data:
  196. - 'mse': Mean squared error for continuous data
  197. - 'nb': Negative binomial for count data (recommended)
  198. - 'zinb': Zero-inflated negative binomial for sparse count data
  199. Parameters
  200. ----------
  201. state_dim : int
  202. Dimension of input space (number of peaks)
  203. hidden_dim : int
  204. Dimension of hidden layers
  205. action_dim : int
  206. Dimension of latent space
  207. loss_mode : {'mse', 'nb', 'zinb'}, default='nb'
  208. Type of reconstruction loss
  209. Notes
  210. -----
  211. For scATAC-seq data, 'nb' or 'zinb' is recommended due to the discrete,
  212. count-based nature of chromatin accessibility measurements.
  213. """
  214. def __init__(
  215. self,
  216. state_dim: int,
  217. hidden_dim: int,
  218. action_dim: int,
  219. loss_mode: Literal["mse", "nb", "zinb"] = "nb",
  220. ):
  221. super().__init__()
  222. self.loss_mode = loss_mode
  223. # Shared base network
  224. self.base_network = nn.Sequential(
  225. nn.Linear(action_dim, hidden_dim),
  226. nn.ReLU(),
  227. nn.Linear(hidden_dim, hidden_dim),
  228. nn.ReLU(),
  229. )
  230. # Configure output heads based on loss mode
  231. if loss_mode in ["nb", "zinb"]:
  232. # Negative binomial: dispersion parameter
  233. self.disp = nn.Parameter(torch.randn(state_dim))
  234. # Mean parameter with Softmax normalization
  235. mean_decoder_seq: nn.Module = nn.Sequential(
  236. nn.Linear(hidden_dim, state_dim),
  237. nn.Softmax(dim=-1)
  238. )
  239. self.mean_decoder = mean_decoder_seq
  240. else: # 'mse' mode
  241. self.mean_decoder = nn.Linear(hidden_dim, state_dim)
  242. # Zero-inflation parameter (ZINB only)
  243. if loss_mode == "zinb":
  244. self.dropout_decoder = nn.Linear(hidden_dim, state_dim)
  245. self.apply(self._init_weights)
  246. @staticmethod
  247. def _init_weights(m: nn.Module) -> None:
  248. """Initialize network weights"""
  249. if isinstance(m, nn.Linear):
  250. nn.init.xavier_normal_(m.weight)
  251. nn.init.constant_(m.bias, 0.01)
  252. def forward(self, x: torch.Tensor):
  253. """
  254. Forward pass through decoder.
  255. Parameters
  256. ----------
  257. x : torch.Tensor
  258. Latent vector (batch_size, action_dim)
  259. Returns
  260. -------
  261. For 'mse' and 'nb' modes:
  262. mean : torch.Tensor
  263. Reconstructed output (batch_size, state_dim)
  264. For 'zinb' mode:
  265. mean : torch.Tensor
  266. Reconstructed mean (batch_size, state_dim)
  267. dropout_logits : torch.Tensor
  268. Zero-inflation logits (batch_size, state_dim)
  269. """
  270. hidden = self.base_network(x)
  271. mean = self.mean_decoder(hidden)
  272. if self.loss_mode == "zinb":
  273. dropout_logits = self.dropout_decoder(hidden)
  274. return mean, dropout_logits
  275. return mean
  276. class LatentODEfunc(nn.Module):
  277. """
  278. Neural ODE function for latent dynamics modeling.
  279. Models continuous temporal dynamics in latent space for trajectory inference
  280. in single-cell data. The ODE function dx/dt = f(x, t) is parameterized by
  281. a two-layer neural network.
  282. Parameters
  283. ----------
  284. n_latent : int, default=10
  285. Dimension of latent space
  286. n_hidden : int, default=25
  287. Dimension of hidden layer
  288. Notes
  289. -----
  290. Used for pseudotime inference in scATAC-seq data, enabling continuous
  291. trajectory modeling of chromatin accessibility dynamics.
  292. """
  293. def __init__(
  294. self,
  295. n_latent: int = 10,
  296. n_hidden: int = 25,
  297. ):
  298. super().__init__()
  299. self.elu = nn.ELU()
  300. self.fc1 = nn.Linear(n_latent, n_hidden)
  301. self.fc2 = nn.Linear(n_hidden, n_latent)
  302. def forward(self, t: torch.Tensor, x: torch.Tensor) -> torch.Tensor:
  303. """
  304. Compute latent dynamics gradient.
  305. Parameters
  306. ----------
  307. t : torch.Tensor
  308. Time point
  309. x : torch.Tensor
  310. Latent state
  311. Returns
  312. -------
  313. dx_dt : torch.Tensor
  314. Temporal gradient in latent space
  315. """
  316. out = self.fc1(x)
  317. out = self.elu(out)
  318. out = self.fc2(out)
  319. return out
  320. class iVAE(nn.Module, NODEMixin):
  321. """
  322. Interpretable Variational Autoencoder (iVAE) with interpretable bottleneck.
  323. Core architecture for iAODE (interpretable Accessibility ODE VAE), designed
  324. for scATAC-seq data analysis. Combines VAE with information bottleneck for
  325. interpretable latent representations.
  326. Parameters
  327. ----------
  328. state_dim : int
  329. Dimension of input state (number of peaks)
  330. hidden_dim : int
  331. Dimension of hidden layers
  332. action_dim : int
  333. Dimension of latent space (full)
  334. i_dim : int
  335. Dimension of interpretable bottleneck
  336. use_ode : bool
  337. Whether to use Neural ODE for trajectory inference
  338. loss_mode : {'mse', 'nb', 'zinb'}, default='nb'
  339. Reconstruction loss type
  340. encoder_type : {'mlp', 'mlp_residual', 'linear', 'transformer'}, default='mlp'
  341. Encoder architecture
  342. encoder_num_layers : int, default=2
  343. Number of encoder layers
  344. encoder_n_heads : int, default=4
  345. Number of attention heads (transformer only)
  346. encoder_d_model : int, optional
  347. Transformer model dimension
  348. device : torch.device
  349. Device for computation
  350. Notes
  351. -----
  352. The interpretable bottleneck (i_dim) provides a compressed representation
  353. that balances reconstruction quality with biological interpretability.
  354. """
  355. def __init__(
  356. self,
  357. state_dim: int,
  358. hidden_dim: int,
  359. action_dim: int,
  360. i_dim: int,
  361. use_ode: bool,
  362. loss_mode: Literal["mse", "nb", "zinb"] = "nb",
  363. encoder_type: Literal["mlp", "mlp_residual", "linear", "transformer"] = "mlp",
  364. encoder_num_layers: int = 2,
  365. encoder_n_heads: int = 4,
  366. encoder_d_model: Optional[int] = None,
  367. device=torch.device("cuda")
  368. if torch.cuda.is_available()
  369. else torch.device("cpu"),
  370. ):
  371. super().__init__()
  372. # Initialize encoder
  373. self.encoder = Encoder(
  374. state_dim=state_dim,
  375. hidden_dim=hidden_dim,
  376. action_dim=action_dim,
  377. use_ode=use_ode,
  378. encoder_type=encoder_type,
  379. encoder_num_layers=encoder_num_layers,
  380. encoder_n_heads=encoder_n_heads,
  381. encoder_d_model=encoder_d_model,
  382. ).to(device)
  383. # Initialize decoder
  384. self.decoder = Decoder(state_dim, hidden_dim, action_dim, loss_mode).to(device)
  385. # Initialize ODE solver
  386. if use_ode:
  387. self.ode_solver = LatentODEfunc(action_dim)
  388. # Interpretable bottleneck layers
  389. self.latent_encoder = nn.Linear(action_dim, i_dim).to(device)
  390. self.latent_decoder = nn.Linear(i_dim, action_dim).to(device)
  391. def forward(self, x_log: torch.Tensor, x_raw: torch.Tensor = None) -> Tuple[torch.Tensor, ...]:
  392. """
  393. Forward pass through VAE.
  394. Parameters
  395. ----------
  396. x_log : torch.Tensor
  397. Log-transformed input tensor (batch_size, state_dim) for encoder stability
  398. x_raw : torch.Tensor, optional
  399. Raw count tensor (batch_size, state_dim) for NB/ZINB loss calculation.
  400. If None, uses x_log (for MSE mode or backward compatibility)
  401. Returns
  402. -------
  403. Tuple containing:
  404. q_z : torch.Tensor
  405. Sampled latent vector
  406. q_m : torch.Tensor
  407. Latent mean
  408. q_s : torch.Tensor
  409. Latent log-variance
  410. x_raw : torch.Tensor
  411. Raw counts for loss calculation
  412. pred_x : torch.Tensor
  413. Reconstructed input (direct path)
  414. le : torch.Tensor
  415. Encoded bottleneck representation
  416. pred_xl : torch.Tensor
  417. Reconstructed input (bottleneck path)
  418. Additional returns for ODE mode:
  419. q_z_ode : torch.Tensor
  420. ODE-evolved latent
  421. pred_x_ode : torch.Tensor
  422. ODE reconstruction
  423. Additional returns for ZINB mode:
  424. dropout_logits : torch.Tensor
  425. Zero-inflation parameters
  426. """
  427. # Use x_log for backward compatibility if x_raw not provided
  428. if x_raw is None:
  429. x_raw = x_log
  430. # Encode using log-transformed data for stability
  431. if self.encoder.use_ode:
  432. q_z, q_m, q_s, t = self.encoder(x_log)
  433. # Sort by pseudotime
  434. idxs = torch.argsort(t)
  435. t = t[idxs]
  436. q_z = q_z[idxs]
  437. q_m = q_m[idxs]
  438. q_s = q_s[idxs]
  439. x_raw = x_raw[idxs] # Sort raw counts to match
  440. # Remove duplicate time points
  441. unique_mask = torch.ones_like(t, dtype=torch.bool)
  442. unique_mask[1:] = t[1:] != t[:-1]
  443. t = t[unique_mask]
  444. q_z = q_z[unique_mask]
  445. q_m = q_m[unique_mask]
  446. q_s = q_s[unique_mask]
  447. x_raw = x_raw[unique_mask] # Apply mask to raw counts
  448. # Solve ODE from initial state
  449. z0 = q_z[0]
  450. q_z_ode = self.solve_ode(self.ode_solver, z0, t)
  451. # Information bottleneck paths
  452. le = self.latent_encoder(q_z)
  453. ld = self.latent_decoder(le)
  454. le_ode = self.latent_encoder(q_z_ode)
  455. ld_ode = self.latent_decoder(le_ode)
  456. # Decode
  457. if self.decoder.loss_mode == "zinb":
  458. pred_x, dropout_logits = self.decoder(q_z)
  459. pred_xl, dropout_logitsl = self.decoder(ld)
  460. pred_x_ode, dropout_logits_ode = self.decoder(q_z_ode)
  461. pred_xl_ode, dropout_logitsl_ode = self.decoder(ld_ode)
  462. return (
  463. q_z, q_m, q_s, x_raw, # Return raw counts for loss
  464. pred_x, dropout_logits,
  465. le, le_ode,
  466. pred_xl, dropout_logitsl,
  467. q_z_ode,
  468. pred_x_ode, dropout_logits_ode,
  469. pred_xl_ode, dropout_logitsl_ode,
  470. )
  471. else:
  472. pred_x = self.decoder(q_z)
  473. pred_xl = self.decoder(ld)
  474. pred_x_ode = self.decoder(q_z_ode)
  475. pred_xl_ode = self.decoder(ld_ode)
  476. return (
  477. q_z, q_m, q_s, x_raw, # Return raw counts for loss
  478. pred_x,
  479. le, le_ode,
  480. pred_xl,
  481. q_z_ode,
  482. pred_x_ode,
  483. pred_xl_ode,
  484. )
  485. else:
  486. q_z, q_m, q_s = self.encoder(x_log) # Encode log-transformed
  487. # Information bottleneck
  488. le = self.latent_encoder(q_z)
  489. ld = self.latent_decoder(le)
  490. # Decode
  491. if self.decoder.loss_mode == "zinb":
  492. pred_x, dropout_logits = self.decoder(q_z)
  493. pred_xl, dropout_logitsl = self.decoder(ld)
  494. return (
  495. q_z, q_m, q_s, x_raw, # Return raw counts for loss
  496. pred_x, dropout_logits,
  497. le,
  498. pred_xl, dropout_logitsl,
  499. )
  500. else:
  501. pred_x = self.decoder(q_z)
  502. pred_xl = self.decoder(ld)
  503. return (q_z, q_m, q_s, x_raw, pred_x, le, pred_xl) # Return raw counts for loss

module.py at commit c4fe36c, under MIT · at the source

Overview

Authors: Zeyu Fu1, Chunlin Chen2, Song Wang1, Junping Wang1, Shilei Chen1
  1. State Key Laboratory of Trauma and Chemical Poisoning, Institute of Combined Injury, Chongqing Engineering Research Center for Nanomedicine, College of Preventive Medicine, Army Medical University,Chongqing, China
  2. Department of Rehabilitation Medicine, The First Affiliated Hospital, Sun Yat-sen University,Guangzhou, China
Journal: Communications biology, volume 9, issue 1, article 507
Dates: received 11 July 2025; accepted 18 February 2026; published online 3 March 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s42003-026-09768-8 · PMID 41775921 · PMCID PMC13066597 · OpenAlex W7133352078
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), human (organism), methods / tools (subfield)
Methods: Statistics, Smoothing, state filtering, decompositions, Connectivity, Machine learning, Single-unit activity, calcium imaging
Keywords: Genetics, Computational biology and bioinformatics
MeSH: Chromatin*, Single-Cell Analysis*, Animals, Autoencoder, Benchmarking, Humans (* major topic)
Topic: Single-cell and spatial transcriptomics (Molecular Biology, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Funding: National Natural Science Foundation of China (National Science Foundation of China) (82222060, 82430103, 82473572, 81930090, 81725019, 82073487, 81602790)
Citations: not cited yet (Europe PMC); 51 references in the paper

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

PeterPonyu/iAODE

License: MIT
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: c4fe36c079cc07895c653248076ae10ef1ec67eb, 2 September 2026
Languages: JavaScript (44), Python (29), Jupyter (6), TypeScript (4), Shell (1)
Size: 181 files, 84 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, license file, environment (pyproject.toml, requirements.txt, setup.py), tests, continuous integration, 6 notebooks
Not found: CITATION.cff, documentation
Tools: NumPy (22 files), Scanpy (14 files), Matplotlib (13 files), SciPy (13 files), pandas (9 files), scikit-learn (7 files), PyTorch (6 files), anndata (4 files)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
86 files

Zenodo 18453104

License: MIT
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the text, “iAODE software and visualization ecosystem for t”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: NumPy (22 files), Scanpy (14 files), Matplotlib (13 files), SciPy (13 files), pandas (9 files), scikit-learn (7 files), PyTorch (6 files), anndata (4 files)
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
  • 30 September 2026: the link answers (HTTP 200)
56 files
At the source:

figshare 31225099

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

Code availability statement

The paper has a code availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

Read it in the paper: doi.org/10.1038/s42003-026-09768-8.

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:

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

The paper has a data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

  • no repository, dataset or request procedure was recognized in it

Read it in the paper: doi.org/10.1038/s42003-026-09768-8.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 30 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 5 authors, 2 keywords, 6 MeSH terms, 1 funder, 43 references.

Cite

This paper

Fu, Z., Chen, C., Wang, S., Wang, J., & Chen, S. (2026). iAODE for benchmarking and continuum modeling of single-cell chromatin accessibility. Communications biology, 9(1), 507. https://doi.org/10.1038/s42003-026-09768-8

BibTeX

@article{fu2026iaode,
author = {Fu, Zeyu and Chen, Chunlin and Wang, Song and Wang, Junping and Chen, Shilei},
title = {{iAODE for benchmarking and continuum modeling of single-cell chromatin accessibility}},
journal = {Communications biology},
year = {2026},
month = mar,
volume = {9},
number = {1},
pages = {507},
publisher = {Nature Publishing Group},
issn = {2399-3642},
doi = {10.1038/s42003-026-09768-8},
url = {https://doi.org/10.1038/s42003-026-09768-8},
pmid = {41775921},
pmcid = {PMC13066597}
}

RIS

TY - JOUR
AU - Fu, Zeyu
AU - Chen, Chunlin
AU - Wang, Song
AU - Wang, Junping
AU - Chen, Shilei
TI - iAODE for benchmarking and continuum modeling of single-cell chromatin accessibility
T2 - Communications biology
J2 - Commun Biol
PY - 2026
DA - 2026/03/03
VL - 9
IS - 1
SP - 507
SN - 2399-3642
PB - Nature Publishing Group
DO - 10.1038/s42003-026-09768-8
UR - https://doi.org/10.1038/s42003-026-09768-8
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s42003-026-09768-8",
"type": "article-journal",
"title": "iAODE for benchmarking and continuum modeling of single-cell chromatin accessibility",
"container-title": "Communications biology",
"author": [
{
"family": "Fu",
"given": "Zeyu"
},
{
"family": "Chen",
"given": "Chunlin"
},
{
"family": "Wang",
"given": "Song"
},
{
"family": "Wang",
"given": "Junping"
},
{
"family": "Chen",
"given": "Shilei"
}
],
"container-title-short": "Commun Biol",
"volume": "9",
"issue": "1",
"page": "507",
"DOI": "10.1038/s42003-026-09768-8",
"PMID": "41775921",
"PMCID": "PMC13066597",
"ISSN": "2399-3642",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s42003-026-09768-8",
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
3
]
]
}
}

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/s42003-026-10462-y [code]
SpaDC enables sequence-based integrative analysis and regulatory inference of spatial chromatin accessibility data.
Journal: Communications biology
In common: anndata, Scanpy, PyTorch, 5 other tools, genetics / omics, 5 references
[2] doi:10.1038/s41467-026-73171-4 [code]
Dissecting epigenetic heterogeneity in single-cell DNA methylomes with a unified framework.
Journal: Nature communications
In common: anndata, Scanpy, PyTorch, 5 other tools, genetics / omics, 2 references
[3] doi:10.1016/j.xgen.2026.101217 [code]
ProtoCloud: A prototypical self-explaining model for single-cell analysis.
Journal: Cell genomics
In common: anndata, Scanpy, PyTorch, 5 other tools, genetics / omics, 2 references
[4] doi:10.1038/s41467-026-71803-3 [code]
Charting the transition from in vitro gliogenesis to the in vivo maturation of human glial progenitor cells transplanted into the hypomyelinated mouse brain.
Journal: Nature communications
In common: anndata, Scanpy, PyTorch, 5 other tools, genetics / omics, 2 references
[5] doi:10.1371/journal.pcbi.1014346 [code]
StPedf: Cell trajectory inference of spatial transcriptomics via spatial proximity embedding and spatial density-adaptive fusion.
Journal: PLoS computational biology
In common: anndata, Scanpy, PyTorch, 5 other tools, genetics / omics, 2 references
[6] doi:10.1038/s41467-026-74000-4 [code]
ArchVelo: archetypal velocity modeling for single-cell multi-omic trajectories.
Journal: Nature communications
In common: anndata, Scanpy, scikit-learn, 4 other tools, genetics / omics, 2 references
[7] doi:10.1126/sciadv.aeb4205 [code]
Learning stochastic dynamics and cell-fate landscapes from single-cell snapshots via optimal transport.
Journal: Science advances
In common: Scanpy, PyTorch, scikit-learn, 4 other tools, 3 references
[8] doi:10.1016/j.celrep.2026.117110 [code]
Single-nucleus multiome analysis in the human prefrontal cortex identifies gene expression and cis-regulatory elements associated with aging.
Journal: Cell reports
In common: anndata, Scanpy, PyTorch, 4 other tools, genetics / omics, 2 references
[9] 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: anndata, Scanpy, PyTorch, 5 other tools, 2 references
[10] doi:10.1093/nar/gkag368 [code]
Single-cell trajectory inference for detecting transient events in biological processes.
Journal: Nucleic acids research
In common: anndata, Scanpy, scikit-learn, 4 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.