pav3 3.0.0.dev19__tar.gz → 3.0.0.dev20__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.
- {pav3-3.0.0.dev19/src/pav3.egg-info → pav3-3.0.0.dev20}/PKG-INFO +1 -1
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/__init__.py +1 -1
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/workflow/rules/align.smk +1 -2
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/workflow/rules/call.smk +13 -10
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/vcf.py +150 -77
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20/src/pav3.egg-info}/PKG-INFO +1 -1
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/LICENSE +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/README.md +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/pyproject.toml +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/setup.cfg +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/__main__.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/__init__.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/features.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/lcmodel/__init__.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/lcmodel/_lcmodel.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/lcmodel/_lcmodel_logistic.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/lcmodel/_lcmodel_null.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/lcmodel/_util.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/lift.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/op.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/records.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/score.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/tables.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/align/trim.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/anno.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/call/__init__.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/call/expr.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/call/integrate.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/call/intra.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/call/util.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/cli/__init__.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/cli/_cli.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/cli/_common_opt.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/cli/_subcommand_batch.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/cli/_subcommand_call.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/cli/_subcommand_license.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/const.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/default/model.json +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/human_95_80/model.json +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/human_95_80/model_info.tar.gz +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/human_95_80/weights.npz +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/human_98_80/model.json +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/human_98_80/model_info.tar.gz +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/human_98_80/weights.npz +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/prim_90_50/model.json +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/prim_90_50/model_info.tar.gz +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/prim_90_50/weights.npz +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/primdiv_85_50/model.json +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/primdiv_85_50/model_info.tar.gz +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/lcmodel/primdiv_85_50/weights.npz +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/tracks/alignment_track_fields.tsv +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/tracks/variant_track_fields.tsv +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/workflow/Snakefile +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/workflow/profiles/pav_default/config.yaml +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/workflow/rules/data.smk +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/workflow/rules/pipeline.smk +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/workflow/rules/tracks.smk +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/dev/__init__.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/dev/imports.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/dev/inter.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/dev/path.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/dev/sm.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/dev/tables.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/fig/__init__.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/fig/const.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/fig/density.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/fig/tracks.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/fig/util.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/inv.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/io.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/kde.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/lgsv/__init__.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/lgsv/call.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/lgsv/chain.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/lgsv/interval.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/lgsv/io.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/lgsv/region_kde.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/lgsv/resources.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/lgsv/struct.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/lgsv/variant.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/params.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/pipeline.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/region.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/schema.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/seq.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/util.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/workflow/__init__.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/workflow/__pycache__/__init__.cpython-312.pyc +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/workflow/__pycache__/call.cpython-312.pyc +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/workflow/__pycache__/resource.cpython-312.pyc +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/workflow/call.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/workflow/resource.py +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3.egg-info/SOURCES.txt +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3.egg-info/dependency_links.txt +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3.egg-info/entry_points.txt +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3.egg-info/requires.txt +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3.egg-info/top_level.txt +0 -0
- {pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/tests/test_score_dtype.py +0 -0
|
@@ -14,7 +14,6 @@ import os
|
|
|
14
14
|
|
|
15
15
|
import agglovar
|
|
16
16
|
import pav3
|
|
17
|
-
import snakemake.io
|
|
18
17
|
import polars as pl
|
|
19
18
|
|
|
20
19
|
global PAV_CONFIG
|
|
@@ -35,7 +34,7 @@ global REF_FAI
|
|
|
35
34
|
#
|
|
36
35
|
|
|
37
36
|
def align_index_files(
|
|
38
|
-
wildcards:
|
|
37
|
+
wildcards: dict[str, str]
|
|
39
38
|
):
|
|
40
39
|
"""
|
|
41
40
|
Get a list of reference index files needed by an aligner.
|
|
@@ -51,7 +51,6 @@ rule call_vcf:
|
|
|
51
51
|
benchmark: 'log/benchmark/{asm_name}/call_vcf.tsv'
|
|
52
52
|
threads: POLARS_MAX_THREADS
|
|
53
53
|
run:
|
|
54
|
-
|
|
55
54
|
pattern_var = 'results/{asm_name}/call/call_{vartype}.parquet'
|
|
56
55
|
pattern_callable = 'results/{asm_name}/call_hap/callable_ref_{hap}.parquet'
|
|
57
56
|
|
|
@@ -62,22 +61,26 @@ rule call_vcf:
|
|
|
62
61
|
df_ref_info = pl.read_parquet(input.ref_info)
|
|
63
62
|
|
|
64
63
|
# Get haplotypes
|
|
65
|
-
|
|
64
|
+
hap_list = pav3.vcf.resolve_hap_list(
|
|
66
65
|
pav3.pipeline.get_hap_list(wildcards.asm_name, ASM_TABLE),
|
|
67
66
|
pav_params.vcf_haplotypes,
|
|
68
67
|
)
|
|
69
68
|
|
|
70
|
-
if not
|
|
69
|
+
if not hap_list:
|
|
71
70
|
raise ValueError(
|
|
72
71
|
f'No haplotypes defined for assembly "{wildcards.asm_name}"'
|
|
73
72
|
)
|
|
74
73
|
|
|
74
|
+
hap_order = [
|
|
75
|
+
(wildcards.asm_name, hap) for hap in hap_list
|
|
76
|
+
]
|
|
77
|
+
|
|
75
78
|
# Add callable table for each genotype
|
|
76
|
-
|
|
77
|
-
hap: pl.scan_parquet(
|
|
79
|
+
callable_dict = {
|
|
80
|
+
(wildcards.asm_name, hap): pl.scan_parquet(
|
|
78
81
|
pattern_callable.format(asm_name=wildcards.asm_name, hap=hap)
|
|
79
82
|
)
|
|
80
|
-
for hap in
|
|
83
|
+
for hap in hap_list
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
# Get genotype tables
|
|
@@ -97,7 +100,7 @@ rule call_vcf:
|
|
|
97
100
|
.with_row_index('_index')
|
|
98
101
|
)
|
|
99
102
|
|
|
100
|
-
if vartype == 'snv':
|
|
103
|
+
if vartype == 'snv' and df.collect_schema().get('vartype') is None:
|
|
101
104
|
df = df.with_columns(pl.lit('SNV').alias('vartype'))
|
|
102
105
|
|
|
103
106
|
# Initialize VCF fields (all but FORMAT and sample columns)
|
|
@@ -122,10 +125,10 @@ rule call_vcf:
|
|
|
122
125
|
try:
|
|
123
126
|
df = (
|
|
124
127
|
df.join(
|
|
125
|
-
pav3.vcf.
|
|
128
|
+
pav3.vcf.gt_column_asm(
|
|
126
129
|
df,
|
|
127
|
-
|
|
128
|
-
|
|
130
|
+
wildcards.asm_name,
|
|
131
|
+
callable_dict,
|
|
129
132
|
col_name='_vcf_field_gt',
|
|
130
133
|
separator='|',
|
|
131
134
|
),
|
|
@@ -17,13 +17,14 @@ __all__ = [
|
|
|
17
17
|
'vcf_fields_seq_insdel',
|
|
18
18
|
'vcf_fields_sym',
|
|
19
19
|
'vcf_fields_snv',
|
|
20
|
-
'
|
|
20
|
+
'gt_column_iterator',
|
|
21
|
+
'gt_column_hap',
|
|
21
22
|
'standard_info_fields',
|
|
22
23
|
'reformat_vcf_table',
|
|
23
|
-
'get_hap_source',
|
|
24
24
|
]
|
|
25
25
|
|
|
26
26
|
|
|
27
|
+
import collections
|
|
27
28
|
from collections.abc import Iterable, Mapping
|
|
28
29
|
import datetime
|
|
29
30
|
from pathlib import Path
|
|
@@ -116,10 +117,10 @@ class AltField:
|
|
|
116
117
|
VCF_VERSION = '4.5'
|
|
117
118
|
|
|
118
119
|
INFO_FIELDS = [
|
|
119
|
-
InfoField(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
),
|
|
120
|
+
# InfoField(
|
|
121
|
+
# 'ID', '1', 'String',
|
|
122
|
+
# 'Unique variant ID',
|
|
123
|
+
# ),
|
|
123
124
|
InfoField(
|
|
124
125
|
'SVLEN', '.', 'Integer',
|
|
125
126
|
'Variant length',
|
|
@@ -207,8 +208,8 @@ VARTYPE_COMPAT = {
|
|
|
207
208
|
|
|
208
209
|
|
|
209
210
|
def get_headers(
|
|
210
|
-
|
|
211
|
-
|
|
211
|
+
ref_filename: Optional[str | Path] = None,
|
|
212
|
+
df_ref_info: Optional[pl.DataFrame] = None,
|
|
212
213
|
) -> list[str]:
|
|
213
214
|
|
|
214
215
|
# Lead headers
|
|
@@ -255,16 +256,13 @@ def get_headers(
|
|
|
255
256
|
return headers
|
|
256
257
|
|
|
257
258
|
def init_vcf_fields(
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
259
|
+
df: pl.LazyFrame,
|
|
260
|
+
ref_fa: Optional[str | Path] = None,
|
|
261
|
+
use_sym: Optional[bool] = None,
|
|
262
|
+
vartype: Optional[str] = None,
|
|
262
263
|
) -> pl.LazyFrame:
|
|
263
264
|
"""Initialize VCF fields.
|
|
264
265
|
|
|
265
|
-
If `hap_source` and `hap_callable` are provided, genotypes will be added to the table. If one is provided and
|
|
266
|
-
the other is None, an error is raised.
|
|
267
|
-
|
|
268
266
|
:param df: Variant table with an "_index" column.
|
|
269
267
|
:param ref_fa: Reference FASTA filename. Required for non-SNV variants.
|
|
270
268
|
:param use_sym: Whether to use symbolic alternate records. If None, INS, DEL, and SNV ore not
|
|
@@ -273,7 +271,8 @@ def init_vcf_fields(
|
|
|
273
271
|
this field ensures the variant types is handled consisntently if all variant types
|
|
274
272
|
are not in table `df` or `df` is empty.
|
|
275
273
|
"""
|
|
276
|
-
|
|
274
|
+
if df.collect_schema().get('_index') is None:
|
|
275
|
+
df = df.with_row_index('_index')
|
|
277
276
|
|
|
278
277
|
vartype_set = set(
|
|
279
278
|
df.select(pl.col('vartype').unique()).collect().to_series()
|
|
@@ -388,8 +387,8 @@ def init_vcf_fields(
|
|
|
388
387
|
|
|
389
388
|
|
|
390
389
|
def vcf_fields_seq_insdel(
|
|
391
|
-
|
|
392
|
-
|
|
390
|
+
df: pl.LazyFrame,
|
|
391
|
+
ref_fa: Path | str,
|
|
393
392
|
) -> pl.LazyFrame:
|
|
394
393
|
"""Set POS, REF, and ALT VCF fields for insertions and deletions (non-symbolic).
|
|
395
394
|
|
|
@@ -606,43 +605,122 @@ def vcf_fields_snv(
|
|
|
606
605
|
)
|
|
607
606
|
|
|
608
607
|
|
|
609
|
-
def
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
608
|
+
def gt_column_iterator(
|
|
609
|
+
df: pl.LazyFrame | pl.DataFrame,
|
|
610
|
+
hap_order: Iterable[tuple[str, str]],
|
|
611
|
+
callable_dict: dict[tuple[str, str], pl.LazyFrame | pl.DataFrame],
|
|
612
|
+
gt_col_name: str = 'gt',
|
|
613
|
+
) -> Iterable[tuple[str, pl.LazyFrame]]:
|
|
614
|
+
"""Get genotype columns for all assemblies/samples.
|
|
615
|
+
|
|
616
|
+
Argument `hap_order` is a list of assembly/haplotype pairs, and it determines the order of
|
|
617
|
+
assemblies (or "samples") and the order of haplotypes for each sample. Generally, it should
|
|
618
|
+
list all the haplotypes for a sample sequentially (e.g.
|
|
619
|
+
`[("a", "h1"), ("a", "h2"), ("b", "h1"), ("b", "h2")]`). If assemblies are not listed
|
|
620
|
+
sequentially, then the first accurance of each assembly name determines the order, but
|
|
621
|
+
haplotype order for each assembly is still preserved.
|
|
622
|
+
|
|
623
|
+
Returns an iterator of assembly name and genotype table. The genotype table contains two
|
|
624
|
+
columns: Column "_index" is the index of `df`, and the second column is string genotypes for
|
|
625
|
+
each record with a column name defined by argument `gt_col_name`.
|
|
626
|
+
|
|
627
|
+
:param df: Table of merged variants.
|
|
628
|
+
:param hap_order: An iterable of assembly/haplotype tuples in the order they will appear.
|
|
629
|
+
:param callable_dict: A dict keyed by assembly name and haplotype (tuple) pointing to tables
|
|
630
|
+
of callable reference regions.
|
|
631
|
+
:param gt_col_name: Name of the genotype column in the returned genotype tables. May not be
|
|
632
|
+
"_index".
|
|
633
|
+
|
|
634
|
+
:returns: An iterator of tuples (assembly name, and genotype table).
|
|
635
|
+
"""
|
|
636
|
+
if gt_col_name is None or not (gt_col_name := gt_col_name.strip()):
|
|
637
|
+
gt_col_name = 'gt'
|
|
638
|
+
|
|
639
|
+
if gt_col_name == '_index':
|
|
640
|
+
raise ValueError(
|
|
641
|
+
'Genotype column argument "gt_col_name" cannot use reserved '
|
|
642
|
+
'column name for row indexes, "_index"'
|
|
643
|
+
)
|
|
644
|
+
|
|
645
|
+
# Set and check assembly and haplotype orders
|
|
646
|
+
hap_order = list(hap_order)
|
|
647
|
+
|
|
648
|
+
if dup_asm_hap := [
|
|
649
|
+
asm_hap for asm_hap, count in collections.Counter(f'{asm_name}-{hap}' for asm_name, hap in hap_order).items()
|
|
650
|
+
if count > 1
|
|
651
|
+
]:
|
|
652
|
+
n = len(dup_asm_hap)
|
|
653
|
+
dup_asm_hap = ', '.join(dup_asm_hap[:3]) + ('...' if n > 3 else '')
|
|
654
|
+
raise ValueError(
|
|
655
|
+
f'Assembly/haplotype pairs must be unique when separated by a dash: '
|
|
656
|
+
f'Found {n} duplicate pairs: {dup_asm_hap}'
|
|
657
|
+
)
|
|
658
|
+
|
|
659
|
+
asm_order = list(dict.fromkeys((asm_name for asm_name, hap in hap_order)).keys())
|
|
660
|
+
|
|
661
|
+
# List of ordered haplotypes per assembly
|
|
662
|
+
hap_dict = {
|
|
663
|
+
asm_name_ordered: list(dict.fromkeys((
|
|
664
|
+
hap for asm_name, hap in hap_order if asm_name == asm_name_ordered
|
|
665
|
+
)).keys())
|
|
666
|
+
for asm_name_ordered in asm_order
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
# Callable dict should have LazyFrame
|
|
670
|
+
callable_dict = dict(callable_dict)
|
|
671
|
+
|
|
672
|
+
for (asm_name, hap), df_callable in callable_dict.values():
|
|
673
|
+
if isinstance(df_callable, pl.DataFrame):
|
|
674
|
+
df_callable[(asm_name, hap)] = df_callable.lazy()
|
|
675
|
+
|
|
676
|
+
for asm_name, hap_list in hap_dict.items():
|
|
677
|
+
yield asm_name, gt_column_asm(
|
|
678
|
+
df,
|
|
679
|
+
asm_name=asm_name,
|
|
680
|
+
callable_dict=callable_dict,
|
|
681
|
+
col_name='gt',
|
|
682
|
+
separator='|',
|
|
683
|
+
)
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
def gt_column_asm(
|
|
687
|
+
df: pl.LazyFrame,
|
|
688
|
+
asm_name: str,
|
|
689
|
+
callable_dict: dict[tuple[str, str], pl.LazyFrame],
|
|
690
|
+
col_name: str = 'gt',
|
|
691
|
+
separator: str = '|',
|
|
692
|
+
) -> pl.LazyFrame:
|
|
693
|
+
"""Get a table of genotypes for a single assembly.
|
|
694
|
+
|
|
695
|
+
The genotype string contains "1" (alternate allele), "0" (reference allele), and "." (no call).
|
|
696
|
+
The order of alleles is defined by keys in `callable_dict` for all records matching the
|
|
697
|
+
assembly name.
|
|
617
698
|
|
|
618
699
|
:param df: Variant table with an "_index" column.
|
|
619
|
-
:param
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
haplotype.
|
|
700
|
+
:param asm_name: Assembly name.
|
|
701
|
+
:param callable_dict: A dictionary keys tuple(assembly name, haplotype name) and values
|
|
702
|
+
containing a polars LazyFrame of callable regions.
|
|
623
703
|
:param col_name: Name of the genotype column in the output table.
|
|
624
704
|
:param separator: Genotype separator character ("|" for phased, "/" for unphased).
|
|
625
705
|
|
|
626
|
-
:return: A polars LazyFrame with two columns, "_index" and the
|
|
706
|
+
:return: A polars LazyFrame with two columns, "_index" and the genotype string (column name is
|
|
707
|
+
set by `col_name`).
|
|
627
708
|
"""
|
|
628
|
-
|
|
629
|
-
if len(hap_source) == 0:
|
|
630
|
-
raise ValueError(f'No haplotypes to get genotypes for')
|
|
631
|
-
|
|
632
|
-
if '_index' not in df.collect_schema():
|
|
709
|
+
if df.collect_schema().get('_index') is None:
|
|
633
710
|
df = df.with_row_index('_index')
|
|
634
711
|
|
|
635
712
|
# Start with an index, add genotype columns
|
|
636
713
|
df_gt = df.select('_index')
|
|
637
714
|
|
|
638
|
-
for hap in
|
|
639
|
-
|
|
715
|
+
for (callable_asm_name, hap), df_callable in callable_dict.items():
|
|
716
|
+
if callable_asm_name != asm_name:
|
|
717
|
+
continue
|
|
640
718
|
|
|
641
719
|
# Determine if each value matches this haplotype.
|
|
642
720
|
callable_hap = (
|
|
643
721
|
agglovar.bed.intersect.as_proportion(
|
|
644
722
|
df,
|
|
645
|
-
|
|
723
|
+
df_callable,
|
|
646
724
|
'callable_hap'
|
|
647
725
|
)
|
|
648
726
|
.with_columns(
|
|
@@ -655,12 +733,10 @@ def gt_column(
|
|
|
655
733
|
'_index', 'chrom', 'pos', 'end',
|
|
656
734
|
(
|
|
657
735
|
pl.col('mg_src')
|
|
658
|
-
.list.
|
|
659
|
-
pl.element().struct.field('
|
|
660
|
-
)
|
|
661
|
-
|
|
662
|
-
.alias('in_hap')
|
|
663
|
-
),
|
|
736
|
+
.list.filter(
|
|
737
|
+
pl.element().struct.field('id') == f'{asm_name}-{hap}'
|
|
738
|
+
).list.len() > 0
|
|
739
|
+
).alias('in_hap'),
|
|
664
740
|
)
|
|
665
741
|
.join(
|
|
666
742
|
callable_hap, on='_index', how='left'
|
|
@@ -693,7 +769,7 @@ def gt_column(
|
|
|
693
769
|
|
|
694
770
|
|
|
695
771
|
def standard_info_fields(
|
|
696
|
-
|
|
772
|
+
df: pl.LazyFrame,
|
|
697
773
|
) -> pl.LazyFrame:
|
|
698
774
|
"""Set standard INFO columns.
|
|
699
775
|
|
|
@@ -713,12 +789,12 @@ def standard_info_fields(
|
|
|
713
789
|
.alias('_vcf_info')
|
|
714
790
|
)
|
|
715
791
|
|
|
716
|
-
if 'id' in cols:
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
792
|
+
# if 'id' in cols:
|
|
793
|
+
# df = df.with_columns(
|
|
794
|
+
# pl.col('_vcf_info').list.concat(
|
|
795
|
+
# pl.concat_str(pl.lit('ID='), 'id')
|
|
796
|
+
# )
|
|
797
|
+
# )
|
|
722
798
|
|
|
723
799
|
if 'varlen' in cols:
|
|
724
800
|
df = df.with_columns(
|
|
@@ -865,7 +941,7 @@ def standard_info_fields(
|
|
|
865
941
|
.then(
|
|
866
942
|
pl.col('_vcf_info').list.concat(
|
|
867
943
|
pl.concat_str(
|
|
868
|
-
pl.lit('
|
|
944
|
+
pl.lit('HOMQRY='),
|
|
869
945
|
pl.col('hom_ref').struct.field('up'),
|
|
870
946
|
pl.lit(','),
|
|
871
947
|
pl.col('hom_ref').struct.field('dn'),
|
|
@@ -930,8 +1006,8 @@ def standard_info_fields(
|
|
|
930
1006
|
|
|
931
1007
|
|
|
932
1008
|
def reformat_vcf_table(
|
|
933
|
-
|
|
934
|
-
|
|
1009
|
+
df: pl.LazyFrame,
|
|
1010
|
+
sample_columns: Optional[Mapping[int, str]] = None,
|
|
935
1011
|
) -> pl.LazyFrame:
|
|
936
1012
|
"""Reformat VCF table to VCF format."""
|
|
937
1013
|
|
|
@@ -967,41 +1043,38 @@ def reformat_vcf_table(
|
|
|
967
1043
|
)
|
|
968
1044
|
|
|
969
1045
|
|
|
970
|
-
def
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
) ->
|
|
974
|
-
"""Get a
|
|
1046
|
+
def resolve_hap_list(
|
|
1047
|
+
hap_list: Iterable[str],
|
|
1048
|
+
vcf_haplotypes: Optional[str],
|
|
1049
|
+
) -> list[str]:
|
|
1050
|
+
"""Get a list of haplotypes in the order they should appear for a sample.
|
|
975
1051
|
|
|
976
1052
|
:param hap_list: List of haplotypes defined for this assembly.
|
|
977
|
-
:param vcf_haplotypes: Optional, a string of haplotypes separated by commas to include in the
|
|
978
|
-
defined, all haplotypes must appear in `hap_list` and the
|
|
1053
|
+
:param vcf_haplotypes: Optional, a string of haplotypes separated by commas to include in the
|
|
1054
|
+
VCF haplotypes. If defined, all haplotypes must appear in `hap_list` and the returned list
|
|
1055
|
+
is subset and ordered by this list.
|
|
979
1056
|
|
|
980
|
-
:
|
|
1057
|
+
:returns: List of haplotypes.
|
|
981
1058
|
"""
|
|
982
|
-
|
|
1059
|
+
hap_list = list(hap_list)
|
|
983
1060
|
|
|
984
1061
|
if vcf_haplotypes is not None:
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
if (missing_hap := set(vcf_haps) - set(hap_list)):
|
|
988
|
-
missing_hap = [
|
|
989
|
-
f'"{hap}"' for hap in sorted(missing_hap)
|
|
990
|
-
]
|
|
1062
|
+
vcf_hap_list = [hap.strip() for hap in vcf_haplotypes.split(',') if hap.strip()]
|
|
991
1063
|
|
|
1064
|
+
if missing_hap := [hap for hap in vcf_hap_list if hap not in set(hap_list)]:
|
|
992
1065
|
missing_n = len(missing_hap)
|
|
993
1066
|
|
|
994
|
-
missing_hap = ', '.join(
|
|
1067
|
+
missing_hap = ', '.join([
|
|
1068
|
+
f'"{hap}"' for hap in missing_hap
|
|
1069
|
+
]) + ('...' if missing_n > 3 else '')
|
|
995
1070
|
|
|
996
1071
|
raise ValueError(
|
|
997
|
-
f'Configuration item "vcf_haplotypes" defines {missing_n} haplotypes
|
|
998
|
-
f'
|
|
1072
|
+
f'Configuration item "vcf_haplotypes" defines {missing_n} haplotypes: '
|
|
1073
|
+
f'{missing_hap}'
|
|
999
1074
|
)
|
|
1000
1075
|
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
return hap_source
|
|
1076
|
+
return vcf_hap_list
|
|
1077
|
+
return hap_list
|
|
1005
1078
|
|
|
1006
1079
|
|
|
1007
1080
|
class _LockingPysam():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/data/workflow/profiles/pav_default/config.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/workflow/__pycache__/__init__.cpython-312.pyc
RENAMED
|
File without changes
|
|
File without changes
|
{pav3-3.0.0.dev19 → pav3-3.0.0.dev20}/src/pav3/workflow/__pycache__/resource.cpython-312.pyc
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|