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.
- dnakit/__init__.py +108 -0
- dnakit/_version.py +5 -0
- dnakit/alignment/__init__.py +6 -0
- dnakit/alignment/pairwise.py +512 -0
- dnakit/alignment/results.py +188 -0
- dnakit/backends/__init__.py +80 -0
- dnakit/backends/external.py +517 -0
- dnakit/backends/registry.py +207 -0
- dnakit/batch.py +452 -0
- dnakit/cache/__init__.py +5 -0
- dnakit/cache/store.py +424 -0
- dnakit/chunking.py +920 -0
- dnakit/cli/__init__.py +5 -0
- dnakit/cli/__main__.py +6 -0
- dnakit/cli/app.py +814 -0
- dnakit/cli/workflow.py +94 -0
- dnakit/config/__init__.py +5 -0
- dnakit/config/loader.py +381 -0
- dnakit/core/__init__.py +80 -0
- dnakit/core/_json.py +206 -0
- dnakit/core/backend_info.py +70 -0
- dnakit/core/collection.py +163 -0
- dnakit/core/coordinates.py +295 -0
- dnakit/core/enums.py +95 -0
- dnakit/core/facade.py +719 -0
- dnakit/core/feature.py +90 -0
- dnakit/core/gap.py +82 -0
- dnakit/core/issues.py +62 -0
- dnakit/core/provenance.py +305 -0
- dnakit/core/record.py +161 -0
- dnakit/core/results.py +134 -0
- dnakit/core/sequence.py +327 -0
- dnakit/datasets/__init__.py +100 -0
- dnakit/datasets/_advanced_shared.py +198 -0
- dnakit/datasets/_metadata.py +33 -0
- dnakit/datasets/advanced_deduplicate.py +183 -0
- dnakit/datasets/advanced_split.py +302 -0
- dnakit/datasets/clustering.py +286 -0
- dnakit/datasets/config.py +531 -0
- dnakit/datasets/deduplicate.py +303 -0
- dnakit/datasets/evaluation.py +244 -0
- dnakit/datasets/filter.py +135 -0
- dnakit/datasets/neural_clustering.py +221 -0
- dnakit/datasets/results.py +520 -0
- dnakit/datasets/split.py +450 -0
- dnakit/descriptors/__init__.py +102 -0
- dnakit/descriptors/_dinucleotide.py +345 -0
- dnakit/descriptors/_shared.py +180 -0
- dnakit/descriptors/all.py +917 -0
- dnakit/descriptors/basic.py +193 -0
- dnakit/descriptors/codon.py +195 -0
- dnakit/descriptors/complexity.py +201 -0
- dnakit/descriptors/entropy.py +101 -0
- dnakit/descriptors/homopolymer.py +105 -0
- dnakit/descriptors/kmer.py +88 -0
- dnakit/descriptors/results.py +286 -0
- dnakit/descriptors/schema.py +414 -0
- dnakit/descriptors/window.py +203 -0
- dnakit/download/__init__.py +54 -0
- dnakit/download/catalogs.py +166 -0
- dnakit/download/ena.py +131 -0
- dnakit/download/encode.py +103 -0
- dnakit/download/files.py +469 -0
- dnakit/download/indexes.py +233 -0
- dnakit/download/metadata.py +164 -0
- dnakit/download/models.py +227 -0
- dnakit/download/ncbi.py +333 -0
- dnakit/download/sequence.py +133 -0
- dnakit/download/ucsc.py +99 -0
- dnakit/evaluation/__init__.py +81 -0
- dnakit/evaluation/_shared.py +288 -0
- dnakit/evaluation/collection.py +270 -0
- dnakit/evaluation/config.py +591 -0
- dnakit/evaluation/distribution.py +287 -0
- dnakit/evaluation/frechet.py +223 -0
- dnakit/evaluation/generative.py +381 -0
- dnakit/evaluation/reference.py +409 -0
- dnakit/evaluation/results.py +137 -0
- dnakit/evaluation/scorecard.py +211 -0
- dnakit/evaluation/sequence.py +403 -0
- dnakit/evaluation/synthesis.py +249 -0
- dnakit/exceptions.py +189 -0
- dnakit/fingerprints/__init__.py +109 -0
- dnakit/fingerprints/_shared.py +116 -0
- dnakit/fingerprints/advanced.py +829 -0
- dnakit/fingerprints/bit.py +229 -0
- dnakit/fingerprints/encoding.py +351 -0
- dnakit/fingerprints/kmer.py +170 -0
- dnakit/fingerprints/results.py +531 -0
- dnakit/fingerprints/sketch.py +246 -0
- dnakit/io/__init__.py +112 -0
- dnakit/io/_advanced_common.py +105 -0
- dnakit/io/_formats.py +994 -0
- dnakit/io/annotations.py +1179 -0
- dnakit/io/api.py +759 -0
- dnakit/io/config.py +315 -0
- dnakit/io/genbank.py +523 -0
- dnakit/io/indexed.py +1146 -0
- dnakit/io/metadata.py +452 -0
- dnakit/io/parquet.py +56 -0
- dnakit/io/results.py +131 -0
- dnakit/io/source.py +138 -0
- dnakit/io/tables.py +1237 -0
- dnakit/molbio/__init__.py +101 -0
- dnakit/molbio/_shared.py +266 -0
- dnakit/molbio/assembly.py +279 -0
- dnakit/molbio/crispr.py +181 -0
- dnakit/molbio/optimization.py +897 -0
- dnakit/molbio/primer3_design.py +667 -0
- dnakit/molbio/primers.py +899 -0
- dnakit/molbio/restriction.py +573 -0
- dnakit/molbio/results.py +583 -0
- dnakit/ops/__init__.py +588 -0
- dnakit/ops/_common.py +201 -0
- dnakit/ops/circular.py +193 -0
- dnakit/ops/concat.py +204 -0
- dnakit/ops/direction.py +27 -0
- dnakit/ops/edit.py +443 -0
- dnakit/ops/evolution.py +991 -0
- dnakit/ops/mutation.py +151 -0
- dnakit/ops/records.py +1012 -0
- dnakit/ops/translation.py +257 -0
- dnakit/patterns/__init__.py +81 -0
- dnakit/patterns/_shared.py +282 -0
- dnakit/patterns/coding.py +360 -0
- dnakit/patterns/crispr.py +337 -0
- dnakit/patterns/motif.py +721 -0
- dnakit/patterns/regions.py +341 -0
- dnakit/patterns/repeats.py +480 -0
- dnakit/patterns/restriction.py +281 -0
- dnakit/patterns/results.py +411 -0
- dnakit/py.typed +1 -0
- dnakit/references/__init__.py +27 -0
- dnakit/references/models.py +155 -0
- dnakit/references/ncbi.py +785 -0
- dnakit/representations/__init__.py +29 -0
- dnakit/representations/backends.py +928 -0
- dnakit/representations/checkpoints.py +356 -0
- dnakit/representations/extraction.py +220 -0
- dnakit/representations/models.py +395 -0
- dnakit/representations/results.py +79 -0
- dnakit/search/__init__.py +132 -0
- dnakit/search/_http.py +271 -0
- dnakit/search/_shared.py +108 -0
- dnakit/search/blast.py +516 -0
- dnakit/search/ena.py +245 -0
- dnakit/search/encode.py +102 -0
- dnakit/search/ensembl.py +874 -0
- dnakit/search/models.py +159 -0
- dnakit/search/ncbi.py +756 -0
- dnakit/search/ucsc.py +388 -0
- dnakit/secondary_structure/__init__.py +38 -0
- dnakit/secondary_structure/dotbracket.py +410 -0
- dnakit/secondary_structure/nupack.py +589 -0
- dnakit/secondary_structure/results.py +142 -0
- dnakit/similarity/__init__.py +125 -0
- dnakit/similarity/_shared.py +152 -0
- dnakit/similarity/approximate.py +258 -0
- dnakit/similarity/compare.py +162 -0
- dnakit/similarity/dashing.py +936 -0
- dnakit/similarity/distance.py +279 -0
- dnakit/similarity/index.py +365 -0
- dnakit/similarity/matrix.py +254 -0
- dnakit/similarity/results.py +676 -0
- dnakit/similarity/search.py +286 -0
- dnakit/similarity/sketch.py +96 -0
- dnakit/similarity/vector.py +662 -0
- dnakit/standardize/__init__.py +77 -0
- dnakit/standardize/_shared.py +100 -0
- dnakit/standardize/config.py +411 -0
- dnakit/standardize/gaps.py +1060 -0
- dnakit/standardize/normalize.py +565 -0
- dnakit/standardize/results.py +247 -0
- dnakit/standardize/validate.py +487 -0
- dnakit/structure3d/__init__.py +47 -0
- dnakit/structure3d/_shared.py +47 -0
- dnakit/structure3d/geometry.py +773 -0
- dnakit/structure3d/pdb.py +253 -0
- dnakit/structure3d/results.py +233 -0
- dnakit/structure3d/threedna.py +174 -0
- dnakit/thermodynamics/__init__.py +112 -0
- dnakit/thermodynamics/_shared.py +92 -0
- dnakit/thermodynamics/backends.py +653 -0
- dnakit/thermodynamics/calculations.py +837 -0
- dnakit/thermodynamics/config.py +175 -0
- dnakit/thermodynamics/equilibrium.py +340 -0
- dnakit/thermodynamics/optics.py +385 -0
- dnakit/thermodynamics/parameters.py +79 -0
- dnakit/thermodynamics/results.py +445 -0
- dnakit/visualization/__init__.py +43 -0
- dnakit/visualization/_svg.py +185 -0
- dnakit/visualization/advanced.py +314 -0
- dnakit/visualization/config.py +255 -0
- dnakit/visualization/export.py +349 -0
- dnakit/visualization/matrix.py +279 -0
- dnakit/visualization/report.py +431 -0
- dnakit/visualization/results.py +236 -0
- dnakit/visualization/sequence.py +459 -0
- dnakit/workflows/__init__.py +45 -0
- dnakit/workflows/manifest.py +365 -0
- dnakit/workflows/runner.py +1548 -0
- dnakit/workflows/schema.py +898 -0
- dnakit-0.1.0.dev0.dist-info/METADATA +126 -0
- dnakit-0.1.0.dev0.dist-info/RECORD +210 -0
- dnakit-0.1.0.dev0.dist-info/WHEEL +5 -0
- dnakit-0.1.0.dev0.dist-info/entry_points.txt +2 -0
- dnakit-0.1.0.dev0.dist-info/licenses/DISCLAIMER.md +26 -0
- dnakit-0.1.0.dev0.dist-info/licenses/LICENSE +21 -0
- dnakit-0.1.0.dev0.dist-info/licenses/THIRD_PARTY_NOTICES.md +73 -0
- dnakit-0.1.0.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Reference-genome resolution and download adapters."""
|
|
2
|
+
|
|
3
|
+
from dnakit.references.models import DownloadProgress, GenomeAssembly, GenomeDownloadResult
|
|
4
|
+
from dnakit.references.ncbi import (
|
|
5
|
+
DEFAULT_CHUNK_SIZE,
|
|
6
|
+
DEFAULT_MAX_DOWNLOAD_BYTES,
|
|
7
|
+
DEFAULT_NCBI_API_BASE_URL,
|
|
8
|
+
DEFAULT_TIMEOUT,
|
|
9
|
+
ProgressCallback,
|
|
10
|
+
download_genome,
|
|
11
|
+
resolve_genome_assembly,
|
|
12
|
+
supported_genome_aliases,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"DEFAULT_CHUNK_SIZE",
|
|
17
|
+
"DEFAULT_MAX_DOWNLOAD_BYTES",
|
|
18
|
+
"DEFAULT_NCBI_API_BASE_URL",
|
|
19
|
+
"DEFAULT_TIMEOUT",
|
|
20
|
+
"DownloadProgress",
|
|
21
|
+
"GenomeAssembly",
|
|
22
|
+
"GenomeDownloadResult",
|
|
23
|
+
"ProgressCallback",
|
|
24
|
+
"download_genome",
|
|
25
|
+
"resolve_genome_assembly",
|
|
26
|
+
"supported_genome_aliases",
|
|
27
|
+
]
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""Value objects returned by reference-genome download adapters."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import Any, Literal, cast
|
|
8
|
+
|
|
9
|
+
from dnakit.core._json import to_json_compatible
|
|
10
|
+
from dnakit.core.provenance import Provenance
|
|
11
|
+
from dnakit.exceptions import ConfigurationError
|
|
12
|
+
|
|
13
|
+
DownloadPhase = Literal["resolve", "download", "extract"]
|
|
14
|
+
_MD5 = re.compile(r"^[0-9a-f]{32}$")
|
|
15
|
+
_SHA256 = re.compile(r"^[0-9a-f]{64}$")
|
|
16
|
+
_ASSEMBLY_ACCESSION = re.compile(r"^GC[AF]_\d+\.\d+$", flags=re.IGNORECASE)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _require_text(value: object, name: str) -> str:
|
|
20
|
+
if not isinstance(value, str) or not value.strip():
|
|
21
|
+
raise ConfigurationError(
|
|
22
|
+
f"{name} must be a non-empty string.", code="INVALID_DOWNLOAD_RESULT"
|
|
23
|
+
)
|
|
24
|
+
return value
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True, slots=True)
|
|
28
|
+
class GenomeAssembly:
|
|
29
|
+
"""Resolved NCBI genome assembly identity."""
|
|
30
|
+
|
|
31
|
+
query: str
|
|
32
|
+
accession: str
|
|
33
|
+
organism: str | None = None
|
|
34
|
+
assembly_name: str | None = None
|
|
35
|
+
source_database: str | None = None
|
|
36
|
+
|
|
37
|
+
def __post_init__(self) -> None:
|
|
38
|
+
_require_text(self.query, "GenomeAssembly query")
|
|
39
|
+
accession = _require_text(self.accession, "GenomeAssembly accession")
|
|
40
|
+
if _ASSEMBLY_ACCESSION.fullmatch(accession) is None:
|
|
41
|
+
raise ConfigurationError(
|
|
42
|
+
"GenomeAssembly accession must be a versioned GCA_ or GCF_ assembly accession.",
|
|
43
|
+
code="INVALID_ASSEMBLY_ACCESSION",
|
|
44
|
+
)
|
|
45
|
+
for name in ("organism", "assembly_name", "source_database"):
|
|
46
|
+
value = getattr(self, name)
|
|
47
|
+
if value is not None:
|
|
48
|
+
_require_text(value, f"GenomeAssembly {name}")
|
|
49
|
+
object.__setattr__(self, "accession", accession.upper())
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass(frozen=True, slots=True)
|
|
53
|
+
class DownloadProgress:
|
|
54
|
+
"""One progress event emitted by a reference-data download."""
|
|
55
|
+
|
|
56
|
+
phase: DownloadPhase
|
|
57
|
+
query: str
|
|
58
|
+
accession: str
|
|
59
|
+
bytes_completed: int
|
|
60
|
+
total_bytes: int | None = None
|
|
61
|
+
current_file: str | None = None
|
|
62
|
+
|
|
63
|
+
def __post_init__(self) -> None:
|
|
64
|
+
if self.phase not in {"resolve", "download", "extract"}:
|
|
65
|
+
raise ConfigurationError(
|
|
66
|
+
"DownloadProgress phase is invalid.", code="INVALID_DOWNLOAD_PROGRESS"
|
|
67
|
+
)
|
|
68
|
+
_require_text(self.query, "DownloadProgress query")
|
|
69
|
+
_require_text(self.accession, "DownloadProgress accession")
|
|
70
|
+
for name, value in (
|
|
71
|
+
("bytes_completed", self.bytes_completed),
|
|
72
|
+
("total_bytes", self.total_bytes),
|
|
73
|
+
):
|
|
74
|
+
if value is not None and (
|
|
75
|
+
isinstance(value, bool) or not isinstance(value, int) or value < 0
|
|
76
|
+
):
|
|
77
|
+
raise ConfigurationError(
|
|
78
|
+
f"DownloadProgress {name} must be a non-negative integer or None.",
|
|
79
|
+
code="INVALID_DOWNLOAD_PROGRESS",
|
|
80
|
+
)
|
|
81
|
+
if self.total_bytes is not None and self.bytes_completed > self.total_bytes:
|
|
82
|
+
raise ConfigurationError(
|
|
83
|
+
"DownloadProgress bytes_completed cannot exceed total_bytes.",
|
|
84
|
+
code="INVALID_DOWNLOAD_PROGRESS",
|
|
85
|
+
)
|
|
86
|
+
if self.current_file is not None:
|
|
87
|
+
_require_text(self.current_file, "DownloadProgress current_file")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass(frozen=True, slots=True)
|
|
91
|
+
class GenomeDownloadResult:
|
|
92
|
+
"""Auditable files and checksums produced by a genome download."""
|
|
93
|
+
|
|
94
|
+
query: str
|
|
95
|
+
accession: str
|
|
96
|
+
organism: str | None
|
|
97
|
+
assembly_name: str | None
|
|
98
|
+
output_directory: str
|
|
99
|
+
fasta_path: str
|
|
100
|
+
metadata_path: str
|
|
101
|
+
checksum_path: str
|
|
102
|
+
package_path: str | None
|
|
103
|
+
download_url: str
|
|
104
|
+
downloaded_bytes: int
|
|
105
|
+
package_sha256: str
|
|
106
|
+
fasta_sha256: str
|
|
107
|
+
fasta_md5: str
|
|
108
|
+
provenance: Provenance
|
|
109
|
+
|
|
110
|
+
def __post_init__(self) -> None:
|
|
111
|
+
for name in (
|
|
112
|
+
"query",
|
|
113
|
+
"accession",
|
|
114
|
+
"output_directory",
|
|
115
|
+
"fasta_path",
|
|
116
|
+
"metadata_path",
|
|
117
|
+
"checksum_path",
|
|
118
|
+
"download_url",
|
|
119
|
+
):
|
|
120
|
+
_require_text(getattr(self, name), f"GenomeDownloadResult {name}")
|
|
121
|
+
for name in ("organism", "assembly_name", "package_path"):
|
|
122
|
+
value = getattr(self, name)
|
|
123
|
+
if value is not None:
|
|
124
|
+
_require_text(value, f"GenomeDownloadResult {name}")
|
|
125
|
+
for name in ("package_sha256", "fasta_sha256", "fasta_md5"):
|
|
126
|
+
value = _require_text(getattr(self, name), f"GenomeDownloadResult {name}").lower()
|
|
127
|
+
pattern = _MD5 if name == "fasta_md5" else _SHA256
|
|
128
|
+
if pattern.fullmatch(value) is None:
|
|
129
|
+
raise ConfigurationError(
|
|
130
|
+
f"GenomeDownloadResult {name} must be a lowercase hexadecimal hash.",
|
|
131
|
+
code="INVALID_DOWNLOAD_RESULT",
|
|
132
|
+
)
|
|
133
|
+
object.__setattr__(self, name, value)
|
|
134
|
+
if (
|
|
135
|
+
isinstance(self.downloaded_bytes, bool)
|
|
136
|
+
or not isinstance(self.downloaded_bytes, int)
|
|
137
|
+
or self.downloaded_bytes < 1
|
|
138
|
+
):
|
|
139
|
+
raise ConfigurationError(
|
|
140
|
+
"GenomeDownloadResult downloaded_bytes must be positive.",
|
|
141
|
+
code="INVALID_DOWNLOAD_RESULT",
|
|
142
|
+
)
|
|
143
|
+
if not isinstance(self.provenance, Provenance):
|
|
144
|
+
raise ConfigurationError(
|
|
145
|
+
"GenomeDownloadResult provenance must be Provenance.",
|
|
146
|
+
code="INVALID_DOWNLOAD_RESULT",
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def to_dict(self) -> dict[str, Any]:
|
|
150
|
+
"""Return a JSON-compatible download manifest."""
|
|
151
|
+
|
|
152
|
+
return cast(dict[str, Any], to_json_compatible(self))
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
__all__ = ["DownloadPhase", "DownloadProgress", "GenomeAssembly", "GenomeDownloadResult"]
|