xengsort 2.2.0__tar.gz → 2.2.2__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.
- {xengsort-2.2.0/xengsort.egg-info → xengsort-2.2.2}/PKG-INFO +32 -21
- {xengsort-2.2.0 → xengsort-2.2.2}/README.md +31 -20
- {xengsort-2.2.0 → xengsort-2.2.2}/pyproject.toml +1 -1
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/cptasks_kmers.py +25 -4
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/fastcash_main.py +5 -4
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/hash_s3c_fbcbvb.py +16 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/io/fastaio.py +7 -3
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/io/fastqio.py +66 -37
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/io/generalio.py +12 -1
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/io/hashio.py +7 -1
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/kmers.py +134 -3
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/lowlevel/libc.py +23 -7
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/lowlevel/llvm.py +27 -2
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/srhash.py +3 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/xengsort/xengsort_classify.py +7 -7
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/xengsort/xengsort_index.py +6 -3
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/xengsort/xengsort_info.py +3 -3
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/xengsort/xengsort_main.py +9 -2
- {xengsort-2.2.0 → xengsort-2.2.2/xengsort.egg-info}/PKG-INFO +32 -21
- {xengsort-2.2.0 → xengsort-2.2.2}/LICENSE +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/MANIFEST.in +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/setup.cfg +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/tests/test_trimmed_reads.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/dnaencode.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/dnaencode_fast.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/fastcash_info.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/fastcash_optimize.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/hash_minimizer.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/hash_srh_fbcbvb.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/io/binaryio.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/io/seqio.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/io/textio.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/io/xorio.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/lowlevel/aligned_arrays.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/lowlevel/bitarray.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/lowlevel/conpro.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/lowlevel/debug.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/lowlevel/intbitarray.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/lowlevel/numbautils.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/lowlevel/packedarray.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/mask.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/mathutils.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/parameters.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/subtable_hashfunctions.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/values/xenograft.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/xengsort/config/classify.yaml +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/xengsort/config/index.yaml +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/xengsort/xengsort_load.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/xengsort/xengsort_remove.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort/xengsort/xengsort_weak.py +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort.egg-info/SOURCES.txt +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort.egg-info/dependency_links.txt +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort.egg-info/entry_points.txt +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort.egg-info/requires.txt +0 -0
- {xengsort-2.2.0 → xengsort-2.2.2}/xengsort.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xengsort
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: xenograft sorting of FASTQ reads into five categories: host, graft, both, neither, ambiguous.
|
|
5
5
|
Author-email: Jens Zentgraf <zentgraf@cs.uni-saarland.de>, Sven Rahmann <rahmann@cs.uni-saarland.de>
|
|
6
6
|
License: MIT License
|
|
@@ -52,6 +52,7 @@ This tool, xengsort, uses 3-way bucketed Cuckoo hashing to efficiently solve the
|
|
|
52
52
|
For a description of the method an evaluation on several datasets, please see our
|
|
53
53
|
[article in "Algorithms for Molecular Biology"](https://almob.biomedcentral.com/articles/10.1186/s13015-021-00181-w), or the initial [WABI 2020 publication](https://drops.dagstuhl.de/opus/volltexte/2020/12793/).
|
|
54
54
|
(There was also a [preprint on bioRxiv](https://www.biorxiv.org/content/10.1101/2020.05.14.095604v2).)
|
|
55
|
+
If you use xengsort to sort converted reads (RRBS or WGBS) there is a [bioRxiv preprint](https://www.biorxiv.org/content/10.64898/2026.10.06.756952v1.abstract) available.
|
|
55
56
|
BibTeX entrys for citation can be found at the end of this README file.
|
|
56
57
|
|
|
57
58
|
In case of problems,
|
|
@@ -71,24 +72,23 @@ Thank you!
|
|
|
71
72
|
|
|
72
73
|
We here provide an example showing how to run xengsort on a human-captured mouse exome (part of one of the datasets described in the paper).
|
|
73
74
|
This tutorial uses the workflow management system `Snakemake` to run the example.
|
|
74
|
-
This is, however, not necessary to use `xengsort`.
|
|
75
|
+
This is, however, not necessary to use `xengsort`.
|
|
75
76
|
Please refer to the Usage Guide below to learn how to run `xengsort` on your own data manually.
|
|
76
77
|
|
|
77
78
|
|
|
78
79
|
Our software `xengsort` is provided as a Python package.
|
|
79
|
-
For efficiency, it uses just-in-time compilation provided by the [numba](http://numba.pydata.org/) package.
|
|
80
|
+
For efficiency, it uses just-in-time compilation provided by the [numba](http://numba.pydata.org/) package.
|
|
80
81
|
We here use the package manager [conda](https://docs.conda.io/en/latest/) to manage Python packages and to use a separate environment for `xengsort`.
|
|
81
82
|
|
|
82
83
|
|
|
83
|
-
### Install the conda package manager (
|
|
84
|
-
Go to https://
|
|
85
|
-
Choose
|
|
86
|
-
Follow the instructions of the installer and append the conda executable to your PATH (even if the installer does not recommend it).
|
|
84
|
+
### Install the conda package manager (conda-forge)
|
|
85
|
+
Go to https://conda-forge.org/download/ and download the conda-forge installer:
|
|
86
|
+
Choose your operating system, follow the instructions of the installer and append the conda executable to your PATH (even if the installer does not recommend it).
|
|
87
87
|
You can let the installer do it, or do it manually by editing your ``.bashrc`` or similar file under Linux or MacOS, or by editing the environment variables under Windows.
|
|
88
88
|
To verify that the installation works, open a new terminal and execute
|
|
89
89
|
```
|
|
90
|
-
conda --version # ideally
|
|
91
|
-
python --version # ideally 3.
|
|
90
|
+
conda --version # ideally 26.9.xx or higher
|
|
91
|
+
python --version # ideally 3.12.xx or higher
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
|
|
@@ -122,7 +122,7 @@ within the cloned directory tree.
|
|
|
122
122
|
|
|
123
123
|
|
|
124
124
|
### Create and activate a conda environment
|
|
125
|
-
To run our software, a [conda](https://
|
|
125
|
+
To run our software, a [conda](https://conda-forge.org/docs/) environment with the required libraries needs to be created.
|
|
126
126
|
A list of needed libraries is provided in the ``environment.yml`` file in the cloned repository;
|
|
127
127
|
it can be used to create a new environment:
|
|
128
128
|
|
|
@@ -133,7 +133,7 @@ conda env create
|
|
|
133
133
|
which will create an environment named ``xengsort`` with the required dependencies,
|
|
134
134
|
using the provided ``environment.yml`` file in the same directory.
|
|
135
135
|
|
|
136
|
-
A more explicit alternative is to run
|
|
136
|
+
A more explicit alternative is to run
|
|
137
137
|
```
|
|
138
138
|
conda create --name xengsort -c conda-forge -c bioconda --file requirements.txt
|
|
139
139
|
```
|
|
@@ -217,11 +217,11 @@ To build an index for xengsort, several parameters must be provided, which are d
|
|
|
217
217
|
First, a file name and a path for the index must be chosen.
|
|
218
218
|
The index is stored in two files. We will use `myindex` to store the index in the current folder.
|
|
219
219
|
|
|
220
|
-
Second, two reference genomes (host and graft) must be provided (in FASTA files).
|
|
221
|
-
We assume that they are given as `host.fa.gz` and `graft.fa.gz`.
|
|
220
|
+
Second, two reference genomes (host and graft) must be provided (in FASTA files).
|
|
221
|
+
We assume that they are given as `host.fa.gz` and `graft.fa.gz`.
|
|
222
222
|
The files can be provided as an uncompressed file or compressed using `gzip`, `bzip2` or `xz`.
|
|
223
|
-
The corresponding options are `-H` or `--host` and `-G` or `--graft`.
|
|
224
|
-
Each option can take several arguments as files.
|
|
223
|
+
The corresponding options are `-H` or `--host` and `-G` or `--graft`.
|
|
224
|
+
Each option can take several arguments as files.
|
|
225
225
|
```
|
|
226
226
|
xengsort index --index myindex -H host.fa.gz -G graft.fa.gz -n 4_500_000_000 [OPTIONS]
|
|
227
227
|
```
|
|
@@ -249,7 +249,7 @@ The final important parameter is about parallelization:
|
|
|
249
249
|
|
|
250
250
|
Most of the parameters can also be provided in a config file (`.yaml`):
|
|
251
251
|
- `--cfg` or `--config` defines the path the the config file.
|
|
252
|
-
|
|
252
|
+
|
|
253
253
|
### How to classify
|
|
254
254
|
|
|
255
255
|
To classify a FASTQ sample (one or several single-end or paired-end files), make sure you are in an environment where xengsort and its dependencies are installed.
|
|
@@ -257,7 +257,7 @@ Then run the `xengsort classify` command with a previously built index, such as
|
|
|
257
257
|
```
|
|
258
258
|
xengsort classify --index myindex --fastq single.fq.gz --prefix myresults --mode count
|
|
259
259
|
```
|
|
260
|
-
for single-end reads, or
|
|
260
|
+
for single-end reads, or
|
|
261
261
|
```
|
|
262
262
|
xengsort classify --index myindex --fastq paired.1.fq.gz --pairs paired.2.fq.gz --prefix myresults --mode count
|
|
263
263
|
```
|
|
@@ -275,7 +275,7 @@ The parameter `--prefix` or equivalently `--out` is required and defines the pre
|
|
|
275
275
|
- `{prefix}.both.1.fq.gz`: reads that could originate from both
|
|
276
276
|
- `{prefix}.neither.1.fq.gz`: reads that originate from neither host nor graft
|
|
277
277
|
- `{prefix}.ambiguous.1.fq.gz`: (few) ambiguous reads that cannot be classified,
|
|
278
|
-
|
|
278
|
+
|
|
279
279
|
and similarly with `.2.fq.gz`. For single-end reads, there is only `.fq.gz` (no numbers).
|
|
280
280
|
|
|
281
281
|
The compression type can be specified using the `--compression` parameter.
|
|
@@ -301,7 +301,7 @@ xengsort index --index myindex -H host.fa.gz -G graft.fa.gz -n 9_000_000_000 --b
|
|
|
301
301
|
If an index is build using the bisulfite parameter, also the read is converted in the classification step.
|
|
302
302
|
It is not necessary to change the parameters of the classification step.
|
|
303
303
|
Currently, it only supports the count-based classification.
|
|
304
|
-
|
|
304
|
+
A detailed description on how the benchmarks on bisulfite sequencing data was performed can be found [here](https://github.com/S-Altend/MethSortBench/tree/main/03_read_sorting).
|
|
305
305
|
|
|
306
306
|
Please report a [GitLab issue](https://gitlab.com/genomeinformatics/xengsort/-/issues) in case of problems.
|
|
307
307
|
|
|
@@ -315,13 +315,13 @@ Happy sorting!
|
|
|
315
315
|
* **Snakemake throws errors when attempting to download the example dataset from SRA**.
|
|
316
316
|
|
|
317
317
|
This may happen for several reasons:
|
|
318
|
-
1. The dataset is quite large, over 20 GB. Make sure you have sufficient space (also temporary space) and sufficient disk quota (on a shared system) to store all of the files.
|
|
318
|
+
1. The dataset is quite large, over 20 GB. Make sure you have sufficient space (also temporary space) and sufficient disk quota (on a shared system) to store all of the files.
|
|
319
319
|
1. Another source of trouble may be that for some reason and older version of `sra-tools` gets called. We use the `fasterq-dump` tool to download the data, which did not exist in older verisons. To use a clean environment with a recent version of `sra-tools`, you can run snakemake as `snakemake -j 16 --use-conda`, which will generate a separate environment only for the download (this takes additional time, but may resolve the problem).
|
|
320
320
|
1. In earlier versions, the dataset was downloaded from a different location which is no longer available. Please check that you are using at least v1.1.0 (`xengsort --version`). If not, please do a fresh clone and follow the tutorial to set up a new environment (delete the old one first) and run `pip install -e .`, as explained above in the tutorial.
|
|
321
321
|
|
|
322
322
|
* **Indexing stops after a few seconds with a failure.**
|
|
323
323
|
|
|
324
|
-
The most likely cause of this is that you have not specified the size of the hash table (`-n` parameter).
|
|
324
|
+
The most likely cause of this is that you have not specified the size of the hash table (`-n` parameter).
|
|
325
325
|
(From version 1.0.1, the `-n` parameter is required, and the error cannot occur anymore. Please update to the latest version!)
|
|
326
326
|
For the human and mouse genomes this is approximately `-n 4_500_000_000` (4.5 billion).
|
|
327
327
|
It is unfortunately a limitation of the implementation that the hash table size has to be specified in advance.
|
|
@@ -377,3 +377,14 @@ In addition, you may also cite the WABI 2020 proceedigs paper:
|
|
|
377
377
|
annote = {Keywords: xenograft sorting, alignment-free method, Cuckoo hashing, k-mer}
|
|
378
378
|
}
|
|
379
379
|
```
|
|
380
|
+
|
|
381
|
+
If you use xengsort to sort converted reads, please also cite our corresponding bioRxiv preprint:
|
|
382
|
+
```
|
|
383
|
+
@article {Altendorfer2026.10.06.756952,
|
|
384
|
+
author = {Altendorfer, Stefan and Zentgraf, Jens and Schmitz, Johanna Elena and Plass, Christoph and Gerh{\"a}user, Clarissa and Rahmann, Sven},
|
|
385
|
+
title = {High-performance xenograft read-sorting for DNA methylation analysis},
|
|
386
|
+
year = {2026},
|
|
387
|
+
doi = {10.64898/2026.10.06.756952},
|
|
388
|
+
journal = {bioRxiv}
|
|
389
|
+
}
|
|
390
|
+
```
|
|
@@ -5,6 +5,7 @@ This tool, xengsort, uses 3-way bucketed Cuckoo hashing to efficiently solve the
|
|
|
5
5
|
For a description of the method an evaluation on several datasets, please see our
|
|
6
6
|
[article in "Algorithms for Molecular Biology"](https://almob.biomedcentral.com/articles/10.1186/s13015-021-00181-w), or the initial [WABI 2020 publication](https://drops.dagstuhl.de/opus/volltexte/2020/12793/).
|
|
7
7
|
(There was also a [preprint on bioRxiv](https://www.biorxiv.org/content/10.1101/2020.05.14.095604v2).)
|
|
8
|
+
If you use xengsort to sort converted reads (RRBS or WGBS) there is a [bioRxiv preprint](https://www.biorxiv.org/content/10.64898/2026.10.06.756952v1.abstract) available.
|
|
8
9
|
BibTeX entrys for citation can be found at the end of this README file.
|
|
9
10
|
|
|
10
11
|
In case of problems,
|
|
@@ -24,24 +25,23 @@ Thank you!
|
|
|
24
25
|
|
|
25
26
|
We here provide an example showing how to run xengsort on a human-captured mouse exome (part of one of the datasets described in the paper).
|
|
26
27
|
This tutorial uses the workflow management system `Snakemake` to run the example.
|
|
27
|
-
This is, however, not necessary to use `xengsort`.
|
|
28
|
+
This is, however, not necessary to use `xengsort`.
|
|
28
29
|
Please refer to the Usage Guide below to learn how to run `xengsort` on your own data manually.
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
Our software `xengsort` is provided as a Python package.
|
|
32
|
-
For efficiency, it uses just-in-time compilation provided by the [numba](http://numba.pydata.org/) package.
|
|
33
|
+
For efficiency, it uses just-in-time compilation provided by the [numba](http://numba.pydata.org/) package.
|
|
33
34
|
We here use the package manager [conda](https://docs.conda.io/en/latest/) to manage Python packages and to use a separate environment for `xengsort`.
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
### Install the conda package manager (
|
|
37
|
-
Go to https://
|
|
38
|
-
Choose
|
|
39
|
-
Follow the instructions of the installer and append the conda executable to your PATH (even if the installer does not recommend it).
|
|
37
|
+
### Install the conda package manager (conda-forge)
|
|
38
|
+
Go to https://conda-forge.org/download/ and download the conda-forge installer:
|
|
39
|
+
Choose your operating system, follow the instructions of the installer and append the conda executable to your PATH (even if the installer does not recommend it).
|
|
40
40
|
You can let the installer do it, or do it manually by editing your ``.bashrc`` or similar file under Linux or MacOS, or by editing the environment variables under Windows.
|
|
41
41
|
To verify that the installation works, open a new terminal and execute
|
|
42
42
|
```
|
|
43
|
-
conda --version # ideally
|
|
44
|
-
python --version # ideally 3.
|
|
43
|
+
conda --version # ideally 26.9.xx or higher
|
|
44
|
+
python --version # ideally 3.12.xx or higher
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
|
|
@@ -75,7 +75,7 @@ within the cloned directory tree.
|
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
### Create and activate a conda environment
|
|
78
|
-
To run our software, a [conda](https://
|
|
78
|
+
To run our software, a [conda](https://conda-forge.org/docs/) environment with the required libraries needs to be created.
|
|
79
79
|
A list of needed libraries is provided in the ``environment.yml`` file in the cloned repository;
|
|
80
80
|
it can be used to create a new environment:
|
|
81
81
|
|
|
@@ -86,7 +86,7 @@ conda env create
|
|
|
86
86
|
which will create an environment named ``xengsort`` with the required dependencies,
|
|
87
87
|
using the provided ``environment.yml`` file in the same directory.
|
|
88
88
|
|
|
89
|
-
A more explicit alternative is to run
|
|
89
|
+
A more explicit alternative is to run
|
|
90
90
|
```
|
|
91
91
|
conda create --name xengsort -c conda-forge -c bioconda --file requirements.txt
|
|
92
92
|
```
|
|
@@ -170,11 +170,11 @@ To build an index for xengsort, several parameters must be provided, which are d
|
|
|
170
170
|
First, a file name and a path for the index must be chosen.
|
|
171
171
|
The index is stored in two files. We will use `myindex` to store the index in the current folder.
|
|
172
172
|
|
|
173
|
-
Second, two reference genomes (host and graft) must be provided (in FASTA files).
|
|
174
|
-
We assume that they are given as `host.fa.gz` and `graft.fa.gz`.
|
|
173
|
+
Second, two reference genomes (host and graft) must be provided (in FASTA files).
|
|
174
|
+
We assume that they are given as `host.fa.gz` and `graft.fa.gz`.
|
|
175
175
|
The files can be provided as an uncompressed file or compressed using `gzip`, `bzip2` or `xz`.
|
|
176
|
-
The corresponding options are `-H` or `--host` and `-G` or `--graft`.
|
|
177
|
-
Each option can take several arguments as files.
|
|
176
|
+
The corresponding options are `-H` or `--host` and `-G` or `--graft`.
|
|
177
|
+
Each option can take several arguments as files.
|
|
178
178
|
```
|
|
179
179
|
xengsort index --index myindex -H host.fa.gz -G graft.fa.gz -n 4_500_000_000 [OPTIONS]
|
|
180
180
|
```
|
|
@@ -202,7 +202,7 @@ The final important parameter is about parallelization:
|
|
|
202
202
|
|
|
203
203
|
Most of the parameters can also be provided in a config file (`.yaml`):
|
|
204
204
|
- `--cfg` or `--config` defines the path the the config file.
|
|
205
|
-
|
|
205
|
+
|
|
206
206
|
### How to classify
|
|
207
207
|
|
|
208
208
|
To classify a FASTQ sample (one or several single-end or paired-end files), make sure you are in an environment where xengsort and its dependencies are installed.
|
|
@@ -210,7 +210,7 @@ Then run the `xengsort classify` command with a previously built index, such as
|
|
|
210
210
|
```
|
|
211
211
|
xengsort classify --index myindex --fastq single.fq.gz --prefix myresults --mode count
|
|
212
212
|
```
|
|
213
|
-
for single-end reads, or
|
|
213
|
+
for single-end reads, or
|
|
214
214
|
```
|
|
215
215
|
xengsort classify --index myindex --fastq paired.1.fq.gz --pairs paired.2.fq.gz --prefix myresults --mode count
|
|
216
216
|
```
|
|
@@ -228,7 +228,7 @@ The parameter `--prefix` or equivalently `--out` is required and defines the pre
|
|
|
228
228
|
- `{prefix}.both.1.fq.gz`: reads that could originate from both
|
|
229
229
|
- `{prefix}.neither.1.fq.gz`: reads that originate from neither host nor graft
|
|
230
230
|
- `{prefix}.ambiguous.1.fq.gz`: (few) ambiguous reads that cannot be classified,
|
|
231
|
-
|
|
231
|
+
|
|
232
232
|
and similarly with `.2.fq.gz`. For single-end reads, there is only `.fq.gz` (no numbers).
|
|
233
233
|
|
|
234
234
|
The compression type can be specified using the `--compression` parameter.
|
|
@@ -254,7 +254,7 @@ xengsort index --index myindex -H host.fa.gz -G graft.fa.gz -n 9_000_000_000 --b
|
|
|
254
254
|
If an index is build using the bisulfite parameter, also the read is converted in the classification step.
|
|
255
255
|
It is not necessary to change the parameters of the classification step.
|
|
256
256
|
Currently, it only supports the count-based classification.
|
|
257
|
-
|
|
257
|
+
A detailed description on how the benchmarks on bisulfite sequencing data was performed can be found [here](https://github.com/S-Altend/MethSortBench/tree/main/03_read_sorting).
|
|
258
258
|
|
|
259
259
|
Please report a [GitLab issue](https://gitlab.com/genomeinformatics/xengsort/-/issues) in case of problems.
|
|
260
260
|
|
|
@@ -268,13 +268,13 @@ Happy sorting!
|
|
|
268
268
|
* **Snakemake throws errors when attempting to download the example dataset from SRA**.
|
|
269
269
|
|
|
270
270
|
This may happen for several reasons:
|
|
271
|
-
1. The dataset is quite large, over 20 GB. Make sure you have sufficient space (also temporary space) and sufficient disk quota (on a shared system) to store all of the files.
|
|
271
|
+
1. The dataset is quite large, over 20 GB. Make sure you have sufficient space (also temporary space) and sufficient disk quota (on a shared system) to store all of the files.
|
|
272
272
|
1. Another source of trouble may be that for some reason and older version of `sra-tools` gets called. We use the `fasterq-dump` tool to download the data, which did not exist in older verisons. To use a clean environment with a recent version of `sra-tools`, you can run snakemake as `snakemake -j 16 --use-conda`, which will generate a separate environment only for the download (this takes additional time, but may resolve the problem).
|
|
273
273
|
1. In earlier versions, the dataset was downloaded from a different location which is no longer available. Please check that you are using at least v1.1.0 (`xengsort --version`). If not, please do a fresh clone and follow the tutorial to set up a new environment (delete the old one first) and run `pip install -e .`, as explained above in the tutorial.
|
|
274
274
|
|
|
275
275
|
* **Indexing stops after a few seconds with a failure.**
|
|
276
276
|
|
|
277
|
-
The most likely cause of this is that you have not specified the size of the hash table (`-n` parameter).
|
|
277
|
+
The most likely cause of this is that you have not specified the size of the hash table (`-n` parameter).
|
|
278
278
|
(From version 1.0.1, the `-n` parameter is required, and the error cannot occur anymore. Please update to the latest version!)
|
|
279
279
|
For the human and mouse genomes this is approximately `-n 4_500_000_000` (4.5 billion).
|
|
280
280
|
It is unfortunately a limitation of the implementation that the hash table size has to be specified in advance.
|
|
@@ -330,3 +330,14 @@ In addition, you may also cite the WABI 2020 proceedigs paper:
|
|
|
330
330
|
annote = {Keywords: xenograft sorting, alignment-free method, Cuckoo hashing, k-mer}
|
|
331
331
|
}
|
|
332
332
|
```
|
|
333
|
+
|
|
334
|
+
If you use xengsort to sort converted reads, please also cite our corresponding bioRxiv preprint:
|
|
335
|
+
```
|
|
336
|
+
@article {Altendorfer2026.10.06.756952,
|
|
337
|
+
author = {Altendorfer, Stefan and Zentgraf, Jens and Schmitz, Johanna Elena and Plass, Christoph and Gerh{\"a}user, Clarissa and Rahmann, Sven},
|
|
338
|
+
title = {High-performance xenograft read-sorting for DNA methylation analysis},
|
|
339
|
+
year = {2026},
|
|
340
|
+
doi = {10.64898/2026.10.06.756952},
|
|
341
|
+
journal = {bioRxiv}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
@@ -544,15 +544,27 @@ def compile_cptask_insert_filtered_subkeys(
|
|
|
544
544
|
myfilter,
|
|
545
545
|
constant_value=0,
|
|
546
546
|
maxfailures=0,
|
|
547
|
-
maxwalk=1000
|
|
547
|
+
maxwalk=1000,
|
|
548
|
+
prefetch_distance=8):
|
|
548
549
|
debugprint0, debugprint1, debugprint2 = debug.debugprint
|
|
549
550
|
dassert = debug.dassert
|
|
551
|
+
|
|
552
|
+
@njit(nogil=True)
|
|
553
|
+
def dummy_prefetch(*_):
|
|
554
|
+
return
|
|
555
|
+
|
|
556
|
+
prefetch_filter = prefetch_table = dummy_prefetch
|
|
550
557
|
if myfilter is not None:
|
|
551
558
|
wwo = "with"
|
|
552
559
|
lookup_and_insert_in_subfilter = myfilter.private.lookup_and_insert_in_subfilter
|
|
560
|
+
table_prefetch_distance = 0
|
|
561
|
+
filter_prefetch_distance = prefetch_distance
|
|
562
|
+
prefetch_filter = myfilter.private.prefetch_block_by_subkey_subfilter
|
|
553
563
|
else:
|
|
554
564
|
wwo = "without"
|
|
555
|
-
|
|
565
|
+
table_prefetch_distance = prefetch_distance
|
|
566
|
+
filter_prefetch_distance = 0
|
|
567
|
+
prefetch_table = myhashtable.private.prefetch_subkey
|
|
556
568
|
@njit(nogil=True)
|
|
557
569
|
def lookup_and_insert_in_subfilter(ft, st, subkey):
|
|
558
570
|
return True
|
|
@@ -599,7 +611,12 @@ def compile_cptask_insert_filtered_subkeys(
|
|
|
599
611
|
# dassert(buffer_type == 1, __name__, 'buffer_type == 1', buffer_type, message='0 means sequence buffer')
|
|
600
612
|
|
|
601
613
|
# consume the buffer
|
|
602
|
-
for
|
|
614
|
+
for ii in range(nsubkeys):
|
|
615
|
+
subkey = active_buffer[ii]
|
|
616
|
+
if filter_prefetch_distance and ii + filter_prefetch_distance < nsubkeys:
|
|
617
|
+
prefetch_filter(ft, active_buffer[ii + prefetch_distance], st)
|
|
618
|
+
if table_prefetch_distance and ii + table_prefetch_distance < nsubkeys:
|
|
619
|
+
prefetch_table(ht, active_buffer[ii + prefetch_distance], st)
|
|
603
620
|
if lookup_and_insert_in_subfilter(ft, st, subkey):
|
|
604
621
|
status, result = update(ht, st, subkey, value) # see docstring below
|
|
605
622
|
if status & 128 == 0:
|
|
@@ -618,9 +635,11 @@ def compile_cptask_insert_filtered_subkeys(
|
|
|
618
635
|
|
|
619
636
|
def compile_cptask_update_existing_subkeys(
|
|
620
637
|
myhashtable,
|
|
621
|
-
constant_value=1
|
|
638
|
+
constant_value=1,
|
|
639
|
+
prefetch_distance=8):
|
|
622
640
|
debugprint0, debugprint1, debugprint2 = debug.debugprint
|
|
623
641
|
update_existing = myhashtable.private.update_existing_ssk
|
|
642
|
+
prefetch = myhashtable.private.prefetch_subkey
|
|
624
643
|
value = uint64(constant_value)
|
|
625
644
|
debugprint1(f"- compiling cptask_update_existing_subkeys: {constant_value=}")
|
|
626
645
|
|
|
@@ -652,6 +671,8 @@ def compile_cptask_update_existing_subkeys(
|
|
|
652
671
|
|
|
653
672
|
# consume the buffer
|
|
654
673
|
for ii in range(nsubkeys):
|
|
674
|
+
if prefetch_distance and ii + prefetch_distance < nsubkeys:
|
|
675
|
+
prefetch(ht, active_buffer[ii + prefetch_distance], st)
|
|
655
676
|
subkey = active_buffer[ii]
|
|
656
677
|
_, _ = update_existing(ht, st, subkey, value) # see docstring below
|
|
657
678
|
# status, result = update_existing(ht, st, subkey, value) # see docstring below
|
|
@@ -7,6 +7,7 @@ from argparse import ArgumentParser
|
|
|
7
7
|
from importlib import import_module # dynamically import subcommand
|
|
8
8
|
from importlib.metadata import metadata
|
|
9
9
|
from os.path import split as splitpath, splitext
|
|
10
|
+
from collections import defaultdict
|
|
10
11
|
|
|
11
12
|
from .lowlevel.debug import set_debugfunctions
|
|
12
13
|
|
|
@@ -28,7 +29,7 @@ def add_hash_table_arguments(p: ArgumentParser):
|
|
|
28
29
|
help="bucket size, i.e. number of elements on a bucket")
|
|
29
30
|
p.add_argument("--fill", type=float, default="0.9",
|
|
30
31
|
help="desired fill rate of the hash table")
|
|
31
|
-
p.add_argument("--subtables", type=int, default=5,
|
|
32
|
+
p.add_argument("--subtables", type=int, default=5,
|
|
32
33
|
help="number of subtables used; subtables+1 threads are used")
|
|
33
34
|
|
|
34
35
|
|
|
@@ -51,20 +52,20 @@ def add_hash_arguments(p: ArgumentParser):
|
|
|
51
52
|
help="number of objects to be stored")
|
|
52
53
|
p.add_argument("--type", default="default", # default="3c_fbcbvb",
|
|
53
54
|
help="hash type (e.g. [s]3c_fbcbvb, 2v_fbcbvb), implemented in hash_{TYPE}.py")
|
|
54
|
-
p.add_argument("--unaligned", action="store_const",
|
|
55
|
+
p.add_argument("--unaligned", action="store_const",
|
|
55
56
|
const=False, dest="aligned", default=None,
|
|
56
57
|
help="use unaligned buckets (smaller, slightly slower; default)")
|
|
57
58
|
p.add_argument("--aligned", action="store_const",
|
|
58
59
|
const=True, dest="aligned", default=None,
|
|
59
60
|
help="use power-of-two aligned buckets (faster, but larger)")
|
|
60
|
-
p.add_argument("--hashfunctions", "--functions",
|
|
61
|
+
p.add_argument("--hashfunctions", "--functions",
|
|
61
62
|
help="hash functions: 'default', 'random', or func1:func2[:func3]")
|
|
62
63
|
# less important hash options
|
|
63
64
|
p.add_argument("--nostatistics", "--nostats", action="store_true",
|
|
64
65
|
help="do not compute or show index statistics at the end")
|
|
65
66
|
p.add_argument("--maxwalk", metavar="INT", type=int, default=500,
|
|
66
67
|
help="maximum length of random walk through hash table before failing [500]")
|
|
67
|
-
p.add_argument("--maxfailures", metavar="INT", type=int, default=0,
|
|
68
|
+
p.add_argument("--maxfailures", metavar="INT", type=int, default=0,
|
|
68
69
|
help="continue even after this many failures [default:0; forever:-1]")
|
|
69
70
|
p.add_argument("--walkseed", type=int, default=7,
|
|
70
71
|
help="seed for random walks while inserting elements [7]")
|
|
@@ -134,6 +134,22 @@ def build_hash(universe, n, subtables, bucketsize,
|
|
|
134
134
|
def prefetch_bucket(table, subtable, bucket):
|
|
135
135
|
startbit = subtable * subtablebits + bucket * bucketsizebits
|
|
136
136
|
hprefetch(table, startbit)
|
|
137
|
+
hprefetch(table, startbit + uint64(bucketsizebits - 1))
|
|
138
|
+
|
|
139
|
+
@njit(nogil=True, locals=dict(
|
|
140
|
+
bucket=int64, startbit=uint64))
|
|
141
|
+
def prefetch_subkey(table, subkey, subtable):
|
|
142
|
+
bucket, _ = get_bs1(subkey)
|
|
143
|
+
startbit = subtable * subtablebits + bucket * bucketsizebits
|
|
144
|
+
hprefetch(table, startbit)
|
|
145
|
+
|
|
146
|
+
bucket, _ = get_bs2(subkey)
|
|
147
|
+
startbit = subtable * subtablebits + bucket * bucketsizebits
|
|
148
|
+
hprefetch(table, startbit)
|
|
149
|
+
|
|
150
|
+
bucket, _ = get_bs3(subkey)
|
|
151
|
+
startbit = subtable * subtablebits + bucket * bucketsizebits
|
|
152
|
+
hprefetch(table, startbit)
|
|
137
153
|
|
|
138
154
|
@njit(nogil=True, locals=dict(
|
|
139
155
|
bucket=int64, startbit=uint64))
|
|
@@ -103,6 +103,7 @@ def cptask_read_fasta_into_buffers(fd, W, inbuffers, incontrol, ininfos, outbuff
|
|
|
103
103
|
inside_seq = True
|
|
104
104
|
header_seq = False
|
|
105
105
|
nseq = 0
|
|
106
|
+
last_seq_length = 2 * W
|
|
106
107
|
while True:
|
|
107
108
|
old = nactive
|
|
108
109
|
old_buffer = active_buffer
|
|
@@ -134,7 +135,11 @@ def cptask_read_fasta_into_buffers(fd, W, inbuffers, incontrol, ininfos, outbuff
|
|
|
134
135
|
if ntodo < 0:
|
|
135
136
|
errorcode = ntodo
|
|
136
137
|
break
|
|
138
|
+
# If we have a long header but a seq smaller W, the offset can be bigger than W
|
|
139
|
+
if header_seq and last_seq_length < W:
|
|
140
|
+
break
|
|
137
141
|
# Nothing read and the offset is not a full (gapped) k-mer
|
|
142
|
+
# I think this should trigger
|
|
138
143
|
if offset < W:
|
|
139
144
|
break
|
|
140
145
|
# Nothing read but we still have some data in the buffer
|
|
@@ -157,7 +162,6 @@ def cptask_read_fasta_into_buffers(fd, W, inbuffers, incontrol, ininfos, outbuff
|
|
|
157
162
|
offset = (W - 1)
|
|
158
163
|
else:
|
|
159
164
|
offset = end_buffer - linemarkbuffers[nactive, nseq - 1, 3]
|
|
160
|
-
|
|
161
165
|
outcontrol[nactive, 7] = nseq
|
|
162
166
|
outcontrol[nactive, 6] = 0 # buffer type sequence data
|
|
163
167
|
|
|
@@ -417,7 +421,7 @@ def fastaextract(args):
|
|
|
417
421
|
seps = args.separators
|
|
418
422
|
sfx = [args.suffix] if args.suffix else []
|
|
419
423
|
seps = [_SEPARATORS.get(sep.upper(), sep) for sep in seps]
|
|
420
|
-
if items is None:
|
|
424
|
+
if items is None:
|
|
421
425
|
items = list()
|
|
422
426
|
seps = list()
|
|
423
427
|
if len(seps) == 1:
|
|
@@ -436,7 +440,7 @@ def fastaextract(args):
|
|
|
436
440
|
def get_header_info(header, items, assigner, seps):
|
|
437
441
|
fields = header.decode("ascii").split()
|
|
438
442
|
assigners = [i for (i, field) in enumerate(fields) if assigner in field]
|
|
439
|
-
if 0 in assigners:
|
|
443
|
+
if 0 in assigners:
|
|
440
444
|
assigners.remove(0)
|
|
441
445
|
D = dict()
|
|
442
446
|
if items is None:
|