dnakit 0.1.0.dev0__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 (210) hide show
  1. dnakit/__init__.py +108 -0
  2. dnakit/_version.py +5 -0
  3. dnakit/alignment/__init__.py +6 -0
  4. dnakit/alignment/pairwise.py +512 -0
  5. dnakit/alignment/results.py +188 -0
  6. dnakit/backends/__init__.py +80 -0
  7. dnakit/backends/external.py +517 -0
  8. dnakit/backends/registry.py +207 -0
  9. dnakit/batch.py +452 -0
  10. dnakit/cache/__init__.py +5 -0
  11. dnakit/cache/store.py +424 -0
  12. dnakit/chunking.py +920 -0
  13. dnakit/cli/__init__.py +5 -0
  14. dnakit/cli/__main__.py +6 -0
  15. dnakit/cli/app.py +814 -0
  16. dnakit/cli/workflow.py +94 -0
  17. dnakit/config/__init__.py +5 -0
  18. dnakit/config/loader.py +381 -0
  19. dnakit/core/__init__.py +80 -0
  20. dnakit/core/_json.py +206 -0
  21. dnakit/core/backend_info.py +70 -0
  22. dnakit/core/collection.py +163 -0
  23. dnakit/core/coordinates.py +295 -0
  24. dnakit/core/enums.py +95 -0
  25. dnakit/core/facade.py +719 -0
  26. dnakit/core/feature.py +90 -0
  27. dnakit/core/gap.py +82 -0
  28. dnakit/core/issues.py +62 -0
  29. dnakit/core/provenance.py +305 -0
  30. dnakit/core/record.py +161 -0
  31. dnakit/core/results.py +134 -0
  32. dnakit/core/sequence.py +327 -0
  33. dnakit/datasets/__init__.py +100 -0
  34. dnakit/datasets/_advanced_shared.py +198 -0
  35. dnakit/datasets/_metadata.py +33 -0
  36. dnakit/datasets/advanced_deduplicate.py +183 -0
  37. dnakit/datasets/advanced_split.py +302 -0
  38. dnakit/datasets/clustering.py +286 -0
  39. dnakit/datasets/config.py +531 -0
  40. dnakit/datasets/deduplicate.py +303 -0
  41. dnakit/datasets/evaluation.py +244 -0
  42. dnakit/datasets/filter.py +135 -0
  43. dnakit/datasets/neural_clustering.py +221 -0
  44. dnakit/datasets/results.py +520 -0
  45. dnakit/datasets/split.py +450 -0
  46. dnakit/descriptors/__init__.py +102 -0
  47. dnakit/descriptors/_dinucleotide.py +345 -0
  48. dnakit/descriptors/_shared.py +180 -0
  49. dnakit/descriptors/all.py +917 -0
  50. dnakit/descriptors/basic.py +193 -0
  51. dnakit/descriptors/codon.py +195 -0
  52. dnakit/descriptors/complexity.py +201 -0
  53. dnakit/descriptors/entropy.py +101 -0
  54. dnakit/descriptors/homopolymer.py +105 -0
  55. dnakit/descriptors/kmer.py +88 -0
  56. dnakit/descriptors/results.py +286 -0
  57. dnakit/descriptors/schema.py +414 -0
  58. dnakit/descriptors/window.py +203 -0
  59. dnakit/download/__init__.py +54 -0
  60. dnakit/download/catalogs.py +166 -0
  61. dnakit/download/ena.py +131 -0
  62. dnakit/download/encode.py +103 -0
  63. dnakit/download/files.py +469 -0
  64. dnakit/download/indexes.py +233 -0
  65. dnakit/download/metadata.py +164 -0
  66. dnakit/download/models.py +227 -0
  67. dnakit/download/ncbi.py +333 -0
  68. dnakit/download/sequence.py +133 -0
  69. dnakit/download/ucsc.py +99 -0
  70. dnakit/evaluation/__init__.py +81 -0
  71. dnakit/evaluation/_shared.py +288 -0
  72. dnakit/evaluation/collection.py +270 -0
  73. dnakit/evaluation/config.py +591 -0
  74. dnakit/evaluation/distribution.py +287 -0
  75. dnakit/evaluation/frechet.py +223 -0
  76. dnakit/evaluation/generative.py +381 -0
  77. dnakit/evaluation/reference.py +409 -0
  78. dnakit/evaluation/results.py +137 -0
  79. dnakit/evaluation/scorecard.py +211 -0
  80. dnakit/evaluation/sequence.py +403 -0
  81. dnakit/evaluation/synthesis.py +249 -0
  82. dnakit/exceptions.py +189 -0
  83. dnakit/fingerprints/__init__.py +109 -0
  84. dnakit/fingerprints/_shared.py +116 -0
  85. dnakit/fingerprints/advanced.py +829 -0
  86. dnakit/fingerprints/bit.py +229 -0
  87. dnakit/fingerprints/encoding.py +351 -0
  88. dnakit/fingerprints/kmer.py +170 -0
  89. dnakit/fingerprints/results.py +531 -0
  90. dnakit/fingerprints/sketch.py +246 -0
  91. dnakit/io/__init__.py +112 -0
  92. dnakit/io/_advanced_common.py +105 -0
  93. dnakit/io/_formats.py +994 -0
  94. dnakit/io/annotations.py +1179 -0
  95. dnakit/io/api.py +759 -0
  96. dnakit/io/config.py +315 -0
  97. dnakit/io/genbank.py +523 -0
  98. dnakit/io/indexed.py +1146 -0
  99. dnakit/io/metadata.py +452 -0
  100. dnakit/io/parquet.py +56 -0
  101. dnakit/io/results.py +131 -0
  102. dnakit/io/source.py +138 -0
  103. dnakit/io/tables.py +1237 -0
  104. dnakit/molbio/__init__.py +101 -0
  105. dnakit/molbio/_shared.py +266 -0
  106. dnakit/molbio/assembly.py +279 -0
  107. dnakit/molbio/crispr.py +181 -0
  108. dnakit/molbio/optimization.py +897 -0
  109. dnakit/molbio/primer3_design.py +667 -0
  110. dnakit/molbio/primers.py +899 -0
  111. dnakit/molbio/restriction.py +573 -0
  112. dnakit/molbio/results.py +583 -0
  113. dnakit/ops/__init__.py +588 -0
  114. dnakit/ops/_common.py +201 -0
  115. dnakit/ops/circular.py +193 -0
  116. dnakit/ops/concat.py +204 -0
  117. dnakit/ops/direction.py +27 -0
  118. dnakit/ops/edit.py +443 -0
  119. dnakit/ops/evolution.py +991 -0
  120. dnakit/ops/mutation.py +151 -0
  121. dnakit/ops/records.py +1012 -0
  122. dnakit/ops/translation.py +257 -0
  123. dnakit/patterns/__init__.py +81 -0
  124. dnakit/patterns/_shared.py +282 -0
  125. dnakit/patterns/coding.py +360 -0
  126. dnakit/patterns/crispr.py +337 -0
  127. dnakit/patterns/motif.py +721 -0
  128. dnakit/patterns/regions.py +341 -0
  129. dnakit/patterns/repeats.py +480 -0
  130. dnakit/patterns/restriction.py +281 -0
  131. dnakit/patterns/results.py +411 -0
  132. dnakit/py.typed +1 -0
  133. dnakit/references/__init__.py +27 -0
  134. dnakit/references/models.py +155 -0
  135. dnakit/references/ncbi.py +785 -0
  136. dnakit/representations/__init__.py +29 -0
  137. dnakit/representations/backends.py +928 -0
  138. dnakit/representations/checkpoints.py +356 -0
  139. dnakit/representations/extraction.py +220 -0
  140. dnakit/representations/models.py +395 -0
  141. dnakit/representations/results.py +79 -0
  142. dnakit/search/__init__.py +132 -0
  143. dnakit/search/_http.py +271 -0
  144. dnakit/search/_shared.py +108 -0
  145. dnakit/search/blast.py +516 -0
  146. dnakit/search/ena.py +245 -0
  147. dnakit/search/encode.py +102 -0
  148. dnakit/search/ensembl.py +874 -0
  149. dnakit/search/models.py +159 -0
  150. dnakit/search/ncbi.py +756 -0
  151. dnakit/search/ucsc.py +388 -0
  152. dnakit/secondary_structure/__init__.py +38 -0
  153. dnakit/secondary_structure/dotbracket.py +410 -0
  154. dnakit/secondary_structure/nupack.py +589 -0
  155. dnakit/secondary_structure/results.py +142 -0
  156. dnakit/similarity/__init__.py +125 -0
  157. dnakit/similarity/_shared.py +152 -0
  158. dnakit/similarity/approximate.py +258 -0
  159. dnakit/similarity/compare.py +162 -0
  160. dnakit/similarity/dashing.py +936 -0
  161. dnakit/similarity/distance.py +279 -0
  162. dnakit/similarity/index.py +365 -0
  163. dnakit/similarity/matrix.py +254 -0
  164. dnakit/similarity/results.py +676 -0
  165. dnakit/similarity/search.py +286 -0
  166. dnakit/similarity/sketch.py +96 -0
  167. dnakit/similarity/vector.py +662 -0
  168. dnakit/standardize/__init__.py +77 -0
  169. dnakit/standardize/_shared.py +100 -0
  170. dnakit/standardize/config.py +411 -0
  171. dnakit/standardize/gaps.py +1060 -0
  172. dnakit/standardize/normalize.py +565 -0
  173. dnakit/standardize/results.py +247 -0
  174. dnakit/standardize/validate.py +487 -0
  175. dnakit/structure3d/__init__.py +47 -0
  176. dnakit/structure3d/_shared.py +47 -0
  177. dnakit/structure3d/geometry.py +773 -0
  178. dnakit/structure3d/pdb.py +253 -0
  179. dnakit/structure3d/results.py +233 -0
  180. dnakit/structure3d/threedna.py +174 -0
  181. dnakit/thermodynamics/__init__.py +112 -0
  182. dnakit/thermodynamics/_shared.py +92 -0
  183. dnakit/thermodynamics/backends.py +653 -0
  184. dnakit/thermodynamics/calculations.py +837 -0
  185. dnakit/thermodynamics/config.py +175 -0
  186. dnakit/thermodynamics/equilibrium.py +340 -0
  187. dnakit/thermodynamics/optics.py +385 -0
  188. dnakit/thermodynamics/parameters.py +79 -0
  189. dnakit/thermodynamics/results.py +445 -0
  190. dnakit/visualization/__init__.py +43 -0
  191. dnakit/visualization/_svg.py +185 -0
  192. dnakit/visualization/advanced.py +314 -0
  193. dnakit/visualization/config.py +255 -0
  194. dnakit/visualization/export.py +349 -0
  195. dnakit/visualization/matrix.py +279 -0
  196. dnakit/visualization/report.py +431 -0
  197. dnakit/visualization/results.py +236 -0
  198. dnakit/visualization/sequence.py +459 -0
  199. dnakit/workflows/__init__.py +45 -0
  200. dnakit/workflows/manifest.py +365 -0
  201. dnakit/workflows/runner.py +1548 -0
  202. dnakit/workflows/schema.py +898 -0
  203. dnakit-0.1.0.dev0.dist-info/METADATA +126 -0
  204. dnakit-0.1.0.dev0.dist-info/RECORD +210 -0
  205. dnakit-0.1.0.dev0.dist-info/WHEEL +5 -0
  206. dnakit-0.1.0.dev0.dist-info/entry_points.txt +2 -0
  207. dnakit-0.1.0.dev0.dist-info/licenses/DISCLAIMER.md +26 -0
  208. dnakit-0.1.0.dev0.dist-info/licenses/LICENSE +21 -0
  209. dnakit-0.1.0.dev0.dist-info/licenses/THIRD_PARTY_NOTICES.md +73 -0
  210. dnakit-0.1.0.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,395 @@
