Ejemplo n.º 1
0
class ModernaFragment5Tests(TestCase):
    """fragment attached at 3' end of model"""
    def setUp(self):
        self.m = RnaModel(data_type='file',
                          data=MINI_TEMPLATE,
                          seq=Sequence("GCGGAUUUALCUCAG"))
        self.s1 = ModernaStructure('file',
                                   SMALL_FRAGMENT,
                                   seq=Sequence("GCGG"))
        self.s2 = ModernaStructure('file',
                                   SMALL_FRAGMENT,
                                   seq=Sequence("GCGG"))

    def test_attributes(self):
        five = ModernaFragment5(self.s1, anchor5=self.m['15'])
        self.assertEqual(len(five.anchor_residues), 1)
        self.assertEqual(len(five.nonanchor_residues), 3)
        self.assertTrue(str(five))

    def test_add_on_3_end(self):
        """Model sequence should change accordingly."""
        five = ModernaFragment5(self.s1, anchor5=self.m['15'])
        self.m.insert_fragment(five)
        self.assertEqual(self.m.get_sequence(), Sequence("GCGGAUUUALCUCAGCGG"))
        self.assertTrue(five.rmsd <= 1.00)

    def test_add_on_3_end_replace(self):
        """Model sequence should change accordingly."""
        five_overwrite = ModernaFragment5(self.s2, anchor5=self.m['9'])
        self.m.insert_fragment(five_overwrite)
        self.assertEqual(self.m.get_sequence(), Sequence("GCGGAUUUACGG"))
        self.assertTrue(five_overwrite.rmsd <= 1.00, 0)
Ejemplo n.º 2
0
    def test_model_with_5p3p_ends(self):
        a = read_alignment('''> target
CAUGCGGAYYYALCUCAGGUA
> mini_template
---GCGGAUUUALCUCAG---
''')
        m = RnaModel(self.t, a)
        m.create_model()
        self.assertEqual(m.get_sequence(), Sequence('CAUGCGGAYYYALCUCAGGUA'))
Ejemplo n.º 3
0
 def test_gaps_in_target(self):
     """Moderna should model gaps in the target, too."""
     a = read_alignment(ALIGN_TARGET_GAP)
     m = RnaModel(self.t, a)
     m.apply_alignment()
     m.insert_all_fragments()
     self.assertEqual(
         m.get_sequence().seq_with_modifications.replace('_', ''),
         '..CUGACCU#P')
Ejemplo n.º 4
0
    def test_5p_extension(self):
        a = read_alignment("""> target
AAAAAAAAAAGCGGAUUUALCUCAG
> template
----------GCGGAUUUALCUCAG
        """)
        m = RnaModel(None, a, data_type='file', data=MINI_TEMPLATE)
        m.add_missing_5p()
        self.assertEqual(m.get_sequence(), a.target_seq)
Ejemplo n.º 5
0
class ModernaFragment3Tests(TestCase):
    def setUp(self):
        """
        fragment attached at 5' end of model.
        """
        self.m = RnaModel(data_type='file',
                          data=MINI_TEMPLATE,
                          seq=Sequence("GCGGAUUUALCUCAG"))
        self.s1 = ModernaStructure('file',
                                   SMALL_FRAGMENT,
                                   seq=Sequence("GCGG"))
        self.s2 = ModernaStructure('file',
                                   SMALL_FRAGMENT,
                                   seq=Sequence("GCGG"))

    def test_attributes(self):
        """Attributes of fragment are accessible."""
        three = ModernaFragment3(self.s1, anchor3=self.m['1'])
        self.assertEqual(len(three.anchor_residues), 1)
        self.assertEqual(len(three.nonanchor_residues), 3)
        self.assertTrue(str(three))

    def test_add_on_5_end(self):
        """Model sequence should change accordingly."""
        three = ModernaFragment3(self.s1, anchor3=self.m['1'])
        self.m.insert_fragment(three)
        self.assertEqual(self.m.get_sequence(), Sequence("GCGGCGGAUUUALCUCAG"))
        self.assertTrue(three.rmsd <= 1.00)

    def test_add_on_5_end_exact(self):
        """Model sequence should change accordingly."""
        # exactly fitting example replacing original residues.
        three_overwrite = ModernaFragment3(self.s2, anchor3=self.m['6'])
        self.m.insert_fragment(three_overwrite)
        self.assertEqual(self.m.get_sequence(), Sequence("GCGUUUALCUCAG"))
        self.assertTrue(three_overwrite.rmsd <= 1.00)

    def test_add_discontinuous(self):
        """Tries to add a helix to an end."""
        helix = ModernaStructure('file', 'test_data/rna_structures/helix.pdb')
        helix_frag = ModernaFragment3(helix, anchor3=self.m['1'], strict=False)
        self.m.insert_fragment(helix_frag)
        self.assertEqual(self.m.get_sequence(),
                         Sequence('CCGACCUUCGGCC_GGUGGCCGAAGGGCGGAUUUALCUCAG'))
Ejemplo n.º 6
0
 def test_create_model_with_gaps(self):
     """Should create the model automatically."""
     a = read_alignment(ALIGN_1B23_1QF6)
     t = Template(RNA_1B23, 'file', 'R')
     m = RnaModel(t, a)
     m.apply_alignment()
     m.insert_all_fragments()
     self.assertEqual(
         m.get_sequence().seq_with_modifications.replace('_', ''),
         'GCCGAUAUAGCUCAGDDGGDAGAGCAGCGCAUUCGUEAUGCGAAG7UCGUAGGTPCGACUCCUAUUAUCGGCACCA'
     )
Ejemplo n.º 7
0
    def test_model_with_hydro_template(self):
        """If the template contains hydrogens, modifications should be added."""
        t = Template(RNA_HYDRO, 'file', 'B')
        a = read_alignment("""> 3tra_A.pdb Z73314.1/2358-2429
UPA
> 1qru_B.pdb X55374.1/1-72
CAA
""")
        m = RnaModel(t, a)
        m.create_model()
        self.assertEqual(m.get_sequence(), Sequence('UPA'))
Ejemplo n.º 8
0
    def test_model_with_alignment_adjustment(self):
        """Introduces small corrections on alignment."""
        a = read_alignment("""> target
ACUGUGAYUA[UACCU#P-G
> template with small errors.
GCG7A----U.UAGCUCA_G
        """)
        t = Template(MINI_TEMPLATE, 'file')
        match_template_with_alignment(t, a)
        m = RnaModel(t, a)
        m.create_model()
        self.assertEqual(m.get_sequence(), Sequence("ACUGUGAYUA[UACCU#PG"))
Ejemplo n.º 9
0
    def test_number_gap(self):
        """Builds model with numbering gap in the template."""
        a = read_alignment("""> target
CCGACCUUCGGCCACCUGACAGUCCUGUGCGGGAAACCGCACAGGACUGUCAACCAGGUAAUAUAACCACCGGGAAACGGUGGUUAUAUUACCUGGUACGCCUUGACGUGGGGGAAACCCCACGUCAAGGCGUGGUGGCCGAAGGUCGG
> template
CCGACCUUCGGCCACCUGACAGUCCUGUGCGG----CCGCACAGGACUGUCAACCAGGUAAUAUAACCACCGG----CGGUGGUUAUAUUACCUGGUACGCCUUGACGUGGGG----CCCCACGUCAAGGCGUGGUGGCCGAAGGUCGG
""")
        t = Template(JMB_TEMPLATE, 'file')
        clean_structure(t)
        m = RnaModel(t, a)
        m.create_model()
        self.assertEqual(m.get_sequence().seq_without_breaks, a.target_seq)
