diffbio 0.1.5__tar.gz → 0.1.7__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.5 → diffbio-0.1.7}/PKG-INFO +12 -11
  2. {diffbio-0.1.5 → diffbio-0.1.7}/README.md +6 -5
  3. {diffbio-0.1.5 → diffbio-0.1.7}/pyproject.toml +8 -7
  4. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/base_operators.py +13 -9
  5. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/neural_components.py +9 -8
  6. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/losses/self_supervised_losses.py +10 -9
  7. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/losses/statistical_losses.py +1 -4
  8. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/_count_vae.py +13 -16
  9. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/_loss_balancing.py +18 -18
  10. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/alignment/profile_hmm.py +1 -4
  11. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/alignment/soft_msa.py +2 -4
  12. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/assembly/gnn_assembly.py +1 -4
  13. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/drug_discovery/_graph_utils.py +5 -6
  14. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/drug_discovery/admet_predictor.py +1 -1
  15. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/drug_discovery/attentive_fp.py +1 -4
  16. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/drug_discovery/dti.py +1 -3
  17. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/drug_discovery/fingerprint.py +12 -11
  18. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/drug_discovery/maccs_keys.py +2 -4
  19. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/drug_discovery/property_predictor.py +1 -1
  20. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/drug_discovery/similarity.py +4 -1
  21. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/epigenomics/chromatin_state.py +5 -5
  22. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/epigenomics/contextual.py +3 -8
  23. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/epigenomics/fno_peak_calling.py +1 -4
  24. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/epigenomics/peak_calling.py +7 -6
  25. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/foundation_models/embedding_probe.py +1 -4
  26. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/foundation_models/foundation_model.py +1 -4
  27. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/foundation_models/frozen.py +1 -1
  28. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/foundation_models/transformer_encoder.py +6 -16
  29. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/mapping/neural_mapper.py +1 -4
  30. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/molecular_dynamics/integrator.py +13 -5
  31. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/multiomics/hic_contact.py +1 -4
  32. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/multiomics/multiomics_vae.py +2 -3
  33. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/multiomics/spatial_deconvolution.py +1 -4
  34. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/embedding.py +1 -4
  35. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/learnable_projection.py +4 -1
  36. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/umap.py +1 -4
  37. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/vae_normalizer.py +43 -6
  38. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/preprocessing/duplicate_filter.py +7 -5
  39. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/preprocessing/error_correction.py +3 -4
  40. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/protein/secondary_structure.py +41 -39
  41. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/rna_structure/rna_folding.py +2 -4
  42. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/rnaseq/motif_discovery.py +5 -5
  43. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/ambient_removal.py +1 -4
  44. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/archetypes.py +8 -5
  45. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/batch_correction.py +1 -2
  46. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/cell_annotation.py +12 -7
  47. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/communication.py +2 -4
  48. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/differential_distribution.py +3 -6
  49. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/doublet_detection.py +12 -11
  50. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/enhanced_batch_correction.py +3 -7
  51. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/grn_inference.py +2 -4
  52. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/imputation.py +1 -4
  53. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/ot_trajectory.py +2 -4
  54. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/simulation.py +3 -5
  55. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/soft_clustering.py +1 -2
  56. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/spatial_domains.py +8 -9
  57. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/velocity.py +1 -4
  58. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/statistical/em_quantification.py +1 -4
  59. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/statistical/hmm.py +1 -1
  60. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/statistical/nb_glm.py +1 -4
  61. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/variant/classifier.py +3 -4
  62. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/variant/cnn_classifier.py +2 -4
  63. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/variant/cnv_segmentation.py +2 -8
  64. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/variant/quality_recalibration.py +1 -4
  65. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/pipelines/differential_expression.py +1 -4
  66. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/pipelines/joint_training.py +19 -30
  67. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/pipelines/minibatch_training.py +18 -36
  68. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/indexed_view.py +15 -5
  69. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/splitters/base.py +23 -0
  70. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/splitters/random.py +3 -21
  71. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/utils/__init__.py +8 -13
  72. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/utils/nn_utils.py +0 -47
  73. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/utils/training.py +15 -62
  74. {diffbio-0.1.5 → diffbio-0.1.7}/.gitignore +0 -0
  75. {diffbio-0.1.5 → diffbio-0.1.7}/LICENSE +0 -0
  76. {diffbio-0.1.5 → diffbio-0.1.7}/benchmarks/README.md +0 -0
  77. {diffbio-0.1.5 → diffbio-0.1.7}/benchmarks/crossmodality/README.md +0 -0
  78. {diffbio-0.1.5 → diffbio-0.1.7}/examples/README.md +0 -0
  79. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/__init__.py +0 -0
  80. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/configs.py +0 -0
  81. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/constants.py +0 -0
  82. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/__init__.py +0 -0
  83. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/data_types.py +0 -0
  84. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/gnn_components.py +0 -0
  85. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/graph_utils.py +0 -0
  86. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/optimal_transport.py +0 -0
  87. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/__init__.py +0 -0
  88. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/_projections_permutahedron.py +0 -0
  89. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/_projections_simplex.py +0 -0
  90. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/_projections_transport.py +0 -0
  91. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/_sorting_network.py +0 -0
  92. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/_types.py +0 -0
  93. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/_utils.py +0 -0
  94. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/autograd_safe.py +0 -0
  95. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/comparison.py +0 -0
  96. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/elementwise.py +0 -0
  97. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/logical.py +0 -0
  98. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/normalization.py +0 -0
  99. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/quantile.py +0 -0
  100. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/selection.py +0 -0
  101. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/sorting.py +0 -0
  102. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/soft_ops/straight_through.py +0 -0
  103. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/core/uncertainty.py +0 -0
  104. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/evaluation/__init__.py +0 -0
  105. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/evaluation/adapters.py +0 -0
  106. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/evaluation/graders.py +0 -0
  107. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/evaluation/problem.py +0 -0
  108. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/evaluation/runner.py +0 -0
  109. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/losses/__init__.py +0 -0
  110. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/losses/alignment_losses.py +0 -0
  111. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/losses/biological_regularization.py +0 -0
  112. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/losses/metric_losses.py +0 -0
  113. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/losses/singlecell_losses.py +0 -0
  114. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/__init__.py +0 -0
  115. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/_masked_gene_transformer.py +0 -0
  116. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/_transformer_validation.py +0 -0
  117. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/alignment/__init__.py +0 -0
  118. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/alignment/scoring.py +0 -0
  119. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/alignment/smith_waterman.py +0 -0
  120. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/assembly/__init__.py +0 -0
  121. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/assembly/metagenomic_binning.py +0 -0
  122. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/crispr/__init__.py +0 -0
  123. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/crispr/guide_scoring.py +0 -0
  124. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/drug_discovery/__init__.py +0 -0
  125. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/drug_discovery/message_passing.py +0 -0
  126. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/drug_discovery/primitives.py +0 -0
  127. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/epigenomics/__init__.py +0 -0
  128. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/foundation_models/__init__.py +0 -0
  129. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/foundation_models/adapters.py +0 -0
  130. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/foundation_models/contracts.py +0 -0
  131. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/foundation_models/experimental.py +0 -0
  132. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/foundation_models/precomputed.py +0 -0
  133. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/mapping/__init__.py +0 -0
  134. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/metabolomics/__init__.py +0 -0
  135. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/metabolomics/isotope_envelope.py +0 -0
  136. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/metabolomics/soft_centroiding.py +0 -0
  137. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/metabolomics/spectral_similarity.py +0 -0
  138. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/molecular_dynamics/__init__.py +0 -0
  139. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/molecular_dynamics/force_field.py +0 -0
  140. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/molecular_dynamics/primitives.py +0 -0
  141. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/multiomics/__init__.py +0 -0
  142. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/multiomics/spatial_gene_detection.py +0 -0
  143. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/__init__.py +0 -0
  144. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/arcsinh_cofactor.py +0 -0
  145. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/differentiable_pca.py +0 -0
  146. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/learnable_normalization.py +0 -0
  147. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/learnable_orthogonal_projection.py +0 -0
  148. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/matrix_free_pca.py +0 -0
  149. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/phate.py +0 -0
  150. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/scaling.py +0 -0
  151. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/normalization/soft_pca.py +0 -0
  152. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/population/__init__.py +0 -0
  153. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/population/ancestry_estimation.py +0 -0
  154. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/preprocessing/__init__.py +0 -0
  155. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/preprocessing/adapter_removal.py +0 -0
  156. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/protein/__init__.py +0 -0
  157. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/quality_filter.py +0 -0
  158. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/rna_structure/__init__.py +0 -0
  159. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/rnaseq/__init__.py +0 -0
  160. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/rnaseq/splicing_psi.py +0 -0
  161. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/__init__.py +0 -0
  162. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/downsampling.py +0 -0
  163. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/knockdown_filter.py +0 -0
  164. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/sindy_grn.py +0 -0
  165. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/soft_hvg.py +0 -0
  166. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/stochastic_gate_selector.py +0 -0
  167. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/switch_de.py +0 -0
  168. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/singlecell/trajectory.py +0 -0
  169. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/statistical/__init__.py +0 -0
  170. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/variant/__init__.py +0 -0
  171. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/variant/deepvariant_pileup.py +0 -0
  172. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/variant/learnable_pileup.py +0 -0
  173. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/operators/variant/pileup.py +0 -0
  174. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/pipelines/__init__.py +0 -0
  175. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/pipelines/adapters.py +0 -0
  176. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/pipelines/enhanced_variant_calling.py +0 -0
  177. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/pipelines/joint_preprocessing.py +0 -0
  178. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/pipelines/perturbation.py +0 -0
  179. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/pipelines/preprocessing.py +0 -0
  180. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/pipelines/single_cell.py +0 -0
  181. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/pipelines/variant_calling.py +0 -0
  182. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/reductions/__init__.py +0 -0
  183. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/reductions/base.py +0 -0
  184. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/reductions/pca_reduction.py +0 -0
  185. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/reductions/tfidf_reduction.py +0 -0
  186. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/samplers/__init__.py +0 -0
  187. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/samplers/perturbation_sampler.py +0 -0
  188. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sequences/__init__.py +0 -0
  189. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sequences/dna.py +0 -0
  190. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sequences/kmer.py +0 -0
  191. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/__init__.py +0 -0
  192. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/_anndata_shared.py +0 -0
  193. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/_batch_iteration.py +0 -0
  194. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/_benchmark_source.py +0 -0
  195. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/_indexed_batch_source.py +0 -0
  196. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/_utils.py +0 -0
  197. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/anndata_interop.py +0 -0
  198. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/anndata_source.py +0 -0
  199. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/archive_ii.py +0 -0
  200. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/balifam.py +0 -0
  201. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/bam.py +0 -0
  202. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/bengrn_ground_truth.py +0 -0
  203. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/contextual_epigenomics.py +0 -0
  204. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/dti.py +0 -0
  205. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/embeddings.py +0 -0
  206. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/encode_peaks.py +0 -0
  207. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/fasta.py +0 -0
  208. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/immune_human.py +0 -0
  209. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/indexed_embeddings.py +0 -0
  210. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/molnet.py +0 -0
  211. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/multiomics.py +0 -0
  212. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/pancreas.py +0 -0
  213. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/perturbation/__init__.py +0 -0
  214. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/perturbation/_types.py +0 -0
  215. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/perturbation/_utils.py +0 -0
  216. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/perturbation/concat_source.py +0 -0
  217. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/perturbation/control_mapping.py +0 -0
  218. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/perturbation/experiment_config.py +0 -0
  219. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/perturbation/h5_metadata_cache.py +0 -0
  220. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/perturbation/output_space.py +0 -0
  221. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/perturbation/perturbation_source.py +0 -0
  222. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/seqfish.py +0 -0
  223. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/sequence_foundation.py +0 -0
  224. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/sources/singlecell_foundation.py +0 -0
  225. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/splitters/__init__.py +0 -0
  226. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/splitters/molecular.py +0 -0
  227. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/splitters/perturbation.py +0 -0
  228. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/splitters/sequence.py +0 -0
  229. {diffbio-0.1.5 → diffbio-0.1.7}/src/diffbio/utils/dependency_runtime.py +0 -0
  230. {diffbio-0.1.5 → diffbio-0.1.7}/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.5
