diff --git a/HW4_Smertina/run_protein_tool.py b/HW4_Smertina/run_protein_tool.py
new file mode 100644
index 0000000..316e834
--- /dev/null
+++ b/HW4_Smertina/run_protein_tool.py
@@ -0,0 +1,143 @@
+def amino_acid_frequency(seq: str) -> dict:
+
+ """
+ Calculates amino acid frequencies
+
+ Arguments:
+ -seq (str) input protein sequence
+ Return:
+ -dictionary with amino acid and its frequency
+
+ """
+
+ # Словарь для хранения частоты аминокислот
+ freq_dict = {}
+ # Подсчитываем количество каждой аминокислоты в последовательности
+ for letter in seq:
+ if letter in freq_dict:
+ freq_dict[letter] += 1
+ else:
+ freq_dict[letter] = 1
+ # Преобразуем количество в проценты
+ for letter in freq_dict:
+ freq_dict[letter] = round(freq_dict[letter] / len(seq) * 100, 2)
+ return freq_dict
+
+# Функция для поиска мотивов в белке
+def find_motifs(seq: str, motif: str):
+
+ """
+ Finds a motif of interest in a protein sequence
+ Arguments:
+ -seq (str) input protein sequence
+ -motif (str) motif to be found in sequence
+ Return:
+ -position(s) of the motif in seq
+
+ """
+ # Список для хранения позиций мотивов в последовательности
+ positions = []
+ # Ищем мотив в последовательности с помощью скользящего окна
+ for i in range(len(seq) - len(motif) + 1):
+ window = seq[i:i+len(motif)]
+ if window == motif:
+ positions.append(i+1)
+ return positions
+
+def check_protein_seq(seq: str) -> str:
+
+ """
+ Checks whether a sequence is written using 1-letter amino acid code
+
+ Arguments:
+ -seq (str) input protein sequence
+ Return:
+ - str, 'single_letter_prot_seq' otherwise 'Invalid Input' error is raised
+
+ """
+ unique_chars = set(seq)
+ single_letter = set('GALMFWKQESPVICYHRNDTgalmfwkqespvicyhrndt')
+
+ if unique_chars <= single_letter:
+ seq = 'single_letter_prot_seq'
+
+ else:
+ raise ValueError("Invalid Input")
+ return seq
+
+def molecular_weight(seq: str) -> int:
+
+ """
+ Calculates molecular weight of a protein
+
+ Arguments:
+ - seq (str) 1-letter coded protein sequence
+ Return:
+ - int, molecular weight (g/mol) rounded to integer
+
+ """
+ if check_protein_seq(seq) == 'single_letter_prot_seq':
+ list_input_seq = list(seq)
+ aa_weight_dict = {'G':75, 'g':75, 'A':89, 'a':89, 'R':174, 'r':174, 'N':132, 'n':132,
+ 'D':133, 'd':133, 'C':121, 'c':133, 'E':147, 'e':147, 'Q':146, 'q':146,
+ 'H':155, 'h':155, 'I':131, 'i':131, 'L':131, 'l':131, 'K':146, 'k':146,
+ 'M':149, 'm':149, 'F':165, 'f':165, 'P':115, 'p':115, 'S':105, 's':105,
+ 'T':119, 't':119, 'W':204, 'w':204, 'Y':181, 'y':181, 'V':117, 'v':117}
+ water_mw = 18
+ for aa in list_input_seq:
+ total_mw = sum(aa_weight_dict[a] for a in list_input_seq)
+ mw_water_removed = (total_mw - (water_mw * (len(list_input_seq)-1)))
+ return mw_water_removed
+def one_to_three_letter(seq: str) -> str:
+
+ """
+ Converts a 1-letter amino acid code sequence into a 3-letter sequence
+
+ Arguments:
+ - seq (str) sequence to convert, must be 1-letter coded protein sequence
+ Return:
+ - str, a 3-letter coded protein sequence without spaces
+
+ """
+ if check_protein_seq(seq) == 'single_letter_prot_seq':
+ aa_code_dict = {'C':'Cys', 'c':'Cys', 'D':'Asp', 'd':'Asp', 'S':'Ser', 's':'Ser', 'Q':'Gln', 'q':'Gln',
+ 'K':'Lys', 'k':'Lys', 'I':'Ile', 'i':'Ile', 'P':'Pro', 'p':'Pro', 'T':'Thr', 't':'Thr',
+ 'F':'Phe', 'f':'Phe', 'N':'Asn', 'n':'Asn', 'G':'Gly', 'g':'Gly', 'H':'His', 'h':'His',
+ 'L':'Leu', 'l':'Leu', 'R':'Arg', 'r':'Arg', 'W':'Trp', 'w':'Trp', 'A':'Ala', 'a':'Ala',
+ 'V':'Val', 'v':'Val', 'E':'Glu', 'e':'Glu', 'Y':'Tyr', 'y':'Tyr', 'M':'Met', 'm':'Met'}
+
+ three_letter_aa = ''
+ for aa in seq:
+ three_letter_aa += aa_code_dict[aa]
+ return three_letter_aa
+
+from typing import Optional
+def run_protein_tool(*args: str, function: str, motif: Optional[str]=None):
+
+ """
+ This is the main function
+ Arguments:
+ -seq(str) protein sequence(s)
+ -function(str) specify the function
+ -motif(str), optional argument for find_motifs function
+ Return:
+ -result of the specified function
+
+ """
+ results = []
+ for seq in args:
+ check_protein_seq(seq)
+ if function == 'check_protein_seq':
+ results.append(check_protein_seq(seq))
+ elif function == 'molecular_weight':
+ results.append(molecular_weight(seq))
+ elif function == 'one_to_three_letter':
+ results.append(one_to_three_letter(seq))
+ elif function == 'amino_acid_frequency':
+ results.append(amino_acid_frequency(seq))
+ elif function == 'find_motifs':
+ results.append(find_motifs(seq, motif))
+ if len(results) == 1:
+ results = results[0]
+ return results
+
diff --git a/README.md b/README.md
index f918170..eccd891 100644
--- a/README.md
+++ b/README.md
@@ -1,65 +1,81 @@
-# HW 4. Functions 2
-> *This is the repo for the fourth homework of the BI Python 2023 course*
+# run_protein_tool
-### Homework description
+```run_protein_tool``` includes a set of commands that perform various operations with protein or peptide sequences of any length. The input sequence(s) must be written
+using 1-letter amino acid code and can contain any of the following 20 amino acids:
-На прошлой неделе вы делали утилиту для работы с последовательностями нуклеиновых кислот (с весьма строгим ТЗ). Пришло время для чего-то более самостоятельного.
+
-#### Основное задание
+The following functions are implemented:
+1. ```molecular_weight``` This function takes 1-letter coded protein sequence(s) (string) and calculates molecular weight rounded to integer in g/mol. The function is not case-sensitive.
+Usage examples:
+```
+run_protein_tool('peptide', function='molecular_weight')
+799
+```
+```
+run_protein_tool('pEpTiDe', function='molecular_weight')
+799
+```
+2. ```one_to_three_letter``` This function takes 1-letter coded protein sequence(s) (string) and returns a 3-letter coded sequence(s) without spaces (string). Usage examples:
+```
+run_protein_tool('PEPTIDE', function='one_to_three_letter')
+'ProGluProThrIleAspGlu'
+```
+```
+run_protein_tool('p', 'peptide', function='one_to_three_letter')
+['Pro', 'ProGluProThrIleAspGlu']
+```
+3. ```amino_acid_frequency``` This function takes 1-letter coded protein sequence(s) (string), calculates frequency for each unique amino acid and creates a dictionary
+with amino acids as keys and corresponding frequencies as values. Usage example:
-Напишите утилиту для работы с последовательностями белков. Там должно быть минимум 5 различных операций, должна быть какая-то точка входа через которую пользователь будет всё это дело использовать. На этом, по сути, всё. Всё целиком зависит от вашей фантазии и креативности. Можете опираться на ДЗ №2 и №3.
+```
+run_protein_tool('MADSEQNQEEAGGGEQREH', function='amino_acid_frequency')
+{'M': 5.26,
+'A': 10.53,
+'D': 5.26,
+'S': 5.26,
+'E': 26.32,
+'Q': 15.79,
+'N': 5.26,
+'G': 15.79,
+'R': 5.26,
+'H': 5.26}
+```
+4. ```find_motifs``` This function takes two string arguments: 1-letter coded protein sequence(s) and a motif of interest, where motif is any sequence which occurence
+will be searched for in the input protein sequence(s). The function returns position(s) of the motif. If a motif was not found, the function will return an empty list.
+Please note that this function can only search for one motif at a time. Usage example:
-Самая главная часть задания - это файл `README.md`. Сделайте краткое введение, напишите описание тула, приведите документацию по использованию со списком аргументов. Добавьте примеры использования. Возможно, вы захотите сделать секцию Troubleshooting. ***Почему это нужно?*** В этот раз проверяющий не будет знать того, как должен работать ваш тул. Это ваш авторский код. Даже самая прекрасная функциональность, не будучи отраженной в README, скорее всего останется незамеченной. README - это ваш способ познакомить пользователя с тулом, показать всё лучше и обосновать, почему именно ваша команда должна получить наивысший балл.
+```
+find_motifs('MADSEQNQEEAGGGEQREH', function='find_motifs', motif='GG')
+[12, 13]
+```
+# Troubleshooting
-Есть люди которые, любят писать документации, а есть те - кто не любит. Найдите в вашей команде того, кто любит. И в будущем в своих рабочих проектах всегда держите рядом такого человек (или будьте им).
+Please make sure that your input sequence(s) is written using the **1-letter** amino acid code as shown in the examples. A sequence containing letters that
+do not correspond to one of the 20 amino acids from the table above will result in 'Invalid Input' error. Please note that function ```find_motifs``` also requires the motif
+of interest as input after the function name.
-Примеры некоторых README, которыми можно вдохновляться:
+# Contributors
-- [MetaFX](https://github.com/ctlab/metafx), тул Артёма Иванова. Там еще и [wiki](https://github.com/ctlab/metafx/wiki) крутое.
-- [samovar](https://github.com/nvaulin/samovar)
-- [MetaGEM](https://github.com/franciscozorrilla/metaGEM)
-- [Pharokka](https://github.com/gbouras13/pharokka)
+Elena Smertina implemented check_protein_seq, molecular_weight, one_to_three_letter and run_protein_tool functions;
+Natalia Erofeeva implemented amino_acid_frequency and find_motifs functions.
-Типовые секции, на которые стоит обратить внимание: Title, Overview, Usage, Options, Examples, Troubleshooting, Contacts.
-**Tехническое требование к заданию.**
-Это задание будет выполняться в командах по 3 человека. Каждый из членов команды должен внести ***как минимум*** 2 функции. Каждое внесение функции должно сопровождаться коммитом с осмысленным описанием коммита. Ниже приведена последовательность действий для успешного выполнения задания (аналогично ДЗ №2):
-1. Посмотрите состав своей команды здесь ([**ССЫЛКА**](https://docs.google.com/spreadsheets/d/1KMBBBu8LqauRpDJb0v1ldPwpvzNn8-KakcHexAcqLsE/edit?usp=sharing)).
-2. Тимлид делает форк данного репозитория. **В форке создает ветку `HW4_`, в ветке создает папку `HW4_`, в этой папке вы всё делаете.**
-3. Члены команды могут либо делать свои форки, либо работать в репозитории тимлида в качестве колабораторов ("contributors"). В любом случае делаете клоны => пишите код локально => пушите.
-4. В конце тимлид делайет pull-request из `HW4_` своего репозитория в `main` этого.
-А также:
-- Сопроводите программу лучшим `README.md` файлом в вашей жизни (на английском языке).
-- В этом ДЗ проблемы с качеством кода (нейминги, пустые строки, анноатции типов, док.стринги, пробелы) могут привести к снижению балла. Воспользуйтесь линтерами чтобы себя обезопасить. IDE по типу PyCharm или VSCode имеют фунцонал по авто-исправлению многих проблем такого рода.
-Автотестов на GitHub в этом ДЗ нет, но вы можете прогнать линтеры на качество кода локально (как в ДЗ №3, подробнее читайте [тут](https://plausible-cannon-091.notion.site/Code-auto-checks-02b2ea69c1d545fca07b50ce5933ed5f?pvs=4)).
-- Программа должна сохранять регистр символов.
-- Программа должна работать только с последовательностями белков.
-- Запрещается использование сторонних модулей.
-### Форма сдачи
-Прикрепите ссылку на pull-request тимлида в Google Class (можете сделать от лица каждого члена команды, но это не обязательно).
+
-### Pазбалловка
-- За каждую из 5 операций - максимум **1.5 балла**
-- За README - максимум **2.5 балла**
-- Если вы не внесли как минимум 2 функции от себя, вы получаете 0 баллов (на баллы остальных членов команды это не влияет).
-- За фото созвона в README можно получить 0.2 доп. балла (но не более 10 баллов суммарно)
-### **Предполагаемый учебный результат**
-
-Это задание позволит вам проявить креативность и учиться быть не только кодером, но и автором. Также это задание поможет окончательно закрепить материал по функциям который мы прошли.
-
-Удачи! ✨✨
+