Ejemplo n.º 10
0
    def test_doublegap_model(self):
        """Should create a model filling two gaps"""
        a = read_alignment('''> target
GGGAUAGUUCCAGABU#A
> template
GGGA-AG--CCAGABU#A
''')
        t = Template(DOUBLEGAP, 'file', 'A')
        m = RnaModel(t, a)
        m.apply_alignment()
        m.insert_all_fragments()
        m.fix_backbone()
        self.assertEqual(m.get_sequence(), Sequence('GGGAUAGUUCCAGABU#A'))
Ejemplo n.º 11
0
 def test_insert_eliminate(self):
     """Inserts a 2D fragment into a model."""
     helix = load_model(HELIX, 'A')
     helix = RnaModel(None, None, 'A', 'residues',
                      helix['1':'8'] + helix['73':'80'])
     mf = ModernaFragment2D(self.motif, \
                     anchor5=helix['7'], anchor3=helix['74'], \
                     anchor5_upper=helix['8'], anchor3_upper=helix['73'], \
                     frag5_upper=self.motif['196'], frag3_upper=self.motif['217'], \
                     new_sequence=Sequence('C'), \
                     model=helix)
     helix.insert_fragment(mf)
     self.assertEqual(helix.get_sequence(), Sequence('AAAAAAAA_UCUUUUUUU'))
     self.assertEqual(helix.get_secstruc(), '(((((((().)))))))')
Ejemplo n.º 12
0
    def test_oppositegap_model(self):
        """Should create a model with close gaps in the other respective sequence"""
        a = read_alignment('''> target
GGGAGAGCRUUAG-BU#A
> template
GGGAGAGCR--AGABU#A
''')
        t = Template(OPPOSITEGAP, 'file', 'A')
        m = RnaModel(t, a)
        m.apply_alignment()
        m.insert_all_fragments()
        self.assertEqual(
            m.get_sequence().seq_with_modifications.replace('_', ''),
            'GGGAGAGCRUUAGBU#A')
Ejemplo n.º 13
0
    def test_long_5p_extension(self):
        a = read_alignment("""> target
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCGGAUUUALCUCAG
> template
----------------------------------------GCGGAUUUALCUCAG
        """)
        # first number == 1 should not work
        m = RnaModel(None, a, data_type='file', data=MINI_TEMPLATE)
        self.assertRaises(RenumeratorError, m.add_missing_5p)
        # first number == 100 should work
        m = RnaModel(None, a, data_type='file', data=MINI_TEMPLATE)
        renumber_chain(m, 100)
        m.add_missing_5p()
        self.assertEqual(m.get_sequence(), a.target_seq)
class FragmentInserterTests(TestCase):
    """
    Tests for the FragmentInserter class
    """
    def setUp(self):
        self.m = RnaModel(data_type='file',data=MINI_TEMPLATE, seq=Sequence("GCGGAUUUALCUCAG"))
        self.s1 = ModernaStructure('file', SMALL_FRAGMENT, seq=Sequence("GCGG"))
        #self.s2 = ModernaStructure('file',SMALL_FRAGMENT, seq=Sequence("GCGG"))
        #self.s3 = ModernaStructure('file', MINI_TEMPLATE, seq=Sequence("GCGGAUUUALCUCAG"))

    def test_insert(self):
        """Inserts fragment into a model"""
        f1 = ModernaFragment53(self.s1, anchor5=self.m['10'],anchor3=self.m['13'])
        finsert = FragmentInserter()
        finsert.insert_fragment(f1, self.m)
        self.assertEqual(self.m.get_sequence(),Sequence("GCGGAUUUALCGCAG"))
Ejemplo n.º 15
0
 def test_fix_backbone_residues(self):
     """Accepts two residue numbers as parameters."""
     m = RnaModel(data_type='file', data=FIXABLE_BACKBONE)
     fix_backbone(m, '4', '5')
     self.assertEqual(m.get_sequence(), Sequence('ACUGUG'))
Ejemplo n.º 16
0
 def test_insert_indel_quality_1(self):
     """Insert a fragment without strand break"""
     t = Template('test_data/gaps/mini_1h4s_T_gap2.pdb', 'file', 'T')
     a = read_alignment('test_data/gaps/ali_gap2.fasta')
     m = RnaModel(t, a)
     self.assertEqual(m.get_sequence().seq_with_modifications.find('_'), -1)