1
+ """Registry and configuration for DNA foundation-model representations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from dataclasses import dataclass, field
7
+ from typing import Literal, TypeAlias
8
+
9
+ from dnakit.exceptions import ConfigurationError
10
+
11
+ CheckpointKind: TypeAlias = Literal["huggingface", "dataverse"]
12
+ LoaderKind: TypeAlias = Literal[
13
+ "transformers",
14
+ "enformer",
15
+ "alphagenome",
16
+ "janusdna",
17
+ "evo2",
18
+ ]
19
+ PoolingMethod: TypeAlias = Literal["mean", "cls", "max", "last"]
20
+ AmbiguityPolicy: TypeAlias = Literal["replace_with_n", "error"]
21
+ TorchDType: TypeAlias = Literal["auto", "float32", "float16", "bfloat16"]
22
+
23
+
24
+ @dataclass(frozen=True, slots=True)
25
+ class DNAEmbeddingModel:
26
+ """One selectable DNA model and its official checkpoint metadata."""
27
+
28
+ name: str
29
+ display_name: str
30
+ loader: LoaderKind
31
+ checkpoint_kind: CheckpointKind
32
+ checkpoint_id: str
33
+ cache_name: str
34
+ source_repository: str
35
+ checkpoint_url: str
36
+ chunk_length: int
37
+ chunk_unit: Literal["bp", "token"]
38
+ default_pooling: PoolingMethod = "mean"
39
+ trust_remote_code: bool = False
40
+ required_package: str | None = None
41
+ output_dimension: int | None = None
42
+ allow_patterns: tuple[str, ...] | None = None
43
+ archive_name: str | None = None
44
+ archive_md5: str | None = None
45
+ evo2_layer: str | None = None
46
+ gated: bool = False
47
+ notes: str = ""
48
+
49
+
50
+ _HF_MODEL_PATTERNS = (
51
+ "*.bin",
52
+ "*.json",
53
+ "*.model",
54
+ "*.pt",
55
+ "*.py",
56
+ "*.safetensors",
57
+ "*.txt",
58
+ )
59
+
60
+
61
+ MODEL_REGISTRY: dict[str, DNAEmbeddingModel] = {
62
+ "dnabert2": DNAEmbeddingModel(
63
+ name="dnabert2",
64
+ display_name="DNABERT-2-117M",
65
+ loader="transformers",
66
+ checkpoint_kind="huggingface",
67
+ checkpoint_id="zhihan1996/DNABERT-2-117M",
68
+ cache_name="dnabert2-117m",
69
+ source_repository="https://github.com/MAGICS-LAB/DNABERT_2",
70
+ checkpoint_url="https://huggingface.co/zhihan1996/DNABERT-2-117M",
71
+ chunk_length=512,
72
+ chunk_unit="token",
73
+ trust_remote_code=True,
74
+ allow_patterns=_HF_MODEL_PATTERNS,
75
+ ),
76
+ "ntv2": DNAEmbeddingModel(
77
+ name="ntv2",
78
+ display_name="Nucleotide Transformer v2 500M multi-species",
79
+ loader="transformers",
80
+ checkpoint_kind="huggingface",
81
+ checkpoint_id="InstaDeepAI/nucleotide-transformer-v2-500m-multi-species",
82
+ cache_name="ntv2-500m-multi-species",
83
+ source_repository="https://github.com/instadeepai/nucleotide-transformer",
84
+ checkpoint_url=(
85
+ "https://huggingface.co/InstaDeepAI/nucleotide-transformer-v2-500m-multi-species"
86
+ ),
87
+ chunk_length=2_048,
88
+ chunk_unit="token",
89
+ trust_remote_code=True,
90
+ allow_patterns=_HF_MODEL_PATTERNS,
91
+ ),
92
+ "hyenadna": DNAEmbeddingModel(
93
+ name="hyenadna",
94
+ display_name="HyenaDNA medium 450k",
95
+ loader="transformers",
96
+ checkpoint_kind="huggingface",
97
+ checkpoint_id="LongSafari/hyenadna-medium-450k-seqlen-hf",
98
+ cache_name="hyenadna-medium-450k",
99
+ source_repository="https://github.com/HazyResearch/hyena-dna",
100
+ checkpoint_url="https://huggingface.co/LongSafari/hyenadna-medium-450k-seqlen-hf",
101
+ chunk_length=450_000,
102
+ chunk_unit="bp",
103
+ trust_remote_code=True,
104
+ allow_patterns=_HF_MODEL_PATTERNS,
105
+ ),
106
+ "caduceus": DNAEmbeddingModel(
107
+ name="caduceus",
108
+ display_name="Caduceus-Ph 131k",
109
+ loader="transformers",
110
+ checkpoint_kind="huggingface",
111
+ checkpoint_id="kuleshov-group/caduceus-ph_seqlen-131k_d_model-256_n_layer-16",
112
+ cache_name="caduceus-ph-131k",
113
+ source_repository="https://github.com/kuleshov-group/caduceus",
114
+ checkpoint_url=(
115
+ "https://huggingface.co/kuleshov-group/caduceus-ph_seqlen-131k_d_model-256_n_layer-16"
116
+ ),
117
+ chunk_length=131_072,
118
+ chunk_unit="bp",
119
+ trust_remote_code=True,
120
+ allow_patterns=_HF_MODEL_PATTERNS,
121
+ ),
122
+ "grover": DNAEmbeddingModel(
123
+ name="grover",
124
+ display_name="GROVER",
125
+ loader="transformers",
126
+ checkpoint_kind="huggingface",
127
+ checkpoint_id="PoetschLab/GROVER",
128
+ cache_name="grover",
129
+ source_repository="https://huggingface.co/PoetschLab/GROVER",
130
+ checkpoint_url="https://huggingface.co/PoetschLab/GROVER",
131
+ chunk_length=512,
132
+ chunk_unit="token",
133
+ allow_patterns=_HF_MODEL_PATTERNS,
134
+ notes="Only model and tokenizer files are downloaded; tokenized chromosomes are excluded.",
135
+ ),
136
+ "lucaone": DNAEmbeddingModel(
137
+ name="lucaone",
138
+ display_name="LucaOne gene step 36.8M",
139
+ loader="transformers",
140
+ checkpoint_kind="huggingface",
141
+ checkpoint_id="LucaGroup/LucaOne-gene-step36.8M",
142
+ cache_name="lucaone-gene-step36-8m",
143
+ source_repository="https://github.com/LucaOne/LucaOne",
144
+ checkpoint_url="https://huggingface.co/LucaGroup/LucaOne-gene-step36.8M",
145
+ chunk_length=4_096,
146
+ chunk_unit="token",
147
+ trust_remote_code=True,
148
+ allow_patterns=_HF_MODEL_PATTERNS,
149
+ ),
150
+ "generator": DNAEmbeddingModel(
151
+ name="generator",
152
+ display_name="GENERator v2 eukaryote 1.2B",
153
+ loader="transformers",
154
+ checkpoint_kind="huggingface",
155
+ checkpoint_id="GenerTeam/GENERator-v2-eukaryote-1.2b-base",
156
+ cache_name="generator-v2-eukaryote-1-2b",
157
+ source_repository="https://github.com/GenerTeam/GENERator",
158
+ checkpoint_url="https://huggingface.co/GenerTeam/GENERator-v2-eukaryote-1.2b-base",
159
+ chunk_length=16_384,
160
+ chunk_unit="token",
161
+ trust_remote_code=True,
162
+ allow_patterns=_HF_MODEL_PATTERNS,
163
+ ),
164
+ "enformer": DNAEmbeddingModel(
165
+ name="enformer",
166
+ display_name="Enformer PyTorch",
167
+ loader="enformer",
168
+ checkpoint_kind="huggingface",
169
+ checkpoint_id="EleutherAI/enformer-official-rough",
170
+ cache_name="enformer-official-rough",
171
+ source_repository="https://github.com/lucidrains/enformer-pytorch",
172
+ checkpoint_url="https://huggingface.co/EleutherAI/enformer-official-rough",
173
+ chunk_length=196_608,
174
+ chunk_unit="bp",
175
+ default_pooling="mean",
176
+ required_package="enformer-pytorch>=0.8.11",
177
+ output_dimension=3_072,
178
+ allow_patterns=_HF_MODEL_PATTERNS,
179
+ ),
180
+ "alphagenome": DNAEmbeddingModel(
181
+ name="alphagenome",
182
+ display_name="AlphaGenome all folds",
183
+ loader="alphagenome",
184
+ checkpoint_kind="huggingface",
185
+ checkpoint_id="google/alphagenome-all-folds",
186
+ cache_name="alphagenome-all-folds",
187
+ source_repository="https://github.com/google-deepmind/alphagenome_research",
188
+ checkpoint_url="https://huggingface.co/google/alphagenome-all-folds",
189
+ chunk_length=1_048_576,
190
+ chunk_unit="bp",
191
+ default_pooling="mean",
192
+ required_package=("git+https://github.com/google-deepmind/alphagenome_research.git"),
193
+ output_dimension=1_536,
194
+ gated=True,
195
+ allow_patterns=None,
196
+ notes="Checkpoint access requires accepting Google's non-commercial model terms.",
197
+ ),
198
+ "janusdna": DNAEmbeddingModel(
199
+ name="janusdna",
200
+ display_name="JanusDNA 131k",
201
+ loader="janusdna",
202
+ checkpoint_kind="dataverse",
203
+ checkpoint_id="doi:10.7910/DVN/HDT0RN",
204
+ cache_name="janusdna-131k",
205
+ source_repository="https://github.com/Qihao-Duan/JanusDNA",
206
+ checkpoint_url="https://dataverse.harvard.edu/api/access/datafile/12016924",
207
+ chunk_length=131_072,
208
+ chunk_unit="bp",
209
+ trust_remote_code=False,
210
+ required_package="JanusDNA source checkout plus its official environment",
211
+ output_dimension=144,
212
+ archive_name=(
213
+ "janusdna_len-131k_d_model-144_inter_dim-576_n_layer-8_lr-8e-3_"
214
+ "step-50K_moeloss-true_1head_onlymoe_finalmlp.tar.bz2"
215
+ ),
216
+ archive_md5="1fce7f29c728f312d72262d6820e2ba0",
217
+ ),
218
+ "evo2": DNAEmbeddingModel(
219
+ name="evo2",
220
+ display_name="Evo 2 7B",
221
+ loader="evo2",
222
+ checkpoint_kind="huggingface",
223
+ checkpoint_id="arcinstitute/evo2_7b",
224
+ cache_name="evo2-7b",
225
+ source_repository="https://github.com/ArcInstitute/evo2",
226
+ checkpoint_url="https://huggingface.co/arcinstitute/evo2_7b",
227
+ chunk_length=70_000,
228
+ chunk_unit="bp",
229
+ default_pooling="mean",
230
+ required_package="evo2>=0.5.3,<0.6",
231
+ output_dimension=4_096,
232
+ allow_patterns=_HF_MODEL_PATTERNS,
233
+ evo2_layer="blocks.28.mlp.l3",
234
+ ),
235
+ }
236
+
237
+
238
+ _MODEL_ALIASES = {
239
+ "alpha-genome": "alphagenome",
240
+ "caduceus-ph": "caduceus",
241
+ "dna-bert-2": "dnabert2",
242
+ "dnabert-2": "dnabert2",
243
+ "enformer-pytorch": "enformer",
244
+ "evo-2": "evo2",
245
+ "generator-v2": "generator",
246
+ "hyena-dna": "hyenadna",
247
+ "janus-dna": "janusdna",
248
+ "luca-one": "lucaone",
249
+ "nt-v2": "ntv2",
250
+ "nucleotide-transformer": "ntv2",
251
+ }
252
+
253
+
254
+ def available_embedding_models() -> tuple[str, ...]:
255
+ """Return the stable model names accepted by :class:`RepresentationConfig`."""
256
+
257
+ return tuple(sorted(MODEL_REGISTRY))
258
+
259
+
260
+ def get_embedding_model(name: str) -> DNAEmbeddingModel:
261
+ """Resolve one canonical model name or documented alias."""
262
+
263
+ if not isinstance(name, str) or not name.strip():
264
+ raise ConfigurationError(
265
+ "model must be a non-empty string.",
266
+ code="INVALID_EMBEDDING_MODEL",
267
+ )
268
+ key = name.strip().lower().replace("_", "-")
269
+ canonical = _MODEL_ALIASES.get(key, key.replace("-", ""))
270
+ if canonical not in MODEL_REGISTRY:
271
+ raise ConfigurationError(
272
+ "Unknown DNA embedding model.",
273
+ code="INVALID_EMBEDDING_MODEL",
274
+ context={"model": name, "available": available_embedding_models()},
275
+ )
276
+ return MODEL_REGISTRY[canonical]
277
+
278
+
279
+ @dataclass(frozen=True, slots=True)
280
+ class RepresentationConfig:
281
+ """Configure checkpoint resolution and sequence-level representation extraction."""
282
+
283
+ model: str = "lucaone"
284
+ checkpoint_dir: str | os.PathLike[str] | None = None
285
+ checkpoint_path: str | os.PathLike[str] | None = None
286
+ model_source_path: str | os.PathLike[str] | None = None
287
+ pooling: PoolingMethod = "mean"
288
+ ambiguity_policy: AmbiguityPolicy = "replace_with_n"
289
+ device: str = "auto"
290
+ dtype: TorchDType = "auto"
291
+ batch_size: int = 4
292
+ max_length: int | None = None
293
+ max_records: int = 10_000
294
+ show_progress: bool = True
295
+ allow_remote_code: bool = False
296
+ hf_token: str | None = field(default=None, repr=False)
297
+
298
+ def __post_init__(self) -> None:
299
+ model_spec = get_embedding_model(self.model)
300
+ object.__setattr__(self, "model", model_spec.name)
301
+ for field_name in ("checkpoint_dir", "checkpoint_path", "model_source_path"):
302
+ value = getattr(self, field_name)
303
+ if value is None:
304
+ continue
305
+ try:
306
+ resolved = os.fspath(value)
307
+ except TypeError as exc:
308
+ raise ConfigurationError(
309
+ f"{field_name} must be path-like or None.",
310
+ code="INVALID_REPRESENTATION_CONFIG",
311
+ ) from exc
312
+ if not resolved.strip():
313
+ raise ConfigurationError(
314
+ f"{field_name} must not be empty.",
315
+ code="INVALID_REPRESENTATION_CONFIG",
316
+ )
317
+ object.__setattr__(self, field_name, resolved)
318
+ if self.checkpoint_dir is not None and self.checkpoint_path is not None:
319
+ raise ConfigurationError(
320
+ "checkpoint_dir and checkpoint_path are mutually exclusive.",
321
+ code="INVALID_REPRESENTATION_CONFIG",
322
+ )
323
+ if self.pooling not in {"mean", "cls", "max", "last"}:
324
+ raise ConfigurationError(
325
+ "Unknown representation pooling method.",
326
+ code="INVALID_REPRESENTATION_POOLING",
327
+ )
328
+ if self.ambiguity_policy not in {"replace_with_n", "error"}:
329
+ raise ConfigurationError(
330
+ "Unknown ambiguity_policy.",
331
+ code="INVALID_REPRESENTATION_CONFIG",
332
+ )
333
+ if not isinstance(self.device, str) or not self.device.strip():
334
+ raise ConfigurationError(
335
+ "device must be non-empty text.",
336
+ code="INVALID_REPRESENTATION_CONFIG",
337
+ )
338
+ if self.dtype not in {"auto", "float32", "float16", "bfloat16"}:
339
+ raise ConfigurationError(
340
+ "Unknown representation dtype.",
341
+ code="INVALID_REPRESENTATION_CONFIG",
342
+ )
343
+ for name, value, maximum in (
344
+ ("batch_size", self.batch_size, 1_024),
345
+ ("max_records", self.max_records, 1_000_000),
346
+ ):
347
+ if isinstance(value, bool) or not isinstance(value, int) or not 1 <= value <= maximum:
348
+ raise ConfigurationError(
349
+ f"{name} must be in [1, {maximum}].",
350
+ code="INVALID_REPRESENTATION_CONFIG",
351
+ )
352
+ if self.max_length is not None and (
353
+ isinstance(self.max_length, bool)
354
+ or not isinstance(self.max_length, int)
355
+ or not 1 <= self.max_length <= 10_000_000
356
+ ):
357
+ raise ConfigurationError(
358
+ "max_length must be None or an integer in [1, 10000000].",
359
+ code="INVALID_REPRESENTATION_CONFIG",
360
+ )
361
+ if not isinstance(self.show_progress, bool):
362
+ raise ConfigurationError(
363
+ "show_progress must be boolean.",
364
+ code="INVALID_REPRESENTATION_CONFIG",
365
+ )
366
+ if not isinstance(self.allow_remote_code, bool):
367
+ raise ConfigurationError(
368
+ "allow_remote_code must be boolean.",
369
+ code="INVALID_REPRESENTATION_CONFIG",
370
+ )
371
+ if self.hf_token is not None and (
372
+ not isinstance(self.hf_token, str) or not self.hf_token.strip()
373
+ ):
374
+ raise ConfigurationError(
375
+ "hf_token must be None or non-empty text.",
376
+ code="INVALID_REPRESENTATION_CONFIG",
377
+ )
378
+
379
+ @property
380
+ def model_spec(self) -> DNAEmbeddingModel:
381
+ """Return the resolved registry entry."""
382
+
383
+ return get_embedding_model(self.model)
384
+
385
+
386
+ __all__ = [
387
+ "MODEL_REGISTRY",
388
+ "AmbiguityPolicy",
389
+ "DNAEmbeddingModel",
390
+ "PoolingMethod",
391
+ "RepresentationConfig",
392
+ "TorchDType",
393
+ "available_embedding_models",
394
+ "get_embedding_model",
395
+ ]
@@ -0,0 +1,79 @@
1
+ """Results returned by DNA representation extraction."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Any
7
+
8
+ from dnakit.exceptions import ConfigurationError
9
+
10
+
11
+ @dataclass(frozen=True, slots=True, eq=False)
12
+ class RepresentationResult:
13
+ """A read-only float32 matrix aligned with the input record IDs."""
14
+
15
+ record_ids: tuple[str, ...]
16
+ representations: Any
17
+ model_name: str
18
+ checkpoint_path: str | None
19
+ pooling: str
20
+ embedding_dimension: int
21
+ input_count: int
22
+ ambiguity_policy: str
23
+
24
+ def __post_init__(self) -> None:
25
+ try:
26
+ import numpy as np
27
+ except ImportError as exc: # pragma: no cover - reached through the neural extra.
28
+ raise ConfigurationError(
29
+ "RepresentationResult requires NumPy.",
30
+ code="MISSING_NEURAL_DEPENDENCY",
31
+ ) from exc
32
+ matrix = np.asarray(self.representations, dtype=np.float32)
33
+ if matrix.ndim != 2:
34
+ raise ConfigurationError(
35
+ "representations must be a two-dimensional matrix.",
36
+ code="INVALID_REPRESENTATION_MATRIX",
37
+ )
38
+ if matrix.shape != (self.input_count, self.embedding_dimension):
39
+ raise ConfigurationError(
40
+ "Representation matrix shape does not match result metadata.",
41
+ code="INVALID_REPRESENTATION_MATRIX",
42
+ context={
43
+ "shape": tuple(int(value) for value in matrix.shape),
44
+ "input_count": self.input_count,
45
+ "embedding_dimension": self.embedding_dimension,
46
+ },
47
+ )
48
+ if len(self.record_ids) != self.input_count:
49
+ raise ConfigurationError(
50
+ "record_ids must align with representation rows.",
51
+ code="INVALID_REPRESENTATION_MATRIX",
52
+ )
53
+ if not np.isfinite(matrix).all():
54
+ raise ConfigurationError(
55
+ "Representations must contain only finite numbers.",
56
+ code="INVALID_REPRESENTATION_MATRIX",
57
+ )
58
+ matrix = np.array(matrix, dtype=np.float32, copy=True, order="C")
59
+ matrix.setflags(write=False)
60
+ object.__setattr__(self, "representations", matrix)
61
+
62
+ def to_dict(self, *, include_representations: bool = True) -> dict[str, object]:
63
+ """Return JSON-compatible metadata and, by default, the extracted vectors."""
64
+
65
+ payload: dict[str, object] = {
66
+ "record_ids": self.record_ids,
67
+ "model_name": self.model_name,
68
+ "checkpoint_path": self.checkpoint_path,
69
+ "pooling": self.pooling,
70
+ "embedding_dimension": self.embedding_dimension,
71
+ "input_count": self.input_count,
72
+ "ambiguity_policy": self.ambiguity_policy,
73
+ }
74
+ if include_representations:
75
+ payload["representations"] = self.representations.tolist()
76
+ return payload
77
+
78
+
79
+ __all__ = ["RepresentationResult"]
@@ -0,0 +1,132 @@
1
+ """Unified, bounded adapters for public biological database queries."""
2
+
3
+ from dnakit.search.blast import (
4
+ DEFAULT_NCBI_BLAST_URL,
5
+ BlastJob,
6
+ BlastProgress,
7
+ BlastStatus,
8
+ blast_results,
9
+ blast_status,
10
+ identify,
11
+ novelty,
12
+ submit_blast,
13
+ wait_for_blast,
14
+ )
15
+ from dnakit.search.ena import (
16
+ DEFAULT_ENA_PORTAL_URL,
17
+ DEFAULT_READ_FIELDS,
18
+ ena_search,
19
+ reads,
20
+ )
21
+ from dnakit.search.ena import (
22
+ project as ena_project,
23
+ )
24
+ from dnakit.search.ena import (
25
+ sample as ena_sample,
26
+ )
27
+ from dnakit.search.encode import DEFAULT_ENCODE_URL, encode_search
28
+ from dnakit.search.ensembl import (
29
+ DEFAULT_ENSEMBL_REST_URL,
30
+ annotation,
31
+ chromosome,
32
+ comparative_alignment,
33
+ genome_info,
34
+ homology,
35
+ id_convert,
36
+ map_coordinates,
37
+ nearby,
38
+ regulation,
39
+ sequence,
40
+ sequence_by_id,
41
+ transcripts,
42
+ variant,
43
+ )
44
+ from dnakit.search.ensembl import (
45
+ lookup as ensembl_lookup,
46
+ )
47
+ from dnakit.search.models import QueryProgress, QueryResult, SearchConfig
48
+ from dnakit.search.ncbi import (
49
+ DEFAULT_NCBI_DATASETS_URL,
50
+ DEFAULT_NCBI_EUTILS_URL,
51
+ accession,
52
+ assembly,
53
+ clinical_variant,
54
+ database_version,
55
+ entrez,
56
+ expression,
57
+ gene,
58
+ literature,
59
+ ncbi_orthologs,
60
+ project,
61
+ sample,
62
+ taxonomy,
63
+ virus,
64
+ )
65
+ from dnakit.search.ucsc import DEFAULT_UCSC_API_URL
66
+ from dnakit.search.ucsc import chromosomes as ucsc_chromosomes
67
+ from dnakit.search.ucsc import files as ucsc_files
68
+ from dnakit.search.ucsc import genomes as ucsc_genomes
69
+ from dnakit.search.ucsc import sequence as ucsc_sequence
70
+ from dnakit.search.ucsc import track_data as ucsc_track_data
71
+ from dnakit.search.ucsc import tracks as ucsc_tracks
72
+
73
+ __all__ = [
74
+ "DEFAULT_ENA_PORTAL_URL",
75
+ "DEFAULT_ENCODE_URL",
76
+ "DEFAULT_ENSEMBL_REST_URL",
77
+ "DEFAULT_NCBI_BLAST_URL",
78
+ "DEFAULT_NCBI_DATASETS_URL",
79
+ "DEFAULT_NCBI_EUTILS_URL",
80
+ "DEFAULT_READ_FIELDS",
81
+ "DEFAULT_UCSC_API_URL",
82
+ "BlastJob",
83
+ "BlastProgress",
84
+ "BlastStatus",
85
+ "QueryProgress",
86
+ "QueryResult",
87
+ "SearchConfig",
88
+ "accession",
89
+ "annotation",
90
+ "assembly",
91
+ "blast_results",
92
+ "blast_status",
93
+ "chromosome",
94
+ "clinical_variant",
95
+ "comparative_alignment",
96
+ "database_version",
97
+ "ena_project",
98
+ "ena_sample",
99
+ "ena_search",
100
+ "encode_search",
101
+ "ensembl_lookup",
102
+ "entrez",
103
+ "expression",
104
+ "gene",
105
+ "genome_info",
106
+ "homology",
107
+ "id_convert",
108
+ "identify",
109
+ "literature",
110
+ "map_coordinates",
111
+ "ncbi_orthologs",
112
+ "nearby",
113
+ "novelty",
114
+ "project",
115
+ "reads",
116
+ "regulation",
117
+ "sample",
118
+ "sequence",
119
+ "sequence_by_id",
120
+ "submit_blast",
121
+ "taxonomy",
122
+ "transcripts",
123
+ "ucsc_chromosomes",
124
+ "ucsc_files",
125
+ "ucsc_genomes",
126
+ "ucsc_sequence",
127
+ "ucsc_track_data",
128
+ "ucsc_tracks",
129
+ "variant",
130
+ "virus",
131
+ "wait_for_blast",
132
+ ]