diffbio 0.1.4__tar.gz → 0.1.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. {diffbio-0.1.4 → diffbio-0.1.6}/PKG-INFO +10 -8
  2. {diffbio-0.1.4 → diffbio-0.1.6}/README.md +4 -2
  3. {diffbio-0.1.4 → diffbio-0.1.6}/pyproject.toml +8 -7
  4. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/base_operators.py +24 -14
  5. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/data_types.py +3 -2
  6. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/neural_components.py +9 -8
  7. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/uncertainty.py +4 -4
  8. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/evaluation/adapters.py +7 -7
  9. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/losses/statistical_losses.py +1 -4
  10. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/_count_vae.py +13 -16
  11. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/_loss_balancing.py +18 -18
  12. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/_masked_gene_transformer.py +16 -20
  13. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/alignment/profile_hmm.py +3 -7
  14. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/alignment/smith_waterman.py +2 -3
  15. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/alignment/soft_msa.py +4 -6
  16. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/assembly/gnn_assembly.py +4 -6
  17. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/assembly/metagenomic_binning.py +5 -3
  18. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/crispr/guide_scoring.py +3 -2
  19. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/drug_discovery/_graph_utils.py +6 -13
  20. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/drug_discovery/admet_predictor.py +5 -4
  21. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/drug_discovery/attentive_fp.py +4 -10
  22. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/drug_discovery/dti.py +4 -5
  23. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/drug_discovery/fingerprint.py +17 -17
  24. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/drug_discovery/maccs_keys.py +6 -9
  25. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/drug_discovery/property_predictor.py +4 -3
  26. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/drug_discovery/similarity.py +7 -7
  27. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/epigenomics/chromatin_state.py +8 -8
  28. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/epigenomics/contextual.py +3 -8
  29. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/epigenomics/fno_peak_calling.py +4 -6
  30. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/epigenomics/peak_calling.py +13 -12
  31. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/foundation_models/embedding_probe.py +3 -6
  32. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/foundation_models/foundation_model.py +7 -10
  33. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/foundation_models/frozen.py +1 -1
  34. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/foundation_models/transformer_encoder.py +9 -19
  35. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/mapping/neural_mapper.py +3 -6
  36. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/metabolomics/isotope_envelope.py +3 -3
  37. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/metabolomics/soft_centroiding.py +3 -3
  38. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/metabolomics/spectral_similarity.py +3 -2
  39. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/molecular_dynamics/force_field.py +2 -2
  40. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/molecular_dynamics/integrator.py +14 -6
  41. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/multiomics/hic_contact.py +3 -6
  42. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/multiomics/multiomics_vae.py +6 -6
  43. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/multiomics/spatial_deconvolution.py +3 -6
  44. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/multiomics/spatial_gene_detection.py +1 -1
  45. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/arcsinh_cofactor.py +3 -3
  46. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/differentiable_pca.py +3 -3
  47. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/embedding.py +3 -6
  48. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/learnable_normalization.py +3 -3
  49. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/learnable_orthogonal_projection.py +4 -3
  50. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/learnable_projection.py +7 -4
  51. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/matrix_free_pca.py +3 -3
  52. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/phate.py +3 -3
  53. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/scaling.py +4 -3
  54. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/soft_pca.py +3 -3
  55. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/umap.py +4 -7
  56. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/vae_normalizer.py +47 -11
  57. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/population/ancestry_estimation.py +3 -2
  58. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/preprocessing/__init__.py +10 -5
  59. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/preprocessing/adapter_removal.py +2 -2
  60. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/preprocessing/duplicate_filter.py +9 -7
  61. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/preprocessing/error_correction.py +5 -6
  62. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/protein/secondary_structure.py +44 -41
  63. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/quality_filter.py +3 -2
  64. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/rna_structure/rna_folding.py +5 -8
  65. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/rnaseq/motif_discovery.py +8 -8
  66. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/rnaseq/splicing_psi.py +3 -3
  67. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/ambient_removal.py +5 -8
  68. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/archetypes.py +10 -7
  69. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/batch_correction.py +3 -4
  70. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/cell_annotation.py +13 -8
  71. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/communication.py +6 -8
  72. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/differential_distribution.py +5 -8
  73. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/doublet_detection.py +24 -62
  74. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/downsampling.py +6 -11
  75. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/enhanced_batch_correction.py +7 -11
  76. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/grn_inference.py +5 -6
  77. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/imputation.py +9 -12
  78. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/ot_trajectory.py +5 -6
  79. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/simulation.py +17 -39
  80. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/sindy_grn.py +2 -2
  81. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/soft_clustering.py +3 -4
  82. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/soft_hvg.py +3 -3
  83. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/spatial_domains.py +12 -13
  84. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/stochastic_gate_selector.py +6 -9
  85. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/switch_de.py +2 -2
  86. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/trajectory.py +5 -4
  87. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/velocity.py +3 -6
  88. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/statistical/em_quantification.py +3 -6
  89. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/statistical/hmm.py +3 -3
  90. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/statistical/nb_glm.py +3 -6
  91. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/variant/classifier.py +7 -8
  92. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/variant/cnn_classifier.py +4 -6
  93. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/variant/cnv_segmentation.py +6 -12
  94. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/variant/deepvariant_pileup.py +3 -3
  95. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/variant/pileup.py +2 -2
  96. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/variant/quality_recalibration.py +3 -6
  97. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/pipelines/adapters.py +4 -3
  98. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/pipelines/differential_expression.py +4 -7
  99. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/pipelines/enhanced_variant_calling.py +13 -7
  100. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/pipelines/joint_preprocessing.py +4 -3
  101. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/pipelines/joint_training.py +17 -28
  102. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/pipelines/minibatch_training.py +16 -32
  103. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/pipelines/preprocessing.py +2 -2
  104. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/pipelines/single_cell.py +19 -11
  105. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/pipelines/variant_calling.py +2 -2
  106. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/anndata_source.py +1 -1
  107. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/indexed_view.py +15 -5
  108. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/splitters/base.py +23 -0
  109. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/splitters/random.py +3 -21
  110. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/utils/__init__.py +9 -12
  111. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/utils/nn_utils.py +0 -47
  112. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/utils/training.py +13 -38
  113. {diffbio-0.1.4 → diffbio-0.1.6}/.gitignore +0 -0
  114. {diffbio-0.1.4 → diffbio-0.1.6}/LICENSE +0 -0
  115. {diffbio-0.1.4 → diffbio-0.1.6}/benchmarks/README.md +0 -0
  116. {diffbio-0.1.4 → diffbio-0.1.6}/benchmarks/crossmodality/README.md +0 -0
  117. {diffbio-0.1.4 → diffbio-0.1.6}/examples/README.md +0 -0
  118. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/__init__.py +0 -0
  119. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/configs.py +0 -0
  120. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/constants.py +0 -0
  121. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/__init__.py +0 -0
  122. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/gnn_components.py +0 -0
  123. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/graph_utils.py +0 -0
  124. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/optimal_transport.py +0 -0
  125. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/__init__.py +0 -0
  126. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/_projections_permutahedron.py +0 -0
  127. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/_projections_simplex.py +0 -0
  128. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/_projections_transport.py +0 -0
  129. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/_sorting_network.py +0 -0
  130. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/_types.py +0 -0
  131. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/_utils.py +0 -0
  132. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/autograd_safe.py +0 -0
  133. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/comparison.py +0 -0
  134. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/elementwise.py +0 -0
  135. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/logical.py +0 -0
  136. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/normalization.py +0 -0
  137. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/quantile.py +0 -0
  138. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/selection.py +0 -0
  139. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/sorting.py +0 -0
  140. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/core/soft_ops/straight_through.py +0 -0
  141. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/evaluation/__init__.py +0 -0
  142. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/evaluation/graders.py +0 -0
  143. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/evaluation/problem.py +0 -0
  144. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/evaluation/runner.py +0 -0
  145. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/losses/__init__.py +0 -0
  146. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/losses/alignment_losses.py +0 -0
  147. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/losses/biological_regularization.py +0 -0
  148. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/losses/metric_losses.py +0 -0
  149. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/losses/self_supervised_losses.py +0 -0
  150. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/losses/singlecell_losses.py +0 -0
  151. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/__init__.py +0 -0
  152. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/_transformer_validation.py +0 -0
  153. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/alignment/__init__.py +0 -0
  154. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/alignment/scoring.py +0 -0
  155. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/assembly/__init__.py +0 -0
  156. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/crispr/__init__.py +0 -0
  157. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/drug_discovery/__init__.py +0 -0
  158. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/drug_discovery/message_passing.py +0 -0
  159. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/drug_discovery/primitives.py +0 -0
  160. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/epigenomics/__init__.py +0 -0
  161. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/foundation_models/__init__.py +0 -0
  162. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/foundation_models/adapters.py +0 -0
  163. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/foundation_models/contracts.py +0 -0
  164. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/foundation_models/experimental.py +0 -0
  165. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/foundation_models/precomputed.py +0 -0
  166. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/mapping/__init__.py +0 -0
  167. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/metabolomics/__init__.py +0 -0
  168. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/molecular_dynamics/__init__.py +0 -0
  169. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/molecular_dynamics/primitives.py +0 -0
  170. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/multiomics/__init__.py +0 -0
  171. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/normalization/__init__.py +0 -0
  172. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/population/__init__.py +0 -0
  173. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/protein/__init__.py +0 -0
  174. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/rna_structure/__init__.py +0 -0
  175. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/rnaseq/__init__.py +0 -0
  176. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/__init__.py +0 -0
  177. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/singlecell/knockdown_filter.py +0 -0
  178. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/statistical/__init__.py +0 -0
  179. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/variant/__init__.py +0 -0
  180. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/operators/variant/learnable_pileup.py +0 -0
  181. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/pipelines/__init__.py +0 -0
  182. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/pipelines/perturbation.py +0 -0
  183. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/reductions/__init__.py +0 -0
  184. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/reductions/base.py +0 -0
  185. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/reductions/pca_reduction.py +0 -0
  186. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/reductions/tfidf_reduction.py +0 -0
  187. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/samplers/__init__.py +0 -0
  188. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/samplers/perturbation_sampler.py +0 -0
  189. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sequences/__init__.py +0 -0
  190. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sequences/dna.py +0 -0
  191. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sequences/kmer.py +0 -0
  192. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/__init__.py +0 -0
  193. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/_anndata_shared.py +0 -0
  194. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/_batch_iteration.py +0 -0
  195. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/_benchmark_source.py +0 -0
  196. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/_indexed_batch_source.py +0 -0
  197. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/_utils.py +0 -0
  198. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/anndata_interop.py +0 -0
  199. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/archive_ii.py +0 -0
  200. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/balifam.py +0 -0
  201. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/bam.py +0 -0
  202. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/bengrn_ground_truth.py +0 -0
  203. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/contextual_epigenomics.py +0 -0
  204. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/dti.py +0 -0
  205. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/embeddings.py +0 -0
  206. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/encode_peaks.py +0 -0
  207. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/fasta.py +0 -0
  208. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/immune_human.py +0 -0
  209. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/indexed_embeddings.py +0 -0
  210. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/molnet.py +0 -0
  211. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/multiomics.py +0 -0
  212. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/pancreas.py +0 -0
  213. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/perturbation/__init__.py +0 -0
  214. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/perturbation/_types.py +0 -0
  215. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/perturbation/_utils.py +0 -0
  216. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/perturbation/concat_source.py +0 -0
  217. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/perturbation/control_mapping.py +0 -0
  218. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/perturbation/experiment_config.py +0 -0
  219. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/perturbation/h5_metadata_cache.py +0 -0
  220. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/perturbation/output_space.py +0 -0
  221. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/perturbation/perturbation_source.py +0 -0
  222. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/seqfish.py +0 -0
  223. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/sequence_foundation.py +0 -0
  224. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/sources/singlecell_foundation.py +0 -0
  225. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/splitters/__init__.py +0 -0
  226. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/splitters/molecular.py +0 -0
  227. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/splitters/perturbation.py +0 -0
  228. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/splitters/sequence.py +0 -0
  229. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/utils/dependency_runtime.py +0 -0
  230. {diffbio-0.1.4 → diffbio-0.1.6}/src/diffbio/utils/quality.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: diffbio
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: End-to-end differentiable bioinformatics for JAX/Flax NNX: alignment, mapping, assembly, variant calling, RNA-seq, single-cell, epigenomics, CRISPR, metabolomics, multi-omics, protein and RNA structure, molecular dynamics and drug-discovery operators composed into trainable pipelines on datarax, artifex, opifex and calibrax
5
5
  Project-URL: Bug Tracker, https://github.com/avitai/DiffBio/issues
