Domanda

Ho un formato di file (formato FASTQ) che codifica una stringa di numeri interi come una stringa in cui ogni numero intero è rappresentato da un codice ASCII con un offset. Purtroppo, ci sono due codifiche di uso comune, uno con un offset di 33 e l'altro con un offset di 64. Io in genere hanno diversi 100 milioni di stringhe di lunghezza 80-150 per convertire da una compensazione all'altro. Il codice più semplice che ho potuto venire con per fare questo tipo di cose è:

def phred64ToStdqual(qualin):
    return(''.join([chr(ord(x)-31) for x in qualin]))

Questo funziona bene, ma non è particolarmente veloce. Per 1 milione di corde, ci vogliono circa 4 secondi sulla mia macchina. Se cambio di utilizzare un paio di dicts a fare la traduzione, posso ottenere questo fino a circa 2 secondi.

ctoi = {}
itoc = {}
for i in xrange(127):
    itoc[i]=chr(i)
    ctoi[chr(i)]=i

def phred64ToStdqual2(qualin):
    return(''.join([itoc[ctoi[x]-31] for x in qualin]))

Se io alla cieca corro sotto Cython, ho capito fino a poco meno di 1 secondo.
Sembra che a livello di C, questo è semplicemente un cast a int, sottrarre, e poi gettato a char. Non ho scritto questo, ma sto cercando di indovinare che è un po 'più veloce. Eventuali suggerimenti tra cui come codice migliore di questo in Python o anche una versione Cython per fare questo sarebbe molto utile.

Grazie,

Sean

È stato utile?

Soluzione

Se si guarda il codice per urllib.quote, c'è qualcosa che è simile a quello che stai facendo. Sembra che:

_map = {}
def phred64ToStdqual2(qualin):
    if not _map:
        for i in range(31, 127):
            _map[chr(i)] = chr(i - 31)
    return ''.join(map(_map.__getitem__, qualin))

Si noti che la funzione di cui sopra funziona nel caso in cui le mappature non sono la stessa lunghezza (in urllib.quote, si deve prendere '%' -.> '% 25'

Ma in realtà, dal momento che ogni traduzione è la stessa lunghezza, Python ha una funzione che fa proprio questo molto rapidamente: maketrans e tradurre . Probabilmente non sarà possibile ottenere molto più veloce di:

import string
_trans = None
def phred64ToStdqual4(qualin):
    global _trans
    if not _trans:
        _trans = string.maketrans(''.join(chr(i) for i in range(31, 127)), ''.join(chr(i) for i in range(127 - 31)))
    return qualin.translate(_trans)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top