Найти - Пользователи
Полная версия: Не могу найти ошибку
Начало » Python для новичков » Не могу найти ошибку
1 2
Kustodiev_17
Здравствуйте.
Обучаюсь на on-line-курсе биоинформатики.
Задача следующая:
Frequent Words with Mismatches Problem: Find the most frequent k-mers with mismatches in a string.
Input: A string Text as well as integers k and d. (You may assume k ≤ 12 and d ≤ 3.)
Дано: Текст генома, целые k и d.

Output: All most frequent k-mers with up to d mismatches in Text.
Необходимо найти: Все самые распространённые k-мерные Куски(Образцы) в Тексте,
допускается не более d несовпадений.
———————
Моя программа:

""" Алгоритм решения (версия 2): Идём по Тексту и рубим Куски длиной k. Формируем Хэш-Словарь.
    Ключ - это числовой(бинарный) эквивалент Куска. Величина - это список. 
    По индексу 0 там собственно строка-Кусок, по индексу 1 там список позиций
    вхождения Куска в Текст с допускаемыми d вариациями.
    
    Создаём список, содержащий под-списки. По индексу 0 в под-списке строка. Под-списков
    столько, что они охватывают по одному экземпляру все возможные варианты строк длиной k.
    По индексу 1 в под-списке будет под-под-список позиций.
    
    Затем обрабатывается уже этот словарь - ищется самый длинный список-Величина,
    или списки с равным максимальным количеством вхождений. Выводим на печать
    строки по индексу 0 в этих списках - это и будет ответ.
"""
TEXT_STRING = "ACGTTGCATGTCGCATGATGCATGAGAGCT"
""" Геномный Текст для поиска.  """
TEXT_STRING_LENGTH = len(TEXT_STRING)
""" Длина Текста.  """
PATTERN_STRING_LENGTH = 4
""" Длина Образца, то есть k-размерность.  """
VALUE_OF_VARIABILITY = 1
""" Допустимое значение Изменчивости при поиске.   """
primary_hash_dictionary = {}
""" Наш Хэш-Словарь """
exit_list = []
""" Список для выходных данных  """
# all_variants_k_mer_list = []
four_digit = []
def main_function_for_k_mer_text_and_mismatch(some_text):
    global primary_hash_dictionary, help_list_for_primary_hash_dictionary_processing
    for i in range(0, (TEXT_STRING_LENGTH - PATTERN_STRING_LENGTH + 1)):
        pattern_some = some_text[i : PATTERN_STRING_LENGTH + i]
        converted_some = ""
        key_some = 0
        for f in range(PATTERN_STRING_LENGTH):
            if pattern_some[f] == "A":
                converted_some += "00"
            elif pattern_some[f] == "C":
                converted_some += "01"
            elif pattern_some[f] == "G":
                converted_some += "10"
            elif pattern_some[f] == "T":
                converted_some += "11"
        """ Преобразовываем строку текущего Куска в "бинарный" Ключ Хэш-Словаря. """
        converted_some = "0b" + converted_some
        key_some = int(converted_some, 2)
        """ Если в словаре уже есть такой Ключ, то только добавляем новое значение
        позиции в список позиций. Если такого Ключа нет, то делаем первичное
        заполнение Хэш-Словаря. """
        if primary_hash_dictionary.has_key(key_some):
            temp_list_1 = primary_hash_dictionary[key_some]
            temp_list_2 = temp_list_1[1]
            temp_list_2.append(i)
            temp_list_1[1] = temp_list_2
            primary_hash_dictionary[key_some] = temp_list_1
        else:
            primary_hash_dictionary[key_some] = [pattern_some, [i]]
""" Теперь создаём список all_variants_k_mer_list с под-списками (а в них 
    под-под-списки).  Так как алфавит генома всего 4 символа, то мы
    создаём список four_digit содержащий в соответствующей позиции
    степень четвёрки. Потом каждое генерируемое число total_index
    мы разлагаем на степени 4 по модулю и в каждый разряд записываем
    соответственно символы A - там где 0, C - там где разряд при
    делении показал 1, G - 2, и T - 3. """
    
