У меня есть относительно простая проблема: учитывая положение в геноме, верните имя гена в этот момент.cython: уменьшает размер класса, уменьшает использование памяти, улучшает скорость
Путь, я решить эту проблему прямо сейчас, используя следующий класс в Cython ::
class BedFile():
""" A Lookup Object """
def __init__(self, bedfile):
self.dict = {}
cdef int start, end
with open(bedfile) as infile:
for line in infile:
f = line.rstrip().split('\t')
if len(f) < 4:
continue
chr = f[0]
start = int(f[1])
end = int(f[2])
gene = f[3]
if chr not in self.dict:
self.dict[chr] = {}
self.dict[chr][gene] = (start, end)
def lookup(self, chromosome, location):
""" Lookup your gene. Returns the gene name """
cdef int l
l = int(location)
answer = ''
for k, v in self.dict[chromosome].items():
if v[0] < l < v[1]:
answer = k
break
if answer:
return answer
else:
return None
Полный проект находится здесь: https://github.com/MikeDacre/python_bed_lookup, хотя весь соответствующий класс выше.
Проблема с кодом как есть в том, что полученный класс/словарь занимает очень большой объем памяти для генома человека, с 110 миллионами генов (это текстовый файл длиной 110 миллионов строк). Я убил функцию init в процессе построения словаря примерно через две минуты, когда он достиг 16 ГБ памяти. Все, что использует большую память, в основном бесполезно.
Я уверен, что мне нужно более эффективный способ сделать это, но я не программист на C, и я очень новичок в cython. Я предполагаю, что я мог бы построить чистую C-структуру какого-либо типа, чтобы сохранить имя гена и начальные и конечные значения. Затем я мог преобразовать lookup() в функцию, которая вызывает другую функцию cdef, называемую _lookup(), и использовать эту функцию cdef для выполнения этого фактического запроса.
В идеальном мире вся структура может жить в памяти и занимать менее 2 ГБ памяти для ~ 2 000 000 записей (каждая запись с двумя целыми и строками).
Edit: я понял, как сделать это эффективно с SQLite для больших файлов, чтобы увидеть полный код с SQLite смотрите здесь: https://github.com/MikeDacre/python_bed_lookup
Однако, я все еще думаю, что выше класс может быть оптимизирован с Cython чтобы сделать словарь меньше в памяти и быстрее искать, любые предложения оценены.
Спасибо!
не Поможет в памяти, но в defaultdict и Csv Lib, несомненно, будет более эффективный –
Это звучит как проблема с данными, а не проблема с кодом. –
@Padraic Cunningham Спасибо, я не знал о defaultdict, хорошо знать. Однако проблема с памятью является главной. Я думаю, что могу сделать это, используя sqlite вместо хранения объекта в памяти, но мне все же интересно, есть ли эффективный подход C-структуры, который был бы более эффективным, чем то, что я здесь сделал. –