Skip to content

Review CEP170B#40

Open
nvaulin wants to merge 1 commit intomainfrom
CEP170B
Open

Review CEP170B#40
nvaulin wants to merge 1 commit intomainfrom
CEP170B

Conversation

@nvaulin
Copy link
Copy Markdown
Member

@nvaulin nvaulin commented Feb 26, 2024

Review CEP170B

Copy link
Copy Markdown

@zmitserbio zmitserbio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В целом, работа оставляет положительное впечатление. Код читабельный, в основном рабочий.
Однако есть проблема с нереализованностью функционала, и в будущем имеет смысл использовать линтер.

Comment thread CEP170B.py
from abc import ABC, abstractmethod
from Bio import SeqIO
from Bio.SeqUtils import gc_fraction
from typing import Tuple
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Насколько мне известно, после python 3.9 не рекомендуется использовать Tuple, хотя работе кода это не мешает.

Comment thread CEP170B.py
Comment on lines +8 to +11
def filter_fastq(input_path: str,
output_filename: str = None,
gc_bounds: Tuple[int, int] = (0, 100),
length_bounds: Tuple[int, int] = (0, 2**32),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Есть некоторое нарушение pep8: не следует оставлять пробелы на концах строк.

Comment thread CEP170B.py
quality_threshold: int = 0) -> None:
'''
Filter FASTQ-sequences based on entered requirements.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Следует убрать \t.

Comment thread CEP170B.py
Comment on lines +16 to +30
Arguments:
- input_path (str): path to the file with FASTQ-sequences
- output_filename (str): name of the output file with
filtered FASTQ-sequences
- gc_bounds (tuple or int, default = (0, 100)): GC-content
interval (percentage) for filtering. Tuple if contains
lower and upper bounds, int if only contains an upper bound.
- length_bounds (tuple or int, default = (0, 2**32)): length
interval for filtering. Tuple if contains lower and upper
bounds, int if only contains an upper bound.
- quality_threshold (int, default = 0): threshold value of average
read quality for filtering.

Note: the output file is saved to the /fastq_filtrator_results
directory. The default output file name is the name of the input file.
Copy link
Copy Markdown

@zmitserbio zmitserbio Mar 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В некоторых строках имеются пробелы на концах.
Гораздо более существенно то, что функция не соответствует заявленному функционалу. Если подать int аргументам gc_bounds и length_bounds, то падает с ошибкой, т.к. не реализован перевод этого int в соответствующий tuple. Это можно было реализовать, например, так:

if isinstance(gc_bounds, int):
    gc_bounds = tuple([0, gc_bounds])
if isinstance(length_bounds, int):
    length_bounds = tuple([0, length_bounds])

Возможно, в будущем имеет смысл писать себе pass или комментарии, чтобы не забывать.

Comment thread CEP170B.py
records = [record for record in SeqIO.parse(handle, "fastq")]

filtered_records = []
for record in records:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь была возможность использовать SeqIO:

Suggested change
for record in records:
for i, record in enumerate(SeqIO.parse(input_path, "fastq")):

Comment thread CEP170B.py
print(f"Filtered sequences saved to {output_path}")


class BiologicalSequence(ABC):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Насколько мне известно, классы более принято располагать перед функциями.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Все так

Comment thread CEP170B.py


class BiologicalSequence(ABC):
def __init__(self, seq: str = None):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Хотя это и не запрещено, в лекции/консультации упоминалось, что лучше не писать код в абстрактном классе.

Comment thread CEP170B.py
return self.seq

def check_alphabet(self):
return set(self.seq.upper()).issubset(self.ALPHABET)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Считаю это достаточно изящным решением.

Comment thread CEP170B.py
def __repr__(self):
return self.seq

def check_alphabet(self):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я думаю, что проверять алфавит разумно было бы в init в обязательном порядке.

Comment thread CEP170B.py
Comment on lines +121 to +122
ALPHABET = {"A", "C", "D", "E", "F", "G", "H", "I","K", "L",
"M", "N","P", "Q", "R", "S", "T", "V", "W", "Y"}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ALPHABET = {"A", "C", "D", "E", "F", "G", "H", "I","K", "L",
"M", "N","P", "Q", "R", "S", "T", "V", "W", "Y"}
ALPHABET = {"A", "C", "D", "E", "F", "G", "H", "I", "K", "L",
"M", "N", "P", "Q", "R", "S", "T", "V", "W", "Y"}

Стоит добавить пробелы. Помимо этого, есть еще некоторое количество пробелов на концах строк и \t в пустых строках, но я полагаю, не имеет смысла на каждом останавливаться. Стоит проверять код линтером, так можно выявить те огрехи, которые невооруженному глазу плохо заметны.

Copy link
Copy Markdown

@anisssum anisssum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Особенно хорошо, что вы использовали абстрактные классы и соблюдали принципы ООП. Ваш код довольно лаконичен и легко читаем, что является плюсом.
В целом, код отлично справляется с поставленными задачами, и замечания касаются мелких деталей и стиля. Отличная работа!

Comment thread CEP170B.py

def gc_content(self):
gc_count = self.seq.count('G') + self.seq.count('C')
return gc_count / len(self.seq) * 100
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно учесть деление на 0.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Верно подмечено

Comment thread CEP170B.py
if output_filename is None:
output_filename = input_path.split("/")[-1].split(".")[0] + "_filtered.fastq"

output_path = "fastq_filtrator_results/" + output_filename
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Отличный вариант с добавлением папки для результатов. Но можно проверить ее существование перед созданием.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это очень очень хорошее замечание. Папку при чем можно было бы делать где нибудь отдельно в начале специальной функцией для создания папок

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants