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,261 @@
|
|
|
1
|
+
"""Differentiable drug-target interaction pipeline.
|
|
2
|
+
|
|
3
|
+
The pipeline combines existing DiffBio building blocks:
|
|
4
|
+
|
|
5
|
+
- ``TransformerSequenceEncoder`` for protein sequence embeddings.
|
|
6
|
+
- ``DifferentiableMolecularFingerprint`` for molecular graph fingerprints.
|
|
7
|
+
|
|
8
|
+
This module centralizes DTI input preparation so benchmarks do not maintain
|
|
9
|
+
bespoke protein/drug feature handling.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
import jax.numpy as jnp
|
|
18
|
+
import numpy as np
|
|
19
|
+
from datarax.core.config import OperatorConfig
|
|
20
|
+
from flax import nnx
|
|
21
|
+
|
|
22
|
+
from diffbio.operators.alignment import PROTEIN_ALPHABET
|
|
23
|
+
from diffbio.operators.drug_discovery.fingerprint import (
|
|
24
|
+
DifferentiableMolecularFingerprint,
|
|
25
|
+
MolecularFingerprintConfig,
|
|
26
|
+
)
|
|
27
|
+
from diffbio.operators.drug_discovery.primitives import (
|
|
28
|
+
DEFAULT_ATOM_FEATURES,
|
|
29
|
+
batch_smiles_to_graphs,
|
|
30
|
+
)
|
|
31
|
+
from diffbio.operators.foundation_models.contracts import AdapterMode, FoundationModelKind
|
|
32
|
+
from diffbio.operators.foundation_models.transformer_encoder import (
|
|
33
|
+
TransformerSequenceEncoder,
|
|
34
|
+
TransformerSequenceEncoderConfig,
|
|
35
|
+
)
|
|
36
|
+
from diffbio.sources.dti import validate_dti_dataset
|
|
37
|
+
|
|
38
|
+
PROTEIN_ONE_HOT_PREPROCESSING_VERSION = "protein_one_hot_v1"
|
|
39
|
+
DTI_PIPELINE_INTEGRATION_LAYER = "shared_dti_pipeline_v1"
|
|
40
|
+
_PROTEIN_ALPHABET_INDEX = {residue: index for index, residue in enumerate(PROTEIN_ALPHABET)}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True)
|
|
44
|
+
class _DTIProteinEncoderConfig:
|
|
45
|
+
"""Protein encoder configuration for the DTI pipeline."""
|
|
46
|
+
|
|
47
|
+
protein_hidden_dim: int = 16
|
|
48
|
+
protein_num_layers: int = 1
|
|
49
|
+
protein_num_heads: int = 2
|
|
50
|
+
protein_intermediate_dim: int = 32
|
|
51
|
+
max_protein_length: int = 32
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass(frozen=True)
|
|
55
|
+
class _DTIDrugEncoderConfig:
|
|
56
|
+
"""Drug encoder configuration for the DTI pipeline."""
|
|
57
|
+
|
|
58
|
+
drug_fingerprint_dim: int = 16
|
|
59
|
+
drug_hidden_dim: int = 16
|
|
60
|
+
drug_num_layers: int = 2
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass(frozen=True)
|
|
64
|
+
class _DTIPairScorerConfig:
|
|
65
|
+
"""Pair scorer and artifact configuration for the DTI pipeline."""
|
|
66
|
+
|
|
67
|
+
pair_hidden_dim: int = 16
|
|
68
|
+
foundation_artifact_id: str = "diffbio.dti_protein_encoder"
|
|
69
|
+
foundation_preprocessing_version: str = PROTEIN_ONE_HOT_PREPROCESSING_VERSION
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass(frozen=True)
|
|
73
|
+
class DTIPipelineConfig(
|
|
74
|
+
_DTIProteinEncoderConfig,
|
|
75
|
+
_DTIDrugEncoderConfig,
|
|
76
|
+
_DTIPairScorerConfig,
|
|
77
|
+
OperatorConfig,
|
|
78
|
+
):
|
|
79
|
+
"""Configuration for the shared differentiable DTI pipeline."""
|
|
80
|
+
|
|
81
|
+
def __post_init__(self) -> None:
|
|
82
|
+
"""Validate the pipeline configuration."""
|
|
83
|
+
super().__post_init__()
|
|
84
|
+
positive_fields = {
|
|
85
|
+
"protein_hidden_dim": self.protein_hidden_dim,
|
|
86
|
+
"protein_num_layers": self.protein_num_layers,
|
|
87
|
+
"protein_num_heads": self.protein_num_heads,
|
|
88
|
+
"protein_intermediate_dim": self.protein_intermediate_dim,
|
|
89
|
+
"max_protein_length": self.max_protein_length,
|
|
90
|
+
"drug_fingerprint_dim": self.drug_fingerprint_dim,
|
|
91
|
+
"drug_hidden_dim": self.drug_hidden_dim,
|
|
92
|
+
"drug_num_layers": self.drug_num_layers,
|
|
93
|
+
"pair_hidden_dim": self.pair_hidden_dim,
|
|
94
|
+
}
|
|
95
|
+
for field_name, value in positive_fields.items():
|
|
96
|
+
if value <= 0:
|
|
97
|
+
raise ValueError(f"{field_name} must be positive.")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class DifferentiableDTIPipeline(nnx.Module):
|
|
101
|
+
"""ConPLex-style DTI scorer with differentiable drug and protein encoders."""
|
|
102
|
+
|
|
103
|
+
def __init__(
|
|
104
|
+
self,
|
|
105
|
+
config: DTIPipelineConfig,
|
|
106
|
+
*,
|
|
107
|
+
rngs: nnx.Rngs | None = None,
|
|
108
|
+
) -> None:
|
|
109
|
+
"""Initialize protein encoder, drug encoder, and pair scorer."""
|
|
110
|
+
super().__init__()
|
|
111
|
+
if rngs is None:
|
|
112
|
+
rngs = nnx.Rngs(0)
|
|
113
|
+
|
|
114
|
+
self.config = nnx.static(config)
|
|
115
|
+
self.protein_encoder = TransformerSequenceEncoder(
|
|
116
|
+
TransformerSequenceEncoderConfig(
|
|
117
|
+
hidden_dim=config.protein_hidden_dim,
|
|
118
|
+
num_layers=config.protein_num_layers,
|
|
119
|
+
num_heads=config.protein_num_heads,
|
|
120
|
+
intermediate_dim=config.protein_intermediate_dim,
|
|
121
|
+
max_length=config.max_protein_length,
|
|
122
|
+
alphabet_size=len(PROTEIN_ALPHABET),
|
|
123
|
+
dropout_rate=0.0,
|
|
124
|
+
pooling="mean",
|
|
125
|
+
artifact_id=config.foundation_artifact_id,
|
|
126
|
+
preprocessing_version=config.foundation_preprocessing_version,
|
|
127
|
+
adapter_mode=AdapterMode.NATIVE_TRAINABLE,
|
|
128
|
+
),
|
|
129
|
+
rngs=rngs,
|
|
130
|
+
)
|
|
131
|
+
self.drug_encoder = DifferentiableMolecularFingerprint(
|
|
132
|
+
MolecularFingerprintConfig(
|
|
133
|
+
fingerprint_dim=config.drug_fingerprint_dim,
|
|
134
|
+
hidden_dim=config.drug_hidden_dim,
|
|
135
|
+
num_layers=config.drug_num_layers,
|
|
136
|
+
in_features=DEFAULT_ATOM_FEATURES,
|
|
137
|
+
normalize=True,
|
|
138
|
+
),
|
|
139
|
+
rngs=rngs,
|
|
140
|
+
)
|
|
141
|
+
self.pair_hidden = nnx.Linear(
|
|
142
|
+
config.protein_hidden_dim + config.drug_fingerprint_dim,
|
|
143
|
+
config.pair_hidden_dim,
|
|
144
|
+
rngs=rngs,
|
|
145
|
+
)
|
|
146
|
+
self.output = nnx.Linear(config.pair_hidden_dim, 1, rngs=rngs)
|
|
147
|
+
|
|
148
|
+
def apply(
|
|
149
|
+
self,
|
|
150
|
+
data: dict[str, Any],
|
|
151
|
+
state: dict[str, Any],
|
|
152
|
+
metadata: dict[str, Any] | None,
|
|
153
|
+
random_params: Any = None,
|
|
154
|
+
stats: dict[str, Any] | None = None,
|
|
155
|
+
) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any] | None]:
|
|
156
|
+
"""Score a prepared paired protein/drug DTI batch."""
|
|
157
|
+
del random_params, stats
|
|
158
|
+
|
|
159
|
+
protein_result, _, _ = self.protein_encoder.apply(
|
|
160
|
+
{
|
|
161
|
+
"sequence": data["protein_one_hot"],
|
|
162
|
+
"attention_mask": data["protein_attention_mask"],
|
|
163
|
+
},
|
|
164
|
+
{},
|
|
165
|
+
None,
|
|
166
|
+
)
|
|
167
|
+
protein_embeddings = jnp.asarray(protein_result["embeddings"], dtype=jnp.float32)
|
|
168
|
+
drug_fingerprints = self._encode_drug_graphs(data["drug_graphs"])
|
|
169
|
+
pair_embeddings = jnp.concatenate([protein_embeddings, drug_fingerprints], axis=-1)
|
|
170
|
+
hidden = nnx.gelu(self.pair_hidden(pair_embeddings))
|
|
171
|
+
scores = self.output(hidden).squeeze(-1)
|
|
172
|
+
|
|
173
|
+
return (
|
|
174
|
+
{
|
|
175
|
+
**data,
|
|
176
|
+
"scores": scores,
|
|
177
|
+
"protein_embeddings": protein_embeddings,
|
|
178
|
+
"drug_fingerprints": drug_fingerprints,
|
|
179
|
+
"pair_embeddings": pair_embeddings,
|
|
180
|
+
"foundation_model": protein_result["foundation_model"],
|
|
181
|
+
"dti_pipeline": self.pipeline_metadata(),
|
|
182
|
+
},
|
|
183
|
+
state,
|
|
184
|
+
metadata,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
def pipeline_metadata(self) -> dict[str, Any]:
|
|
188
|
+
"""Return benchmark-facing metadata for the integrated DTI path."""
|
|
189
|
+
return {
|
|
190
|
+
"integration_layer": DTI_PIPELINE_INTEGRATION_LAYER,
|
|
191
|
+
"pipeline_name": type(self).__name__,
|
|
192
|
+
"protein_encoder": {
|
|
193
|
+
"operator": "TransformerSequenceEncoder",
|
|
194
|
+
"model_family": FoundationModelKind.SEQUENCE_TRANSFORMER.value,
|
|
195
|
+
"adapter_mode": AdapterMode.NATIVE_TRAINABLE.value,
|
|
196
|
+
"preprocessing_version": self.config.foundation_preprocessing_version,
|
|
197
|
+
},
|
|
198
|
+
"drug_encoder": {
|
|
199
|
+
"operator": "DifferentiableMolecularFingerprint",
|
|
200
|
+
"differentiable": True,
|
|
201
|
+
},
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
def _encode_drug_graphs(self, drug_graphs: dict[str, Any]) -> jnp.ndarray:
|
|
205
|
+
"""Encode a padded molecular graph batch with the shared fingerprint operator."""
|
|
206
|
+
fingerprints = []
|
|
207
|
+
batch_size = int(drug_graphs["node_features"].shape[0])
|
|
208
|
+
for index in range(batch_size):
|
|
209
|
+
graph = {
|
|
210
|
+
"node_features": drug_graphs["node_features"][index],
|
|
211
|
+
"adjacency": drug_graphs["adjacency"][index],
|
|
212
|
+
"edge_features": drug_graphs["edge_features"][index],
|
|
213
|
+
"node_mask": drug_graphs["node_mask"][index],
|
|
214
|
+
}
|
|
215
|
+
result, _, _ = self.drug_encoder.apply(graph, {}, None)
|
|
216
|
+
fingerprints.append(result["fingerprint"])
|
|
217
|
+
return jnp.stack(fingerprints)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def build_dti_pipeline_inputs(
|
|
221
|
+
data: dict[str, Any],
|
|
222
|
+
*,
|
|
223
|
+
config: DTIPipelineConfig | None = None,
|
|
224
|
+
) -> dict[str, Any]:
|
|
225
|
+
"""Build one encoded protein/graph batch from a validated DTI payload."""
|
|
226
|
+
validate_dti_dataset(data)
|
|
227
|
+
resolved_config = config or DTIPipelineConfig()
|
|
228
|
+
protein_one_hot, protein_attention_mask = encode_protein_sequences(
|
|
229
|
+
data["protein_sequences"],
|
|
230
|
+
max_length=resolved_config.max_protein_length,
|
|
231
|
+
)
|
|
232
|
+
return {
|
|
233
|
+
"protein_one_hot": protein_one_hot,
|
|
234
|
+
"protein_attention_mask": protein_attention_mask,
|
|
235
|
+
"drug_graphs": batch_smiles_to_graphs(list(data["drug_smiles"])),
|
|
236
|
+
"targets": jnp.asarray(data["targets"], dtype=jnp.float32),
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def encode_protein_sequences(
|
|
241
|
+
sequences: list[str],
|
|
242
|
+
*,
|
|
243
|
+
max_length: int,
|
|
244
|
+
) -> tuple[jnp.ndarray, jnp.ndarray]:
|
|
245
|
+
"""One-hot encode protein strings using the shared alignment alphabet."""
|
|
246
|
+
if max_length <= 0:
|
|
247
|
+
raise ValueError("max_length must be positive.")
|
|
248
|
+
|
|
249
|
+
encoded = np.zeros((len(sequences), max_length, len(PROTEIN_ALPHABET)), dtype=np.float32)
|
|
250
|
+
attention_mask = np.zeros((len(sequences), max_length), dtype=np.float32)
|
|
251
|
+
|
|
252
|
+
for sequence_index, sequence in enumerate(sequences):
|
|
253
|
+
for residue_index, residue in enumerate(sequence[:max_length]):
|
|
254
|
+
amino_acid_index = _PROTEIN_ALPHABET_INDEX.get(residue.upper())
|
|
255
|
+
if amino_acid_index is None:
|
|
256
|
+
encoded[sequence_index, residue_index, :] = 1.0 / len(PROTEIN_ALPHABET)
|
|
257
|
+
else:
|
|
258
|
+
encoded[sequence_index, residue_index, amino_acid_index] = 1.0
|
|
259
|
+
attention_mask[sequence_index, residue_index] = 1.0
|
|
260
|
+
|
|
261
|
+
return jnp.asarray(encoded), jnp.asarray(attention_mask)
|