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
dnakit/search/models.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""Immutable configuration and results for public database queries."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import math
|
|
6
|
+
from collections.abc import Iterable, Mapping
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Any, cast
|
|
9
|
+
|
|
10
|
+
from dnakit.core import Provenance
|
|
11
|
+
from dnakit.core._json import FrozenDict, freeze_mapping, to_json_compatible
|
|
12
|
+
from dnakit.exceptions import ConfigurationError
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True, slots=True)
|
|
16
|
+
class SearchConfig:
|
|
17
|
+
"""Resource and contact settings shared by remote query adapters.
|
|
18
|
+
|
|
19
|
+
``api_key`` is sent only to NCBI services. It is never included in a
|
|
20
|
+
``QueryResult.request_url`` or serialized result.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
timeout: float = 30.0
|
|
24
|
+
max_response_bytes: int = 20_000_000
|
|
25
|
+
max_records: int = 1_000
|
|
26
|
+
api_key: str | None = None
|
|
27
|
+
email: str | None = None
|
|
28
|
+
tool: str = "dnakit"
|
|
29
|
+
|
|
30
|
+
def __post_init__(self) -> None:
|
|
31
|
+
if (
|
|
32
|
+
isinstance(self.timeout, bool)
|
|
33
|
+
or not isinstance(self.timeout, (int, float))
|
|
34
|
+
or not math.isfinite(self.timeout)
|
|
35
|
+
or not 0 < self.timeout <= 300
|
|
36
|
+
):
|
|
37
|
+
raise ConfigurationError(
|
|
38
|
+
"SearchConfig timeout must be in (0, 300].", code="INVALID_SEARCH_CONFIG"
|
|
39
|
+
)
|
|
40
|
+
for name, value, maximum in (
|
|
41
|
+
("max_response_bytes", self.max_response_bytes, 100_000_000),
|
|
42
|
+
("max_records", self.max_records, 10_000),
|
|
43
|
+
):
|
|
44
|
+
if isinstance(value, bool) or not isinstance(value, int) or not 1 <= value <= maximum:
|
|
45
|
+
raise ConfigurationError(
|
|
46
|
+
f"SearchConfig {name} must be in [1, {maximum}].",
|
|
47
|
+
code="INVALID_SEARCH_CONFIG",
|
|
48
|
+
)
|
|
49
|
+
for name in ("api_key", "email"):
|
|
50
|
+
value = getattr(self, name)
|
|
51
|
+
if value is not None and (not isinstance(value, str) or not value.strip()):
|
|
52
|
+
raise ConfigurationError(
|
|
53
|
+
f"SearchConfig {name} must be None or non-empty text.",
|
|
54
|
+
code="INVALID_SEARCH_CONFIG",
|
|
55
|
+
)
|
|
56
|
+
if not isinstance(self.tool, str) or not self.tool.strip():
|
|
57
|
+
raise ConfigurationError(
|
|
58
|
+
"SearchConfig tool must be non-empty text.", code="INVALID_SEARCH_CONFIG"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass(frozen=True, slots=True)
|
|
63
|
+
class QueryProgress:
|
|
64
|
+
"""One optional progress event emitted by a batch query."""
|
|
65
|
+
|
|
66
|
+
completed: int
|
|
67
|
+
total: int
|
|
68
|
+
item: str
|
|
69
|
+
|
|
70
|
+
def __post_init__(self) -> None:
|
|
71
|
+
if (
|
|
72
|
+
isinstance(self.completed, bool)
|
|
73
|
+
or not isinstance(self.completed, int)
|
|
74
|
+
or isinstance(self.total, bool)
|
|
75
|
+
or not isinstance(self.total, int)
|
|
76
|
+
or not 0 <= self.completed <= self.total
|
|
77
|
+
or self.total < 1
|
|
78
|
+
):
|
|
79
|
+
raise ConfigurationError(
|
|
80
|
+
"QueryProgress counts are invalid.", code="INVALID_QUERY_PROGRESS"
|
|
81
|
+
)
|
|
82
|
+
if not isinstance(self.item, str) or not self.item:
|
|
83
|
+
raise ConfigurationError(
|
|
84
|
+
"QueryProgress item must be non-empty text.", code="INVALID_QUERY_PROGRESS"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass(frozen=True, init=False)
|
|
89
|
+
class QueryResult:
|
|
90
|
+
"""Auditable, provider-neutral records returned by one logical query."""
|
|
91
|
+
|
|
92
|
+
query_type: str
|
|
93
|
+
provider: str
|
|
94
|
+
request_url: str
|
|
95
|
+
records: tuple[FrozenDict, ...]
|
|
96
|
+
total_count: int | None
|
|
97
|
+
next_page_token: str | None
|
|
98
|
+
metadata: FrozenDict
|
|
99
|
+
provenance: Provenance
|
|
100
|
+
|
|
101
|
+
def __init__(
|
|
102
|
+
self,
|
|
103
|
+
query_type: str,
|
|
104
|
+
provider: str,
|
|
105
|
+
request_url: str,
|
|
106
|
+
records: Iterable[Mapping[str, object]],
|
|
107
|
+
provenance: Provenance,
|
|
108
|
+
*,
|
|
109
|
+
total_count: int | None = None,
|
|
110
|
+
next_page_token: str | None = None,
|
|
111
|
+
metadata: Mapping[str, object] | None = None,
|
|
112
|
+
) -> None:
|
|
113
|
+
for name, value in (
|
|
114
|
+
("query_type", query_type),
|
|
115
|
+
("provider", provider),
|
|
116
|
+
("request_url", request_url),
|
|
117
|
+
):
|
|
118
|
+
if not isinstance(value, str) or not value.strip():
|
|
119
|
+
raise ConfigurationError(
|
|
120
|
+
f"QueryResult {name} must be non-empty text.",
|
|
121
|
+
code="INVALID_QUERY_RESULT",
|
|
122
|
+
)
|
|
123
|
+
frozen_records = tuple(freeze_mapping(record) for record in records)
|
|
124
|
+
if total_count is not None and (
|
|
125
|
+
isinstance(total_count, bool)
|
|
126
|
+
or not isinstance(total_count, int)
|
|
127
|
+
or total_count < len(frozen_records)
|
|
128
|
+
):
|
|
129
|
+
raise ConfigurationError(
|
|
130
|
+
"QueryResult total_count must be None or at least the returned record count.",
|
|
131
|
+
code="INVALID_QUERY_RESULT",
|
|
132
|
+
)
|
|
133
|
+
if next_page_token is not None and (
|
|
134
|
+
not isinstance(next_page_token, str) or not next_page_token.strip()
|
|
135
|
+
):
|
|
136
|
+
raise ConfigurationError(
|
|
137
|
+
"QueryResult next_page_token must be None or non-empty text.",
|
|
138
|
+
code="INVALID_QUERY_RESULT",
|
|
139
|
+
)
|
|
140
|
+
if not isinstance(provenance, Provenance):
|
|
141
|
+
raise ConfigurationError(
|
|
142
|
+
"QueryResult provenance must be Provenance.", code="INVALID_QUERY_RESULT"
|
|
143
|
+
)
|
|
144
|
+
object.__setattr__(self, "query_type", query_type)
|
|
145
|
+
object.__setattr__(self, "provider", provider)
|
|
146
|
+
object.__setattr__(self, "request_url", request_url)
|
|
147
|
+
object.__setattr__(self, "records", frozen_records)
|
|
148
|
+
object.__setattr__(self, "total_count", total_count)
|
|
149
|
+
object.__setattr__(self, "next_page_token", next_page_token)
|
|
150
|
+
object.__setattr__(self, "metadata", freeze_mapping(metadata))
|
|
151
|
+
object.__setattr__(self, "provenance", provenance)
|
|
152
|
+
|
|
153
|
+
def to_dict(self) -> dict[str, Any]:
|
|
154
|
+
"""Return a JSON-compatible result without credentials."""
|
|
155
|
+
|
|
156
|
+
return cast(dict[str, Any], to_json_compatible(self))
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
__all__ = ["QueryProgress", "QueryResult", "SearchConfig"]
|