agglovar 0.0.1.dev12__tar.gz → 0.0.1.dev13__tar.gz
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.
- {agglovar-0.0.1.dev12/src/agglovar.egg-info → agglovar-0.0.1.dev13}/PKG-INFO +2 -1
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/pyproject.toml +1 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/__init__.py +4 -2
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/align/score.py +2 -2
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/bed/col.py +1 -4
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/bed/join.py +32 -0
- agglovar-0.0.1.dev13/src/agglovar/expr/__init__.py +7 -0
- agglovar-0.0.1.dev13/src/agglovar/expr/variant.py +61 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/merge/base.py +12 -11
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/merge/cumulative.py +20 -17
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/pairwise/overlap/_const.py +3 -2
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/pairwise/overlap/_overlap.py +158 -103
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/pairwise/overlap/_stage.py +27 -41
- agglovar-0.0.1.dev13/src/agglovar/schema.py +38 -0
- agglovar-0.0.1.dev13/src/agglovar/vcf/__init__.py +18 -0
- agglovar-0.0.1.dev13/src/agglovar/vcf/_vcf_const.py +72 -0
- agglovar-0.0.1.dev13/src/agglovar/vcf/_vcf_header.py +909 -0
- agglovar-0.0.1.dev13/src/agglovar/vcf/_vcf_read.py +664 -0
- agglovar-0.0.1.dev13/src/agglovar/vcf/_vcf_write.py +52 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13/src/agglovar.egg-info}/PKG-INFO +2 -1
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar.egg-info/SOURCES.txt +8 -1
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar.egg-info/requires.txt +1 -0
- agglovar-0.0.1.dev12/src/agglovar/schema.py +0 -30
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/LICENSE +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/README.md +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/setup.cfg +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/align/__init__.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/align/op.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/bed/__init__.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/bed/intersect.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/bed/merge.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/dev/__init__.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/dev/imports.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/fa.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/io.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/kmer/__init__.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/kmer/plot.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/kmer/util.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/merge/__init__.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/merge/config/__init__.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/merge/config/parser.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/merge/config/stage.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/merge/config/strategy.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/merge/om/__init__.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/merge/om/_executor_base.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/merge/om/_executor_nr.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/meta/__init__.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/meta/decorators.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/meta/descriptors.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/pairwise/__init__.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/pairwise/base.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/pairwise/overlap/__init__.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/pairwise/weights.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/seqmatch.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/util/__init__.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/util/str.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar/util/var.py +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar.egg-info/dependency_links.txt +0 -0
- {agglovar-0.0.1.dev12 → agglovar-0.0.1.dev13}/src/agglovar.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agglovar
|
|
3
|
-
Version: 0.0.1.
|
|
3
|
+
Version: 0.0.1.dev13
|
|
4
4
|
Summary: Toolkit for fast genomic variant transformations and intersects
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Python: >=3.12
|
|
@@ -12,6 +12,7 @@ Requires-Dist: intervaltree>=3.1.0
|
|
|
12
12
|
Requires-Dist: numpy>=2.3.0
|
|
13
13
|
Requires-Dist: ply>=3.11
|
|
14
14
|
Requires-Dist: polars[numpy,pandas,pyarrow]>=1.35.2
|
|
15
|
+
Requires-Dist: pysam>=0.23.3
|
|
15
16
|
Provides-Extra: plot
|
|
16
17
|
Requires-Dist: matplotlib>=3.10.3; extra == "plot"
|
|
17
18
|
Provides-Extra: all
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Agglovar: A toolkit for fast genomic variant transformations and intersects."""
|
|
2
2
|
|
|
3
|
-
__version__ = '0.0.1.
|
|
3
|
+
__version__ = '0.0.1.dev13'
|
|
4
4
|
|
|
5
5
|
__all__ = [
|
|
6
6
|
'align',
|
|
@@ -13,6 +13,7 @@ __all__ = [
|
|
|
13
13
|
'meta',
|
|
14
14
|
'schema',
|
|
15
15
|
'seqmatch',
|
|
16
|
+
'vcf',
|
|
16
17
|
'util',
|
|
17
18
|
]
|
|
18
19
|
|
|
@@ -26,4 +27,5 @@ from . import merge
|
|
|
26
27
|
from . import meta
|
|
27
28
|
from . import schema
|
|
28
29
|
from . import seqmatch
|
|
29
|
-
from . import
|
|
30
|
+
from . import vcf
|
|
31
|
+
from . import util
|
|
@@ -128,7 +128,7 @@ class ScoreModel(ABC):
|
|
|
128
128
|
self,
|
|
129
129
|
op_arr: np.ndarray,
|
|
130
130
|
) -> float:
|
|
131
|
-
"""
|
|
131
|
+
"""Sum scores for affine models using a vectorized implementation.
|
|
132
132
|
|
|
133
133
|
:param op_arr: Array of alignment operations (op_code: first column, op_len: second column).
|
|
134
134
|
|
|
@@ -285,7 +285,7 @@ class AffineScoreModel(ScoreModel):
|
|
|
285
285
|
self,
|
|
286
286
|
op_arr: np.ndarray,
|
|
287
287
|
) -> float:
|
|
288
|
-
"""
|
|
288
|
+
"""Sum scores for affine models using a A vectorized implementation.
|
|
289
289
|
|
|
290
290
|
:param op_arr: Array of alignment operations (op_code: first column, op_len: second column).
|
|
291
291
|
|
|
@@ -123,7 +123,6 @@ def get_coord_cols(
|
|
|
123
123
|
|
|
124
124
|
:return: An object with column names.
|
|
125
125
|
"""
|
|
126
|
-
|
|
127
126
|
if isinstance(col_names, CoordCol):
|
|
128
127
|
return col_names
|
|
129
128
|
|
|
@@ -137,7 +136,7 @@ def get_coord_cols(
|
|
|
137
136
|
else:
|
|
138
137
|
col_names_tuple = tuple((
|
|
139
138
|
col.strip() if col is not None else None
|
|
140
|
-
|
|
139
|
+
for col in col_names
|
|
141
140
|
))
|
|
142
141
|
|
|
143
142
|
if len(col_names_tuple) != 3:
|
|
@@ -181,7 +180,6 @@ def make_unique_col(
|
|
|
181
180
|
|
|
182
181
|
:return: Unique column name.
|
|
183
182
|
"""
|
|
184
|
-
|
|
185
183
|
new_col = col
|
|
186
184
|
i = 0
|
|
187
185
|
|
|
@@ -189,5 +187,4 @@ def make_unique_col(
|
|
|
189
187
|
i += 1
|
|
190
188
|
new_col = f'{col}_{i}'
|
|
191
189
|
|
|
192
|
-
|
|
193
190
|
return new_col
|
|
@@ -192,6 +192,8 @@ def _join_chunks(
|
|
|
192
192
|
col_a = join_resources.col_a
|
|
193
193
|
col_b = join_resources.col_b
|
|
194
194
|
|
|
195
|
+
yield_count = 0
|
|
196
|
+
|
|
195
197
|
for chrom, last_index_a in (
|
|
196
198
|
df_a
|
|
197
199
|
.group_by(col_a.chrom)
|
|
@@ -275,8 +277,38 @@ def _join_chunks(
|
|
|
275
277
|
|
|
276
278
|
start_index_b = end_index_b
|
|
277
279
|
|
|
280
|
+
yield_count += 1
|
|
281
|
+
|
|
278
282
|
start_index_a = end_index_a
|
|
279
283
|
|
|
284
|
+
if yield_count == 0:
|
|
285
|
+
# Iterator should always return at least one chunk, even if empty. Prevents pl.concat from failing.
|
|
286
|
+
yield (
|
|
287
|
+
df_a.filter(False)
|
|
288
|
+
.join(
|
|
289
|
+
df_b.filter(False),
|
|
290
|
+
left_on=col_a.chrom,
|
|
291
|
+
right_on=col_b.chrom,
|
|
292
|
+
how='inner',
|
|
293
|
+
)
|
|
294
|
+
.filter(
|
|
295
|
+
pl.col(col_b.pos) - distance <= pl.col(col_a.end),
|
|
296
|
+
pl.col(col_b.end) + distance >= pl.col(col_a.pos),
|
|
297
|
+
)
|
|
298
|
+
.select(
|
|
299
|
+
pl.col('_index_a').alias('index_a'),
|
|
300
|
+
pl.col('_index_b').alias('index_b'),
|
|
301
|
+
pl.col(col_a.chrom).alias('chrom'),
|
|
302
|
+
pl.max_horizontal(col_a.pos, col_b.pos).alias('pos'),
|
|
303
|
+
pl.min_horizontal(col_a.end, col_b.end).alias('end'),
|
|
304
|
+
)
|
|
305
|
+
.with_columns(
|
|
306
|
+
pl.min_horizontal('pos', 'end').alias('pos'),
|
|
307
|
+
pl.max_horizontal('pos', 'end').alias('end'),
|
|
308
|
+
(pl.col('pos') - pl.col('end')).alias('distance')
|
|
309
|
+
)
|
|
310
|
+
).collect().lazy()
|
|
311
|
+
|
|
280
312
|
|
|
281
313
|
def pairwise_join_tree(
|
|
282
314
|
df_a: pl.LazyFrame | pl.DataFrame,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Polars expressions used by variant calling routines."""
|
|
2
|
+
|
|
3
|
+
__all__ = [
|
|
4
|
+
'id_snv_expr',
|
|
5
|
+
'id_nonsnv_expr',
|
|
6
|
+
'sort_cols',
|
|
7
|
+
'id_expr_noalias',
|
|
8
|
+
'id_expr',
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
import polars as pl
|
|
12
|
+
|
|
13
|
+
id_snv_expr = (
|
|
14
|
+
pl.concat_str(
|
|
15
|
+
pl.col('chrom'),
|
|
16
|
+
pl.lit('-'),
|
|
17
|
+
pl.col('pos') + 1,
|
|
18
|
+
pl.lit('-SNV-'),
|
|
19
|
+
pl.col('ref').str.to_uppercase(),
|
|
20
|
+
pl.col('alt').str.to_uppercase(),
|
|
21
|
+
)
|
|
22
|
+
)
|
|
23
|
+
"""Expression for generating SNV IDs."""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
id_nonsnv_expr = (
|
|
27
|
+
pl.concat_str(
|
|
28
|
+
pl.col('chrom'),
|
|
29
|
+
pl.lit('-'),
|
|
30
|
+
(pl.col('pos') + 1).cast(pl.String),
|
|
31
|
+
pl.lit('-'),
|
|
32
|
+
pl.col('vartype').str.to_uppercase(),
|
|
33
|
+
pl.lit('-'),
|
|
34
|
+
pl.col('varlen').cast(pl.String)
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
"""Expression for generating non-SNV IDs."""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
sort_cols = (
|
|
41
|
+
pl.col('chrom'),
|
|
42
|
+
pl.col('pos'),
|
|
43
|
+
pl.col('end'),
|
|
44
|
+
pl.col('filter').list.len(),
|
|
45
|
+
pl.coalesce(
|
|
46
|
+
pl.col('^id$'),
|
|
47
|
+
pl.lit(None),
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
"""Sort columns for variant tables."""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
id_expr_noalias = (
|
|
54
|
+
pl.when(pl.col('vartype').str.to_uppercase() == 'SNV')
|
|
55
|
+
.then(id_snv_expr)
|
|
56
|
+
.otherwise(id_nonsnv_expr)
|
|
57
|
+
)
|
|
58
|
+
"""Expression for generating variant IDs."""
|
|
59
|
+
|
|
60
|
+
id_expr = id_expr_noalias.alias('id')
|
|
61
|
+
"""Expression for generating variant IDs including alias "id" for the result (ideal for `with_column()`)."""
|
|
@@ -58,7 +58,7 @@ class MergeBase(ABC):
|
|
|
58
58
|
def get_intersect_tuples(
|
|
59
59
|
callsets: Iterable[CallsetDefType],
|
|
60
60
|
retain_index: bool = False,
|
|
61
|
-
pre_filter: Optional[Iterable[pl.Expr]] = None,
|
|
61
|
+
pre_filter: Optional[Iterable[pl.Expr] | pl.Expr] = None,
|
|
62
62
|
) -> list[tuple[pl.LazyFrame, str, int]]:
|
|
63
63
|
"""
|
|
64
64
|
Transform input arguments to a list of tuples with set fields.
|
|
@@ -92,7 +92,10 @@ class MergeBase(ABC):
|
|
|
92
92
|
|
|
93
93
|
i = 0
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
if isinstance(pre_filter, pl.Expr):
|
|
96
|
+
pre_filter = [pre_filter]
|
|
97
|
+
else:
|
|
98
|
+
pre_filter = list(pre_filter if pre_filter is not None else [])
|
|
96
99
|
|
|
97
100
|
if callsets is None:
|
|
98
101
|
raise ValueError('Missing callsets')
|
|
@@ -143,15 +146,13 @@ class MergeBase(ABC):
|
|
|
143
146
|
.with_columns(
|
|
144
147
|
pl.coalesce(
|
|
145
148
|
pl.col(r'^id$'), # Existing ID if present
|
|
146
|
-
pl.
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
.otherwise(pl.col('id'))
|
|
154
|
-
).cast(pl.String).alias('id')
|
|
149
|
+
pl.lit(None)
|
|
150
|
+
)
|
|
151
|
+
.cast(pl.String)
|
|
152
|
+
.fill_null(
|
|
153
|
+
pl.concat_str(pl.lit('var'), pl.col('_mg_src_index'))
|
|
154
|
+
)
|
|
155
|
+
.alias('id')
|
|
155
156
|
)
|
|
156
157
|
.filter(
|
|
157
158
|
*pre_filter
|
|
@@ -114,7 +114,12 @@ def _get_match(
|
|
|
114
114
|
df_cumulative
|
|
115
115
|
.with_row_index('_index')
|
|
116
116
|
.join(
|
|
117
|
-
|
|
117
|
+
(
|
|
118
|
+
df_join.lazy()
|
|
119
|
+
.select(
|
|
120
|
+
pl.all().name.prefix('_mg_join_')
|
|
121
|
+
)
|
|
122
|
+
),
|
|
118
123
|
left_on='_index', right_on='_mg_join_index_a', how='inner'
|
|
119
124
|
)
|
|
120
125
|
.with_columns(
|
|
@@ -164,7 +169,7 @@ class MergeCumulative(MergeBase):
|
|
|
164
169
|
self,
|
|
165
170
|
callsets: Iterable[CallsetDefType],
|
|
166
171
|
retain_index: bool = False,
|
|
167
|
-
pre_filter: Optional[Iterable[pl.Expr]] = None,
|
|
172
|
+
pre_filter: Optional[Iterable[pl.Expr] | pl.Expr] = None,
|
|
168
173
|
sort: bool = True,
|
|
169
174
|
add_id: bool = True,
|
|
170
175
|
) -> pl.LazyFrame:
|
|
@@ -196,21 +201,20 @@ class MergeCumulative(MergeBase):
|
|
|
196
201
|
if col not in all_col_dict:
|
|
197
202
|
all_col_dict[col] = dtype
|
|
198
203
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
# Initialize cumulative table
|
|
202
|
-
df_next, src_name, src_index = callsets[0]
|
|
203
|
-
|
|
204
|
-
merge_stat_cols = { # Empty join, gets names of columns this join will return
|
|
205
|
-
col: dtype for col, dtype in self.pairwise_join.join(df_next.head(0), df_next.head(0)).collect_schema().items()
|
|
206
|
-
if col not in {'index_a', 'index_b', 'id_a', 'id_b'}
|
|
207
|
-
}
|
|
204
|
+
# Build reqired_cols from expected columns (includes optional columns), preserve order found in tables
|
|
205
|
+
required_cols = [col for col in all_col_dict.keys() if col in set(self.pairwise_join.expected_cols)]
|
|
208
206
|
|
|
209
207
|
# Cumulative merge
|
|
210
208
|
df_cumulative = None
|
|
209
|
+
merge_stat_cols = None
|
|
211
210
|
|
|
212
211
|
for df_next, src_name, src_index in callsets:
|
|
213
212
|
if df_cumulative is None:
|
|
213
|
+
merge_stat_cols = { # Empty join, gets names of columns this join will return
|
|
214
|
+
col: dtype for col, dtype in self.pairwise_join.join(df_next.head(0), df_next.head(0)).collect_schema().items()
|
|
215
|
+
if col not in {'index_a', 'index_b', 'id_a', 'id_b'}
|
|
216
|
+
}
|
|
217
|
+
|
|
214
218
|
df_cumulative = (
|
|
215
219
|
_init_cumulative(df_next, src_index, src_name, required_cols, merge_stat_cols)
|
|
216
220
|
.sort('chrom', 'pos', 'end', 'id')
|
|
@@ -224,6 +228,7 @@ class MergeCumulative(MergeBase):
|
|
|
224
228
|
df_join = (
|
|
225
229
|
(
|
|
226
230
|
self.pairwise_join.join(df_cumulative, df_next)
|
|
231
|
+
.sort('weight', descending=True)
|
|
227
232
|
.unique('index_a', keep='first')
|
|
228
233
|
.unique('index_b', keep='first')
|
|
229
234
|
.sort('index_a', 'index_b')
|
|
@@ -266,6 +271,9 @@ class MergeCumulative(MergeBase):
|
|
|
266
271
|
_init_cumulative(
|
|
267
272
|
(
|
|
268
273
|
df_next
|
|
274
|
+
# .with_columns(
|
|
275
|
+
# pl.col('index_b').alias('_mg_src_index')
|
|
276
|
+
# )
|
|
269
277
|
.join(
|
|
270
278
|
df_join.lazy(),
|
|
271
279
|
left_on='_mg_src_index', right_on='index_b', how='anti'
|
|
@@ -276,13 +284,8 @@ class MergeCumulative(MergeBase):
|
|
|
276
284
|
)
|
|
277
285
|
|
|
278
286
|
df_cumulative = (
|
|
279
|
-
pl.concat([
|
|
280
|
-
df_match.drop('_mg_src_index', strict=False),
|
|
281
|
-
df_nomatch.drop('_mg_src_index', strict=False),
|
|
282
|
-
df_new.drop('_mg_src_index', strict=False),
|
|
283
|
-
])
|
|
287
|
+
pl.concat([df_match, df_nomatch, df_new])
|
|
284
288
|
.sort('chrom', 'pos', 'end')
|
|
285
|
-
.with_row_index('_mg_src_index')
|
|
286
289
|
.collect()
|
|
287
290
|
.lazy()
|
|
288
291
|
)
|
|
@@ -33,8 +33,9 @@ AUTOGEN_COLS: frozenset[str] = frozenset({
|
|
|
33
33
|
|
|
34
34
|
DEFAULT_CHUNK_SIZE: int = 1_500
|
|
35
35
|
"""
|
|
36
|
-
Default
|
|
37
|
-
|
|
36
|
+
Default number of df_a variants per chunk. Chunking controls peak memory and determines the batch
|
|
37
|
+
size presented to the sequence-alignment thread pool — larger values amortize thread-pool overhead
|
|
38
|
+
better but use more memory. Tune alongside ``n_threads`` based on available RAM and CPU count.
|
|
38
39
|
"""
|
|
39
40
|
|
|
40
41
|
EXPR_OVERLAP_RO = (
|