6
6
  Project-URL: Documentation, https://diffbio.readthedocs.io
@@ -45,22 +45,22 @@ Classifier: Topic :: Software Development :: Libraries
45
45
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
46
46
  Requires-Python: <3.14,>=3.12
47
47
  Requires-Dist: anndata>=0.9.1
48
- Requires-Dist: avitai-artifex>=0.1.5
48
+ Requires-Dist: avitai-artifex>=0.1.9
49
49
  Requires-Dist: beartype>=0.14.1
50
50
  Requires-Dist: biopython>=1.81
51
- Requires-Dist: calibrax>=0.1.5
51
+ Requires-Dist: calibrax>=0.1.6
52
52
  Requires-Dist: chex>=0.1.7
53
- Requires-Dist: datarax>=0.1.7
53
+ Requires-Dist: datarax>=0.1.11
54
54
  Requires-Dist: flax>=0.12.9
55
55
  Requires-Dist: h5py>=3.7
56
56
  Requires-Dist: jax-md>=0.2.27
57
57
  Requires-Dist: jax>=0.11.1
58
58
  Requires-Dist: jaxtyping>=0.2.20
59
59
  Requires-Dist: numpy>=1.24
60
- Requires-Dist: opifex>=0.2.2
60
+ Requires-Dist: opifex>=0.2.7
61
61
  Requires-Dist: optax>=0.2.8