3
+ Version: 0.1.7
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.8
52
52
  Requires-Dist: chex>=0.1.7
53
- Requires-Dist: datarax>=0.1.10
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'
@@ -352,10 +352,11 @@ result, _, _ = pipeline.apply(batch_data, {}, None)
352
352
  ### Training a Pipeline
353
353
 
354
354
  ```python
355
+ from calibrax.metrics.functional import softmax_cross_entropy
356
+ from substrax.optim import OptimizerConfig
355
357
  from diffbio.utils import (
356
358
  Trainer,
357
359
  TrainingConfig,
358
- cross_entropy_loss,
359
360
  create_synthetic_training_data,
360
361
  data_iterator,
361
362
  )
@@ -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
@@ -382,10 +384,9 @@ trainer = Trainer(pipeline, config)
382
384
 
383
385
  # Define loss function
384
386
  def loss_fn(predictions, targets):
385
- return cross_entropy_loss(
387
+ return softmax_cross_entropy(
386
388
  predictions["logits"],
387
389
  targets["labels"],
388
- num_classes=3,
389
390
  )
390
391
 
391
392
  # Train
@@ -138,10 +138,11 @@ result, _, _ = pipeline.apply(batch_data, {}, None)
138
138
  ### Training a Pipeline
139
139
 
140
140
  ```python