Ejemplo n.º 17
0
class ModernaFragment53Tests(TestCase):
    """
    Checks basic functionality of the ModernaFragment class.
    """
    def setUp(self):
        self.m = RnaModel(data_type='file',
                          data=MINI_TEMPLATE,
                          seq=Sequence("GCGGAUUUALCUCAG"))
        self.s1 = ModernaStructure('file',
                                   SMALL_FRAGMENT,
                                   seq=Sequence("GCGG"))
        self.s2 = ModernaStructure('file',
                                   SMALL_FRAGMENT,
                                   seq=Sequence("GCGG"))
        self.s3 = ModernaStructure('file',
                                   MINI_TEMPLATE,
                                   seq=Sequence("GCGGAUUUALCUCAG"))

    def test_attributes(self):
        """object attributes are set up correctly."""
        f1 = ModernaFragment53(self.s1,
                               anchor5=self.m['10'],
                               anchor3=self.m['13'])
        self.assertEqual(len(f1.struc), 4)
        self.assertEqual(f1.anchor5.fixed_resi, self.m['10'])
        self.assertEqual(f1.anchor3.fixed_resi, self.m['13'])
        self.assertEqual(f1.struc.get_sequence(), Sequence("GCGG"))
        self.assertTrue(str(f1))
        # anchor residues
        self.assertEqual(len(f1.anchor_residues), 2)
        self.assertEqual(f1.anchor_residues[0].mobile_resi.identifier, '1')
        self.assertEqual(f1.anchor_residues[1].mobile_resi.identifier, '4')
        f1.prepare_anchor_residues()
        self.assertEqual(f1.anchor_residues[0].mobile_resi.identifier, '1')
        self.assertEqual(f1.anchor_residues[1].mobile_resi.identifier, '4')
        # non-anchors
        self.assertEqual(len(f1.nonanchor_residues), 2)
        # second example
        f2 = ModernaFragment53(self.s2,
                               anchor5=self.m['1'],
                               anchor3=self.m['4'],
                               new_sequence=Sequence('GL'))
        self.assertEqual(len(f2.struc), 4)
        self.assertEqual(f2.struc.get_sequence(), Sequence("GCGG"))
        self.assertEqual(f2.new_sequence, Sequence("GL"))

    def test_get_resi_to_remove(self):
        """Should return resi identifiers between anchors and of anchors itself."""
        f1 = ModernaFragment53(self.s1,
                               anchor5=self.m['10'],
                               anchor3=self.m['13'])
        result = f1.get_resi_to_remove(self.m)
        self.assertEqual(result, ['10', '11', '12', '13'])

    def test_renumber(self):
        """New numbering should start at anchor5, and then go through alphabet."""
        f1 = ModernaFragment53(self.s1,
                               anchor5=self.m['10'],
                               anchor3=self.m['13'])
        f1.prepare_anchor_residues()
        f1.renumber()
        self.assertEqual([r.identifier for r in self.s1],
                         ['10', '10A', '10B', '13'])
        # second example
        f2 = ModernaFragment53(self.s2,
                               anchor5=self.m['1'],
                               anchor3=self.m['4'],
                               new_sequence=Sequence('GL'))
        f2.prepare_anchor_residues()
        f2.renumber()
        self.assertEqual([r.identifier for r in self.s2],
                         ['1', '1A', '1B', '4'])

    def test_superimpose_fragment(self):
        """Should apply superimposition and return RMSD"""
        f1 = ModernaFragment53(self.s1,
                               anchor5=self.m['10'],
                               anchor3=self.m['13'])
        rmsd = f1.superimpose()
        self.assertAlmostEqual(rmsd, 1.0, 0)  # MM: ? 1.1253267913922658
        # second fragment should fit perfectly
        f2 = ModernaFragment53(self.s2,
                               anchor5=self.m['1'],
                               anchor3=self.m['4'],
                               new_sequence=Sequence('GL'))
        rmsd = f2.superimpose()
        self.assertAlmostEqual(rmsd, 0.00)

    def test_refine(self):
        """Should change both numbers and sequence, and superimpose."""
        f2 = ModernaFragment53(self.s2,
                               anchor5=self.m['1'],
                               anchor3=self.m['4'],
                               new_sequence=Sequence('GL'))
        f2.superimpose()
        f2.prepare_anchor_residues()
        f2.renumber()
        f2.apply_seq()
        numbers = [r.identifier for r in self.s2]
        self.assertEqual(numbers, ['1', '1A', '1B', '4'])
        self.assertEqual(self.s2.get_sequence(), Sequence('GGLG'))

    def test_clash(self):
        """Should not clash with a given piece of structure."""
        f1 = ModernaFragment53(self.s1,
                               anchor5=self.m['10'],
                               anchor3=self.m['13'])
        self.assertFalse(f1.has_clashes(self.m['8':'10']))
        f2 = ModernaFragment53(self.s2,
                               anchor5=self.m['1'],
                               anchor3=self.m['4'],
                               new_sequence=Sequence('GL'))
        self.assertTrue(f2.has_clashes(self.m['1':'4']))

    def test_create_long_fragment(self):
        """Fragments with 26+ residues should be OK."""
        t = load_template(RNA_1C0A, 'B')
        resis = t['5':'45']
        long_seq = Sequence("AUAUAUAUAUGCGCGCGCGCAUAUAUAUAUGCGCGCGCG")
        struc = ModernaStructure('residues', resis)
        frag = ModernaFragment53(struc,
                                 anchor5=t['5'],
                                 anchor3=t['45'],
                                 new_sequence=long_seq)
        frag.superimpose()
        frag.prepare_anchor_residues()
        frag.renumber()
        frag.apply_seq()
        self.assertEqual(struc.get_sequence(),
                         Sequence("CAUAUAUAUAUGCGCGCGCGCAUAUAUAUAUGCGCGCGCGG"))

    def test_add_numbering_letters(self):
        """Model numbers should change accordingly."""
        middle1 = ModernaFragment53(self.s1,
                                    anchor5=self.m['9'],
                                    anchor3=self.m['14'],
                                    keep=keep_nothing)
        middle1.prepare_anchor_residues()
        middle1.renumber(self.m)
        self.m.insert_fragment(middle1)
        numbers = [r.identifier for r in self.m]
        expected = [
            '1', '2', '3', '4', '5', '6', '7', '8', '9', '9A', '9B', '14', '15'
        ]
        self.assertEqual(numbers, expected)

    def test_add_keep_numbers(self):
        """Model numbers should change accordingly."""
        middle1 = ModernaFragment53(self.s1,
                                    anchor5=self.m['9'],
                                    anchor3=self.m['14'],
                                    keep=keep_first_last)
        middle1.prepare_anchor_residues()
        middle1.renumber(self.m)
        self.m.insert_fragment(middle1)
        numbers = [r.identifier for r in self.m]
        expected = [
            '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '13', '14', '15'
        ]
        self.assertEqual(numbers, expected)

    def test_add_continuous_exact(self):
        """Model sequence should change accordingly."""
        f2 = ModernaFragment53(self.s2,
                               anchor5=self.m['1'],
                               anchor3=self.m['4'],
                               new_sequence=Sequence('GL'))
        self.m.insert_fragment(f2)
        self.assertEqual(self.m.get_sequence(), Sequence("GGLGAUUUALCUCAG"))
        self.assertAlmostEqual(f2.rmsd, 0.000, 2)
Ejemplo n.º 18
0
 def test_create_model_with_unknown(self):
     """Alignment that contains unknown bases in the target."""
     a = read_alignment(MINI_ALIGNMENT_WITH_UNK)
     m = RnaModel(self.t, a)
     m.create_model()
     self.assertEqual(m.get_sequence(), Sequence('..CUGUQQUACCU#P'))
Ejemplo n.º 19
0
 def test_fix_backbone(self):
     """Fixes backbone breaks."""
     m = RnaModel(data_type='file', data=FIXABLE_BACKBONE)
     fix_backbone(m)
     self.assertEqual(m.get_sequence(), Sequence('ACUGUG'))
