pie-phasing-benchmark 0.11.1__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.
- pie_phasing_benchmark-0.11.1/LICENSE +21 -0
- pie_phasing_benchmark-0.11.1/PKG-INFO +185 -0
- pie_phasing_benchmark-0.11.1/README.md +164 -0
- pie_phasing_benchmark-0.11.1/pie/pie/__init__.py +0 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/F1_related.py +39 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/__init__.py +0 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/cal_NGx0.py +14 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/cal_ref.py +62 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/check_filters.py +22 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/cli.py +114 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/evaluation.py +339 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/intersect.py +167 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/lib/__init__.py +0 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/lib/hamming.c +40 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/pie_class.py +83 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/raw_metrics.py +51 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/read_bed.py +37 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/read_vcf.py +76 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/safediv.py +7 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/sort_chrom.py +18 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/write_block.py +19 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/write_evaluation.py +128 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/write_genotype.py +122 -0
- pie_phasing_benchmark-0.11.1/pie/pie/module/write_lmdb.py +20 -0
- pie_phasing_benchmark-0.11.1/pie/pie/pie.py +143 -0
- pie_phasing_benchmark-0.11.1/pie/pie_phasing_benchmark.egg-info/PKG-INFO +185 -0
- pie_phasing_benchmark-0.11.1/pie/pie_phasing_benchmark.egg-info/SOURCES.txt +35 -0
- pie_phasing_benchmark-0.11.1/pie/pie_phasing_benchmark.egg-info/dependency_links.txt +1 -0
- pie_phasing_benchmark-0.11.1/pie/pie_phasing_benchmark.egg-info/entry_points.txt +2 -0
- pie_phasing_benchmark-0.11.1/pie/pie_phasing_benchmark.egg-info/requires.txt +14 -0
- pie_phasing_benchmark-0.11.1/pie/pie_phasing_benchmark.egg-info/top_level.txt +1 -0
- pie_phasing_benchmark-0.11.1/pyproject.toml +3 -0
- pie_phasing_benchmark-0.11.1/setup.cfg +4 -0
- pie_phasing_benchmark-0.11.1/setup.py +53 -0
- pie_phasing_benchmark-0.11.1/tests/test_bed.py +20 -0
- pie_phasing_benchmark-0.11.1/tests/test_format.py +51 -0
- pie_phasing_benchmark-0.11.1/tests/test_include_genotype.py +20 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Jun Mencius
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pie-phasing-benchmark
|
|
3
|
+
Version: 0.11.1
|
|
4
|
+
Summary: Phasing all-in-one evaluator
|
|
5
|
+
Home-page: https://github.com/JMencius/pie
|
|
6
|
+
Author: Jun Mencius
|
|
7
|
+
Author-email: zjmeng22@m.fudan.edu.cn
|
|
8
|
+
Keywords: pie,haplotype,phasing,benchmark
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: click>=8.1.8
|
|
13
|
+
Requires-Dist: cyvcf2>=0.31.3
|
|
14
|
+
Requires-Dist: sortedcontainers>=2.4.0
|
|
15
|
+
Requires-Dist: pyfastx>=2.2.0
|
|
16
|
+
Requires-Dist: lmdb==1.8.1; python_version < "3.9"
|
|
17
|
+
Requires-Dist: lmdb>=2.0.0; python_version >= "3.9"
|
|
18
|
+
Requires-Dist: numba>=0.58.1
|
|
19
|
+
Provides-Extra: test
|
|
20
|
+
Requires-Dist: pytest; extra == "test"
|
|
21
|
+
|
|
22
|
+
<img src="pie_logo.png" width = "100">
|
|
23
|
+
|
|
24
|
+
# pie
|
|
25
|
+
Phasing all-In-one Evaluator, for haplotype phasing evaluation
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
Currently, `Pie` does not support online installation, but will be available through `pip` or `conda` upon publication.
|
|
29
|
+
|
|
30
|
+
Installation will finish in a few minutes.
|
|
31
|
+
|
|
32
|
+
### Use `pip` to conduct local installation
|
|
33
|
+
1. Create new virtual environment
|
|
34
|
+
```
|
|
35
|
+
conda create -n pie python=3.8;
|
|
36
|
+
conda activate pie;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
2. Navigate to the base directory, which contains `setup.py`. Use `pip` to install `pie`.
|
|
40
|
+
```
|
|
41
|
+
pip install .;
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Usages
|
|
45
|
+
### Required arguments
|
|
46
|
+
| Parameters | Description | Format or example |
|
|
47
|
+
|:---:|:---:|:---:|
|
|
48
|
+
| `-i or --input` | file for evaluation | .vcf / .vcf.gz |
|
|
49
|
+
| `-c or --compare` | ground truth file | .vcf / .vcf.gz |
|
|
50
|
+
| `-r or --ref` | reference file | .fa / .fasta / .fai |
|
|
51
|
+
| `-o or --output` | Output file prefix | exmaple: ./test/output_name |
|
|
52
|
+
|
|
53
|
+
### Recommend flag
|
|
54
|
+
Use `--verbose` to monitor the running process and enable detailed logging.
|
|
55
|
+
|
|
56
|
+
### Full usages
|
|
57
|
+
```
|
|
58
|
+
Usage: pie [OPTIONS]
|
|
59
|
+
|
|
60
|
+
Options:
|
|
61
|
+
-i, --input TEXT Input vcf/vcf.gz file for evaluation [required]
|
|
62
|
+
-n, --name TEXT User defined sample name, [default: Sample]
|
|
63
|
+
-c, --compare TEXT Ground truth vcf/vcf.gz file for comparison
|
|
64
|
+
[required]
|
|
65
|
+
-r, --ref TEXT Reference file fasta file (.fasta or .fa) or fasta
|
|
66
|
+
index file (.fai) [required]
|
|
67
|
+
-o, --output TEXT Output file prefix, such as -o ./test/output_name
|
|
68
|
+
[required]
|
|
69
|
+
-t, --threads INTEGER Maximum numbers of parallel threads [default: 24]
|
|
70
|
+
-m, --max-len INTEGER Maximum variant distance for pairwise calculation
|
|
71
|
+
[default: 250000]
|
|
72
|
+
-b, --bed TEXT .bed file specifying genomic regions to include
|
|
73
|
+
[default: None]
|
|
74
|
+
--min-sv INTEGER Minimal length threshold of Structral Variant
|
|
75
|
+
[default: 30, ALT length > 30 bp is SV]
|
|
76
|
+
--chrom TEXT Chromosome to evaluate,use comma to join chromosome
|
|
77
|
+
name e.g. --chrom chr1,chr2,chr3
|
|
78
|
+
[default:chr1,chr2,chr3,...,chr22]
|
|
79
|
+
--sexchrom TEXT Sex chromosme,use comma to join chromosome name e.g.
|
|
80
|
+
--sexchrom chrX,chrY [default: chrX,chrY]
|
|
81
|
+
--mincount INTEGER Minimum numbers of phased sites in a phase block
|
|
82
|
+
[default: 2]
|
|
83
|
+
--block Output phasing block start and end positions in a BED
|
|
84
|
+
file
|
|
85
|
+
--no-sex Ignore sex chromosome
|
|
86
|
+
--canonical Canonical mode, only evaluate single mutation SNV
|
|
87
|
+
ignore double heterozygous site
|
|
88
|
+
--only-snv Only evaluate single nucleotide variation
|
|
89
|
+
--only-indel Only evaluate insertion and deletion
|
|
90
|
+
--only-sv Only evaluate structural variant
|
|
91
|
+
--no-snv Ignore single nucleotide variation
|
|
92
|
+
--no-indel Ignore insertion and deletion
|
|
93
|
+
--no-sv Ignore structural variant
|
|
94
|
+
--no-double Ignore double heterozygous site
|
|
95
|
+
--no-sort Do not sort chromosome or regions, directly use the
|
|
96
|
+
input order
|
|
97
|
+
--verbose Enable verbose mode, printing parameters and progress
|
|
98
|
+
to standard output
|
|
99
|
+
--version Show the version and exit.
|
|
100
|
+
--help Show this message and exit.
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Exmaples
|
|
104
|
+
Suppose `phase.vcf` is the sample VCF file to be evaluated against the ground truth VCF file (`truth.vcf`).
|
|
105
|
+
1. (Comprehensive) Evaluate all autosome
|
|
106
|
+
```
|
|
107
|
+
pie --verbose -i phase.vcf -c truth.vcf -r ref.fa -o ./output/comprehensive
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
2. (Chromosome specific) Restrict evaluation to selected chromosome
|
|
111
|
+
```
|
|
112
|
+
pie --verbose --chrom chr6 -i phase.vcf -c truth.vcf -r ref.fa -o ./output/chr6
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
3. (Region specific) Focus only on regions defined in a BED file.
|
|
116
|
+
```
|
|
117
|
+
pie --verbose -i phase.vcf -c truth.vcf -r ref.fa --bed mhc.bed -o ./output/mhc
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
4. (Filter) Exclude structural variants (SV) from the analysis
|
|
121
|
+
```
|
|
122
|
+
pie --verbose -i phase.vcf -c truth.vcf -r ref.fa --no-sv -o ./output/no_sv
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
5. (More output) Output raw phasing block start and end positions to a BED file
|
|
126
|
+
```
|
|
127
|
+
pie --verbose -i phase.vcf -c truth.vcf -r ref.fa --block -o ./output/more
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
6. (Miscellaneous) Evaluate only SNVs on chromosome 6 and output raw block start and end positions to a BED file.
|
|
131
|
+
```
|
|
132
|
+
pie --verbose -i phase.vcf -c truth.vcf -r ref.fa --chrom chr6 --only-snv --block -o ./output/misc
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Test data
|
|
136
|
+
Small query and truth test files are provided in [here](./tests) including three formats:
|
|
137
|
+
| Filename | Format | Description |
|
|
138
|
+
|:---:|:---:|:---:|
|
|
139
|
+
| small_query.vcf | VCF | Uncompressed VCF |
|
|
140
|
+
| small_query.vcf.gz | VCF.GZ | Compressed VCF |
|
|
141
|
+
| small_query.bcf | BCF | Binary VCF |
|
|
142
|
+
|
|
143
|
+
`small_truth.vcf` is provided as the truth.
|
|
144
|
+
|
|
145
|
+
The `VCF` format follows regulations in <https://samtools.github.io/hts-specs/VCFv4.1.pdf>
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
## Output file
|
|
149
|
+
| Output suffix | Description | Condition |
|
|
150
|
+
|:---:|:---:|:--:|
|
|
151
|
+
| `.variant.stats.csv` | Genotype evaluation result and phased percentage | Always generated |
|
|
152
|
+
| `.perchrom.csv` | Per chromosome phasing evaluation result | Always generated |
|
|
153
|
+
| `.overall.csv` | Overall sample evaluation result | Always generated |
|
|
154
|
+
| `.blocks.bed` | Raw phasing block start end in `-i` or `--input` file | with `--block` set |
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
## Resouce consumption
|
|
158
|
+
`Pie` is expected to completed evaluation within minutes with the default 24 threads on a stardard X86 platfrom.
|
|
159
|
+
|
|
160
|
+
The actual performance may vary depending on factors such as size of `vcf`, I/O speed, memory speed, and CPU capabilities.
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
## Acknowledgements
|
|
164
|
+
`Pie` is dependent on the following libraries, we are grateful to all the developers/maintainers:
|
|
165
|
+
- [click](https://github.com/pallets/click): Python command line
|
|
166
|
+
- [cyvcf2](https://github.com/brentp/cyvcf2): VCF/BCF processing
|
|
167
|
+
- [pyfastx](https://github.com/lmdu/pyfastx): Reference FASTA processing
|
|
168
|
+
- [numba](https://github.com/numba/numba): JIT accerleration
|
|
169
|
+
- [sortedcontainers](https://github.com/grantjenks/python-sortedcontainers): Python Sorted Container Types
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<img src="pie_logo.png" width = "100">
|
|
2
|
+
|
|
3
|
+
# pie
|
|
4
|
+
Phasing all-In-one Evaluator, for haplotype phasing evaluation
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
Currently, `Pie` does not support online installation, but will be available through `pip` or `conda` upon publication.
|
|
8
|
+
|
|
9
|
+
Installation will finish in a few minutes.
|
|
10
|
+
|
|
11
|
+
### Use `pip` to conduct local installation
|
|
12
|
+
1. Create new virtual environment
|
|
13
|
+
```
|
|
14
|
+
conda create -n pie python=3.8;
|
|
15
|
+
conda activate pie;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
2. Navigate to the base directory, which contains `setup.py`. Use `pip` to install `pie`.
|
|
19
|
+
```
|
|
20
|
+
pip install .;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usages
|
|
24
|
+
### Required arguments
|
|
25
|
+
| Parameters | Description | Format or example |
|
|
26
|
+
|:---:|:---:|:---:|
|
|
27
|
+
| `-i or --input` | file for evaluation | .vcf / .vcf.gz |
|
|
28
|
+
| `-c or --compare` | ground truth file | .vcf / .vcf.gz |
|
|
29
|
+
| `-r or --ref` | reference file | .fa / .fasta / .fai |
|
|
30
|
+
| `-o or --output` | Output file prefix | exmaple: ./test/output_name |
|
|
31
|
+
|
|
32
|
+
### Recommend flag
|
|
33
|
+
Use `--verbose` to monitor the running process and enable detailed logging.
|
|
34
|
+
|
|
35
|
+
### Full usages
|
|
36
|
+
```
|
|
37
|
+
Usage: pie [OPTIONS]
|
|
38
|
+
|
|
39
|
+
Options:
|
|
40
|
+
-i, --input TEXT Input vcf/vcf.gz file for evaluation [required]
|
|
41
|
+
-n, --name TEXT User defined sample name, [default: Sample]
|
|
42
|
+
-c, --compare TEXT Ground truth vcf/vcf.gz file for comparison
|
|
43
|
+
[required]
|
|
44
|
+
-r, --ref TEXT Reference file fasta file (.fasta or .fa) or fasta
|
|
45
|
+
index file (.fai) [required]
|
|
46
|
+
-o, --output TEXT Output file prefix, such as -o ./test/output_name
|
|
47
|
+
[required]
|
|
48
|
+
-t, --threads INTEGER Maximum numbers of parallel threads [default: 24]
|
|
49
|
+
-m, --max-len INTEGER Maximum variant distance for pairwise calculation
|
|
50
|
+
[default: 250000]
|
|
51
|
+
-b, --bed TEXT .bed file specifying genomic regions to include
|
|
52
|
+
[default: None]
|
|
53
|
+
--min-sv INTEGER Minimal length threshold of Structral Variant
|
|
54
|
+
[default: 30, ALT length > 30 bp is SV]
|
|
55
|
+
--chrom TEXT Chromosome to evaluate,use comma to join chromosome
|
|
56
|
+
name e.g. --chrom chr1,chr2,chr3
|
|
57
|
+
[default:chr1,chr2,chr3,...,chr22]
|
|
58
|
+
--sexchrom TEXT Sex chromosme,use comma to join chromosome name e.g.
|
|
59
|
+
--sexchrom chrX,chrY [default: chrX,chrY]
|
|
60
|
+
--mincount INTEGER Minimum numbers of phased sites in a phase block
|
|
61
|
+
[default: 2]
|
|
62
|
+
--block Output phasing block start and end positions in a BED
|
|
63
|
+
file
|
|
64
|
+
--no-sex Ignore sex chromosome
|
|
65
|
+
--canonical Canonical mode, only evaluate single mutation SNV
|
|
66
|
+
ignore double heterozygous site
|
|
67
|
+
--only-snv Only evaluate single nucleotide variation
|
|
68
|
+
--only-indel Only evaluate insertion and deletion
|
|
69
|
+
--only-sv Only evaluate structural variant
|
|
70
|
+
--no-snv Ignore single nucleotide variation
|
|
71
|
+
--no-indel Ignore insertion and deletion
|
|
72
|
+
--no-sv Ignore structural variant
|
|
73
|
+
--no-double Ignore double heterozygous site
|
|
74
|
+
--no-sort Do not sort chromosome or regions, directly use the
|
|
75
|
+
input order
|
|
76
|
+
--verbose Enable verbose mode, printing parameters and progress
|
|
77
|
+
to standard output
|
|
78
|
+
--version Show the version and exit.
|
|
79
|
+
--help Show this message and exit.
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Exmaples
|
|
83
|
+
Suppose `phase.vcf` is the sample VCF file to be evaluated against the ground truth VCF file (`truth.vcf`).
|
|
84
|
+
1. (Comprehensive) Evaluate all autosome
|
|
85
|
+
```
|
|
86
|
+
pie --verbose -i phase.vcf -c truth.vcf -r ref.fa -o ./output/comprehensive
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
2. (Chromosome specific) Restrict evaluation to selected chromosome
|
|
90
|
+
```
|
|
91
|
+
pie --verbose --chrom chr6 -i phase.vcf -c truth.vcf -r ref.fa -o ./output/chr6
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
3. (Region specific) Focus only on regions defined in a BED file.
|
|
95
|
+
```
|
|
96
|
+
pie --verbose -i phase.vcf -c truth.vcf -r ref.fa --bed mhc.bed -o ./output/mhc
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
4. (Filter) Exclude structural variants (SV) from the analysis
|
|
100
|
+
```
|
|
101
|
+
pie --verbose -i phase.vcf -c truth.vcf -r ref.fa --no-sv -o ./output/no_sv
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
5. (More output) Output raw phasing block start and end positions to a BED file
|
|
105
|
+
```
|
|
106
|
+
pie --verbose -i phase.vcf -c truth.vcf -r ref.fa --block -o ./output/more
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
6. (Miscellaneous) Evaluate only SNVs on chromosome 6 and output raw block start and end positions to a BED file.
|
|
110
|
+
```
|
|
111
|
+
pie --verbose -i phase.vcf -c truth.vcf -r ref.fa --chrom chr6 --only-snv --block -o ./output/misc
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Test data
|
|
115
|
+
Small query and truth test files are provided in [here](./tests) including three formats:
|
|
116
|
+
| Filename | Format | Description |
|
|
117
|
+
|:---:|:---:|:---:|
|
|
118
|
+
| small_query.vcf | VCF | Uncompressed VCF |
|
|
119
|
+
| small_query.vcf.gz | VCF.GZ | Compressed VCF |
|
|
120
|
+
| small_query.bcf | BCF | Binary VCF |
|
|
121
|
+
|
|
122
|
+
`small_truth.vcf` is provided as the truth.
|
|
123
|
+
|
|
124
|
+
The `VCF` format follows regulations in <https://samtools.github.io/hts-specs/VCFv4.1.pdf>
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
## Output file
|
|
128
|
+
| Output suffix | Description | Condition |
|
|
129
|
+
|:---:|:---:|:--:|
|
|
130
|
+
| `.variant.stats.csv` | Genotype evaluation result and phased percentage | Always generated |
|
|
131
|
+
| `.perchrom.csv` | Per chromosome phasing evaluation result | Always generated |
|
|
132
|
+
| `.overall.csv` | Overall sample evaluation result | Always generated |
|
|
133
|
+
| `.blocks.bed` | Raw phasing block start end in `-i` or `--input` file | with `--block` set |
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
## Resouce consumption
|
|
137
|
+
`Pie` is expected to completed evaluation within minutes with the default 24 threads on a stardard X86 platfrom.
|
|
138
|
+
|
|
139
|
+
The actual performance may vary depending on factors such as size of `vcf`, I/O speed, memory speed, and CPU capabilities.
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
## Acknowledgements
|
|
143
|
+
`Pie` is dependent on the following libraries, we are grateful to all the developers/maintainers:
|
|
144
|
+
- [click](https://github.com/pallets/click): Python command line
|
|
145
|
+
- [cyvcf2](https://github.com/brentp/cyvcf2): VCF/BCF processing
|
|
146
|
+
- [pyfastx](https://github.com/lmdu/pyfastx): Reference FASTA processing
|
|
147
|
+
- [numba](https://github.com/numba/numba): JIT accerleration
|
|
148
|
+
- [sortedcontainers](https://github.com/grantjenks/python-sortedcontainers): Python Sorted Container Types
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
File without changes
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def cal_precision(TP: int, FP: int) -> float:
|
|
5
|
+
denominator = TP + FP
|
|
6
|
+
|
|
7
|
+
if denominator != 0:
|
|
8
|
+
precision = TP / denominator
|
|
9
|
+
return precision
|
|
10
|
+
else:
|
|
11
|
+
return math.nan
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def cal_recall(TP: int, FN: int) -> float:
|
|
15
|
+
denominator = TP + FN
|
|
16
|
+
|
|
17
|
+
if denominator != 0:
|
|
18
|
+
recall = TP / denominator
|
|
19
|
+
return recall
|
|
20
|
+
else:
|
|
21
|
+
return math.nan
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def cal_f1(precision: float, recall: float) -> float:
|
|
25
|
+
denominator = precision + recall
|
|
26
|
+
if (denominator != 0) and not(math.isnan(denominator)):
|
|
27
|
+
F1 = (2 * precision * recall) / denominator
|
|
28
|
+
return F1
|
|
29
|
+
else:
|
|
30
|
+
return math.nan
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def cal_all(TP: int, FP: int, FN: int) -> tuple:
|
|
34
|
+
precision = cal_precision(TP, FP)
|
|
35
|
+
recall = cal_recall(TP, FN)
|
|
36
|
+
f1 = cal_f1(precision, recall)
|
|
37
|
+
|
|
38
|
+
return (precision, recall, f1)
|
|
39
|
+
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
def cal_NGx0(len_list: list, total_len: int, p: int) -> int:
|
|
2
|
+
total_len = int(total_len)
|
|
3
|
+
target = total_len * p / 100
|
|
4
|
+
|
|
5
|
+
if sum(len_list) < target:
|
|
6
|
+
return None
|
|
7
|
+
|
|
8
|
+
len_list.sort(reverse = True)
|
|
9
|
+
|
|
10
|
+
cummulative = 0
|
|
11
|
+
for i in len_list:
|
|
12
|
+
cummulative += i
|
|
13
|
+
if cummulative >= target:
|
|
14
|
+
return i
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import pyfastx
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_ref_len(ref: str, chrom: list) -> dict:
|
|
8
|
+
suffix = os.path.splitext(ref)[1]
|
|
9
|
+
if suffix == ".fa" or suffix == ".fasta":
|
|
10
|
+
length_dict = fasta_mode(ref, chrom)
|
|
11
|
+
return length_dict
|
|
12
|
+
elif suffix == ".fai":
|
|
13
|
+
length_dict = fai_mode(ref, chrom)
|
|
14
|
+
return length_dict
|
|
15
|
+
else:
|
|
16
|
+
logging.error("Invalid file suffix of the reference file, must be either .fasta/.fa or .fai")
|
|
17
|
+
raise ValueError("Invalid file suffix of the reference file")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def fasta_mode(ref: str, chrom: list) -> dict:
|
|
22
|
+
chr_len = dict()
|
|
23
|
+
exist = set()
|
|
24
|
+
for name, seq in pyfastx.Fasta(ref, build_index = False):
|
|
25
|
+
if name in chrom:
|
|
26
|
+
chr_len[name] = len(seq)
|
|
27
|
+
exist.add(name)
|
|
28
|
+
|
|
29
|
+
if len(chr_len) == len(chrom):
|
|
30
|
+
return chr_len
|
|
31
|
+
else:
|
|
32
|
+
for i in chrom:
|
|
33
|
+
if i not in exist:
|
|
34
|
+
logging.warning(f"{i} not in reference file")
|
|
35
|
+
return chr_len
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def fai_mode(ref_fai: str, chrom: list) -> dict:
|
|
40
|
+
chr_len = dict()
|
|
41
|
+
exist = set()
|
|
42
|
+
with open(ref_fai, 'r') as f:
|
|
43
|
+
for line in f:
|
|
44
|
+
m = line.split()
|
|
45
|
+
if len(m) >= 2:
|
|
46
|
+
name = m[0]
|
|
47
|
+
if name in chrom:
|
|
48
|
+
chr_len[name] = int(m[1])
|
|
49
|
+
exist.add(name)
|
|
50
|
+
|
|
51
|
+
if len(chr_len) == len(chrom):
|
|
52
|
+
return chr_len
|
|
53
|
+
else:
|
|
54
|
+
for i in chrom:
|
|
55
|
+
if i not in exist:
|
|
56
|
+
logging.warning(f"{i} not in reference file")
|
|
57
|
+
return chr_len
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def check_filters(filters: dict) -> bool:
|
|
5
|
+
only_count = ([filters["only_snv"], filters["only_indel"], filters["only_sv"]]).count(True)
|
|
6
|
+
if only_count > 1:
|
|
7
|
+
logging.error("Only one of --only_snv, --only_indel, or --only_sv can be set at a time.")
|
|
8
|
+
return False
|
|
9
|
+
|
|
10
|
+
if filters["only_snv"] and filters["no_snv"]:
|
|
11
|
+
logging.error("Can not set --only_snv and --no_snv simultaneously")
|
|
12
|
+
return False
|
|
13
|
+
|
|
14
|
+
if filters["only_indel"] and filters["no_indel"]:
|
|
15
|
+
logging.error("Can not set --only_indel and --no_indel simultaneously")
|
|
16
|
+
return False
|
|
17
|
+
|
|
18
|
+
if filters["only_sv"] and filters["no_sv"]:
|
|
19
|
+
logging.error("Can not set --only_sv and --no_sv simultaneously")
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
return True
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import click
|
|
4
|
+
import math
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from pie.module.sort_chrom import sort_chrom
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
@click.command()
|
|
10
|
+
@click.option("-i", "--input", required = True, type = str, help = "Input vcf/vcf.gz file for evaluation")
|
|
11
|
+
@click.option("-n", "--name", default = "Sample", type = str, help = "User defined sample name, [default: Sample]")
|
|
12
|
+
@click.option("-c", "--compare", required = True, type = str, help = "Ground truth vcf/vcf.gz file for comparison")
|
|
13
|
+
@click.option("-r", "--ref", required = True, type = str, help = "Reference file fasta file (.fasta or .fa) or fasta index file (.fai)")
|
|
14
|
+
@click.option("-o", "--output", required = True, type = str, help = "Output file prefix, such as -o ./test/output_name")
|
|
15
|
+
@click.option("-t", "--threads", default = 24, type = int, help = "Maximum numbers of parallel threads [default: 24]")
|
|
16
|
+
@click.option("-m", "--max-len", default = 250 * 10**3, type = int, help = "Maximum variant distance for pairwise calculation [default: 250000]")
|
|
17
|
+
@click.option("-b", "--bed", default = None, type = str, help = r".bed file specifying genomic regions to include [default: None]")
|
|
18
|
+
@click.option("--min-sv", default = 30, type = int, help = "Minimal length threshold of Structral Variant [default: 30, ALT length > 30 bp is SV]")
|
|
19
|
+
@click.option("--chrom", default = ','.join(["chr" + str(i) for i in range(1, 23)]), type = str, help = "Chromosome to evaluate,use comma to join chromosome name e.g. --chrom chr1,chr2,chr3 [default:chr1,chr2,chr3,...,chr22]")
|
|
20
|
+
@click.option("--sexchrom", default = "chrX,chrY", type = str, help = "Sex chromosme,use comma to join chromosome name e.g. --sexchrom chrX,chrY [default: chrX,chrY]")
|
|
21
|
+
@click.option("--mincount", default = 2, type = int, help = "Minimum numbers of phased sites in a phase block [default: 2]")
|
|
22
|
+
@click.option("--block", is_flag = True, help = r"Output phasing block start and end positions in a BED file")
|
|
23
|
+
@click.option("--no-sex", is_flag = True, help = "Ignore sex chromosome")
|
|
24
|
+
@click.option("--canonical", is_flag = True, help = "Canonical mode, only evaluate single mutation SNV ignore double heterozygous site")
|
|
25
|
+
@click.option("--only-snv", is_flag = True, help = "Only evaluate single nucleotide variation")
|
|
26
|
+
@click.option("--only-indel", is_flag = True, help = "Only evaluate insertion and deletion")
|
|
27
|
+
@click.option("--only-sv", is_flag = True, help = "Only evaluate structural variant")
|
|
28
|
+
@click.option("--no-snv", is_flag = True, help = "Ignore single nucleotide variation")
|
|
29
|
+
@click.option("--no-indel", is_flag = True, help = "Ignore insertion and deletion")
|
|
30
|
+
@click.option("--no-sv", is_flag = True, help = "Ignore structural variant")
|
|
31
|
+
@click.option("--no-double", is_flag = True, help = "Ignore double heterozygous site")
|
|
32
|
+
@click.option("--no-sort", is_flag = True, help = "Do not sort chromosome or regions, directly use the input order")
|
|
33
|
+
@click.option("--lmdb", is_flag = True, hidden = True, help = "Output intermediate hamming result as .lmdb file")
|
|
34
|
+
@click.option("--verbose", is_flag = True, help = "Enable verbose mode, printing parameters and progress to standard output")
|
|
35
|
+
@click.version_option(version="0.11.1", prog_name = r"Phasing all-in-one evaluator (pie), based on Python 3.7+")
|
|
36
|
+
def cli(input, name, compare, ref, output, threads, max_len, bed, min_sv, chrom, sexchrom, mincount, canonical, block, no_sex, only_snv, only_indel, only_sv, no_snv, no_indel, no_sv, no_double, no_sort, lmdb, verbose) -> tuple:
|
|
37
|
+
|
|
38
|
+
# set logging
|
|
39
|
+
logging.basicConfig(level = logging.DEBUG, format = "%(asctime)s - %(levelname)s - %(message)s")
|
|
40
|
+
|
|
41
|
+
# clean parameters
|
|
42
|
+
input = os.path.abspath(input)
|
|
43
|
+
compare = os.path.abspath(compare)
|
|
44
|
+
ref = os.path.abspath(ref)
|
|
45
|
+
|
|
46
|
+
if bed:
|
|
47
|
+
bed = os.path.abspath(bed)
|
|
48
|
+
|
|
49
|
+
if canonical:
|
|
50
|
+
only_snv = True
|
|
51
|
+
no_double = True
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# check parameters
|
|
55
|
+
input_vcf = Path(input)
|
|
56
|
+
compare_vcf = Path(compare)
|
|
57
|
+
if not (input_vcf.suffix == ".vcf" or input_vcf.suffix == ".bcf" or (".gz" in input_vcf.suffixes and ".vcf" in input_vcf.suffixes)):
|
|
58
|
+
raise ValueError(r"-i or --input must be .vcf or .vcf.gz file. You provided a file with a different extension")
|
|
59
|
+
if not (compare_vcf.suffix == ".vcf" or compare_vcf.suffix == ".bcf" or (".gz" in compare_vcf.suffixes and ".vcf" in compare_vcf.suffixes)):
|
|
60
|
+
raise ValueError(r"-c or --compare must be .vcf or .vcf.gz file. You provided a file with a different extension")
|
|
61
|
+
|
|
62
|
+
ref_file = Path(ref)
|
|
63
|
+
if not (ref_file.suffix == ".fa" or ref_file.suffix == ".fasta" or ref_file.suffix == ".fai"):
|
|
64
|
+
raise ValueError(r"-r or --ref must be .fa, .fasta, or .fai file. You provided a file with a different extension")
|
|
65
|
+
|
|
66
|
+
if bed:
|
|
67
|
+
bed_file = Path(bed)
|
|
68
|
+
if not (bed_file.suffix == ".bed"):
|
|
69
|
+
raise ValueError(r"--bed must be .bed file. You provided a file with a different extension")
|
|
70
|
+
|
|
71
|
+
output_dir = os.path.dirname(output)
|
|
72
|
+
if not (os.path.exists(output_dir)):
|
|
73
|
+
raise ValueError(f"The output directory {output_dir} does not exist")
|
|
74
|
+
else:
|
|
75
|
+
if not os.path.isdir(output_dir):
|
|
76
|
+
raise ValueError(f"The output directory {output_dir} exists but is not a directory")
|
|
77
|
+
|
|
78
|
+
if threads > os.cpu_count():
|
|
79
|
+
logging.warning(f"-t or --threads set threads exceed the system CPU thread count ({os.cpu_count()})")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
# process chromosome area
|
|
83
|
+
chrom = [i.strip() for i in chrom.split(',')]
|
|
84
|
+
if not chrom:
|
|
85
|
+
raise ValueError("-c or --chrom must be in comma joined string e.g. chr1,chr2,ch3")
|
|
86
|
+
|
|
87
|
+
sexchrom = [i.strip() for i in sexchrom.split(',')]
|
|
88
|
+
if not chrom:
|
|
89
|
+
raise ValueError("--sexchrom must be in comma joined string e.g. chr1,chr2,ch3")
|
|
90
|
+
|
|
91
|
+
if no_sex:
|
|
92
|
+
clean_chrom = []
|
|
93
|
+
for i in chrom:
|
|
94
|
+
if i not in sexchrom:
|
|
95
|
+
clean_chrom.append(i)
|
|
96
|
+
chrom = clean_chrom
|
|
97
|
+
|
|
98
|
+
# sort chromosome
|
|
99
|
+
if not no_sort:
|
|
100
|
+
chrom = sort_chrom(chrom)
|
|
101
|
+
|
|
102
|
+
# print parameters in verbose mode
|
|
103
|
+
if verbose:
|
|
104
|
+
ctx = click.get_current_context()
|
|
105
|
+
logging.info("Command parameters:")
|
|
106
|
+
for param in ctx.command.params:
|
|
107
|
+
param_name = param.name
|
|
108
|
+
if param_name != "version":
|
|
109
|
+
param_value = ctx.params[param_name]
|
|
110
|
+
logging.info(f"{param_name}: {param_value}")
|
|
111
|
+
|
|
112
|
+
return (input, name, compare, ref, output, threads, max_len, bed, min_sv, chrom, sexchrom, mincount, canonical, block, no_sex, only_snv, only_indel, only_sv, no_snv, no_indel, no_sv, no_double, no_sort, lmdb, verbose)
|
|
113
|
+
|
|
114
|
+
|