141
+ from calibrax.metrics.functional import softmax_cross_entropy
142
+ from substrax.optim import OptimizerConfig
141
143
  from diffbio.utils import (
142
144
  Trainer,
143
145
  TrainingConfig,
144
- cross_entropy_loss,
145
146
  create_synthetic_training_data,
146
147
  data_iterator,
147
148
  )
@@ -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
@@ -168,10 +170,9 @@ trainer = Trainer(pipeline, config)
168
170
 
169
171
  # Define loss function
170
172
  def loss_fn(predictions, targets):
171
- return cross_entropy_loss(
173
+ return softmax_cross_entropy(
172
174
  predictions["logits"],
173
175
  targets["labels"],
174
- num_classes=3,
175
176
  )
176
177
 
177
178
  # Train
@@ -37,15 +37,16 @@ classifiers = [
37
37
  ]
38
38
  dependencies = [
39
39
  # Datarax - operator, source, and pipeline contracts
40
- "datarax>=0.1.10",
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.8",
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.5"
74
+ version = "0.1.7"
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",
@@ -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,7 +274,7 @@ 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,
@@ -298,7 +300,9 @@ class EncoderDecoderOperator(OperatorModule):
298
300
  Sampled latent representation.
299
301
  """
300
302
  if key is None:
301
- key = get_rng_key(self.rngs, "sample", fallback_seed=0)
303
+ key = key_from(
304
+ self.rngs, streams=("sample", "default"), context=f"{type(self).__name__} sampling"
305
+ )
302
306
  std = jnp.exp(0.5 * log_var)
303
307
  epsilon = jax.random.normal(key, mean.shape)
304
308
  return mean + std * epsilon
@@ -473,7 +477,7 @@ class HMMOperator(OperatorModule):
473
477
  self,
474
478
  config: OperatorConfig,
475
479
  *,
476
- rngs: nnx.Rngs | None = None,
480
+ rngs: nnx.Rngs,
477
481
  name: str | None = None,
478
482
  ):
479
483
  """Initialize HMMOperator.
@@ -490,20 +494,20 @@ class HMMOperator(OperatorModule):
490
494
  self.temperature = getattr(config, "temperature", DEFAULT_TEMPERATURE)
491
495
 
492
496
  # Initialize HMM parameters
493
- rngs = ensure_rngs(rngs)
494
497
 
498
+ context = f"{type(self).__name__} parameters"
495
499
  # Transition logits (will be normalized via log_softmax)
496
- key = get_rng_key(rngs, "params", fallback_seed=0)
500
+ key = key_from(rngs, streams=("params", "default"), context=context)
497
501
  init_trans = jax.random.normal(key, (self.num_states, self.num_states)) * 0.1
498
502
  self.log_transition_params = nnx.Param(init_trans)
499
503
 
500
504
  # Emission logits
501
- key = get_rng_key(rngs, "params", fallback_seed=1)
505
+ key = key_from(rngs, streams=("params", "default"), context=context)
502
506
  init_emit = jax.random.normal(key, (self.num_states, self.num_emissions)) * 0.1
503
507
  self.log_emission_params = nnx.Param(init_emit)
504
508
 
505
509
  # Initial state logits
506
- key = get_rng_key(rngs, "params", fallback_seed=2)
510
+ key = key_from(rngs, streams=("params", "default"), context=context)
507
511
  init_initial = jax.random.normal(key, (self.num_states,)) * 0.1
508
512
  self.log_initial_params = nnx.Param(init_initial)
509
513
 
@@ -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)
@@ -11,10 +11,11 @@ term, which the ``core.losses`` ledger flags as the one genuinely new B6 piece.
11
11
  from __future__ import annotations
12
12
 
13
13
  import jax
14
+ from calibrax.metrics.functional import mae, mse
14
15
  from flax import nnx
15
16
 
16
- _EPSILON = 1.0e-8
17
- _VALID_LOSS_TYPES = ("mse", "mae")
17
+ _LOSSES = {"mse": mse, "mae": mae}
18
+ _VALID_LOSS_TYPES = tuple(_LOSSES)
18
19
 
19
20
 
20
21
  def masked_value_loss(
@@ -23,28 +24,28 @@ def masked_value_loss(
23
24
  mask: jax.Array,
24
25
  *,
25
26
  loss_type: str = "mse",
26
- epsilon: float = _EPSILON,
27
27
  ) -> jax.Array:
28
28
  """Reconstruction loss averaged over masked positions only.
29
29
 
30
+ The reduction is calibrax's masked mean: positions where ``mask`` is nonzero are
31
+ averaged, the rest contribute nothing, and an all-zero mask gives ``0`` rather than
32
+ ``0 / 0``.
33
+
30
34
  Args:
31
35
  predictions: Predicted values, any shape broadcastable with ``mask``.
32
36
  targets: Ground-truth values, same shape as ``predictions``.
33
37
  mask: ``1`` at positions to reconstruct (the masked-out values), ``0`` elsewhere.
34
38
  loss_type: ``"mse"`` (squared error) or ``"mae"`` (absolute error).
35
- epsilon: Stabilizer so an all-zero mask returns ``0`` rather than ``0 / 0``.
36
39
 
37
40
  Returns:
38
- The mask-weighted mean reconstruction error at the masked positions.
41
+ The mean reconstruction error at the masked positions.
39
42
 
40
43
  Raises:
41
44
  ValueError: If ``loss_type`` is not one of ``("mse", "mae")``.
42
45
  """
43
- if loss_type not in _VALID_LOSS_TYPES:
46
+ if loss_type not in _LOSSES:
44
47
  raise ValueError(f"loss_type must be one of {_VALID_LOSS_TYPES}, got {loss_type!r}")
45
- residual = predictions - targets
46
- error = residual**2 if loss_type == "mse" else abs(residual)
47
- return (mask * error).sum() / (mask.sum() + epsilon)
48
+ return _LOSSES[loss_type](predictions, targets, mask=mask)
48
49
 
49
50
 
50
51
  class MaskedValueLoss(nnx.Module):
@@ -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)
@@ -88,7 +88,7 @@ class ProfileHMMSearch(TemperatureOperator):
88
88
  self,
89
89
  config: ProfileHMMConfig,
90
90
  *,
91
- rngs: nnx.Rngs | None = None,
91
+ rngs: nnx.Rngs,
92
92
  name: str | None = None,
93
93
  ):
