2010-09-27 16 views
6

Ho un formato file (formato fastq) che codifica una stringa di interi come stringa in cui ogni intero è rappresentato da un codice ASCII con un offset. Sfortunatamente, ci sono due codifiche di uso comune, una con un offset di 33 e l'altra con un offset di 64. In genere ho diverse 100 milioni di stringhe di lunghezza 80-150 per convertire da un offset all'altro. Il codice più semplice che ho potuto venire con per fare questo tipo di cose è:Converti codifica ascii in int e viceversa in python (rapidamente)

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 l'uso di un paio di dicts per fare la traduzione, posso ridurlo 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 ciecamente corro sotto Cython, ho capito fino a poco meno di 1 secondo.
Sembra al livello C, questo è semplicemente un cast per int, sottrarre e quindi eseguire il cast in char. Non ho scritto questo, ma suppongo che sia un po 'più veloce. Qualche suggerimento, incluso come migliorare il codice in questo in Python o anche in una versione cython, sarebbe abbastanza utile.

Grazie,

Sean

+0

Provare a sostituire '[]' con '() 'usare i generatori piuttosto che creare e scartare gli elenchi. Dubito che farà un enorme differenza, ma dovrebbe fare qualcosa. – RichieHindle

+0

Sostituendo [] con(), i() sono ridondanti con qualsiasi python recente – pixelbeat

+0

Ottima idea, ma il join di stringhe ha bisogno di un elenco, credo, in modo che non funzioni direttamente Non credo. – seandavi

risposta

4

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)) 

Nota che la funzione precedente 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 translate 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) 
+0

Grazie, Mike. Questo è un veloce lampo di 0,1 secondi sulla stessa macchina di cui sopra e sarà abbastanza veloce per i miei scopi. Rimarrò con phred64ToStdqual4() come elencato sopra .... – seandavi