62
62
  Requires-Dist: scipy>=1.10
63
- Requires-Dist: substrax>=0.1.5
63
+ Requires-Dist: substrax>=0.1.9
64
64
  Provides-Extra: all
65
65
  Requires-Dist: bandit[toml]>=1.8.6; extra == 'all'
66
66
  Requires-Dist: beartype>=0.14.1; extra == 'all'
@@ -353,6 +353,7 @@ result, _, _ = pipeline.apply(batch_data, {}, None)
353
353
 
354
354
  ```python
355
355
  from diffbio.utils import (
356
+ from substrax.optim import OptimizerConfig
356
357
  Trainer,
357
358
  TrainingConfig,
358
359
  cross_entropy_loss,
@@ -371,10 +372,11 @@ inputs, targets = create_synthetic_training_data(
371
372
 
372
373
  # Configure training
373
374
  config = TrainingConfig(
374
- learning_rate=1e-3,
375
+ optimizer=OptimizerConfig(
376
+ optimizer_type="adam", learning_rate=1e-3, gradient_clip_norm=1.0
377
+ ),
375
378
  num_epochs=50,
376
379
  log_every=10,
377
- grad_clip_norm=1.0,
378
380
  )
379
381
 
380
382
  # Create trainer
@@ -139,6 +139,7 @@ result, _, _ = pipeline.apply(batch_data, {}, None)
139
139
 
140
140
  ```python