94
94
  """Initialize the profile HMM operator.
@@ -100,9 +100,6 @@ class ProfileHMMSearch(TemperatureOperator):
100
100
  """
101
101
  super().__init__(config, rngs=rngs, name=name)
102
102
 
103
- if rngs is None:
104
- rngs = nnx.Rngs(0)
105
-
106
103
  self.profile_length = config.profile_length
107
104
  self.alphabet_size = config.alphabet_size
108
105
  # Temperature is now managed by TemperatureOperator via self._temperature
@@ -32,9 +32,9 @@ from diffbio.core.base_operators import TemperatureOperator
32
32
  from diffbio.utils.nn_utils import (
33
33
  ARTIFEX_GELU_MLP_KWARGS,
34
34
  ARTIFEX_GELU_NO_OUTPUT_MLP_KWARGS,
35
- ensure_rngs,
36
35
  )
37
36
 
37
+
38
38
  logger = logging.getLogger(__name__)
39
39
 
40
40
 
@@ -220,7 +220,7 @@ class SoftProgressiveMSA(TemperatureOperator):
220
220
  self,
221
221
  config: SoftProgressiveMSAConfig,
222
222
  *,
223
- rngs: nnx.Rngs | None = None,
223
+ rngs: nnx.Rngs,
224
224
  name: str | None = None,
