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.
- diffbio/__init__.py +39 -0
- diffbio/configs.py +75 -0
- diffbio/constants.py +204 -0
- diffbio/core/__init__.py +127 -0
- diffbio/core/base_operators.py +612 -0
- diffbio/core/data_types.py +260 -0
- diffbio/core/gnn_components.py +629 -0
- diffbio/core/graph_utils.py +149 -0
- diffbio/core/neural_components.py +270 -0
- diffbio/core/optimal_transport.py +133 -0
- diffbio/core/soft_ops/__init__.py +216 -0
- diffbio/core/soft_ops/_projections_permutahedron.py +1864 -0
- diffbio/core/soft_ops/_projections_simplex.py +240 -0
- diffbio/core/soft_ops/_projections_transport.py +508 -0
- diffbio/core/soft_ops/_sorting_network.py +204 -0
- diffbio/core/soft_ops/_types.py +15 -0
- diffbio/core/soft_ops/_utils.py +342 -0
- diffbio/core/soft_ops/autograd_safe.py +120 -0
- diffbio/core/soft_ops/comparison.py +235 -0
- diffbio/core/soft_ops/elementwise.py +309 -0
- diffbio/core/soft_ops/logical.py +146 -0
- diffbio/core/soft_ops/quantile.py +376 -0
- diffbio/core/soft_ops/selection.py +236 -0
- diffbio/core/soft_ops/sorting.py +926 -0
- diffbio/core/soft_ops/straight_through.py +261 -0
- diffbio/core/uncertainty.py +279 -0
- diffbio/evaluation/__init__.py +42 -0
- diffbio/evaluation/adapters.py +409 -0
- diffbio/evaluation/graders.py +223 -0
- diffbio/evaluation/problem.py +157 -0
- diffbio/evaluation/runner.py +277 -0
- diffbio/losses/__init__.py +59 -0
- diffbio/losses/alignment_losses.py +222 -0
- diffbio/losses/biological_regularization.py +288 -0
- diffbio/losses/metric_losses.py +139 -0
- diffbio/losses/singlecell_losses.py +387 -0
- diffbio/losses/statistical_losses.py +345 -0
- diffbio/operators/__init__.py +60 -0
- diffbio/operators/_count_vae.py +197 -0
- diffbio/operators/_loss_balancing.py +65 -0
- diffbio/operators/_masked_gene_transformer.py +118 -0
- diffbio/operators/_transformer_validation.py +50 -0
- diffbio/operators/alignment/__init__.py +51 -0
- diffbio/operators/alignment/profile_hmm.py +350 -0
- diffbio/operators/alignment/scoring.py +127 -0
- diffbio/operators/alignment/smith_waterman.py +261 -0
- diffbio/operators/alignment/soft_msa.py +419 -0
- diffbio/operators/assembly/__init__.py +27 -0
- diffbio/operators/assembly/gnn_assembly.py +252 -0
- diffbio/operators/assembly/metagenomic_binning.py +296 -0
- diffbio/operators/crispr/__init__.py +17 -0
- diffbio/operators/crispr/guide_scoring.py +269 -0
- diffbio/operators/drug_discovery/__init__.py +133 -0
- diffbio/operators/drug_discovery/_graph_utils.py +142 -0
- diffbio/operators/drug_discovery/admet_predictor.py +285 -0
- diffbio/operators/drug_discovery/attentive_fp.py +411 -0
- diffbio/operators/drug_discovery/dti.py +261 -0
- diffbio/operators/drug_discovery/fingerprint.py +490 -0
- diffbio/operators/drug_discovery/maccs_keys.py +267 -0
- diffbio/operators/drug_discovery/message_passing.py +200 -0
- diffbio/operators/drug_discovery/primitives.py +242 -0
- diffbio/operators/drug_discovery/property_predictor.py +163 -0
- diffbio/operators/drug_discovery/similarity.py +193 -0
- diffbio/operators/epigenomics/__init__.py +35 -0
- diffbio/operators/epigenomics/chromatin_state.py +491 -0
- diffbio/operators/epigenomics/contextual.py +288 -0
- diffbio/operators/epigenomics/fno_peak_calling.py +153 -0
- diffbio/operators/epigenomics/peak_calling.py +555 -0
- diffbio/operators/foundation_models/__init__.py +119 -0
- diffbio/operators/foundation_models/adapters.py +114 -0
- diffbio/operators/foundation_models/contracts.py +245 -0
- diffbio/operators/foundation_models/embedding_probe.py +83 -0
- diffbio/operators/foundation_models/experimental.py +128 -0
- diffbio/operators/foundation_models/foundation_model.py +332 -0
- diffbio/operators/foundation_models/frozen.py +59 -0
- diffbio/operators/foundation_models/precomputed.py +270 -0
- diffbio/operators/foundation_models/transformer_encoder.py +564 -0
- diffbio/operators/mapping/__init__.py +17 -0
- diffbio/operators/mapping/neural_mapper.py +493 -0
- diffbio/operators/metabolomics/__init__.py +39 -0
- diffbio/operators/metabolomics/spectral_similarity.py +315 -0
- diffbio/operators/molecular_dynamics/__init__.py +51 -0
- diffbio/operators/molecular_dynamics/force_field.py +265 -0
- diffbio/operators/molecular_dynamics/integrator.py +304 -0
- diffbio/operators/molecular_dynamics/primitives.py +115 -0
- diffbio/operators/multiomics/__init__.py +38 -0
- diffbio/operators/multiomics/hic_contact.py +377 -0
- diffbio/operators/multiomics/multiomics_vae.py +325 -0
- diffbio/operators/multiomics/spatial_deconvolution.py +316 -0
- diffbio/operators/multiomics/spatial_gene_detection.py +493 -0
- diffbio/operators/normalization/__init__.py +42 -0
- diffbio/operators/normalization/embedding.py +222 -0
- diffbio/operators/normalization/phate.py +400 -0
- diffbio/operators/normalization/umap.py +261 -0
- diffbio/operators/normalization/vae_normalizer.py +258 -0
- diffbio/operators/population/__init__.py +17 -0
- diffbio/operators/population/ancestry_estimation.py +274 -0
- diffbio/operators/preprocessing/__init__.py +76 -0
- diffbio/operators/preprocessing/adapter_removal.py +311 -0
- diffbio/operators/preprocessing/duplicate_filter.py +317 -0
- diffbio/operators/preprocessing/error_correction.py +287 -0
- diffbio/operators/protein/__init__.py +31 -0
- diffbio/operators/protein/secondary_structure.py +509 -0
- diffbio/operators/quality_filter.py +128 -0
- diffbio/operators/rna_structure/__init__.py +35 -0
- diffbio/operators/rna_structure/rna_folding.py +509 -0
- diffbio/operators/rnaseq/__init__.py +23 -0
- diffbio/operators/rnaseq/motif_discovery.py +251 -0
- diffbio/operators/rnaseq/splicing_psi.py +216 -0
- diffbio/operators/singlecell/__init__.py +193 -0
- diffbio/operators/singlecell/ambient_removal.py +333 -0
- diffbio/operators/singlecell/archetypes.py +191 -0
- diffbio/operators/singlecell/batch_correction.py +288 -0
- diffbio/operators/singlecell/cell_annotation.py +519 -0
- diffbio/operators/singlecell/communication.py +704 -0
- diffbio/operators/singlecell/differential_distribution.py +243 -0
- diffbio/operators/singlecell/doublet_detection.py +657 -0
- diffbio/operators/singlecell/downsampling.py +166 -0
- diffbio/operators/singlecell/enhanced_batch_correction.py +519 -0
- diffbio/operators/singlecell/grn_inference.py +336 -0
- diffbio/operators/singlecell/imputation.py +429 -0
- diffbio/operators/singlecell/knockdown_filter.py +176 -0
- diffbio/operators/singlecell/ot_trajectory.py +277 -0
- diffbio/operators/singlecell/simulation.py +444 -0
- diffbio/operators/singlecell/sindy_grn.py +247 -0
- diffbio/operators/singlecell/soft_clustering.py +211 -0
- diffbio/operators/singlecell/spatial_domains.py +677 -0
- diffbio/operators/singlecell/switch_de.py +184 -0
- diffbio/operators/singlecell/trajectory.py +447 -0
- diffbio/operators/singlecell/velocity.py +361 -0
- diffbio/operators/statistical/__init__.py +35 -0
- diffbio/operators/statistical/em_quantification.py +260 -0
- diffbio/operators/statistical/hmm.py +234 -0
- diffbio/operators/statistical/nb_glm.py +272 -0
- diffbio/operators/variant/__init__.py +64 -0
- diffbio/operators/variant/classifier.py +333 -0
- diffbio/operators/variant/cnn_classifier.py +255 -0
- diffbio/operators/variant/cnv_segmentation.py +678 -0
- diffbio/operators/variant/deepvariant_pileup.py +426 -0
- diffbio/operators/variant/pileup.py +240 -0
- diffbio/operators/variant/quality_recalibration.py +274 -0
- diffbio/pipelines/__init__.py +65 -0
- diffbio/pipelines/differential_expression.py +279 -0
- diffbio/pipelines/enhanced_variant_calling.py +326 -0
- diffbio/pipelines/perturbation.py +407 -0
- diffbio/pipelines/preprocessing.py +267 -0
- diffbio/pipelines/single_cell.py +366 -0
- diffbio/pipelines/variant_calling.py +490 -0
- diffbio/samplers/__init__.py +9 -0
- diffbio/samplers/perturbation_sampler.py +142 -0
- diffbio/sequences/__init__.py +34 -0
- diffbio/sequences/dna.py +239 -0
- diffbio/sources/__init__.py +149 -0
- diffbio/sources/_anndata_shared.py +89 -0
- diffbio/sources/_batch_iteration.py +37 -0
- diffbio/sources/_benchmark_source.py +152 -0
- diffbio/sources/_indexed_batch_source.py +38 -0
- diffbio/sources/_utils.py +45 -0
- diffbio/sources/anndata_interop.py +387 -0
- diffbio/sources/anndata_source.py +361 -0
- diffbio/sources/archive_ii.py +174 -0
- diffbio/sources/balifam.py +207 -0
- diffbio/sources/bam.py +265 -0
- diffbio/sources/bengrn_ground_truth.py +306 -0
- diffbio/sources/contextual_epigenomics.py +242 -0
- diffbio/sources/dti.py +359 -0
- diffbio/sources/embeddings.py +203 -0
- diffbio/sources/encode_peaks.py +223 -0
- diffbio/sources/fasta.py +226 -0
- diffbio/sources/immune_human.py +172 -0
- diffbio/sources/indexed_embeddings.py +128 -0
- diffbio/sources/indexed_view.py +191 -0
- diffbio/sources/molnet.py +493 -0
- diffbio/sources/multiomics.py +279 -0
- diffbio/sources/pancreas.py +108 -0
- diffbio/sources/perturbation/__init__.py +69 -0
- diffbio/sources/perturbation/_types.py +51 -0
- diffbio/sources/perturbation/_utils.py +125 -0
- diffbio/sources/perturbation/concat_source.py +115 -0
- diffbio/sources/perturbation/control_mapping.py +215 -0
- diffbio/sources/perturbation/experiment_config.py +261 -0
- diffbio/sources/perturbation/h5_metadata_cache.py +218 -0
- diffbio/sources/perturbation/output_space.py +52 -0
- diffbio/sources/perturbation/perturbation_source.py +513 -0
- diffbio/sources/seqfish.py +145 -0
- diffbio/sources/sequence_foundation.py +68 -0
- diffbio/sources/singlecell_foundation.py +68 -0
- diffbio/splitters/__init__.py +63 -0
- diffbio/splitters/base.py +251 -0
- diffbio/splitters/molecular.py +330 -0
- diffbio/splitters/perturbation.py +199 -0
- diffbio/splitters/random.py +217 -0
- diffbio/splitters/sequence.py +201 -0
- diffbio/utils/__init__.py +55 -0
- diffbio/utils/dependency_runtime.py +115 -0
- diffbio/utils/nn_utils.py +157 -0
- diffbio/utils/quality.py +45 -0
- diffbio/utils/training.py +585 -0
- diffbio-0.1.0.dist-info/METADATA +480 -0
- diffbio-0.1.0.dist-info/RECORD +202 -0
- diffbio-0.1.0.dist-info/WHEEL +4 -0
- diffbio-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"""Spatial transcriptomics deconvolution operator.
|
|
2
|
+
|
|
3
|
+
This module provides differentiable cell type deconvolution for
|
|
4
|
+
spatial transcriptomics data.
|
|
5
|
+
|
|
6
|
+
Key technique: Uses neural network to learn spot embeddings that account
|
|
7
|
+
for spatial context, then performs soft assignment to reference cell type
|
|
8
|
+
profiles using attention mechanisms.
|
|
9
|
+
|
|
10
|
+
Applications: Cell type mapping in spatial transcriptomics, tissue
|
|
11
|
+
composition analysis, spatial cell-cell interaction studies.
|
|
12
|
+
|
|
13
|
+
Inherits from TemperatureOperator to get:
|
|
14
|
+
|
|
15
|
+
- _temperature property for temperature-controlled smoothing
|
|
16
|
+
- soft_max() for logsumexp-based smooth maximum
|
|
17
|
+
- soft_argmax() for soft position selection
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import logging
|
|
21
|
+
from dataclasses import dataclass
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
24
|
+
import jax
|
|
25
|
+
import jax.numpy as jnp
|
|
26
|
+
from artifex.generative_models.core.base import MLP
|
|
27
|
+
from datarax.core.config import OperatorConfig
|
|
28
|
+
from flax import nnx
|
|
29
|
+
from jaxtyping import Array, Float, PyTree
|
|
30
|
+
|
|
31
|
+
from diffbio.core.base_operators import TemperatureOperator
|
|
32
|
+
from diffbio.utils.nn_utils import ARTIFEX_GELU_MLP_KWARGS, ARTIFEX_GELU_NO_OUTPUT_MLP_KWARGS
|
|
33
|
+
|
|
34
|
+
logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True)
|
|
38
|
+
class SpatialDeconvolutionConfig(OperatorConfig):
|
|
39
|
+
"""Configuration for SpatialDeconvolution.
|
|
40
|
+
|
|
41
|
+
Attributes:
|
|
42
|
+
n_genes: Number of genes in expression profiles.
|
|
43
|
+
n_cell_types: Number of reference cell types.
|
|
44
|
+
hidden_dim: Hidden dimension for neural networks.
|
|
45
|
+
num_layers: Number of encoder layers.
|
|
46
|
+
spatial_hidden: Hidden dimension for spatial encoder.
|
|
47
|
+
dropout_rate: Dropout rate for regularization.
|
|
48
|
+
temperature: Temperature for softmax operations.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
n_genes: int = 2000
|
|
52
|
+
n_cell_types: int = 10
|
|
53
|
+
hidden_dim: int = 128
|
|
54
|
+
num_layers: int = 2
|
|
55
|
+
spatial_hidden: int = 32
|
|
56
|
+
dropout_rate: float = 0.1
|
|
57
|
+
temperature: float = 1.0
|
|
58
|
+
|
|
59
|
+
def __post_init__(self) -> None:
|
|
60
|
+
"""Validate spatial deconvolution configuration."""
|
|
61
|
+
super().__post_init__()
|
|
62
|
+
if self.num_layers < 1:
|
|
63
|
+
raise ValueError("SpatialDeconvolutionConfig.num_layers must be at least 1.")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class SpotEncoder(nnx.Module):
|
|
67
|
+
"""Encoder for spatial spot expression profiles."""
|
|
68
|
+
|
|
69
|
+
def __init__(
|
|
70
|
+
self,
|
|
71
|
+
n_genes: int,
|
|
72
|
+
hidden_dim: int,
|
|
73
|
+
num_layers: int,
|
|
74
|
+
*,
|
|
75
|
+
rngs: nnx.Rngs,
|
|
76
|
+
):
|
|
77
|
+
"""Initialize the spot encoder.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
n_genes: Number of genes.
|
|
81
|
+
hidden_dim: Hidden dimension.
|
|
82
|
+
num_layers: Number of layers.
|
|
83
|
+
rngs: Random number generators.
|
|
84
|
+
"""
|
|
85
|
+
super().__init__()
|
|
86
|
+
self.backbone = MLP(
|
|
87
|
+
hidden_dims=[hidden_dim] * num_layers,
|
|
88
|
+
in_features=n_genes,
|
|
89
|
+
rngs=rngs,
|
|
90
|
+
**ARTIFEX_GELU_MLP_KWARGS,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def __call__(
|
|
94
|
+
self,
|
|
95
|
+
expression: Float[Array, "n_spots n_genes"],
|
|
96
|
+
) -> Float[Array, "n_spots hidden_dim"]:
|
|
97
|
+
"""Encode spot expression.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
expression: Spot expression matrix.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Spot embeddings.
|
|
104
|
+
"""
|
|
105
|
+
backbone_output = self.backbone(expression)
|
|
106
|
+
if isinstance(backbone_output, tuple):
|
|
107
|
+
raise TypeError("Spatial deconvolution spot backbone must return a single tensor.")
|
|
108
|
+
return backbone_output
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class SpatialEncoder(nnx.Module):
|
|
112
|
+
"""Encoder for spatial coordinates."""
|
|
113
|
+
|
|
114
|
+
def __init__(
|
|
115
|
+
self,
|
|
116
|
+
hidden_dim: int,
|
|
117
|
+
*,
|
|
118
|
+
rngs: nnx.Rngs,
|
|
119
|
+
):
|
|
120
|
+
"""Initialize the spatial encoder.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
hidden_dim: Hidden dimension.
|
|
124
|
+
rngs: Random number generators.
|
|
125
|
+
"""
|
|
126
|
+
super().__init__()
|
|
127
|
+
self.backbone = MLP(
|
|
128
|
+
hidden_dims=[hidden_dim, hidden_dim],
|
|
129
|
+
in_features=2,
|
|
130
|
+
rngs=rngs,
|
|
131
|
+
**ARTIFEX_GELU_NO_OUTPUT_MLP_KWARGS,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
def __call__(
|
|
135
|
+
self,
|
|
136
|
+
coordinates: Float[Array, "n_spots 2"],
|
|
137
|
+
) -> Float[Array, "n_spots hidden_dim"]:
|
|
138
|
+
"""Encode spatial coordinates.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
coordinates: Spot coordinates (x, y).
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Spatial embeddings.
|
|
145
|
+
"""
|
|
146
|
+
backbone_output = self.backbone(coordinates)
|
|
147
|
+
if isinstance(backbone_output, tuple):
|
|
148
|
+
raise TypeError("Spatial deconvolution spatial backbone must return a single tensor.")
|
|
149
|
+
return backbone_output
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class SpatialDeconvolution(TemperatureOperator):
|
|
153
|
+
"""Differentiable spatial transcriptomics deconvolution.
|
|
154
|
+
|
|
155
|
+
This operator performs cell type deconvolution of spatial
|
|
156
|
+
transcriptomics spots using reference single-cell profiles.
|
|
157
|
+
It incorporates spatial context through coordinate embeddings.
|
|
158
|
+
|
|
159
|
+
Algorithm:
|
|
160
|
+
1. Encode spot expression profiles
|
|
161
|
+
2. Encode spatial coordinates
|
|
162
|
+
3. Combine expression and spatial features
|
|
163
|
+
4. Compute attention to reference cell type profiles
|
|
164
|
+
5. Apply softmax for cell type proportions
|
|
165
|
+
6. Reconstruct expression from proportions
|
|
166
|
+
|
|
167
|
+
Inherits from TemperatureOperator to get:
|
|
168
|
+
|
|
169
|
+
- _temperature property for temperature-controlled smoothing
|
|
170
|
+
- soft_max() for logsumexp-based smooth maximum
|
|
171
|
+
- soft_argmax() for soft position selection
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
config: SpatialDeconvolutionConfig with model parameters.
|
|
175
|
+
rngs: Flax NNX random number generators.
|
|
176
|
+
name: Optional operator name.
|
|
177
|
+
|
|
178
|
+
Example:
|
|
179
|
+
```python
|
|
180
|
+
config = SpatialDeconvolutionConfig(n_cell_types=10)
|
|
181
|
+
deconv = SpatialDeconvolution(config, rngs=nnx.Rngs(42))
|
|
182
|
+
data = {"spot_expression": spots, "reference_profiles": refs, "coordinates": coords}
|
|
183
|
+
result, state, meta = deconv.apply(data, {}, None)
|
|
184
|
+
```
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
def __init__(
|
|
188
|
+
self,
|
|
189
|
+
config: SpatialDeconvolutionConfig,
|
|
190
|
+
*,
|
|
191
|
+
rngs: nnx.Rngs | None = None,
|
|
192
|
+
name: str | None = None,
|
|
193
|
+
):
|
|
194
|
+
"""Initialize the spatial deconvolution operator.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
config: Deconvolution configuration.
|
|
198
|
+
rngs: Random number generators for initialization.
|
|
199
|
+
name: Optional operator name.
|
|
200
|
+
"""
|
|
201
|
+
super().__init__(config, rngs=rngs, name=name)
|
|
202
|
+
|
|
203
|
+
if rngs is None:
|
|
204
|
+
rngs = nnx.Rngs(0)
|
|
205
|
+
|
|
206
|
+
self.hidden_dim = config.hidden_dim
|
|
207
|
+
# Temperature is now managed by TemperatureOperator via self._temperature
|
|
208
|
+
|
|
209
|
+
# Expression encoder
|
|
210
|
+
self.spot_encoder = SpotEncoder(
|
|
211
|
+
n_genes=config.n_genes,
|
|
212
|
+
hidden_dim=config.hidden_dim,
|
|
213
|
+
num_layers=config.num_layers,
|
|
214
|
+
rngs=rngs,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
# Spatial encoder
|
|
218
|
+
self.spatial_encoder = SpatialEncoder(
|
|
219
|
+
hidden_dim=config.spatial_hidden,
|
|
220
|
+
rngs=rngs,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
# Combine expression and spatial
|
|
224
|
+
self.combine_linear = nnx.Linear(
|
|
225
|
+
in_features=config.hidden_dim + config.spatial_hidden,
|
|
226
|
+
out_features=config.hidden_dim,
|
|
227
|
+
rngs=rngs,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# Reference profile encoder
|
|
231
|
+
self.ref_encoder = nnx.Linear(
|
|
232
|
+
in_features=config.n_genes,
|
|
233
|
+
out_features=config.hidden_dim,
|
|
234
|
+
rngs=rngs,
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
# Output projection for cell type scores
|
|
238
|
+
self.output_linear = nnx.Linear(
|
|
239
|
+
in_features=config.hidden_dim,
|
|
240
|
+
out_features=config.n_cell_types,
|
|
241
|
+
rngs=rngs,
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
def apply(
|
|
245
|
+
self,
|
|
246
|
+
data: PyTree,
|
|
247
|
+
state: PyTree,
|
|
248
|
+
metadata: dict[str, Any] | None,
|
|
249
|
+
random_params: Any = None,
|
|
250
|
+
stats: dict[str, Any] | None = None,
|
|
251
|
+
) -> tuple[PyTree, PyTree, dict[str, Any] | None]:
|
|
252
|
+
"""Apply spatial deconvolution.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
data: Dictionary containing:
|
|
256
|
+
- "spot_expression": Spot expression (n_spots, n_genes)
|
|
257
|
+
- "reference_profiles": Reference profiles (n_cell_types, n_genes)
|
|
258
|
+
- "coordinates": Spot coordinates (n_spots, 2)
|
|
259
|
+
state: Element state (passed through unchanged)
|
|
260
|
+
metadata: Element metadata (passed through unchanged)
|
|
261
|
+
random_params: Not used
|
|
262
|
+
stats: Not used
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
Tuple of (transformed_data, state, metadata):
|
|
266
|
+
- transformed_data contains:
|
|
267
|
+
|
|
268
|
+
- "spot_expression": Original expression
|
|
269
|
+
- "reference_profiles": Original references
|
|
270
|
+
- "coordinates": Original coordinates
|
|
271
|
+
- "cell_proportions": Deconvolved proportions
|
|
272
|
+
- "reconstructed_expression": Reconstructed expression
|
|
273
|
+
- "spatial_embeddings": Spatial feature embeddings
|
|
274
|
+
- state is passed through unchanged
|
|
275
|
+
- metadata is passed through unchanged
|
|
276
|
+
"""
|
|
277
|
+
spot_expression = data["spot_expression"]
|
|
278
|
+
reference_profiles = data["reference_profiles"]
|
|
279
|
+
coordinates = data["coordinates"]
|
|
280
|
+
|
|
281
|
+
# Encode spot expression
|
|
282
|
+
spot_emb = self.spot_encoder(spot_expression) # (n_spots, hidden_dim)
|
|
283
|
+
|
|
284
|
+
# Encode spatial coordinates
|
|
285
|
+
spatial_emb = self.spatial_encoder(coordinates) # (n_spots, spatial_hidden)
|
|
286
|
+
|
|
287
|
+
# Combine expression and spatial features
|
|
288
|
+
combined = jnp.concatenate([spot_emb, spatial_emb], axis=-1)
|
|
289
|
+
combined = nnx.gelu(self.combine_linear(combined)) # (n_spots, hidden_dim)
|
|
290
|
+
|
|
291
|
+
# Encode reference profiles
|
|
292
|
+
ref_emb = self.ref_encoder(reference_profiles) # (n_cell_types, hidden_dim)
|
|
293
|
+
|
|
294
|
+
# Compute attention scores (dot product similarity)
|
|
295
|
+
# (n_spots, hidden_dim) @ (hidden_dim, n_cell_types) -> (n_spots, n_cell_types)
|
|
296
|
+
scores = jnp.einsum("sh,ch->sc", combined, ref_emb)
|
|
297
|
+
|
|
298
|
+
# Cell type proportions via softmax
|
|
299
|
+
# Use inherited _temperature property from TemperatureOperator
|
|
300
|
+
cell_proportions = jax.nn.softmax(scores / self._temperature, axis=-1)
|
|
301
|
+
|
|
302
|
+
# Reconstruct expression: proportions @ reference_profiles
|
|
303
|
+
# (n_spots, n_cell_types) @ (n_cell_types, n_genes) -> (n_spots, n_genes)
|
|
304
|
+
reconstructed = jnp.einsum("sc,cg->sg", cell_proportions, reference_profiles)
|
|
305
|
+
|
|
306
|
+
# Build output
|
|
307
|
+
transformed_data = {
|
|
308
|
+
"spot_expression": spot_expression,
|
|
309
|
+
"reference_profiles": reference_profiles,
|
|
310
|
+
"coordinates": coordinates,
|
|
311
|
+
"cell_proportions": cell_proportions,
|
|
312
|
+
"reconstructed_expression": reconstructed,
|
|
313
|
+
"spatial_embeddings": combined,
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return transformed_data, state, metadata
|