def all_variants_k_mer_list_function_creating_and_now_processing():
    # global all_variants_k_mer_list
    global four_digit
    global primary_hash_dictionary, exit_list
    max_number_of_position = 1
    for digit_fours in range(PATTERN_STRING_LENGTH):
        four_digit.append(4 ** digit_fours)
    # print four_digit
    for total_index in range(PATTERN_STRING_LENGTH ** 4):
        some_string = ""
        for digit_in_string in range(PATTERN_STRING_LENGTH - 1, -1, -1):
            quasi_digit = total_index // (four_digit[digit_in_string])
            total_index = total_index % (four_digit[digit_in_string])
            if quasi_digit == 0:
                digit_symbol = "A"
                some_string = some_string + digit_symbol
            elif quasi_digit == 1:
                digit_symbol = "C"
                some_string = some_string + digit_symbol
            elif quasi_digit == 2:
                digit_symbol = "G"
                some_string = some_string + digit_symbol
            elif quasi_digit == 3:
                digit_symbol = "T"
                some_string = some_string + digit_symbol
        temp_list_1 = []
        # print some_string
        for key in primary_hash_dictionary:
            temp_list_2 = primary_hash_dictionary[key]
            pattern_some = temp_list_2[0]
            position_list_2 = temp_list_2[1]
            # print "pattern_some = ", pattern_some, "", position_list_2
            index_of_pattern_some = 0
            for m in range(PATTERN_STRING_LENGTH):
                if some_string[m] != pattern_some[m]:
                    index_of_pattern_some += 1
                    if index_of_pattern_some == (VALUE_OF_VARIABILITY + 1):
                        break
            if index_of_pattern_some <= VALUE_OF_VARIABILITY:
                temp_list_1 = temp_list_1 + position_list_2
        # print temp_list_1
        # print ""
        if len(temp_list_1) == max_number_of_position:
            exit_list.append(some_string)
        elif len(temp_list_1) > max_number_of_position:
            max_number_of_position = len(temp_list_1)
            exit_list = [some_string]
        # all_variants_k_mer_list.append([some_string, temp_list_1])
    print ""
    print " ".join(exit_list)
    print max_number_of_position
    
main_function_for_k_mer_text_and_mismatch(TEXT_STRING)
all_variants_k_mer_list_function_creating_and_now_processing()
—————————
Мои проблемы:
1) Программа даёт верные ответы для части тестовых данных, когда длина Куска 4-5 нуклеотидов, а вариабильность = 1, но даёт неверные ответы, когда Куска 9-10 нуклеотидов, Текст (генома) 500-600
нуклеотидов и вариабильность 2-3. Причём если изменить генерацию всех возможных вариантов Образцов длины k на:
some_string = ""
        for digit_in_string in range(PATTERN_STRING_LENGTH - 1, -1, -1):
            quasi_digit = total_index // (four_digit[digit_in_string])
            total_index = total_index % (four_digit[digit_in_string])
            if quasi_digit == 0:
                digit_symbol = "A"
                some_string =  digit_symbol + some_string
            elif quasi_digit == 1:
                digit_symbol = "C"
                some_string = digit_symbol + some_string
            elif quasi_digit == 2:
                digit_symbol = "G"
                some_string = digit_symbol + some_string
            elif quasi_digit == 3:
                digit_symbol = "T"
                some_string = digit_symbol + some_string
То верные ответы остаются верными, а вот неверные ответы изменяются (правда остаются неверными всё равно).
2) Программированием занялся совсем недавно и полный новичок. Работаю c программой Python(x,y)
Там есть отладочный модуль. Если у кого-то опыт работы с тамошним отладчиком? Или подскажите ресурсы (желательно на русском языке - форумы, книги, статьи)
Singularity
А где это такие курсы есть?
Kustodiev_17
Здравствуйте, Singularity.

Есть на Курсере: https://www.coursera.org/
Kustodiev_17
Коллеги, прошу меня простить - ошибка возникала из-за моей невнимательности - и все данные для ея поиска у меня имелись. Дело в том, что в цикле:

for total_index in range(PATTERN_STRING_LENGTH ** 4):

мной не правильно был внесён параметр (описка), правильный вариант:

for total_index in range(4 ** PATTERN_STRING_LENGTH):

(Поэтому-то на маленьких данных всё работало, ну и совпадение было,
PATTERN_STRING_LENGTH равнялось четырём).

После данного исправления программа выдаёт правильный ответ. Однако задание не выполнено,
так как на курсе условие - на всё про всё даётся 5 минут (надо успеть скачать новые данные, а
размер их больше, чем тестовые). При PATTERN_STRING_LENGTH = 10 и VALUE_OF_VARIABILITY = 2
(Текст генома примерно 500-600 символов) программа считает 22 минуты 40 секунд. Так, что буду
работать над алгоритмом. Впрочем я уже сталкивался с такой ситуацией - обсчёт генома бактерии
из (примерно) 4 600 000 нуклеотидов занимал в моей версии 10 часов. После двух недель думания
и чтения литературы по теории алгоритмов версия программы обсчитала весь геном за 39 секунд.