225
225
  ):
226
226
  """Initialize the soft progressive MSA operator.
@@ -232,8 +232,6 @@ class SoftProgressiveMSA(TemperatureOperator):
232
232
  """
233
233
  super().__init__(config, rngs=rngs, name=name)
234
234
 
235
- rngs = ensure_rngs(rngs)
236
-
237
235
  self.hidden_dim = config.hidden_dim
238
236
  # Temperature is now managed by TemperatureOperator via self._temperature
239
237
  self.alphabet_size = config.alphabet_size
@@ -97,7 +97,7 @@ class GNNAssemblyNavigator(GraphOperator):
97
97
  self,
98
98
  config: GNNAssemblyNavigatorConfig,
99
99
  *,
100
- rngs: nnx.Rngs | None = None,
100
+ rngs: nnx.Rngs,
101
101
  name: str | None = None,
102
102
  ):
103
103
  """Initialize the GNN assembly navigator.
@@ -109,9 +109,6 @@ class GNNAssemblyNavigator(GraphOperator):
109
109
  """
110
110
  super().__init__(config, rngs=rngs, name=name)
111
111
 
112
- if rngs is None:
113
- rngs = nnx.Rngs(0)
114
-
115
112
  self.hidden_dim = config.hidden_dim
116
113
 
117
114
  # Temperature management (similar to TemperatureOperator pattern)
@@ -7,7 +7,7 @@ import jax.numpy as jnp
7
7
  from flax import nnx
8
8
 
9
9
  from diffbio.operators.drug_discovery.message_passing import StackedMessagePassing
10
- from diffbio.utils.nn_utils import ensure_rngs
10
+
11
11
 
12
12
  logger = logging.getLogger(__name__)
13
13
 
@@ -44,7 +44,7 @@ def _require_config_attr(config: Any, attr: str) -> Any:
44
44
  def initialize_graph_encoder(
45
45
  module: Any,
46
46
  *,
47
- rngs: nnx.Rngs | None,
47
+ rngs: nnx.Rngs,
48
48
  hidden_dim: int,
49
49
  num_layers: int,
50
50
  in_features: int,
@@ -52,7 +52,6 @@ def initialize_graph_encoder(
52
52
  attr: str = "encoder",
53
53
  ) -> nnx.Rngs:
54
54
  """Ensure RNGs and attach a message-passing encoder."""
55
- resolved_rngs = ensure_rngs(rngs)
56
55
  setattr(
57
56
  module,
58
57
  attr,
@@ -60,18 +59,18 @@ def initialize_graph_encoder(
60
59
  hidden_dim=hidden_dim,
61
60
  num_layers=num_layers,
62
61
  in_features=in_features,
63
- rngs=resolved_rngs,
62
+ rngs=rngs,
64
63
  num_edge_features=num_edge_features,
65
64
  ),
66
65
  )
67
- return resolved_rngs
66
+ return rngs
68
67
 
69
68
 
70
69
  def initialize_graph_encoder_from_config(
71
70
  module: Any,
72
71
  config: Any,
73
72
  *,
74
- rngs: nnx.Rngs | None,
73
+ rngs: nnx.Rngs,
75
74
  num_layers_attr: str = "num_message_passing_steps",
76
75
  hidden_dim_attr: str = "hidden_dim",
77
76
  in_features_attr: str = "in_features",
@@ -161,7 +161,7 @@ class ADMETPredictor(OperatorModule):
161
161
  self,
162
162
  config: ADMETConfig,
163
163
  *,
164
- rngs: nnx.Rngs | None = None,
164
+ rngs: nnx.Rngs,
165
165
  name: str | None = None,
166
166
  ):
167
167
  """Initialize ADMET predictor.
@@ -221,7 +221,7 @@ class AttentiveFP(OperatorModule):
221
221
  self,
222
222
  config: AttentiveFPConfig,
223
223
  *,
224
- rngs: nnx.Rngs | None = None,
224
+ rngs: nnx.Rngs,
225
225
  ):
226
226
  """Initialize AttentiveFP.
227
227
 
@@ -231,9 +231,6 @@ class AttentiveFP(OperatorModule):
231
231
  """
232
232
  super().__init__(config, rngs=rngs)
233
233
 
234
- if rngs is None:
235
- rngs = nnx.Rngs(0)
236
-
237
234
  # Initial linear projection
238
235
  self.input_proj = nnx.Linear(config.in_features, config.hidden_dim, rngs=rngs)
239
236
 
@@ -105,12 +105,10 @@ class DifferentiableDTIPipeline(nnx.Module):
105
105
  self,
106
106
  config: DTIPipelineConfig,
107
107
  *,
108
- rngs: nnx.Rngs | None = None,
108
+ rngs: nnx.Rngs,
109
109
  ) -> None:
110
110
  """Initialize protein encoder, drug encoder, and pair scorer."""
111
111
  super().__init__()
112
- if rngs is None:
113
- rngs = nnx.Rngs(0)
114
112
 
115
113
  self.config = nnx.static(config)
116
114
  self.protein_encoder = TransformerSequenceEncoder(