Учебная страница курса биоинформатики,
год поступления 2013
Подсказки и советы к практикуму 7
Задание 2. Скрипт, читающий fasta-файл с несколькими последовательностями
Ваш скрипт должен состоять из следующих смысловых частей. Советую выделить их в тексте скрипта как-нибудь, как минимум разделяющими их пустыми строками, а еще лучше - строками-комментариями.
При работе над скриптом очень полезно писать смысловые части по очереди и проверять, правильно ли они работают. Не старайтесь сперва написать все, а потом запустить: это можно делать только тогда, когда Вы очень уверены в своих силах!
2.1. Задайте класс, который будет описывать белки
Выберите ему подходящее название (например, Protein).
- Создайте три атрибута класса. Обдумайте имена атрибутов и этого класса: они должны быть лаконичными, но отражающими назначение переменной или функции. Например:
идентификатор – id_RefSeq;
описание – description;
последовательность – sequence.
Добавьте к классу пустой инициализирующий метод __init__(self), т.е. в теле метода не пишите никаких команд, вместо этого напишите, допустим, 5 + 3 или 0. Совсем пустым метод оставить нельзя, будут ошибки О том, что это за метод, можно почитать подробнее в справочной информации. Мы еще вернемся к нему чуть позже.
Добавьте к классу метод, печатающего информацию в формате fasta с заданным числом букв в строке последовательности. Например, можно назвать его print_fasta. Если Вы уже сделали задание практикума 6, то по сути реализация этого метода у Вас уже есть! Если нет, ничего страшного: напишите его сейчас. Та функция, напомню, должна была принимать 4 аргумента (идентификатор, описание, последовательности и количество символов), а этот метод сможет обойтись двумя: вызвавшим его объектом (self), через который он сможет обратиться к идентификатору, описанию и последовательности, и, собственно, желаемым числом букв.
2.2. Протестируйте заданный класс
Попробуйте создать экземпляр класса: напишите, например, a = Protein().
Вручную задайте атрибуты этого белка. Задавать их можно точно так же, как обычные переменные; только имя переменной-атрибута сложное и состоит из имени экземпляра класса, которому принадлежит эта переменная, точки и названия атрибута. Например, чтобы задать описание только что созданного объекта a, можно написать: a.description = "hypothetical protein. Попробуйте сделать то же самое для других атрибутов!
Вызовите атрибуты объекта a на печать по очереди с помощью обычной команды print. Опять-таки, атрибут объекта a – то же самое, что обычная переменная, только имя у нее сложное. Проверьте, что все работает.
Вызовите у объекта a метод print_fasta(), подав ей на вход ОДИН аргумент – нужное число букв в строке последовательности. Заметьте, что при задании функции Вы прописывали ей 2 аргумента, первый с именем self, а второй как раз нужное число букв. В этом разделе справки можно прочитать подробнее про это.
2.3. Задание инициализирующего метода __init__()
Пришло время сделать так, чтобы при создании экземпляра класса можно было сразу же передать нужные значения атрибутов, а не выписывать их отдельными тремя командами.
При создании экземпляра класса, например a = Protein(), Вы реально вызываете метод (на что указывают круглые скобки), и этот метод на самом деле и есть этот __init__(). Можете считать, что при создании экземпляра класса его неприятное название заменяется на более удобное.
Чтобы можно было прямо этому методу подать на вход, например, 3 строчки (по количеству атрибутов класса, которые надо присвоить), нужно при его определении добавить к аргументу self еще 3 аргумента. Например, пусть они будут обозначены i (сокращение от id), d (сокращение от description) и s (сокращение от sequence).
В теле метода нам надо присвоить соответствующим атрибутам объекта self остальные поданные методу аргументы. Например, имя переменной-идентификатора нового объекта будет self.id_RefSeq, и ей можно присвоить значение аргумента i.
Пропишите три команды, присваивающие атрибутам объекта self (то есть реально – как раз создающегося нового объекта) значения переменных, поданных на вход.
- Обязательно проверьте, что все работает; вернитесь к пункту 2.2, но теперь создание нового экземпляра вместе с присвоением ему всех атрибутов должно занимать всего одну строчку, например такую:
a = Protein("YP_0000001", "hypothetical protein", "MDRFTDFGAAAAAA"
- Проверьте, что переменные правильно присваиваются. Создайте несколько элементов класса.
2.4. Алгоритм чтения файла
Совет:: используйте в этом алгоритме свои наработки, полученные в предыдущем практикуме. Если какое-то из заданий того практикума выполнить не удалось, подумайте, каким образом с помощью циклов, условий и функций строк и списков можно реализовать две вещи:
- разбирать строку с "шапкой" последовательности, на две переменные: идентификатор и описание.
добавлять к некоторой заданной вне цикла переменной sequence все строчки последовательности, из которых удаляются символы конца строки.
После этого можете изучить алгоритм:
Откройте fasta-файл с несколькими последовательностями для чтения (см. в справочной информации, как это сделать).
- Создайте вне цикла переменную-список, куда будут складываться последовательности по мере прочтения
Создайте вне цикла три переменные, которые я условно буду называть далее переменными-контейнерами. В них будет храниться прочитанная информация об идентификаторе и описании до тех пор, пока соответствующая ей последовательность не будет прочитана до конца и не придет время сохранить их в конкретном экземпляре класса Protein.
Проходите по строчкам файла в цикле for и у каждой строки отрезайте символ конца строки. Далее возможно 3 варианта:
- Длина строчки равна 0: значит, ее надо пропустить, перейдя на следующий виток цикла;
Первый символ строчки – это >. В прошлом практикуме Вы могли опознать эту строчку по номеру, но теперь таких строчек будет несколько, и их номера Вы наперед не знаете. Поэтому имеет смысл проверять именно первый символ. Есть 2 варианта:
- Если речь идет о первой строке, то есть никакая последовательность аминокислот еще не читалась, то нам нужно просто разобрать эту строку так, как Вы уже делали в прошлом практикуме, и записать во временные переменные идентификатор и описание.
А вот если мы сейчас уже натолкнулись на второй (или третий, и т.п.) белок, то это значит, что в этот момент переменные-контейнеры заполнены информацией о предыдущем белке! Если мы будем действовать так же, как и раньше, мы перезапишем их новой информацией, а предыдущая потеряется. Поэтому нужно в этот момент создать новый объект класса Protein, подав на вход его инициализирующей функции значения из переменных-контейнеров, а потом добавить этот объект добавить в ранее созданный список. Также надо не забыть "опустошить" эти переменные, например присвоить им значения "".
Первый символ строчки – не >. Это значит, что в этой строчке содержится последовательность белка, и надо дописать ее к переменной-контейнеру с последовательностью.
Когда цикл завершится, в переменных-контейнерах будет храниться информация о самом последнем белке, который был прочитан, но не был записан в список (ведь записываем мы в этом алгоритме только наткнувшись на символ > следующего белка). Поэтому после цикла нужно будет сделать это (создать новый объект класса Protein и добавить его в список) вручную.
2.5. Проверьте, что алгоритм чтения файла работает
Для проверки в тех местах, где у Вас создается новый объект класса Protein, заставьте скрипт выводить на экран командой print значения переменных-контейнеров. Убедитесь, что эти значения - именно то, что должно в них содержаться.
Если что-то не работает, пройдитесь по своему алгоритму еще раз, сверяя его с описанным выше. Проверьте внимательно уровни вложенности условий внутри цикла! Об отступах и уровнях вложенности можно подробнее прочитать разъяснение тут.
Если Вы все сделали верно – Вы получили список из четырех элементов класса Protein.
- Проверьте длину списка, распечатайте на пробу идентификатор, описание и последовательность какого-то одного из них.
2.6. Финальная проверка работы скрипта и распечатка информации в формате fasta
- Если все работает, напишите цикл, который будет проходить по списку белков и вызывать у каждого его элемента метод класса, печатающий информацию в формате fasta на экран.
В качестве контрольной проверки работоспособности скрипта сохраните результат его работы в файл с помощью оператора перенаправления потока STDOUT – > (см. подсказки к практикуму 5). Если все верно, это должен быть файл в формате fasta; попробуйте запустить скрипт еще раз, подав ему в качестве аргумента этот файл: все должно работать.
Задание 3. Обработка информации из командной строки
В этой части вам надо импортировать модуль sys и проверить, сколько элементов в его списке argv, которое хранит информацию о поданных скрипту аргументах.
Для более подробной информации обращайтесь к соответствующему разделу справочной информации.
Если скрипту для работы нужно получить какие-то параметры из командной строки, он должен уметь попросить их задать. Например, если пользователь запустит его вовсе без параметров – скрипт должен деликатно напомнить, какие параметры ему требуются и завершить работу. Если этого не сделать, скрипт все равно завершит работу, но с ошибкой, а так Вы покажете, что "все под контролем". Впоследствии, когда Вы будете учиться программировать на Python всерьез, Вам нужно будет всегда следить за такими вещами, причем делать это не только "вручную", но и с помощью специальных средств.
Не забудьте, что число, поданное на вход скрипту, будет сохранено в списке sys.argv как текст, поэтому нужно привести его к типу int.