Suurin osa toistaiseksi lähetetyistä ratkaisuista ovat joko hitaita tai voivat tuottaa vääriä tuloksia joissakin tapauksissa. (En ole testannut Picardia, jonka uskon toimivan tarkoitetulla tavalla. Mutta henkilökohtaisesti minulla on taipumus vetäytyä, kun minun on perustettava JVM!)
Lähestymme ongelmaa eri näkökulmasta:
Hyvillä hash-funktioilla on ~ O (1) monimutkaisuus hakua varten. Jos voimme luoda QNAME-tiedostoistamme hash-taulukon, BAM-tiedoston etsimisen tulisi olla O (n) tietueiden määrässä. Python-kehittäjät ovat erittäin ylpeitä haspy-toiminnosta cpythonissa, joten käytämme sitä:
#! / Usr / bin / env python3import syswith open (sys.argv [1], 'r') ) hakemistotiedostona: ids = set (l.rstrip ('\ r \ n') l: lle hakemistotiedostossa) riville sys.stdin: qname, _ = line.split ('\ t', 1) jos qname tunnuksissa : sys.stdout.write (rivi)
Testisarjalla, joka koostuu ~ 3 Gt: n BAM-tiedostosta ja qnames.txt
-kohdasta, jossa on ~ 65K merkintää, käynnissä samtools-näkymä input.bam | ./idfilter.py qnames.txt vie testipalvelimellani noin 6,5 sekuntia . Vertailun vuoksi SAM: n piippaaminen fgrep -f qnames.txt
-palveluun (käyttäen GNU grep -ohjelmaa) kestää noin 8,5 sekuntia (mutta saattaa tuottaa vääriä tuloksia).
(Miksi grep
tuottaa väärät tulokset? Jos qnames.txt
-kentässäsi on QNAME foo
, mutta BAM-tiedostosi sisältää myös fooX
ja fooY
, ne kaikki vastaavat fgrep
. Ratkaisu on ankkuroida kaikki hakumallisi rivin alkuun ja välilehteen, esim. ^ foo \ t
, mutta sitten sinun on käytettävä tavallista grep
, jonka on rakennettava NFA jokaiselle mallille, eikä fgrep
, joka toteuttaa Aho-Corasickia, ja olet suuruusluokkaa hitaampi.)
Olen kirjoittanut pienen Python-komentosarjoni uudelleen Rustiin käyttämällä std :: collections :: HashMap
hash-funktiota varten ja käyttämällä rust_htslib-laatikkoa lukemaan ja kirjoittamaan suoraan BAM: sta, ja tämä on enemmän yli kaksi kertaa nopeammin kuin Python, vaikka BAM-tiedostoa luettaisiin ja kirjoitettaisiin. Rustini ei kuitenkaan todellakaan sovi julkiseen kulutukseen ...