141
141
  from diffbio.utils import (
142
+ from substrax.optim import OptimizerConfig
142
143
  Trainer,
143
144
  TrainingConfig,
144
145
  cross_entropy_loss,
@@ -157,10 +158,11 @@ inputs, targets = create_synthetic_training_data(
157
158
 
158
159
  # Configure training
159
160
  config = TrainingConfig(
160
- learning_rate=1e-3,
161
+ optimizer=OptimizerConfig(
162
+ optimizer_type="adam", learning_rate=1e-3, gradient_clip_norm=1.0
163
+ ),
161
164
  num_epochs=50,
162
165
  log_every=10,
163
- grad_clip_norm=1.0,
164
166
  )
165
167
 
166
168
  # Create trainer
@@ -37,15 +37,16 @@ classifiers = [
37
37
  ]
38
38
  dependencies = [
39
39
  # Datarax - operator, source, and pipeline contracts
40
- "datarax>=0.1.7",
40
+ "datarax>=0.1.11",
41
41
  # Artifex - modeling, modality, and transformer substrate
42
- "avitai-artifex>=0.1.5",
42
+ "avitai-artifex>=0.1.9",
43
43
  # Opifex - scientific ML, operator learning, and advanced optimization
44
- "opifex>=0.2.2",
44
+ "opifex>=0.2.7",
45
45
  # Calibrax - benchmarking, comparison, profiling, and regression control
46
- "calibrax>=0.1.5",
47
- # Substrax - device identity, meshes and checkpoint store shared by the siblings
48
- "substrax>=0.1.5",
46
+ "calibrax>=0.1.6",
47
+ # Substrax - device identity, meshes, runtime settings and checkpoint store shared by the
48
+ # siblings; 0.1.6 adds substrax.runtime, substrax.artifacts and substrax.testing.
49
+ "substrax>=0.1.9",
49
50
  # JAX ecosystem
50
51
  "beartype>=0.14.1",
51
52
  "chex>=0.1.7",
@@ -70,7 +71,7 @@ license = {file = "LICENSE"}
70
71
  name = "diffbio"
71
72
  readme = "README.md"
72
73
  requires-python = ">=3.12,<3.14"
73
- version = "0.1.4"
74
+ version = "0.1.6"
74
75
 
75
76
  [project.optional-dependencies]
76
77
  all = ["diffbio[benchmark,chem,cuda12,dev,docs,genomics,metal,soft-ops-advanced,soft-ops-ot,test,torch-io]"]
@@ -25,11 +25,13 @@ from datarax.core.config import OperatorConfig
25
25
  from datarax.core.operator import OperatorModule
26
26
  from flax import nnx
27
27
  from jaxtyping import Array, Float, Int, PyTree
28
+ from substrax.rng import key_from
28
29
 
29
30
  from diffbio.constants import DEFAULT_TEMPERATURE
30
31
  from diffbio.core.graph_utils import scatter_aggregate as scatter_aggregate_fn
31
32
  from diffbio.core.soft_ops import sorting as soft_sorting
32
- from diffbio.utils.nn_utils import ensure_rngs, get_rng_key, init_learnable_param
33
+ from diffbio.utils.nn_utils import init_learnable_param
34
+
33
35
 
34
36
  __all__ = [
35
37
  "TemperatureOperator",
@@ -139,7 +141,7 @@ class TemperatureOperator(OperatorModule):
139
141
  data: PyTree,
140
142
  state: PyTree,
141
143
  metadata: dict[str, Any] | None,
142
- random_params: Any = None,
144
+ key: jax.Array | None = None,
143
145
  stats: dict[str, Any] | None = None,
144
146
  ) -> tuple[PyTree, PyTree, dict[str, Any] | None]:
145
147
  """Base apply method - should be overridden by subclasses."""
@@ -233,7 +235,7 @@ class SequenceOperator(OperatorModule):
233
235
  data: PyTree,
234
236
  state: PyTree,
235
237
  metadata: dict[str, Any] | None,
236
- random_params: Any = None,
238
+ key: jax.Array | None = None,
237
239
  stats: dict[str, Any] | None = None,
238
240
  ) -> tuple[PyTree, PyTree, dict[str, Any] | None]:
239
241
  """Base apply method - should be overridden by subclasses."""
@@ -258,7 +260,7 @@ class EncoderDecoderOperator(OperatorModule):
258
260
  self,
259
261
  config: OperatorConfig,
260
262
  *,
261
- rngs: nnx.Rngs | None = None,
263
+ rngs: nnx.Rngs,
262
264
  name: str | None = None,
263
265
  ):
264
266
  """Initialize EncoderDecoderOperator.
@@ -272,12 +274,13 @@ class EncoderDecoderOperator(OperatorModule):
272
274
 
273
275
  self.latent_dim = getattr(config, "latent_dim", 10)
274
276
  self.hidden_dim = getattr(config, "hidden_dim", 64)
275
- self.rngs = ensure_rngs(rngs)
277
+ self.rngs = rngs
276
278
 
277
279
  def reparameterize(
278
280
  self,
279
281
  mean: Float[Array, "... latent_dim"],
280
282
  log_var: Float[Array, "... latent_dim"],
283
+ key: jax.Array | None = None,
281
284
  ) -> Float[Array, "... latent_dim"]:
282
285
  """Sample from latent distribution using reparameterization trick.
283
286
 
@@ -288,11 +291,18 @@ class EncoderDecoderOperator(OperatorModule):
288
291
  Args:
289
292
  mean: Mean of the latent distribution.
290
293
  log_var: Log variance of the latent distribution.
294
+ key: The key to draw epsilon from. ``apply`` passes the record's key, so a
295
+ record's sample follows the record; a training loss such as
296
+ ``compute_elbo_loss`` passes none and draws from the operator's ``sample``
297
+ stream, which advances on every call.
291
298
 
292
299
  Returns:
293
300
  Sampled latent representation.
294
301
  """
295
- key = get_rng_key(self.rngs, "sample", fallback_seed=0)
302
+ if key is None:
303
+ key = key_from(
304
+ self.rngs, streams=("sample", "default"), context=f"{type(self).__name__} sampling"
305
+ )
296
306
  std = jnp.exp(0.5 * log_var)
297
307
  epsilon = jax.random.normal(key, mean.shape)
298
308
  return mean + std * epsilon
@@ -345,7 +355,7 @@ class EncoderDecoderOperator(OperatorModule):
345
355
  data: PyTree,
346
356
  state: PyTree,
347
357
  metadata: dict[str, Any] | None,
348
- random_params: Any = None,
358
+ key: jax.Array | None = None,
349
359
  stats: dict[str, Any] | None = None,
350
360
  ) -> tuple[PyTree, PyTree, dict[str, Any] | None]:
351
361
  """Base apply method - should be overridden by subclasses."""
@@ -442,7 +452,7 @@ class GraphOperator(OperatorModule):
442
452
  data: PyTree,
443
453
  state: PyTree,
444
454
  metadata: dict[str, Any] | None,
445
- random_params: Any = None,
455
+ key: jax.Array | None = None,
446
456
  stats: dict[str, Any] | None = None,
447
457
  ) -> tuple[PyTree, PyTree, dict[str, Any] | None]:
448
458
  """Base apply method - should be overridden by subclasses."""
@@ -467,7 +477,7 @@ class HMMOperator(OperatorModule):
467
477
  self,
468
478
  config: OperatorConfig,
469
479
  *,
470
- rngs: nnx.Rngs | None = None,
480
+ rngs: nnx.Rngs,
471
481
  name: str | None = None,
472
482
  ):
473
483
  """Initialize HMMOperator.
@@ -484,20 +494,20 @@ class HMMOperator(OperatorModule):
484
494
  self.temperature = getattr(config, "temperature", DEFAULT_TEMPERATURE)
485
495
 
486
496
  # Initialize HMM parameters
487
- rngs = ensure_rngs(rngs)
488
497
 
498
+ context = f"{type(self).__name__} parameters"
489
499
  # Transition logits (will be normalized via log_softmax)
490
- key = get_rng_key(rngs, "params", fallback_seed=0)
500
+ key = key_from(rngs, streams=("params", "default"), context=context)
491
501
  init_trans = jax.random.normal(key, (self.num_states, self.num_states)) * 0.1
492
502
  self.log_transition_params = nnx.Param(init_trans)
493
503
 
494
504
  # Emission logits
495
- key = get_rng_key(rngs, "params", fallback_seed=1)
505
+ key = key_from(rngs, streams=("params", "default"), context=context)
496
506
  init_emit = jax.random.normal(key, (self.num_states, self.num_emissions)) * 0.1
497
507
  self.log_emission_params = nnx.Param(init_emit)
498
508
 
499
509
  # Initial state logits
500
- key = get_rng_key(rngs, "params", fallback_seed=2)
510
+ key = key_from(rngs, streams=("params", "default"), context=context)
501
511
  init_initial = jax.random.normal(key, (self.num_states,)) * 0.1
502
512
  self.log_initial_params = nnx.Param(init_initial)
503
513
 
@@ -593,7 +603,7 @@ class HMMOperator(OperatorModule):
593
603
  data: PyTree,
594
604
  state: PyTree,
595
605
  metadata: dict[str, Any] | None,
596
- random_params: Any = None,
606
+ key: jax.Array | None = None,
597
607
  stats: dict[str, Any] | None = None,
598
608
  ) -> tuple[PyTree, PyTree, dict[str, Any] | None]:
599
609
  """Base apply method - should be overridden by subclasses."""
@@ -6,6 +6,7 @@ the expected interfaces and data structures across the DiffBio codebase.
6
6
 
7
7
  from typing import Any, Protocol, TypedDict, runtime_checkable
8
8
 
9
+ import jax
9
10
  from jaxtyping import Array, Float
10
11
 
11
12
  # =============================================================================
@@ -166,7 +167,7 @@ class DifferentiableOperator(Protocol):
166
167
  data: dict[str, Any],
167
168
  state: StateDict,
168
169
  metadata: MetadataDict,
169
- random_params: Any = None,
170
+ key: jax.Array | None = None,
170
171
  stats: dict[str, Any] | None = None,
171
172
  ) -> OperatorOutput:
172
173
  """Apply the operator to input data.
@@ -175,7 +176,7 @@ class DifferentiableOperator(Protocol):
175
176
  data: Input data dictionary.
176
177
  state: Element state.
177
178
  metadata: Element metadata.
178
- random_params: Random parameters for stochastic operations.
179
+ key: The record's PRNG key; a stochastic operator draws from it.
179
180
  stats: Statistics dictionary.
180
181
 
181
182
  Returns:
@@ -27,17 +27,10 @@ from typing import Literal
27
27
  import jax
28
28
  import jax.numpy as jnp
29
29
  from artifex.generative_models.core.base import MLP
30
- from flax import nnx
31
- from jaxtyping import Array, Float, Int
32
-
33
- from diffbio.constants import DEFAULT_TEMPERATURE
34
- from diffbio.core.graph_utils import scatter_aggregate
35
- from diffbio.utils.nn_utils import get_rng_key
36
30
 
37
31
  # =============================================================================
38
32
  # Re-export from artifex (import when available, provide stubs otherwise)
39
33
  # =============================================================================
40
-
41
34
  from artifex.generative_models.core.layers.positional import (
42
35
  PositionalEncoding,
43
36
  RotaryPositionalEncoding as RoPE,
@@ -47,6 +40,12 @@ from artifex.generative_models.core.layers.residual import (
47
40
  Conv1DResidualBlock as ResidualBlock1D,
48
41
  Conv2DResidualBlock as ResidualBlock2D,
49
42
  )
43
+ from flax import nnx
44
+ from jaxtyping import Array, Float, Int
45
+ from substrax.rng import key_from
46
+
47
+ from diffbio.constants import DEFAULT_TEMPERATURE
48
+ from diffbio.core.graph_utils import scatter_aggregate
50
49
 
51
50
 
52
51
  __all__ = [
@@ -115,7 +114,9 @@ class GumbelSoftmaxModule(nnx.Module):
115
114
  Returns:
116
115
  Samples of same shape as logits.
117
116
  """
