Beispiel #1
0
 def test_init(self):
     """PC: init functions as expected """
     # instantiate the class
     pc = PerformanceCalculator(self._gold_standard_data)
     # Check one of the values
     self.assertEqual(\
         pc._gold_standard['12206666'][PointMutation(95,'D','N')],2)
Beispiel #2
0
    def setUp(self):

        self.mutation = PointMutation(42,'W','G')
        self.amino_acid_codes = dict([('GLY','G'),('ALA','A'),('LEU','L'),\
            ('MET','M'),('PHE','F'),('TRP','W'),('LYS','K'),('GLN','Q'),\
            ('GLU','E'),('SER','S'),('PRO','P'),('VAL','V'),('ILE','I'),\
            ('CYS','C'),('TYR','Y'),('HIS','H'),('ARG','R'),('ASN','N'),\
            ('ASP','D'),('THR','T'),('GLYCINE','G'),('ALANINE','A'),\
            ('XAA','X'),('GLX','Z'),('ASX','B'),\
            ('LEUCINE','L'),('METHIONINE','M'),('PHENYLALANINE','F'),\
            ('VALINE','V'),('ISOLEUCINE','I'),('TYROSINE','Y'),\
            ('TRYPTOPHAN','W'),('SERINE','S'),('PROLINE','P'),\
            ('THREONINE','T'),('CYSTEINE','C'),('ASPARAGINE','N'),\
            ('GLUTAMINE','Q'),('LYSINE','K'),('HISTIDINE','H'),\
            ('ARGININE','R'),('ASPARTATE','D'),('GLUTAMATE','E'),\
            ('ASPARTIC ACID','D'),('GLUTAMIC ACID','E'),\
            ('G','G'),('A','A'),('V','V'),('L','L'),('I','I'),('M','M'),\
            ('F','F'),('Y','Y'),('W','W'),('S','S'),('P','P'),('T','T'),\
            ('C','C'),('N','N'),('Q','Q'),('K','K'),('H','H'),('R','R'),\
            ('D','D'),('E','E')]) 
