2014-02-07 5 views
1

У меня есть двоичный файл с определенным форматом, описанный here для тех, кто заинтересован. Формат не является импортной. Я могу читать и преобразовывать эти данные в форму, которую хочу, но проблема в том, что эти двоичные файлы имеют в них много информации. Если я просто возвращаю байты как прочитанные, это очень быстро (менее 1 секунды), но я не могу ничего использовать с этими байтами, их нужно сначала преобразовать в генотипы, и это код, который, как представляется, замедляя работу.Медленное преобразование двоичных данных

Преобразования для серии байт в генотипы следующего

 h = ['%02x' % ord(b) for b in currBytes] 
     b = ''.join([bin(int(i, 16))[2:].zfill(8)[::-1] for i in h])[:nBits] 
     genotypes = [b[i:i+2] for i in range(0, len(b), 2)] 
     map = {'00': 0, '01': 1, '11': 2, '10': None} 
     return [map[i] for i in genotypes] 

То, что я надеюсь, что есть более быстрый способ сделать это? Есть идеи? Ниже приведены результаты запуска python -m cProfile test.py, где test.py вызывает объект считывателя, который я написал для чтения этих файлов.

vlan1711:src davykavanagh$ python -m cProfile test.py 
183, 593483, 108607389, 366, 368, 46 
that took 93.6410450935 
     86649088 function calls in 96.396 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 1.248 1.248 2.753 2.753 plinkReader.py:13(__init__) 
     1 0.000 0.000 0.000 0.000 plinkReader.py:47(plinkReader) 
     1 0.000 0.000 0.000 0.000 plinkReader.py:48(__init__) 
     1 0.000 0.000 0.000 0.000 plinkReader.py:5(<module>) 
     1 0.000 0.000 0.000 0.000 plinkReader.py:55(__iter__) 
    593484 77.634 0.000 91.477 0.000 plinkReader.py:58(next) 
     1 0.000 0.000 0.000 0.000 plinkReader.py:71(SNP) 
    593483 1.123 0.000 1.504 0.000 plinkReader.py:75(__init__) 
     1 0.000 0.000 0.000 0.000 plinkReader.py:8(plinkFiles) 
     1 0.000 0.000 0.000 0.000 plinkReader.py:85(Person) 
     183 0.000 0.000 0.001 0.000 plinkReader.py:89(__init__) 
     1 2.166 2.166 96.396 96.396 test.py:5(<module>) 
27300218 5.909 0.000 5.909 0.000 {bin} 
    593483 0.080 0.000 0.080 0.000 {len} 
     1 0.000 0.000 0.000 0.000 {math.ceil} 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
     2 0.000 0.000 0.000 0.000 {method 'format' of 'str' objects} 
    593483 0.531 0.000 0.531 0.000 {method 'join' of 'str' objects} 
    593485 0.588 0.000 0.588 0.000 {method 'read' of 'file' objects} 
    593666 0.257 0.000 0.257 0.000 {method 'rsplit' of 'str' objects} 
    593666 0.125 0.000 0.125 0.000 {method 'rstrip' of 'str' objects} 
27300218 4.098 0.000 4.098 0.000 {method 'zfill' of 'str' objects} 
     3 0.000 0.000 0.000 0.000 {open} 
27300218 1.820 0.000 1.820 0.000 {ord} 
    593483 0.817 0.000 0.817 0.000 {range} 
     2 0.000 0.000 0.000 0.000 {time.time} 

ответ

1

Вы замедляете работу, создавая списки и большие строки, которые вам не нужны. Вы просто изучаете биты байтов и конвертируете двухбитовые группы в числа. Это может быть достигнуто гораздо проще, например. г. по этому коду:

def convert(currBytes, nBits): 
    for byte in currBytes: 
    for p in range(4): 
     bits = (ord(byte) >> (p*2)) & 3 
     yield None if bits == 1 else 1 if bits == 2 else 2 if bits == 3 else 0 
     nBits -= 2 
     if nBits <= 0: 
     raise StopIteration() 

В случае, если вам действительно нужно list в конце концов, просто используйте

list(convert(currBytes, nBits)) 

Но я предполагаю, что могут быть случаи, в которых вы просто хотите перебрать результаты:

for blurp in convert(currBytes, nBits): 
    # handle your blurp (0, 1, 2, or None) 
+0

Прохладный. Да, nBits уродлив. Это связано с тем, что мы заранее знаем, сколько пар битов ожидать (так что да, nBits всегда кратно 2), и если это число не кратно 8, то последний байт дополняется дополнительными нулями. –

+1

Я работаю над дальнейшей урезанной версией, которая вообще не включает преобразование строк. В конце концов вы просто используете биты. Это можно сделать лучше. Подожди. – Alfe

+1

Хорошо, посмотрите на мой новый ответ. Это лучше, чем старый. И я думаю, что это значительно ускорит ваши вещи, в зависимости от размера ввода. В худшем случае я получил sth как ускоряющий фактор 100. – Alfe

Смежные вопросы