diff --git a/rpg/rule.py b/rpg/rule.py index 595d12f03e400f5db22d4592e2428561a510317f..15af66b2b98e61f1dd57a238afff992cc7a910da 100644 --- a/rpg/rule.py +++ b/rpg/rule.py @@ -33,22 +33,22 @@ class Rule: """Definition of a principal rule defining where a cleavage occurs. :param index: position where to look for a specific amino acid - :param letter: amino acid to look for - :param cut: cut or not at this position on this amino acid - :param pos: cut before (0) of after (1) amino acid. -1 for unused value + :param amino_acid: amino acid to look for + :param cleavage: cleavage or not at this position on this amino acid + :param pos: cleavage before (0) of after (1) amino acid. -1 for unused value :type index: signed int - :type letter: char - :type cut: bool + :type amino_acid: char + :type cleavage: bool :type pos: int :var rules: additional sub-rules of this rule :vartype rules: list(:py:class:`Rule`) """ - def __init__(self, index, letter, cut, pos): + def __init__(self, index, amino_acid, cleavage, pos): self.index = index # where to look for this aa? - self.letter = letter # the aa - self.cut = cut # if letter detected at index, cut or not? - self.pos = pos # cut before (0) of after (1) letter (-1 if not used) + self.amino_acid = amino_acid # the aa + self.cleavage = cleavage # if amino_acid detected at index, cleavage or not? + self.pos = pos # cleavage before (0) of after (1) amino_acid (-1 if not used) self.rules = [] # List of additional rules # self representation for print @@ -60,10 +60,10 @@ class Rule: ret += "index=" + str(self.index) + "\n" for _ in range(lvl): ret += "\t" - ret += "amino_acid=" + str(self.letter) + "\n" + ret += "amino_acid=" + str(self.amino_acid) + "\n" for _ in range(lvl): ret += "\t" - ret += "cleavage=" + str(self.cut) + "\n" + ret += "cleavage=" + str(self.cleavage) + "\n" for _ in range(lvl): ret += "\t" ret += "position=" + str(self.pos) + "\n" @@ -84,7 +84,7 @@ class Rule: def equ(self, other): """Test equality with another rule **without taking into - account sub-rules nor `cut`**. + account sub-rules nor `cleavage`**. :param other: rule to compare with :type other: :py:class:`Rule` @@ -94,12 +94,12 @@ class Rule: :note: use '==' for complete equality including sub-rules. """ - return (self.index == other.index) and (self.letter == other.letter) \ + return (self.index == other.index) and (self.amino_acid == other.amino_acid) \ and (self.pos == other.pos) def contains(self, other): """Test if another rule is contains in sub-rules **without - taking into account sub-rules nor `cut`** and return the + taking into account sub-rules nor `cleavage`** and return the sub-rule if founded. :param other: rule to compare with @@ -116,7 +116,7 @@ class Rule: def contains_any_level(self, other, ret=False): """Test if another rule is contains within **without taking into - account sub-rules nor `cut`** no matter what level. + account sub-rules nor `cleavage`** no matter what level. :param other: rule to compare with :type other: :py:class:`Rule` @@ -139,8 +139,8 @@ class Rule: :return: header of this rule in Python :rtype: str """ - return 'rule.Rule(' + str(self.index) + ', "' + str(self.letter) + \ - '", ' + str(self.cut) + ', ' + str(self.pos) + ')' + return 'rule.Rule(' + str(self.index) + ', "' + str(self.amino_acid) + \ + '", ' + str(self.cleavage) + ', ' + str(self.pos) + ')' def get_all_headers(self): """Format header of the rule and sub-rules in Python. @@ -174,14 +174,14 @@ class Rule: ret_name = str(self.pos).upper() else: ret_name = prev_name - # Should we add the new letter of the rule before or + # Should we add the new amino_acid of the rule before or # after the prev_name? if self.index > 0: - ret_name += self.letter + ret_name += self.amino_acid elif not ret_name: - ret_name = self.letter + ret_name = self.amino_acid else: - ret_name = self.letter + "_" + ret_name + ret_name = self.amino_acid + "_" + ret_name # Add the index on the name to avoid same name if self.index != 0: ret_name += str(self.index) @@ -191,23 +191,23 @@ class Rule: ret_com = prev_com # Modify the prev_com if needed if prev_com != " # ": - if self.cut: + if self.cleavage: ret_com = ret_com.replace("Never", "Always") else: ret_com = ret_com.replace("Always", "Never") - # Order of letter + # Order of amino_acid if self.index > 0: ret_com = ret_com.replace(", except...", ", followed by " + - self.letter + ", except...") + self.amino_acid + ", except...") else: ret_com = ret_com.replace(", except...", ", preceded by " + - self.letter + ", except...") + self.amino_acid + ", except...") # First comment else: - ret_com += "Always" if self.cut else "Never" + ret_com += "Always" if self.cleavage else "Never" ret_com += " cleaves " ret_com += "after " if self.pos > 0 else "before " - ret_com += self.letter + ret_com += self.amino_acid ret_com += ", except..." # Full line to write ret_total = ret_name + " = " + self.get_header() + ret_com @@ -297,7 +297,7 @@ def check_rule(exprule): core.handle_errors(to_print + "^", 2) ret = "" - # No letter after a letter (all UPPER except or) + # No amino_acid after a amino_acid (all UPPER except or) if ret != "": res = re.search(r"[A-Z][A-Z]", clean_exprule) if res: @@ -471,7 +471,7 @@ def add_rule(rules_list, a_rule): # Flag this conflicting rules to_remove.add(k) # Edit the rule - a_rule.cut = not a_rule.cut + a_rule.cleavage = not a_rule.cleavage # Add it to the sub-rule that already exist # without modifying it add_rule(i.rules, a_rule) @@ -499,18 +499,18 @@ def create_rules(all_rules): # All rules correctly added, ready to be printed correct_rules = [] # handle " or " keyword and split it into several rules - for tmp_rule, tmp_cut in list(all_rules.items()): + for tmp_rule, tmp_cleavage in list(all_rules.items()): # Remove this rule from main list all_rules.pop(tmp_rule) # Split this rule on " or " tmp_rules = split_complex_rule(tmp_rule) # Add all the cleaned rules corresponding for rul in tmp_rules: - all_rules[rul] = tmp_cut + all_rules[rul] = tmp_cleavage # handle multiple "," in one parenthesis #so we got only ONE "," per rule - for tmp_rule, tmp_cut in list(all_rules.items()): + for tmp_rule, tmp_cleavage in list(all_rules.items()): if tmp_rule.count(",") > 1: # Remove this complex rule all_rules.pop(tmp_rule) @@ -518,18 +518,18 @@ def create_rules(all_rules): # Beginning of the complex rule begpos = tmp_rule.find("(,") # Should be like ...(' - beg_cut = tmp_rule[:begpos + 2] + beg_cleavage = tmp_rule[:begpos + 2] # Should be like ...( - beg_no_cut = tmp_rule[:begpos + 1] + beg_no_cleavage = tmp_rule[:begpos + 1] # Ending of the complex rule endpos = tmp_rule.find(",)") # Should be like ...') - end_cut = tmp_rule[endpos:] + end_cleavage = tmp_rule[endpos:] # Should be like ...) - end_no_cut = tmp_rule[endpos + 1:] + end_no_cleavage = tmp_rule[endpos + 1:] # Add rules - all_rules[beg_cut + tmp_rule[begpos + 2] + end_no_cut] = tmp_cut - all_rules[beg_no_cut + tmp_rule[begpos + 2] + end_cut] = tmp_cut + all_rules[beg_cleavage + tmp_rule[begpos + 2] + end_no_cleavage] = tmp_cleavage + all_rules[beg_no_cleavage + tmp_rule[begpos + 2] + end_cleavage] = tmp_cleavage # Sort rules, smaller first all_rules_keys = list(all_rules.keys()) @@ -561,23 +561,23 @@ def create_rules(all_rules): # Create rule for the cleaving zone if dict_rule[0][0] == ",": - # Before letter + # Before amino_acid cleaving_zone = Rule(0, str(dict_rule[0][1]), all_rules[rul], 0) else: - # After letter + # After amino_acid cleaving_zone = Rule(0, str(dict_rule[0][0]), all_rules[rul], 1) # Is there sub-rule? if len(dict_rule) > 1: - # Reverse the cutting boolean - cleaving_zone.cut = not cleaving_zone.cut + # Reverse the cleavageting boolean + cleaving_zone.cleavage = not cleaving_zone.cleavage # Upper-rule previous_rule = cleaving_zone # Only the deeper rule should have the correct boolean cleav = not all_rules[rul] # Exceptions to handle - if cleaving_zone.cut and len(dict_rule) > 1: + if cleaving_zone.cleavage and len(dict_rule) > 1: # Backup this exception exceptions.append(dict_rule) # No exception @@ -608,10 +608,10 @@ def create_rules(all_rules): for dict_exc in exceptions: # Create rule for the cleaving zone if dict_exc[0][0] == ",": - # Before letter + # Before amino_acid cleaving_zone = Rule(0, str(dict_exc[0][1]), all_rules[rul], 0) else: - # After letter + # After amino_acid cleaving_zone = Rule(0, str(dict_exc[0][0]), all_rules[rul], 1) # Default main_rule @@ -718,15 +718,15 @@ def add_missing_rule(main_rule, dict_of_rule, rule_to_add): where_to_add = reachable_pos[min(reachable_pos)] # Create the Rule for this exception tmp_rule = Rule(rule_to_add[0], rule_to_add[1], False, -1) - # Change upper rules to cut - # Dangerous, works because .equ doesn't look cutting position. + # Change upper rules to cleavage + # Dangerous, works because .equ doesn't look cleavageting position. # I can't find an upper rule that should be at F with sub-rule at F # Something like '(D,)(G)': False, '(X)(D,)(G)': False # But it is none sens, but this actually BUG... # What I should do is checking if the rule already exist. If so, add # a new one. But I will end-up with two identical rules at the same # level saying T and F. - where_to_add.cut = True + where_to_add.cleavage = True # If it is not already there if not where_to_add.contains(tmp_rule) and not where_to_add.equ(tmp_rule): # Add manually the rule @@ -773,56 +773,56 @@ def find_rechable_pos(main_rule, dict_of_rule): ret[len(dict_of_rule)] = main_rule return ret -def handle_rule(seq, pos, a_rule, cut): +def handle_rule(seq, pos, a_rule, cleavage): """Recursive handling of a :py:class:`Rule` determining if a - sequence must be cutted at a given position according to the rule. + sequence must be cleavageted at a given position according to the rule. :param seq: sequence to test :param pos: position on the sequence :param a_rule: the rule - :param cut: boolean telling if it must be cutted or not + :param cleavage: boolean telling if it must be cleavageted or not :type seq: str :type pos: int :type a_rule: :py:class:`Rule` - :type cut: bool + :type cleavage: bool - :return: `True` if sequence must be cutted + :return: `True` if sequence must be cleavageted :rtype: bool or None """ - # return of the function: should we cut this? - ret = cut - # Need to try because it can be the first/last letter + # return of the function: should we cleavage this? + ret = cleavage + # Need to try because it can be the first/last amino_acid # and we need to look before/after # After is handle by try, but before, because python like str[-x], # we need an if :-/ try: - # If the rule applies, i.e. the letter to watch is the good one + # If the rule applies, i.e. the amino_acid to watch is the good one if (pos + a_rule.index) >= 0 and \ - seq[pos + a_rule.index] == a_rule.letter: - # If no previous 'False' and this is cutting - if a_rule.cut and ret is not False: + seq[pos + a_rule.index] == a_rule.amino_acid: + # If no previous 'False' and this is cleavageting + if a_rule.cleavage and ret is not False: ret = True # Handle the sub-rules (exceptions) for rul in a_rule.rules: - # Apply the rule: do we need to cut? + # Apply the rule: do we need to cleavage? ret = handle_rule(seq, pos, rul, ret) - # Is is not cutting - elif not a_rule.cut: + # Is is not cleavageting + elif not a_rule.cleavage: # Reinit ret = None # Handle sub-rules if a_rule.rules: # Handle the rules (exceptions) for rul in a_rule.rules: - # Apply the rule: do we need to cut? + # Apply the rule: do we need to cleavage? ret = handle_rule(seq, pos, rul, ret) - # No sub-rules and not cutting + # No sub-rules and not cleavageting else: # We are at the end a of rule that applies - # and say to NOT cut. So it will never cut. + # and say to NOT cleavage. So it will never cleavage. ret = False - # Doesn't work: begin or end of sequence, don't change cut value + # Doesn't work: begin or end of sequence, don't change cleavage value except IndexError: pass return ret diff --git a/tests/test_rule.py b/tests/test_rule.py index fc451f9cd5ff627a5c221d94ab06ecdd481f90e4..2fc7cb203a83c7451d1ecf2042c70ce3427fab11 100644 --- a/tests/test_rule.py +++ b/tests/test_rule.py @@ -8,10 +8,10 @@ def test_rule(): """Test class 'Rule'""" # Simple rule0 index = 0 - letter = "D" - cut = True + amino_acid = "D" + cleavage = True pos = 0 - rule0 = rule.Rule(index, letter, cut, pos) + rule0 = rule.Rule(index, amino_acid, cleavage, pos) # Test function '__repr__()' print_res = rule0.__repr__() @@ -19,19 +19,19 @@ def test_rule(): # Simple rule1 index = 2 - letter = "Q" - cut = False + amino_acid = "Q" + cleavage = False pos = 1 - rule1 = rule.Rule(index, letter, cut, pos) + rule1 = rule.Rule(index, amino_acid, cleavage, pos) print_res = rule1.__repr__() assert print_res == "index=2\namino_acid=Q\ncleavage=False\nposition=1\n" # Simple rule2 identical to 1 index = 0 - letter = "D" - cut = True + amino_acid = "D" + cleavage = True pos = 0 - rule2 = rule.Rule(index, letter, cut, pos) + rule2 = rule.Rule(index, amino_acid, cleavage, pos) # Test function '__eq__()' assert rule0 == rule2 @@ -140,7 +140,7 @@ def test_check_rule(): res = rule.check_rule(expr) assert res == expr - # No UPPER letter after a letter + # No UPPER amino_acid after a amino_acid expr = "(AB,)" res = rule.check_rule(expr) assert res == "" @@ -235,12 +235,12 @@ def test_split_complex_rule(): def test_add_rule(): """Test function 'add_rule(rules_list, rule)'.""" rules_list = [] - # Add a basic rule that cut before 'A' + # Add a basic rule that cleavage before 'A' rule1 = rule.Rule(0, "A", True, 0) rule.add_rule(rules_list, rule1) assert rules_list[0].index == 0 - assert rules_list[0].letter == "A" - assert rules_list[0].cut is True + assert rules_list[0].amino_acid == "A" + assert rules_list[0].cleavage is True assert rules_list[0].pos is 0 assert len(rules_list) == 1 assert rules_list[0] == rule1 @@ -257,7 +257,7 @@ def test_add_rule(): rule.add_rule(rules_list, rule3) assert len(rules_list) == 1 - # Add a rule that cut after 'B' and a sub-rule (except if Y after) + # Add a rule that cleavage after 'B' and a sub-rule (except if Y after) rule4 = rule.Rule(0, "B", True, 1) rule4.rules.append(rule.Rule(2, "Y", False, 1)) rule.add_rule(rules_list, rule4) @@ -265,24 +265,24 @@ def test_add_rule(): assert rules_list[0] == rule1 assert rules_list[1] == rule4 assert len(rule4.rules) == 1 - # It doesn't change rule4.cut - assert rule4.cut is True + # It doesn't change rule4.cleavage + assert rule4.cleavage is True assert rules_list[1].rules[0].index == 2 - assert rules_list[1].rules[0].letter == "Y" - assert rules_list[1].rules[0].cut is False + assert rules_list[1].rules[0].amino_acid == "Y" + assert rules_list[1].rules[0].cleavage is False assert rules_list[1].rules[0].pos == 1 - # Add a rule that DOESN'T cut after 'C' + # Add a rule that DOESN'T cleavage after 'C' rule5 = rule.Rule(0, "C", False, True) - # Add a sub-rule in rule5 that is cutting before 'A' (same as rule1) + # Add a sub-rule in rule5 that is cleavageting before 'A' (same as rule1) rule5.rules.append(rule.Rule(0, "A", True, 0)) rule.add_rule(rules_list, rule5) # It is NOT recorded as the rule already exist assert len(rules_list) == 2 - # But it modify rule5.cut - assert rule5.cut is True + # But it modify rule5.cleavage + assert rule5.cleavage is True # And rule5 is added to rule1 sub-rules - assert rules_list[0].rules[1].letter == "C" + assert rules_list[0].rules[1].amino_acid == "C" # create a complex rule containing B rule6 = rule.Rule(0, "D", True, 1) @@ -293,20 +293,20 @@ def test_add_rule(): rule.add_rule(rules_list, rule6) # It is NOT added assert len(rules_list) == 2 - # rule6.cut should have change - assert rule6.cut is False + # rule6.cleavage should have change + assert rule6.cleavage is False # rule6 should have only 3 sub-rules, 'E', 'F' and 'G' assert len(rule6.rules) == 3 # Those have been added to rule4 - assert rule4.rules[1].rules[0].letter == "E" - assert rule4.rules[1].rules[1].letter == "F" - assert rules_list[1].rules[1].rules[2].letter == "G" # Same as rule4 + assert rule4.rules[1].rules[0].amino_acid == "E" + assert rule4.rules[1].rules[1].amino_acid == "F" + assert rules_list[1].rules[1].rules[2].amino_acid == "G" # Same as rule4 def test_create_rules(): """Test function 'create_rules(all_rules)'.""" all_rules = {} # Simplest rule - # Cut before A + # cleavage before A rule1 = "(,A)" all_rules[rule1] = True @@ -316,7 +316,7 @@ def test_create_rules(): assert truth1 in res # More complex rule - # Cut after B or C + # cleavage after B or C rule2 = "(B or C,)" all_rules[rule2] = True # Truth for rule2 @@ -403,40 +403,40 @@ def test_create_rules(): assert len(res) == 4 def test_handle_rule(): - """Test function 'handle_rule(seq, pos, a_rule, cut)'""" + """Test function 'handle_rule(seq, pos, a_rule, cleavage)'""" - # We cut after E preceeded by D + # We cleavage after E preceeded by D a_rule = {} rule_txt = "(D)(E,)" a_rule[rule_txt] = True all_rules = rule.create_rules(a_rule) seq = "ABCDEF" pos = 4 - cut = None # Not needed here - res = rule.handle_rule(seq, pos, all_rules[0], cut) + cleavage = None # Not needed here + res = rule.handle_rule(seq, pos, all_rules[0], cleavage) assert res is True - # We cut after E preceeded by D + # We cleavage after E preceeded by D a_rule = {} rule_txt = "(D)(E,)" a_rule[rule_txt] = True all_rules = rule.create_rules(a_rule) seq = "ABCXEF" pos = 4 - cut = None # Not needed here - res = rule.handle_rule(seq, pos, all_rules[0], cut) + cleavage = None # Not needed here + res = rule.handle_rule(seq, pos, all_rules[0], cleavage) assert res is None - # We cut after E preceeded by D + # We cleavage after E preceeded by D a_rule = {} rule_txt = "(D)(E,)" a_rule[rule_txt] = True all_rules = rule.create_rules(a_rule) seq = "ABCDEF" pos = 3 # Not E - cut = None # Not needed here - res = rule.handle_rule(seq, pos, all_rules[0], cut) + cleavage = None # Not needed here + res = rule.handle_rule(seq, pos, all_rules[0], cleavage) assert res is None - # We cut after E NOT preceeded by D + # We cleavage after E NOT preceeded by D a_rule = {} rule_txt = "(E,)" a_rule[rule_txt] = True @@ -445,11 +445,11 @@ def test_handle_rule(): all_rules = rule.create_rules(a_rule) seq = "ABCXEF" pos = 4 - cut = None # Not needed here - res = rule.handle_rule(seq, pos, all_rules[0], cut) + cleavage = None # Not needed here + res = rule.handle_rule(seq, pos, all_rules[0], cleavage) assert res is True - # We cut after E NOT preceeded by D + # We cleavage after E NOT preceeded by D a_rule = {} rule_txt = "(E,)" a_rule[rule_txt] = True @@ -458,6 +458,6 @@ def test_handle_rule(): all_rules = rule.create_rules(a_rule) seq = "ABCDEF" pos = 4 - cut = None # Not needed here - res = rule.handle_rule(seq, pos, all_rules[0], cut) + cleavage = None # Not needed here + res = rule.handle_rule(seq, pos, all_rules[0], cleavage) assert res is False