bioforge 3.1.0__tar.gz → 3.2.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.1.0 → bioforge-3.2.0}/PKG-INFO +1 -1
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/__init__.py +1 -1
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/genomemap.py +45 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge.egg-info/PKG-INFO +1 -1
- {bioforge-3.1.0 → bioforge-3.2.0}/tests/test_genomemap.py +17 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/LICENSE +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/README.md +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/aligner.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/analyze.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/bgzf.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/biocore.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/engine/__init__.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/engine/_loader.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/engine/build.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/engine/engine.c +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/engine/engine.dll +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/minimizers.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/qcreport.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/refindex.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge/smart_translator.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge.egg-info/SOURCES.txt +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge.egg-info/dependency_links.txt +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge.egg-info/entry_points.txt +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge.egg-info/requires.txt +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/bioforge.egg-info/top_level.txt +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/pyproject.toml +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/setup.cfg +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/setup.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/tests/test_aligner.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/tests/test_analyze.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/tests/test_bgzf.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/tests/test_biocore.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/tests/test_errors.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/tests/test_minimizers.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/tests/test_qcreport.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/tests/test_refindex.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/tests/test_streaming.py +0 -0
- {bioforge-3.1.0 → bioforge-3.2.0}/tests/test_translator.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bioforge
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.2.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
|
|
@@ -31,6 +31,8 @@ en Python ya es correcto y rápido para el nº de anclas habitual.
|
|
|
31
31
|
|
|
32
32
|
from __future__ import annotations
|
|
33
33
|
|
|
34
|
+
import os
|
|
35
|
+
from multiprocessing import Pool
|
|
34
36
|
from typing import NamedTuple, Optional
|
|
35
37
|
|
|
36
38
|
import numpy as np
|
|
@@ -337,6 +339,21 @@ def _mapq(chains: list[Chain], i: int) -> int:
|
|
|
337
339
|
return int(max(0, min(60, round(60 * (1.0 - ratio)))))
|
|
338
340
|
|
|
339
341
|
|
|
342
|
+
# ── Workers de multiprocessing (a nivel de módulo → picklables) ─────────────────
|
|
343
|
+
_MP_ALIGNER: "Optional[GenomeAligner]" = None
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def _mp_init(aligner: "GenomeAligner") -> None:
|
|
347
|
+
"""Inicializador de cada proceso: guarda el índice (se pasa una vez)."""
|
|
348
|
+
global _MP_ALIGNER
|
|
349
|
+
_MP_ALIGNER = aligner
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _mp_worker(args) -> "list[Mapping]":
|
|
353
|
+
read, min_chain_score, max_hits = args
|
|
354
|
+
return _MP_ALIGNER.map(read, min_chain_score, max_hits)
|
|
355
|
+
|
|
356
|
+
|
|
340
357
|
class GenomeAligner:
|
|
341
358
|
"""Mapeador de reads contra una referencia (seed-chain-align)."""
|
|
342
359
|
|
|
@@ -363,3 +380,31 @@ class GenomeAligner:
|
|
|
363
380
|
if mp is not None:
|
|
364
381
|
mappings.append(mp._replace(mapq=_mapq(chains, i)))
|
|
365
382
|
return mappings
|
|
383
|
+
|
|
384
|
+
def map_batch(self, reads, n_processes: int = 0,
|
|
385
|
+
min_chain_score: float = 40.0,
|
|
386
|
+
max_hits: int = 5) -> list[list[Mapping]]:
|
|
387
|
+
"""Mapea muchos reads en PARALELO → lista de listas de Mapping.
|
|
388
|
+
|
|
389
|
+
Los reads son independientes (paralelismo perfecto). Usa procesos
|
|
390
|
+
(multiprocessing) porque el GIL impide que los hilos escalen: el trabajo
|
|
391
|
+
por read es mayoritariamente Python. El índice se pasa una vez a cada
|
|
392
|
+
proceso; el orden de salida coincide con el de ``reads``.
|
|
393
|
+
|
|
394
|
+
``n_processes``: 0 = todos los núcleos · 1 = secuencial · N = N procesos.
|
|
395
|
+
|
|
396
|
+
Nota (Windows/macOS): el script que lo llame debe estar protegido por
|
|
397
|
+
``if __name__ == "__main__":`` (requisito de multiprocessing). Si el
|
|
398
|
+
arranque de procesos falla, cae a secuencial con gracia.
|
|
399
|
+
"""
|
|
400
|
+
reads = list(reads)
|
|
401
|
+
if n_processes == 1 or len(reads) <= 1:
|
|
402
|
+
return [self.map(r, min_chain_score, max_hits) for r in reads]
|
|
403
|
+
nt = (os.cpu_count() or 1) if n_processes <= 0 else n_processes
|
|
404
|
+
args = [(r, min_chain_score, max_hits) for r in reads]
|
|
405
|
+
chunk = max(1, len(reads) // (nt * 4))
|
|
406
|
+
try:
|
|
407
|
+
with Pool(processes=nt, initializer=_mp_init, initargs=(self,)) as pool:
|
|
408
|
+
return pool.map(_mp_worker, args, chunksize=chunk)
|
|
409
|
+
except Exception: # noqa: BLE001 — fallback secuencial
|
|
410
|
+
return [self.map(r, min_chain_score, max_hits) for r in reads]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bioforge
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.2.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
|
|
@@ -129,6 +129,23 @@ def test_copias_multiples():
|
|
|
129
129
|
|
|
130
130
|
# ── Salida PAF ──────────────────────────────────────────────────────────────────
|
|
131
131
|
|
|
132
|
+
def test_map_batch_igual_que_secuencial():
|
|
133
|
+
genoma = _rng_seq(30_000, 20)
|
|
134
|
+
ga = GenomeAligner(genoma, k=15, w=10)
|
|
135
|
+
reads = [genoma[o : o + 400] for o in (1000, 5000, 12000, 20000)]
|
|
136
|
+
seq = [ga.map(r) for r in reads]
|
|
137
|
+
|
|
138
|
+
# ruta secuencial de la API (n_processes=1)
|
|
139
|
+
b1 = ga.map_batch(reads, n_processes=1)
|
|
140
|
+
assert [len(x) for x in b1] == [len(x) for x in seq]
|
|
141
|
+
|
|
142
|
+
# ruta paralela (procesos): mismo resultado y mismo orden
|
|
143
|
+
b2 = ga.map_batch(reads, n_processes=2)
|
|
144
|
+
assert len(b2) == len(reads)
|
|
145
|
+
for got, exp in zip(b2, seq, strict=True):
|
|
146
|
+
assert [m.target_start for m in got] == [m.target_start for m in exp]
|
|
147
|
+
|
|
148
|
+
|
|
132
149
|
def test_formato_paf():
|
|
133
150
|
genoma = _rng_seq(30_000, 16)
|
|
134
151
|
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
|
|
File without changes
|