Всем удачи.
Kustodiev_17
Здравствуйте.
Последняя часть моего последнего поста была, пожалуй, слишком оптимистичной. “Усушил” код исходя из своих новичковских представлений, а он выполняется за такое же время. Да, и работаю я сейчас на копьютере-ветеране: для сравнения запустил программму, которая работала с геномом бактерии - получилось, что нынешний мой комп в два раза медленнее (сработал за 01 минуту и 09 секунд вместо 39 секунд).
Мои мысли:
1) У Лутца “Изучаем Питон” указана инфа про ускорители типа Psyco и транслятор Shedskin - однако у меня нет опыта работы с этим хозяйством. Как подступиться и насколько это быстро даст результаты (время освоения и применения - хотелось бы в течение недели уложиться).
2) Скорее всего узкое место моей программы - генерация всех возможных строк от “AAA…AA” до “TT….TTT” - если у кого есть опыт как это сделать с меньшими временнЫми затратами - буду признателен и буду за вас молится всем компьютерным БогАм как минимум до 01.01.2015.
По поводу “узкого места” у меня есть такой план “реализации своими силами” - сгенерить заранее файлы (три штуки) со строками в вариантах длины 8, 9 и 10 символов (это то, что в моей программе величина PATTERN_STRING_LENGTH). И в зависимости от полученного задания программа будет целиком считывать весь объём данных без генерации, обращаясь к соответствующему файлу, либо, если PATTERN_STRING_LENGTH < 8, то генерить напрямую.
В самом худшем случае, который пока встречается PATTERN_STRING_LENGTH = 10, то есть всех возможных комбинаций 4 ** 10 = 2 ** 20 = (2 ** 10) ** 2 = (1024) ** 2 примерно 1 000 000 или 10 ** 6. Соответственно размер файла со строками = (примерно) 10М. Мой ветеран возможно будет переваривать столько же (буду пробовать в любом случае, так как нужен опыт по работе с файлами - пока он минимален - бактериальный геном считывать получается, а вот поиск/запись, тем более структурированная - пока мне не известна).

Всем удачи.
sergeek
Kustodiev_17
генерация всех возможных строк от “AAA…AA” до “TT….TTT”
In [19]: from itertools import product
In [20]: for c in product('ACGT',repeat=2):
    ...:     print(''.join(c))
    ...:     
AA
AC
AG
AT
CA
CC
CG
CT
GA
GC
GG
GT
TA
TC
TG
TT
так?
Kustodiev_17
у меня есть такой план …
не надо так медленней будет
Kustodiev_17
Да, нужно именно получать строки заданной длинны (теоретически до 12 символов, а практически до 10 символов). То есть, если PATTERN_STRING_LENGTH = 9, то по моему алгоритму нужно получить все строки -
AAAAAAAAA
AAAAAAAAC
AAAAAAAAG
AAAAAAAAT
AAAAAAACA
AAAAAAACC
……
TTTTTTTTG
TTTTTTTTT

К моему сожалению синтаксис
In [20]:
и
product('ACGT',repeat=2)
мне не знаком. Что это за модуль itertools/product? Хотелось бы по-подробнее, если вас не затруднит, sergeek

Обновление: Инфу по itertools нашёл (http://docs.python.org/2/library/itertools.html), единственное не понял пока как эти все значения присваивать строковой переменной (мне на печать вывод без надобности).
sergeek
Kustodiev_17
In [20]:
это приглашение к вводу в ipython, тоже самое что
>>>
Kustodiev_17
product('ACGT',repeat=2)
это функция из модуля itertools - считает декартово произведение, в параметр len вводится число ваших символов, например для 12
from itertools import product
for c in product('ACGT',repeat=12):
    print(''.join(c))


Kustodiev_17
Спасибо, sergeek. Сейчас осваиваю новый материал. Думаю, что вопросов быть не должно. Благодарю ещё раз.
sergeek
Kustodiev_17
единственное не понял пока как эти все значения присваивать строковой переменной (мне на печать вывод без надобности).
я привел пример с выводом для лучшего понимания
присваивавается она так же как и другие

from itertools import product
for c in product('ACGT',repeat=12):
    var = ''.join(c)

по вашему коду мне показалось что вы поймете о чем я пишу
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB