bioforge 3.4.0__tar.gz → 4.0.0__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.
- {bioforge-3.4.0 → bioforge-4.0.0}/PKG-INFO +16 -7
- {bioforge-3.4.0 → bioforge-4.0.0}/README.md +15 -6
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/__init__.py +1 -1
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/genomemap.py +110 -20
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge.egg-info/PKG-INFO +16 -7
- {bioforge-3.4.0 → bioforge-4.0.0}/tests/test_genomemap.py +50 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/LICENSE +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/aligner.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/analyze.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/bgzf.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/biocore.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/engine/__init__.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/engine/_loader.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/engine/build.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/engine/engine.c +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/engine/engine.dll +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/minimizers.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/qcreport.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/refindex.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge/smart_translator.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge.egg-info/SOURCES.txt +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge.egg-info/dependency_links.txt +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge.egg-info/entry_points.txt +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge.egg-info/requires.txt +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/bioforge.egg-info/top_level.txt +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/pyproject.toml +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/setup.cfg +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/setup.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/tests/test_aligner.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/tests/test_analyze.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/tests/test_bgzf.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/tests/test_biocore.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/tests/test_errors.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/tests/test_minimizers.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/tests/test_qcreport.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/tests/test_refindex.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/tests/test_streaming.py +0 -0
- {bioforge-3.4.0 → bioforge-4.0.0}/tests/test_translator.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bioforge
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0
|
|
4
4
|
Summary: High-performance bioinformatics engine for Edge Computing — 5-bit encoding, vectorised NumPy core, optional C backend
|
|
5
5
|
Author-email: Aarón Aranda Torrijos <noe9601@gmail.com>
|
|
6
6
|
License: # PolyForm Noncommercial License 1.0.0
|
|
@@ -562,17 +562,26 @@ minimap2-style: minimizer seeding → chaining (C DP) → banded extension.
|
|
|
562
562
|
```python
|
|
563
563
|
from bioforge import GenomeAligner
|
|
564
564
|
|
|
565
|
-
|
|
565
|
+
# Single sequence, or a whole multi-contig genome:
|
|
566
|
+
mapper = GenomeAligner({"chr1": chr1_seq, "chr2": chr2_seq, "plasmid": p_seq})
|
|
566
567
|
|
|
567
568
|
for m in mapper.map(read):
|
|
568
569
|
print(m.to_paf()) # standard PAF, one line per mapping
|
|
569
|
-
|
|
570
|
-
|
|
570
|
+
print(m.target_name, m.strand, m.target_start, f"{m.identity:.1%}")
|
|
571
|
+
|
|
572
|
+
# Map many reads in parallel (uses processes):
|
|
573
|
+
results = mapper.map_batch(reads, n_processes=0) # 0 = all cores
|
|
571
574
|
```
|
|
572
575
|
|
|
573
|
-
Handles
|
|
574
|
-
|
|
575
|
-
|
|
576
|
+
Handles multi-chromosome references (reports the contig + local coordinates),
|
|
577
|
+
both strands, aligns the full read, tolerates mismatches/indels, and reports a
|
|
578
|
+
mapping quality. The minimizer and chaining kernels run in the C engine (with
|
|
579
|
+
NumPy fallbacks).
|
|
580
|
+
|
|
581
|
+
> **Speed, honestly:** indexing is fast, but read mapping is not yet
|
|
582
|
+
> competitive with hand-tuned C mappers like minimap2 — the mapping pipeline is
|
|
583
|
+
> being moved into the C engine. Use BioForge's mapper where its strengths fit:
|
|
584
|
+
> pure-Python/NumPy core, tiny footprint, `pip install` and go, no C toolchain.
|
|
576
585
|
|
|
577
586
|
### Full mutation analysis pipeline (DNA + protein)
|
|
578
587
|
|
|
@@ -242,17 +242,26 @@ minimap2-style: minimizer seeding → chaining (C DP) → banded extension.
|
|
|
242
242
|
```python
|
|
243
243
|
from bioforge import GenomeAligner
|
|
244
244
|
|
|
245
|
-
|
|
245
|
+
# Single sequence, or a whole multi-contig genome:
|
|
246
|
+
mapper = GenomeAligner({"chr1": chr1_seq, "chr2": chr2_seq, "plasmid": p_seq})
|
|
246
247
|
|
|
247
248
|
for m in mapper.map(read):
|
|
248
249
|
print(m.to_paf()) # standard PAF, one line per mapping
|
|
249
|
-
|
|
250
|
-
|
|
250
|
+
print(m.target_name, m.strand, m.target_start, f"{m.identity:.1%}")
|
|
251
|
+
|
|
252
|
+
# Map many reads in parallel (uses processes):
|
|
253
|
+
results = mapper.map_batch(reads, n_processes=0) # 0 = all cores
|
|
251
254
|
```
|
|
252
255
|
|
|
253
|
-
Handles
|
|
254
|
-
|
|
255
|
-
|
|
256
|
+
Handles multi-chromosome references (reports the contig + local coordinates),
|
|
257
|
+
both strands, aligns the full read, tolerates mismatches/indels, and reports a
|
|
258
|
+
mapping quality. The minimizer and chaining kernels run in the C engine (with
|
|
259
|
+
NumPy fallbacks).
|
|
260
|
+
|
|
261
|
+
> **Speed, honestly:** indexing is fast, but read mapping is not yet
|
|
262
|
+
> competitive with hand-tuned C mappers like minimap2 — the mapping pipeline is
|
|
263
|
+
> being moved into the C engine. Use BioForge's mapper where its strengths fit:
|
|
264
|
+
> pure-Python/NumPy core, tiny footprint, `pip install` and go, no C toolchain.
|
|
256
265
|
|
|
257
266
|
### Full mutation analysis pipeline (DNA + protein)
|
|
258
267
|
|
|
@@ -255,12 +255,19 @@ class Mapping(NamedTuple):
|
|
|
255
255
|
identity: float
|
|
256
256
|
chain_score: float
|
|
257
257
|
cigar: Optional[str]
|
|
258
|
+
target_name: str = "ref" # nombre del contig/cromosoma al que mapea
|
|
258
259
|
|
|
259
|
-
def to_paf(self, query_name: str = "query",
|
|
260
|
-
|
|
260
|
+
def to_paf(self, query_name: str = "query",
|
|
261
|
+
target_name: Optional[str] = None) -> str:
|
|
262
|
+
"""Serializa a una línea PAF (el formato de minimap2).
|
|
263
|
+
|
|
264
|
+
Si no se pasa ``target_name``, se usa el del propio mapeo (el contig al
|
|
265
|
+
que mapeó, útil con referencias multi-cromosoma).
|
|
266
|
+
"""
|
|
267
|
+
tname = target_name if target_name is not None else self.target_name
|
|
261
268
|
fields = [
|
|
262
269
|
query_name, self.query_len, self.query_start, self.query_end,
|
|
263
|
-
self.strand,
|
|
270
|
+
self.strand, tname, self.target_len,
|
|
264
271
|
self.target_start, self.target_end,
|
|
265
272
|
self.num_matches, self.block_len, self.mapq,
|
|
266
273
|
]
|
|
@@ -300,12 +307,31 @@ def _cigar(aln_ref: str, aln_read: str) -> tuple[str, int, int]:
|
|
|
300
307
|
return cigar, n_match, int(op.size)
|
|
301
308
|
|
|
302
309
|
|
|
303
|
-
def _extend(ref: str, read: str, ch: Chain
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
310
|
+
def _extend(ref: str, read: str, ch: Chain, k: int,
|
|
311
|
+
cstart: int, cend: int) -> Optional[Mapping]:
|
|
312
|
+
"""Fase 5: alinea el READ COMPLETO contra la referencia y arma el Mapping.
|
|
313
|
+
|
|
314
|
+
La ventana de referencia se sitúa por la diagonal de la cadena
|
|
315
|
+
(``d`` = posición ref donde cae el inicio del read) y se recorta al contig
|
|
316
|
+
``[cstart, cend)``. Así la alineación cubre todo el read (no solo la región
|
|
317
|
+
de la cadena); si el read sobresale por un borde del contig, esa parte queda
|
|
318
|
+
recortada (soft-clip) de forma natural.
|
|
319
|
+
"""
|
|
320
|
+
Lr = len(read)
|
|
321
|
+
if ch.strand == 0:
|
|
322
|
+
d = int(np.median(ch.anchor_ref - ch.anchor_read))
|
|
323
|
+
oriented = read
|
|
324
|
+
else:
|
|
325
|
+
# hebra inversa: se alinea revcomp(read) hacia delante; diagonal:
|
|
326
|
+
d = int(np.median(ch.anchor_ref + ch.anchor_read)) - (Lr - k)
|
|
327
|
+
oriented = _revcomp(read)
|
|
328
|
+
|
|
329
|
+
rs = max(cstart, d)
|
|
330
|
+
re = min(cend, d + Lr)
|
|
331
|
+
if re - rs < 1:
|
|
332
|
+
return None
|
|
333
|
+
ref_sub = ref[rs:re]
|
|
334
|
+
read_sub = oriented[rs - d:re - d] # porción del read dentro de la ventana
|
|
309
335
|
if not ref_sub or not read_sub:
|
|
310
336
|
return None
|
|
311
337
|
|
|
@@ -317,15 +343,20 @@ def _extend(ref: str, read: str, ch: Chain) -> Optional[Mapping]:
|
|
|
317
343
|
cigar, n_match, block = _cigar(res.aligned_a, res.aligned_b)
|
|
318
344
|
identity = res.identity
|
|
319
345
|
except Exception: # noqa: BLE001 — extensión best-effort
|
|
320
|
-
cigar, n_match, block, identity = None, ch.n_anchors *
|
|
321
|
-
|
|
346
|
+
cigar, n_match, block, identity = None, ch.n_anchors * k, re - rs, 1.0
|
|
347
|
+
|
|
348
|
+
# coords de query en el read ORIGINAL (hacia delante), aun en hebra inversa
|
|
349
|
+
if ch.strand == 0:
|
|
350
|
+
q_start, q_end = rs - d, re - d
|
|
351
|
+
else:
|
|
352
|
+
q_start, q_end = Lr - (re - d), Lr - (rs - d)
|
|
322
353
|
|
|
323
354
|
return Mapping(
|
|
324
|
-
query_len=
|
|
325
|
-
query_start=
|
|
355
|
+
query_len=Lr,
|
|
356
|
+
query_start=q_start, query_end=q_end,
|
|
326
357
|
strand="+" if ch.strand == 0 else "-",
|
|
327
358
|
target_len=len(ref),
|
|
328
|
-
target_start=
|
|
359
|
+
target_start=rs, target_end=re,
|
|
329
360
|
num_matches=n_match, block_len=block,
|
|
330
361
|
mapq=0, identity=identity, chain_score=ch.score, cigar=cigar,
|
|
331
362
|
)
|
|
@@ -357,19 +388,74 @@ def _mp_worker(args) -> "list[Mapping]":
|
|
|
357
388
|
|
|
358
389
|
|
|
359
390
|
class GenomeAligner:
|
|
360
|
-
"""Mapeador de reads contra una referencia (seed-chain-align).
|
|
391
|
+
"""Mapeador de reads contra una referencia (seed-chain-align).
|
|
392
|
+
|
|
393
|
+
La referencia puede ser:
|
|
394
|
+
• una cadena (un solo contig), o
|
|
395
|
+
• un dict ``{nombre: secuencia}`` o iterable de ``(nombre, secuencia)``
|
|
396
|
+
para varios cromosomas/contigs (genomas reales).
|
|
397
|
+
|
|
398
|
+
Multi-contig: los contigs se concatenan con separadores de ``N`` (que los
|
|
399
|
+
minimizers excluyen → ningún k-mer cruza fronteras). Se indexa el conjunto y
|
|
400
|
+
al mapear la posición global se traduce a (contig, posición local).
|
|
401
|
+
"""
|
|
361
402
|
|
|
362
|
-
def __init__(self, reference
|
|
403
|
+
def __init__(self, reference, k: int = 15, w: int = 10,
|
|
363
404
|
max_occ: Optional[int] = 50, name: str = "ref"):
|
|
364
|
-
self.reference
|
|
365
|
-
|
|
405
|
+
contigs = self._normalize(reference, name) # [(nombre, seq), ...]
|
|
406
|
+
sep = "N" * k # rompe k-meros de frontera
|
|
407
|
+
parts: list[str] = []
|
|
408
|
+
self._names: list[str] = []
|
|
409
|
+
self._starts_list: list[int] = []
|
|
410
|
+
self._lengths: list[int] = []
|
|
411
|
+
g = 0
|
|
412
|
+
for i, (nm, seq) in enumerate(contigs):
|
|
413
|
+
seq = seq.upper()
|
|
414
|
+
if i > 0:
|
|
415
|
+
parts.append(sep); g += len(sep)
|
|
416
|
+
self._names.append(str(nm))
|
|
417
|
+
self._starts_list.append(g)
|
|
418
|
+
self._lengths.append(len(seq))
|
|
419
|
+
parts.append(seq); g += len(seq)
|
|
420
|
+
|
|
421
|
+
self.reference = "".join(parts) # concatenado (con N)
|
|
422
|
+
self._starts = np.array(self._starts_list, dtype=np.int64)
|
|
423
|
+
self.name = self._names[0] if len(self._names) == 1 else "multi"
|
|
366
424
|
self.index = ReferenceIndex.from_sequence(self.reference, k=k, w=w,
|
|
367
425
|
max_occ=max_occ)
|
|
368
426
|
|
|
427
|
+
@staticmethod
|
|
428
|
+
def _normalize(reference, name: str) -> "list[tuple[str, str]]":
|
|
429
|
+
if isinstance(reference, str):
|
|
430
|
+
return [(name, reference)]
|
|
431
|
+
if isinstance(reference, dict):
|
|
432
|
+
return list(reference.items())
|
|
433
|
+
return [(n, s) for n, s in reference] # iterable de pares
|
|
434
|
+
|
|
369
435
|
@property
|
|
370
436
|
def k(self) -> int:
|
|
371
437
|
return self.index.k
|
|
372
438
|
|
|
439
|
+
@property
|
|
440
|
+
def n_contigs(self) -> int:
|
|
441
|
+
return len(self._names)
|
|
442
|
+
|
|
443
|
+
def _contig_of(self, gpos: int) -> int:
|
|
444
|
+
"""Índice del contig que contiene la posición global ``gpos``."""
|
|
445
|
+
i = int(np.searchsorted(self._starts, gpos, side="right")) - 1
|
|
446
|
+
return max(0, i)
|
|
447
|
+
|
|
448
|
+
def _localize(self, mp: Mapping) -> Mapping:
|
|
449
|
+
"""Traduce coords globales de un mapeo a (contig, coords locales)."""
|
|
450
|
+
ci = self._contig_of(mp.target_start)
|
|
451
|
+
cstart, clen = self._starts_list[ci], self._lengths[ci]
|
|
452
|
+
return mp._replace(
|
|
453
|
+
target_name=self._names[ci],
|
|
454
|
+
target_len=clen,
|
|
455
|
+
target_start=mp.target_start - cstart,
|
|
456
|
+
target_end=min(mp.target_end - cstart, clen),
|
|
457
|
+
)
|
|
458
|
+
|
|
373
459
|
def map(self, read: str, min_chain_score: float = 40.0,
|
|
374
460
|
max_hits: int = 5) -> list[Mapping]:
|
|
375
461
|
"""Mapea un read → lista de Mapping (primaria primero)."""
|
|
@@ -378,9 +464,13 @@ class GenomeAligner:
|
|
|
378
464
|
chains = chain(anchors, min_score=min_chain_score)[:max_hits]
|
|
379
465
|
mappings: list[Mapping] = []
|
|
380
466
|
for i, ch in enumerate(chains):
|
|
381
|
-
|
|
467
|
+
# Contig de la cadena → sus límites acotan la ventana de extensión.
|
|
468
|
+
ci = self._contig_of(ch.ref_start)
|
|
469
|
+
cstart = self._starts_list[ci]
|
|
470
|
+
cend = cstart + self._lengths[ci]
|
|
471
|
+
mp = _extend(self.reference, read, ch, self.k, cstart, cend)
|
|
382
472
|
if mp is not None:
|
|
383
|
-
mappings.append(mp._replace(mapq=_mapq(chains, i)))
|
|
473
|
+
mappings.append(self._localize(mp._replace(mapq=_mapq(chains, i))))
|
|
384
474
|
return mappings
|
|
385
475
|
|
|
386
476
|
def map_batch(self, reads, n_processes: int = 0,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bioforge
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0
|
|
4
4
|
Summary: High-performance bioinformatics engine for Edge Computing — 5-bit encoding, vectorised NumPy core, optional C backend
|
|
5
5
|
Author-email: Aarón Aranda Torrijos <noe9601@gmail.com>
|
|
6
6
|
License: # PolyForm Noncommercial License 1.0.0
|
|
@@ -562,17 +562,26 @@ minimap2-style: minimizer seeding → chaining (C DP) → banded extension.
|
|
|
562
562
|
```python
|
|
563
563
|
from bioforge import GenomeAligner
|
|
564
564
|
|
|
565
|
-
|
|
565
|
+
# Single sequence, or a whole multi-contig genome:
|
|
566
|
+
mapper = GenomeAligner({"chr1": chr1_seq, "chr2": chr2_seq, "plasmid": p_seq})
|
|
566
567
|
|
|
567
568
|
for m in mapper.map(read):
|
|
568
569
|
print(m.to_paf()) # standard PAF, one line per mapping
|
|
569
|
-
|
|
570
|
-
|
|
570
|
+
print(m.target_name, m.strand, m.target_start, f"{m.identity:.1%}")
|
|
571
|
+
|
|
572
|
+
# Map many reads in parallel (uses processes):
|
|
573
|
+
results = mapper.map_batch(reads, n_processes=0) # 0 = all cores
|
|
571
574
|
```
|
|
572
575
|
|
|
573
|
-
Handles
|
|
574
|
-
|
|
575
|
-
|
|
576
|
+
Handles multi-chromosome references (reports the contig + local coordinates),
|
|
577
|
+
both strands, aligns the full read, tolerates mismatches/indels, and reports a
|
|
578
|
+
mapping quality. The minimizer and chaining kernels run in the C engine (with
|
|
579
|
+
NumPy fallbacks).
|
|
580
|
+
|
|
581
|
+
> **Speed, honestly:** indexing is fast, but read mapping is not yet
|
|
582
|
+
> competitive with hand-tuned C mappers like minimap2 — the mapping pipeline is
|
|
583
|
+
> being moved into the C engine. Use BioForge's mapper where its strengths fit:
|
|
584
|
+
> pure-Python/NumPy core, tiny footprint, `pip install` and go, no C toolchain.
|
|
576
585
|
|
|
577
586
|
### Full mutation analysis pipeline (DNA + protein)
|
|
578
587
|
|
|
@@ -146,6 +146,56 @@ def test_map_batch_igual_que_secuencial():
|
|
|
146
146
|
assert [m.target_start for m in got] == [m.target_start for m in exp]
|
|
147
147
|
|
|
148
148
|
|
|
149
|
+
def test_multicontig_mapea_al_contig_correcto():
|
|
150
|
+
rng = np.random.default_rng(30)
|
|
151
|
+
chr1 = "".join("ACGT"[i] for i in rng.integers(0, 4, 40_000))
|
|
152
|
+
chr2 = "".join("ACGT"[i] for i in rng.integers(0, 4, 25_000))
|
|
153
|
+
plas = "".join("ACGT"[i] for i in rng.integers(0, 4, 6_000))
|
|
154
|
+
ga = GenomeAligner({"chr1": chr1, "chr2": chr2, "plasmid": plas}, k=15, w=10)
|
|
155
|
+
assert ga.n_contigs == 3
|
|
156
|
+
|
|
157
|
+
# read de chr2: contig y coords LOCALES correctas
|
|
158
|
+
mp = ga.map(chr2[12_000:12_500])[0]
|
|
159
|
+
assert mp.target_name == "chr2"
|
|
160
|
+
assert mp.target_len == len(chr2)
|
|
161
|
+
assert mp.target_start - mp.query_start == 12_000 # diagonal local
|
|
162
|
+
assert mp.identity > 0.99
|
|
163
|
+
|
|
164
|
+
# read del plasmid en hebra inversa
|
|
165
|
+
mp = ga.map(_revcomp(plas[2_000:2_400]))[0]
|
|
166
|
+
assert mp.target_name == "plasmid"
|
|
167
|
+
assert mp.strand == "-"
|
|
168
|
+
assert mp.target_start < 2_400 and mp.target_end > 0
|
|
169
|
+
|
|
170
|
+
# el PAF lleva el contig correcto sin pasar target_name
|
|
171
|
+
assert ga.map(chr1[5_000:5_500])[0].to_paf().split("\t")[5] == "chr1"
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def test_extension_cubre_el_read_entero():
|
|
175
|
+
# La extensión alinea el read COMPLETO (no solo la región de la cadena).
|
|
176
|
+
genoma = _rng_seq(60_000, 33)
|
|
177
|
+
ga = GenomeAligner(genoma, k=15, w=10)
|
|
178
|
+
o, Lr = 25_000, 500
|
|
179
|
+
mp = ga.map(genoma[o : o + Lr])[0]
|
|
180
|
+
assert mp.query_start == 0 # empieza en el inicio del read…
|
|
181
|
+
assert mp.query_end == Lr # …y llega al final
|
|
182
|
+
assert mp.target_start == o # posición exacta (no + offset de minimizer)
|
|
183
|
+
assert mp.identity > 0.99
|
|
184
|
+
# con mutaciones también cubre el read entero
|
|
185
|
+
read = _mutate(genoma[o : o + 600], n_mut=12, seed_=2)
|
|
186
|
+
mp = ga.map(read)[0]
|
|
187
|
+
assert mp.query_start == 0 and mp.query_end == 600
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def test_multicontig_lista_de_pares():
|
|
191
|
+
# también acepta un iterable de (nombre, secuencia)
|
|
192
|
+
a = _rng_seq(8000, 31)
|
|
193
|
+
b = _rng_seq(8000, 32)
|
|
194
|
+
ga = GenomeAligner([("A", a), ("B", b)], k=15, w=10)
|
|
195
|
+
assert ga.n_contigs == 2
|
|
196
|
+
assert ga.map(b[3000:3400])[0].target_name == "B"
|
|
197
|
+
|
|
198
|
+
|
|
149
199
|
def test_formato_paf():
|
|
150
200
|
genoma = _rng_seq(30_000, 16)
|
|
151
201
|
ga = GenomeAligner(genoma, k=15, w=10)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|