xengsort 2.0.4__tar.gz → 2.0.7__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.0.4 → xengsort-2.0.7}/MANIFEST.in +2 -1
- {xengsort-2.0.4/xengsort.egg-info → xengsort-2.0.7}/PKG-INFO +39 -19
- {xengsort-2.0.4 → xengsort-2.0.7}/README.md +10 -12
- {xengsort-2.0.4 → xengsort-2.0.7}/pyproject.toml +26 -11
- xengsort-2.0.7/tests/test_trimmed_reads.py +28 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/cptasks_kmers.py +305 -8
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/dnaencode.py +11 -8
- xengsort-2.0.7/xengsort/fastcash_info.py +83 -0
- xengsort-2.0.7/xengsort/fastcash_main.py +248 -0
- xengsort-2.0.7/xengsort/fastcash_optimize.py +765 -0
- xengsort-2.0.7/xengsort/hash_minimizer.py +1113 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/hash_s3c_fbcbvb.py +122 -64
- xengsort-2.0.7/xengsort/hash_srh_fbcbvb.py +862 -0
- xengsort-2.0.7/xengsort/io/binaryio.py +62 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/io/fastaio.py +201 -18
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/io/fastqio.py +1 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/io/generalio.py +32 -4
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/io/hashio.py +8 -1
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/io/textio.py +1 -1
- xengsort-2.0.7/xengsort/io/xorio.py +94 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/kmers.py +1 -1
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/lowlevel/bitarray.py +5 -4
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/lowlevel/conpro.py +15 -8
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/lowlevel/intbitarray.py +1 -1
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/lowlevel/llvm.py +1 -1
- xengsort-2.0.7/xengsort/lowlevel/numbautils.py +25 -0
- xengsort-2.0.7/xengsort/lowlevel/packedarray.py +186 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/mathutils.py +5 -3
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/parameters.py +5 -4
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/srhash.py +2 -2
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/subtable_hashfunctions.py +23 -18
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/xengsort/xengsort_classify.py +6 -11
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/xengsort/xengsort_index.py +9 -0
- xengsort-2.0.7/xengsort/xengsort/xengsort_info.py +83 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/xengsort/xengsort_load.py +4 -5
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/xengsort/xengsort_main.py +57 -71
- {xengsort-2.0.4 → xengsort-2.0.7/xengsort.egg-info}/PKG-INFO +39 -19
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort.egg-info/SOURCES.txt +11 -16
- xengsort-2.0.7/xengsort.egg-info/requires.txt +5 -0
- xengsort-2.0.4/setup.py +0 -42
- xengsort-2.0.4/tests/test_encoding.py +0 -21
- xengsort-2.0.4/tests/test_trimmed_reads.py +0 -33
- xengsort-2.0.4/xengsort/_version.py +0 -27
- xengsort-2.0.4/xengsort/xengsort/__pycache__/xengsort_classify.cpython-310.pyc +0 -0
- xengsort-2.0.4/xengsort/xengsort/__pycache__/xengsort_classify.cpython-311.pyc +0 -0
- xengsort-2.0.4/xengsort/xengsort/__pycache__/xengsort_index.cpython-310.pyc +0 -0
- xengsort-2.0.4/xengsort/xengsort/__pycache__/xengsort_index.cpython-311.pyc +0 -0
- xengsort-2.0.4/xengsort/xengsort/__pycache__/xengsort_info.cpython-311.pyc +0 -0
- xengsort-2.0.4/xengsort/xengsort/__pycache__/xengsort_main.cpython-310.pyc +0 -0
- xengsort-2.0.4/xengsort/xengsort/__pycache__/xengsort_main.cpython-311.pyc +0 -0
- xengsort-2.0.4/xengsort/xengsort/__pycache__/xengsort_weak.cpython-310.pyc +0 -0
- xengsort-2.0.4/xengsort/xengsort/__pycache__/xengsort_weak.cpython-311.pyc +0 -0
- xengsort-2.0.4/xengsort/xengsort/config/classify.yaml +0 -60
- xengsort-2.0.4/xengsort/xengsort/config/index.yaml +0 -9
- xengsort-2.0.4/xengsort.egg-info/not-zip-safe +0 -1
- xengsort-2.0.4/xengsort.egg-info/requires.txt +0 -4
- {xengsort-2.0.4 → xengsort-2.0.7}/LICENSE +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/setup.cfg +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/io/seqio.py +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/lowlevel/aligned_arrays.py +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/lowlevel/debug.py +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/lowlevel/libc.py +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/mask.py +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/values/xenograft.py +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/xengsort/xengsort_remove.py +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort/xengsort/xengsort_weak.py +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort.egg-info/dependency_links.txt +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort.egg-info/entry_points.txt +0 -0
- {xengsort-2.0.4 → xengsort-2.0.7}/xengsort.egg-info/top_level.txt +0 -0
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: xengsort
|
|
3
|
-
Version: 2.0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 2.0.7
|
|
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
|
-
License: MIT
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2019-2022 Jens Zentgraf & Sven Rahmann
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
7
28
|
Project-URL: Homepage, https://gitlab.com/genomeinformatics/xengsort
|
|
8
29
|
Project-URL: Bug Tracker, https://gitlab.com/genomeinformatics/xengsort/issues
|
|
9
30
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -14,13 +35,14 @@ Classifier: Environment :: Console
|
|
|
14
35
|
Classifier: Intended Audience :: Science/Research
|
|
15
36
|
Classifier: Natural Language :: English
|
|
16
37
|
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
17
|
-
Requires-Python:
|
|
38
|
+
Requires-Python: >=3.12
|
|
18
39
|
Description-Content-Type: text/markdown
|
|
19
40
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist: numpy>=
|
|
21
|
-
Requires-Dist: numba>=0.
|
|
41
|
+
Requires-Dist: numpy>=2
|
|
42
|
+
Requires-Dist: numba>=0.60
|
|
22
43
|
Requires-Dist: pytest
|
|
23
|
-
Requires-Dist: jsonargparse
|
|
44
|
+
Requires-Dist: jsonargparse>=4.29.0
|
|
45
|
+
Requires-Dist: pip
|
|
24
46
|
|
|
25
47
|
# xengsort: Fast lightweight accurate xenograft sorting
|
|
26
48
|
|
|
@@ -116,7 +138,7 @@ conda create --name xengsort -c conda-forge -c bioconda --file requirements.txt
|
|
|
116
138
|
```
|
|
117
139
|
which will do the same thing using the packages mentioned in `requirements.txt`.
|
|
118
140
|
|
|
119
|
-
**Note:** While xengsort works on
|
|
141
|
+
**Note:** While xengsort works on Linux without problems, some of the required packages may currently not exist for Windows/Mac.
|
|
120
142
|
|
|
121
143
|
Setting up the environment may take some time, as conda searches and downloads packages.
|
|
122
144
|
After all dependencies are resolved, you activate the environment and install the package from the repository into this environment.
|
|
@@ -127,7 +149,7 @@ pip install -e . # install xengsort package using pip
|
|
|
127
149
|
```
|
|
128
150
|
|
|
129
151
|
|
|
130
|
-
|
|
152
|
+
## Run the Snakemake example workflow
|
|
131
153
|
|
|
132
154
|
You can in principle remove `snakemake-minimal` and `sra-toolkit` from the list of packages.
|
|
133
155
|
However, you will not be able to automatically run the provided example workflow or download sequence datasets from SRA.
|
|
@@ -170,7 +192,7 @@ This will run for quite some time (especially downloads and index creation), bes
|
|
|
170
192
|
The results will appear in the `results/` directory.
|
|
171
193
|
|
|
172
194
|
To run your own human/mouse xenograft analysis, you can continue to use the same index.
|
|
173
|
-
All reference files, including the index
|
|
195
|
+
All reference files, including the index (`.hash` and `.info`) are in the `ref/` directory.
|
|
174
196
|
You can follow the structure of the Snakefile to create your own custom workflow.
|
|
175
197
|
Additional information on how to use `xengsort` is given in the usage guide below.
|
|
176
198
|
|
|
@@ -205,29 +227,27 @@ xengsort index --index myindex -H host.fa.gz -G graft.fa.gz -n 4_500_000_000 [O
|
|
|
205
227
|
|
|
206
228
|
We must specify the size of the hash table:
|
|
207
229
|
|
|
208
|
-
- `-n` or `--nobjects`: number of k-mers that will be stored in the hash table. This depends on the used
|
|
230
|
+
- `-n` or `--nobjects`: number of k-mers that will be stored in the hash table. This depends on the used reference genomes and must be estimated beforehand! As a precise estimate of the number of different k-mers can be difficult, you can err on the safe side and provide a generously large estimate, examine the final (low) load factor and then rebuild the index with a smaller `-n` parameter to achieve the desired load. There are also some tools that quickly estimate the number of distinct k-mers in large files, such as [ntCard](https://github.com/bcgsc/ntCard) or [KmerEstimate](https://github.com/srbehera11/KmerEstimate). As a guide: Human and mouse genome and transcriptome together comprise around 4.5 billion 25-mers, as shown in the examples above.
|
|
209
231
|
**This option must be specified; there is no default!**
|
|
210
232
|
|
|
211
233
|
|
|
212
234
|
We may further specify additional properties of the hash table:
|
|
213
235
|
|
|
214
|
-
- `-
|
|
236
|
+
- `-b` or `--bucketsize` indicates how many elements can be stored in one bucket (or page). This is 4 by default.
|
|
215
237
|
|
|
216
238
|
- `--fill` between 0.0 and 1.0 describes the desired fill rate or load factor of the hash table.
|
|
217
239
|
Together with `-n`, the number of slots in the table is calculated as `ceil(n/fill)`. In our experiments we used 0.88. (The number of buckets is then the smallest odd integer that is at least `ceil(ceil(n/fill)/p)`.)
|
|
218
240
|
|
|
219
|
-
- `--aligned` or `--unaligned`: indicates whether each bucket should consume a number of bits that is a power of 2. Using `--aligned` ensures that each bucket stays within the same cache line, but may waste space (padding bits), yielding faster speed but
|
|
241
|
+
- `--aligned` or `--unaligned`: indicates whether each bucket should consume a number of bits that is a power of 2. Using `--aligned` ensures that each bucket stays within the same cache line, but may waste space (padding bits), yielding faster speed but possibly (much!) larger space requirements. With `--unaligned`, no bits are used for padding and buckets may cross cache line boundaries. This is slightly slower, but may save a little or a lot of space (depending on the bucket size in bits). The default is `--unaligned`, because the speed decrease is small and the memory savings can be significant.
|
|
220
242
|
|
|
221
243
|
- `--hashfunctions` defines the parameters for the hash functions used to store the key-value pairs. If the parameter is unspecified, different random functions are chosen each time. The hash functions can be specified using a colon separated list: `--hashfunctions linear945:linear9123641:linear349341847`. It is recommended to have them chosen randomly unless you need strictly reproducible behavior, in which case the example given here is recommended.
|
|
222
244
|
|
|
223
|
-
The final important parameter is about
|
|
245
|
+
The final important parameter is about parallelization:
|
|
224
246
|
|
|
225
|
-
- `-
|
|
226
|
-
|
|
227
|
-
The following hash table options should not be modified from their default values and are for internal development only:
|
|
228
|
-
|
|
229
|
-
- `-P` or `--parameters` can be used to combine all parameters stated above into one string (see the `--help` text)
|
|
247
|
+
- `-W` or `--weakthreads` defines how many threads are used to calculate weak *k*-mers.
|
|
230
248
|
|
|
249
|
+
Most of the parameters can also be provided in a config file (`.yaml`):
|
|
250
|
+
- `--cfg` or `--config` defines the path the the config file.
|
|
231
251
|
|
|
232
252
|
### How to classify
|
|
233
253
|
|
|
@@ -92,7 +92,7 @@ conda create --name xengsort -c conda-forge -c bioconda --file requirements.txt
|
|
|
92
92
|
```
|
|
93
93
|
which will do the same thing using the packages mentioned in `requirements.txt`.
|
|
94
94
|
|
|
95
|
-
**Note:** While xengsort works on
|
|
95
|
+
**Note:** While xengsort works on Linux without problems, some of the required packages may currently not exist for Windows/Mac.
|
|
96
96
|
|
|
97
97
|
Setting up the environment may take some time, as conda searches and downloads packages.
|
|
98
98
|
After all dependencies are resolved, you activate the environment and install the package from the repository into this environment.
|
|
@@ -103,7 +103,7 @@ pip install -e . # install xengsort package using pip
|
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
## Run the Snakemake example workflow
|
|
107
107
|
|
|
108
108
|
You can in principle remove `snakemake-minimal` and `sra-toolkit` from the list of packages.
|
|
109
109
|
However, you will not be able to automatically run the provided example workflow or download sequence datasets from SRA.
|
|
@@ -146,7 +146,7 @@ This will run for quite some time (especially downloads and index creation), bes
|
|
|
146
146
|
The results will appear in the `results/` directory.
|
|
147
147
|
|
|
148
148
|
To run your own human/mouse xenograft analysis, you can continue to use the same index.
|
|
149
|
-
All reference files, including the index
|
|
149
|
+
All reference files, including the index (`.hash` and `.info`) are in the `ref/` directory.
|
|
150
150
|
You can follow the structure of the Snakefile to create your own custom workflow.
|
|
151
151
|
Additional information on how to use `xengsort` is given in the usage guide below.
|
|
152
152
|
|
|
@@ -181,29 +181,27 @@ xengsort index --index myindex -H host.fa.gz -G graft.fa.gz -n 4_500_000_000 [O
|
|
|
181
181
|
|
|
182
182
|
We must specify the size of the hash table:
|
|
183
183
|
|
|
184
|
-
- `-n` or `--nobjects`: number of k-mers that will be stored in the hash table. This depends on the used
|
|
184
|
+
- `-n` or `--nobjects`: number of k-mers that will be stored in the hash table. This depends on the used reference genomes and must be estimated beforehand! As a precise estimate of the number of different k-mers can be difficult, you can err on the safe side and provide a generously large estimate, examine the final (low) load factor and then rebuild the index with a smaller `-n` parameter to achieve the desired load. There are also some tools that quickly estimate the number of distinct k-mers in large files, such as [ntCard](https://github.com/bcgsc/ntCard) or [KmerEstimate](https://github.com/srbehera11/KmerEstimate). As a guide: Human and mouse genome and transcriptome together comprise around 4.5 billion 25-mers, as shown in the examples above.
|
|
185
185
|
**This option must be specified; there is no default!**
|
|
186
186
|
|
|
187
187
|
|
|
188
188
|
We may further specify additional properties of the hash table:
|
|
189
189
|
|
|
190
|
-
- `-
|
|
190
|
+
- `-b` or `--bucketsize` indicates how many elements can be stored in one bucket (or page). This is 4 by default.
|
|
191
191
|
|
|
192
192
|
- `--fill` between 0.0 and 1.0 describes the desired fill rate or load factor of the hash table.
|
|
193
193
|
Together with `-n`, the number of slots in the table is calculated as `ceil(n/fill)`. In our experiments we used 0.88. (The number of buckets is then the smallest odd integer that is at least `ceil(ceil(n/fill)/p)`.)
|
|
194
194
|
|
|
195
|
-
- `--aligned` or `--unaligned`: indicates whether each bucket should consume a number of bits that is a power of 2. Using `--aligned` ensures that each bucket stays within the same cache line, but may waste space (padding bits), yielding faster speed but
|
|
195
|
+
- `--aligned` or `--unaligned`: indicates whether each bucket should consume a number of bits that is a power of 2. Using `--aligned` ensures that each bucket stays within the same cache line, but may waste space (padding bits), yielding faster speed but possibly (much!) larger space requirements. With `--unaligned`, no bits are used for padding and buckets may cross cache line boundaries. This is slightly slower, but may save a little or a lot of space (depending on the bucket size in bits). The default is `--unaligned`, because the speed decrease is small and the memory savings can be significant.
|
|
196
196
|
|
|
197
197
|
- `--hashfunctions` defines the parameters for the hash functions used to store the key-value pairs. If the parameter is unspecified, different random functions are chosen each time. The hash functions can be specified using a colon separated list: `--hashfunctions linear945:linear9123641:linear349341847`. It is recommended to have them chosen randomly unless you need strictly reproducible behavior, in which case the example given here is recommended.
|
|
198
198
|
|
|
199
|
-
The final important parameter is about
|
|
199
|
+
The final important parameter is about parallelization:
|
|
200
200
|
|
|
201
|
-
- `-
|
|
202
|
-
|
|
203
|
-
The following hash table options should not be modified from their default values and are for internal development only:
|
|
204
|
-
|
|
205
|
-
- `-P` or `--parameters` can be used to combine all parameters stated above into one string (see the `--help` text)
|
|
201
|
+
- `-W` or `--weakthreads` defines how many threads are used to calculate weak *k*-mers.
|
|
206
202
|
|
|
203
|
+
Most of the parameters can also be provided in a config file (`.yaml`):
|
|
204
|
+
- `--cfg` or `--config` defines the path the the config file.
|
|
207
205
|
|
|
208
206
|
### How to classify
|
|
209
207
|
|
|
@@ -1,17 +1,35 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["setuptools
|
|
2
|
+
requires = ["setuptools>=69.0.3"]
|
|
3
3
|
build-backend = "setuptools.build_meta"
|
|
4
4
|
|
|
5
|
+
|
|
5
6
|
[project]
|
|
6
7
|
name = "xengsort"
|
|
7
|
-
version = "2.0.
|
|
8
|
+
version = "2.0.7"
|
|
9
|
+
|
|
10
|
+
license = {file = "LICENSE"}
|
|
11
|
+
|
|
8
12
|
authors = [
|
|
9
13
|
{ name="Jens Zentgraf", email="zentgraf@cs.uni-saarland.de" },
|
|
10
14
|
{ name="Sven Rahmann", email="rahmann@cs.uni-saarland.de" }
|
|
11
15
|
]
|
|
12
|
-
|
|
16
|
+
|
|
17
|
+
description = "xenograft sorting of FASTQ reads into five categories: host, graft, both, neither, ambiguous."
|
|
18
|
+
|
|
13
19
|
readme = "README.md"
|
|
14
|
-
|
|
20
|
+
|
|
21
|
+
requires-python = ">=3.12"
|
|
22
|
+
|
|
23
|
+
dependencies = [
|
|
24
|
+
"numpy>=2",
|
|
25
|
+
"numba>=0.60",
|
|
26
|
+
"pytest",
|
|
27
|
+
"jsonargparse>=4.29.0",
|
|
28
|
+
"pip",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
scripts = {xengsort = "xengsort.xengsort.xengsort_main:main"}
|
|
32
|
+
|
|
15
33
|
classifiers = [
|
|
16
34
|
"Programming Language :: Python :: 3",
|
|
17
35
|
"License :: OSI Approved :: MIT License",
|
|
@@ -22,13 +40,10 @@ classifiers = [
|
|
|
22
40
|
"Natural Language :: English",
|
|
23
41
|
"Topic :: Scientific/Engineering :: Bio-Informatics"
|
|
24
42
|
]
|
|
25
|
-
dependencies = [
|
|
26
|
-
"numpy>=1.24",
|
|
27
|
-
"numba>=0.57",
|
|
28
|
-
"pytest",
|
|
29
|
-
"jsonargparse",
|
|
30
|
-
]
|
|
31
43
|
|
|
32
44
|
[project.urls]
|
|
33
45
|
"Homepage" = "https://gitlab.com/genomeinformatics/xengsort"
|
|
34
|
-
"Bug Tracker" = "https://gitlab.com/genomeinformatics/xengsort/issues"
|
|
46
|
+
"Bug Tracker" = "https://gitlab.com/genomeinformatics/xengsort/issues"
|
|
47
|
+
|
|
48
|
+
[tool.setuptools]
|
|
49
|
+
packages=["xengsort"]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from fastcash.io.fastqio import fastq_chunks_paired
|
|
2
|
+
|
|
3
|
+
def test_fastq_chunks_paired_file2_trimmed():
|
|
4
|
+
pair = ("tests/data/test_chunks1.fq", "tests/data/test_chunks2.fq")
|
|
5
|
+
reads1 = 0
|
|
6
|
+
reads2 = 0
|
|
7
|
+
for buf1, linemarks1, buf2, linemarks2 in fastq_chunks_paired(pair, bufsize=4000, maxreads=40):
|
|
8
|
+
assert len(linemarks1) == len(linemarks2)
|
|
9
|
+
for read in range(len(linemarks1)):
|
|
10
|
+
for nuc in range(linemarks2[read][1]-linemarks2[read][0]-1):
|
|
11
|
+
assert buf2[linemarks2[read][0]:linemarks2[read][1]][nuc] == buf1[linemarks1[read][0]:linemarks1[read][1]][nuc]
|
|
12
|
+
reads1 += len(linemarks1)
|
|
13
|
+
reads2 += len(linemarks2)
|
|
14
|
+
assert reads1 == reads2
|
|
15
|
+
assert reads1 == 60
|
|
16
|
+
|
|
17
|
+
def test_fastq_chunks_paired_file1_trimmed():
|
|
18
|
+
pair = ("tests/data/test_chunks2.fq", "tests/data/test_chunks1.fq")
|
|
19
|
+
reads1 = 0
|
|
20
|
+
reads2 = 0
|
|
21
|
+
for buf1, linemarks1, buf2, linemarks2 in fastq_chunks_paired(pair, bufsize=4000, maxreads=40):
|
|
22
|
+
assert len(linemarks1) == len(linemarks2)
|
|
23
|
+
for read in range(len(linemarks1)):
|
|
24
|
+
for nuc in range(linemarks1[read][1]-linemarks1[read][0]-1):
|
|
25
|
+
assert buf2[linemarks2[read][0]:linemarks2[read][1]][nuc] == buf1[linemarks1[read][0]:linemarks1[read][1]][nuc]
|
|
26
|
+
reads1 += len(linemarks1)
|
|
27
|
+
reads2 += len(linemarks2)
|
|
28
|
+
assert reads1 == reads2 == 60
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
fastcash/cptasks_kmers.py
|
|
3
3
|
Functions for compiling ConsumerProducerTasks for k-mers
|
|
4
4
|
"""
|
|
5
5
|
|
|
@@ -65,6 +65,7 @@ def compile_cptask_scatter_kmers_from_linemarked(
|
|
|
65
65
|
if p >= outbufsize:
|
|
66
66
|
if j >= 0:
|
|
67
67
|
outcontrol[j, 7] = outbufsize
|
|
68
|
+
outcontrol[j, 6] = 1 # buffer type k-mer codes
|
|
68
69
|
mark_buffer_for_reading(outcontrol, j)
|
|
69
70
|
stj = j - st * noutbuffers_per_subtable # the "local" j for subtable st
|
|
70
71
|
assert 0 <= stj < noutbuffers_per_subtable
|
|
@@ -175,6 +176,221 @@ def compile_cptask_scatter_kmers_from_linemarked(
|
|
|
175
176
|
assert outbuffers.shape[1] >= outbufsize
|
|
176
177
|
assert outinfos.shape[1] == 0
|
|
177
178
|
|
|
179
|
+
wait_read = wait_write = 0
|
|
180
|
+
nactive = -1 # active input buffer
|
|
181
|
+
outidx = np.full(nsubtables, (-1), dtype=np.int32)
|
|
182
|
+
outpos = np.full(nsubtables, outbufsize, dtype=np.int32)
|
|
183
|
+
while True:
|
|
184
|
+
nactive, wait = find_buffer_for_reading(incontrol, nactive)
|
|
185
|
+
wait_read += wait
|
|
186
|
+
if nactive < 0: # all finished
|
|
187
|
+
errorcode = int(nactive <= -2)
|
|
188
|
+
break
|
|
189
|
+
active_buffer = inbuffers[nactive]
|
|
190
|
+
buffer_type = incontrol[nactive, 6]
|
|
191
|
+
if buffer_type == 0:
|
|
192
|
+
nseqs = incontrol[nactive, 7]
|
|
193
|
+
errorcode = 0
|
|
194
|
+
linemarks = linemarkbuffers[nactive]
|
|
195
|
+
for i in range(nseqs):
|
|
196
|
+
sq = active_buffer[linemarks[i, 0]:linemarks[i, 1]]
|
|
197
|
+
quick_dna_to_2bits(sq)
|
|
198
|
+
(wait, _errorcode) = _process(
|
|
199
|
+
sq, outidx, outpos, outbuffers, outcontrol)
|
|
200
|
+
wait_write += wait
|
|
201
|
+
errorcode |= _errorcode
|
|
202
|
+
if errorcode:
|
|
203
|
+
mark_my_buffers_failed(incontrol)
|
|
204
|
+
debugprint2("- FAILED: cptask_scatter_kmers", errorcode)
|
|
205
|
+
break
|
|
206
|
+
elif buffer_type == 1:
|
|
207
|
+
nkeys = incontrol[nactive, 7]
|
|
208
|
+
errorcode = 0
|
|
209
|
+
active_buffer = active_buffer.view(np.uint64)
|
|
210
|
+
for i in range(nkeys):
|
|
211
|
+
key = active_buffer[i]
|
|
212
|
+
(wait, _errorcode) = _store(
|
|
213
|
+
key, outidx, outpos, outbuffers, outcontrol)
|
|
214
|
+
wait_write += wait
|
|
215
|
+
errorcode |= _errorcode
|
|
216
|
+
if errorcode:
|
|
217
|
+
mark_my_buffers_failed(incontrol)
|
|
218
|
+
debugprint2("- FAILED: cptask_scatter_kmers", errorcode)
|
|
219
|
+
break
|
|
220
|
+
else:
|
|
221
|
+
raise ValueError("- buffer type {buffer_type} not supported in cptask_scatter_kmers")
|
|
222
|
+
|
|
223
|
+
mark_buffer_for_writing(incontrol, nactive)
|
|
224
|
+
# We break out of while True loop when all bufferes were marked as finished by FASTQ reader processes
|
|
225
|
+
# We then let the next task read our output buffers one final time.
|
|
226
|
+
if not errorcode:
|
|
227
|
+
for st in range(nsubtables):
|
|
228
|
+
j = outidx[st]
|
|
229
|
+
if j >= 0:
|
|
230
|
+
# assert outpos[st] > 0
|
|
231
|
+
outcontrol[j, 7] = outpos[st]
|
|
232
|
+
mark_buffer_for_reading(outcontrol, j)
|
|
233
|
+
debugprint2("- ending: cptask_scatter_kmers", errorcode)
|
|
234
|
+
return (wait_read, wait_write, -errorcode)
|
|
235
|
+
|
|
236
|
+
return _cptask_scatter_kmers
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def compile_cptask_scatter_kmers_position_from_linemarked(
|
|
240
|
+
mask, values, rcmode, hf0,
|
|
241
|
+
nsubtables, noutbuffers_per_subtable, outbufsize):
|
|
242
|
+
"""
|
|
243
|
+
Compile a cptask function that
|
|
244
|
+
creates (gapped) k-mers and value from linemarked buffers.
|
|
245
|
+
The Value is a compressed representation of chromosome and position.
|
|
246
|
+
- mask: a Mask object
|
|
247
|
+
- rcmode: how to treat reverse complements; f, r, b, max, min
|
|
248
|
+
- hf0: the 0-th hash function that determines the subtable
|
|
249
|
+
- nsubtables: the number of subtables
|
|
250
|
+
- noutbuffers_per_subtable: number of output buffers per subtable
|
|
251
|
+
- outbufsize: the output buffer size for which to compile this function
|
|
252
|
+
"""
|
|
253
|
+
debugprint0, debugprint1, debugprint2 = debug.debugprint
|
|
254
|
+
both = (rcmode[0].lower() == "b")
|
|
255
|
+
|
|
256
|
+
k, w, tpl = mask.k, mask.w, mask.tuple
|
|
257
|
+
assert len(tpl) == k
|
|
258
|
+
if k < 1 or k > 32:
|
|
259
|
+
raise ValueError(f"Only 1 <= k <= 32 is supported, but {k=}.")
|
|
260
|
+
codemask = uint64(4**(k - 1) - 1)
|
|
261
|
+
revcomp, ccode = compile_revcomp_and_canonical_code(k, rcmode)
|
|
262
|
+
if mask.is_contiguous:
|
|
263
|
+
debugprint1(f"- compiling cptask_scatter_kmers for contiguous {k}-mers.")
|
|
264
|
+
else:
|
|
265
|
+
debugprint1(f"- compiling cptask_scatter_kmers for gapped ({k},{w})-mers: {mask.mask}.")
|
|
266
|
+
|
|
267
|
+
merge_seq_pos = values.merge_seq_pos
|
|
268
|
+
|
|
269
|
+
@njit(nogil=True, locals=dict(
|
|
270
|
+
code=uint64, st=uint64, sk=uint64,
|
|
271
|
+
j=int32, stj=int32, p=int32, wait=int64))
|
|
272
|
+
def _store(code, chrom, position, outidx, outpos, outbuffers, outcontrol):
|
|
273
|
+
st, sk = hf0(code)
|
|
274
|
+
j = outidx[st]
|
|
275
|
+
p = outpos[st]
|
|
276
|
+
error = 0
|
|
277
|
+
wait_write = 0 # TODO: do we count wait time correctly?
|
|
278
|
+
if p >= outbufsize:
|
|
279
|
+
if j >= 0:
|
|
280
|
+
outcontrol[j, 7] = outbufsize
|
|
281
|
+
outcontrol[j, 6] = 1 # buffer type k-mer codes
|
|
282
|
+
mark_buffer_for_reading(outcontrol, j)
|
|
283
|
+
stj = j - st * noutbuffers_per_subtable # the "local" j for subtable st
|
|
284
|
+
assert 0 <= stj < noutbuffers_per_subtable
|
|
285
|
+
else:
|
|
286
|
+
assert j == -1
|
|
287
|
+
stj = -1
|
|
288
|
+
stoutcontrol = outcontrol[(st * noutbuffers_per_subtable):(st + 1) * noutbuffers_per_subtable]
|
|
289
|
+
stj, wait = find_buffer_for_writing(stoutcontrol, stj)
|
|
290
|
+
outidx[st] = j = (stj + st * noutbuffers_per_subtable)
|
|
291
|
+
outpos[st] = p = 0
|
|
292
|
+
error = outcontrol[j, 1]
|
|
293
|
+
outbuffers[j, p] = sk # put subkey (not code!) into outbuffer
|
|
294
|
+
value = merge_seq_pos(chrom, position)
|
|
295
|
+
outbuffers[j, p + 1] = value
|
|
296
|
+
outpos[st] += 2
|
|
297
|
+
return (wait, error)
|
|
298
|
+
|
|
299
|
+
@njit(nogil=True, locals=dict(
|
|
300
|
+
code=uint64, i=int64, j=int64, c=uint64,
|
|
301
|
+
errorcode=int32, _errorcode=int32,
|
|
302
|
+
wait=int64, _wait=int64))
|
|
303
|
+
def _process_gapped(seq, chrom, offset, *allout): # (outidx, outpos, outbuffers, outcontrol):
|
|
304
|
+
startpoints = seq.size - tpl[k - 1]
|
|
305
|
+
errorcode = 0
|
|
306
|
+
wait = 0
|
|
307
|
+
for i in range(startpoints):
|
|
308
|
+
code = 0
|
|
309
|
+
for j in tpl:
|
|
310
|
+
c = seq[i + j]
|
|
311
|
+
if c > 3:
|
|
312
|
+
break
|
|
313
|
+
code = uint64(code << 2) | uint64(c)
|
|
314
|
+
else: # no break
|
|
315
|
+
if both:
|
|
316
|
+
_wait, errorcode = _store(code, chrom, offset + i, *allout) # outidx, outpos, outbuffers, outcontrol)
|
|
317
|
+
wait += wait
|
|
318
|
+
_wait, _errorcode = _store(revcomp(code), chrom, offset + i, *allout) # outidx, outpos, outbuffers, outcontrol)
|
|
319
|
+
wait += _wait
|
|
320
|
+
errorcode |= _errorcode
|
|
321
|
+
else:
|
|
322
|
+
_wait, errorcode = _store(ccode(code), chrom, offset + i, *allout) # outidx, outpos, outbuffers, outcontrol)
|
|
323
|
+
wait += _wait
|
|
324
|
+
if errorcode != 0:
|
|
325
|
+
break
|
|
326
|
+
return (wait, errorcode)
|
|
327
|
+
|
|
328
|
+
@njit(nogil=True, locals=dict(
|
|
329
|
+
code=uint64, i=int64, j=int64, c=uint64, errorcode=int32,
|
|
330
|
+
wait=int64, _wait=int64))
|
|
331
|
+
def _process_contiguous(seq, chrom, offset, *allout): # (outidx, outpos, outbuffers, outcontrol):
|
|
332
|
+
endpoint = seq.size - (k - 1)
|
|
333
|
+
valid = False
|
|
334
|
+
errorcode = 0
|
|
335
|
+
wait = 0
|
|
336
|
+
i = 0
|
|
337
|
+
while i < endpoint:
|
|
338
|
+
if not valid:
|
|
339
|
+
code = 0
|
|
340
|
+
for j in range(k):
|
|
341
|
+
c = seq[i + j]
|
|
342
|
+
if c > 3:
|
|
343
|
+
i += j + 1 # skip invalid
|
|
344
|
+
break
|
|
345
|
+
code = (code << 2) | c
|
|
346
|
+
else: # no break
|
|
347
|
+
valid = True
|
|
348
|
+
if not valid:
|
|
349
|
+
continue # with while
|
|
350
|
+
else: # was valid, we have an old code
|
|
351
|
+
c = seq[i + k - 1]
|
|
352
|
+
if c > 3:
|
|
353
|
+
valid = False
|
|
354
|
+
i += k # skip invalid
|
|
355
|
+
continue # with while
|
|
356
|
+
code = ((code & codemask) << 2) | c
|
|
357
|
+
# at this point, we have a valid code
|
|
358
|
+
if both:
|
|
359
|
+
_wait, errorcode = _store(code, chrom, offset + i, *allout) # outidx, outpos, outbuffers, outcontrol)
|
|
360
|
+
wait += _wait
|
|
361
|
+
_wait, _errorcode = _store(revcomp(code), chrom, offset + i, *allout) # outidx, outpos, outbuffers, outcontrol)
|
|
362
|
+
wait += _wait
|
|
363
|
+
errorcode |= _errorcode
|
|
364
|
+
else:
|
|
365
|
+
_wait, errorcode = _store(ccode(code), chrom, offset + i, *allout) # outidx, outpos, outbuffers, outcontrol)
|
|
366
|
+
wait += _wait
|
|
367
|
+
i += 1
|
|
368
|
+
if errorcode != 0:
|
|
369
|
+
break
|
|
370
|
+
return (wait, errorcode)
|
|
371
|
+
|
|
372
|
+
_process = _process_contiguous if mask.is_contiguous else _process_gapped
|
|
373
|
+
|
|
374
|
+
@njit(nogil=True, locals=dict(
|
|
375
|
+
nactive=int32, nseqs=int32, i=int32, j=int32, outj=int32,
|
|
376
|
+
wait=int64, wait_read=int64, wait_write=int64,
|
|
377
|
+
errorcode=int32, _errorcode=int32))
|
|
378
|
+
def _cptask_scatter_kmers(inbuffers, incontrol, ininfos, outbuffers, outcontrol, outinfos):
|
|
379
|
+
# find a linemarked buffer to read (among inbuffers)
|
|
380
|
+
# find and reserve nsubtables output buffers among the output buffers [outinfos]
|
|
381
|
+
# incontrol[i, 7]: number of FASTQ reads in input buffer i
|
|
382
|
+
# ininfos[i]: linemarks for input buffer i
|
|
383
|
+
# outcontrol[B, 7]: k-mers in buffer B
|
|
384
|
+
debugprint2("- running: cptask_scatter_kmers; outbuffers shape =", outbuffers.shape)
|
|
385
|
+
assert inbuffers.ndim == 2
|
|
386
|
+
assert outbuffers.ndim == 2
|
|
387
|
+
M, N = ininfos.shape
|
|
388
|
+
assert N % 6 == 0 # We have 6 entries per linemark. Start and end of record and read and chromosome and positions
|
|
389
|
+
linemarkbuffers = ininfos.reshape(M, N // 6, 6)
|
|
390
|
+
assert outbuffers.shape[0] == nsubtables * noutbuffers_per_subtable
|
|
391
|
+
assert outbuffers.shape[1] >= outbufsize
|
|
392
|
+
assert outinfos.shape[1] == 0
|
|
393
|
+
|
|
178
394
|
wait_read = wait_write = 0
|
|
179
395
|
nactive = -1 # active input buffer
|
|
180
396
|
outidx = np.full(nsubtables, (-1), dtype=np.int32)
|
|
@@ -187,13 +403,18 @@ def compile_cptask_scatter_kmers_from_linemarked(
|
|
|
187
403
|
break
|
|
188
404
|
active_buffer = inbuffers[nactive]
|
|
189
405
|
nseqs = incontrol[nactive, 7]
|
|
406
|
+
buffer_type = incontrol[nactive, 6]
|
|
407
|
+
assert buffer_type == 0 # 0 means sequence buffer
|
|
408
|
+
|
|
190
409
|
errorcode = 0
|
|
191
410
|
linemarks = linemarkbuffers[nactive]
|
|
192
411
|
for i in range(nseqs):
|
|
193
412
|
sq = active_buffer[linemarks[i, 0]:linemarks[i, 1]]
|
|
413
|
+
chromosome = linemarks[i, 4]
|
|
414
|
+
position = linemarks[i, 5]
|
|
194
415
|
quick_dna_to_2bits(sq)
|
|
195
416
|
(wait, _errorcode) = _process(
|
|
196
|
-
sq, outidx, outpos, outbuffers, outcontrol)
|
|
417
|
+
sq, chromosome, position, outidx, outpos, outbuffers, outcontrol)
|
|
197
418
|
wait_write += wait
|
|
198
419
|
errorcode |= _errorcode
|
|
199
420
|
if errorcode:
|
|
@@ -201,7 +422,7 @@ def compile_cptask_scatter_kmers_from_linemarked(
|
|
|
201
422
|
debugprint2("- FAILED: cptask_scatter_kmers", errorcode)
|
|
202
423
|
break
|
|
203
424
|
mark_buffer_for_writing(incontrol, nactive)
|
|
204
|
-
# We break out of while True loop when all
|
|
425
|
+
# We break out of while True loop when all buffers were marked as finished by FASTQ reader processes
|
|
205
426
|
# We then let the next task read our output buffers one final time.
|
|
206
427
|
if not errorcode:
|
|
207
428
|
for st in range(nsubtables):
|
|
@@ -216,6 +437,68 @@ def compile_cptask_scatter_kmers_from_linemarked(
|
|
|
216
437
|
return _cptask_scatter_kmers
|
|
217
438
|
|
|
218
439
|
|
|
440
|
+
def compile_cptask_insert_subkey_value(
|
|
441
|
+
myhashtable,
|
|
442
|
+
maxfailures=0,
|
|
443
|
+
maxwalk=1000):
|
|
444
|
+
debugprint0, debugprint1, debugprint2 = debug.debugprint
|
|
445
|
+
update = myhashtable.private.update_ssk
|
|
446
|
+
|
|
447
|
+
@njit(nogil=True, locals=dict(
|
|
448
|
+
nactive=int32, value=uint64, mytotal=int64, failed=int64,
|
|
449
|
+
nsubkeys=int32, subkey=uint64, status=int32, result=uint64,
|
|
450
|
+
wait=int64, wait_read=int64, wait_write=int64))
|
|
451
|
+
def _cptask_insert_subkey_value(st, ht, ft, inbuffers, incontrol, ininfos, outbuffers, outcontrol, outinfos):
|
|
452
|
+
"""
|
|
453
|
+
Insert subkeys and values of k-mers into subtables of a hash table.
|
|
454
|
+
"""
|
|
455
|
+
# incontrol[i, 0]: buffer status
|
|
456
|
+
# incontrol[i, 1]: set to nonzero on error
|
|
457
|
+
# incontrol[i, 7]: k-mers (or subkeys) in input buffer i
|
|
458
|
+
assert inbuffers.ndim == 2
|
|
459
|
+
assert outbuffers.ndim == 2
|
|
460
|
+
assert outbuffers.shape[0] == 1
|
|
461
|
+
assert outbuffers.shape[1] >= maxwalk + 1
|
|
462
|
+
assert outinfos.shape[1] == 0
|
|
463
|
+
debugprint2("- running: cptask_insert_subkey_value; subtable", st)
|
|
464
|
+
|
|
465
|
+
wait_read = wait_write = 0
|
|
466
|
+
nactive = -1 # active input buffer
|
|
467
|
+
active_buffer = inbuffers[0] # irrelevant
|
|
468
|
+
out = outbuffers[0]
|
|
469
|
+
failed = mytotal = 0
|
|
470
|
+
while True:
|
|
471
|
+
nactive, wait = find_buffer_for_reading(incontrol, nactive)
|
|
472
|
+
wait_read += wait
|
|
473
|
+
if nactive < 0: # all finished
|
|
474
|
+
debugprint2("- ending: cptask_insert_subkey_value; subtable", st, "with", mytotal, "total and", failed, "failed k-mers.")
|
|
475
|
+
break
|
|
476
|
+
active_buffer = inbuffers[nactive]
|
|
477
|
+
nsubkeys = incontrol[nactive, 7]
|
|
478
|
+
buffer_type = incontrol[nactive, 6]
|
|
479
|
+
assert buffer_type == 1 # 1 means k-mer/subkey buffer
|
|
480
|
+
# TODO: NOTE: This is an interleaved subkey/value buffer.
|
|
481
|
+
# Is this a different type?
|
|
482
|
+
|
|
483
|
+
# consume the buffer
|
|
484
|
+
for i in range(0, nsubkeys, 2):
|
|
485
|
+
subkey = active_buffer[i]
|
|
486
|
+
value = active_buffer[i + 1]
|
|
487
|
+
status, result = update(ht, st, subkey, value) # see docstring below
|
|
488
|
+
if status & 128 == 0:
|
|
489
|
+
out[result] += 1
|
|
490
|
+
failed += (status == 0)
|
|
491
|
+
mytotal += nsubkeys
|
|
492
|
+
mark_buffer_for_writing(incontrol, nactive)
|
|
493
|
+
if failed > maxfailures:
|
|
494
|
+
mark_my_buffers_failed(incontrol)
|
|
495
|
+
debugprint2("- FAILED: cptask_insert_subkey_value; subtable", st, "with", mytotal, "total and", failed, "failed k-mers.")
|
|
496
|
+
break
|
|
497
|
+
return (mytotal, failed, wait_read, wait_write, -(failed > 0))
|
|
498
|
+
|
|
499
|
+
return _cptask_insert_subkey_value
|
|
500
|
+
|
|
501
|
+
|
|
219
502
|
def compile_cptask_insert_filtered_subkeys(
|
|
220
503
|
myhashtable,
|
|
221
504
|
myfilter,
|
|
@@ -229,7 +512,7 @@ def compile_cptask_insert_filtered_subkeys(
|
|
|
229
512
|
else:
|
|
230
513
|
wwo = "without"
|
|
231
514
|
|
|
232
|
-
@njit(nogil=True
|
|
515
|
+
@njit(nogil=True)
|
|
233
516
|
def lookup_and_insert_in_subfilter(ft, st, subkey):
|
|
234
517
|
return True
|
|
235
518
|
update = myhashtable.private.update_ssk
|
|
@@ -268,6 +551,9 @@ def compile_cptask_insert_filtered_subkeys(
|
|
|
268
551
|
break
|
|
269
552
|
active_buffer = inbuffers[nactive]
|
|
270
553
|
nsubkeys = incontrol[nactive, 7]
|
|
554
|
+
buffer_type = incontrol[nactive, 6]
|
|
555
|
+
assert buffer_type == 1 # 1 means k-mer buffer (or subkeys)
|
|
556
|
+
|
|
271
557
|
# consume the buffer
|
|
272
558
|
for subkey in active_buffer[:nsubkeys]:
|
|
273
559
|
if lookup_and_insert_in_subfilter(ft, st, subkey):
|
|
@@ -316,11 +602,22 @@ def compile_cptask_update_existing_subkeys(
|
|
|
316
602
|
break
|
|
317
603
|
active_buffer = inbuffers[nactive]
|
|
318
604
|
nsubkeys = incontrol[nactive, 7]
|
|
605
|
+
buffer_type = incontrol[nactive, 6]
|
|
606
|
+
# print("&&& buffer_type", buffer_type)
|
|
607
|
+
assert buffer_type == 1 # 1 means k-mer buffer (0 would be sequence buffer)
|
|
608
|
+
|
|
319
609
|
# consume the buffer
|
|
320
|
-
for
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
610
|
+
for ii in range(nsubkeys):
|
|
611
|
+
subkey = active_buffer[ii]
|
|
612
|
+
_, _ = update_existing(ht, st, subkey, value) # see docstring below
|
|
613
|
+
# status, result = update_existing(ht, st, subkey, value) # see docstring below
|
|
614
|
+
# if status & 128:
|
|
615
|
+
# print("update ->", result)
|
|
616
|
+
# else:
|
|
617
|
+
# print("ignore unknown")
|
|
618
|
+
# if status & 128 == 0:
|
|
619
|
+
# failed += (status == 0) # TODO: should we not just ignore new stuff?
|
|
620
|
+
# The current implementation will count not directly insertable stuff as failures.
|
|
324
621
|
mytotal += nsubkeys
|
|
325
622
|
mark_buffer_for_writing(incontrol, nactive)
|
|
326
623
|
debugprint2("- ending: cptask_update_existing_subkeys; subtable", st, "with", mytotal, "total and", failed, "failed k-mers.")
|