diffbio 0.1.0__py3-none-any.whl

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 (202) hide show
  1. diffbio/__init__.py +39 -0
  2. diffbio/configs.py +75 -0
  3. diffbio/constants.py +204 -0
  4. diffbio/core/__init__.py +127 -0
  5. diffbio/core/base_operators.py +612 -0
  6. diffbio/core/data_types.py +260 -0
  7. diffbio/core/gnn_components.py +629 -0
  8. diffbio/core/graph_utils.py +149 -0
  9. diffbio/core/neural_components.py +270 -0
  10. diffbio/core/optimal_transport.py +133 -0
  11. diffbio/core/soft_ops/__init__.py +216 -0
  12. diffbio/core/soft_ops/_projections_permutahedron.py +1864 -0
  13. diffbio/core/soft_ops/_projections_simplex.py +240 -0
  14. diffbio/core/soft_ops/_projections_transport.py +508 -0
  15. diffbio/core/soft_ops/_sorting_network.py +204 -0
  16. diffbio/core/soft_ops/_types.py +15 -0
  17. diffbio/core/soft_ops/_utils.py +342 -0
  18. diffbio/core/soft_ops/autograd_safe.py +120 -0
  19. diffbio/core/soft_ops/comparison.py +235 -0
  20. diffbio/core/soft_ops/elementwise.py +309 -0
  21. diffbio/core/soft_ops/logical.py +146 -0
  22. diffbio/core/soft_ops/quantile.py +376 -0
  23. diffbio/core/soft_ops/selection.py +236 -0
  24. diffbio/core/soft_ops/sorting.py +926 -0
  25. diffbio/core/soft_ops/straight_through.py +261 -0
  26. diffbio/core/uncertainty.py +279 -0
  27. diffbio/evaluation/__init__.py +42 -0
  28. diffbio/evaluation/adapters.py +409 -0
  29. diffbio/evaluation/graders.py +223 -0
  30. diffbio/evaluation/problem.py +157 -0
  31. diffbio/evaluation/runner.py +277 -0
  32. diffbio/losses/__init__.py +59 -0
  33. diffbio/losses/alignment_losses.py +222 -0
  34. diffbio/losses/biological_regularization.py +288 -0
  35. diffbio/losses/metric_losses.py +139 -0
  36. diffbio/losses/singlecell_losses.py +387 -0
  37. diffbio/losses/statistical_losses.py +345 -0
  38. diffbio/operators/__init__.py +60 -0
  39. diffbio/operators/_count_vae.py +197 -0
  40. diffbio/operators/_loss_balancing.py +65 -0
  41. diffbio/operators/_masked_gene_transformer.py +118 -0
  42. diffbio/operators/_transformer_validation.py +50 -0
  43. diffbio/operators/alignment/__init__.py +51 -0
  44. diffbio/operators/alignment/profile_hmm.py +350 -0
  45. diffbio/operators/alignment/scoring.py +127 -0
  46. diffbio/operators/alignment/smith_waterman.py +261 -0
  47. diffbio/operators/alignment/soft_msa.py +419 -0
  48. diffbio/operators/assembly/__init__.py +27 -0
  49. diffbio/operators/assembly/gnn_assembly.py +252 -0
  50. diffbio/operators/assembly/metagenomic_binning.py +296 -0
  51. diffbio/operators/crispr/__init__.py +17 -0
  52. diffbio/operators/crispr/guide_scoring.py +269 -0
  53. diffbio/operators/drug_discovery/__init__.py +133 -0
  54. diffbio/operators/drug_discovery/_graph_utils.py +142 -0
  55. diffbio/operators/drug_discovery/admet_predictor.py +285 -0
  56. diffbio/operators/drug_discovery/attentive_fp.py +411 -0
  57. diffbio/operators/drug_discovery/dti.py +261 -0
  58. diffbio/operators/drug_discovery/fingerprint.py +490 -0
  59. diffbio/operators/drug_discovery/maccs_keys.py +267 -0
  60. diffbio/operators/drug_discovery/message_passing.py +200 -0
  61. diffbio/operators/drug_discovery/primitives.py +242 -0
  62. diffbio/operators/drug_discovery/property_predictor.py +163 -0
  63. diffbio/operators/drug_discovery/similarity.py +193 -0
  64. diffbio/operators/epigenomics/__init__.py +35 -0
  65. diffbio/operators/epigenomics/chromatin_state.py +491 -0
  66. diffbio/operators/epigenomics/contextual.py +288 -0
  67. diffbio/operators/epigenomics/fno_peak_calling.py +153 -0
  68. diffbio/operators/epigenomics/peak_calling.py +555 -0
  69. diffbio/operators/foundation_models/__init__.py +119 -0
  70. diffbio/operators/foundation_models/adapters.py +114 -0
  71. diffbio/operators/foundation_models/contracts.py +245 -0
  72. diffbio/operators/foundation_models/embedding_probe.py +83 -0
  73. diffbio/operators/foundation_models/experimental.py +128 -0
  74. diffbio/operators/foundation_models/foundation_model.py +332 -0
  75. diffbio/operators/foundation_models/frozen.py +59 -0
  76. diffbio/operators/foundation_models/precomputed.py +270 -0
  77. diffbio/operators/foundation_models/transformer_encoder.py +564 -0
  78. diffbio/operators/mapping/__init__.py +17 -0
  79. diffbio/operators/mapping/neural_mapper.py +493 -0
  80. diffbio/operators/metabolomics/__init__.py +39 -0
  81. diffbio/operators/metabolomics/spectral_similarity.py +315 -0
  82. diffbio/operators/molecular_dynamics/__init__.py +51 -0
  83. diffbio/operators/molecular_dynamics/force_field.py +265 -0
  84. diffbio/operators/molecular_dynamics/integrator.py +304 -0
  85. diffbio/operators/molecular_dynamics/primitives.py +115 -0
  86. diffbio/operators/multiomics/__init__.py +38 -0
  87. diffbio/operators/multiomics/hic_contact.py +377 -0
  88. diffbio/operators/multiomics/multiomics_vae.py +325 -0
  89. diffbio/operators/multiomics/spatial_deconvolution.py +316 -0
  90. diffbio/operators/multiomics/spatial_gene_detection.py +493 -0
  91. diffbio/operators/normalization/__init__.py +42 -0
  92. diffbio/operators/normalization/embedding.py +222 -0
  93. diffbio/operators/normalization/phate.py +400 -0
  94. diffbio/operators/normalization/umap.py +261 -0
  95. diffbio/operators/normalization/vae_normalizer.py +258 -0
  96. diffbio/operators/population/__init__.py +17 -0
  97. diffbio/operators/population/ancestry_estimation.py +274 -0
  98. diffbio/operators/preprocessing/__init__.py +76 -0
  99. diffbio/operators/preprocessing/adapter_removal.py +311 -0
  100. diffbio/operators/preprocessing/duplicate_filter.py +317 -0
  101. diffbio/operators/preprocessing/error_correction.py +287 -0
  102. diffbio/operators/protein/__init__.py +31 -0
  103. diffbio/operators/protein/secondary_structure.py +509 -0
  104. diffbio/operators/quality_filter.py +128 -0
  105. diffbio/operators/rna_structure/__init__.py +35 -0
  106. diffbio/operators/rna_structure/rna_folding.py +509 -0
  107. diffbio/operators/rnaseq/__init__.py +23 -0
  108. diffbio/operators/rnaseq/motif_discovery.py +251 -0
  109. diffbio/operators/rnaseq/splicing_psi.py +216 -0
  110. diffbio/operators/singlecell/__init__.py +193 -0
  111. diffbio/operators/singlecell/ambient_removal.py +333 -0
  112. diffbio/operators/singlecell/archetypes.py +191 -0
  113. diffbio/operators/singlecell/batch_correction.py +288 -0
  114. diffbio/operators/singlecell/cell_annotation.py +519 -0
  115. diffbio/operators/singlecell/communication.py +704 -0
  116. diffbio/operators/singlecell/differential_distribution.py +243 -0
  117. diffbio/operators/singlecell/doublet_detection.py +657 -0
  118. diffbio/operators/singlecell/downsampling.py +166 -0
  119. diffbio/operators/singlecell/enhanced_batch_correction.py +519 -0
  120. diffbio/operators/singlecell/grn_inference.py +336 -0
  121. diffbio/operators/singlecell/imputation.py +429 -0
  122. diffbio/operators/singlecell/knockdown_filter.py +176 -0
  123. diffbio/operators/singlecell/ot_trajectory.py +277 -0
  124. diffbio/operators/singlecell/simulation.py +444 -0
  125. diffbio/operators/singlecell/sindy_grn.py +247 -0
  126. diffbio/operators/singlecell/soft_clustering.py +211 -0
  127. diffbio/operators/singlecell/spatial_domains.py +677 -0
  128. diffbio/operators/singlecell/switch_de.py +184 -0
  129. diffbio/operators/singlecell/trajectory.py +447 -0
  130. diffbio/operators/singlecell/velocity.py +361 -0
  131. diffbio/operators/statistical/__init__.py +35 -0
  132. diffbio/operators/statistical/em_quantification.py +260 -0
  133. diffbio/operators/statistical/hmm.py +234 -0
  134. diffbio/operators/statistical/nb_glm.py +272 -0
  135. diffbio/operators/variant/__init__.py +64 -0
  136. diffbio/operators/variant/classifier.py +333 -0
  137. diffbio/operators/variant/cnn_classifier.py +255 -0
  138. diffbio/operators/variant/cnv_segmentation.py +678 -0
  139. diffbio/operators/variant/deepvariant_pileup.py +426 -0
  140. diffbio/operators/variant/pileup.py +240 -0
  141. diffbio/operators/variant/quality_recalibration.py +274 -0
  142. diffbio/pipelines/__init__.py +65 -0
  143. diffbio/pipelines/differential_expression.py +279 -0
  144. diffbio/pipelines/enhanced_variant_calling.py +326 -0
  145. diffbio/pipelines/perturbation.py +407 -0
  146. diffbio/pipelines/preprocessing.py +267 -0
  147. diffbio/pipelines/single_cell.py +366 -0
  148. diffbio/pipelines/variant_calling.py +490 -0
  149. diffbio/samplers/__init__.py +9 -0
  150. diffbio/samplers/perturbation_sampler.py +142 -0
  151. diffbio/sequences/__init__.py +34 -0
  152. diffbio/sequences/dna.py +239 -0
  153. diffbio/sources/__init__.py +149 -0
  154. diffbio/sources/_anndata_shared.py +89 -0
  155. diffbio/sources/_batch_iteration.py +37 -0
  156. diffbio/sources/_benchmark_source.py +152 -0
  157. diffbio/sources/_indexed_batch_source.py +38 -0
  158. diffbio/sources/_utils.py +45 -0
  159. diffbio/sources/anndata_interop.py +387 -0
  160. diffbio/sources/anndata_source.py +361 -0
  161. diffbio/sources/archive_ii.py +174 -0
  162. diffbio/sources/balifam.py +207 -0
  163. diffbio/sources/bam.py +265 -0
  164. diffbio/sources/bengrn_ground_truth.py +306 -0
  165. diffbio/sources/contextual_epigenomics.py +242 -0
  166. diffbio/sources/dti.py +359 -0
  167. diffbio/sources/embeddings.py +203 -0
  168. diffbio/sources/encode_peaks.py +223 -0
  169. diffbio/sources/fasta.py +226 -0
  170. diffbio/sources/immune_human.py +172 -0
  171. diffbio/sources/indexed_embeddings.py +128 -0
  172. diffbio/sources/indexed_view.py +191 -0
  173. diffbio/sources/molnet.py +493 -0
  174. diffbio/sources/multiomics.py +279 -0
  175. diffbio/sources/pancreas.py +108 -0
  176. diffbio/sources/perturbation/__init__.py +69 -0
  177. diffbio/sources/perturbation/_types.py +51 -0
  178. diffbio/sources/perturbation/_utils.py +125 -0
  179. diffbio/sources/perturbation/concat_source.py +115 -0
  180. diffbio/sources/perturbation/control_mapping.py +215 -0
  181. diffbio/sources/perturbation/experiment_config.py +261 -0
  182. diffbio/sources/perturbation/h5_metadata_cache.py +218 -0
  183. diffbio/sources/perturbation/output_space.py +52 -0
  184. diffbio/sources/perturbation/perturbation_source.py +513 -0
  185. diffbio/sources/seqfish.py +145 -0
  186. diffbio/sources/sequence_foundation.py +68 -0
  187. diffbio/sources/singlecell_foundation.py +68 -0
  188. diffbio/splitters/__init__.py +63 -0
  189. diffbio/splitters/base.py +251 -0
  190. diffbio/splitters/molecular.py +330 -0
  191. diffbio/splitters/perturbation.py +199 -0
  192. diffbio/splitters/random.py +217 -0
  193. diffbio/splitters/sequence.py +201 -0
  194. diffbio/utils/__init__.py +55 -0
  195. diffbio/utils/dependency_runtime.py +115 -0
  196. diffbio/utils/nn_utils.py +157 -0
  197. diffbio/utils/quality.py +45 -0
  198. diffbio/utils/training.py +585 -0
  199. diffbio-0.1.0.dist-info/METADATA +480 -0
  200. diffbio-0.1.0.dist-info/RECORD +202 -0
  201. diffbio-0.1.0.dist-info/WHEEL +4 -0
  202. diffbio-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,211 @@
1
+ """Soft K-Means clustering operator for single-cell analysis.
2
+
3
+ This module provides a differentiable implementation of soft k-means
4
+ clustering, enabling gradient-based learning of cluster centroids.
5
+
6
+ Key technique: Replace hard cluster assignment with softmax-based
7
+ soft assignments for fully differentiable clustering.
8
+
9
+ Applications: Cell type clustering, Leiden-like community detection.
10
+
11
+ Inherits from TemperatureOperator to get:
12
+
13
+ - _temperature property for temperature-controlled smoothing
14
+ - soft_max() for logsumexp-based smooth maximum
15
+ - soft_argmax() for soft position selection
16
+ """
17
+
18
+ import logging
19
+ from dataclasses import dataclass
20
+ from typing import Any
21
+
22
+ import jax
23
+ import jax.numpy as jnp
24
+ from datarax.core.config import OperatorConfig
25
+ from flax import nnx
26
+ from jaxtyping import Array, Float, Int, PyTree
27
+
28
+ from diffbio.core.base_operators import TemperatureOperator
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ class SoftClusteringConfig(OperatorConfig):
35
+ """Configuration for SoftKMeansClustering.
36
+
37
+ Attributes:
38
+ n_clusters: Number of clusters.
39
+ n_features: Dimensionality of input embeddings.
40
+ temperature: Temperature for softmax (lower = sharper).
41
+ learnable_centroids: Whether centroids are learnable parameters.
42
+ """
43
+
44
+ n_clusters: int = 10
45
+ n_features: int = 50
46
+ temperature: float = 1.0
47
+ learnable_centroids: bool = True
48
+
49
+
50
+ class SoftKMeansClustering(TemperatureOperator):
51
+ """Differentiable soft k-means clustering.
52
+
53
+ This operator implements soft k-means with learnable cluster centroids.
54
+ Instead of hard cluster assignments, cells are softly assigned to clusters
55
+ using softmax over negative squared distances.
56
+
57
+ Algorithm:
58
+ 1. Compute squared distances from cells to centroids
59
+ 2. Apply softmax for soft assignments: P(k|x) = softmax(-||x - c_k||² / T)
60
+ 3. Optionally update centroids based on weighted means
61
+
62
+ Inherits from TemperatureOperator to get:
63
+
64
+ - _temperature property for temperature-controlled smoothing
65
+ - soft_max() for logsumexp-based smooth maximum
66
+ - soft_argmax() for soft position selection
67
+
68
+ Args:
69
+ config: SoftClusteringConfig with model parameters.
70
+ rngs: Flax NNX random number generators.
71
+ name: Optional operator name.
72
+
73
+ Example:
74
+ ```python
75
+ config = SoftClusteringConfig(n_clusters=10, n_features=50)
76
+ clusterer = SoftKMeansClustering(config, rngs=nnx.Rngs(42))
77
+ data = {"embeddings": cell_embeddings}
78
+ result, state, meta = clusterer.apply(data, {}, None)
79
+ ```
80
+ """
81
+
82
+ def __init__(
83
+ self,
84
+ config: SoftClusteringConfig,
85
+ *,
86
+ rngs: nnx.Rngs | None = None,
87
+ name: str | None = None,
88
+ ):
89
+ """Initialize the soft k-means clustering operator.
90
+
91
+ Args:
92
+ config: Clustering configuration.
93
+ rngs: Random number generators for initialization.
94
+ name: Optional operator name.
95
+ """
96
+ super().__init__(config, rngs=rngs, name=name)
97
+
98
+ rngs = rngs or nnx.Rngs(0)
99
+ self.cluster_shape = nnx.static((config.n_clusters, config.n_features))
100
+ self.n_clusters, self.n_features = self.cluster_shape
101
+ # Temperature is now managed by TemperatureOperator via self._temperature
102
+
103
+ # Initialize cluster centroids
104
+ key = rngs.params()
105
+ init_centroids = jax.random.normal(key, self.cluster_shape) * 0.1
106
+ self.centroids = nnx.Param(init_centroids)
107
+
108
+ def compute_distances(
109
+ self,
110
+ embeddings: Float[Array, "n_cells n_features"],
111
+ ) -> Float[Array, "n_cells n_clusters"]:
112
+ """Compute squared distances from cells to centroids.
113
+
114
+ Args:
115
+ embeddings: Cell embedding vectors.
116
+
117
+ Returns:
118
+ Squared Euclidean distances to each centroid.
119
+ """
120
+ centroids = self.centroids[...] # (n_clusters, n_features)
121
+
122
+ # Efficient distance computation using expansion
123
+ # ||x - c||² = ||x||² + ||c||² - 2 * x · c
124
+ emb_sq = jnp.sum(embeddings**2, axis=-1, keepdims=True) # (n_cells, 1)
125
+ cent_sq = jnp.sum(centroids**2, axis=-1) # (n_clusters,)
126
+ dot_product = jnp.einsum("nf,kf->nk", embeddings, centroids) # (n_cells, n_clusters)
127
+
128
+ distances_sq = emb_sq + cent_sq - 2 * dot_product
129
+
130
+ return distances_sq
131
+
132
+ def compute_assignments(
133
+ self,
134
+ embeddings: Float[Array, "n_cells n_features"],
135
+ ) -> Float[Array, "n_cells n_clusters"]:
136
+ """Compute soft cluster assignments.
137
+
138
+ Args:
139
+ embeddings: Cell embedding vectors.
140
+
141
+ Returns:
142
+ Soft assignment probabilities for each cluster.
143
+ """
144
+ distances_sq = self.compute_distances(embeddings)
145
+
146
+ # Soft assignments via softmax over negative distances
147
+ # Use inherited _temperature property from TemperatureOperator
148
+ assignments = jax.nn.softmax(-distances_sq / self._temperature, axis=-1)
149
+
150
+ return assignments
151
+
152
+ def get_hard_labels(
153
+ self,
154
+ assignments: Float[Array, "n_cells n_clusters"],
155
+ ) -> Int[Array, "n_cells"]:
156
+ """Get hard cluster labels from soft assignments.
157
+
158
+ Args:
159
+ assignments: Soft cluster assignments.
160
+
161
+ Returns:
162
+ Hard cluster labels (argmax).
163
+ """
164
+ return jnp.argmax(assignments, axis=-1)
165
+
166
+ def apply(
167
+ self,
168
+ data: PyTree,
169
+ state: PyTree,
170
+ metadata: dict[str, Any] | None,
171
+ random_params: Any = None,
172
+ stats: dict[str, Any] | None = None,
173
+ ) -> tuple[PyTree, PyTree, dict[str, Any] | None]:
174
+ """Apply soft k-means clustering to cell embeddings.
175
+
176
+ Args:
177
+ data: Dictionary containing:
178
+ - "embeddings": Cell embeddings (n_cells, n_features)
179
+ state: Element state (passed through unchanged)
180
+ metadata: Element metadata (passed through unchanged)
181
+ random_params: Not used
182
+ stats: Not used
183
+
184
+ Returns:
185
+ Tuple of (transformed_data, state, metadata):
186
+ - transformed_data contains:
187
+
188
+ - "embeddings": Original embeddings
189
+ - "cluster_assignments": Soft assignment probabilities
190
+ - "cluster_labels": Hard cluster labels
191
+ - "centroids": Cluster centroid positions
192
+ - state is passed through unchanged
193
+ - metadata is passed through unchanged
194
+ """
195
+ embeddings = data["embeddings"]
196
+
197
+ # Compute soft assignments
198
+ assignments = self.compute_assignments(embeddings)
199
+
200
+ # Get hard labels
201
+ labels = self.get_hard_labels(assignments)
202
+
203
+ # Build output data
204
+ transformed_data = {
205
+ "embeddings": embeddings,
206
+ "cluster_assignments": assignments,
207
+ "cluster_labels": labels,
208
+ "centroids": self.centroids[...],
209
+ }
210
+
211
+ return transformed_data, state, metadata