Beispiel #3
0
    def test_normalized_mutations_varied_input(self):
        """PC: Normalized Mutations functions with varied extracted mutations
        """
        # 
        perf = self._pc.calculate_normalized_mutations(\
            {'3476160':{PointMutation(22,'T','C'):1},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,1)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,5)
        self.assertEqual(perf.TrueNegative,None)
        # An extra count has no effect
        perf = self._pc.calculate_normalized_mutations(\
            {'3476160':{PointMutation(22,'T','C'):2},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,1)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,5)
        self.assertEqual(perf.TrueNegative,None)
        # ...and two extra counts have no effect
        perf = self._pc.calculate_normalized_mutations(\
            {'3476160':{PointMutation(22,'T','C'):3},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,1)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,5)
        self.assertEqual(perf.TrueNegative,None)
        
        # One missing count has no effect
        perf = self._pc.calculate_normalized_mutations(\
            {'3476160': {PointMutation(87,'S','C'): 1,\
                        PointMutation(22,'T','C'): 1},\
             '14500716': {},\
             '12206666': {PointMutation(95,'D','A'): 4,\
                         PointMutation(95,'D','N'): 2,\
                         PointMutation(95,'D','E'): 2},\
             '11327835': {PointMutation(64,'H','A'): 3}})
        self.assertEqual(perf.TruePositive,6)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,0)
        self.assertEqual(perf.TrueNegative,None)
        # Two missing counts have no effect
        perf = self._pc.calculate_normalized_mutations(\
            {'3476160': {PointMutation(87,'S','C'): 1,\
                        PointMutation(22,'T','C'): 1},\
             '14500716': {},\
             '12206666': {PointMutation(95,'D','A'): 4,\
                         PointMutation(95,'D','N'): 2,\
                         PointMutation(95,'D','E'): 2},\
             '11327835': {PointMutation(64,'H','A'): 2}})
        self.assertEqual(perf.TruePositive,6)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,0)
        self.assertEqual(perf.TrueNegative,None)

        # One extra mutation tallied as one FalsePositive 
        perf = self._pc.calculate_normalized_mutations(\
            {'3476160':{PointMutation(42,'L','Y'):1},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,0)
        self.assertEqual(perf.FalsePositive,1)
        self.assertEqual(perf.FalseNegative,6)
        self.assertEqual(perf.TrueNegative,None)
        # Two counts of one extra mutation tallied as one FalsePositive 
        perf = self._pc.calculate_normalized_mutations(\
            {'3476160':{PointMutation(42,'L','Y'):2},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,0)
        self.assertEqual(perf.FalsePositive,1)
        self.assertEqual(perf.FalseNegative,6)
        self.assertEqual(perf.TrueNegative,None)
        # Two extra mutations tallied as two FalsePositives 
        perf = self._pc.calculate_normalized_mutations(\
            {'3476160':{PointMutation(42,'L','Y'):1},\
             '14500716':{PointMutation(33,'P','T'):1},\
             '12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,0)
        self.assertEqual(perf.FalsePositive,2)
        self.assertEqual(perf.FalseNegative,6)
        self.assertEqual(perf.TrueNegative,None)
Beispiel #4
0
    def test_document_retrieval_varied_input(self):
        """PC: Document Retrieval functions with varied extracted mutations
        """
        # 
        perf = self._pc.calculate_document_retrieval(\
            {'3476160':{PointMutation(22,'T','C'):1},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,1)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,2)
        self.assertEqual(perf.TrueNegative,1)
        # An extra count has no effect
        perf = self._pc.calculate_document_retrieval(\
            {'3476160':{PointMutation(22,'T','C'):2},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,1)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,2)
        self.assertEqual(perf.TrueNegative,1)
        # ...and two extra counts has no effect
        perf = self._pc.calculate_document_retrieval(\
            {'3476160':{PointMutation(22,'T','C'):3},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,1)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,2)
        self.assertEqual(perf.TrueNegative,1)
        
        # One missing count has no effect
        perf = self._pc.calculate_document_retrieval(\
            {'3476160': {PointMutation(87,'S','C'): 1,\
                        PointMutation(22,'T','C'): 1},\
             '14500716': {},\
             '12206666': {PointMutation(95,'D','A'): 4,\
                         PointMutation(95,'D','N'): 2,\
                         PointMutation(95,'D','E'): 2},\
             '11327835': {PointMutation(64,'H','A'): 3}})
        self.assertEqual(perf.TruePositive,3)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,0)
        self.assertEqual(perf.TrueNegative,1)
        # Two missing counts has no effect
        perf = self._pc.calculate_document_retrieval(\
            {'3476160': {PointMutation(87,'S','C'): 1,\
                        PointMutation(22,'T','C'): 1},\
             '14500716': {},\
             '12206666': {PointMutation(95,'D','A'): 4,\
                         PointMutation(95,'D','N'): 2,\
                         PointMutation(95,'D','E'): 2},\
             '11327835': {PointMutation(64,'H','A'): 2}})
        self.assertEqual(perf.TruePositive,3)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,0)
        self.assertEqual(perf.TrueNegative,1)

        # Incorrect mutations still counts as a TP document 
        perf = self._pc.calculate_document_retrieval(\
            {'3476160':{PointMutation(42,'L','Y'):1},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,1)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,2)
        self.assertEqual(perf.TrueNegative,1)
        # False Positive/TrueNegative tallied correctly 
        perf = self._pc.calculate_document_retrieval(\
            {'3476160':{},'14500716':{PointMutation(42,'L','Y'):1},\
             '12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,0)
        self.assertEqual(perf.FalsePositive,1)
        self.assertEqual(perf.FalseNegative,3)
        self.assertEqual(perf.TrueNegative,0)
Beispiel #5
0
    def test_extracted_mentions_varied_input(self):
        """PC: Extracted Mentions functions with varied extracted mutations
        """
        # 
        perf = self._pc.calculate_extracted_mentions(\
            {'3476160':{PointMutation(22,'T','C'):1},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,1)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,13)
        self.assertEqual(perf.TrueNegative,None)
        # An extra count results in a false positive
        perf = self._pc.calculate_extracted_mentions(\
            {'3476160':{PointMutation(22,'T','C'):2},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,1)
        self.assertEqual(perf.FalsePositive,1)
        self.assertEqual(perf.FalseNegative,13)
        self.assertEqual(perf.TrueNegative,None)
        # ...and two extra counts results in two false positives
        perf = self._pc.calculate_extracted_mentions(\
            {'3476160':{PointMutation(22,'T','C'):3},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,1)
        self.assertEqual(perf.FalsePositive,2)
        self.assertEqual(perf.FalseNegative,13)
        self.assertEqual(perf.TrueNegative,None)
        
        # One missing count results in one false negative (see 11327835)
        # and one less true positive
        perf = self._pc.calculate_extracted_mentions(\
             {'3476160': {PointMutation(87,'S','C'): 1,\
                        PointMutation(22,'T','C'): 1},\
             '14500716': {},\
             '12206666': {PointMutation(95,'D','A'): 4,\
                         PointMutation(95,'D','N'): 2,\
                         PointMutation(95,'D','E'): 2},\
             '11327835': {PointMutation(64,'H','A'): 3}})
        self.assertEqual(perf.TruePositive,13)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,1)
        self.assertEqual(perf.TrueNegative,None)
        # Two missing counts results in two false negatives (see 11327835)
        # and two less true positives
        perf = self._pc.calculate_extracted_mentions(\
            {'3476160': {PointMutation(87,'S','C'): 1,\
                        PointMutation(22,'T','C'): 1},\
             '14500716': {},\
             '12206666': {PointMutation(95,'D','A'): 4,\
                         PointMutation(95,'D','N'): 2,\
                         PointMutation(95,'D','E'): 2},\
             '11327835': {PointMutation(64,'H','A'): 2}})
        self.assertEqual(perf.TruePositive,12)
        self.assertEqual(perf.FalsePositive,0)
        self.assertEqual(perf.FalseNegative,2)
        self.assertEqual(perf.TrueNegative,None)

        # One extra mutation tallied as one FalsePositive 
        perf = self._pc.calculate_extracted_mentions(\
            {'3476160':{PointMutation(42,'L','Y'):1},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,0)
        self.assertEqual(perf.FalsePositive,1)
        self.assertEqual(perf.FalseNegative,14)
        self.assertEqual(perf.TrueNegative,None)
        # Two extra mutations tallied as two FalsePositives 
        perf = self._pc.calculate_extracted_mentions(\
            {'3476160':{PointMutation(42,'L','Y'):2},\
             '14500716':{},'12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,0)
        self.assertEqual(perf.FalsePositive,2)
        self.assertEqual(perf.FalseNegative,14)
        self.assertEqual(perf.TrueNegative,None)
        perf = self._pc.calculate_extracted_mentions(\
            {'3476160':{PointMutation(42,'L','Y'):1},\
             '14500716':{PointMutation(33,'P','T'):1},\
             '12206666':{},'11327835':{}})
        self.assertEqual(perf.TruePositive,0)
        self.assertEqual(perf.FalsePositive,2)
        self.assertEqual(perf.FalseNegative,14)
        self.assertEqual(perf.TrueNegative,None)
Beispiel #6
0
        self.assertEqual(parse_extraction_data(\
            self._fake_gold_standard_file_w_spans),self._gold_standard_data)

    

if __name__ == "__main__":

    fake_gold_standard_file = """3476160\tT22C\tS87C
        14500716
        12206666\tD95A\tD95A\tD95A\tD95E\tD95E\tD95A\tD95N\tD95N
        11327835\tH64A\tH64A\tH64A\tH64A"""

    fake_gold_standard_file_w_spans = \
        """3476160\tT22C:0,4\tS87C:9,15
        14500716
        12206666\tD95A:4,12\tD95A:22,33\tD95A:44,55\tD95E:55,66\tD95E:0,4\tD95A:99,100\tD95N:1000,1006\tD95N:99,104
        11327835\tH64A:66,72\tH64A:42,45\tH64A:6,9999\tH64A:88,99"""


    gold_standard_data = {\
            '3476160': {PointMutation(87,'S','C'): 1,\
                        PointMutation(22,'T','C'): 1},\
            '14500716': {},\
            '12206666': {PointMutation(95,'D','A'): 4,\
                         PointMutation(95,'D','N'): 2,\
                         PointMutation(95,'D','E'): 2},\
            '11327835': {PointMutation(64,'H','A'): 4}\
            }

    main()
Beispiel #7
0
class PointMutationTests(TestCase):
    
    def setUp(self):

        self.mutation = PointMutation(42,'W','G')
        self.amino_acid_codes = dict([('GLY','G'),('ALA','A'),('LEU','L'),\
            ('MET','M'),('PHE','F'),('TRP','W'),('LYS','K'),('GLN','Q'),\
            ('GLU','E'),('SER','S'),('PRO','P'),('VAL','V'),('ILE','I'),\
            ('CYS','C'),('TYR','Y'),('HIS','H'),('ARG','R'),('ASN','N'),\
            ('ASP','D'),('THR','T'),('GLYCINE','G'),('ALANINE','A'),\
            ('XAA','X'),('GLX','Z'),('ASX','B'),\
            ('LEUCINE','L'),('METHIONINE','M'),('PHENYLALANINE','F'),\
            ('VALINE','V'),('ISOLEUCINE','I'),('TYROSINE','Y'),\
            ('TRYPTOPHAN','W'),('SERINE','S'),('PROLINE','P'),\
            ('THREONINE','T'),('CYSTEINE','C'),('ASPARAGINE','N'),\
            ('GLUTAMINE','Q'),('LYSINE','K'),('HISTIDINE','H'),\
            ('ARGININE','R'),('ASPARTATE','D'),('GLUTAMATE','E'),\
            ('ASPARTIC ACID','D'),('GLUTAMIC ACID','E'),\
            ('G','G'),('A','A'),('V','V'),('L','L'),('I','I'),('M','M'),\
            ('F','F'),('Y','Y'),('W','W'),('S','S'),('P','P'),('T','T'),\
            ('C','C'),('N','N'),('Q','Q'),('K','K'),('H','H'),('R','R'),\
            ('D','D'),('E','E')]) 

    def test_valid_init(self):
        """PointMutation: __init__ functions as expected (valid data)"""
        m = PointMutation(42,'A','C')
        self.assertEqual(m.Position,42)
        self.assertEqual(m.WtResidue,'A')
        self.assertEqual(m.MutResidue,'C') 
        
        m = PointMutation(42,'Ala','Cys')
        self.assertEqual(m.Position,42)
        self.assertEqual(m.WtResidue,'A')
        self.assertEqual(m.MutResidue,'C') 
        
        m = PointMutation(42,'ALA','CYS')
        self.assertEqual(m.Position,42)
        self.assertEqual(m.WtResidue,'A')
        self.assertEqual(m.MutResidue,'C') 
        
        m = PointMutation(42,'A','Cys')
        self.assertEqual(m.Position,42)
        self.assertEqual(m.WtResidue,'A')
        self.assertEqual(m.MutResidue,'C') 
        
        m = PointMutation('42','A','C')
        self.assertEqual(m.Position,42)
        self.assertEqual(m.WtResidue,'A')
        self.assertEqual(m.MutResidue,'C') 

    def test_hash(self):
        """PointMutation: hash functions as expected """
        self.assertEqual(hash(self.mutation), \
            hash(str(type(self.mutation)) + 'W42G'))

    def test_invalid_init(self):
        """PointMutation: __init__ functions as expected (invalid data)"""
        self.assertRaises(MutationError,PointMutation,'hello','A','C')
        self.assertRaises(MutationError,PointMutation,42,'O','C')
        self.assertRaises(MutationError,PointMutation,0,'A','C')
        self.assertRaises(MutationError,PointMutation,-42,'A','C')
        self.assertRaises(MutationError,PointMutation,42,'A','O')
        self.assertRaises(MutationError,PointMutation,42,'A','5')

    def test_str(self):
        """PointMutation: __str__ functions as expected """
        self.assertEqual(str(self.mutation),'W42G')

    def test_eq(self):
        """PointMutation: == functions as expected """
        self.assertEqual(self.mutation == PointMutation(42,'W','G'), True)
        self.assertEqual(self.mutation == PointMutation('42','W','G'), True)
        self.assertEqual(self.mutation == PointMutation(41,'W','G'), False)
        self.assertEqual(self.mutation == PointMutation(42,'Y','G'), False)
        self.assertEqual(self.mutation == PointMutation(42,'W','C'), False)
        
    def test_ne(self):
        """PointMutation: != functions as expected """
        self.assertEqual(self.mutation != PointMutation(42,'W','G'), False)
        self.assertEqual(self.mutation != PointMutation('42','W','G'), False)
        self.assertEqual(self.mutation != PointMutation(41,'W','G'), True)
        self.assertEqual(self.mutation != PointMutation(42,'Y','G'), True)
        self.assertEqual(self.mutation != PointMutation(42,'W','C'), True)

    def test_normalize_residue_identity(self):
        """PointMutation: normalize functions with valid input
        """ 
        # test normalizations from one-letter, three-letter, and full name
        # amino acid mentions to their one-letter codes
        # NOTE: the abbreviated and unabbreviated forms were manually entered
        # twice -- once in the mutation_finder.py file, and once in this
        # test file -- to test for errors which may have occurred during data
        # entry
        for test_input,expected_output in self.amino_acid_codes.items():
            self.assertEqual(self.mutation._normalize_residue_identity(\
                test_input),expected_output)
            # check for case-insensitivity
            self.assertEqual(self.mutation._normalize_residue_identity(\
                test_input.lower()),expected_output)

    def test_normalize_residue_identity_error_handling(self):
        """PointMutation: normalize functions with invalid input """
        # Try some bad values
        for test_input in ['','O','xxala','alaxx','asdasd','42']:
            self.assertRaises(MutationError,\
              self.mutation._normalize_residue_identity,test_input)
        # Try some bad types
        for test_input in [{},[],42,0.42]:
            self.assertRaises(MutationError,\
              self.mutation._normalize_residue_identity,test_input)
    def setUp(self):

        self.mutation = PointMutation(42, "W", "G")
        self.amino_acid_codes = dict(
            [
                ("GLY", "G"),
                ("ALA", "A"),
                ("LEU", "L"),
                ("MET", "M"),
                ("PHE", "F"),
                ("TRP", "W"),
                ("LYS", "K"),
                ("GLN", "Q"),
                ("GLU", "E"),
                ("SER", "S"),
                ("PRO", "P"),
                ("VAL", "V"),
                ("ILE", "I"),
                ("CYS", "C"),
                ("TYR", "Y"),
                ("HIS", "H"),
                ("ARG", "R"),
                ("ASN", "N"),
                ("ASP", "D"),
                ("THR", "T"),
                ("GLYCINE", "G"),
                ("ALANINE", "A"),
                ("XAA", "X"),
                ("GLX", "Z"),
                ("ASX", "B"),
                ("LEUCINE", "L"),
                ("METHIONINE", "M"),
                ("PHENYLALANINE", "F"),
                ("VALINE", "V"),
                ("ISOLEUCINE", "I"),
                ("TYROSINE", "Y"),
                ("TRYPTOPHAN", "W"),
                ("SERINE", "S"),
                ("PROLINE", "P"),
                ("THREONINE", "T"),
                ("CYSTEINE", "C"),
                ("ASPARAGINE", "N"),
                ("GLUTAMINE", "Q"),
                ("LYSINE", "K"),
                ("HISTIDINE", "H"),
                ("ARGININE", "R"),
                ("ASPARTATE", "D"),
                ("GLUTAMATE", "E"),
                ("ASPARTIC ACID", "D"),
                ("GLUTAMIC ACID", "E"),
                ("G", "G"),
                ("A", "A"),
                ("V", "V"),
                ("L", "L"),
                ("I", "I"),
                ("M", "M"),
                ("F", "F"),
                ("Y", "Y"),
                ("W", "W"),
                ("S", "S"),
                ("P", "P"),
                ("T", "T"),
                ("C", "C"),
                ("N", "N"),
                ("Q", "Q"),
                ("K", "K"),
                ("H", "H"),
                ("R", "R"),
                ("D", "D"),
                ("E", "E"),
            ]
        )
class PointMutationTests(TestCase):
    def setUp(self):

        self.mutation = PointMutation(42, "W", "G")
        self.amino_acid_codes = dict(
            [
                ("GLY", "G"),
                ("ALA", "A"),
                ("LEU", "L"),
                ("MET", "M"),
                ("PHE", "F"),
                ("TRP", "W"),
                ("LYS", "K"),
                ("GLN", "Q"),
                ("GLU", "E"),
                ("SER", "S"),
                ("PRO", "P"),
                ("VAL", "V"),
                ("ILE", "I"),
                ("CYS", "C"),
                ("TYR", "Y"),
                ("HIS", "H"),
                ("ARG", "R"),
                ("ASN", "N"),
                ("ASP", "D"),
                ("THR", "T"),
                ("GLYCINE", "G"),
                ("ALANINE", "A"),
                ("XAA", "X"),
                ("GLX", "Z"),
                ("ASX", "B"),
                ("LEUCINE", "L"),
                ("METHIONINE", "M"),
                ("PHENYLALANINE", "F"),
                ("VALINE", "V"),
                ("ISOLEUCINE", "I"),
                ("TYROSINE", "Y"),
                ("TRYPTOPHAN", "W"),
                ("SERINE", "S"),
                ("PROLINE", "P"),
                ("THREONINE", "T"),
                ("CYSTEINE", "C"),
                ("ASPARAGINE", "N"),
                ("GLUTAMINE", "Q"),
                ("LYSINE", "K"),
                ("HISTIDINE", "H"),
                ("ARGININE", "R"),
                ("ASPARTATE", "D"),
                ("GLUTAMATE", "E"),
                ("ASPARTIC ACID", "D"),
                ("GLUTAMIC ACID", "E"),
                ("G", "G"),
                ("A", "A"),
                ("V", "V"),
                ("L", "L"),
                ("I", "I"),
                ("M", "M"),
                ("F", "F"),
                ("Y", "Y"),
                ("W", "W"),
                ("S", "S"),
                ("P", "P"),
                ("T", "T"),
                ("C", "C"),
                ("N", "N"),
                ("Q", "Q"),
                ("K", "K"),
                ("H", "H"),
                ("R", "R"),
                ("D", "D"),
                ("E", "E"),
            ]
        )

    def test_valid_init(self):
        """PointMutation: __init__ functions as expected (valid data)"""
        m = PointMutation(42, "A", "C")
        self.assertEqual(m.Position, 42)
        self.assertEqual(m.WtResidue, "A")
        self.assertEqual(m.MutResidue, "C")

        m = PointMutation(42, "Ala", "Cys")
        self.assertEqual(m.Position, 42)
        self.assertEqual(m.WtResidue, "A")
        self.assertEqual(m.MutResidue, "C")

        m = PointMutation(42, "ALA", "CYS")
        self.assertEqual(m.Position, 42)
        self.assertEqual(m.WtResidue, "A")
        self.assertEqual(m.MutResidue, "C")

        m = PointMutation(42, "A", "Cys")
        self.assertEqual(m.Position, 42)
        self.assertEqual(m.WtResidue, "A")
        self.assertEqual(m.MutResidue, "C")

        m = PointMutation("42", "A", "C")
        self.assertEqual(m.Position, 42)
        self.assertEqual(m.WtResidue, "A")
        self.assertEqual(m.MutResidue, "C")

    def test_hash(self):
        """PointMutation: hash functions as expected """
        self.assertEqual(hash(self.mutation), hash(str(type(self.mutation)) + "W42G"))

    def test_invalid_init(self):
        """PointMutation: __init__ functions as expected (invalid data)"""
        self.assertRaises(MutationError, PointMutation, "hello", "A", "C")
        self.assertRaises(MutationError, PointMutation, 42, "O", "C")
        self.assertRaises(MutationError, PointMutation, 0, "A", "C")
        self.assertRaises(MutationError, PointMutation, -42, "A", "C")
        self.assertRaises(MutationError, PointMutation, 42, "A", "O")
        self.assertRaises(MutationError, PointMutation, 42, "A", "5")

    def test_str(self):
        """PointMutation: __str__ functions as expected """
        self.assertEqual(str(self.mutation), "W42G")

    def test_eq(self):
        """PointMutation: == functions as expected """
        self.assertEqual(self.mutation == PointMutation(42, "W", "G"), True)
        self.assertEqual(self.mutation == PointMutation("42", "W", "G"), True)
        self.assertEqual(self.mutation == PointMutation(41, "W", "G"), False)
        self.assertEqual(self.mutation == PointMutation(42, "Y", "G"), False)
        self.assertEqual(self.mutation == PointMutation(42, "W", "C"), False)

    def test_ne(self):
        """PointMutation: != functions as expected """
        self.assertEqual(self.mutation != PointMutation(42, "W", "G"), False)
        self.assertEqual(self.mutation != PointMutation("42", "W", "G"), False)
        self.assertEqual(self.mutation != PointMutation(41, "W", "G"), True)
        self.assertEqual(self.mutation != PointMutation(42, "Y", "G"), True)
        self.assertEqual(self.mutation != PointMutation(42, "W", "C"), True)

    def test_normalize_residue_identity(self):
        """PointMutation: normalize functions with valid input
        """
        # test normalizations from one-letter, three-letter, and full name
        # amino acid mentions to their one-letter codes
        # NOTE: the abbreviated and unabbreviated forms were manually entered
        # twice -- once in the mutation_finder.py file, and once in this
        # test file -- to test for errors which may have occurred during data
        # entry
        for test_input, expected_output in self.amino_acid_codes.items():
            self.assertEqual(self.mutation._normalize_residue_identity(test_input), expected_output)
            # check for case-insensitivity
            self.assertEqual(self.mutation._normalize_residue_identity(test_input.lower()), expected_output)

    def test_normalize_residue_identity_error_handling(self):
        """PointMutation: normalize functions with invalid input """
        # Try some bad values
        for test_input in ["", "O", "xxala", "alaxx", "asdasd", "42"]:
            self.assertRaises(MutationError, self.mutation._normalize_residue_identity, test_input)
        # Try some bad types
        for test_input in [{}, [], 42, 0.42]:
            self.assertRaises(MutationError, self.mutation._normalize_residue_identity, test_input)