Back to index

python-biopython  1.60
test_PDB.py
Go to the documentation of this file.
00001 # Copyright 2009 by Eric Talevich.  All rights reserved.
00002 # Revisions copyright 2009-2010 by Peter Cock.  All rights reserved.
00003 #
00004 # Converted by Eric Talevich from an older unit test copyright 2002
00005 # by Thomas Hamelryck.
00006 # 
00007 # This code is part of the Biopython distribution and governed by its
00008 # license. Please see the LICENSE file that should have been included
00009 # as part of this package.
00010 
00011 """Unit tests for the Bio.PDB module."""
00012 import os
00013 import tempfile
00014 import unittest
00015 import warnings
00016 from StringIO import StringIO
00017 
00018 try:
00019     import numpy
00020     from numpy import dot #Missing on PyPy's micronumpy
00021     del dot
00022 except ImportError:
00023     from Bio import MissingPythonDependencyError
00024     raise MissingPythonDependencyError(
00025         "Install NumPy if you want to use Bio.PDB.")
00026 
00027 from Bio.Seq import Seq
00028 from Bio.Alphabet import generic_protein
00029 from Bio.PDB import PDBParser, PPBuilder, CaPPBuilder, PDBIO
00030 from Bio.PDB import HSExposureCA, HSExposureCB, ExposureCN
00031 from Bio.PDB.PDBExceptions import PDBConstructionException, PDBConstructionWarning
00032 from Bio.PDB import rotmat, Vector
00033 
00034 # NB: the 'A_' prefix ensures this test case is run first
00035 class A_ExceptionTest(unittest.TestCase):
00036     """Errors and warnings while parsing of flawed PDB files.
00037 
00038     These tests must be executed because of the way Python's warnings module
00039     works -- a warning is only logged the first time it is encountered.
00040     """
00041     def test_1_warnings(self):
00042         """Check warnings: Parse a flawed PDB file in permissive mode.
00043 
00044         NB: The try/finally block is adapted from the warnings.catch_warnings
00045         context manager in the Python 2.6 standard library.
00046         """
00047         warnings.simplefilter('always', PDBConstructionWarning)
00048         try:
00049             # Equivalent to warnings.catch_warnings -- hackmagic
00050             orig_showwarning = warnings.showwarning
00051             all_warns = []
00052             def showwarning(*args, **kwargs):
00053                 all_warns.append(args[0])
00054             warnings.showwarning = showwarning
00055             # Trigger warnings
00056             p = PDBParser(PERMISSIVE=True)
00057             p.get_structure("example", "PDB/a_structure.pdb")
00058             self.assertEqual(len(all_warns), 14)
00059             for wrn, msg in zip(all_warns, [
00060                 # Expected warning messages:
00061                 "Used element 'N' for Atom (name=N) with given element ''",
00062                 "Used element 'C' for Atom (name=CA) with given element ''",
00063                 "Atom names ' CA ' and 'CA  ' differ only in spaces at line 17.",
00064                 "Used element 'CA' for Atom (name=CA  ) with given element ''",
00065                 'Atom N defined twice in residue <Residue ARG het=  resseq=2 icode= > at line 21.',
00066                 'disordered atom found with blank altloc before line 33.',
00067                 "Residue (' ', 4, ' ') redefined at line 43.",
00068                 "Blank altlocs in duplicate residue SER (' ', 4, ' ') at line 43.",
00069                 "Residue (' ', 10, ' ') redefined at line 75.",
00070                 "Residue (' ', 14, ' ') redefined at line 106.",
00071                 "Residue (' ', 16, ' ') redefined at line 135.",
00072                 "Residue (' ', 80, ' ') redefined at line 633.",
00073                 "Residue (' ', 81, ' ') redefined at line 646.",
00074                 'Atom O defined twice in residue <Residue HOH het=W resseq=67 icode= > at line 822.'
00075                 ]):
00076                 self.assertTrue(msg in str(wrn), str(wrn))
00077         finally:
00078             warnings.showwarning = orig_showwarning
00079 
00080     def test_2_strict(self):
00081         """Check error: Parse a flawed PDB file in strict mode."""
00082         warnings.simplefilter('ignore', PDBConstructionWarning)
00083         try:
00084             parser = PDBParser(PERMISSIVE=False)
00085             self.assertRaises(PDBConstructionException,
00086                    parser.get_structure, "example", "PDB/a_structure.pdb")
00087         finally:
00088             warnings.filters.pop()
00089      
00090     def test_3_bad_xyz(self):
00091         """Check error: Parse an entry with bad x,y,z value."""
00092         data = "ATOM      9  N   ASP A 152      21.554  34.953  27.691  1.00 19.26           N\n"
00093         parser = PDBParser(PERMISSIVE=False)
00094         s = parser.get_structure("example", StringIO(data))
00095         data = "ATOM      9  N   ASP A 152      21.ish  34.953  27.691  1.00 19.26           N\n"
00096         self.assertRaises(PDBConstructionException,
00097                 parser.get_structure, "example", StringIO(data))       
00098 
00099 
00100 class HeaderTests(unittest.TestCase):
00101     """Tests for parse_pdb_header."""
00102 
00103     def test_capsid(self):
00104         """Parse the header of a known PDB file (1A8O)."""
00105         parser = PDBParser()
00106         struct = parser.get_structure('1A8O', 'PDB/1A8O.pdb')
00107         self.assertAlmostEqual(struct.header['resolution'], 1.7)
00108         # Case-insensitive string comparisons
00109         known_strings = {
00110                 'author': 'T.R.Gamble,S.Yoo,F.F.Vajdos,U.K.Von Schwedler,D.K.Worthylake,H.Wang,J.P.Mccutcheon,W.I.Sundquist,C.P.Hill',
00111                 'deposition_date': '1998-03-27',
00112                 'head': 'viral protein',
00113                 'journal': 'AUTH   T.R.GAMBLE,S.YOO,F.F.VAJDOS,U.K.VON SCHWEDLER,AUTH 2 D.K.WORTHYLAKE,H.WANG,J.P.MCCUTCHEON,W.I.SUNDQUIST,AUTH 3 C.P.HILLTITL   STRUCTURE OF THE CARBOXYL-TERMINAL DIMERIZATIONTITL 2 DOMAIN OF THE HIV-1 CAPSID PROTEIN.REF    SCIENCE                       V. 278   849 1997REFN                   ISSN 0036-8075PMID   9346481DOI    10.1126/SCIENCE.278.5339.849',
00114                 'journal_reference': 't.r.gamble,s.yoo,f.f.vajdos,u.k.von schwedler, d.k.worthylake,h.wang,j.p.mccutcheon,w.i.sundquist, c.p.hill structure of the carboxyl-terminal dimerization domain of the hiv-1 capsid protein. science v. 278 849 1997 issn 0036-8075 9346481 10.1126/science.278.5339.849 ',
00115                 'keywords': 'capsid, core protein, hiv, c-terminal domain, viral protein',
00116                 'name': ' hiv capsid c-terminal domain',
00117                 'release_date': '1998-10-14',
00118                 'structure_method': 'x-ray diffraction',
00119                 }
00120         for key, expect in known_strings.iteritems():
00121             self.assertEqual(struct.header[key].lower(), expect.lower())
00122 
00123     def test_fibril(self):
00124         """Parse the header of another PDB file (2BEG)."""
00125         parser = PDBParser()
00126         struct = parser.get_structure('2BEG', 'PDB/2BEG.pdb')
00127         known_strings = {
00128                 'author': 'T.Luhrs,C.Ritter,M.Adrian,D.Riek-Loher,B.Bohrmann,H.Dobeli,D.Schubert,R.Riek',
00129                 'deposition_date': '2005-10-24',
00130                 'head': 'protein fibril',
00131                 'journal': "AUTH   T.LUHRS,C.RITTER,M.ADRIAN,D.RIEK-LOHER,B.BOHRMANN,AUTH 2 H.DOBELI,D.SCHUBERT,R.RIEKTITL   3D STRUCTURE OF ALZHEIMER'S AMYLOID-{BETA}(1-42)TITL 2 FIBRILS.REF    PROC.NATL.ACAD.SCI.USA        V. 102 17342 2005REFN                   ISSN 0027-8424PMID   16293696DOI    10.1073/PNAS.0506723102",
00132                 'journal_reference': "t.luhrs,c.ritter,m.adrian,d.riek-loher,b.bohrmann, h.dobeli,d.schubert,r.riek 3d structure of alzheimer's amyloid-{beta}(1-42) fibrils. proc.natl.acad.sci.usa v. 102 17342 2005 issn 0027-8424 16293696 10.1073/pnas.0506723102 ",
00133                 'keywords': "alzheimer's, fibril, protofilament, beta-sandwich, quenched hydrogen/deuterium exchange, pairwise mutagenesis, protein fibril",
00134                 'name': " 3d structure of alzheimer's abeta(1-42) fibrils",
00135                 'release_date': '2005-11-22',
00136                 'structure_method': 'solution nmr',
00137                 }
00138         for key, expect in known_strings.iteritems():
00139             self.assertEqual(struct.header[key].lower(), expect.lower())
00140 
00141 
00142 class ParseTest(unittest.TestCase):
00143     def setUp(self):
00144         warnings.simplefilter('ignore', PDBConstructionWarning)
00145         p = PDBParser(PERMISSIVE=1)
00146         self.structure = p.get_structure("example", "PDB/a_structure.pdb")
00147         warnings.filters.pop()
00148 
00149     def test_c_n(self):
00150         """Extract polypeptides using C-N."""
00151         ppbuild = PPBuilder()
00152         polypeptides = ppbuild.build_peptides(self.structure[1])
00153         self.assertEqual(len(polypeptides), 1)
00154         pp = polypeptides[0]
00155         # Check the start and end positions
00156         self.assertEqual(pp[0].get_id()[1], 2)
00157         self.assertEqual(pp[-1].get_id()[1], 86)
00158         # Check the sequence
00159         s = pp.get_sequence()
00160         self.assertTrue(isinstance(s, Seq))
00161         self.assertEqual(s.alphabet, generic_protein)
00162         self.assertEqual("RCGSQGGGSTCPGLRCCSIWGWCGDSEPYCGRTCENKCWSGER"
00163                          "SDHRCGAAVGNPPCGQDRCCSVHGWCGGGNDYCSGGNCQYRC",
00164                          str(s))
00165 
00166     def test_ca_ca(self):
00167         """Extract polypeptides using CA-CA."""
00168         ppbuild = CaPPBuilder()
00169         polypeptides = ppbuild.build_peptides(self.structure[1])
00170         self.assertEqual(len(polypeptides), 1)
00171         pp = polypeptides[0]
00172         # Check the start and end positions
00173         self.assertEqual(pp[0].get_id()[1], 2)
00174         self.assertEqual(pp[-1].get_id()[1], 86)
00175         # Check the sequence
00176         s = pp.get_sequence()
00177         self.assertTrue(isinstance(s, Seq))
00178         self.assertEqual(s.alphabet, generic_protein)
00179         self.assertEqual("RCGSQGGGSTCPGLRCCSIWGWCGDSEPYCGRTCENKCWSGER"
00180                          "SDHRCGAAVGNPPCGQDRCCSVHGWCGGGNDYCSGGNCQYRC",
00181                          str(s))
00182 
00183     def test_structure(self):
00184         """Verify the structure of the parsed example PDB file."""
00185         # Structure contains 2 models
00186         self.assertEqual(len(self.structure), 2)
00187         # --- Checking model 0 ---
00188         m0 = self.structure[0]
00189         # Model 0 contains 1 chain
00190         self.assertEqual(len(m0), 1)
00191         # Chain 'A' contains 1 residue
00192         self.assertEqual(len(m0['A']), 1)
00193         # Residue ('H_PCA', 1, ' ') contains 8 atoms.
00194         residue = m0['A'].get_list()[0]
00195         self.assertEqual(residue.get_id(), ('H_PCA', 1, ' '))
00196         self.assertEqual(len(residue), 9)
00197         # --- Checking model 1 ---
00198         m1 = self.structure[1]
00199         # Model 1 contains 3 chains
00200         self.assertEqual(len(m1), 3)
00201         # Deconstruct this data structure to check each chain
00202         chain_data = [ # chain_id, chain_len, [(residue_id, residue_len), ...]
00203             ('A', 86, [ ((' ', 0, ' '), 1 ),
00204                         ((' ', 2, ' '), 11),
00205                         ((' ', 3, ' '), 6, 1), # disordered
00206                         ((' ', 4, ' '), 4 ),
00207                         ((' ', 5, ' '), 6 ),
00208                         ((' ', 6, ' '), 9 ),
00209                         ((' ', 7, ' '), 4 ),
00210                         ((' ', 8, ' '), 4 ),
00211                         ((' ', 9, ' '), 4 ),
00212                         ((' ', 10, ' '), 6, ['GLY', 'SER']), # point mut
00213                         ((' ', 11, ' '), 7 ),
00214                         ((' ', 12, ' '), 6 ),
00215                         ((' ', 13, ' '), 7 ),
00216                         ((' ', 14, ' '), 4, ['ALA', 'GLY']), # point mut
00217                         ((' ', 15, ' '), 8, 3), # disordered
00218                         ((' ', 16, ' '), 11, ['ARG', 'TRP']), # point mut
00219                         ((' ', 17, ' '), 6 ),
00220                         ((' ', 18, ' '), 6 ),
00221                         ((' ', 19, ' '), 6 ),
00222                         ((' ', 20, ' '), 8 ),
00223                         ((' ', 21, ' '), 14),
00224                         ((' ', 22, ' '), 4 ),
00225                         ((' ', 23, ' '), 14),
00226                         ((' ', 24, ' '), 6 ),
00227                         ((' ', 25, ' '), 4 ),
00228                         ((' ', 26, ' '), 8 ),
00229                         ((' ', 27, ' '), 6 ),
00230                         ((' ', 28, ' '), 9, 5), # disordered
00231                         ((' ', 29, ' '), 7 ),
00232                         ((' ', 30, ' '), 12),
00233                         ((' ', 31, ' '), 6 ),
00234                         ((' ', 32, ' '), 4 ),
00235                         ((' ', 33, ' '), 11),
00236                         ((' ', 34, ' '), 7 ),
00237                         ((' ', 35, ' '), 6 ),
00238                         ((' ', 36, ' '), 9 ),
00239                         ((' ', 37, ' '), 8 ),
00240                         ((' ', 38, ' '), 9 ),
00241                         ((' ', 39, ' '), 6 ),
00242                         ((' ', 40, ' '), 14),
00243                         ((' ', 41, ' '), 6 ),
00244                         ((' ', 42, ' '), 4 ),
00245                         ((' ', 43, ' '), 9 ),
00246                         ((' ', 44, ' '), 11),
00247                         ((' ', 45, ' '), 6, 1), # disordered
00248                         ((' ', 46, ' '), 8 ),
00249                         ((' ', 47, ' '), 10),
00250                         ((' ', 48, ' '), 11),
00251                         ((' ', 49, ' '), 6 ),
00252                         ((' ', 50, ' '), 4 ),
00253                         ((' ', 51, ' '), 5 ),
00254                         ((' ', 52, ' '), 5 ),
00255                         ((' ', 53, ' '), 7 ),
00256                         ((' ', 54, ' '), 4 ),
00257                         ((' ', 55, ' '), 8 ),
00258                         ((' ', 56, ' '), 7 ),
00259                         ((' ', 57, ' '), 7 ),
00260                         ((' ', 58, ' '), 6 ),
00261                         ((' ', 59, ' '), 4 ),
00262                         ((' ', 60, ' '), 9 ),
00263                         ((' ', 61, ' '), 8 ),
00264                         ((' ', 62, ' '), 11),
00265                         ((' ', 63, ' '), 6 ),
00266                         ((' ', 64, ' '), 6 ),
00267                         ((' ', 65, ' '), 6 ),
00268                         ((' ', 66, ' '), 7 ),
00269                         ((' ', 67, ' '), 10),
00270                         ((' ', 68, ' '), 4 ),
00271                         ((' ', 69, ' '), 14),
00272                         ((' ', 70, ' '), 6 ),
00273                         ((' ', 71, ' '), 4 ),
00274                         ((' ', 72, ' '), 4 ),
00275                         ((' ', 73, ' '), 4 ),
00276                         ((' ', 74, ' '), 8, 3), # disordered
00277                         ((' ', 75, ' '), 8 ),
00278                         ((' ', 76, ' '), 12),
00279                         ((' ', 77, ' '), 6 ),
00280                         ((' ', 78, ' '), 6 ),
00281                         ((' ', 79, ' '), 4, 4), # disordered
00282                         ((' ', 80, ' '), 4, ['GLY', 'SER']), # point mut
00283                         ((' ', 81, ' '), 8, ['ASN', 'LYS']), # point mut
00284                         ((' ', 82, ' '), 6 ),
00285                         ((' ', 83, ' '), 9 ),
00286                         ((' ', 84, ' '), 12),
00287                         ((' ', 85, ' '), 11),
00288                         ((' ', 86, ' '), 6 ),
00289                         ]),
00290             ('B', 4, [ (('H_NAG', 1, ' '), 14),
00291                         (('H_NAG', 2, ' '), 14),
00292                         (('H_NAG', 3, ' '), 14),
00293                         (('H_NAG', 4, ' '), 14),
00294                         ]),
00295             (' ', 76, [ (('W', 1, ' '), 1),
00296                         (('W', 2, ' '), 1),
00297                         (('W', 3, ' '), 1),
00298                         (('W', 4, ' '), 1),
00299                         (('W', 5, ' '), 1),
00300                         (('W', 6, ' '), 1),
00301                         (('W', 7, ' '), 1),
00302                         (('W', 8, ' '), 1),
00303                         (('W', 9, ' '), 1),
00304                         (('W', 10, ' '), 1),
00305                         (('W', 11, ' '), 1),
00306                         (('W', 12, ' '), 1),
00307                         (('W', 13, ' '), 1),
00308                         (('W', 14, ' '), 1),
00309                         (('W', 15, ' '), 1),
00310                         (('W', 16, ' '), 1),
00311                         (('W', 17, ' '), 1),
00312                         (('W', 18, ' '), 1),
00313                         (('W', 19, ' '), 1),
00314                         (('W', 20, ' '), 1),
00315                         (('W', 21, ' '), 1),
00316                         (('W', 22, ' '), 1),
00317                         (('W', 23, ' '), 1),
00318                         (('W', 24, ' '), 1),
00319                         (('W', 25, ' '), 1),
00320                         (('W', 26, ' '), 1),
00321                         (('W', 27, ' '), 1),
00322                         (('W', 28, ' '), 1),
00323                         (('W', 29, ' '), 1),
00324                         (('W', 30, ' '), 1),
00325                         (('W', 31, ' '), 1),
00326                         (('W', 32, ' '), 1),
00327                         (('W', 33, ' '), 1),
00328                         (('W', 34, ' '), 1),
00329                         (('W', 35, ' '), 1),
00330                         (('W', 36, ' '), 1),
00331                         (('W', 37, ' '), 1),
00332                         (('W', 38, ' '), 1),
00333                         (('W', 39, ' '), 1),
00334                         (('W', 40, ' '), 1),
00335                         (('W', 41, ' '), 1),
00336                         (('W', 42, ' '), 1),
00337                         (('W', 43, ' '), 1),
00338                         (('W', 44, ' '), 1),
00339                         (('W', 45, ' '), 1),
00340                         (('W', 46, ' '), 1),
00341                         (('W', 47, ' '), 1),
00342                         (('W', 48, ' '), 1),
00343                         (('W', 49, ' '), 1),
00344                         (('W', 50, ' '), 1),
00345                         (('W', 51, ' '), 1),
00346                         (('W', 52, ' '), 1),
00347                         (('W', 53, ' '), 1),
00348                         (('W', 54, ' '), 1),
00349                         (('W', 55, ' '), 1),
00350                         (('W', 56, ' '), 1),
00351                         (('W', 57, ' '), 1),
00352                         (('W', 58, ' '), 1),
00353                         (('W', 59, ' '), 1),
00354                         (('W', 60, ' '), 1),
00355                         (('W', 61, ' '), 1),
00356                         (('W', 62, ' '), 1),
00357                         (('W', 63, ' '), 1),
00358                         (('W', 64, ' '), 1),
00359                         (('W', 65, ' '), 1),
00360                         (('W', 66, ' '), 1),
00361                         (('W', 67, ' '), 1),
00362                         (('W', 68, ' '), 1),
00363                         (('W', 69, ' '), 1),
00364                         (('W', 70, ' '), 1),
00365                         (('W', 71, ' '), 1),
00366                         (('W', 72, ' '), 1),
00367                         (('W', 73, ' '), 1),
00368                         (('W', 74, ' '), 1),
00369                         (('W', 75, ' '), 1),
00370                         (('W', 77, ' '), 1),
00371                         ])
00372                         ]
00373  
00374         for c_idx, chn in enumerate(chain_data):
00375             # Check chain ID and length
00376             chain = m1.get_list()[c_idx]
00377             self.assertEqual(chain.get_id(), chn[0])
00378             self.assertEqual(len(chain), chn[1])
00379             for r_idx, res in enumerate(chn[2]):
00380                 residue = chain.get_list()[r_idx]
00381                 # Check residue ID and atom count
00382                 self.assertEqual(residue.get_id(), res[0])
00383                 self.assertEqual(len(residue), res[1])
00384                 disorder_lvl = residue.is_disordered()
00385                 if disorder_lvl == 1:
00386                     # Check the number of disordered atoms
00387                     disordered_count = sum(1 for atom in residue
00388                                            if atom.is_disordered())
00389                     if disordered_count:
00390                         self.assertEqual(disordered_count, res[2])
00391                 elif disorder_lvl == 2:
00392                     # Point mutation -- check residue names
00393                     self.assertEqual(residue.disordered_get_id_list(), res[2])
00394 
00395     def test_details(self):
00396         """Verify details of the parsed example PDB file."""
00397         structure = self.structure
00398         self.assertEqual(len(structure), 2)
00399 
00400         #First model
00401         model = structure[0]
00402         self.assertEqual(model.id, 0)
00403         self.assertEqual(model.level, "M")
00404         self.assertEqual(len(model), 1)
00405         chain = model["A"]
00406         self.assertEqual(chain.id, "A")
00407         self.assertEqual(chain.level, "C")
00408         self.assertEqual(len(chain), 1)
00409         self.assertEqual(" ".join(residue.resname for residue in chain), "PCA")
00410         self.assertEqual(" ".join(atom.name for atom in chain.get_atoms()),
00411                          "N CA CB CG CD OE C O CA  ")
00412         self.assertEqual(" ".join(atom.element for atom in chain.get_atoms()),
00413                          "N C C C C O C O CA")
00414         #Second model
00415         model = structure[1]
00416         self.assertEqual(model.id, 1)
00417         self.assertEqual(model.level, "M")
00418         self.assertEqual(len(model), 3)
00419         chain = model["A"]
00420         self.assertEqual(chain.id, "A")
00421         self.assertEqual(chain.level, "C")
00422         self.assertEqual(len(chain), 86)
00423         self.assertEqual(" ".join(residue.resname for residue in chain),
00424                          "CYS ARG CYS GLY SER GLN GLY GLY GLY SER THR CYS "
00425                          "PRO GLY LEU ARG CYS CYS SER ILE TRP GLY TRP CYS "
00426                          "GLY ASP SER GLU PRO TYR CYS GLY ARG THR CYS GLU "
00427                          "ASN LYS CYS TRP SER GLY GLU ARG SER ASP HIS ARG "
00428                          "CYS GLY ALA ALA VAL GLY ASN PRO PRO CYS GLY GLN "
00429                          "ASP ARG CYS CYS SER VAL HIS GLY TRP CYS GLY GLY "
00430                          "GLY ASN ASP TYR CYS SER GLY GLY ASN CYS GLN TYR "
00431                          "ARG CYS")
00432         self.assertEqual(" ".join(atom.name for atom in chain.get_atoms()),
00433                          "C N CA C O CB CG CD NE CZ NH1 NH2 N CA C O CB SG "
00434                          "N CA C O N CA C O CB OG N CA C O CB CG CD OE1 NE2 "
00435                          "N CA C O N CA C O N CA C O N CA C O CB OG N CA C "
00436                          "O CB OG1 CG2 N CA C O CB SG N CA C O CB CG CD N "
00437                          "CA C O N CA C O CB CG CD1 CD2 N CA C O CB CG CD NE "
00438                          "CZ NH1 NH2 N CA C O CB SG N CA C O CB SG N CA C O "
00439                          "CB OG N CA C O CB CG1 CG2 CD1 N CA C O CB CG CD1 "
00440                          "CD2 NE1 CE2 CE3 CZ2 CZ3 CH2 N CA C O N CA C O CB "
00441                          "CG CD1 CD2 NE1 CE2 CE3 CZ2 CZ3 CH2 N CA C O CB SG "
00442                          "N CA C O N CA C O CB CG OD1 OD2 N CA C O CB OG N "
00443                          "CA C O CB CG CD OE1 OE2 N CA C O CB CG CD N CA C O "
00444                          "CB CG CD1 CD2 CE1 CE2 CZ OH N CA C O CB SG N CA C "
00445                          "O N CA C O CB CG CD NE CZ NH1 NH2 N CA C O CB OG1 "
00446                          "CG2 N CA C O CB SG N CA C O CB CG CD OE1 OE2 N CA "
00447                          "C O CB CG OD1 ND2 N CA C O CB CG CD CE NZ N CA C O "
00448                          "CB SG N CA C O CB CG CD1 CD2 NE1 CE2 CE3 CZ2 CZ3 "
00449                          "CH2 N CA C O CB OG N CA C O N CA C O CB CG CD OE1 "
00450                          "OE2 N CA C O CB CG CD NE CZ NH1 NH2 N CA C O CB OG "
00451                          "N CA C O CB CG OD1 OD2 N CA C O CB CG ND1 CD2 CE1 "
00452                          "NE2 N CA C O CB CG CD NE CZ NH1 NH2 N CA C O CB SG "
00453                          "N CA C O N CA C O CB N CA C O CB N CA C O CB CG1 "
00454                          "CG2 N CA C O N CA C O CB CG OD1 ND2 N CA C O CB CG "
00455                          "CD N CA C O CB CG CD N CA C O CB SG N CA C O N CA "
00456                          "C O CB CG CD OE1 NE2 N CA C O CB CG OD1 OD2 N CA C "
00457                          "O CB CG CD NE CZ NH1 NH2 N CA C O CB SG N CA C O "
00458                          "CB SG N CA C O CB OG N CA C O CB CG1 CG2 N CA C O "
00459                          "CB CG ND1 CD2 CE1 NE2 N CA C O N CA C O CB CG CD1 "
00460                          "CD2 NE1 CE2 CE3 CZ2 CZ3 CH2 N CA C O CB SG N CA C "
00461                          "O N CA C O N CA C O N CA C O CB CG OD1 ND2 N CA C O "
00462                          "CB CG OD1 OD2 N CA C O CB CG CD1 CD2 CE1 CE2 CZ OH "
00463                          "N CA C O CB SG N CA C O CB OG N CA C O N CA C O N "
00464                          "CA C O CB CG OD1 ND2 N CA C O CB SG N CA C O CB CG "
00465                          "CD OE1 NE2 N CA C O CB CG CD1 CD2 CE1 CE2 CZ OH N "
00466                          "CA C O CB CG CD NE CZ NH1 NH2 N CA C O CB SG")
00467         self.assertEqual(" ".join(atom.element for atom in chain.get_atoms()),
00468                          "C N C C O C C C N C N N N C C O C S N C C O N C C O "
00469                          "C O N C C O C C C O N N C C O N C C O N C C O N C C "
00470                          "O C O N C C O C O C N C C O C S N C C O C C C N C C "
00471                          "O N C C O C C C C N C C O C C C N C N N N C C O C S "
00472                          "N C C O C S N C C O C O N C C O C C C C N C C O C C "
00473                          "C C N C C C C C N C C O N C C O C C C C N C C C C C "
00474                          "N C C O C S N C C O N C C O C C O O N C C O C O N C "
00475                          "C O C C C O O N C C O C C C N C C O C C C C C C C O "
00476                          "N C C O C S N C C O N C C O C C C N C N N N C C O C "
00477                          "O C N C C O C S N C C O C C C O O N C C O C C O N N "
00478                          "C C O C C C C N N C C O C S N C C O C C C C N C C C "
00479                          "C C N C C O C O N C C O N C C O C C C O O N C C O C "
00480                          "C C N C N N N C C O C O N C C O C C O O N C C O C C "
00481                          "N C C N N C C O C C C N C N N N C C O C S N C C O N "
00482                          "C C O C N C C O C N C C O C C C N C C O N C C O C C "
00483                          "O N N C C O C C C N C C O C C C N C C O C S N C C O "
00484                          "N C C O C C C O N N C C O C C O O N C C O C C C N C "
00485                          "N N N C C O C S N C C O C S N C C O C O N C C O C C "
00486                          "C N C C O C C N C C N N C C O N C C O C C C C N C C "
00487                          "C C C N C C O C S N C C O N C C O N C C O N C C O C "
00488                          "C O N N C C O C C O O N C C O C C C C C C C O N C C "
00489                          "O C S N C C O C O N C C O N C C O N C C O C C O N N "
00490                          "C C O C S N C C O C C C O N N C C O C C C C C C C O "
00491                          "N C C O C C C N C N N N C C O C S")
00492 
00493 
00494 class ParseReal(unittest.TestCase):
00495     """Testing with real PDB files."""
00496 
00497     def test_empty(self):
00498         """Parse an empty file."""
00499         parser = PDBParser()
00500         filenumber, filename = tempfile.mkstemp()
00501         os.close(filenumber)
00502         try:
00503             struct = parser.get_structure('MT', filename)
00504             # Structure has no children (models)
00505             self.assertFalse(len(struct))
00506         finally:
00507             os.remove(filename)
00508 
00509     def test_c_n(self):
00510         """Extract polypeptides from 1A80."""
00511         parser = PDBParser(PERMISSIVE=False)
00512         structure = parser.get_structure("example", "PDB/1A8O.pdb")
00513         self.assertEqual(len(structure), 1)
00514         for ppbuild in [PPBuilder(), CaPPBuilder()]:
00515             #==========================================================
00516             #First try allowing non-standard amino acids,
00517             polypeptides = ppbuild.build_peptides(structure[0], False)
00518             self.assertEqual(len(polypeptides), 1)
00519             pp = polypeptides[0]
00520             # Check the start and end positions
00521             self.assertEqual(pp[0].get_id()[1], 151)
00522             self.assertEqual(pp[-1].get_id()[1], 220)
00523             # Check the sequence
00524             s = pp.get_sequence()
00525             self.assertTrue(isinstance(s, Seq))
00526             self.assertEqual(s.alphabet, generic_protein)
00527             #Here non-standard MSE are shown as M
00528             self.assertEqual("MDIRQGPKEPFRDYVDRFYKTLRAEQASQEVKNWMTETLLVQ"
00529                              "NANPDCKTILKALGPGATLEEMMTACQG", str(s))
00530             #==========================================================
00531             #Now try strict version with only standard amino acids
00532             #Should ignore MSE 151 at start, and then break the chain
00533             #at MSE 185, and MSE 214,215
00534             polypeptides = ppbuild.build_peptides(structure[0], True)
00535             self.assertEqual(len(polypeptides), 3)
00536             #First fragment
00537             pp = polypeptides[0]
00538             self.assertEqual(pp[0].get_id()[1], 152)
00539             self.assertEqual(pp[-1].get_id()[1], 184)
00540             s = pp.get_sequence()
00541             self.assertTrue(isinstance(s, Seq))
00542             self.assertEqual(s.alphabet, generic_protein)
00543             self.assertEqual("DIRQGPKEPFRDYVDRFYKTLRAEQASQEVKNW", str(s))
00544             #Second fragment
00545             pp = polypeptides[1]
00546             self.assertEqual(pp[0].get_id()[1], 186)
00547             self.assertEqual(pp[-1].get_id()[1], 213)
00548             s = pp.get_sequence()
00549             self.assertTrue(isinstance(s, Seq))
00550             self.assertEqual(s.alphabet, generic_protein)
00551             self.assertEqual("TETLLVQNANPDCKTILKALGPGATLEE", str(s))
00552             #Third fragment
00553             pp = polypeptides[2]
00554             self.assertEqual(pp[0].get_id()[1], 216)
00555             self.assertEqual(pp[-1].get_id()[1], 220)
00556             s = pp.get_sequence()
00557             self.assertTrue(isinstance(s, Seq))
00558             self.assertEqual(s.alphabet, generic_protein)
00559             self.assertEqual("TACQG", str(s))
00560 
00561     def test_strict(self):
00562         """Parse 1A8O.pdb file in strict mode."""
00563         parser = PDBParser(PERMISSIVE=False)
00564         structure = parser.get_structure("example", "PDB/1A8O.pdb")
00565         self.assertEqual(len(structure), 1)
00566         model = structure[0]
00567         self.assertEqual(model.id, 0)
00568         self.assertEqual(model.level, "M")
00569         self.assertEqual(len(model), 1)
00570         chain = model["A"]
00571         self.assertEqual(chain.id, "A")
00572         self.assertEqual(chain.level, "C")
00573         self.assertEqual(len(chain), 158)
00574         self.assertEqual(" ".join(residue.resname for residue in chain),
00575                          "MSE ASP ILE ARG GLN GLY PRO LYS GLU PRO PHE ARG "
00576                          "ASP TYR VAL ASP ARG PHE TYR LYS THR LEU ARG ALA "
00577                          "GLU GLN ALA SER GLN GLU VAL LYS ASN TRP MSE THR "
00578                          "GLU THR LEU LEU VAL GLN ASN ALA ASN PRO ASP CYS "
00579                          "LYS THR ILE LEU LYS ALA LEU GLY PRO GLY ALA THR "
00580                          "LEU GLU GLU MSE MSE THR ALA CYS GLN GLY HOH HOH "
00581                          "HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH "
00582                          "HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH "
00583                          "HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH "
00584                          "HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH "
00585                          "HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH "
00586                          "HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH "
00587                          "HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH HOH "
00588                          "HOH HOH")
00589         self.assertEqual(" ".join(atom.name for atom in chain.get_atoms()),
00590                          "N CA C O CB CG SE CE N CA C O CB CG OD1 OD2 N CA "
00591                          "C O CB CG1 CG2 CD1 N CA C O CB CG CD NE CZ NH1 "
00592                          "NH2 N CA C O CB CG CD OE1 NE2 N CA C O N CA C O "
00593                          "CB CG CD N CA C O CB CG CD CE NZ N CA C O CB CG "
00594                          "CD OE1 OE2 N CA C O CB CG CD N CA C O CB CG CD1 "
00595                          "CD2 CE1 CE2 CZ N CA C O CB CG CD NE CZ NH1 NH2 N "
00596                          "CA C O CB CG OD1 OD2 N CA C O CB CG CD1 CD2 CE1 "
00597                          "CE2 CZ OH N CA C O CB CG1 CG2 N CA C O CB CG OD1 "
00598                          "OD2 N CA C O CB CG CD NE CZ NH1 NH2 N CA C O CB "
00599                          "CG CD1 CD2 CE1 CE2 CZ N CA C O CB CG CD1 CD2 CE1 "
00600                          "CE2 CZ OH N CA C O CB CG CD CE NZ N CA C O CB "
00601                          "OG1 CG2 N CA C O CB CG CD1 CD2 N CA C O CB CG CD "
00602                          "NE CZ NH1 NH2 N CA C O CB N CA C O CB CG CD OE1 "
00603                          "OE2 N CA C O CB CG CD OE1 NE2 N CA C O CB N CA C "
00604                          "O CB OG N CA C O CB CG CD OE1 NE2 N CA C O CB CG "
00605                          "CD OE1 OE2 N CA C O CB CG1 CG2 N CA C O CB CG CD "
00606                          "CE NZ N CA C O CB CG OD1 ND2 N CA C O CB CG CD1 "
00607                          "CD2 NE1 CE2 CE3 CZ2 CZ3 CH2 N CA C O CB CG SE CE "
00608                          "N CA C O CB OG1 CG2 N CA C O CB CG CD OE1 OE2 N "
00609                          "CA C O CB OG1 CG2 N CA C O CB CG CD1 CD2 N CA C "
00610                          "O CB CG CD1 CD2 N CA C O CB CG1 CG2 N CA C O CB "
00611                          "CG CD OE1 NE2 N CA C O CB CG OD1 ND2 N CA C O CB "
00612                          "N CA C O CB CG OD1 ND2 N CA C O CB CG CD N CA C "
00613                          "O CB CG OD1 OD2 N CA C O CB SG N CA C O CB CG CD "
00614                          "CE NZ N CA C O CB OG1 CG2 N CA C O CB CG1 CG2 "
00615                          "CD1 N CA C O CB CG CD1 CD2 N CA C O CB CG CD CE "
00616                          "NZ N CA C O CB N CA C O CB CG CD1 CD2 N CA C O N "
00617                          "CA C O CB CG CD N CA C O N CA C O CB N CA C O CB "
00618                          "OG1 CG2 N CA C O CB CG CD1 CD2 N CA C O CB CG CD "
00619                          "OE1 OE2 N CA C O CB CG CD OE1 OE2 N CA C O CB CG "
00620                          "SE CE N CA C O CB CG SE CE N CA C O CB OG1 CG2 N "
00621                          "CA C O CB N CA C O CB SG N CA C O CB CG CD OE1 "
00622                          "NE2 N CA C O OXT O O O O O O O O O O O O O O O O "
00623                          "O O O O O O O O O O O O O O O O O O O O O O O O "
00624                          "O O O O O O O O O O O O O O O O O O O O O O O O "
00625                          "O O O O O O O O O O O O O O O O O O O O O O O O")
00626         self.assertEqual(" ".join(atom.element for atom in chain.get_atoms()),
00627                          "N C C O C C SE C N C C O C C O O N C C O C C C C "
00628                          "N C C O C C C N C N N N C C O C C C O N N C C O "
00629                          "N C C O C C C N C C O C C C C N N C C O C C C O "
00630                          "O N C C O C C C N C C O C C C C C C C N C C O C "
00631                          "C C N C N N N C C O C C O O N C C O C C C C C C "
00632                          "C O N C C O C C C N C C O C C O O N C C O C C C "
00633                          "N C N N N C C O C C C C C C C N C C O C C C C C "
00634                          "C C O N C C O C C C C N N C C O C O C N C C O C "
00635                          "C C C N C C O C C C N C N N N C C O C N C C O C "
00636                          "C C O O N C C O C C C O N N C C O C N C C O C O "
00637                          "N C C O C C C O N N C C O C C C O O N C C O C C "
00638                          "C N C C O C C C C N N C C O C C O N N C C O C C "
00639                          "C C N C C C C C N C C O C C SE C N C C O C O C N "
00640                          "C C O C C C O O N C C O C O C N C C O C C C C N "
00641                          "C C O C C C C N C C O C C C N C C O C C C O N N "
00642                          "C C O C C O N N C C O C N C C O C C O N N C C O "
00643                          "C C C N C C O C C O O N C C O C S N C C O C C C "
00644                          "C N N C C O C O C N C C O C C C C N C C O C C C "
00645                          "C N C C O C C C C N N C C O C N C C O C C C C N "
00646                          "C C O N C C O C C C N C C O N C C O C N C C O C "
00647                          "O C N C C O C C C C N C C O C C C O O N C C O C "
00648                          "C C O O N C C O C C SE C N C C O C C SE C N C C "
00649                          "O C O C N C C O C N C C O C S N C C O C C C O N "
00650                          "N C C O O O O O O O O O O O O O O O O O O O O O "
00651                          "O O O O O O O O O O O O O O O O O O O O O O O O "
00652                          "O O O O O O O O O O O O O O O O O O O O O O O O "
00653                          "O O O O O O O O O O O O O O O O O O O O O")
00654 
00655     def test_model_numbering(self):
00656         """Preserve model serial numbers during I/O."""
00657         def confirm_numbering(struct):
00658             self.assertEqual(len(struct), 20)
00659             for idx, model in enumerate(struct):
00660                 self.assertTrue(model.serial_num, idx + 1)
00661                 self.assertTrue(model.serial_num, model.id + 1)
00662         parser = PDBParser()
00663         struct1 = parser.get_structure("1mot", "PDB/1MOT.pdb")
00664         confirm_numbering(struct1)
00665         # Round trip: serialize and parse again
00666         io = PDBIO()
00667         io.set_structure(struct1)
00668         filenumber, filename = tempfile.mkstemp()
00669         os.close(filenumber)
00670         try:
00671             io.save(filename)
00672             struct2 = parser.get_structure("1mot", filename)
00673             confirm_numbering(struct2)
00674         finally:
00675             os.remove(filename)
00676 
00677 
00678 class Exposure(unittest.TestCase):
00679     "Testing Bio.PDB.HSExposure."
00680     def setUp(self):
00681         warnings.simplefilter('ignore', PDBConstructionWarning)
00682         pdb_filename = "PDB/a_structure.pdb"
00683         structure=PDBParser(PERMISSIVE=True).get_structure('X', pdb_filename)
00684         warnings.filters.pop()
00685         self.model=structure[1]
00686         #Look at first chain only
00687         a_residues=list(self.model["A"].child_list)
00688         self.assertEqual(86, len(a_residues))
00689         self.assertEqual(a_residues[0].get_resname(), "CYS")
00690         self.assertEqual(a_residues[1].get_resname(), "ARG")
00691         self.assertEqual(a_residues[2].get_resname(), "CYS")
00692         self.assertEqual(a_residues[3].get_resname(), "GLY")
00693         #...
00694         self.assertEqual(a_residues[-3].get_resname(), "TYR")
00695         self.assertEqual(a_residues[-2].get_resname(), "ARG")
00696         self.assertEqual(a_residues[-1].get_resname(), "CYS")
00697         self.a_residues = a_residues
00698         self.radius = 13.0
00699 
00700     def test_HSExposureCA(self):
00701         """HSExposureCA."""
00702         hse = HSExposureCA(self.model, self.radius)
00703         residues = self.a_residues
00704         self.assertEqual(0, len(residues[0].xtra))
00705         self.assertEqual(0, len(residues[1].xtra))
00706         self.assertEqual(3, len(residues[2].xtra))
00707         self.assertAlmostEqual(0.81250973133184456, residues[2].xtra["EXP_CB_PCB_ANGLE"])
00708         self.assertEqual(14, residues[2].xtra["EXP_HSE_A_D"])
00709         self.assertEqual(14, residues[2].xtra["EXP_HSE_A_U"])
00710         self.assertEqual(3, len(residues[3].xtra))
00711         self.assertAlmostEqual(1.3383737, residues[3].xtra["EXP_CB_PCB_ANGLE"])
00712         self.assertEqual(13, residues[3].xtra["EXP_HSE_A_D"])
00713         self.assertEqual(16, residues[3].xtra["EXP_HSE_A_U"])
00714         #...
00715         self.assertEqual(3, len(residues[-2].xtra))
00716         self.assertAlmostEqual(0.77124014456278489, residues[-2].xtra["EXP_CB_PCB_ANGLE"])
00717         self.assertEqual(24, residues[-2].xtra["EXP_HSE_A_D"])
00718         self.assertEqual(24, residues[-2].xtra["EXP_HSE_A_U"])
00719         self.assertEqual(0, len(residues[-1].xtra))
00720 
00721     def test_HSExposureCB(self):
00722         """HSExposureCB."""
00723         hse = HSExposureCB(self.model, self.radius)
00724         residues = self.a_residues
00725         self.assertEqual(0, len(residues[0].xtra))
00726         self.assertEqual(2, len(residues[1].xtra))
00727         self.assertEqual(20, residues[1].xtra["EXP_HSE_B_D"])
00728         self.assertEqual(5, residues[1].xtra["EXP_HSE_B_U"])
00729         self.assertEqual(2, len(residues[2].xtra))
00730         self.assertEqual(10, residues[2].xtra["EXP_HSE_B_D"])
00731         self.assertEqual(18, residues[2].xtra["EXP_HSE_B_U"])
00732         self.assertEqual(2, len(residues[3].xtra))
00733         self.assertEqual(7, residues[3].xtra["EXP_HSE_B_D"])
00734         self.assertEqual(22, residues[3].xtra["EXP_HSE_B_U"])
00735         #...
00736         self.assertEqual(2, len(residues[-2].xtra))
00737         self.assertEqual(14, residues[-2].xtra["EXP_HSE_B_D"])
00738         self.assertEqual(34, residues[-2].xtra["EXP_HSE_B_U"])
00739         self.assertEqual(2, len(residues[-1].xtra))
00740         self.assertEqual(23, residues[-1].xtra["EXP_HSE_B_D"])
00741         self.assertEqual(15, residues[-1].xtra["EXP_HSE_B_U"])
00742 
00743     def test_ExposureCN(self):
00744         """HSExposureCN."""
00745         hse = ExposureCN(self.model, self.radius)
00746         residues = self.a_residues
00747         self.assertEqual(0, len(residues[0].xtra))
00748         self.assertEqual(1, len(residues[1].xtra))
00749         self.assertEqual(25, residues[1].xtra["EXP_CN"])
00750         self.assertEqual(1, len(residues[2].xtra))
00751         self.assertEqual(28, residues[2].xtra["EXP_CN"])
00752         self.assertEqual(1, len(residues[3].xtra))
00753         self.assertEqual(29, residues[3].xtra["EXP_CN"])
00754         #...
00755         self.assertEqual(1, len(residues[-2].xtra))
00756         self.assertEqual(48, residues[-2].xtra["EXP_CN"])
00757         self.assertEqual(1, len(residues[-1].xtra))
00758         self.assertEqual(38, residues[-1].xtra["EXP_CN"])
00759 
00760 class Atom_Element(unittest.TestCase):
00761     """induces Atom Element from Atom Name"""
00762 
00763     def setUp(self):
00764         warnings.simplefilter('ignore', PDBConstructionWarning)
00765         pdb_filename = "PDB/a_structure.pdb"
00766         structure=PDBParser(PERMISSIVE=True).get_structure('X', pdb_filename)
00767         warnings.filters.pop()
00768         self.residue = structure[0]['A'][('H_PCA', 1, ' ')]
00769 
00770     def test_AtomElement(self):
00771         """ Atom Element """
00772         atoms = self.residue.child_list
00773         self.assertEqual('N', atoms[0].element) # N
00774         self.assertEqual('C', atoms[1].element) # Alpha Carbon
00775         self.assertEqual('CA', atoms[8].element) # Calcium
00776 
00777     def test_ions(self):
00778         """Element for magnesium is assigned correctly."""
00779         pdb_filename = "PDB/ions.pdb"
00780         structure=PDBParser(PERMISSIVE=True).get_structure('X', pdb_filename)
00781         # check magnesium atom
00782         atoms = structure[0]['A'][('H_ MG', 1, ' ')].child_list
00783         self.assertEqual('MG', atoms[0].element)
00784 
00785 class IterationTests(unittest.TestCase):        
00786 
00787     def setUp(self):
00788         self.struc = PDBParser(PERMISSIVE=True).get_structure('X', "PDB/a_structure.pdb")
00789 
00790     def test_get_chains(self):
00791         """Yields chains from different models separately."""
00792         chains = [chain.id for chain in self.struc.get_chains()]
00793         self.assertEqual(chains, ['A','A', 'B', ' '])
00794 
00795     def test_get_residues(self):
00796         """Yields all residues from all models."""
00797         residues = [resi.id for resi in self.struc.get_residues()]
00798         self.assertEqual(len(residues), 167)
00799 
00800     def test_get_atoms(self):
00801         """Yields all atoms from the structure, excluding duplicates and ALTLOCs which are not parsed."""
00802         atoms = ["%12s"%str((atom.id, atom.altloc)) for atom in self.struc.get_atoms()]
00803         self.assertEqual(len(atoms), 756)
00804 
00805 
00806 #class RenumberTests(unittest.TestCase):
00807 #    """Tests renumbering of structures."""
00808 #    
00809 #    def setUp(self):
00810 #        warnings.simplefilter('ignore', PDBConstructionWarning)
00811 #        pdb_filename = "PDB/1A8O.pdb"
00812 #        self.structure=PDBParser(PERMISSIVE=True).get_structure('X', pdb_filename)
00813 #        warnings.filters.pop()
00814 #        
00815 #    def test_renumber_residues(self):
00816 #        """Residues in a structure are renumbered."""
00817 #        self.structure.renumber_residues()
00818 #        nums = [resi.id[1] for resi in self.structure[0]['A'].child_list]
00819 #        print nums
00820 # 
00821 # -------------------------------------------------------------
00822 
00823 class TransformTests(unittest.TestCase):        
00824 
00825     def setUp(self):
00826         self.s = PDBParser(PERMISSIVE=True).get_structure(
00827             'X', "PDB/a_structure.pdb")
00828         self.m = self.s.get_list()[0]
00829         self.c = self.m.get_list()[0]
00830         self.r = self.c.get_list()[0]
00831         self.a = self.r.get_list()[0]
00832 
00833     def get_total_pos(self, o):
00834         """
00835         Returns the sum of the positions of atoms in an entity along
00836         with the number of atoms.
00837         """
00838         if hasattr(o, "get_coord"):
00839             return o.get_coord(), 1
00840         total_pos = numpy.array((0.0,0.0,0.0))
00841         total_count = 0
00842         for p in o.get_list():
00843             pos, count = self.get_total_pos(p)
00844             total_pos += pos
00845             total_count += count
00846         return total_pos, total_count
00847 
00848     def get_pos(self, o):
00849         """
00850         Returns the average atom position in an entity.
00851         """
00852         pos, count = self.get_total_pos(o)
00853         return 1.0*pos/count
00854 
00855     def test_transform(self):
00856         """Transform entities (rotation and translation)."""
00857         for o in (self.s, self.m, self.c, self.r, self.a):
00858             rotation = rotmat(Vector(1,3,5), Vector(1,0,0))
00859             translation=numpy.array((2.4,0,1), 'f')
00860             oldpos = self.get_pos(o)
00861             o.transform(rotation, translation)
00862             newpos = self.get_pos(o)
00863             newpos_check = numpy.dot(oldpos, rotation) +  translation 
00864             for i in range(0, 3):
00865                 self.assertAlmostEqual(newpos[i], newpos_check[i])
00866 
00867 
00868 class CopyTests(unittest.TestCase):        
00869 
00870     def setUp(self):
00871         self.s = PDBParser(PERMISSIVE=True).get_structure(
00872             'X', "PDB/a_structure.pdb")
00873         self.m = self.s.get_list()[0]
00874         self.c = self.m.get_list()[0]
00875         self.r = self.c.get_list()[0]
00876         self.a = self.r.get_list()[0]
00877 
00878     def test_atom_copy(self):
00879         aa = self.a.copy()
00880         self.assertFalse(self.a is aa)
00881         self.assertFalse(self.a.get_coord() is aa.get_coord())
00882 
00883     def test_entitity_copy(self):
00884         """Make a copy of a residue."""
00885         for e in (self.s, self.m, self.c, self.r):
00886             ee = e.copy()
00887             self.assertFalse(e is ee)
00888             self.assertFalse(e.get_list()[0] is ee.get_list()[0])
00889 
00890 
00891 if __name__ == '__main__':
00892     runner = unittest.TextTestRunner(verbosity=2)
00893     unittest.main(testRunner=runner)