Ejemplo n.º 20
0
class ModelMinimization:
    """
    Main class for minimizing models
    """
    def __init__(self, options, temp_path):
        self.options = options
        # structure
        print 'Loading model from %s, chain %s'%(options.input_file, options.chain_name)
        self.model = load_model(options.input_file, options.chain_name)
        self.model_passive = None
        self.stem5,  self.stem3 = None, None
        self.sequence_before = self.model.get_sequence()
        self.model_resnumbers = []
        # parameters
        self.residues = None
        if options.residues:
            self.residues = options.residues.split('-')
        self.cycles = int(options.cycles)
        self.output_name = options.output_file
        self.modifications = []
        self.restraints = []
        self.mmtk_output_file = 'mmtk_output.pdb'
        self.temp_pdb_file = temp_path

    def model_to_tempfile(self):
        """writes model to temporary file."""
        self.model.write_pdb_file(self.temp_pdb_file)
        self.model = None

    def tempfile_to_model(self):
        """Reads model from temporary file."""
        self.model = load_model(self.temp_pdb_file, self.options.chain_name)

    def extract_region(self):
        self.model.renumber_chain()
        """Cuts out the residues for optimization and keeps the rest in memory."""
        if self.residues:
            print '\nExtracting the region to be optimized (%s-%s) from the model.'%(self.residues[0], self.residues[1])
            print '\t.. total residues in model                    : %4i'%len(self.model)
            self.model_passive = self.model.find_residues_not_in_range(self.residues[0], self.residues[1])
            print '\t.. residues not participating in optimization : %4i (+2 for superposition afterwards)'%(len(self.model_passive)-2)
            print '\t   '+','.join([r.identifier for r in self.model_passive])
            self.model = RnaModel(None, None, self.options.chain_name, 'residues', self.model[self.residues[0]:self.residues[1]])
            # memorize residue numbers because MMTK screws them
            self.model_resnumbers = [r.identifier for r in self.model]
            print '\t.. residues participating in optimization     : %4i'%len(self.model)
            print '\t   '+','.join([r.identifier for r in self.model])
            # keeps duplicate versions of the residues indicated by self.residues,
            # so they can be superimposed later
            self.stem5,  self.stem3 = self.model[self.residues[0]], self.model[self.residues[1]]
        else:
            self.struc_to_optimize = self.model

    def merge_region(self):
        """Merges the optimized residues with the memorized ones."""
        residues = [r for r in self.model]
        if self.model_passive:
            # apply old residue numbers
            print '\nRestoring original numeration in the optimized region.'
            for num, resi in zip(self.model_resnumbers, residues):
                #print resi, num
                #self.model.renumber_residue(resi.identifier, num)
                resi.change_number(num)
            self.model = ModernaStructure('residues',residues)
            # do the superposition
            print '\nSuperimposing the optimized part onto the rest of the model.'
            all_atoms = self.model.get_all_atoms()
            sup = ModernaSuperimposer(moved_atoms = all_atoms)
            sup.get_atoms([self.stem5, self.stem3], BACKBONE_ATOMS, 'fixed')
            resi5, resi3 = self.model[self.residues[0]], self.model[self.residues[1]]
            sup.get_atoms([resi5, resi3], BACKBONE_ATOMS, 'moved')
            sup.superimpose()

            # merge residues
            print '\nMerging the optimized part with the rest of the model.'
            resi = [r for r in self.model]
            for r in self.model_passive:
                if r.identifier not in self.residues:
                    resi.append(r)
            self.model = RnaModel(None, None, self.options.chain_name, 'residues', resi)


    def remove_modifications(self):
        """Memorizes modified nucleotides for later, and then removes them."""
        print '\nRemoving modified bases from the model.'
        for resi in self.model.get_modified_residues():
            resi=self.model[resi]
            modi = (resi.identifier, resi.long_abbrev)
            print '\t.. %s at position %s'%modi
            self.modifications.append(modi)
        self.model.remove_all_modifications()
        # check for O3 atoms
        for resi in self.model:
            if resi.child_dict.has_key(' O3P'):
                raise OptimizationError('O3P atoms cannot be handled by MMTK!')


    def change_atom_names(self, forth=False, back=False):
        """Replaces atom and residue names so that MMTK can iterpret them."""
        print '\nReplacing names in temporary PDB file (%s)'%((forth and 'ModeRNA->MMTK') or (back and 'MMTK->ModeRNA'))
        if forth: nameset = FORTH_SET
        elif back: nameset = BACK_SET
        else: raise OptimizationError("Invalid options for changing atom names.")
        # replace residue and atom names
        out = []
        for line in open(self.temp_pdb_file):
            if line.startswith('ATOM') or line.startswith('HETATM'):
                resiname = nameset.replace_residue_name(line[17:20])
                atomname = nameset.replace_atom_name(line[12:16])
                line = line[:12]+atomname+line[16:17]+resiname+line[20:]
            if len(line)>13 and line[13]!='H': # discard hydrogens
                out.append(line)
        open(self.temp_pdb_file, 'w').writelines(out)


    def create_restraints(self, chain):
        """If a residue range was specified, these residues are cut out, and """
        if self.residues:
            print '\t.. building restraints'
            first_resi = chain[0]
            last_resi = chain[-1]

            # distances between the two terminal residues
            dist_po = (self.stem5['P'] - self.stem3["O3'"])/10.0
            restraints = HarmonicDistanceRestraint(first_resi.phosphate.P, last_resi.sugar.O_3, dist_po, 10000.)
            dist_co = (self.stem5["O5'"] - self.stem3["O3'"])/10.0
            restraints += HarmonicDistanceRestraint(first_resi.sugar.O_5, last_resi.sugar.C_3, dist_co, 10000.)
            dist_cc = (self.stem5["C5'"] - self.stem3["C4'"])/10.0
            restraints += HarmonicDistanceRestraint(first_resi.sugar.C_5, last_resi.sugar.C_4, dist_cc, 10000.)

            # angles between the two terminal residues
            angle_cpo = calc_angle(self.stem5["C4'"].get_vector(), self.stem3["P"].get_vector(), self.stem3["O3'"].get_vector())
            #angle_cpo = calc_angle(self.stem3["P"].coord-self.stem5["C4'"].coord, self.stem3["P"].coord-self.stem3["O3'"].coord)
            restraints += HarmonicAngleRestraint(first_resi.sugar.C_4, last_resi.phosphate.P, last_resi.sugar.O_3, angle_cpo, 100000.)
            angle_pco1 = calc_angle(self.stem5["P"].get_vector(), self.stem3["C4'"].get_vector(), self.stem3["O3'"].get_vector())
            restraints += HarmonicAngleRestraint(first_resi.phosphate.P, last_resi.sugar.C_4, last_resi.sugar.O_3, angle_pco1, 10000.)
            angle_pco2 = calc_angle(self.stem5["P"].get_vector(), self.stem5["C4'"].get_vector(), self.stem3["O3'"].get_vector())
            restraints += HarmonicAngleRestraint(first_resi.phosphate.P, first_resi.sugar.C_4, last_resi.sugar.O_3, angle_pco2, 10000.)
            angle_pcc = calc_angle(self.stem5["P"].get_vector(), self.stem5["C4'"].get_vector(), self.stem3["C4'"].get_vector())
            restraints += HarmonicAngleRestraint(first_resi.phosphate.P, first_resi.sugar.C_4, last_resi.sugar.C_4, angle_pcc, 10000.)
            # torsion between the two terminal residues
            # THESE PRODUCE SEGMENTATION FAULTS - THE OTHERS MUST SUFFICE
            # restraints += HarmonicDihedralRestraint(first_resi.phosphate.P, first_resi.sugar.C_4, last_resi.phosphate.P, last_resi.sugar.C_4, 1.0, 10.)
            #restraints += HarmonicDihedralRestraint(first_resi.phosphate.P, first_resi.sugar.C_4, last_resi.sugar.C_4, last_resi.sugar.O_3, 0.0, 100000.)
            #restraints += HarmonicDihedralRestraint(first_resi.sugar.C_4, first_resi.sugar.O_3, last_resi.phosphate.P, last_resi.sugar.C_4, 0.0, 100000.)
            #restraints += HarmonicDihedralRestraint(first_resi.sugar.C_4, first_resi.sugar.O_3, last_resi.sugar.C_4, last_resi.sugar.O_3, 0.0, 100000.)

            return restraints

    def optimize(self):
        """Run the optimization with MMTK"""
        print '\n-------------------------------------------------------------------------------'
        print '\n MMTK Optimization starts...'

        print '\t.. building universe'
        configuration = PDBConfiguration(self.temp_pdb_file)
        # Construct the nucleotide chain object. This also constructs positions
        # for the missing hydrogens, using geometrical criteria.
        chain = configuration.createNucleotideChains()[0]
        universe = InfiniteUniverse()
        universe.addObject(chain)

        restraints = self.create_restraints(chain)

        # define force field
        print '\t.. setting up force field'
        if restraints:
            ff = Amber94ForceField() + restraints
        else:
            ff = Amber94ForceField()
        universe.setForceField(ff)

        # do the minimization
        print '\t.. starting minimization with %i cycles'%self.cycles
        minimizer = ConjugateGradientMinimizer(universe)
        minimizer(steps = self.cycles)
        # write the intermediate output
        print '\t.. writing MMTK output to %s'% self.temp_pdb_file
        if self.model_passive:
            print '\t   (please note that MMTK applies a different numeration of residues.\n\t    The original one will be restored in the final output).'
        universe.writeToFile(self.mmtk_output_file)
        open(self.temp_pdb_file, 'w').write(open(self.mmtk_output_file).read())
        print '\n-------------------------------------------------------------------------------'

    def add_modifications(self):
        """Restores modifications on the model."""
        print "\nAdding modifications back to the model:"
        for position, modif in self.modifications:
            print "\t.. adding %s in position %s"%(modif, position)
            self.model[position].add_modification(modif)
        # check if sequence stayed the same
        print '\nSequence before optimization'
        print self.sequence_before
        print 'Sequence after optimization'
        print self.model.get_sequence()

    def write_result(self):
        """Creates the output file."""
        print "\nWriting final output to: %s"%self.output_name
        self.model.write_pdb_file(self.output_name)