118
- key = get_rng_key(self.rngs, "dropout", fallback_seed=0)
117
+ key = key_from(
118
+ self.rngs, streams=("dropout", "default"), context="GumbelSoftmaxModule sampling"
119
+ )
119
120
  gumbel_noise = jax.random.gumbel(key, logits.shape)
120
121
  perturbed = (logits + gumbel_noise) / self.temperature
121
122
  soft_sample = jax.nn.softmax(perturbed, axis=-1)
@@ -161,7 +161,7 @@ class EnsembleUQOperator(OperatorModule):
161
161
  data: PyTree,
162
162
  state: PyTree,
163
163
  metadata: dict[str, Any] | None,
164
- random_params: Any = None, # noqa: ARG002
164
+ key: jax.Array | None = None, # noqa: ARG002
165
165
  stats: dict[str, Any] | None = None, # noqa: ARG002
166
166
  ) -> tuple[PyTree, PyTree, dict[str, Any] | None]:
167
167
  """Run ensemble forward passes and aggregate with uncertainty.
@@ -170,7 +170,7 @@ class EnsembleUQOperator(OperatorModule):
170
170
  data: Input data dict for the base operator.
171
171
  state: Element state (passed through).
172
172
  metadata: Element metadata (passed through).
173
- random_params: Unused.
173
+ key: Unused.
174
174
  stats: Unused.
175
175
 
176
176
  Returns:
@@ -241,7 +241,7 @@ class MCSamplingUQOperator(OperatorModule):
241
241
  data: PyTree,
242
242
  state: PyTree,
243
243
  metadata: dict[str, Any] | None,
244
- random_params: Any = None, # noqa: ARG002
244
+ key: jax.Array | None = None, # noqa: ARG002
245
245
  stats: dict[str, Any] | None = None, # noqa: ARG002
246
246
  ) -> tuple[PyTree, PyTree, dict[str, Any] | None]:
247
247
  """Run Monte Carlo sampling to estimate empirical intervals.
@@ -250,7 +250,7 @@ class MCSamplingUQOperator(OperatorModule):
250
250
  data: Input data dict for the base operator.
251
251
  state: Element state (passed through).
252
252
  metadata: Element metadata (passed through).
253
- random_params: Unused.
253
+ key: Unused.
254
254
  stats: Unused.
255
255
 
256
256
  Returns:
@@ -135,7 +135,7 @@ class TaskAdapter:
135
135
  else:
136
136
  adapted = data_dict
137
137
 
138
- result, _, _ = operator.apply(adapted, {}, None)
138
+ result, _, _ = operator.apply(adapted, {}, None, jax.random.key(self._seed))
139
139
  # Propagate retention info
140
140
  if "retention_weights" not in result and "quality_scores" in adapted:
141
141
  quality = adapted["quality_scores"]
@@ -160,7 +160,7 @@ class TaskAdapter:
160
160
  temperature=temperature,
161
161
  )
162
162
  operator = SoftKMeansClustering(op_config, rngs=nnx.Rngs(self._seed))
163
- result, _, _ = operator.apply(data_dict, {}, None)
163
+ result, _, _ = operator.apply(data_dict, {}, None, jax.random.key(self._seed))
164
164
  return result
165
165
 
166
166
  def _run_de(self, data_dict: dict[str, Any], config: dict[str, Any]) -> dict[str, Any]:
@@ -178,7 +178,7 @@ class TaskAdapter:
178
178
  n_conditions=n_conditions,
179
179
  )
180
180
  pipeline = DifferentialExpressionPipeline(op_config, rngs=nnx.Rngs(self._seed))
181
- result, _, _ = pipeline.apply(data_dict, {}, None)
181
+ result, _, _ = pipeline.apply(data_dict, {}, None, jax.random.key(self._seed))
182
182
 
183
183
  # Add gene names for grader extraction
184
184
  if "gene_names" not in result:
@@ -202,7 +202,7 @@ class TaskAdapter:
202
202
  n_clusters=n_clusters,
203
203
  )
204
204
  operator = DifferentiableHarmony(op_config, rngs=nnx.Rngs(self._seed))
205
- result, _, _ = operator.apply(data_dict, {}, None)
205
+ result, _, _ = operator.apply(data_dict, {}, None, jax.random.key(self._seed))
206
206
  return result
207
207
 
208
208
  def _run_normalization(
@@ -222,7 +222,7 @@ class TaskAdapter:
222
222
  latent_dim=latent_dim,
223
223
  )
224
224
  operator = VAENormalizer(op_config, rngs=nnx.Rngs(self._seed))
225
- result, _, _ = operator.apply(data_dict, {}, None)
225
+ result, _, _ = operator.apply(data_dict, {}, None, jax.random.key(self._seed))
226
226
  return result
227
227
 
228
228
  def _run_trajectory(self, data_dict: dict[str, Any], config: dict[str, Any]) -> dict[str, Any]:
@@ -240,7 +240,7 @@ class TaskAdapter:
240
240
  n_diffusion_components=n_diffusion_components,
241
241
  )
242
242
  operator = DifferentiablePseudotime(op_config, rngs=nnx.Rngs(self._seed))
243
- result, _, _ = operator.apply(data_dict, {}, None)
243
+ result, _, _ = operator.apply(data_dict, {}, None, jax.random.key(self._seed))
244
244
  return result
245
245
 
246
246
  def _run_spatial_analysis(
@@ -260,7 +260,7 @@ class TaskAdapter:
260
260
  n_domains=n_domains,
261
261
  )
262
262
  operator = DifferentiableSpatialDomain(op_config, rngs=nnx.Rngs(self._seed))
263
- result, _, _ = operator.apply(data_dict, {}, None)
263
+ result, _, _ = operator.apply(data_dict, {}, None, jax.random.key(self._seed))
264
264
  return result
265
265
 
266
266
  def _run_cell_annotation(
@@ -261,7 +261,7 @@ class HMMLikelihoodLoss(nnx.Module):
261
261
  n_states: int,
262
262
  n_emissions: int,
263
263
  *,
264
- rngs: nnx.Rngs | None = None,
264
+ rngs: nnx.Rngs,
265
265
  ):
266
266
  """Initialize the HMM loss.
267
267
 
@@ -272,9 +272,6 @@ class HMMLikelihoodLoss(nnx.Module):
272
272
  """
273
273
  super().__init__()
274
274
 
275
- if rngs is None:
276
- rngs = nnx.Rngs(0)
277
-
278
275
  self.n_states = n_states
279
276
  self.n_emissions = n_emissions
280
277
 
@@ -4,14 +4,13 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Any
6
6
 
7
- from artifex.generative_models.core.base import MLP
8
- from flax import nnx
9
7
  import jax
10
8
  import jax.numpy as jnp
9
+ from artifex.generative_models.core.base import MLP
10
+ from flax import nnx
11
11
  from jaxtyping import Array, Float
12
12
 
13
13
  from diffbio.losses.statistical_losses import zinb_negative_log_likelihood
14
- from diffbio.utils.nn_utils import ensure_rngs
15
14
 
16
15
 
17
16
  class CountVAEBackboneMixin:
@@ -32,10 +31,9 @@ class CountVAEBackboneMixin:
32
31
  latent_dim: int,
33
32
  hidden_dims: list[int],
34
33
  n_outputs: int,
35
- rngs: nnx.Rngs | None,
34
+ rngs: nnx.Rngs,
36
35
  ) -> None:
37
36
  """Initialise the shared count-VAE encoder and decoder layers."""
38
- safe_rngs = ensure_rngs(rngs)
39
37
 
40
38
  encoder_hidden_dims = list(hidden_dims)
41
39
  decoder_hidden_dims = list(reversed(hidden_dims))
@@ -47,7 +45,7 @@ class CountVAEBackboneMixin:
47
45
  activation="relu",
48
46
  output_activation="relu",
49
47
  use_batch_norm=False,
50
- rngs=safe_rngs,
48
+ rngs=rngs,
51
49
  )
52
50
  encoder_out_dim = encoder_hidden_dims[-1]
53
51
  else:
@@ -57,12 +55,12 @@ class CountVAEBackboneMixin:
57
55
  self.fc_mean = nnx.Linear(
58
56
  in_features=encoder_out_dim,
59
57
  out_features=latent_dim,
60
- rngs=safe_rngs,
58
+ rngs=rngs,
61
59
  )
62
60
  self.fc_logvar = nnx.Linear(
63
61
  in_features=encoder_out_dim,
64
62
  out_features=latent_dim,
65
- rngs=safe_rngs,
63
+ rngs=rngs,
66
64
  )
67
65
 
68
66
  if decoder_hidden_dims:
@@ -72,7 +70,7 @@ class CountVAEBackboneMixin:
72
70
  activation="relu",
73
71
  output_activation="relu",
74
72
  use_batch_norm=False,
75
- rngs=safe_rngs,
73
+ rngs=rngs,
76
74
  )