Ejemplo n.º 21
0
class CommandTests(TestCase):
    """
    Acceptance tests for all scripting commands in Moderna.

    The order of most function parameters follows the
        T.A.M. (template, alignment, model) paradigm:
        The first parameter of a function refers to the template
        or a part of a structure which is taken,
        the second to an alignment or residue name,
        the third to the model.
    """
    def setUp(self):
        self.a = read_alignment(MINI_ALIGNMENT)
        self.a2 = read_alignment(MINI_ALIGNMENT_WITH_UNK)
        self.t = Template(MINI_TEMPLATE, seq=Sequence("GCGGAUUUALCUCAG"))
        self.m = RnaModel()

    def tearDown(self):
        self.a = None
        self.a2 = None
        self.t = None
        self.m = None

    def count_atoms(self, filename):
        # counts atoms in a PDB file
        atoms = 0
        for l in open(filename):
            if l[:4] == 'ATOM': atoms += 1
        return atoms

    #----------------------------------------------------------
    def test_add_modification_in_model(self):
        """Add modification to a residue already in the model."""
        copy_single_residue(self.t['5'], self.m)
        add_modification(self.m['5'], 'm1G')
        self.assertEqual(self.m.get_sequence(), Sequence('K'))

    def test_add_modification_and_copy(self):
        """Add modification and copy to model."""
        add_modification(self.t['5'], 'm1G', self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('K'))

    #----------------------------------------------------------
    def test_add_all_modifications(self):
        """Add modifications from the alignment and copy."""
        add_all_modifications(self.t, self.a, self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('[_#P'))
        # KR: should the 'Y' in the loop be skipped because it is not there?
        # KR: should the residues be copied automatically?

    #----------------------------------------------------------
    def test_add_pair_to_base(self):
        """ """
        m = load_model(MINI_TEMPLATE)
        add_pair_to_base(m, '3', '20', Sequence('C'))
        self.assertEqual(m.get_sequence(), Sequence('GCGGAUUUALCUCAG_C'))
        self.assertEqual(m.get_secstruc(), '..(............)')

    #----------------------------------------------------------
    def test_apply_alignment(self):
        """Do everything except inserting indels."""
        apply_alignment(self.t, self.a, self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('ACUGUA[UACCU#PG'))

    #----------------------------------------------------------
    def test_apply_all_indels(self):
        """Do inserting indels only."""
        self.m.template = self.t
        copy_some_residues(self.t['1':'15'], self.m)
        apply_all_indels(self.a, self.m)
        fix_backbone(self.m)
        self.assertEqual(self.m.get_sequence(),
                         Sequence('GCGGUGAYUAUUALCUCAG'))

    def test_analyze_geometry(self):
        result = analyze_geometry(self.t)
        self.assertTrue(isinstance(result, GeometryAnalyzer))

    #----------------------------------------------------------
    def test_change_sequence(self):
        """Changes the entire sequence of a structure."""
        m = load_model(MINI_TEMPLATE)
        change_sequence(m, "AGCU!#7/PYLLAAA")
        self.assertEqual(m.get_sequence(), Sequence("AGCU!#7/PYLLAAA"))

    #----------------------------------------------------------
    def test_copy_identical_residues_default(self):
        """Copy all residues that are the same,including modifications."""
        copy_identical_residues(self.t, self.a, self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('C_G_UA_CU_G'))

    def test_copy_identical_residues_no_modif(self):
        """Copy all residues that are the same, excluding modifications."""
        copy_identical_residues(self.t, self.a, self.m, modifications=False)
        self.assertEqual(self.m.get_sequence(), Sequence('C_G_UA_CU_G'))

    #----------------------------------------------------------
    def test_copy_single_residue(self):
        """Copy residue from template."""
        copy_single_residue(self.t['5'], self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('A'))

    def test_copy_single_residue_number(self):
        """Copy residue, allow renumbering."""
        copy_single_residue(self.t['5'], self.m, '6')
        self.assertEqual(self.m.get_sequence(), Sequence('A'))
        self.assertEqual(self.m['6'].short_abbrev, 'A')

    def test_copy_single_residue_strict(self):
        """Copy residue, but strict option rejects ... ."""
        copy_single_residue(self.t['5'], self.m, strict=True)
        self.assertEqual(self.m.get_sequence(), Sequence('A'))
        # KR: What should the strict option do?

    #----------------------------------------------------------
    def test_copy_some_residues(self):
        """Copy more than one residue from template."""
        copy_some_residues([self.t['5'], self.t['7']], self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('A_U'))

    def test_copy_some_residues_range(self):
        """Copy more than one residue, allow range operator."""
        copy_some_residues(self.t['5':'8'], self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('AUUU'))

    def test_copy_some_residues_into_blank(self):
        """Should copy residues into an empty model without alignment"""
        t = load_template(RNA_1C0A, 'B')
        m = RnaModel()
        copy_some_residues(t['31':'35'] + t['38':'42'], m)
        self.assertEqual(len(m), 10)

    def test_copy_some_residues_number(self):
        """Copy more than one residue from template."""
        copy_some_residues([self.t['5'], self.t['7']], self.m, ['4', '7A'])
        self.assertEqual(self.m.get_sequence(), Sequence('A_U'))
        self.assertEqual(self.m['4'].short_abbrev, 'A')
        self.assertEqual(self.m['7A'].short_abbrev, 'U')

    def test_copy_some_residues_strict(self):
        """Copy more than one residue, but strict option rejects ..."""
        copy_some_residues(self.t['5':'8'], self.m, strict=True)
        self.assertEqual(self.m.get_sequence(), Sequence('AUUU'))

    #----------------------------------------------------------
    def test_create_fragment(self):
        """Loads a fragment."""
        f = create_fragment(HELIX, anchor5=self.t['3'], anchor3=self.t['9'])
        self.assertEqual(
            f.struc.get_sequence(),
            Sequence(
                'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU'
            ))

    #----------------------------------------------------------
    def test_create_model_empty(self):
        """No options result in an empty model."""
        m = create_model()
        self.assertEqual(m.get_sequence(), Sequence(''))

    def test_create_model_ali(self):
        """Apply the alignment and insert indels automatically."""
        m = create_model(self.t, self.a)
        self.assertEqual(m.get_sequence(), Sequence('ACUGUGAYUA[UACCU#PG'))

    def test_create_model_ali2(self):
        """Apply the alignment and insert indels automatically."""
        m = create_model(self.t, self.a2)
        self.assertEqual(m.get_sequence(), Sequence('..CUGUQQUACCU#P'))

    def test_create_model_ali_improve(self):
        """Correct small errors in the alignment automatically."""
        ali = read_alignment(MINI_ALIGNMENT_INACCURATE)
        m = create_model(self.t, ali)
        self.assertEqual(m.get_sequence(), Sequence('ACUGUA7UACCUAPG'))

    def test_create_model_incorrect(self):
        """Giving an improper template seq should raise an exception."""
        # should also create log message.
        a = read_alignment(DNA_ALIGNMENT)
        self.assertRaises(ModernaError, create_model, self.t, a)

    #----------------------------------------------------------
    def test_clean_structure(self):
        m = load_model(NASTY_PDB, 'A')
        result = clean_structure(m)
        self.assertTrue(result)
        self.assertFalse(re.search('Water residues present', str(result)))

    #----------------------------------------------------------
    def test_delete_residue(self):
        """Removes a single residue completely."""
        copy_some_residues(self.t['1':'4'], self.m)
        delete_residue('3', self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('GC_G'))

    #----------------------------------------------------------
    def test_examine_structure(self):
        m = load_model(NASTY_PDB, 'A')
        result = examine_structure(m)
        self.assertTrue(result)
        self.assertTrue(re.search('Water residues present', str(result)))

    #----------------------------------------------------------
    def test_exchange_single_base_default(self):
        """Exchange base already in the model."""
        copy_some_residues(self.t['6':'11'], self.m)
        exchange_single_base(self.m['7'], 'C')
        exchange_single_base(self.m['10'], 'A')
        self.assertEqual(self.m.get_sequence(), Sequence('UCUAAC'))

    def test_exchange_single_base_and_copy(self):
        """Exchange base and copy to the model."""
        exchange_single_base(self.t['7'], 'C', self.m)
        exchange_single_base(self.t['10'], 'A', self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('C_A'))

    #----------------------------------------------------------
    def test_exchange_some_bases_default(self):
        """Exchange some bases already in the model."""
        copy_some_residues(self.t['6':'11'], self.m)
        exchange_some_bases([self.m['7'], self.m['10']], 'CA')
        self.assertEqual(self.m.get_sequence(), Sequence('UCUAAC'))

    def test_exchange_some_bases_range(self):
        """Exchange some bases, apply range."""
        copy_some_residues(self.t['6':'11'], self.m)
        exchange_some_bases(self.m['7':'9'], 'CAG')
        self.assertEqual(self.m.get_sequence(), Sequence('UCAGLC'))

    def test_exchange_some_bases_and_copy(self):
        """Exchange some bases and copy from template."""
        exchange_some_bases(self.t['7':'9'], 'CGA', self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('CGA'))

    def test_exchange_some_bases_and_copy_list(self):
        """Exchange some bases and copy from template."""
        exchange_some_bases([self.t['7'], self.t['9']], 'CA', self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('C_A'))

    #----------------------------------------------------------
    def test_exchange_mismatches(self):
        """Exchanges all standard base mismatches and copies."""
        exchange_mismatches(self.t, self.a, self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('A_U_UA'))

    #----------------------------------------------------------
    def test_extend_helix(self):
        m = load_model(RNA_1EHZ, 'A')
        extend_helix(m, '3', '70', Sequence("AGUC_GACU"))
        self.assertEqual(
            m.get_sequence(),
            Sequence(
                'GCGAGUCGAUUUALCUCAGDDGGGAGAGCRCCAGABU#AAYAP?UGGAG7UC?UGUGTPCG"UCCACAGAAUUGACUCGCACCA'
            ))
        self.assertEqual(
            m.get_secstruc(),
            '(((((((((((..((((........)))).((((.........)))).....(((((.......))))))))))))))))....'
        )

    #----------------------------------------------------------
    def test_find_clashes(self):
        """Finds clashes."""
        clashes = find_clashes(self.t)
        self.assertFalse(clashes)

    def test_find_clashes_empty(self):
        """Finding clashes works with empty model."""
        clashes = find_clashes(self.m)
        self.assertFalse(clashes)

    def test_find_clashes_positive(self):
        """Finding clashes returns a list of clashing residue pairs."""
        m = load_model(CLASHING_STRUCTURE)
        clashes = find_clashes(m)
        self.assertTrue(clashes)
        # check return type
        self.assertEqual(len(clashes), 1)
        self.assertEqual(clashes[0][0].identifier, '3')
        self.assertEqual(clashes[0][1].identifier, '4')

    def test_find_clashes_list(self):
        """Finding clashes works with a list as input."""
        clashes = find_clashes([self.t['3'], self.t['6']])
        self.assertFalse(clashes)

    def test_find_clashes_two_structures(self):
        """Finding clashes works with residues from two structures."""
        copy_single_residue(self.t['3'], self.m)
        #clashes = find_clashes(self.t['1':'10']+ [self.m['3']])
        clashes = find_clashes([self.t['3'], self.m['3']])
        self.assertTrue(clashes)
        # check different expressions.
        clashes = find_clashes([self.t['3'], self.m['3']])
        self.assertTrue(clashes)

    def test_find_clashes_two_structures_negative(self):
        """Make sure that two distinct residues do not collide."""
        copy_single_residue(self.t['3'], self.m)
        clashes = find_clashes([self.t['7'], self.m['3']])
        self.assertFalse(clashes)

    #----------------------------------------------------------
    def test_find_modifications(self):
        """Finding modifications returns a dictionary."""
        mods = find_modifications(self.t)
        self.assertTrue('10' in mods)
        self.assertEqual(mods['10'].long_abbrev, 'm2G')
        # KR: Check return type with MM

    def test_find_modifications_empty(self):
        """Finding modifications returns a dictionary."""
        mods = find_modifications(self.m)
        self.assertEqual(mods, {})
        # KR: Check return type with MM

    def test_find_modifications_advanced(self):
        """
        Tests for the modification recognizer: take 1ehz,
        run the topology matcher on it, and compare the 
        results to a manually entered list of modifications.
        """
        # check the modifications in 1ehz
        ehz_modifications = (('10', 'L'), ('16', 'D'), ('17', 'D'),
                             ('26', 'R'), ('32', 'B'), ('34', '#'),
                             ('37', 'Y'), ('39', 'P'), ('40', '?'),
                             ('46', '7'), ('49', '?'), ('54', 'T'),
                             ('55', 'P'), ('58', '"'))
        t = load_template(RNA_1EHZ, 'A')
        modifications = find_modifications(t)
        self.assertEqual(len(modifications), len(ehz_modifications))
        keys = list(modifications.keys())
        keys.sort()
        for i in range(len(ehz_modifications)):
            self.assertEqual(keys[i], ehz_modifications[i][0])
            self.assertEqual(modifications[keys[i]].identifier,
                             ehz_modifications[i][0])
            self.assertEqual(modifications[keys[i]].short_abbrev,
                             ehz_modifications[i][1])

    #----------------------------------------------------------
    def test_fix_backbone(self):
        """Fixes backbone breaks."""
        m = RnaModel(data_type='file', data=FIXABLE_BACKBONE)
        fix_backbone(m)
        self.assertEqual(m.get_sequence(), Sequence('ACUGUG'))

    def test_fix_backbone_residues(self):
        """Accepts two residue numbers as parameters."""
        m = RnaModel(data_type='file', data=FIXABLE_BACKBONE)
        fix_backbone(m, '4', '5')
        self.assertEqual(m.get_sequence(), Sequence('ACUGUG'))

    #----------------------------------------------------------
    def test_find_fragment(self):
        m = load_model(RNA_HAIRPIN, 'D')
        candidates = find_fragment(m, '30', '40', Sequence("AGCUAGCU"))
        self.assertTrue(len(candidates) > 0)
        self.assertTrue(
            isinstance(candidates[0].fragment_instance, ModernaFragment))

    def test_find_fragment_secstruc(self):
        m = load_model(RNA_HAIRPIN, 'D')
        candidates = find_fragment(m,
                                   '30',
                                   '40',
                                   Sequence("AGCUAGCU"),
                                   secstruc='((....))')
        self.assertTrue(len(candidates) > 0)
        frag = candidates[0].fragment_instance
        finsert = FragmentInserter()
        finsert.prepare_fragment(frag, m)
        self.assertEqual(frag.struc.get_secstruc(), '(((....)))')

    def test_insert_fragment_cand(self):
        m = load_model(RNA_HAIRPIN, 'D')
        candidates = find_fragment(m, '30', '40', Sequence("AGCUAGCU"))
        insert_fragment(m, candidates[0])
        self.assertEqual(m.get_sequence(), Sequence("CUGAGCUAGCUC"))

    def test_insert_fragment_cand_secstruc(self):
        m = load_model(RNA_HAIRPIN, 'D')
        #TODO: try this example
        candidates = find_fragment(m,
                                   '30',
                                   '40',
                                   Sequence('ACCGCCCGGU'),
                                   20,
                                   secstruc='(((....)))')
        insert_fragment(m, candidates[0])
        self.assertEqual(m.get_sequence(), Sequence("CUGACCGCCCGGUC"))
        self.assertEqual(m.get_secstruc(), "..((((....))))")

    def test_insert_two_strand_fragment(self):
        m = load_model(RNA_HAIRPIN, 'D')
        insert_two_strand_fragment(m, '30', '40', '31', '39', '195', '219',
                                   '196', '217', BULGE_MOTIF)
        fix_backbone(m)
        self.assertEqual(m.get_sequence(), Sequence("CUGCCUQUC/CGGC"))
        self.assertEqual(m.get_secstruc(), "..((.......).)")

    #----------------------------------------------------------
    def test_get_base_pairs(self):
        result = get_base_pairs(self.t)
        self.assertEqual(str(result['8']), '[8 WH 14]')

    def test_get_sequence(self):
        """Returning the entire sequence of a structure object."""
        seq = get_sequence(self.t)
        self.assertEqual(seq, Sequence('GCGGAUUUALCUCAG'))
        #TODO: Add test for discontinuous and strangely numbered struc.

    def test_get_sequence_chain(self):
        """Template structures should return their own sequence."""
        t = load_template(MINI_TEMPLATE, MINI_TEMPLATE_CHAIN_NAME)
        seq = get_sequence(t)
        self.assertEqual(seq, Sequence("GCGGAUUUALCUCAG"))

    def test_get_secstruc(self):
        """Get secondary structure in dot-bracket format."""
        h = load_template(RNA_HAIRPIN, 'D')
        ss = get_secstruc(h)
        self.assertEqual(ss, "..((.......))")

    def test_get_stacking(self):
        result = get_stacking(self.t)
        self.assertEqual(len(result), 9)
        self.assertEqual(result[0], ('1', '2', '>>'))

    #----------------------------------------------------------
    def test_load_alignment(self):
        """Return alignment loaded from fasta file."""
        a = load_alignment(MINI_ALIGNMENT)
        self.assertTrue(isinstance(a, RNAAlignment))
        self.assertEqual(a.aligned_template_seq,
                         Sequence('GCGGA----UUUALCUCAG'))
        self.assertEqual(a.aligned_target_seq, Sequence('ACUGUGAYUA[UACCU#PG'))

    #----------------------------------------------------------
    def test_load_template(self):
        """Return template loaded from PDB file."""
        t = load_template(MINI_TEMPLATE)
        self.assertTrue(isinstance(t, Template))
        self.assertEqual(t.get_sequence(), Sequence('GCGGAUUUALCUCAG'))

    #----------------------------------------------------------
    def test_load_model(self):
        """Return model loaded from PDB file."""
        m = load_model(MINI_TEMPLATE)
        self.assertTrue(isinstance(m, RnaModel))
        self.assertEqual(m.get_sequence(), Sequence('GCGGAUUUALCUCAG'))

    #----------------------------------------------------------
    def test_match_template_with_alignment(self):
        """Check if template sequence and alignment match."""
        # positive example
        self.assertTrue(match_template_with_alignment(self.t, self.a))
        # negative example
        t = load_template(CLASHING_STRUCTURE)
        self.assertFalse(match_template_with_alignment(t, self.a))

    #----------------------------------------------------------
    def test_match_model_with_alignment(self):
        """Check if model sequence and alignment match."""
        # negative example
        m = create_model()
        self.assertFalse(match_alignment_with_model(self.a, m))
        # positive example
        m = create_model(self.t, self.a)
        self.assertTrue(match_alignment_with_model(self.a, m))

    #----------------------------------------------------------
    def test_rotate_chi(self):
        """Rotates chi angle of a single base."""
        copy_some_residues(self.t['3':'5'], self.m)
        coord_before = self.m['4']['C5'].coord
        rotate_chi(self.m['4'], 90)
        coord_after = self.m['4']['C5'].coord
        self.assertNotEqual(list(coord_after), list(coord_before))

    #----------------------------------------------------------
    def test_remove_all_modifications(self):
        """Removes all modifications from a structure."""
        copy_some_residues(self.t['1':'15'], self.m)
        remove_all_modifications(self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('GCGGAUUUAGCUCAG'))

    def test_remove_modifications_advanced(self):
        """
        Tests for modification removal: take 1ehz, 
        remove all modifications. Run the modification recognizer. Make 
        sure that no modifications are found, but the correct number 
        of normal bases instead.
        """
        m = load_model(MINI_TEMPLATE, MINI_TEMPLATE_CHAIN_NAME)
        remove_all_modifications(m)
        modifications = find_modifications(m)
        self.assertEqual(modifications, {})
        self.assertEqual(len(m), 15)

    #----------------------------------------------------------
    def test_remove_modification_default(self):
        """Removes a modification from the model."""
        copy_some_residues(self.t['1':'15'], self.m)
        remove_modification(self.m['10'])
        self.assertEqual(self.m.get_sequence(), Sequence('GCGGAUUUAGCUCAG'))

    def test_remove_modification_empty(self):
        """Raises Exception if base is not modified."""
        copy_some_residues(self.t['1':'15'], self.m)
        self.assertRaises(ModernaError, remove_modification, self.m['11'])

    def test_remove_modification_and_copy(self):
        """Removes a modification, copies to model."""
        remove_modification(self.t['10'], self.m)
        self.assertEqual(self.m.get_sequence(), Sequence('G'))

    #----------------------------------------------------------
    def test_remove_mismatching_modifications(self):
        """Removes modifications that are no matches in the alignment."""
        remove_mismatching_modifications(self.t, self.a, self.m)
        # KR: !!! maybe apply_mismatching_modifications is better because of copy.
        self.assertEqual(self.m.get_sequence(), Sequence('C'))
        # KR: could add more sophisticated example.

    #----------------------------------------------------------
    def test_renumber_chain(self):
        copy_some_residues(self.t['1':'15'], self.m)
        renumber_chain(self.m, '4')
        sumnum = sum([int(r.identifier) for r in self.m])
        self.assertEqual(sumnum, 165)

    #----------------------------------------------------------
    def test_shrink_helix(self):
        m = load_model(RNA_1EHZ, 'A')
        shrink_helix(m, '3', '70', '7', '66')
        self.assertEqual(
            m.get_sequence(),
            Sequence(
                'GCGUUALCUCAGDDGGGAGAGCRCCAGABU#AAYAP?UGGAG7UC?UGUGTPCG"UCCACAGACGCACCA'
            ))
        self.assertEqual(
            m.get_secstruc(),
            '((((..((((........)))).((((.........)))).....(((((.......)))))))))....'
        )

    #----------------------------------------------------------
    def test_write_model(self):
        """Creates a PDB file."""
        copy_some_residues(self.t['1':'5'], self.m)
        if os.access(OUTPUT, os.F_OK): os.remove(OUTPUT)
        write_model(self.m, OUTPUT)
        self.assertTrue(os.access(OUTPUT, os.F_OK))
        # re-read
        new = load_model(OUTPUT)
        self.assertEqual(new.get_sequence(), Sequence('GCGGA'))
        # test writing a template
        t = load_template(MINI_TEMPLATE)
        write_model(t, OUTPUT)
        new = load_model(OUTPUT)
        self.assertEqual(new.get_sequence(), Sequence('GCGGAUUUALCUCAG'))

    #----------------------------------------------------------
    def remove_frag_cand_files(self, testout):
        """Remove files with fragment candidates."""
        if os.access(testout, os.F_OK): os.remove(testout)
        if os.access(testout[:-4], os.F_OK):
            for fn in os.listdir(testout[:-4]):
                os.remove(testout[:-4] + os.sep + fn)
        else:
            os.mkdir(testout[:-4])

    def test_write_fragment_candidates(self):
        """Fragment candidate file should be created."""
        testout = 'test_data/test_output.pdb'
        self.remove_frag_cand_files(testout)
        copy_some_residues(self.t['1':'10'], self.m)
        candidates = find_fragment(self.m, '2', '8', Sequence('AGCU#'), 20)
        write_fragment_candidates(candidates, testout[:-4])
        self.assertTrue(os.access(testout[:-4], os.F_OK))

    #----------------------------------------------------------
    def test_write_fragment_candidates_contents(self):
        """Fragment candidate file should contain the right number of models."""
        testout = 'test_data/test_output.pdb'
        self.remove_frag_cand_files(testout)
        copy_some_residues(self.t['1':'10'], self.m)
        candidates = find_fragment(self.m, '2', '8', Sequence('AGCU#'), 7)
        write_fragment_candidates(candidates, testout[:-4])
        for i, fn in enumerate(os.listdir(testout[:-4])):
            if not fn.endswith('.pdb'): continue
            p = PDBParser()
            struc = p.get_structure('cand', testout[:-4] + os.sep + fn)
            self.assertEqual(len(struc.child_list), 1)
        self.assertEqual(i, 7)

    #----------------------------------------------------------
    def test_write_secstruc(self):
        """Creates a Vienna file."""
        if os.access(OUTPUT, os.F_OK): os.remove(OUTPUT)
        write_secstruc(self.t, OUTPUT)
        self.assertTrue(os.access(OUTPUT, os.F_OK))
        r = open(OUTPUT).readlines()
        self.assertTrue(re.search("\A>", r[0]))
        self.assertTrue(re.search("\AGCGGAUUUALCUCAG\n", r[1]))
        self.assertTrue(re.search("\A\.{15}\Z", r[2]))
        os.remove(OUTPUT)

    #----------------------------------------------------------

    #
    # SOME OTHER TESTS
    #
    def test_first_level(self):
        """only checks whether a pdb file was created."""
        t = load_template(MINI_TEMPLATE, MINI_TEMPLATE_CHAIN_NAME)
        a = load_alignment(MINI_ALIGNMENT)
        m = create_model(t, a)
        if os.access(OUTPUT, os.F_OK):
            os.remove(OUTPUT)
        write_model(m, OUTPUT)
        self.assertTrue(os.access(OUTPUT, os.F_OK))
        os.unlink(OUTPUT)

    def test_add_custom_fragment(self):
        """Fragments loaded from a file should be inserted."""
        t = load_template(RNA_1C0A, 'B')
        m = create_model()
        copy_some_residues(t['31':'35'] + t['38':'42'], m)
        f = create_fragment(FRAGMENT1,
                            anchor5=m['35'],
                            anchor3=m['38'],
                            chain_name='A',
                            sequence=None)
        m.insert_fragment(f)
        self.assertTrue(m['35A'] and m['35B'])

    #----------------------------------------------------------
    def test_read_write(self):
        """
        Tests for file processing:take 1ehz and 2-3 other PDB files. 
        Write it to a file. Read it again. Check that the structure contains 
        the right number of atoms, and that the added residues are in 
        the right position.
        """
        m = load_model(RNA_1EHZ)
        atoms_before = self.count_atoms(RNA_1EHZ)
        if os.access(OUTPUT, os.F_OK): os.remove(OUTPUT)
        write_model(m, OUTPUT)
        self.assertTrue(os.access(OUTPUT, os.F_OK))
        atoms_after = self.count_atoms(OUTPUT)
        self.assertEqual(atoms_after, atoms_before)
        os.unlink(OUTPUT)

    def test_build_model_2bte_B(self):
        """ Tests building model for 2j00_W on template 2bte_B.pdb"""
        ali_string = """> 2j00_W.pdb CP000026.1/4316393-4316321
GC-C--C--G---G--A-------U----A---G---C---U-C--AGU--------CGGU----------A-GA-G--C-------A----G---G-G----G-A--------U----------U-----G--------A-----------A----------A------------A-------------U---C--C--C-CGU--------------------------------------------------G--UC-C-U--U---G-G--U---U-C-G-----AU-----------U-----C---C--G---A---G--------U--C---C--G--G-GCA-CCA
> 2bte_B.pdb 
GC-C--G--G---G--G-------U----G---G---C---G-G--A-AU-------GGGU----------A-GACG--C-------G----C---A-U----G-A--------C_---------A-----U--------C-----------A----------U------------G-------------U---G--C--G-CAA--------------------------------------------------G-CGU-G-C--G---G-G--U---U-C-A-----AG-----------U-----C---C--C---G---C--------C--C---C--C--G-GCA-CCA"""
        ali = read_alignment(ali_string)
        t = load_template(RNA_2BTE, 'B')
        m = create_model(t, ali, 'B')

    def test_build_model_1exd_B(self):
        """Tests building model for 2tra_A on template 1exd_B.pdb"""
        ali_string = """> 2tra_A
UC-C--G--U---G--A-------U----A---G---U---U-P--AAD---------GGD---------CA-GA-A--U-------G----G---G-C----G-C--------P----------U-----G--------U-----------C----------K------------C-------------G---U--G--C-CAG--------------------------------------------------A---U-?-G--G---G-G--T   ---P-C-A-----AU-----------U-----C---C--C---C---G--------U--C---G--C--G-GAG-C--
> 1ehd_B.pdb 
-G-G--G--G---U--A-------U----C---G---C---C-A--AGC---------GGU----------A-AG-G--C-------A----C---C-G----G-A--------U----------U-----C--------U-----------G----------A------------U-------------U---C--C--G-G-A--------------------------------------------------G--GU-C-G--A---G-G--U   ---U-C-G-----AA-----------U-----C---C--U---C---G--------U--A---C--C--C-CAG-CCA"""
        ali = read_alignment(ali_string)
        t = load_template(RNA_1EXD, 'B')
        m = create_model(t, ali, 'B')

    def test_build_model_1efw_D(self):
        """ Tests building model for 1ehz_A on template 1efw_D. Should work even when 50 fragment candidates are checked"""
        ali_string = """> 1ehz_A.pdb M14856.1/1-73
GC-G--G--A---U--U-------U----A---L---C---U-C--AGD--------DGGG----------A-GA-G--C-------R----C---C-A----G-A--------B----------U-----#--------A-----------A----------Y------------A-------------P---?--U--G-GAG--------------------------------------------------7--UC-?-U--G---U-G--T   ---P-C-G-----"U-----------C-----C---A--C---A---G--------A--A---U--U--C-GCA-CCA
> 1efw_D.pdb
GG-A--G--C---G--G-------4----A---G---U---U-C--AGD--------CGGD---------DA-GA-A--U-------A----C---C-U----G-C--------C----------U-----Q--------U-----------C----------/------------C-------------G---C--A--G-GGG--------------------------------------------------7--UC-G-C--G---G-G--018U---P-C-G-----AG-----------U-----C---C--C---G---P--------C--C---G--U--U-CC-----"""
        ali = read_alignment(ali_string)
        t = load_template(RNA_1EFW, 'D')
        m = create_model(t, ali, 'D')
        if os.access(OUTPUT, os.F_OK): os.remove(OUTPUT)
        write_model(m, OUTPUT)
        self.assertTrue(os.access(OUTPUT, os.F_OK))