77
75
  decoder_out_dim = decoder_hidden_dims[-1]
78
76
  else:
@@ -82,17 +80,16 @@ class CountVAEBackboneMixin:
82
80
  self.fc_output = nnx.Linear(
83
81
  in_features=decoder_out_dim,
84
82
  out_features=n_outputs,
85
- rngs=safe_rngs,
83
+ rngs=rngs,
86
84
  )
87
85
 
88
86
  def _init_count_vae_operator(
89
87
  self,
90
88
  *,
91
89
  config: Any,
92
- rngs: nnx.Rngs | None,
90
+ rngs: nnx.Rngs,
93
91
  ) -> nnx.Rngs:
94
- """Initialise shared count-VAE operator state and return safe RNGs."""
95
- safe_rngs = ensure_rngs(rngs)
92
+ """Initialise shared count-VAE operator state and return the rngs it used."""
96
93
  self.n_genes = config.n_genes
97
94
  self.stream_name = nnx.static(config.stream_name)
98
95
  self._init_count_vae_backbone(
@@ -100,9 +97,9 @@ class CountVAEBackboneMixin:
100
97
  latent_dim=config.latent_dim,
101
98
  hidden_dims=config.hidden_dims,
102
99
  n_outputs=config.n_genes,
103
- rngs=safe_rngs,
100
+ rngs=rngs,
104
101
  )
105
- return safe_rngs
102
+ return rngs
106
103
 
107
104
  def encode(
108
105
  self,
@@ -145,7 +142,7 @@ class CountVAEBackbone(CountVAEBackboneMixin, nnx.Module):
145
142
  latent_dim: int,
146
143
  hidden_dims: list[int],
147
144
  n_outputs: int,
148
- rngs: nnx.Rngs | None = None,
145
+ rngs: nnx.Rngs,
149
146
  ) -> None:
150
147
  """Initialise a standalone shared count-VAE backbone."""
151
148
  super().__init__()
@@ -10,21 +10,18 @@ from flax import nnx
10
10
  from jaxtyping import Array, Float
11
11
  from opifex.core.physics.gradnorm import GradNormBalancer
12
12
 
13
- from diffbio.utils.nn_utils import ensure_rngs
14
-
15
13
 
16
14
  def combine_scalar_losses(
17
15
  losses: Mapping[str, Float[Array, ""]],
18
16
  *,
19
- use_gradnorm: bool,
20
- rngs: nnx.Rngs | None = None,
17
+ balancer: GradNormBalancer | None,
21
18
  ) -> Float[Array, ""]:
22
- """Combine scalar losses with optional GradNorm-based balancing.
19
+ """Combine scalar losses, weighted by ``balancer`` when one is given.
23
20
 
24
21
  Args:
25
22
  losses: Named scalar losses to combine.
26
- use_gradnorm: Whether to balance losses with ``GradNormBalancer``.
27
- rngs: Optional random generators used when constructing GradNorm.
23
+ balancer: The ``GradNormBalancer`` whose weights combine the losses, or ``None``
24
+ to sum them.
28
25
 
29
26
  Returns:
30
27
  Combined scalar loss.
@@ -35,15 +32,9 @@ def combine_scalar_losses(
35
32
  if not losses:
36
33
  msg = "losses must contain at least one scalar loss"
37
34
  raise ValueError(msg)
38
-
39
35
  loss_values = list(losses.values())
40
- if use_gradnorm:
41
- balancer = GradNormBalancer(
42
- num_losses=len(loss_values),
43
- rngs=ensure_rngs(rngs),
44
- )
36
+ if balancer is not None:
45
37
  return balancer.compute_weighted_loss(jnp.stack(loss_values))
46
-
47
38
  total_loss = loss_values[0]
48
39
  for loss_value in loss_values[1:]:
49
40
  total_loss = total_loss + loss_value
@@ -51,16 +42,25 @@ def combine_scalar_losses(
51
42
 
52
43
 
53
44
  class LossBalancingMixin:
54
- """Reusable operator mixin exposing ``compute_balanced_loss``."""
45
+ """Reusable operator mixin exposing ``compute_balanced_loss``.
46
+
47
+ The mixin is a stateless combiner: with ``config.use_gradnorm`` it builds a fresh
48
+ ``GradNormBalancer`` from the operator's ``rngs`` on every call and never updates its
49
+ weights, so it weights the losses equally; a training loop that wants adaptive GradNorm
50
+ composes the balancer itself across steps, as ``diffbio.pipelines.joint_training`` does.
51
+ """
55
52
 
56
53
  config: Any
54
+ rngs: nnx.Rngs
57
55
 
58
56
  def compute_balanced_loss(
59
57
  self,
60
58
  losses: Mapping[str, Float[Array, ""]],
61
59
  ) -> Float[Array, ""]:
62
60
  """Combine operator loss terms using the config's GradNorm flag."""
63
- return combine_scalar_losses(
64
- losses,
65
- use_gradnorm=bool(getattr(self.config, "use_gradnorm", False)),
61
+ balancer = (
62
+ GradNormBalancer(num_losses=len(losses), rngs=self.rngs)
63
+ if getattr(self.config, "use_gradnorm", False)
64
+ else None
66
65
  )
66
+ return combine_scalar_losses(losses, balancer=balancer)